[llvm] r281631 - [InstCombine] allow icmp (sub nsw) folds for vectors

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 15 11:05:17 PDT 2016


Author: spatel
Date: Thu Sep 15 13:05:17 2016
New Revision: 281631

URL: http://llvm.org/viewvc/llvm-project?rev=281631&view=rev
Log:
[InstCombine] allow icmp (sub nsw) folds for vectors

Also, clean up the code and comments for the existing folds in foldICmpSubConstant().

Modified:
    llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
    llvm/trunk/test/Transforms/InstCombine/icmp.ll

Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?rev=281631&r1=281630&r2=281631&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Thu Sep 15 13:05:17 2016
@@ -1420,30 +1420,6 @@ Instruction *InstCombiner::foldICmpWithC
   if (!CI)
     return nullptr;
 
-  // The following transforms are only worth it if the only user of the subtract
-  // is the icmp.
-  if (X->hasOneUse()) {
-    // (icmp sgt (sub nsw A B), -1) -> (icmp sge A, B)
-    if (Pred == ICmpInst::ICMP_SGT && CI->isAllOnesValue() &&
-        match(X, m_NSWSub(m_Value(A), m_Value(B))))
-      return new ICmpInst(ICmpInst::ICMP_SGE, A, B);
-
-    // (icmp sgt (sub nsw A B), 0) -> (icmp sgt A, B)
-    if (Pred == ICmpInst::ICMP_SGT && CI->isZero() &&
-        match(X, m_NSWSub(m_Value(A), m_Value(B))))
-      return new ICmpInst(ICmpInst::ICMP_SGT, A, B);
-
-    // (icmp slt (sub nsw A B), 0) -> (icmp slt A, B)
-    if (Pred == ICmpInst::ICMP_SLT && CI->isZero() &&
-        match(X, m_NSWSub(m_Value(A), m_Value(B))))
-      return new ICmpInst(ICmpInst::ICMP_SLT, A, B);
-
-    // (icmp slt (sub nsw A B), 1) -> (icmp sle A, B)
-    if (Pred == ICmpInst::ICMP_SLT && CI->isOne() &&
-        match(X, m_NSWSub(m_Value(A), m_Value(B))))
-      return new ICmpInst(ICmpInst::ICMP_SLE, A, B);
-  }
-
   if (Cmp.isEquality()) {
     ConstantInt *CI2;
     if (match(X, m_AShr(m_ConstantInt(CI2), m_Value(A))) ||
@@ -2306,27 +2282,46 @@ Instruction *InstCombiner::foldICmpDivCo
 Instruction *InstCombiner::foldICmpSubConstant(ICmpInst &Cmp,
                                                BinaryOperator *Sub,
                                                const APInt *C) {
+  Value *X = Sub->getOperand(0), *Y = Sub->getOperand(1);
+  ICmpInst::Predicate Pred = Cmp.getPredicate();
+
+  // The following transforms are only worth it if the only user of the subtract
+  // is the icmp.
+  if (!Sub->hasOneUse())
+    return nullptr;
+
+  if (Sub->hasNoSignedWrap()) {
+    // (icmp sgt (sub nsw X, Y), -1) -> (icmp sge X, Y)
+    if (Pred == ICmpInst::ICMP_SGT && C->isAllOnesValue())
+      return new ICmpInst(ICmpInst::ICMP_SGE, X, Y);
+
+    // (icmp sgt (sub nsw X, Y), 0) -> (icmp sgt X, Y)
+    if (Pred == ICmpInst::ICMP_SGT && *C == 0)
+      return new ICmpInst(ICmpInst::ICMP_SGT, X, Y);
+
+    // (icmp slt (sub nsw X, Y), 0) -> (icmp slt X, Y)
+    if (Pred == ICmpInst::ICMP_SLT && *C == 0)
+      return new ICmpInst(ICmpInst::ICMP_SLT, X, Y);
+
+    // (icmp slt (sub nsw X, Y), 1) -> (icmp sle X, Y)
+    if (Pred == ICmpInst::ICMP_SLT && *C == 1)
+      return new ICmpInst(ICmpInst::ICMP_SLE, X, Y);
+  }
+
   const APInt *C2;
-  if (!match(Sub->getOperand(0), m_APInt(C2)) || !Sub->hasOneUse())
+  if (!match(X, m_APInt(C2)))
     return nullptr;
 
-  // C-X <u C2 -> (X|(C2-1)) == C
-  //   iff C & (C2-1) == C2-1
-  //       C2 is a power of 2
-  if (Cmp.getPredicate() == ICmpInst::ICMP_ULT && C->isPowerOf2() &&
+  // C2 - Y <u C -> (Y | (C - 1)) == C2
+  //   iff (C2 & (C - 1)) == C - 1 and C is a power of 2
+  if (Pred == ICmpInst::ICMP_ULT && C->isPowerOf2() &&
       (*C2 & (*C - 1)) == (*C - 1))
-    return new ICmpInst(ICmpInst::ICMP_EQ,
-                        Builder->CreateOr(Sub->getOperand(1), *C - 1),
-                        Sub->getOperand(0));
-
-  // C-X >u C2 -> (X|C2) != C
-  //   iff C & C2 == C2
-  //       C2+1 is a power of 2
-  if (Cmp.getPredicate() == ICmpInst::ICMP_UGT && (*C + 1).isPowerOf2() &&
-      (*C2 & *C) == *C)
-    return new ICmpInst(ICmpInst::ICMP_NE,
-                        Builder->CreateOr(Sub->getOperand(1), *C),
-                        Sub->getOperand(0));
+    return new ICmpInst(ICmpInst::ICMP_EQ, Builder->CreateOr(Y, *C - 1), X);
+
+  // C2 - Y >u C -> (Y | C) != C2
+  //   iff C2 & C == C and C + 1 is a power of 2
+  if (Pred == ICmpInst::ICMP_UGT && (*C + 1).isPowerOf2() && (*C2 & *C) == *C)
+    return new ICmpInst(ICmpInst::ICMP_NE, Builder->CreateOr(Y, *C), X);
 
   return nullptr;
 }

Modified: llvm/trunk/test/Transforms/InstCombine/icmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/icmp.ll?rev=281631&r1=281630&r2=281631&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/icmp.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/icmp.ll Thu Sep 15 13:05:17 2016
@@ -2315,8 +2315,7 @@ define i1 @f1(i64 %a, i64 %b) {
 
 define <2 x i1> @f1_vec(<2 x i64> %a, <2 x i64> %b) {
 ; CHECK-LABEL: @f1_vec(
-; CHECK-NEXT:    [[T:%.*]] = sub nsw <2 x i64> %a, %b
-; CHECK-NEXT:    [[V:%.*]] = icmp sgt <2 x i64> [[T]], <i64 -1, i64 -1>
+; CHECK-NEXT:    [[V:%.*]] = icmp sge <2 x i64> %a, %b
 ; CHECK-NEXT:    ret <2 x i1> [[V]]
 ;
   %t = sub nsw <2 x i64> %a, %b
@@ -2336,8 +2335,7 @@ define i1 @f2(i64 %a, i64 %b) {
 
 define <2 x i1> @f2_vec(<2 x i64> %a, <2 x i64> %b) {
 ; CHECK-LABEL: @f2_vec(
-; CHECK-NEXT:    [[T:%.*]] = sub nsw <2 x i64> %a, %b
-; CHECK-NEXT:    [[V:%.*]] = icmp sgt <2 x i64> [[T]], zeroinitializer
+; CHECK-NEXT:    [[V:%.*]] = icmp sgt <2 x i64> %a, %b
 ; CHECK-NEXT:    ret <2 x i1> [[V]]
 ;
   %t = sub nsw <2 x i64> %a, %b
@@ -2357,8 +2355,7 @@ define i1 @f3(i64 %a, i64 %b) {
 
 define <2 x i1> @f3_vec(<2 x i64> %a, <2 x i64> %b) {
 ; CHECK-LABEL: @f3_vec(
-; CHECK-NEXT:    [[T:%.*]] = sub nsw <2 x i64> %a, %b
-; CHECK-NEXT:    [[V:%.*]] = icmp slt <2 x i64> [[T]], zeroinitializer
+; CHECK-NEXT:    [[V:%.*]] = icmp slt <2 x i64> %a, %b
 ; CHECK-NEXT:    ret <2 x i1> [[V]]
 ;
   %t = sub nsw <2 x i64> %a, %b
@@ -2378,8 +2375,7 @@ define i1 @f4(i64 %a, i64 %b) {
 
 define <2 x i1> @f4_vec(<2 x i64> %a, <2 x i64> %b) {
 ; CHECK-LABEL: @f4_vec(
-; CHECK-NEXT:    [[T:%.*]] = sub nsw <2 x i64> %a, %b
-; CHECK-NEXT:    [[V:%.*]] = icmp slt <2 x i64> [[T]], <i64 1, i64 1>
+; CHECK-NEXT:    [[V:%.*]] = icmp sle <2 x i64> %a, %b
 ; CHECK-NEXT:    ret <2 x i1> [[V]]
 ;
   %t = sub nsw <2 x i64> %a, %b




More information about the llvm-commits mailing list