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
This commit is contained in:
Benjamin Kramer
2011-03-10 18:40:14 +00:00
parent f7fdad15d9
commit 6b96fe7e14
2 changed files with 56 additions and 1 deletions

View File

@@ -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)) &&