@@ -3569,6 +3569,11 @@ bool DependenceInfo::invalidate(Function &F, const PreservedAnalyses &PA,
3569
3569
Inv.invalidate <LoopAnalysis>(F, PA);
3570
3570
}
3571
3571
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.
3572
3577
static bool checkOffsets (ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
3573
3578
uint64_t EltSize) {
3574
3579
if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(V)) {
@@ -3578,9 +3583,20 @@ static bool checkOffsets(ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
3578
3583
}
3579
3584
if (auto *Cst = dyn_cast<SCEVConstant>(V)) {
3580
3585
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.
3581
3593
return C.srem (EltSize) == 0 ;
3582
3594
}
3583
3595
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.
3584
3600
auto checkParamsMultipleOfSize = [&](const SCEV *V,
3585
3601
const SCEV *&Param) -> bool {
3586
3602
if (EltSize == 1 )
@@ -3600,6 +3616,12 @@ static bool checkOffsets(ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
3600
3616
return true ;
3601
3617
auto Rem = Val.srem (APInt (Val.getBitWidth (), EltSize, /* isSigned=*/ true ));
3602
3618
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.
3603
3625
return true ;
3604
3626
LLVM_DEBUG (dbgs () << " SCEV with different offsets: " << *Param << " - "
3605
3627
<< *V << " = " << *Diff << " % " << EltSize << " = "
@@ -3614,6 +3636,10 @@ static bool checkOffsets(ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
3614
3636
const SCEV *Remainder = SE->getURemExpr (Diff, Val);
3615
3637
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Remainder))
3616
3638
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.
3617
3643
return true ;
3618
3644
3619
3645
// Check by using the division computation.
@@ -3625,17 +3651,32 @@ static bool checkOffsets(ScalarEvolution *SE, const SCEV *V, const SCEV *&Param,
3625
3651
<< *Param << " - " << *V << " = " << *Diff << " \n "
3626
3652
<< " Remainder = " << *Remainder << " \n "
3627
3653
<< " 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>
3628
3666
return false ;
3629
3667
};
3668
+
3630
3669
// Expressions like "n".
3631
3670
if (isa<SCEVUnknown>(V))
3632
3671
return checkParamsMultipleOfSize (V, Param);
3672
+
3633
3673
// Expressions like "n + 1".
3634
3674
if (isa<SCEVAddExpr>(V))
3635
3675
return !SCEVExprContains (V, [](const SCEV *S) {
3636
3676
return isa<SCEVUnknown>(S);
3637
3677
}) || checkParamsMultipleOfSize (V, Param);
3638
3678
3679
+ // Expressions like "n * 2".
3639
3680
if (isa<SCEVMulExpr>(V))
3640
3681
return !SCEVExprContains (V, [](const SCEV *S) {
3641
3682
return isa<SCEVUnknown>(S);
0 commit comments