@@ -188,12 +188,31 @@ RuntimeCheckingPtrGroup::RuntimeCheckingPtrGroup(
188188 Members.push_back (Index);
189189}
190190
191+ // / Returns \p A + \p B, if it is guaranteed not to unsigned wrap. Otherwise
192+ // / return nullptr.
193+ static const SCEV *addSCEVOverflow (const SCEV *A, const SCEV *B,
194+ ScalarEvolution &SE) {
195+ if (!SE.willNotOverflow (Instruction::Add, false , A, B))
196+ return nullptr ;
197+ return SE.getAddExpr (A, B);
198+ }
199+
200+ // / Returns \p A * \p B, if it is guaranteed not to unsigned wrap. Otherwise
201+ // / return nullptr.
202+ static const SCEV *mulSCEVOverflow (const SCEV *A, const SCEV *B,
203+ ScalarEvolution &SE) {
204+ if (!SE.willNotOverflow (Instruction::Mul, false , A, B))
205+ return nullptr ;
206+ return SE.getMulExpr (A, B);
207+ }
208+
191209// / Return true, if evaluating \p AR at \p MaxBTC cannot wrap, because \p AR at
192210// / \p MaxBTC is guaranteed inbounds of the accessed object.
193- static bool evaluateAddRecAtMaxBTCWillNotWrap (const SCEVAddRecExpr *AR,
194- const SCEV *MaxBTC,
195- ScalarEvolution &SE,
196- const DataLayout &DL) {
211+ static bool evaluatePtrAddRecAtMaxBTCWillNotWrap (const SCEVAddRecExpr *AR,
212+ const SCEV *MaxBTC,
213+ const SCEV *EltSize,
214+ ScalarEvolution &SE,
215+ const DataLayout &DL) {
197216 auto *PointerBase = SE.getPointerBase (AR->getStart ());
198217 auto *StartPtr = dyn_cast<SCEVUnknown>(PointerBase);
199218 if (!StartPtr)
@@ -208,29 +227,45 @@ static bool evaluateAddRecAtMaxBTCWillNotWrap(const SCEVAddRecExpr *AR,
208227 const SCEV *Step = AR->getStepRecurrence (SE);
209228 Type *WiderTy = SE.getWiderType (MaxBTC->getType (), Step->getType ());
210229 Step = SE.getNoopOrSignExtend (Step, WiderTy);
211- MaxBTC = SE.getNoopOrSignExtend (MaxBTC, WiderTy);
230+ MaxBTC = SE.getNoopOrZeroExtend (MaxBTC, WiderTy);
231+
232+ // For the computations below, make sure they don't unsigned wrap.
233+ if (!SE.isKnownPredicate (CmpInst::ICMP_UGE, AR->getStart (), StartPtr))
234+ return false ;
235+ const SCEV *StartOffset = SE.getNoopOrSignExtend (
236+ SE.getMinusSCEV (AR->getStart (), StartPtr), WiderTy);
237+
238+ const SCEV *OffsetAtLastIter =
239+ mulSCEVOverflow (MaxBTC, SE.getAbsExpr (Step, false ), SE);
240+ if (!OffsetAtLastIter)
241+ return false ;
242+
243+ const SCEV *OffsetLastAccessedByte = addSCEVOverflow (
244+ OffsetAtLastIter, SE.getNoopOrZeroExtend (EltSize, WiderTy), SE);
245+ if (!OffsetLastAccessedByte)
246+ return false ;
247+
212248 if (SE.isKnownPositive (Step)) {
213- // For positive steps, check if (AR->getStart() - StartPtr) + MaxBTC <=
214- // DerefBytes / Step
215- const SCEV *StartOffset = SE.getNoopOrSignExtend (
216- SE.getMinusSCEV (AR->getStart (), StartPtr), WiderTy);
217- return SE.isKnownPredicate (
218- CmpInst::ICMP_ULE, SE.getAddExpr (StartOffset, MaxBTC),
219- SE.getUDivExpr (SE.getConstant (WiderTy, DerefBytes), Step));
249+ // For positive steps, check if
250+ // (AR->getStart() - StartPtr) + (MaxBTC * Step) + EltSize <= DerefBytes,
251+ // while making sure none of the computations unsigned wrap themselves.
252+ const SCEV *LastAccessedByte =
253+ addSCEVOverflow (StartOffset, OffsetLastAccessedByte, SE);
254+ if (!LastAccessedByte)
255+ return false ;
256+ return SE.isKnownPredicate (CmpInst::ICMP_ULE, LastAccessedByte,
257+ SE.getConstant (WiderTy, DerefBytes));
220258 }
259+
221260 if (SE.isKnownNegative (Step)) {
222- // For negative steps, check using StartOffset == AR->getStart() - StartPtr:
223- // * StartOffset >= MaxBTC * Step
224- // * AND StartOffset <= DerefBytes / Step
225- auto *StartOffset = SE.getNoopOrSignExtend (
226- SE.getMinusSCEV (AR->getStart (), StartPtr), WiderTy);
227- return SE.isKnownPredicate (
228- CmpInst::ICMP_UGE, StartOffset,
229- SE.getMulExpr (MaxBTC, SE.getNegativeSCEV (Step))) &&
230- SE.isKnownPredicate (
231- CmpInst::ICMP_ULE, StartOffset,
232- SE.getUDivExpr (SE.getConstant (WiderTy, DerefBytes),
233- SE.getNegativeSCEV (Step)));
261+ // For negative steps check if
262+ // * StartOffset >= (MaxBTC * Step + EltSize)
263+ // * StartOffset <= DerefBytes.
264+ return SE
265+ .isKnownPredicate (CmpInst::ICMP_SGE, StartOffset,
266+ OffsetLastAccessedByte)
267+ SE.isKnownPredicate (CmpInst::ICMP_ULE, StartOffset,
268+ SE.getConstant (WiderTy, DerefBytes));
234269 }
235270 return false ;
236271}
@@ -271,14 +306,18 @@ std::pair<const SCEV *, const SCEV *> llvm::getStartAndEndForAccess(
271306 // than the start of the AddRec due to wrapping (for example consider
272307 // MaxBTC = -2). If that's the case, set ScEnd to -(EltSize + 1). ScEnd
273308 // will get incremented by EltSize before returning, so this effectively
274- // sets ScEnd to unsigned max. Note that LAA separately checks that
275- // accesses cannot not wrap, so unsigned max represents an upper bound.
276- ScEnd = SE->getAddExpr (
277- SE->getNegativeSCEV (EltSizeSCEV),
278- SE->getSCEV (ConstantExpr::getIntToPtr (
279- ConstantInt::get (EltSizeSCEV->getType (), -1 ), AR->getType ())));
280- if (evaluateAddRecAtMaxBTCWillNotWrap (AR, MaxBTC, *SE, DL))
309+ // sets ScEnd to the maximum unsigned value for the type. Note that LAA
310+ // separately checks that accesses cannot not wrap, so unsigned max
311+ // represents an upper bound.
312+ if (evaluatePtrAddRecAtMaxBTCWillNotWrap (AR, MaxBTC, EltSizeSCEV, *SE,
313+ DL)) {
281314 ScEnd = AR->evaluateAtIteration (MaxBTC, *SE);
315+ } else {
316+ ScEnd = SE->getAddExpr (
317+ SE->getNegativeSCEV (EltSizeSCEV),
318+ SE->getSCEV (ConstantExpr::getIntToPtr (
319+ ConstantInt::get (EltSizeSCEV->getType (), -1 ), AR->getType ())));
320+ }
282321 }
283322 const SCEV *Step = AR->getStepRecurrence (*SE);
284323
0 commit comments