From: David Majnemer Date: Sat, 1 Nov 2014 09:09:51 +0000 (+0000) Subject: InstCombine: Combine (X+cst) < 0 --> X < -cst X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=f74443e53a62e5a26d4db0d804ef9e3d8d6b2499 InstCombine: Combine (X+cst) < 0 --> X < -cst This can happen pretty often in code that looks like: int foo = bar - 1; if (foo < 0) do stuff In this case, bar < 1 is an equivalent condition. This transform requires that the add instruction be annotated with nsw. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221045 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 0288dfd1c5a..bd1b67ddcfa 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3015,6 +3015,12 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { if (BO1 && BO1->getOpcode() == Instruction::Add) C = BO1->getOperand(0), D = BO1->getOperand(1); + // icmp (X+cst) < 0 --> X < -cst + if (NoOp0WrapProblem && ICmpInst::isSigned(Pred) && match(Op1, m_Zero())) + if (ConstantInt *RHSC = dyn_cast_or_null(B)) + if (!RHSC->isMinValue(/*isSigned=*/true)) + return new ICmpInst(Pred, A, ConstantExpr::getNeg(RHSC)); + // 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, diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index 343f80cfeb9..8c65d9cefc8 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -1479,3 +1479,35 @@ define i1 @shl_ap1_non_zero_ap2_non_zero_ap1_3(i32 %a) { %cmp = icmp eq i32 %shl, 50 ret i1 %cmp } + +; CHECK-LABEL: @icmp_sgt_zero_add_nsw +; CHECK-NEXT: icmp sgt i32 %a, -1 +define i1 @icmp_sgt_zero_add_nsw(i32 %a) { + %add = add nsw i32 %a, 1 + %cmp = icmp sgt i32 %add, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @icmp_sge_zero_add_nsw +; CHECK-NEXT: icmp sgt i32 %a, -2 +define i1 @icmp_sge_zero_add_nsw(i32 %a) { + %add = add nsw i32 %a, 1 + %cmp = icmp sge i32 %add, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @icmp_slt_zero_add_nsw +; CHECK-NEXT: icmp slt i32 %a, -1 +define i1 @icmp_slt_zero_add_nsw(i32 %a) { + %add = add nsw i32 %a, 1 + %cmp = icmp slt i32 %add, 0 + ret i1 %cmp +} + +; CHECK-LABEL: @icmp_sle_zero_add_nsw +; CHECK-NEXT: icmp slt i32 %a, 0 +define i1 @icmp_sle_zero_add_nsw(i32 %a) { + %add = add nsw i32 %a, 1 + %cmp = icmp sle i32 %add, 0 + ret i1 %cmp +}