[llvm] r353313 - [InstCombine] X | C == C --> (X & ~C) == 0

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 6 08:43:54 PST 2019


Author: spatel
Date: Wed Feb  6 08:43:54 2019
New Revision: 353313

URL: http://llvm.org/viewvc/llvm-project?rev=353313&view=rev
Log:
[InstCombine] X | C == C --> (X & ~C) == 0

We should canonicalize to one of these forms,
and compare-with-zero could be more conducive
to follow-on transforms. This also leads to
generally better codegen as shown in PR40611:
https://bugs.llvm.org/show_bug.cgi?id=40611

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=353313&r1=353312&r2=353313&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp (original)
+++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp Wed Feb  6 08:43:54 2019
@@ -1771,13 +1771,22 @@ Instruction *InstCombiner::foldICmpOrCon
                           ConstantInt::get(V->getType(), 1));
   }
 
-  // X | C == C --> X <=u C
-  // X | C != C --> X  >u C
-  //   iff C+1 is a power of 2 (C is a bitmask of the low bits)
-  if (Cmp.isEquality() && Cmp.getOperand(1) == Or->getOperand(1) &&
-      (C + 1).isPowerOf2()) {
-    Pred = (Pred == CmpInst::ICMP_EQ) ? CmpInst::ICMP_ULE : CmpInst::ICMP_UGT;
-    return new ICmpInst(Pred, Or->getOperand(0), Or->getOperand(1));
+  Value *OrOp0 = Or->getOperand(0), *OrOp1 = Or->getOperand(1);
+  if (Cmp.isEquality() && Cmp.getOperand(1) == OrOp1) {
+    // X | C == C --> X <=u C
+    // X | C != C --> X  >u C
+    //   iff C+1 is a power of 2 (C is a bitmask of the low bits)
+    if ((C + 1).isPowerOf2()) {
+      Pred = (Pred == CmpInst::ICMP_EQ) ? CmpInst::ICMP_ULE : CmpInst::ICMP_UGT;
+      return new ICmpInst(Pred, OrOp0, OrOp1);
+    }
+    // More general: are all bits outside of a mask constant set or not set?
+    // X | C == C --> (X & ~C) == 0
+    // X | C != C --> (X & ~C) != 0
+    if (Or->hasOneUse()) {
+      Value *A = Builder.CreateAnd(OrOp0, ~C);
+      return new ICmpInst(Pred, A, ConstantInt::getNullValue(OrOp0->getType()));
+    }
   }
 
   if (!Cmp.isEquality() || !C.isNullValue() || !Or->hasOneUse())
@@ -1798,8 +1807,8 @@ Instruction *InstCombiner::foldICmpOrCon
   // Are we using xors to bitwise check for a pair of (in)equalities? Convert to
   // a shorter form that has more potential to be folded even further.
   Value *X1, *X2, *X3, *X4;
-  if (match(Or->getOperand(0), m_OneUse(m_Xor(m_Value(X1), m_Value(X2)))) &&
-      match(Or->getOperand(1), m_OneUse(m_Xor(m_Value(X3), m_Value(X4))))) {
+  if (match(OrOp0, m_OneUse(m_Xor(m_Value(X1), m_Value(X2)))) &&
+      match(OrOp1, m_OneUse(m_Xor(m_Value(X3), m_Value(X4))))) {
     // ((X1 ^ X2) || (X3 ^ X4)) == 0 --> (X1 == X2) && (X3 == X4)
     // ((X1 ^ X2) || (X3 ^ X4)) != 0 --> (X1 != X2) || (X3 != X4)
     Value *Cmp12 = Builder.CreateICmp(Pred, X1, X2);

Modified: llvm/trunk/test/Transforms/InstCombine/icmp.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/icmp.ll?rev=353313&r1=353312&r2=353313&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/icmp.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/icmp.ll Wed Feb  6 08:43:54 2019
@@ -2169,8 +2169,8 @@ define <2 x i1> @or63_ne63_vec(<2 x i8>
 
 define i1 @orC_eqC(i32 %x) {
 ; CHECK-LABEL: @orC_eqC(
-; CHECK-NEXT:    [[T0:%.*]] = or i32 [[X:%.*]], 42
-; CHECK-NEXT:    [[T1:%.*]] = icmp eq i32 [[T0]], 42
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[X:%.*]], -43
+; CHECK-NEXT:    [[T1:%.*]] = icmp eq i32 [[TMP1]], 0
 ; CHECK-NEXT:    ret i1 [[T1]]
 ;
   %t0 = or i32 %x, 42
@@ -2182,8 +2182,8 @@ define i1 @orC_eqC(i32 %x) {
 
 define <2 x i1> @orC_eqC_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @orC_eqC_vec(
-; CHECK-NEXT:    [[T0:%.*]] = or <2 x i8> [[X:%.*]], <i8 43, i8 43>
-; CHECK-NEXT:    [[T1:%.*]] = icmp eq <2 x i8> [[T0]], <i8 43, i8 43>
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 -44, i8 -44>
+; CHECK-NEXT:    [[T1:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[T1]]
 ;
   %t0 = or <2 x i8> %x, <i8 43, i8 43>
@@ -2195,8 +2195,8 @@ define <2 x i1> @orC_eqC_vec(<2 x i8> %x
 
 define i1 @orC_neC(i32 %x) {
 ; CHECK-LABEL: @orC_neC(
-; CHECK-NEXT:    [[T0:%.*]] = or i32 [[X:%.*]], -42
-; CHECK-NEXT:    [[T1:%.*]] = icmp ne i32 [[T0]], -42
+; CHECK-NEXT:    [[TMP1:%.*]] = and i32 [[X:%.*]], 41
+; CHECK-NEXT:    [[T1:%.*]] = icmp ne i32 [[TMP1]], 0
 ; CHECK-NEXT:    ret i1 [[T1]]
 ;
   %t0 = or i32 %x, -42
@@ -2208,8 +2208,8 @@ define i1 @orC_neC(i32 %x) {
 
 define <2 x i1> @orC_neC_vec(<2 x i8> %x) {
 ; CHECK-LABEL: @orC_neC_vec(
-; CHECK-NEXT:    [[T0:%.*]] = or <2 x i8> [[X:%.*]], <i8 -43, i8 -43>
-; CHECK-NEXT:    [[T1:%.*]] = icmp ne <2 x i8> [[T0]], <i8 -43, i8 -43>
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], <i8 42, i8 42>
+; CHECK-NEXT:    [[T1:%.*]] = icmp ne <2 x i8> [[TMP1]], zeroinitializer
 ; CHECK-NEXT:    ret <2 x i1> [[T1]]
 ;
   %t0 = or <2 x i8> %x, <i8 -43, i8 -43>




More information about the llvm-commits mailing list