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

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 21 07:13:27 PDT 2024


================
@@ -1428,6 +1428,46 @@ 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 *I0,
+                                          Value *I1, const DataLayout &DL,
+                                          InstCombiner::BuilderTy &Builder) {
+  static_assert(IntrID == Intrinsic::cttz || IntrID == Intrinsic::ctlz,
+                "This helper only supports cttz and ctlz intrinsics");
+
+  Value *X;
+  Value *Z;
+  if (match(I0, m_OneUse(m_Intrinsic<IntrID>(m_Value(X), m_Value(Z))))) {
+    auto BitWidth = I1->getType()->getScalarSizeInBits();
+    auto *Ty = I1->getType();
+
+    Value *NewCtOp = X;
+    auto LessBitWidth = [BitWidth](auto &C) { return C.ult(BitWidth); };
+    if (match(I1, m_CheckedInt(LessBitWidth))) {
+      Constant *NewConst = ConstantFoldBinaryOpOperands(
+          IntrID == Intrinsic::cttz ? Instruction::Shl : Instruction::LShr,
+          IntrID == Intrinsic::cttz
+              ? ConstantInt::get(Ty, 1)
+              : ConstantInt::get(Ty, APInt::getSignedMinValue(BitWidth)),
+          cast<Constant>(I1), DL);
+      NewCtOp = Builder.CreateOr(X, NewConst);
+    } else if (!match(I1, m_CheckedInt(std::not_fn(LessBitWidth)))) {
+      return nullptr; // Non-splat vector with elements < and >= BitWidth
+    }
+
+    return CallInst::Create(Intrinsic::getDeclaration(OrigInst->getModule(),
+                                                      IntrID,
+                                                      OrigInst->getType()),
+                            {NewCtOp, Z});
----------------
mskamp wrote:

Done. That makes it necessary to call `replaceInstUsesWith` on the result, right?

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


More information about the llvm-commits mailing list