Skip to content

Commit

Permalink
[InstCombine] More thoroughly canonicalize the position of zexts
Browse files Browse the repository at this point in the history
We correctly canonicalized (add (sext x), (sext y)) to (sext (add x, y))
where possible.  However, we didn't perform the same canonicalization
for zexts or for muls.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@290733 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
majnemer committed Dec 30, 2016
1 parent 54223ae commit beaec29
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 9 deletions.
56 changes: 47 additions & 9 deletions lib/Transforms/InstCombine/InstCombineAddSub.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1226,15 +1226,16 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
if (SExtInst *LHSConv = dyn_cast<SExtInst>(LHS)) {
// (add (sext x), cst) --> (sext (add x, cst'))
if (ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS)) {
Constant *CI =
ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getType());
if (LHSConv->hasOneUse() &&
ConstantExpr::getSExt(CI, I.getType()) == RHSC &&
WillNotOverflowSignedAdd(LHSConv->getOperand(0), CI, I)) {
// Insert the new, smaller add.
Value *NewAdd = Builder->CreateNSWAdd(LHSConv->getOperand(0),
CI, "addconv");
return new SExtInst(NewAdd, I.getType());
if (LHSConv->hasOneUse()) {
Constant *CI =
ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getType());
if (ConstantExpr::getSExt(CI, I.getType()) == RHSC &&
WillNotOverflowSignedAdd(LHSConv->getOperand(0), CI, I)) {
// Insert the new, smaller add.
Value *NewAdd =
Builder->CreateNSWAdd(LHSConv->getOperand(0), CI, "addconv");
return new SExtInst(NewAdd, I.getType());
}
}
}

Expand All @@ -1256,6 +1257,43 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
}
}

// Check for (add (zext x), y), see if we can merge this into an
// integer add followed by a zext.
if (auto *LHSConv = dyn_cast<ZExtInst>(LHS)) {
// (add (zext x), cst) --> (zext (add x, cst'))
if (ConstantInt *RHSC = dyn_cast<ConstantInt>(RHS)) {
if (LHSConv->hasOneUse()) {
Constant *CI =
ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getType());
if (ConstantExpr::getZExt(CI, I.getType()) == RHSC &&
WillNotOverflowSignedAdd(LHSConv->getOperand(0), CI, I)) {
// Insert the new, smaller add.
Value *NewAdd =
Builder->CreateNUWAdd(LHSConv->getOperand(0), CI, "addconv");
return new ZExtInst(NewAdd, I.getType());
}
}
}

// (add (zext x), (zext y)) --> (zext (add int x, y))
if (auto *RHSConv = dyn_cast<ZExtInst>(RHS)) {
// Only do this if x/y have the same type, if at last one of them has a
// single use (so we don't increase the number of zexts), and if the
// integer add will not overflow.
if (LHSConv->getOperand(0)->getType() ==
RHSConv->getOperand(0)->getType() &&
(LHSConv->hasOneUse() || RHSConv->hasOneUse()) &&
computeOverflowForUnsignedAdd(LHSConv->getOperand(0),
RHSConv->getOperand(0),
&I) == OverflowResult::NeverOverflows) {
// Insert the new integer add.
Value *NewAdd = Builder->CreateNUWAdd(
LHSConv->getOperand(0), RHSConv->getOperand(0), "addconv");
return new ZExtInst(NewAdd, I.getType());
}
}
}

// (add (xor A, B) (and A, B)) --> (or A, B)
{
Value *A = nullptr, *B = nullptr;
Expand Down
73 changes: 73 additions & 0 deletions lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,79 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
}
}

// Check for (mul (sext x), y), see if we can merge this into an
// integer mul followed by a sext.
if (SExtInst *Op0Conv = dyn_cast<SExtInst>(Op0)) {
// (mul (sext x), cst) --> (sext (mul x, cst'))
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
if (Op0Conv->hasOneUse()) {
Constant *CI =
ConstantExpr::getTrunc(Op1C, Op0Conv->getOperand(0)->getType());
if (ConstantExpr::getSExt(CI, I.getType()) == Op1C &&
WillNotOverflowSignedMul(Op0Conv->getOperand(0), CI, I)) {
// Insert the new, smaller mul.
Value *NewMul =
Builder->CreateNSWMul(Op0Conv->getOperand(0), CI, "mulconv");
return new SExtInst(NewMul, I.getType());
}
}
}

// (mul (sext x), (sext y)) --> (sext (mul int x, y))
if (SExtInst *Op1Conv = dyn_cast<SExtInst>(Op1)) {
// Only do this if x/y have the same type, if at last one of them has a
// single use (so we don't increase the number of sexts), and if the
// integer mul will not overflow.
if (Op0Conv->getOperand(0)->getType() ==
Op1Conv->getOperand(0)->getType() &&
(Op0Conv->hasOneUse() || Op1Conv->hasOneUse()) &&
WillNotOverflowSignedMul(Op0Conv->getOperand(0),
Op1Conv->getOperand(0), I)) {
// Insert the new integer mul.
Value *NewMul = Builder->CreateNSWMul(
Op0Conv->getOperand(0), Op1Conv->getOperand(0), "mulconv");
return new SExtInst(NewMul, I.getType());
}
}
}

// Check for (mul (zext x), y), see if we can merge this into an
// integer mul followed by a zext.
if (auto *Op0Conv = dyn_cast<ZExtInst>(Op0)) {
// (mul (zext x), cst) --> (zext (mul x, cst'))
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
if (Op0Conv->hasOneUse()) {
Constant *CI =
ConstantExpr::getTrunc(Op1C, Op0Conv->getOperand(0)->getType());
if (ConstantExpr::getZExt(CI, I.getType()) == Op1C &&
WillNotOverflowSignedMul(Op0Conv->getOperand(0), CI, I)) {
// Insert the new, smaller mul.
Value *NewMul =
Builder->CreateNUWMul(Op0Conv->getOperand(0), CI, "mulconv");
return new ZExtInst(NewMul, I.getType());
}
}
}

// (mul (zext x), (zext y)) --> (zext (mul int x, y))
if (auto *Op1Conv = dyn_cast<ZExtInst>(Op1)) {
// Only do this if x/y have the same type, if at last one of them has a
// single use (so we don't increase the number of zexts), and if the
// integer mul will not overflow.
if (Op0Conv->getOperand(0)->getType() ==
Op1Conv->getOperand(0)->getType() &&
(Op0Conv->hasOneUse() || Op1Conv->hasOneUse()) &&
computeOverflowForUnsignedMul(Op0Conv->getOperand(0),
Op1Conv->getOperand(0),
&I) == OverflowResult::NeverOverflows) {
// Insert the new integer mul.
Value *NewMul = Builder->CreateNUWMul(
Op0Conv->getOperand(0), Op1Conv->getOperand(0), "mulconv");
return new ZExtInst(NewMul, I.getType());
}
}
}

if (!I.hasNoSignedWrap() && WillNotOverflowSignedMul(Op0, Op1, I)) {
Changed = true;
I.setHasNoSignedWrap(true);
Expand Down

0 comments on commit beaec29

Please sign in to comment.