[llvm] [LoopIdiom] Add a range attribute to formed memset/memcpy/memmove (PR #226801)
Kuba Mracek via llvm-commits
llvm-commits at lists.llvm.org
Sun Oct 11 01:17:23 PDT 2026
================
@@ -1092,6 +1092,51 @@ 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));
+
+ // The length is in [0, (MaxBTC + 1) * ElemsPerIter]. Bail if that doesn't
+ // fit in the length's type.
+ unsigned BW = Len->getType()->getIntegerBitWidth();
+ if (MaxBTC.getActiveBits() > BW)
+ return;
+ bool Overflow;
+ APInt MaxTripCount = MaxBTC.zextOrTrunc(BW).uadd_ov(APInt(BW, 1), Overflow);
+ if (Overflow)
+ return;
+ APInt MaxLen = MaxTripCount.umul_ov(APInt(BW, ElemsPerIter), Overflow);
+ if (Overflow)
+ return;
+ // ConstantRange's upper end is exclusive, so the range ends at MaxLen + 1.
+ APInt RangeEnd = MaxLen.uadd_ov(APInt(BW, 1), Overflow);
+ if (Overflow)
+ return;
----------------
kubamracek wrote:
TIL!
https://github.com/llvm/llvm-project/pull/226801
More information about the llvm-commits
mailing list