From: Chad Rosier Date: Mon, 9 May 2016 19:30:20 +0000 (+0000) Subject: [InstCombine] Fold icmp eq/ne (udiv i32 A, B), 0 -> icmp ugt/ule B, A. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f9451d9d7f6e6b46b75980da2b700781906d757d;p=llvm [InstCombine] Fold icmp eq/ne (udiv i32 A, B), 0 -> icmp ugt/ule B, A. Differential Revision: http://reviews.llvm.org/D20036 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@268960 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/InstCombine/InstCombineCompares.cpp b/lib/Transforms/InstCombine/InstCombineCompares.cpp index 80ae406604b..28a5bd80236 100644 --- a/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -2105,6 +2105,8 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI, if (Instruction *R = FoldICmpDivCst(ICI, cast(LHSI), DivRHS)) return R; + // FIXME: Handle (icmp ugt (udiv i32 CI2, A), CI) and + // (icmp ult (udiv i32 CI2, A), CI). break; case Instruction::Sub: { @@ -3583,12 +3585,22 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { // See if we are doing a comparison between a constant and an instruction that // can be folded into the comparison. if (ConstantInt *CI = dyn_cast(Op1)) { + Value *A = nullptr, *B = nullptr; // Since the RHS is a ConstantInt (CI), if the left hand side is an // instruction, see if that instruction also has constants so that the // instruction can be folded into the icmp if (Instruction *LHSI = dyn_cast(Op0)) if (Instruction *Res = visitICmpInstWithInstAndIntCst(I, LHSI, CI)) return Res; + + // (icmp eq/ne (udiv A, B), 0) -> (icmp ugt/ule i32 B, A) + if (I.isEquality() && CI->isZero() && + match(Op0, m_UDiv(m_Value(A), m_Value(B)))) { + ICmpInst::Predicate Pred = I.getPredicate() == ICmpInst::ICMP_EQ + ? ICmpInst::ICMP_UGT + : ICmpInst::ICMP_ULE; + return new ICmpInst(Pred, B, A); + } } // Handle icmp with constant (but not simple integer constant) RHS diff --git a/test/Transforms/InstCombine/compare-udiv.ll b/test/Transforms/InstCombine/compare-udiv.ll new file mode 100644 index 00000000000..d919d77a5b2 --- /dev/null +++ b/test/Transforms/InstCombine/compare-udiv.ll @@ -0,0 +1,41 @@ +; RUN: opt -instcombine -S < %s | FileCheck %s + +; CHECK-LABEL: @test1 +; CHECK: %cmp1 = icmp ugt i32 %d, %n +define i1 @test1(i32 %n, i32 %d) { + %div = udiv i32 %n, %d + %cmp1 = icmp eq i32 %div, 0 + ret i1 %cmp1 +} + +; CHECK-LABEL: @test2 +; CHECK: %cmp1 = icmp ugt i32 %d, 64 +define i1 @test2(i32 %d) { + %div = udiv i32 64, %d + %cmp1 = icmp eq i32 %div, 0 + ret i1 %cmp1 +} + +; CHECK-LABEL: @test3 +; CHECK: %cmp1 = icmp ule i32 %d, %n +define i1 @test3(i32 %n, i32 %d) { + %div = udiv i32 %n, %d + %cmp1 = icmp ne i32 %div, 0 + ret i1 %cmp1 +} + +; CHECK-LABEL: @test4 +; CHECK: %cmp1 = icmp ult i32 %d, 65 +define i1 @test4(i32 %d) { + %div = udiv i32 64, %d + %cmp1 = icmp ne i32 %div, 0 + ret i1 %cmp1 +} + +; CHECK-LABEL: @test5 +; CHECK: ret i1 true +define i1 @test5(i32 %d) { + %div = udiv i32 -1, %d + %cmp1 = icmp ne i32 %div, 0 + ret i1 %cmp1 +} diff --git a/test/Transforms/InstCombine/exact.ll b/test/Transforms/InstCombine/exact.ll index 868d60ac46b..3670d38a02b 100644 --- a/test/Transforms/InstCombine/exact.ll +++ b/test/Transforms/InstCombine/exact.ll @@ -121,6 +121,14 @@ define i1 @udiv_icmp1(i64 %X) nounwind { ret i1 %B } +; CHECK-LABEL: @udiv_icmp2( +; CHECK: icmp eq i64 %X, 0 +define i1 @udiv_icmp2(i64 %X) nounwind { + %A = udiv exact i64 %X, 5 ; X/5 == 0 --> x == 0 + %B = icmp eq i64 %A, 0 + ret i1 %B +} + ; CHECK-LABEL: @sdiv_icmp1( ; CHECK: icmp eq i64 %X, 0 define i1 @sdiv_icmp1(i64 %X) nounwind {