diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 51c5f2abddb..7adabe54d24 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -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(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(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(LHS); + BinaryOperator *RBO = dyn_cast(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(LHS) || isa(RHS)) diff --git a/test/Transforms/InstSimplify/2011-01-18-Compare.ll b/test/Transforms/InstSimplify/compare.ll similarity index 88% rename from test/Transforms/InstSimplify/2011-01-18-Compare.ll rename to test/Transforms/InstSimplify/compare.ll index e08ee2c6fb5..250e44ce340 100644 --- a/test/Transforms/InstSimplify/2011-01-18-Compare.ll +++ b/test/Transforms/InstSimplify/compare.ll @@ -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