summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp73
1 files changed, 73 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index c70d7585cac..2f72e0ab6e9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -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);
OpenPOWER on IntegriCloud