[llvm] [LoopIdiom] Add a range attribute to formed memset/memcpy/memmove (PR #226801)
Nathan Corbyn via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 28 05:34:06 PDT 2026
================
@@ -1089,6 +1089,41 @@ static const SCEV *getNumBytes(const SCEV *BECount, Type *IntPtr,
SCEV::FlagNUW);
}
+/// Add a range to newly formed memset/memmove/memcpy intrinsic with an upper
+/// bound derived from the loop's constant max trip count.
+static void addRangeAttrFromTripCount(CallInst *NewCall, unsigned ArgNo,
+ uint64_t ElemsPerIter,
+ const SCEV *BECount, Loop *L,
+ ScalarEvolution *SE) {
+ Value *Len = NewCall->getArgOperand(ArgNo);
+ if (isa<Constant>(Len)) return;
+
+ // Two upper bounds:
+ // (1) constant max backedge-taken count
+ const APInt *Max1;
+ if (!match(SE->getConstantMaxBackedgeTakenCount(L), m_scev_APInt(Max1)))
+ return;
+
+ // (2) loop guards (new call is in preheader, so guards dominate the call)
+ APInt Max2 = SE->getUnsignedRangeMax(SE->applyLoopGuards(BECount, L));
+
+ // Use the tighter bound
+ unsigned MaxWidth = std::max(Max1->getBitWidth(), Max2.getBitWidth());
+ APInt MaxBTC = APIntOps::umin(Max1->zext(MaxWidth), Max2.zext(MaxWidth));
+
+ // Bail if bound beyond bitwidth, overflows, or is MaxValue
+ unsigned BW = Len->getType()->getIntegerBitWidth();
+ if (MaxBTC.getActiveBits() >= BW) return;
+ APInt MaxTripCount = MaxBTC.zext(BW) + 1;
----------------
cofibrant wrote:
I don't understand this. I don't think there's any guarantee at this point that `MaxBTC.getBitWidth() <= BW` so why do we care if we overflow `BW`? To make sure `MaxBTC` is expressible with `BW` bits? If so, `MaxBTC.getActiveBits() >= BW` seems like the wrong way to assert this: I understand this guarantees the add won't overflow, but `MaxBTC` could still have a very large bitwidth with only a few high bits active, leaving the value still outside of the range expressible by `BW`.
https://github.com/llvm/llvm-project/pull/226801
More information about the llvm-commits
mailing list