[llvm] 142f744 - [InstCombine] Canonicalize `(X^(X-1)) u{ge, lt} X` as pow2 test

Noah Goldstein via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 21 12:15:21 PDT 2023


Author: Noah Goldstein
Date: 2023-07-21T14:15:06-05:00
New Revision: 142f7448e770f25b774b058a7eab1f107c4daad9

URL: https://github.com/llvm/llvm-project/commit/142f7448e770f25b774b058a7eab1f107c4daad9
DIFF: https://github.com/llvm/llvm-project/commit/142f7448e770f25b774b058a7eab1f107c4daad9.diff

LOG: [InstCombine] Canonicalize `(X^(X-1)) u{ge,lt} X` as pow2 test

https://alive2.llvm.org/ce/z/T8osF6

Differential Revision: https://reviews.llvm.org/D152673

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index dbb33e89359fa4..e43c10cb533c7c 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4979,6 +4979,7 @@ static Instruction *foldICmpPow2Test(ICmpInst &I,
   Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
   const CmpInst::Predicate Pred = I.getPredicate();
   Value *A = nullptr;
+  bool CheckIs;
   if (I.isEquality()) {
     // (A & (A-1)) == 0 --> ctpop(A) < 2 (two commuted variants)
     // ((A-1) & A) != 0 --> ctpop(A) > 1 (two commuted variants)
@@ -4994,14 +4995,28 @@ static Instruction *foldICmpPow2Test(ICmpInst &I,
     else if (match(Op1,
                    m_OneUse(m_c_And(m_Neg(m_Specific(Op0)), m_Specific(Op0)))))
       A = Op0;
+
+    CheckIs = Pred == ICmpInst::ICMP_EQ;
+  } else if (Pred == ICmpInst::ICMP_UGE || Pred == ICmpInst::ICMP_ULT) {
+    // (A ^ (A-1)) u>= A --> ctpop(A) < 2 (two commuted variants)
+    // ((A-1) ^ A) u< A --> ctpop(A) > 1 (two commuted variants)
+    if (match(Op0, m_OneUse(m_c_Xor(m_Add(m_Specific(Op1), m_AllOnes()),
+                                    m_Specific(Op1)))))
+      A = Op1;
+    else if (match(Op1, m_OneUse(m_c_Xor(m_Add(m_Specific(Op0), m_AllOnes()),
+                                         m_Specific(Op0)))))
+      A = Op0;
+
+    CheckIs = Pred == ICmpInst::ICMP_UGE;
   }
+
   if (A) {
     Type *Ty = A->getType();
     CallInst *CtPop = Builder.CreateUnaryIntrinsic(Intrinsic::ctpop, A);
-    return Pred == ICmpInst::ICMP_EQ ? new ICmpInst(ICmpInst::ICMP_ULT, CtPop,
-                                                    ConstantInt::get(Ty, 2))
-                                     : new ICmpInst(ICmpInst::ICMP_UGT, CtPop,
-                                                    ConstantInt::get(Ty, 1));
+    return CheckIs ? new ICmpInst(ICmpInst::ICMP_ULT, CtPop,
+                                  ConstantInt::get(Ty, 2))
+                   : new ICmpInst(ICmpInst::ICMP_UGT, CtPop,
+                                  ConstantInt::get(Ty, 1));
   }
 
   return nullptr;

diff  --git a/llvm/test/Transforms/InstCombine/ispow2.ll b/llvm/test/Transforms/InstCombine/ispow2.ll
index 81f5610b23bb4e..e7d2a5714b6e59 100644
--- a/llvm/test/Transforms/InstCombine/ispow2.ll
+++ b/llvm/test/Transforms/InstCombine/ispow2.ll
@@ -1157,9 +1157,8 @@ define i1 @is_pow2_fail_pr63327(i32 %x) {
 define i1 @blsmsk_is_p2_or_z(i32 %xx, i32 %yy) {
 ; CHECK-LABEL: @blsmsk_is_p2_or_z(
 ; CHECK-NEXT:    [[X:%.*]] = or i32 [[XX:%.*]], [[YY:%.*]]
-; CHECK-NEXT:    [[XM1:%.*]] = add i32 [[X]], -1
-; CHECK-NEXT:    [[Y:%.*]] = xor i32 [[X]], [[XM1]]
-; CHECK-NEXT:    [[R:%.*]] = icmp uge i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG0]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ult i32 [[TMP1]], 2
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %x = or i32 %xx, %yy
@@ -1171,9 +1170,8 @@ define i1 @blsmsk_is_p2_or_z(i32 %xx, i32 %yy) {
 
 define i1 @blsmsk_isnt_p2_or_z(i32 %x) {
 ; CHECK-LABEL: @blsmsk_isnt_p2_or_z(
-; CHECK-NEXT:    [[XM1:%.*]] = add i32 [[X:%.*]], -1
-; CHECK-NEXT:    [[Y:%.*]] = xor i32 [[XM1]], [[X]]
-; CHECK-NEXT:    [[R:%.*]] = icmp ult i32 [[Y]], [[X]]
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]]
+; CHECK-NEXT:    [[R:%.*]] = icmp ugt i32 [[TMP1]], 1
 ; CHECK-NEXT:    ret i1 [[R]]
 ;
   %xm1 = add i32 %x, -1


        


More information about the llvm-commits mailing list