@@ -361,30 +361,43 @@ bool llvm::isDereferenceableAndAlignedInLoop(
361
361
AccessSize = MaxPtrDiff;
362
362
AccessSizeSCEV = PtrDiff;
363
363
} else if (auto *MinAdd = dyn_cast<SCEVAddExpr>(AccessStart)) {
364
- if (MinAdd-> getNumOperands () != 2 )
365
- return false ;
364
+ const auto *NewBase = dyn_cast<SCEVUnknown>(SE. getPointerBase (MinAdd));
365
+ const auto *OffsetSCEV = SE. removePointerBase (MinAdd) ;
366
366
367
- const auto *Offset = dyn_cast<SCEVConstant>(MinAdd->getOperand (0 ));
368
- const auto *NewBase = dyn_cast<SCEVUnknown>(MinAdd->getOperand (1 ));
369
- if (!Offset || !NewBase)
367
+ if (!OffsetSCEV || !NewBase)
370
368
return false ;
371
369
372
- // The following code below assumes the offset is unsigned, but GEP
373
- // offsets are treated as signed so we can end up with a signed value
374
- // here too. For example, suppose the initial PHI value is (i8 255),
375
- // the offset will be treated as (i8 -1) and sign-extended to (i64 -1).
376
- if (Offset->getAPInt ().isNegative ())
377
- return false ;
370
+ if (const auto *Offset = dyn_cast<SCEVConstant>(OffsetSCEV)) {
371
+ // The following code below assumes the offset is unsigned, but GEP
372
+ // offsets are treated as signed so we can end up with a signed value
373
+ // here too. For example, suppose the initial PHI value is (i8 255),
374
+ // the offset will be treated as (i8 -1) and sign-extended to (i64 -1).
375
+ if (Offset->getAPInt ().isNegative ())
376
+ return false ;
378
377
379
- // For the moment, restrict ourselves to the case where the offset is a
380
- // multiple of the requested alignment and the base is aligned.
381
- // TODO: generalize if a case found which warrants
382
- if (Offset->getAPInt ().urem (Alignment.value ()) != 0 )
383
- return false ;
378
+ // For the moment, restrict ourselves to the case where the offset is a
379
+ // multiple of the requested alignment and the base is aligned.
380
+ // TODO: generalize if a case found which warrants
381
+ if (Offset->getAPInt ().urem (Alignment.value ()) != 0 )
382
+ return false ;
384
383
385
- AccessSize = MaxPtrDiff + Offset->getAPInt ();
386
- AccessSizeSCEV = SE.getAddExpr (PtrDiff, Offset);
387
- Base = NewBase->getValue ();
384
+ AccessSize = MaxPtrDiff + Offset->getAPInt ();
385
+ AccessSizeSCEV = SE.getAddExpr (PtrDiff, Offset);
386
+ Base = NewBase->getValue ();
387
+ } else {
388
+ // Same checks as above, but for a symbolic offset.
389
+ if (!SE.isKnownNonNegative (OffsetSCEV))
390
+ return false ;
391
+ // Check divisibility by alignment
392
+ auto AlignVal = APInt (64 , Alignment.value ());
393
+ if (!SE.isKnownPredicate (ICmpInst::ICMP_EQ,
394
+ SE.getURemExpr (OffsetSCEV, SE.getConstant (AlignVal)),
395
+ SE.getZero (OffsetSCEV->getType ())))
396
+ return false ;
397
+ AccessSizeSCEV = SE.getAddExpr (PtrDiff, OffsetSCEV);
398
+ AccessSize = MaxPtrDiff + SE.getUnsignedRangeMax (OffsetSCEV);
399
+ Base = NewBase->getValue ();
400
+ }
388
401
} else
389
402
return false ;
390
403
0 commit comments