[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