diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2011-03-10 18:40:14 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2011-03-10 18:40:14 +0000 |
commit | b49b964b9832cbf48b0cd9734a30202cc0a08681 (patch) | |
tree | 4e16d12ac4bf6b4c2a962001e6da1cabd91cd3e8 /llvm/lib/Transforms | |
parent | 258a605fce06c6159f7409a55f46141457390a68 (diff) | |
download | bcm5719-llvm-b49b964b9832cbf48b0cd9734a30202cc0a08681.tar.gz bcm5719-llvm-b49b964b9832cbf48b0cd9734a30202cc0a08681.zip |
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.
llvm-svn: 127418
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 0e464507a7e..bfdc17eff7e 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/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)) && |