Teach instsimplify that X+Y>=X+Z is the same as Y>=Z if neither side overflows,

plus some variations of this.  According to my auto-simplifier this occurs a lot
but usually in combination with max/min idioms.  Because max/min aren't handled
yet this unfortunately doesn't have much effect in the testsuite.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125462 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2011-02-13 17:15:40 +00:00
parent d239e5af64
commit 52fb846578
2 changed files with 69 additions and 2 deletions

View File

@ -986,7 +986,7 @@ static Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact,
if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) &&
cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap())
return X;
return 0;
}
@ -1016,7 +1016,7 @@ static Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact,
if (match(Op0, m_Shl(m_Value(X), m_Specific(Op1))) &&
cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap())
return X;
return 0;
}
@ -1588,6 +1588,53 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
}
}
// Special logic for binary operators.
BinaryOperator *LBO = dyn_cast<BinaryOperator>(LHS);
BinaryOperator *RBO = dyn_cast<BinaryOperator>(RHS);
if (MaxRecurse && (LBO || RBO)) {
// Analyze the case when either LHS or RHS is an add instruction.
Value *A = 0, *B = 0, *C = 0, *D = 0;
// LHS = A + B (or A and B are null); RHS = C + D (or C and D are null).
bool NoLHSWrapProblem = false, NoRHSWrapProblem = false;
if (LBO && LBO->getOpcode() == Instruction::Add) {
A = LBO->getOperand(0); B = LBO->getOperand(1);
NoLHSWrapProblem = ICmpInst::isEquality(Pred) ||
(CmpInst::isUnsigned(Pred) && LBO->hasNoUnsignedWrap()) ||
(CmpInst::isSigned(Pred) && LBO->hasNoSignedWrap());
}
if (RBO && RBO->getOpcode() == Instruction::Add) {
C = RBO->getOperand(0); D = RBO->getOperand(1);
NoRHSWrapProblem = ICmpInst::isEquality(Pred) ||
(CmpInst::isUnsigned(Pred) && RBO->hasNoUnsignedWrap()) ||
(CmpInst::isSigned(Pred) && RBO->hasNoSignedWrap());
}
// icmp (X+Y), X -> icmp Y, 0 for equalities or if there is no overflow.
if ((A == RHS || B == RHS) && NoLHSWrapProblem)
if (Value *V = SimplifyICmpInst(Pred, A == RHS ? B : A,
Constant::getNullValue(RHS->getType()),
TD, DT, MaxRecurse-1))
return V;
// icmp X, (X+Y) -> icmp 0, Y for equalities or if there is no overflow.
if ((C == LHS || D == LHS) && NoRHSWrapProblem)
if (Value *V = SimplifyICmpInst(Pred,
Constant::getNullValue(LHS->getType()),
C == LHS ? D : C, TD, DT, MaxRecurse-1))
return V;
// 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) &&
NoLHSWrapProblem && NoRHSWrapProblem) {
// 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;
if (Value *V = SimplifyICmpInst(Pred, Y, Z, TD, DT, MaxRecurse-1))
return V;
}
}
// If the comparison is with the result of a select instruction, check whether
// comparing with either branch of the select always yields the same value.
if (isa<SelectInst>(LHS) || isa<SelectInst>(RHS))

View File

@ -91,6 +91,26 @@ define i1 @add3(i8 %x, i8 %y) {
; CHECK: ret i1 %c
}
define i1 @add4(i32 %x, i32 %y) {
; CHECK: @add4
%z = add nsw i32 %y, 1
%s1 = add nsw i32 %x, %y
%s2 = add nsw i32 %x, %z
%c = icmp slt i32 %s1, %s2
ret i1 %c
; CHECK: ret i1 true
}
define i1 @add5(i32 %x, i32 %y) {
; CHECK: @add5
%z = add nuw i32 %y, 1
%s1 = add nuw i32 %x, %z
%s2 = add nuw i32 %x, %y
%c = icmp ugt i32 %s1, %s2
ret i1 %c
; CHECK: ret i1 true
}
define i1 @addpowtwo(i32 %x, i32 %y) {
; CHECK: @addpowtwo
%l = lshr i32 %x, 1