From ec8a8b54379c1f4fef5233eed9b75bf12f4fdba1 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Wed, 9 Mar 2016 21:05:07 +0000 Subject: [PATCH] [InstCombine] (icmp sgt smin(PosA, B) 0) -> (icmp sgt B 0) When checking whether an smin is positive, we can move the comparison to one of the inputs if the other is known positive. If the known positive one is the min, then the other can't be negative. If the other is the min, then we compute the min. Differential Revision: http://reviews.llvm.org/D17873 llvm-svn: 263059 --- .../InstCombine/InstCombineCompares.cpp | 13 +++++++ .../Transforms/InstCombine/min-positive.ll | 34 +++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/min-positive.ll diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 6ee0525ea18f..703506d80982 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3173,6 +3173,19 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { return Res; } + // (icmp sgt smin(PosA, B) 0) -> (icmp sgt B 0) + if (CI->isZero() && I.getPredicate() == ICmpInst::ICMP_SGT) + if (auto *SI = dyn_cast(Op0)) { + SelectPatternResult SPR = matchSelectPattern(SI, A, B); + if (SPR.Flavor == SPF_SMIN) { + if (isKnownNonNegative(A, DL) && isKnownNonZero(A, DL)) + return new ICmpInst(I.getPredicate(), B, CI); + if (isKnownNonNegative(B, DL) && isKnownNonZero(B, DL)) + return new ICmpInst(I.getPredicate(), A, CI); + } + } + + // The following transforms are only 'worth it' if the only user of the // subtraction is the icmp. if (Op0->hasOneUse()) { diff --git a/llvm/test/Transforms/InstCombine/min-positive.ll b/llvm/test/Transforms/InstCombine/min-positive.ll new file mode 100644 index 000000000000..9bbdb2944a32 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/min-positive.ll @@ -0,0 +1,34 @@ +; RUN: opt -S -instcombine < %s | FileCheck %s + +@g = external global i32 + +define i1 @test(i32 %other) { +; CHECK-LABEL: @test +; CHECK: %test = icmp sgt i32 %other, 0 + %positive = load i32, i32* @g, !range !{i32 1, i32 2048} + %cmp = icmp slt i32 %positive, %other + %sel = select i1 %cmp, i32 %positive, i32 %other + %test = icmp sgt i32 %sel, 0 + ret i1 %test +} + +define i1 @test2(i32 %other) { +; CHECK-LABEL: @test2 +; CHECK: %test = icmp sgt i32 %other, 0 + %positive = load i32, i32* @g, !range !{i32 1, i32 2048} + %cmp = icmp slt i32 %other, %positive + %sel = select i1 %cmp, i32 %other, i32 %positive + %test = icmp sgt i32 %sel, 0 + ret i1 %test +} + +; %positive might be zero +define i1 @test3(i32 %other) { +; CHECK-LABEL: @test3 +; CHECK: %test = icmp sgt i32 %sel, 0 + %positive = load i32, i32* @g, !range !{i32 0, i32 2048} + %cmp = icmp slt i32 %positive, %other + %sel = select i1 %cmp, i32 %positive, i32 %other + %test = icmp sgt i32 %sel, 0 + ret i1 %test +}