[llvm] [InstCombine] Fold Minimum over Trailing/Leading Bits Counts (PR #90402)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Wed May 1 04:47:08 PDT 2024


================
@@ -1428,6 +1428,40 @@ static Instruction *foldBitOrderCrossLogicOp(Value *V,
   return nullptr;
 }
 
+/// Fold an unsigned minimum of trailing or leading zero bits counts:
+///   umin(cttz(CtOp, ZeroUndef), ConstOp) --> cttz(CtOp | (1 << ConstOp))
+///   umin(ctlz(CtOp, ZeroUndef), ConstOp) --> ctlz(CtOp | ((1 << (bitwidth-1))
+///                                              >> ConstOp))
+template <Intrinsic::ID IntrID>
+static Instruction *foldMinimumOverTrailingOrLeadingZeroCount(
+    Instruction *OrigInst, Value *CtOp, Value *ZeroUndef, Constant *ConstOp,
+    const DataLayout &DL, InstCombiner::BuilderTy &Builder) {
+  static_assert(IntrID == Intrinsic::cttz || IntrID == Intrinsic::ctlz,
+                "This helper only supports cttz and ctlz intrinsics");
+
+  auto BitWidth = ConstOp->getType()->getScalarSizeInBits();
+  auto *Ty = ConstOp->getType();
+
+  Constant *NewConst = ConstantFoldSelectInstruction(
+      ConstantFoldCompareInstOperands(CmpInst::ICMP_ULT, ConstOp,
+                                      ConstantInt::get(Ty, BitWidth), DL),
+      ConstantFoldBinaryOpOperands(
+          IntrID == Intrinsic::cttz ? Instruction::Shl : Instruction::LShr,
+          IntrID == Intrinsic::cttz
+              ? ConstantInt::get(Ty, 1)
+              : ConstantInt::get(Ty, APInt::getSignedMinValue(BitWidth)),
+          ConstOp, DL),
+      Constant::getNullValue(Ty));
+
+  Value *NewCtOp =
+      NewConst->isZeroValue() ? CtOp : Builder.CreateOr(CtOp, NewConst);
+
+  return CallInst::Create(Intrinsic::getDeclaration(OrigInst->getModule(),
----------------
RKSimon wrote:

Its fine for this fold to only work for cases with all elements less than bitwidth.

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


More information about the llvm-commits mailing list