mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-02 04:24:22 +00:00
InstCombine: Annotate sub with nsw when we prove it's safe
We can prove that a 'sub' can be a 'sub nsw' under certain conditions: - The sign bits of the operands is the same. - Both operands have more than 1 sign bit. The subtraction cannot be a signed overflow in either case. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216037 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -956,6 +956,38 @@ bool InstCombiner::WillNotOverflowUnsignedAdd(Value *LHS, Value *RHS) {
|
||||
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
|
||||
/// overflow to change the sign bit or have a carry out.
|
||||
/// TODO: Handle this for Vectors.
|
||||
bool InstCombiner::WillNotOverflowSignedSub(Value *LHS, Value *RHS) {
|
||||
// If LHS and RHS each have at least two sign bits, the subtraction
|
||||
// cannot overflow.
|
||||
if (ComputeNumSignBits(LHS) > 1 && ComputeNumSignBits(RHS) > 1)
|
||||
return true;
|
||||
|
||||
if (IntegerType *IT = dyn_cast<IntegerType>(LHS->getType())) {
|
||||
unsigned BitWidth = IT->getBitWidth();
|
||||
APInt LHSKnownZero(BitWidth, 0);
|
||||
APInt LHSKnownOne(BitWidth, 0);
|
||||
computeKnownBits(LHS, LHSKnownZero, LHSKnownOne);
|
||||
|
||||
APInt RHSKnownZero(BitWidth, 0);
|
||||
APInt RHSKnownOne(BitWidth, 0);
|
||||
computeKnownBits(RHS, RHSKnownZero, RHSKnownOne);
|
||||
|
||||
// Subtraction of two 2's compliment numbers having identical signs will
|
||||
// never overflow.
|
||||
if ((LHSKnownOne[BitWidth - 1] && RHSKnownOne[BitWidth - 1]) ||
|
||||
(LHSKnownZero[BitWidth - 1] && RHSKnownZero[BitWidth - 1]))
|
||||
return true;
|
||||
|
||||
// TODO: implement logic similar to checkRippleForAdd
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Checks if any operand is negative and we can convert add to sub.
|
||||
// This function checks for following negative patterns
|
||||
// ADD(XOR(OR(Z, NOT(C)), C)), 1) == NEG(AND(Z, C))
|
||||
@ -1623,7 +1655,13 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||
return ReplaceInstUsesWith(I, Res);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
bool Changed = false;
|
||||
if (!I.hasNoSignedWrap() && WillNotOverflowSignedSub(Op0, Op1)) {
|
||||
Changed = true;
|
||||
I.setHasNoSignedWrap(true);
|
||||
}
|
||||
|
||||
return Changed ? &I : nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFSub(BinaryOperator &I) {
|
||||
|
Reference in New Issue
Block a user