@@ -188,12 +188,31 @@ RuntimeCheckingPtrGroup::RuntimeCheckingPtrGroup(
188
188
Members.push_back (Index);
189
189
}
190
190
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
+
191
209
// / Return true, if evaluating \p AR at \p MaxBTC cannot wrap, because \p AR at
192
210
// / \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) {
197
216
auto *PointerBase = SE.getPointerBase (AR->getStart ());
198
217
auto *StartPtr = dyn_cast<SCEVUnknown>(PointerBase);
199
218
if (!StartPtr)
@@ -208,29 +227,45 @@ static bool evaluateAddRecAtMaxBTCWillNotWrap(const SCEVAddRecExpr *AR,
208
227
const SCEV *Step = AR->getStepRecurrence (SE);
209
228
Type *WiderTy = SE.getWiderType (MaxBTC->getType (), Step->getType ());
210
229
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
+
212
248
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));
220
258
}
259
+
221
260
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));
234
269
}
235
270
return false ;
236
271
}
@@ -271,14 +306,18 @@ std::pair<const SCEV *, const SCEV *> llvm::getStartAndEndForAccess(
271
306
// than the start of the AddRec due to wrapping (for example consider
272
307
// MaxBTC = -2). If that's the case, set ScEnd to -(EltSize + 1). ScEnd
273
308
// 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)) {
281
314
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
+ }
282
321
}
283
322
const SCEV *Step = AR->getStepRecurrence (*SE);
284
323
0 commit comments