[llvm] [InstCombine] Fold (bw-1) - ctlz(x&-x) to cttz (PR #205383)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 23 10:01:24 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: AZero13 (AZero13)

<details>
<summary>Changes</summary>

Works for non-powers of 2.

Alive2: https://alive2.llvm.org/ce/z/-cbxFz

---
Full diff: https://github.com/llvm/llvm-project/pull/205383.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp (+8-4) 
- (modified) llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll (+28) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 78be7c6ea2900..af10ac712886a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1504,17 +1504,21 @@ static Instruction *foldSelectCtlzToCttz(ICmpInst *ICI, Value *TrueVal,
                                          Value *FalseVal,
                                          InstCombiner::BuilderTy &Builder) {
   unsigned BitWidth = TrueVal->getType()->getScalarSizeInBits();
-  if (!isPowerOf2_32(BitWidth) || !ICI->isEquality() ||
-      !match(ICI->getOperand(1), m_Zero()))
+  if (!ICI->isEquality() || !match(ICI->getOperand(1), m_Zero()))
     return nullptr;
 
   if (ICI->getPredicate() == ICmpInst::ICMP_NE)
     std::swap(TrueVal, FalseVal);
 
   Value *Ctlz;
-  if (!match(FalseVal,
-             m_Xor(m_Value(Ctlz), m_SpecificInt(BitWidth - 1))))
+  if (match(FalseVal,
+            m_Xor(m_Value(Ctlz), m_SpecificIntAllowPoison(BitWidth - 1)))) {
+    if (!isPowerOf2_32(BitWidth))
+      return nullptr;
+  } else if (!match(FalseVal, m_Sub(m_SpecificIntAllowPoison(BitWidth - 1),
+                                    m_Value(Ctlz)))) {
     return nullptr;
+  }
 
   if (!match(Ctlz, m_Ctlz(m_Value(), m_Value())))
     return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll b/llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll
index d1f25b19d35a0..9b85008bbcac6 100644
--- a/llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll
+++ b/llvm/test/Transforms/InstCombine/select-ctlz-to-cttz.ll
@@ -340,3 +340,31 @@ define i4 @PR45762_logical(i3 %x4) {
   %sel_71 = select i1 %t12, i4 %one_hot_16, i4 %umul_23
   ret i4 %sel_71
 }
+
+define i32 @select_clz_to_ctz_sub_constant_for_zero(i32 %a) {
+; CHECK-LABEL: @select_clz_to_ctz_sub_constant_for_zero(
+; CHECK-NEXT:    [[COND:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[A:%.*]], i1 false)
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+  %sub = sub i32 0, %a
+  %and = and i32 %a, %sub
+  %lz = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %and, i1 false)
+  %tobool = icmp eq i32 %a, 0
+  %sub1 = sub nsw i32 31, %lz
+  %cond = select i1 %tobool, i32 32, i32 %sub1
+  ret i32 %cond
+}
+
+define i33 @select_clz_to_ctz_sub_constant_for_zero_33(i33 %a) {
+; CHECK-LABEL: @select_clz_to_ctz_sub_constant_for_zero_33(
+; CHECK-NEXT:    [[COND:%.*]] = call range(i33 0, 34) i33 @llvm.cttz.i33(i33 [[A:%.*]], i1 false)
+; CHECK-NEXT:    ret i33 [[COND]]
+;
+  %sub = sub i33 0, %a
+  %and = and i33 %a, %sub
+  %lz = tail call range(i33 0, 34) i33 @llvm.ctlz.i33(i33 %and, i1 false)
+  %tobool = icmp eq i33 %a, 0
+  %sub1 = sub nsw i33 32, %lz
+  %cond = select i1 %tobool, i33 33, i33 %sub1
+  ret i33 %cond
+}

``````````

</details>


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


More information about the llvm-commits mailing list