@@ -3569,6 +3569,11 @@ bool DependenceInfo::invalidate(Function &F, const PreservedAnalyses &PA,
35693569 Inv.invalidate <LoopAnalysis>(F, PA);
35703570}
35713571
3572+ // Check that memory access offsets in V are multiples of array element size
3573+ // EltSize. Param records the first parametric expression. If the scalar
3574+ // evolution V contains two or more parameters, we check that the subsequent
3575+ // parametric expressions are multiples of the first parametric expression
3576+ // Param.
35723577static bool checkOffsets (ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
35733578 uint64_t EltSize) {
35743579 if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(V)) {
@@ -3578,9 +3583,20 @@ static bool checkOffsets(ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
35783583 }
35793584 if (auto *Cst = dyn_cast<SCEVConstant>(V)) {
35803585 APInt C = Cst->getAPInt ();
3586+
3587+ // For example, alias_with_different_offsets in
3588+ // test/Analysis/DependenceAnalysis/DifferentOffsets.ll accesses "%A + 2":
3589+ // %arrayidx = getelementptr inbounds i8, ptr %A, i64 2
3590+ // store i32 42, ptr %arrayidx, align 1
3591+ // which is writing an i32, i.e., EltSize = 4 bytes, with an offset C = 2.
3592+ // checkOffsets returns false, as the offset C=2 is not a multiple of 4.
35813593 return C.srem (EltSize) == 0 ;
35823594 }
35833595
3596+ // Use a lambda helper function to check V for parametric expressions.
3597+ // Param records the first parametric expression. If the scalar evolution V
3598+ // contains two or more parameters, we check that the subsequent parametric
3599+ // expressions are multiples of the first parametric expression Param.
35843600 auto checkParamsMultipleOfSize = [&](const SCEV *V,
35853601 const SCEV *&Param) -> bool {
35863602 if (EltSize == 1 )
@@ -3600,6 +3616,12 @@ static bool checkOffsets(ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
36003616 return true ;
36013617 auto Rem = Val.srem (APInt (Val.getBitWidth (), EltSize, /* isSigned=*/ true ));
36023618 if (Rem.isZero ())
3619+ // For example in test/Analysis/DependenceAnalysis/Preliminary.ll
3620+ // SrcSCEV = ((4 * (sext i8 %n to i64))<nsw> + %A)
3621+ // DstSCEV = (4 + (4 * (sext i8 %n to i64))<nsw> + %A)
3622+ // Param = (4 * (sext i8 %n to i64))<nsw>
3623+ // V = 4 + (4 * (sext i8 %n to i64))<nsw>
3624+ // Diff = -4, Rem = 0, and so all offsets are multiple of 4.
36033625 return true ;
36043626 LLVM_DEBUG (dbgs () << " SCEV with different offsets: " << *Param << " - "
36053627 << *V << " = " << *Diff << " % " << EltSize << " = "
@@ -3614,6 +3636,10 @@ static bool checkOffsets(ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
36143636 const SCEV *Remainder = SE->getURemExpr (Diff, Val);
36153637 if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Remainder))
36163638 if (C->getValue ()->isZero ())
3639+ // For example test/Analysis/DependenceAnalysis/DADelin.ll
3640+ // SrcSCEV = {{{%A,+,(4 * %m * %o)}<%for.cond1.preheader>,+,(4 * %o)}
3641+ // DstSCEV = {{{%A,+,(4 * %m * %o)}<%for.cond1.preheader>,+,(4 * %o)}
3642+ // The strides '(4 * %m * %o)' and '(4 * %o)' are multiple of 4.
36173643 return true ;
36183644
36193645 // Check by using the division computation.
@@ -3625,17 +3651,32 @@ static bool checkOffsets(ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
36253651 << *Param << " - " << *V << " = " << *Diff << " \n "
36263652 << " Remainder = " << *Remainder << " \n "
36273653 << " Q = " << *Q << " Product = " << *Product << " \n " );
3654+ // For example in test/Analysis/DependenceAnalysis/MIVCheckConst.ll
3655+ // SrcSCEV = {(80640 + (4 * (1 + %n) * %v1) + %A),+,(8 * %v1)}<%bb13>
3656+ // DstSCEV = {(126720 + (128 * %m) + %A),+,256}<%bb13>
3657+ // We fail to prove that the offsets 80640 + (4 * (1 + %n) * %v1) and
3658+ // (8 * %v1) are multiples of 128.
3659+ // Param = 80640 + (4 * (1 + %n) * %v1)
3660+ // (80640 + (4 * (1 + %n) * %v1)) - (8 * %v1) =
3661+ // (80640 + ((-4 + (4 * %n)) * %v1))
3662+ // Remainder = (zext i7 ((trunc i32 %v1 to i7) *
3663+ // (-4 + (4 * (trunc i32 %n to i7)))) to i32)
3664+ // Q = ((80640 + ((-4 + (4 * %n)) * %v1)) /u 128)
3665+ // Product = (128 * ((80640 + ((-4 + (4 * %n)) * %v1)) /u 128))<nuw>
36283666 return false ;
36293667 };
3668+
36303669 // Expressions like "n".
36313670 if (isa<SCEVUnknown>(V))
36323671 return checkParamsMultipleOfSize (V, Param);
3672+
36333673 // Expressions like "n + 1".
36343674 if (isa<SCEVAddExpr>(V))
36353675 return !SCEVExprContains (V, [](const SCEV *S) {
36363676 return isa<SCEVUnknown>(S);
36373677 }) || checkParamsMultipleOfSize (V, Param);
36383678
3679+ // Expressions like "n * 2".
36393680 if (isa<SCEVMulExpr>(V))
36403681 return !SCEVExprContains (V, [](const SCEV *S) {
36413682 return isa<SCEVUnknown>(S);
0 commit comments