]> granicus.if.org Git - llvm/commitdiff
[InstCombine] Fold icmp eq/ne (udiv i32 A, B), 0 -> icmp ugt/ule B, A.
authorChad Rosier <mcrosier@codeaurora.org>
Mon, 9 May 2016 19:30:20 +0000 (19:30 +0000)
committerChad Rosier <mcrosier@codeaurora.org>
Mon, 9 May 2016 19:30:20 +0000 (19:30 +0000)
Differential Revision: http://reviews.llvm.org/D20036

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@268960 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/InstCombine/InstCombineCompares.cpp
test/Transforms/InstCombine/compare-udiv.ll [new file with mode: 0644]
test/Transforms/InstCombine/exact.ll

index 80ae406604b34085f0fe79d9410897595f1936dc..28a5bd802360f7b19f9edf66fbbebecadd72561d 100644 (file)
@@ -2105,6 +2105,8 @@ Instruction *InstCombiner::visitICmpInstWithInstAndIntCst(ICmpInst &ICI,
       if (Instruction *R = FoldICmpDivCst(ICI, cast<BinaryOperator>(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<ConstantInt>(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<Instruction>(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 (file)
index 0000000..d919d77
--- /dev/null
@@ -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
+}
index 868d60ac46b1502171bb4a5d15841f8cf5927ea7..3670d38a02b061f37a10222117eba60a21f1a958 100644 (file)
@@ -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 {