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

via llvm-commits llvm-commits at lists.llvm.org
Sat Jun 22 02:14:55 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))
+static Value *
+foldMinimumOverTrailingOrLeadingZeroCount(Intrinsic::ID IntrID, Value *I0,
+                                          Value *I1, const DataLayout &DL,
+                                          InstCombiner::BuilderTy &Builder) {
+  assert((IntrID == Intrinsic::cttz || IntrID == Intrinsic::ctlz) &&
+         "This helper only supports cttz and ctlz intrinsics");
+
+  if (I0->hasOneUse()) {
+    if (auto *II0 = dyn_cast<IntrinsicInst>(I0);
+        II0 && II0->getIntrinsicID() == IntrID) {
+      Value *X = II0->getArgOperand(0);
+      Value *Z = II0->getArgOperand(1);
+
+      auto BitWidth = I1->getType()->getScalarSizeInBits();
+      auto *Ty = I1->getType();
+
+      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);
+        return Builder.CreateBinaryIntrinsic(IntrID,
+                                             Builder.CreateOr(X, NewConst), Z);
+      }
+      if (match(I1, m_CheckedInt(std::not_fn(LessBitWidth)))) {
+        return I0;
+      }
----------------
mskamp wrote:

Yes but apparently only for scalars. In contrast, the transformation here also handles splat and non-splat constant vectors. At least that's the result of some quick tests I did; and after a quick glance at the code, I think that `ValueLattice::markConstant` only handles `ConstantInt` and therefore we get a „full“ constant range in CVP for vector constants.

If this case (all elements >= BitWidth) shouldn't be handled in `InstCombine`, I can of course remove this case here and only handle the case that all vector elements are < BitWidth. Should I do this?

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


More information about the llvm-commits mailing list