[llvm] Missing opt with ctlz and shifts of power of 2 constants (#41333) (PR #74175)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sun Dec 3 21:41:13 PST 2023


================
@@ -549,6 +551,37 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
 
     if (match(Op0, m_Intrinsic<Intrinsic::abs>(m_Value(X))))
       return IC.replaceOperand(II, 0, X);
+
+    // cttz(shl(%const, %val), 1) --> add(cttz(%const, 1), %val)
+    if (match(Op0, m_Shl(m_Constant(C), m_Value(X))) && match(Op1, m_One())) {
+      Value *ConstCttz =
+          IC.Builder.CreateBinaryIntrinsic(Intrinsic::cttz, C, Op1);
+      return BinaryOperator::CreateAdd(ConstCttz, X);
+    }
+
+    // cttz(lshr exact (%const, %val), 0) --> sub(cttz(%const, 0), %val)
+    if (match(Op0, m_Exact(m_LShr(m_Constant(C), m_Value(X))))) {
+      Value *ConstCttz =
+          IC.Builder.CreateBinaryIntrinsic(Intrinsic::cttz, C, Op1);
+      return BinaryOperator::CreateSub(ConstCttz, X);
+    }
+  } else {
+    // ctlz(lshr(%const, %val), 1) --> add(ctlz(%const, 1), %val)
+    if (match(Op0, m_LShr(m_Constant(C), m_Value(X))) && match(Op1, m_One())) {
+      Value *ConstCtlz =
+          IC.Builder.CreateBinaryIntrinsic(Intrinsic::ctlz, C, Op1);
+      return BinaryOperator::CreateAdd(ConstCtlz, X);
+    }
+
+    // ctlz(shl nuw (%const, %val), 0)     |
+    // ctlz(shl nsw (%const, %val), 0)     |--> sub(ctlz(%const, 0), %val)
+    // ctlz(shl nuw nsw (%const, %val), 0) |
+    if (match(Op0, m_NUWShl(m_Constant(C), m_Value(X))) ||
+        match(Op0, m_NSWShl(m_Constant(C), m_Value(X)))) {
----------------
dtcxzyw wrote:

The transform `ctlz(shl nuw (%const, %val), 0) --> sub(ctlz(%const, 0), %val)` is incorrect when `%const` is a zero.
Alive2: https://alive2.llvm.org/ce/z/xSYGSx

The transform `ctlz(shl nsw (%const, %val), 0) --> sub(ctlz(%const, 0), %val)` is also incorrect.
Alive2: https://alive2.llvm.org/ce/z/U7AJZY


https://github.com/llvm/llvm-project/pull/74175


More information about the llvm-commits mailing list