[llvm] [AggressiveInstCombine] Fold split-width i32 cttz/ctlz patterns into wide i64 intrinsics (PR #192296)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 15 11:40:45 PDT 2026


================
@@ -68,6 +76,439 @@ static cl::opt<unsigned>
                           cl::desc("The maximum length of a constant string to "
                                    "inline a memchr call."));
 
+/// Try to fold a phi that merges two 32-bit cttz operations into a single
+/// 64-bit cttz. This pattern arises when a 64-bit cttz is implemented as
+/// two 32-bit cttz operations with a branch on whether the low half is zero:
+///
+/// GuardBB:
+///   %lo = trunc i64 %val to i32
+///   %cmp = icmp eq i32 %lo, 0
+///   br i1 %cmp, label %HiBB, label %LoBB
+///
+/// HiBB:
+///   %shr = lshr i64 %val, 32
+///   %hi = trunc i64 %shr to i32
+///   %cttz_hi = call i32 @llvm.cttz.i32(i32 %hi, i1 false)
+///   %val_is_zero = icmp eq i64 %val, 0
+///   %cttz_hi_plus32 = or i32 %cttz_hi, 32
+///   %hi_result = select i1 %val_is_zero, i32 ZeroResult, i32 %cttz_hi_plus32
+///   br label %PhiBB
+///
+/// LoBB:
+///   %cttz_lo = call i32 @llvm.cttz.i32(i32 %lo, i1 true)
+///   br label %PhiBB
+///
+/// PhiBB:
+///   %result = phi i32 [%hi_result, %HiBB], [%cttz_lo, %LoBB]
+/// -->
+///   %cttz64 = call i64 @llvm.cttz.i64(i64 %val, i1 true)
+///   %trunc = trunc i64 %cttz64 to i32
+///   %val_is_zero = icmp eq i64 %val, 0
+///   %result = select i1 %val_is_zero, i32 ZeroResult, i32 %trunc
+///
+/// Alive proof:  https://alive2.llvm.org/ce/z/FHgJpq
+static bool foldSplitWidthCTTZ(Instruction &I, const DominatorTree &DT) {
+  if (I.getOpcode() != Instruction::PHI || I.getNumOperands() != 2)
+    return false;
+
+  if (!I.getType()->isIntegerTy(32))
----------------
topperc wrote:

Can we write this in a type independent way?

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


More information about the llvm-commits mailing list