Analysis: Reformulate WillNotOverflowUnsignedAdd for reusability

WillNotOverflowUnsignedAdd's smarts will live in ValueTracking as
computeOverflowForUnsignedAdd.  It now returns a tri-state result:
never overflows, always overflows and sometimes overflows.

llvm-svn: 225329
This commit is contained in:
David Majnemer 2015-01-07 00:39:50 +00:00
parent 3b83b3fa0b
commit 5310c1e954
5 changed files with 46 additions and 45 deletions

View File

@ -221,6 +221,11 @@ namespace llvm {
AssumptionCache *AC, AssumptionCache *AC,
const Instruction *CxtI, const Instruction *CxtI,
const DominatorTree *DT); const DominatorTree *DT);
OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS,
const DataLayout *DL,
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT);
} // end namespace llvm } // end namespace llvm
#endif #endif

View File

@ -2729,3 +2729,32 @@ OverflowResult llvm::computeOverflowForUnsignedMul(Value *LHS, Value *RHS,
return OverflowResult::MayOverflow; return OverflowResult::MayOverflow;
} }
OverflowResult llvm::computeOverflowForUnsignedAdd(Value *LHS, Value *RHS,
const DataLayout *DL,
AssumptionCache *AC,
const Instruction *CxtI,
const DominatorTree *DT) {
bool LHSKnownNonNegative, LHSKnownNegative;
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, DL, /*Depth=*/0,
AC, CxtI, DT);
if (LHSKnownNonNegative || LHSKnownNegative) {
bool RHSKnownNonNegative, RHSKnownNegative;
ComputeSignBit(RHS, RHSKnownNonNegative, RHSKnownNegative, DL, /*Depth=*/0,
AC, CxtI, DT);
if (LHSKnownNegative && RHSKnownNegative) {
// The sign bit is set in both cases: this MUST overflow.
// Create a simple add instruction, and insert it into the struct.
return OverflowResult::AlwaysOverflows;
}
if (LHSKnownNonNegative && RHSKnownNonNegative) {
// The sign bit is clear in both cases: this CANNOT overflow.
// Create a simple add instruction, and insert it into the struct.
return OverflowResult::NeverOverflows;
}
}
return OverflowResult::MayOverflow;
}

View File

@ -282,7 +282,6 @@ private:
bool DoXform = true); bool DoXform = true);
Instruction *transformSExtICmp(ICmpInst *ICI, Instruction &CI); Instruction *transformSExtICmp(ICmpInst *ICI, Instruction &CI);
bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS, Instruction *CxtI); bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS, Instruction *CxtI);
bool WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS, Instruction *CxtI);
bool WillNotOverflowSignedSub(Value *LHS, Value *RHS, Instruction *CxtI); bool WillNotOverflowSignedSub(Value *LHS, Value *RHS, Instruction *CxtI);
bool WillNotOverflowUnsignedSub(Value *LHS, Value *RHS, Instruction *CxtI); bool WillNotOverflowUnsignedSub(Value *LHS, Value *RHS, Instruction *CxtI);
bool WillNotOverflowSignedMul(Value *LHS, Value *RHS, Instruction *CxtI); bool WillNotOverflowSignedMul(Value *LHS, Value *RHS, Instruction *CxtI);
@ -391,6 +390,10 @@ public:
const Instruction *CxtI) { const Instruction *CxtI) {
return llvm::computeOverflowForUnsignedMul(LHS, RHS, DL, AC, CxtI, DT); return llvm::computeOverflowForUnsignedMul(LHS, RHS, DL, AC, CxtI, DT);
} }
OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS,
const Instruction *CxtI) {
return llvm::computeOverflowForUnsignedAdd(LHS, RHS, DL, AC, CxtI, DT);
}
private: private:
/// SimplifyAssociativeOrCommutative - This performs a few simplifications for /// SimplifyAssociativeOrCommutative - This performs a few simplifications for

View File

