mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-28 06:24:57 +00:00
Analysis: Reformulate WillNotOverflowUnsignedMul for reusability
WillNotOverflowUnsignedMul's smarts will live in ValueTracking as computeOverflowForUnsignedMul. It now returns a tri-state result: never overflows, always overflows and sometimes overflows. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225076 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -217,6 +217,12 @@ namespace llvm {
|
|||||||
const DataLayout *DL = nullptr,
|
const DataLayout *DL = nullptr,
|
||||||
const DominatorTree *DT = nullptr);
|
const DominatorTree *DT = nullptr);
|
||||||
|
|
||||||
|
enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows };
|
||||||
|
OverflowResult computeOverflowForUnsignedMul(Value *LHS, Value *RHS,
|
||||||
|
const DataLayout *DL,
|
||||||
|
AssumptionTracker *AT,
|
||||||
|
const Instruction *CxtI,
|
||||||
|
const DominatorTree *DT);
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -2672,3 +2672,42 @@ bool llvm::isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI) {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OverflowResult llvm::computeOverflowForUnsignedMul(Value *LHS, Value *RHS,
|
||||||
|
const DataLayout *DL,
|
||||||
|
AssumptionTracker *AT,
|
||||||
|
const Instruction *CxtI,
|
||||||
|
const DominatorTree *DT) {
|
||||||
|
// Multiplying n * m significant bits yields a result of n + m significant
|
||||||
|
// bits. If the total number of significant bits does not exceed the
|
||||||
|
// result bit width (minus 1), there is no overflow.
|
||||||
|
// This means if we have enough leading zero bits in the operands
|
||||||
|
// we can guarantee that the result does not overflow.
|
||||||
|
// Ref: "Hacker's Delight" by Henry Warren
|
||||||
|
unsigned BitWidth = LHS->getType()->getScalarSizeInBits();
|
||||||
|
APInt LHSKnownZero(BitWidth, 0);
|
||||||
|
APInt RHSKnownZero(BitWidth, 0);
|
||||||
|
APInt TmpKnownOne(BitWidth, 0);
|
||||||
|
computeKnownBits(LHS, LHSKnownZero, TmpKnownOne, DL, /*Depth=*/0, AT, CxtI, DT);
|
||||||
|
computeKnownBits(RHS, RHSKnownZero, TmpKnownOne, DL, /*Depth=*/0, AT, CxtI, DT);
|
||||||
|
// Note that underestimating the number of zero bits gives a more
|
||||||
|
// conservative answer.
|
||||||
|
unsigned ZeroBits = LHSKnownZero.countLeadingOnes() +
|
||||||
|
RHSKnownZero.countLeadingOnes();
|
||||||
|
// First handle the easy case: if we have enough zero bits there's
|
||||||
|
// definitely no overflow.
|
||||||
|
if (ZeroBits >= BitWidth)
|
||||||
|
return OverflowResult::NeverOverflows;
|
||||||
|
|
||||||
|
// Get the largest possible values for each operand.
|
||||||
|
APInt LHSMax = ~LHSKnownZero;
|
||||||
|
APInt RHSMax = ~RHSKnownZero;
|
||||||
|
|
||||||
|
// We know the multiply operation doesn't overflow if the maximum values for
|
||||||
|
// each operand will not overflow after we multiply them together.
|
||||||
|
bool Overflow;
|
||||||
|
LHSMax.umul_ov(RHSMax, Overflow);
|
||||||
|
|
||||||
|
return Overflow ? OverflowResult::MayOverflow
|
||||||
|
: OverflowResult::NeverOverflows;
|
||||||
|
}
|
||||||
|
@ -286,7 +286,6 @@ private:
|
|||||||
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);
|
||||||
bool WillNotOverflowUnsignedMul(Value *LHS, Value *RHS, Instruction *CxtI);
|
|
||||||
Value *EmitGEPOffset(User *GEP);
|
Value *EmitGEPOffset(User *GEP);
|
||||||
Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
|
Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
|
||||||
Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask);
|
Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask);
|
||||||
@ -388,6 +387,10 @@ public:
|
|||||||
return llvm::ComputeSignBit(V, KnownZero, KnownOne, DL, Depth, AT, CxtI,
|
return llvm::ComputeSignBit(V, KnownZero, KnownOne, DL, Depth, AT, CxtI,
|
||||||
DT);
|
DT);
|
||||||
}
|
}
|
||||||
|
OverflowResult computeOverflowForUnsignedMul(Value *LHS, Value *RHS,
|
||||||
|
const Instruction *CxtI) {
|
||||||
|
return llvm::computeOverflowForUnsignedMul(LHS, RHS, DL, AT, CxtI, DT);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// SimplifyAssociativeOrCommutative - This performs a few simplifications for
|
/// SimplifyAssociativeOrCommutative - This performs a few simplifications for
|
||||||
|
@ -440,24 +440,8 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
|||||||
}
|
}
|
||||||
case Intrinsic::umul_with_overflow: {
|
case Intrinsic::umul_with_overflow: {
|
||||||
Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1);
|
Value *LHS = II->getArgOperand(0), *RHS = II->getArgOperand(1);
|
||||||
unsigned BitWidth = cast<IntegerType>(LHS->getType())->getBitWidth();
|
OverflowResult OR = computeOverflowForUnsignedMul(LHS, RHS, II);
|
||||||
|
if (OR == OverflowResult::NeverOverflows) {
|
||||||
APInt LHSKnownZero(BitWidth, 0);
|
|
||||||
APInt LHSKnownOne(BitWidth, 0);
|
|
||||||
computeKnownBits(LHS, LHSKnownZero, LHSKnownOne, 0, II);
|
|
||||||
APInt RHSKnownZero(BitWidth, 0);
|
|
||||||
APInt RHSKnownOne(BitWidth, 0);
|
|
||||||
computeKnownBits(RHS, RHSKnownZero, RHSKnownOne, 0, II);
|
|
||||||
|
|
||||||
// Get the largest possible values for each operand.
|
|
||||||
APInt LHSMax = ~LHSKnownZero;
|
|
||||||
APInt RHSMax = ~RHSKnownZero;
|
|
||||||
|
|
||||||
// If multiplying the maximum values does not overflow then we can turn
|
|
||||||
// this into a plain NUW mul.
|
|
||||||
bool Overflow;
|
|
||||||
LHSMax.umul_ov(RHSMax, Overflow);
|
|
||||||
if (!Overflow) {
|
|
||||||
return CreateOverflowTuple(II, Builder->CreateNUWMul(LHS, RHS), false);
|
return CreateOverflowTuple(II, Builder->CreateNUWMul(LHS, RHS), false);
|
||||||
}
|
}
|
||||||
} // FALL THROUGH
|
} // FALL THROUGH
|
||||||
|
@ -165,39 +165,6 @@ bool InstCombiner::WillNotOverflowSignedMul(Value *LHS, Value *RHS,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Return true if we can prove that:
|
|
||||||
/// (mul LHS, RHS) === (mul nuw LHS, RHS)
|
|
||||||
bool InstCombiner::WillNotOverflowUnsignedMul(Value *LHS, Value *RHS,
|
|
||||||
Instruction *CxtI) {
|
|
||||||
// Multiplying n * m significant bits yields a result of n + m significant
|
|
||||||
// bits. If the total number of significant bits does not exceed the
|
|
||||||
// result bit width (minus 1), there is no overflow.
|
|
||||||
// This means if we have enough leading zero bits in the operands
|
|
||||||
// we can guarantee that the result does not overflow.
|
|
||||||
// Ref: "Hacker's Delight" by Henry Warren
|
|
||||||
unsigned BitWidth = LHS->getType()->getScalarSizeInBits();
|
|
||||||
APInt LHSKnownZero(BitWidth, 0);
|
|
||||||
APInt RHSKnownZero(BitWidth, 0);
|
|
||||||
APInt TmpKnownOne(BitWidth, 0);
|
|
||||||
computeKnownBits(LHS, LHSKnownZero, TmpKnownOne, 0, CxtI);
|
|
||||||
computeKnownBits(RHS, RHSKnownZero, TmpKnownOne, 0, CxtI);
|
|
||||||
// Note that underestimating the number of zero bits gives a more
|
|
||||||
// conservative answer.
|
|
||||||
unsigned ZeroBits = LHSKnownZero.countLeadingOnes() +
|
|
||||||
RHSKnownZero.countLeadingOnes();
|
|
||||||
// First handle the easy case: if we have enough zero bits there's
|
|
||||||
// definitely no overflow.
|
|
||||||
if (ZeroBits >= BitWidth)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// There is an ambiguous cases where there can be no overflow:
|
|
||||||
// ZeroBits == BitWidth - 1
|
|
||||||
// However, determining overflow requires calculating the sign bit of
|
|
||||||
// LHS * RHS/2.
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
||||||
bool Changed = SimplifyAssociativeOrCommutative(I);
|
bool Changed = SimplifyAssociativeOrCommutative(I);
|
||||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||||
@ -413,7 +380,9 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
|||||||
I.setHasNoSignedWrap(true);
|
I.setHasNoSignedWrap(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!I.hasNoUnsignedWrap() && WillNotOverflowUnsignedMul(Op0, Op1, &I)) {
|
if (!I.hasNoUnsignedWrap() &&
|
||||||
|
computeOverflowForUnsignedMul(Op0, Op1, &I) ==
|
||||||
|
OverflowResult::NeverOverflows) {
|
||||||
Changed = true;
|
Changed = true;
|
||||||
I.setHasNoUnsignedWrap(true);
|
I.setHasNoUnsignedWrap(true);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user