From: Duncan Sands Date: Sun, 13 Feb 2011 17:15:40 +0000 (+0000) Subject: Teach instsimplify that X+Y>=X+Z is the same as Y>=Z if neither side overflows, X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=52fb846578714d14bbde9b28884a6a8729217677;p=oota-llvm.git 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 --- 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/2011-01-18-Compare.ll deleted file mode 100644 index e08ee2c6fb5..00000000000 --- a/test/Transforms/InstSimplify/2011-01-18-Compare.ll +++ /dev/null @@ -1,169 +0,0 @@ -; RUN: opt < %s -instsimplify -S | FileCheck %s -target datalayout = "p:32:32" - -define i1 @ptrtoint() { -; CHECK: @ptrtoint - %a = alloca i8 - %tmp = ptrtoint i8* %a to i32 - %r = icmp eq i32 %tmp, 0 - ret i1 %r -; CHECK: ret i1 false -} - -define i1 @zext(i32 %x) { -; CHECK: @zext - %e1 = zext i32 %x to i64 - %e2 = zext i32 %x to i64 - %r = icmp eq i64 %e1, %e2 - ret i1 %r -; CHECK: ret i1 true -} - -define i1 @zext2(i1 %x) { -; CHECK: @zext2 - %e = zext i1 %x to i32 - %c = icmp ne i32 %e, 0 - ret i1 %c -; CHECK: ret i1 %x -} - -define i1 @zext3() { -; CHECK: @zext3 - %e = zext i1 1 to i32 - %c = icmp ne i32 %e, 0 - ret i1 %c -; CHECK: ret i1 true -} - -define i1 @sext(i32 %x) { -; CHECK: @sext - %e1 = sext i32 %x to i64 - %e2 = sext i32 %x to i64 - %r = icmp eq i64 %e1, %e2 - ret i1 %r -; CHECK: ret i1 true -} - -define i1 @sext2(i1 %x) { -; CHECK: @sext2 - %e = sext i1 %x to i32 - %c = icmp ne i32 %e, 0 - ret i1 %c -; CHECK: ret i1 %x -} - -define i1 @sext3() { -; CHECK: @sext3 - %e = sext i1 1 to i32 - %c = icmp ne i32 %e, 0 - ret i1 %c -; CHECK: ret i1 true -} - -define i1 @add(i32 %x, i32 %y) { -; CHECK: @add - %l = lshr i32 %x, 1 - %q = lshr i32 %y, 1 - %r = or i32 %q, 1 - %s = add i32 %l, %r - %c = icmp eq i32 %s, 0 - ret i1 %c -; CHECK: ret i1 false -} - -define i1 @add2(i8 %x, i8 %y) { -; CHECK: @add2 - %l = or i8 %x, 128 - %r = or i8 %y, 129 - %s = add i8 %l, %r - %c = icmp eq i8 %s, 0 - ret i1 %c -; CHECK: ret i1 false -} - -define i1 @add3(i8 %x, i8 %y) { -; CHECK: @add3 - %l = zext i8 %x to i32 - %r = zext i8 %y to i32 - %s = add i32 %l, %r - %c = icmp eq i32 %s, 0 - ret i1 %c -; CHECK: ret i1 %c -} - -define i1 @addpowtwo(i32 %x, i32 %y) { -; CHECK: @addpowtwo - %l = lshr i32 %x, 1 - %r = shl i32 1, %y - %s = add i32 %l, %r - %c = icmp eq i32 %s, 0 - ret i1 %c -; CHECK: ret i1 false -} - -define i1 @or(i32 %x) { -; CHECK: @or - %o = or i32 %x, 1 - %c = icmp eq i32 %o, 0 - ret i1 %c -; CHECK: ret i1 false -} - -define i1 @shl(i32 %x) { -; CHECK: @shl - %s = shl i32 1, %x - %c = icmp eq i32 %s, 0 - ret i1 %c -; CHECK: ret i1 false -} - -define i1 @lshr(i32 %x) { -; CHECK: @lshr - %s = lshr i32 -1, %x - %c = icmp eq i32 %s, 0 - ret i1 %c -; CHECK: ret i1 false -} - -define i1 @ashr(i32 %x) { -; CHECK: @ashr - %s = ashr i32 -1, %x - %c = icmp eq i32 %s, 0 - ret i1 %c -; CHECK: ret i1 false -} - -define i1 @select1(i1 %cond) { -; CHECK: @select1 - %s = select i1 %cond, i32 1, i32 0 - %c = icmp eq i32 %s, 1 - ret i1 %c -; CHECK: ret i1 %cond -} - -define i1 @select2(i1 %cond) { -; CHECK: @select2 - %x = zext i1 %cond to i32 - %s = select i1 %cond, i32 %x, i32 0 - %c = icmp ne i32 %s, 0 - ret i1 %c -; CHECK: ret i1 %cond -} - -define i1 @select3(i1 %cond) { -; CHECK: @select3 - %x = zext i1 %cond to i32 - %s = select i1 %cond, i32 1, i32 %x - %c = icmp ne i32 %s, 0 - ret i1 %c -; CHECK: ret i1 %cond -} - -define i1 @select4(i1 %cond) { -; CHECK: @select4 - %invert = xor i1 %cond, 1 - %s = select i1 %invert, i32 0, i32 1 - %c = icmp ne i32 %s, 0 - ret i1 %c -; CHECK: ret i1 %cond -} diff --git a/test/Transforms/InstSimplify/compare.ll b/test/Transforms/InstSimplify/compare.ll new file mode 100644 index 00000000000..250e44ce340 --- /dev/null +++ b/test/Transforms/InstSimplify/compare.ll @@ -0,0 +1,189 @@ +; RUN: opt < %s -instsimplify -S | FileCheck %s +target datalayout = "p:32:32" + +define i1 @ptrtoint() { +; CHECK: @ptrtoint + %a = alloca i8 + %tmp = ptrtoint i8* %a to i32 + %r = icmp eq i32 %tmp, 0 + ret i1 %r +; CHECK: ret i1 false +} + +define i1 @zext(i32 %x) { +; CHECK: @zext + %e1 = zext i32 %x to i64 + %e2 = zext i32 %x to i64 + %r = icmp eq i64 %e1, %e2 + ret i1 %r +; CHECK: ret i1 true +} + +define i1 @zext2(i1 %x) { +; CHECK: @zext2 + %e = zext i1 %x to i32 + %c = icmp ne i32 %e, 0 + ret i1 %c +; CHECK: ret i1 %x +} + +define i1 @zext3() { +; CHECK: @zext3 + %e = zext i1 1 to i32 + %c = icmp ne i32 %e, 0 + ret i1 %c +; CHECK: ret i1 true +} + +define i1 @sext(i32 %x) { +; CHECK: @sext + %e1 = sext i32 %x to i64 + %e2 = sext i32 %x to i64 + %r = icmp eq i64 %e1, %e2 + ret i1 %r +; CHECK: ret i1 true +} + +define i1 @sext2(i1 %x) { +; CHECK: @sext2 + %e = sext i1 %x to i32 + %c = icmp ne i32 %e, 0 + ret i1 %c +; CHECK: ret i1 %x +} + +define i1 @sext3() { +; CHECK: @sext3 + %e = sext i1 1 to i32 + %c = icmp ne i32 %e, 0 + ret i1 %c +; CHECK: ret i1 true +} + +define i1 @add(i32 %x, i32 %y) { +; CHECK: @add + %l = lshr i32 %x, 1 + %q = lshr i32 %y, 1 + %r = or i32 %q, 1 + %s = add i32 %l, %r + %c = icmp eq i32 %s, 0 + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @add2(i8 %x, i8 %y) { +; CHECK: @add2 + %l = or i8 %x, 128 + %r = or i8 %y, 129 + %s = add i8 %l, %r + %c = icmp eq i8 %s, 0 + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @add3(i8 %x, i8 %y) { +; CHECK: @add3 + %l = zext i8 %x to i32 + %r = zext i8 %y to i32 + %s = add i32 %l, %r + %c = icmp eq i32 %s, 0 + ret i1 %c +; 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 + %r = shl i32 1, %y + %s = add i32 %l, %r + %c = icmp eq i32 %s, 0 + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @or(i32 %x) { +; CHECK: @or + %o = or i32 %x, 1 + %c = icmp eq i32 %o, 0 + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @shl(i32 %x) { +; CHECK: @shl + %s = shl i32 1, %x + %c = icmp eq i32 %s, 0 + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @lshr(i32 %x) { +; CHECK: @lshr + %s = lshr i32 -1, %x + %c = icmp eq i32 %s, 0 + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @ashr(i32 %x) { +; CHECK: @ashr + %s = ashr i32 -1, %x + %c = icmp eq i32 %s, 0 + ret i1 %c +; CHECK: ret i1 false +} + +define i1 @select1(i1 %cond) { +; CHECK: @select1 + %s = select i1 %cond, i32 1, i32 0 + %c = icmp eq i32 %s, 1 + ret i1 %c +; CHECK: ret i1 %cond +} + +define i1 @select2(i1 %cond) { +; CHECK: @select2 + %x = zext i1 %cond to i32 + %s = select i1 %cond, i32 %x, i32 0 + %c = icmp ne i32 %s, 0 + ret i1 %c +; CHECK: ret i1 %cond +} + +define i1 @select3(i1 %cond) { +; CHECK: @select3 + %x = zext i1 %cond to i32 + %s = select i1 %cond, i32 1, i32 %x + %c = icmp ne i32 %s, 0 + ret i1 %c +; CHECK: ret i1 %cond +} + +define i1 @select4(i1 %cond) { +; CHECK: @select4 + %invert = xor i1 %cond, 1 + %s = select i1 %invert, i32 0, i32 1 + %c = icmp ne i32 %s, 0 + ret i1 %c +; CHECK: ret i1 %cond +}