summaryrefslogtreecommitdiff
path: root/lib/Transforms
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2011-03-10 18:40:14 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2011-03-10 18:40:14 +0000
commit6b96fe7e146f7eb594e67210c6bef511ad0a2058 (patch)
treee45377cac2b691fd66dff4e8cb4f59c7f2193ba5 /lib/Transforms
parentf7fdad15d910fc27bc9334faab5b71c101455e1a (diff)
downloadllvm-6b96fe7e146f7eb594e67210c6bef511ad0a2058.tar.gz
llvm-6b96fe7e146f7eb594e67210c6bef511ad0a2058.tar.bz2
llvm-6b96fe7e146f7eb594e67210c6bef511ad0a2058.tar.xz
InstCombine: Turn umul_with_overflow into mul nuw if we can prove that it cannot overflow.
This happens a lot in clang-compiled C++ code because it adds overflow checks to operator new[]: unsigned *foo(unsigned n) { return new unsigned[n]; } We can optimize away the overflow check on 64 bit targets because (uint64_t)n*4 cannot overflow. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@127418 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/InstCombine/InstCombineCalls.cpp30
1 files changed, 29 insertions, 1 deletions
diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 0e464507a7..bfdc17eff7 100644
--- a/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -475,7 +475,35 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
}
}
break;
- case Intrinsic::umul_with_overflow:
+ case Intrinsic::umul_with_overflow: {
+ Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1);
+ unsigned BitWidth = cast<IntegerType>(LHS->getType())->getBitWidth();
+ APInt Mask = APInt::getAllOnesValue(BitWidth);
+
+ APInt LHSKnownZero(BitWidth, 0);
+ APInt LHSKnownOne(BitWidth, 0);
+ ComputeMaskedBits(LHS, Mask, LHSKnownZero, LHSKnownOne);
+ APInt RHSKnownZero(BitWidth, 0);
+ APInt RHSKnownOne(BitWidth, 0);
+ ComputeMaskedBits(RHS, Mask, RHSKnownZero, RHSKnownOne);
+
+ // Get the largest possible values for each operand, extended to be large
+ // enough so that every possible product of two BitWidth-sized ints fits.
+ APInt LHSMax = (~LHSKnownZero).zext(BitWidth*2);
+ APInt RHSMax = (~RHSKnownZero).zext(BitWidth*2);
+
+ // If multiplying the maximum values does not overflow then we can turn
+ // this into a plain NUW mul.
+ if ((LHSMax * RHSMax).getActiveBits() <= BitWidth) {
+ Value *Mul = Builder->CreateNUWMul(LHS, RHS, "umul_with_overflow");
+ Constant *V[] = {
+ UndefValue::get(LHS->getType()),
+ Builder->getFalse()
+ };
+ Constant *Struct = ConstantStruct::get(II->getContext(), V, 2, false);
+ return InsertValueInst::Create(Struct, Mul, 0);
+ }
+ } // FALL THROUGH
case Intrinsic::smul_with_overflow:
// Canonicalize constants into the RHS.
if (isa<Constant>(II->getArgOperand(0)) &&