1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

[InstCombine] Merge duplicate functionality between InstCombine and ValueTracking

Summary:
Merge overflow computation for signed add,
appearing both in InstCombine and ValueTracking.

As part of the merge,
cleanup the interface for overflow checks in InstCombine.

Patch by Yoav Ben-Shalom.

Reviewers: craig.topper, majnemer

Reviewed By: craig.topper

Subscribers: takuto.ikuta, llvm-commits

Differential Revision: https://reviews.llvm.org/D32946

llvm-svn: 303029
This commit is contained in:
Craig Topper 2017-05-15 02:44:08 +00:00
parent f89b6ec89f
commit 6fa9bfae0a
4 changed files with 92 additions and 109 deletions

View File

@ -3495,6 +3495,51 @@ OverflowResult llvm::computeOverflowForUnsignedAdd(const Value *LHS,
return OverflowResult::MayOverflow;
}
/// \brief Return true if we can prove that adding the two values of the
/// knownbits will not overflow.
/// Otherwise return false.
static bool checkRippleForSignedAdd(const KnownBits &LHSKnown,
const KnownBits &RHSKnown) {
// Addition of two 2's complement numbers having opposite signs will never
// overflow.
if ((LHSKnown.isNegative() && RHSKnown.isNonNegative()) ||
(LHSKnown.isNonNegative() && RHSKnown.isNegative()))
return true;
// If either of the values is known to be non-negative, adding them can only
// overflow if the second is also non-negative, so we can assume that.
// Two non-negative numbers will only overflow if there is a carry to the
// sign bit, so we can check if even when the values are as big as possible
// there is no overflow to the sign bit.
if (LHSKnown.isNonNegative() || RHSKnown.isNonNegative()) {
APInt MaxLHS = ~LHSKnown.Zero;
MaxLHS.clearSignBit();
APInt MaxRHS = ~RHSKnown.Zero;
MaxRHS.clearSignBit();
APInt Result = std::move(MaxLHS) + std::move(MaxRHS);
return Result.isSignBitClear();
}
// If either of the values is known to be negative, adding them can only
// overflow if the second is also negative, so we can assume that.
// Two negative number will only overflow if there is no carry to the sign
// bit, so we can check if even when the values are as small as possible
// there is overflow to the sign bit.
if (LHSKnown.isNegative() || RHSKnown.isNegative()) {
APInt MinLHS = LHSKnown.One;
MinLHS.clearSignBit();
APInt MinRHS = RHSKnown.One;
MinRHS.clearSignBit();
APInt Result = std::move(MinLHS) + std::move(MinRHS);
return Result.isSignBitSet();
}
// If we reached here it means that we know nothing about the sign bits.
// In this case we can't know if there will be an overflow, since by
// changing the sign bits any two values can be made to overflow.
return false;
}
static OverflowResult computeOverflowForSignedAdd(const Value *LHS,
const Value *RHS,
const AddOperator *Add,
@ -3506,14 +3551,29 @@ static OverflowResult computeOverflowForSignedAdd(const Value *LHS,
return OverflowResult::NeverOverflows;
}
// If LHS and RHS each have at least two sign bits, the addition will look
// like
//
// XX..... +
// YY.....
//
// If the carry into the most significant position is 0, X and Y can't both
// be 1 and therefore the carry out of the addition is also 0.
//
// If the carry into the most significant position is 1, X and Y can't both
// be 0 and therefore the carry out of the addition is also 1.
//
// Since the carry into the most significant position is always equal to
// the carry out of the addition, there is no signed overflow.
if (ComputeNumSignBits(LHS, DL, 0, AC, CxtI, DT) > 1 &&
ComputeNumSignBits(RHS, DL, 0, AC, CxtI, DT) > 1)
return OverflowResult::NeverOverflows;
KnownBits LHSKnown = computeKnownBits(LHS, DL, /*Depth=*/0, AC, CxtI, DT);
KnownBits RHSKnown = computeKnownBits(RHS, DL, /*Depth=*/0, AC, CxtI, DT);
if ((LHSKnown.isNonNegative() && RHSKnown.isNegative()) ||
(LHSKnown.isNegative() && RHSKnown.isNonNegative())) {
// The sign bits are opposite: this CANNOT overflow.
if (checkRippleForSignedAdd(LHSKnown, RHSKnown))
return OverflowResult::NeverOverflows;
}
// The remaining code needs Add to be available. Early returns if not so.
if (!Add)
@ -3525,7 +3585,8 @@ static OverflowResult computeOverflowForSignedAdd(const Value *LHS,
// operands.
bool LHSOrRHSKnownNonNegative =
(LHSKnown.isNonNegative() || RHSKnown.isNonNegative());
bool LHSOrRHSKnownNegative = (LHSKnown.isNegative() || RHSKnown.isNegative());
bool LHSOrRHSKnownNegative =
(LHSKnown.isNegative() || RHSKnown.isNegative());
if (LHSOrRHSKnownNonNegative || LHSOrRHSKnownNegative) {
KnownBits AddKnown = computeKnownBits(Add, DL, /*Depth=*/0, AC, CxtI, DT);
if ((AddKnown.isNonNegative() && LHSOrRHSKnownNonNegative) ||

View File

@ -847,92 +847,6 @@ Value *FAddCombine::createAddendVal(const FAddend &Opnd, bool &NeedNeg) {
return createFMul(OpndVal, Coeff.getValue(Instr->getType()));
}
/// \brief Return true if we can prove that adding the two values of the
/// knownbits will not overflow.
/// Otherwise return false.
static bool checkRippleForAdd(const KnownBits &LHSKnown,
const KnownBits &RHSKnown) {
// Addition of two 2's complement numbers having opposite signs will never
// overflow.
if ((LHSKnown.isNegative() && RHSKnown.isNonNegative()) ||
(LHSKnown.isNonNegative() && RHSKnown.isNegative()))
return true;
// If either of the values is known to be non-negative, adding them can only
// overflow if the second is also non-negative, so we can assume that.
// Two non-negative numbers will only overflow if there is a carry to the
// sign bit, so we can check if even when the values are as big as possible
// there is no overflow to the sign bit.
if (LHSKnown.isNonNegative() || RHSKnown.isNonNegative()) {
APInt MaxLHS = ~LHSKnown.Zero;
MaxLHS.clearSignBit();
APInt MaxRHS = ~RHSKnown.Zero;
MaxRHS.clearSignBit();
APInt Result = std::move(MaxLHS) + std::move(MaxRHS);
return Result.isSignBitClear();
}
// If either of the values is known to be negative, adding them can only
// overflow if the second is also negative, so we can assume that.
// Two negative number will only overflow if there is no carry to the sign
// bit, so we can check if even when the values are as small as possible
// there is overflow to the sign bit.
if (LHSKnown.isNegative() || RHSKnown.isNegative()) {
APInt MinLHS = LHSKnown.One;
MinLHS.clearSignBit();
APInt MinRHS = RHSKnown.One;
MinRHS.clearSignBit();
APInt Result = std::move(MinLHS) + std::move(MinRHS);
return Result.isSignBitSet();
}
// If we reached here it means that we know nothing about the sign bits.
// In this case we can't know if there will be an overflow, since by
// changing the sign bits any two values can be made to overflow.
return false;
}
/// Return true if we can prove that:
/// (sext (add LHS, RHS)) === (add (sext LHS), (sext RHS))
/// This basically requires proving that the add in the original type would not
/// overflow to change the sign bit or have a carry out.
bool InstCombiner::WillNotOverflowSignedAdd(Value *LHS, Value *RHS,
Instruction &CxtI) {
// There are different heuristics we can use for this. Here are some simple
// ones.
// If LHS and RHS each have at least two sign bits, the addition will look
// like
//
// XX..... +
// YY.....
//
// If the carry into the most significant position is 0, X and Y can't both
// be 1 and therefore the carry out of the addition is also 0.
//
// If the carry into the most significant position is 1, X and Y can't both
// be 0 and therefore the carry out of the addition is also 1.
//
// Since the carry into the most significant position is always equal to
// the carry out of the addition, there is no signed overflow.
if (ComputeNumSignBits(LHS, 0, &CxtI) > 1 &&
ComputeNumSignBits(RHS, 0, &CxtI) > 1)
return true;
unsigned BitWidth = LHS->getType()->getScalarSizeInBits();
KnownBits LHSKnown(BitWidth);
computeKnownBits(LHS, LHSKnown, 0, &CxtI);
KnownBits RHSKnown(BitWidth);
computeKnownBits(RHS, RHSKnown, 0, &CxtI);
// Check if carry bit of addition will not cause overflow.
if (checkRippleForAdd(LHSKnown, RHSKnown))
return true;
return false;
}
/// \brief Return true if we can prove that:
/// (sub LHS, RHS) === (sub nsw LHS, RHS)
/// This basically requires proving that the add in the original type would not
@ -1306,8 +1220,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
Constant *CI =
ConstantExpr::getTrunc(RHSC, LHSConv->getOperand(0)->getType());
if (ConstantExpr::getZExt(CI, I.getType()) == RHSC &&
computeOverflowForUnsignedAdd(LHSConv->getOperand(0), CI, &I) ==
OverflowResult::NeverOverflows) {
willNotOverflowUnsignedAdd(LHSConv->getOperand(0), CI, I)) {
// Insert the new, smaller add.
Value *NewAdd =
Builder->CreateNUWAdd(LHSConv->getOperand(0), CI, "addconv");
@ -1324,9 +1237,8 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
if (LHSConv->getOperand(0)->getType() ==
RHSConv->getOperand(0)->getType() &&
(LHSConv->hasOneUse() || RHSConv->hasOneUse()) &&
computeOverflowForUnsignedAdd(LHSConv->getOperand(0),
RHSConv->getOperand(0),
&I) == OverflowResult::NeverOverflows) {
willNotOverflowUnsignedAdd(LHSConv->getOperand(0),
RHSConv->getOperand(0), I)) {
// Insert the new integer add.
Value *NewAdd = Builder->CreateNUWAdd(
LHSConv->getOperand(0), RHSConv->getOperand(0), "addconv");
@ -1368,15 +1280,13 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
}
// TODO(jingyue): Consider WillNotOverflowSignedAdd and
// WillNotOverflowUnsignedAdd to reduce the number of invocations of
// willNotOverflowUnsignedAdd to reduce the number of invocations of
// computeKnownBits.
if (!I.hasNoSignedWrap() && WillNotOverflowSignedAdd(LHS, RHS, I)) {
Changed = true;
I.setHasNoSignedWrap(true);
}
if (!I.hasNoUnsignedWrap() &&
computeOverflowForUnsignedAdd(LHS, RHS, &I) ==
OverflowResult::NeverOverflows) {
if (!I.hasNoUnsignedWrap() && willNotOverflowUnsignedAdd(LHS, RHS, I)) {
Changed = true;
I.setHasNoUnsignedWrap(true);
}

View File

@ -388,10 +388,21 @@ private:
bool DoTransform = true);
Instruction *transformSExtICmp(ICmpInst *ICI, Instruction &CI);
bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS, Instruction &CxtI);
bool WillNotOverflowSignedAdd(Value *LHS, Value *RHS, Instruction &CxtI) {
return computeOverflowForSignedAdd(LHS, RHS, &CxtI) ==
OverflowResult::NeverOverflows;
};
bool willNotOverflowUnsignedAdd(Value *LHS, Value *RHS, Instruction &CxtI) {
return computeOverflowForUnsignedAdd(LHS, RHS, &CxtI) ==
OverflowResult::NeverOverflows;
};
bool WillNotOverflowSignedSub(Value *LHS, Value *RHS, Instruction &CxtI);
bool WillNotOverflowUnsignedSub(Value *LHS, Value *RHS, Instruction &CxtI);
bool WillNotOverflowSignedMul(Value *LHS, Value *RHS, Instruction &CxtI);
bool willNotOverflowUnsignedMul(Value *LHS, Value *RHS, Instruction &CxtI) {
return computeOverflowForUnsignedMul(LHS, RHS, &CxtI) ==
OverflowResult::NeverOverflows;
};
Value *EmitGEPOffset(User *GEP);
Instruction *scalarizePHI(ExtractElementInst &EI, PHINode *PN);
Value *EvaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask);
@ -515,6 +526,11 @@ public:
const Instruction *CxtI) {
return llvm::computeOverflowForUnsignedAdd(LHS, RHS, DL, &AC, CxtI, &DT);
}
OverflowResult computeOverflowForSignedAdd(const Value *LHS,
const Value *RHS,
const Instruction *CxtI) const {
return llvm::computeOverflowForSignedAdd(LHS, RHS, DL, &AC, CxtI, &DT);
}
/// Maximum size of array considered when transforming.
uint64_t MaxArraySizeForCombine;

View File

@ -422,8 +422,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
Constant *CI =
ConstantExpr::getTrunc(Op1C, Op0Conv->getOperand(0)->getType());
if (ConstantExpr::getZExt(CI, I.getType()) == Op1C &&
computeOverflowForUnsignedMul(Op0Conv->getOperand(0), CI, &I) ==
OverflowResult::NeverOverflows) {
willNotOverflowUnsignedMul(Op0Conv->getOperand(0), CI, I)) {
// Insert the new, smaller mul.
Value *NewMul =
Builder->CreateNUWMul(Op0Conv->getOperand(0), CI, "mulconv");
@ -440,9 +439,8 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
if (Op0Conv->getOperand(0)->getType() ==
Op1Conv->getOperand(0)->getType() &&
(Op0Conv->hasOneUse() || Op1Conv->hasOneUse()) &&
computeOverflowForUnsignedMul(Op0Conv->getOperand(0),
Op1Conv->getOperand(0),
&I) == OverflowResult::NeverOverflows) {
willNotOverflowUnsignedMul(Op0Conv->getOperand(0),
Op1Conv->getOperand(0), I)) {
// Insert the new integer mul.
Value *NewMul = Builder->CreateNUWMul(
Op0Conv->getOperand(0), Op1Conv->getOperand(0), "mulconv");
@ -456,9 +454,7 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
I.setHasNoSignedWrap(true);
}
if (!I.hasNoUnsignedWrap() &&
computeOverflowForUnsignedMul(Op0, Op1, &I) ==
OverflowResult::NeverOverflows) {
if (!I.hasNoUnsignedWrap() && willNotOverflowUnsignedMul(Op0, Op1, I)) {
Changed = true;
I.setHasNoUnsignedWrap(true);
}