@ -937,22 +937,6 @@ bool InstCombiner::WillNotOverflowSignedAdd(Value *LHS, Value *RHS,
return false; return false;
} }
/// WillNotOverflowUnsignedAdd - Return true if we can prove that:
/// (zext (add LHS, RHS)) === (add (zext LHS), (zext RHS))
bool InstCombiner::WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS,
Instruction *CxtI) {
// There are different heuristics we can use for this. Here is a simple one.
// If the sign bit of LHS and that of RHS are both zero, no unsigned wrap.
bool LHSKnownNonNegative, LHSKnownNegative;
bool RHSKnownNonNegative, RHSKnownNegative;
ComputeSignBit(LHS, LHSKnownNonNegative, LHSKnownNegative, /*Depth=*/0, CxtI);
ComputeSignBit(RHS, RHSKnownNonNegative, RHSKnownNegative, /*Depth=*/0, CxtI);
if (LHSKnownNonNegative && RHSKnownNonNegative)
return true;
return false;
}
/// \brief Return true if we can prove that: /// \brief Return true if we can prove that:
/// (sub LHS, RHS) === (sub nsw LHS, RHS) /// (sub LHS, RHS) === (sub nsw LHS, RHS)
/// This basically requires proving that the add in the original type would not /// This basically requires proving that the add in the original type would not
@ -1327,7 +1311,9 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
Changed = true; Changed = true;
I.setHasNoSignedWrap(true); I.setHasNoSignedWrap(true);
} }
if (!I.hasNoUnsignedWrap() && WillNotOverflowUnsignedAdd(LHS, RHS, &I)) { if (!I.hasNoUnsignedWrap() &&
computeOverflowForUnsignedAdd(LHS, RHS, &I) ==
OverflowResult::NeverOverflows) {
Changed = true; Changed = true;
I.setHasNoUnsignedWrap(true); I.setHasNoUnsignedWrap(true);
} }

View File

@ -352,33 +352,11 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
break; break;
case Intrinsic::uadd_with_overflow: { case Intrinsic::uadd_with_overflow: {
Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1); Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1);
IntegerType *IT = cast<IntegerType>(II->getArgOperand(0)->getType()); OverflowResult OR = computeOverflowForUnsignedAdd(LHS, RHS, II);
uint32_t BitWidth = IT->getBitWidth(); if (OR == OverflowResult::NeverOverflows)
APInt LHSKnownZero(BitWidth, 0); return CreateOverflowTuple(II, Builder->CreateNUWAdd(LHS, RHS), false);
APInt LHSKnownOne(BitWidth, 0); if (OR == OverflowResult::AlwaysOverflows)
computeKnownBits(LHS, LHSKnownZero, LHSKnownOne, 0, II); return CreateOverflowTuple(II, Builder->CreateAdd(LHS, RHS), true);
bool LHSKnownNegative = LHSKnownOne[BitWidth - 1];
bool LHSKnownPositive = LHSKnownZero[BitWidth - 1];
if (LHSKnownNegative || LHSKnownPositive) {
APInt RHSKnownZero(BitWidth, 0);
APInt RHSKnownOne(BitWidth, 0);
computeKnownBits(RHS, RHSKnownZero, RHSKnownOne, 0, II);
bool RHSKnownNegative = RHSKnownOne[BitWidth - 1];
bool RHSKnownPositive = RHSKnownZero[BitWidth - 1];
if (LHSKnownNegative && RHSKnownNegative) {
// The sign bit is set in both cases: this MUST overflow.
// Create a simple add instruction, and insert it into the struct.
return CreateOverflowTuple(II, Builder->CreateAdd(LHS, RHS), true,
/*ReUseName*/true);
}
if (LHSKnownPositive && RHSKnownPositive) {
// The sign bit is clear in both cases: this CANNOT overflow.
// Create a simple add instruction, and insert it into the struct.
return CreateOverflowTuple(II, Builder->CreateNUWAdd(LHS, RHS), false);
}
}
} }
// FALL THROUGH uadd into sadd // FALL THROUGH uadd into sadd
case Intrinsic::sadd_with_overflow: case Intrinsic::sadd_with_overflow: