[PATCH] D126617: [InstCombine] Optimize shift+lshr+and conversion pattern to simple comparison.

chenglin.bi via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun May 29 09:46:51 PDT 2022


bcl5980 created this revision.
bcl5980 added reviewers: spatel, RKSimon, lebedev.ri, craig.topper, nikic.
Herald added subscribers: StephenFan, hiraditya.
Herald added a project: All.
bcl5980 requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

iff C,C1 <https://reviews.llvm.org/C1> is pow2 and Log2(C1 <https://reviews.llvm.org/C1>) < Log2(C)+C2 < BitWidth:

  ((C1 << X) >> C2) & C -> X == (Log2(C)+C2-Log2(C1)) ? C : 0; https://alive2.llvm.org/ce/z/nCVQHa

iff C,C1 <https://reviews.llvm.org/C1> is pow2 and Log2(C)+C2 < Log2(C1 <https://reviews.llvm.org/C1>):

  ((C1 >> X) >> C2) & C -> X == (Log2(C1)-Log2(C)-C2) ? C : 0; https://alive2.llvm.org/ce/z/bAm-Lw

Fix issue https://github.com/llvm/llvm-project/issues/55739


https://reviews.llvm.org/D126617

Files:
  llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
  llvm/test/Transforms/InstCombine/and.ll


Index: llvm/test/Transforms/InstCombine/and.ll
===================================================================
--- llvm/test/Transforms/InstCombine/and.ll
+++ llvm/test/Transforms/InstCombine/and.ll
@@ -1624,9 +1624,8 @@
 
 define i16 @shl_lshr_pow2_const(i16 %x) {
 ; CHECK-LABEL: @shl_lshr_pow2_const(
-; CHECK-NEXT:    [[SHL:%.*]] = shl i16 4, [[X:%.*]]
-; CHECK-NEXT:    [[LSHR:%.*]] = lshr i16 [[SHL]], 6
-; CHECK-NEXT:    [[R:%.*]] = and i16 [[LSHR]], 8
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i16 [[X:%.*]], 7
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i16 8, i16 0
 ; CHECK-NEXT:    ret i16 [[R]]
 ;
   %shl = shl i16 4, %x
@@ -1699,9 +1698,8 @@
 
 define i16 @lshr_lshr_pow2_const(i16 %x) {
 ; CHECK-LABEL: @lshr_lshr_pow2_const(
-; CHECK-NEXT:    [[LSHR1:%.*]] = lshr i16 2048, [[X:%.*]]
-; CHECK-NEXT:    [[LSHR2:%.*]] = lshr i16 [[LSHR1]], 6
-; CHECK-NEXT:    [[R:%.*]] = and i16 [[LSHR2]], 4
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp eq i16 [[X:%.*]], 3
+; CHECK-NEXT:    [[R:%.*]] = select i1 [[TMP1]], i16 4, i16 0
 ; CHECK-NEXT:    ret i16 [[R]]
 ;
   %lshr1 = lshr i16 2048, %x
Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
===================================================================
--- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1885,6 +1885,42 @@
         return new ZExtInst(And, Ty);
       }
     }
+
+    const APInt *C1;
+    const APInt *C2;
+    Value *X;
+    if (C->isPowerOf2()) {
+      if (match(Op0, m_OneUse(m_LShr(m_Shl(m_APInt(C1), m_Value(X)),
+                                     m_APInt(C2)))) &&
+          C1->isPowerOf2()) {
+        unsigned Log2C1 = C1->countTrailingZeros();
+        unsigned Log2C = C->countTrailingZeros();
+        unsigned LShrEqBits = Log2C + C2->getZExtValue();
+        if (LShrEqBits >= Log2C1 && LShrEqBits < Width) {
+          // iff C,C1 is pow2 and Log2(C1) < Log2(C)+C2 < BitWidth:
+          // ((C1 << X) >> C2) & C -> X == (Log2(C)+C2-Log2(C1)) ? C : 0
+          unsigned CmpC = LShrEqBits - Log2C1;
+          Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, CmpC));
+          return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C),
+                                    ConstantInt::getNullValue(Ty));
+        }
+      }
+      if (match(Op0, m_OneUse(m_LShr(m_LShr(m_APInt(C1), m_Value(X)),
+                                     m_APInt(C2)))) &&
+          C1->isPowerOf2()) {
+        unsigned Log2C1 = C1->countTrailingZeros();
+        unsigned Log2C = C->countTrailingZeros();
+        unsigned LShrEqBits = Log2C + C2->getZExtValue();
+        if (LShrEqBits < Log2C1) {
+          // iff C,C1 is pow2 and Log2(C)+C2 < Log2(C1):
+          // ((C1 >> X) >> C2) & C -> X == (Log2(C1)-Log2(C)-C2) ? C : 0
+          unsigned CmpC = Log2C1 - LShrEqBits;
+          Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, CmpC));
+          return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C),
+                                    ConstantInt::getNullValue(Ty));
+        }
+      }
+    }
   }
 
   if (match(&I, m_And(m_OneUse(m_Shl(m_ZExt(m_Value(X)), m_Value(Y))),


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D126617.432793.patch
Type: text/x-patch
Size: 3182 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220529/083652f6/attachment.bin>


More information about the llvm-commits mailing list