[llvm] [LAA] Fix off-by-EltSize in negative-step deref bounds check (PR #211964)

Aleksandr Popov via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 2 05:53:19 PDT 2026


================
@@ -264,15 +274,15 @@ static bool evaluatePtrAddRecAtMaxBTCWillNotWrap(
   Step = SE.getNoopOrSignExtend(Step, WiderTy);
   MaxBTC = SE.getNoopOrZeroExtend(MaxBTC, WiderTy);
 
-  // For the computations below, make sure they don't unsigned wrap.
-  // FIXME: for a negative step the lowest accessed address is not
-  // AR->getStart() but AR->evaluateAtIteration(MaxBTC, SE); the check below
-  // therefore compares StartPtr against the highest accessed address instead
-  // of the lowest.
-  if (!SE.isKnownPredicate(CmpInst::ICMP_UGE, AR->getStart(), StartPtr))
+  const SCEV *LowestAddr = IsKnownNonNegative
+                               ? static_cast<const SCEV *>(AR->getStart())
+                               : AR->evaluateAtIteration(MaxBTC, SE);
+  // Lower-bound safety check: the lowest accessed address must not fall below
+  // StartPtr.
+  if (!SE.isKnownPredicate(CmpInst::ICMP_UGE, LowestAddr, StartPtr))
----------------
aleks-tmb wrote:

Good point, thanks. 
I've added a test case `reverse_inner_start_is_outer_addrec` where the inner AddRec's start is an outer-loop AddRec. getPointerBase() does strip it, but `LowestOffset` keeps the outer AddRec, so it stays correct. 
The lower-bound check can't be discharged for such a start anyway, so we bail out and keep `Low: null` - which is the right answer there.

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


More information about the llvm-commits mailing list