mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-25 16:24:23 +00:00
Transform "A + B >= A + C" into "B >= C" if the adds do not wrap. Likewise for some
variations (some of these were already present so I unified the code). Spotted by my auto-simplifier as occurring a lot. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125734 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -698,13 +698,6 @@ Instruction *InstCombiner::FoldICmpAddOpCst(ICmpInst &ICI,
|
|||||||
if (Pred == ICmpInst::ICMP_NE)
|
if (Pred == ICmpInst::ICMP_NE)
|
||||||
return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(X->getContext()));
|
return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(X->getContext()));
|
||||||
|
|
||||||
// If this is an instruction (as opposed to constantexpr) get NUW/NSW info.
|
|
||||||
bool isNUW = false, isNSW = false;
|
|
||||||
if (BinaryOperator *Add = dyn_cast<BinaryOperator>(TheAdd)) {
|
|
||||||
isNUW = Add->hasNoUnsignedWrap();
|
|
||||||
isNSW = Add->hasNoSignedWrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
// From this point on, we know that (X+C <= X) --> (X+C < X) because C != 0,
|
// From this point on, we know that (X+C <= X) --> (X+C < X) because C != 0,
|
||||||
// so the values can never be equal. Similiarly for all other "or equals"
|
// so the values can never be equal. Similiarly for all other "or equals"
|
||||||
// operators.
|
// operators.
|
||||||
@ -713,10 +706,6 @@ Instruction *InstCombiner::FoldICmpAddOpCst(ICmpInst &ICI,
|
|||||||
// (X+2) <u X --> X >u (MAXUINT-2) --> X > 253
|
// (X+2) <u X --> X >u (MAXUINT-2) --> X > 253
|
||||||
// (X+MAXUINT) <u X --> X >u (MAXUINT-MAXUINT) --> X != 0
|
// (X+MAXUINT) <u X --> X >u (MAXUINT-MAXUINT) --> X != 0
|
||||||
if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE) {
|
if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_ULE) {
|
||||||
// If this is an NUW add, then this is always false.
|
|
||||||
if (isNUW)
|
|
||||||
return ReplaceInstUsesWith(ICI, ConstantInt::getFalse(X->getContext()));
|
|
||||||
|
|
||||||
Value *R =
|
Value *R =
|
||||||
ConstantExpr::getSub(ConstantInt::getAllOnesValue(CI->getType()), CI);
|
ConstantExpr::getSub(ConstantInt::getAllOnesValue(CI->getType()), CI);
|
||||||
return new ICmpInst(ICmpInst::ICMP_UGT, X, R);
|
return new ICmpInst(ICmpInst::ICMP_UGT, X, R);
|
||||||
@ -725,12 +714,8 @@ Instruction *InstCombiner::FoldICmpAddOpCst(ICmpInst &ICI,
|
|||||||
// (X+1) >u X --> X <u (0-1) --> X != 255
|
// (X+1) >u X --> X <u (0-1) --> X != 255
|
||||||
// (X+2) >u X --> X <u (0-2) --> X <u 254
|
// (X+2) >u X --> X <u (0-2) --> X <u 254
|
||||||
// (X+MAXUINT) >u X --> X <u (0-MAXUINT) --> X <u 1 --> X == 0
|
// (X+MAXUINT) >u X --> X <u (0-MAXUINT) --> X <u 1 --> X == 0
|
||||||
if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE) {
|
if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_UGE)
|
||||||
// If this is an NUW add, then this is always true.
|
|
||||||
if (isNUW)
|
|
||||||
return ReplaceInstUsesWith(ICI, ConstantInt::getTrue(X->getContext()));
|
|
||||||
return new ICmpInst(ICmpInst::ICMP_ULT, X, ConstantExpr::getNeg(CI));
|
return new ICmpInst(ICmpInst::ICMP_ULT, X, ConstantExpr::getNeg(CI));
|
||||||
}
|
|
||||||
|
|
||||||
unsigned BitWidth = CI->getType()->getPrimitiveSizeInBits();
|
unsigned BitWidth = CI->getType()->getPrimitiveSizeInBits();
|
||||||
ConstantInt *SMax = ConstantInt::get(X->getContext(),
|
ConstantInt *SMax = ConstantInt::get(X->getContext(),
|
||||||
@ -742,16 +727,8 @@ Instruction *InstCombiner::FoldICmpAddOpCst(ICmpInst &ICI,
|
|||||||
// (X+MINSINT) <s X --> X >s (MAXSINT-MINSINT) --> X >s -1
|
// (X+MINSINT) <s X --> X >s (MAXSINT-MINSINT) --> X >s -1
|
||||||
// (X+ -2) <s X --> X >s (MAXSINT- -2) --> X >s 126
|
// (X+ -2) <s X --> X >s (MAXSINT- -2) --> X >s 126
|
||||||
// (X+ -1) <s X --> X >s (MAXSINT- -1) --> X != 127
|
// (X+ -1) <s X --> X >s (MAXSINT- -1) --> X != 127
|
||||||
if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE) {
|
if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SLE)
|
||||||
// If this is an NSW add, then we have two cases: if the constant is
|
|
||||||
// positive, then this is always false, if negative, this is always true.
|
|
||||||
if (isNSW) {
|
|
||||||
bool isTrue = CI->getValue().isNegative();
|
|
||||||
return ReplaceInstUsesWith(ICI, ConstantInt::get(ICI.getType(), isTrue));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ICmpInst(ICmpInst::ICMP_SGT, X, ConstantExpr::getSub(SMax, CI));
|
return new ICmpInst(ICmpInst::ICMP_SGT, X, ConstantExpr::getSub(SMax, CI));
|
||||||
}
|
|
||||||
|
|
||||||
// (X+ 1) >s X --> X <s (MAXSINT-(1-1)) --> X != 127
|
// (X+ 1) >s X --> X <s (MAXSINT-(1-1)) --> X != 127
|
||||||
// (X+ 2) >s X --> X <s (MAXSINT-(2-1)) --> X <s 126
|
// (X+ 2) >s X --> X <s (MAXSINT-(2-1)) --> X <s 126
|
||||||
@ -760,13 +737,6 @@ Instruction *InstCombiner::FoldICmpAddOpCst(ICmpInst &ICI,
|
|||||||
// (X+ -2) >s X --> X <s (MAXSINT-(-2-1)) --> X <s -126
|
// (X+ -2) >s X --> X <s (MAXSINT-(-2-1)) --> X <s -126
|
||||||
// (X+ -1) >s X --> X <s (MAXSINT-(-1-1)) --> X == -128
|
// (X+ -1) >s X --> X <s (MAXSINT-(-1-1)) --> X == -128
|
||||||
|
|
||||||
// If this is an NSW add, then we have two cases: if the constant is
|
|
||||||
// positive, then this is always true, if negative, this is always false.
|
|
||||||
if (isNSW) {
|
|
||||||
bool isTrue = !CI->getValue().isNegative();
|
|
||||||
return ReplaceInstUsesWith(ICI, ConstantInt::get(ICI.getType(), isTrue));
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE);
|
assert(Pred == ICmpInst::ICMP_SGT || Pred == ICmpInst::ICMP_SGE);
|
||||||
Constant *C = ConstantInt::get(X->getContext(), CI->getValue()-1);
|
Constant *C = ConstantInt::get(X->getContext(), CI->getValue()-1);
|
||||||
return new ICmpInst(ICmpInst::ICMP_SLT, X, ConstantExpr::getSub(SMax, C));
|
return new ICmpInst(ICmpInst::ICMP_SLT, X, ConstantExpr::getSub(SMax, C));
|
||||||
@ -2263,60 +2233,115 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
|||||||
if (Instruction *R = visitICmpInstWithCastAndCast(I))
|
if (Instruction *R = visitICmpInstWithCastAndCast(I))
|
||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if it's the same type of instruction on the left and right.
|
|
||||||
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
|
|
||||||
if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1)) {
|
|
||||||
if (Op0I->getOpcode() == Op1I->getOpcode() && Op0I->hasOneUse() &&
|
|
||||||
Op1I->hasOneUse() && Op0I->getOperand(1) == Op1I->getOperand(1)) {
|
|
||||||
switch (Op0I->getOpcode()) {
|
|
||||||
default: break;
|
|
||||||
case Instruction::Add:
|
|
||||||
case Instruction::Sub:
|
|
||||||
case Instruction::Xor:
|
|
||||||
if (I.isEquality()) // a+x icmp eq/ne b+x --> a icmp b
|
|
||||||
return new ICmpInst(I.getPredicate(), Op0I->getOperand(0),
|
|
||||||
Op1I->getOperand(0));
|
|
||||||
// icmp u/s (a ^ signbit), (b ^ signbit) --> icmp s/u a, b
|
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0I->getOperand(1))) {
|
|
||||||
if (CI->getValue().isSignBit()) {
|
|
||||||
ICmpInst::Predicate Pred = I.isSigned()
|
|
||||||
? I.getUnsignedPredicate()
|
|
||||||
: I.getSignedPredicate();
|
|
||||||
return new ICmpInst(Pred, Op0I->getOperand(0),
|
|
||||||
Op1I->getOperand(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CI->getValue().isMaxSignedValue()) {
|
|
||||||
ICmpInst::Predicate Pred = I.isSigned()
|
|
||||||
? I.getUnsignedPredicate()
|
|
||||||
: I.getSignedPredicate();
|
|
||||||
Pred = I.getSwappedPredicate(Pred);
|
|
||||||
return new ICmpInst(Pred, Op0I->getOperand(0),
|
|
||||||
Op1I->getOperand(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Instruction::Mul:
|
|
||||||
if (!I.isEquality())
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Op0I->getOperand(1))) {
|
// Special logic for binary operators.
|
||||||
// a * Cst icmp eq/ne b * Cst --> a & Mask icmp b & Mask
|
BinaryOperator *BO0 = dyn_cast<BinaryOperator>(Op0);
|
||||||
// Mask = -1 >> count-trailing-zeros(Cst).
|
BinaryOperator *BO1 = dyn_cast<BinaryOperator>(Op1);
|
||||||
if (!CI->isZero() && !CI->isOne()) {
|
if (BO0 || BO1) {
|
||||||
const APInt &AP = CI->getValue();
|
CmpInst::Predicate Pred = I.getPredicate();
|
||||||
ConstantInt *Mask = ConstantInt::get(I.getContext(),
|
bool NoOp0WrapProblem = false, NoOp1WrapProblem = false;
|
||||||
APInt::getLowBitsSet(AP.getBitWidth(),
|
if (BO0 && isa<OverflowingBinaryOperator>(BO0))
|
||||||
AP.getBitWidth() -
|
NoOp0WrapProblem = ICmpInst::isEquality(Pred) ||
|
||||||
AP.countTrailingZeros()));
|
(CmpInst::isUnsigned(Pred) && BO0->hasNoUnsignedWrap()) ||
|
||||||
Value *And1 = Builder->CreateAnd(Op0I->getOperand(0), Mask);
|
(CmpInst::isSigned(Pred) && BO0->hasNoSignedWrap());
|
||||||
Value *And2 = Builder->CreateAnd(Op1I->getOperand(0), Mask);
|
if (BO1 && isa<OverflowingBinaryOperator>(BO1))
|
||||||
return new ICmpInst(I.getPredicate(), And1, And2);
|
NoOp1WrapProblem = ICmpInst::isEquality(Pred) ||
|
||||||
}
|
(CmpInst::isUnsigned(Pred) && BO1->hasNoUnsignedWrap()) ||
|
||||||
|
(CmpInst::isSigned(Pred) && BO1->hasNoSignedWrap());
|
||||||
|
|
||||||
|
// Analyze the case when either Op0 or Op1 is an add instruction.
|
||||||
|
// Op0 = A + B (or A and B are null); Op1 = C + D (or C and D are null).
|
||||||
|
Value *A = 0, *B = 0, *C = 0, *D = 0;
|
||||||
|
if (BO0 && BO0->getOpcode() == Instruction::Add)
|
||||||
|
A = BO0->getOperand(0), B = BO0->getOperand(1);
|
||||||
|
if (BO1 && BO1->getOpcode() == Instruction::Add)
|
||||||
|
C = BO1->getOperand(0), D = BO1->getOperand(1);
|
||||||
|
|
||||||
|
// icmp (X+Y), X -> icmp Y, 0 for equalities or if there is no overflow.
|
||||||
|
if ((A == Op1 || B == Op1) && NoOp0WrapProblem)
|
||||||
|
return new ICmpInst(Pred, A == Op1 ? B : A,
|
||||||
|
Constant::getNullValue(Op1->getType()));
|
||||||
|
|
||||||
|
// icmp X, (X+Y) -> icmp 0, Y for equalities or if there is no overflow.
|
||||||
|
if ((C == Op0 || D == Op0) && NoOp1WrapProblem)
|
||||||
|
return new ICmpInst(Pred, Constant::getNullValue(Op0->getType()),
|
||||||
|
C == Op0 ? D : C);
|
||||||
|
|
||||||
|
// icmp (X+Y), (X+Z) -> icmp Y,Z for equalities or if there is no overflow.
|
||||||
|
if (A && C && (A == C || A == D || B == C || B == D) &&
|
||||||
|
NoOp0WrapProblem && NoOp1WrapProblem &&
|
||||||
|
// Try not to increase register pressure.
|
||||||
|
BO0->hasOneUse() && BO1->hasOneUse()) {
|
||||||
|
// Determine Y and Z in the form icmp (X+Y), (X+Z).
|
||||||
|
Value *Y = (A == C || A == D) ? B : A;
|
||||||
|
Value *Z = (C == A || C == B) ? D : C;
|
||||||
|
return new ICmpInst(Pred, Y, Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Analyze the case when either Op0 or Op1 is a sub instruction.
|
||||||
|
// Op0 = A - B (or A and B are null); Op1 = C - D (or C and D are null).
|
||||||
|
A = 0; B = 0; C = 0; D = 0;
|
||||||
|
if (BO0 && BO0->getOpcode() == Instruction::Sub)
|
||||||
|
A = BO0->getOperand(0), B = BO0->getOperand(1);
|
||||||
|
if (BO1 && BO1->getOpcode() == Instruction::Sub)
|
||||||
|
C = BO1->getOperand(0), D = BO1->getOperand(1);
|
||||||
|
|
||||||
|
// icmp (Y-X), (Z-X) -> icmp Y,Z for equalities or if there is no overflow.
|
||||||
|
if (B && D && B == D && NoOp0WrapProblem && NoOp1WrapProblem &&
|
||||||
|
// Try not to increase register pressure.
|
||||||
|
BO0->hasOneUse() && BO1->hasOneUse())
|
||||||
|
return new ICmpInst(Pred, A, C);
|
||||||
|
|
||||||
|
if (BO0 && BO1 && BO0->getOpcode() == BO1->getOpcode() &&
|
||||||
|
BO0->hasOneUse() && BO1->hasOneUse() &&
|
||||||
|
BO0->getOperand(1) == BO1->getOperand(1)) {
|
||||||
|
switch (BO0->getOpcode()) {
|
||||||
|
default: break;
|
||||||
|
case Instruction::Add:
|
||||||
|
case Instruction::Sub:
|
||||||
|
case Instruction::Xor:
|
||||||
|
if (I.isEquality()) // a+x icmp eq/ne b+x --> a icmp b
|
||||||
|
return new ICmpInst(I.getPredicate(), BO0->getOperand(0),
|
||||||
|
BO1->getOperand(0));
|
||||||
|
// icmp u/s (a ^ signbit), (b ^ signbit) --> icmp s/u a, b
|
||||||
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(BO0->getOperand(1))) {
|
||||||
|
if (CI->getValue().isSignBit()) {
|
||||||
|
ICmpInst::Predicate Pred = I.isSigned()
|
||||||
|
? I.getUnsignedPredicate()
|
||||||
|
: I.getSignedPredicate();
|
||||||
|
return new ICmpInst(Pred, BO0->getOperand(0),
|
||||||
|
BO1->getOperand(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CI->getValue().isMaxSignedValue()) {
|
||||||
|
ICmpInst::Predicate Pred = I.isSigned()
|
||||||
|
? I.getUnsignedPredicate()
|
||||||
|
: I.getSignedPredicate();
|
||||||
|
Pred = I.getSwappedPredicate(Pred);
|
||||||
|
return new ICmpInst(Pred, BO0->getOperand(0),
|
||||||
|
BO1->getOperand(0));
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case Instruction::Mul:
|
||||||
|
if (!I.isEquality())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (ConstantInt *CI = dyn_cast<ConstantInt>(BO0->getOperand(1))) {
|
||||||
|
// a * Cst icmp eq/ne b * Cst --> a & Mask icmp b & Mask
|
||||||
|
// Mask = -1 >> count-trailing-zeros(Cst).
|
||||||
|
if (!CI->isZero() && !CI->isOne()) {
|
||||||
|
const APInt &AP = CI->getValue();
|
||||||
|
ConstantInt *Mask = ConstantInt::get(I.getContext(),
|
||||||
|
APInt::getLowBitsSet(AP.getBitWidth(),
|
||||||
|
AP.getBitWidth() -
|
||||||
|
AP.countTrailingZeros()));
|
||||||
|
Value *And1 = Builder->CreateAnd(BO0->getOperand(0), Mask);
|
||||||
|
Value *And2 = Builder->CreateAnd(BO1->getOperand(0), Mask);
|
||||||
|
return new ICmpInst(I.getPredicate(), And1, And2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2400,18 +2425,6 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
|||||||
return new ICmpInst(I.getPredicate(), B,
|
return new ICmpInst(I.getPredicate(), B,
|
||||||
Constant::getNullValue(B->getType()));
|
Constant::getNullValue(B->getType()));
|
||||||
|
|
||||||
// (A+B) == A -> B == 0
|
|
||||||
if (match(Op0, m_Add(m_Specific(Op1), m_Value(B))) ||
|
|
||||||
match(Op0, m_Add(m_Value(B), m_Specific(Op1))))
|
|
||||||
return new ICmpInst(I.getPredicate(), B,
|
|
||||||
Constant::getNullValue(B->getType()));
|
|
||||||
|
|
||||||
// A == (A+B) -> B == 0
|
|
||||||
if (match(Op1, m_Add(m_Specific(Op0), m_Value(B))) ||
|
|
||||||
match(Op1, m_Add(m_Value(B), m_Specific(Op0))))
|
|
||||||
return new ICmpInst(I.getPredicate(), B,
|
|
||||||
Constant::getNullValue(B->getType()));
|
|
||||||
|
|
||||||
// (X&Z) == (Y&Z) -> (X^Y) & Z == 0
|
// (X&Z) == (Y&Z) -> (X^Y) & Z == 0
|
||||||
if (Op0->hasOneUse() && Op1->hasOneUse() &&
|
if (Op0->hasOneUse() && Op1->hasOneUse() &&
|
||||||
match(Op0, m_And(m_Value(A), m_Value(B))) &&
|
match(Op0, m_And(m_Value(A), m_Value(B))) &&
|
||||||
|
@ -234,3 +234,22 @@ define i1 @test24(i64 %i) {
|
|||||||
ret i1 %cmp
|
ret i1 %cmp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; CHECK: @test25
|
||||||
|
; CHECK: %c = icmp sgt i32 %x, %y
|
||||||
|
; CHECK: ret i1 %c
|
||||||
|
define i1 @test25(i32 %x, i32 %y, i32 %z) {
|
||||||
|
%lhs = add nsw i32 %x, %z
|
||||||
|
%rhs = add nsw i32 %y, %z
|
||||||
|
%c = icmp sgt i32 %lhs, %rhs
|
||||||
|
ret i1 %c
|
||||||
|
}
|
||||||
|
|
||||||
|
; CHECK: @test26
|
||||||
|
; CHECK: %c = icmp sgt i32 %x, %y
|
||||||
|
; CHECK: ret i1 %c
|
||||||
|
define i1 @test26(i32 %x, i32 %y, i32 %z) {
|
||||||
|
%lhs = sub nsw i32 %x, %z
|
||||||
|
%rhs = sub nsw i32 %y, %z
|
||||||
|
%c = icmp sgt i32 %lhs, %rhs
|
||||||
|
ret i1 %c
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user