@@ -3634,7 +3634,9 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
3634
3634
const SCEV *DstSCEV = SE->getSCEV (DstPtr);
3635
3635
LLVM_DEBUG (dbgs () << " SrcSCEV = " << *SrcSCEV << " \n " );
3636
3636
LLVM_DEBUG (dbgs () << " DstSCEV = " << *DstSCEV << " \n " );
3637
- if (SE->getPointerBase (SrcSCEV) != SE->getPointerBase (DstSCEV)) {
3637
+ const SCEV *SrcBase = SE->getPointerBase (SrcSCEV);
3638
+ const SCEV *DstBase = SE->getPointerBase (DstSCEV);
3639
+ if (SrcBase != DstBase) {
3638
3640
// If two pointers have different bases, trying to analyze indexes won't
3639
3641
// work; we can't compare them to each other. This can happen, for example,
3640
3642
// if one is produced by an LCSSA PHI node.
@@ -3645,6 +3647,100 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
3645
3647
return std::make_unique<Dependence>(Src, Dst);
3646
3648
}
3647
3649
3650
+ auto EltSize = SrcLoc.Size .toRaw ();
3651
+ assert (EltSize == DstLoc.Size .toRaw () && " Array element size differ" );
3652
+
3653
+ // Check that memory access offsets in V are multiples of array EltSize.
3654
+ std::function<bool (const SCEV *, const SCEV *&)> checkOffsets =
3655
+ [&](const SCEV *V, const SCEV *&Param) -> bool {
3656
+ if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(V)) {
3657
+ if (!checkOffsets (AddRec->getStart (), Param))
3658
+ return false ;
3659
+ return checkOffsets (AddRec->getStepRecurrence (*SE), Param);
3660
+ }
3661
+ if (auto *Cst = dyn_cast<SCEVConstant>(V)) {
3662
+ APInt C = Cst->getAPInt ();
3663
+ return C.srem (EltSize) == 0 ;
3664
+ }
3665
+
3666
+ auto checkParamsMultipleOfSize = [&](const SCEV *V,
3667
+ const SCEV *&Param) -> bool {
3668
+ if (EltSize == 1 )
3669
+ return true ;
3670
+ if (!Param) {
3671
+ Param = V;
3672
+ return true ;
3673
+ }
3674
+ if (Param == V)
3675
+ return true ;
3676
+
3677
+ // Check whether "(Param - V) % Size == 0".
3678
+ const SCEV *Diff = SE->getMinusSCEV (Param, V);
3679
+ if (const SCEVConstant *Cst = dyn_cast<SCEVConstant>(Diff)) {
3680
+ APInt Val = Cst->getAPInt ();
3681
+ if (Val.isZero ())
3682
+ return true ;
3683
+ auto Rem =
3684
+ Val.srem (APInt (Val.getBitWidth (), EltSize, /* isSigned=*/ true ));
3685
+ if (Rem.isZero ())
3686
+ return true ;
3687
+ LLVM_DEBUG (dbgs () << " SCEV with different offsets: " << *Param << " - "
3688
+ << *V << " = " << *Diff << " % " << EltSize << " = "
3689
+ << Rem << " != 0\n " );
3690
+ return false ;
3691
+ }
3692
+ // Check if the symbolic difference is a multiple of Size.
3693
+ const SCEV *Val = SE->getConstant (
3694
+ APInt (Diff->getType ()->getScalarSizeInBits (), EltSize));
3695
+
3696
+ // Check by using the remainder computation.
3697
+ const SCEV *Remainder = SE->getURemExpr (Diff, Val);
3698
+ if (const SCEVConstant *C = dyn_cast<SCEVConstant>(Remainder))
3699
+ if (C->getValue ()->isZero ())
3700
+ return true ;
3701
+
3702
+ // Check by using the division computation.
3703
+ const SCEV *Q = SE->getUDivExpr (Diff, Val);
3704
+ const SCEV *Product = SE->getMulExpr (Q, Val);
3705
+ if (Diff == Product)
3706
+ return true ;
3707
+ LLVM_DEBUG (dbgs () << " SCEV with different offsets:\n "
3708
+ << *Param << " - " << *V << " = " << *Diff << " \n "
3709
+ << " Remainder = " << *Remainder << " \n "
3710
+ << " Q = " << *Q << " Product = " << *Product << " \n " );
3711
+ return false ;
3712
+ };
3713
+ // Expressions like "n".
3714
+ if (isa<SCEVUnknown>(V))
3715
+ return checkParamsMultipleOfSize (V, Param);
3716
+ // Expressions like "n + 1".
3717
+ if (isa<SCEVAddExpr>(V))
3718
+ return !SCEVExprContains (V, [](const SCEV *S) {
3719
+ return isa<SCEVUnknown>(S);
3720
+ }) || checkParamsMultipleOfSize (V, Param);
3721
+
3722
+ if (isa<SCEVMulExpr>(V))
3723
+ return !SCEVExprContains (V, [](const SCEV *S) {
3724
+ return isa<SCEVUnknown>(S);
3725
+ }) || checkParamsMultipleOfSize (V, Param);
3726
+
3727
+ LLVM_DEBUG (dbgs () << " SCEV node not handled yet: " << *V << " \n " );
3728
+ return false ;
3729
+ };
3730
+
3731
+ // Check that memory access offsets are multiples of element sizes.
3732
+ const SCEV *SrcEv = SE->getMinusSCEV (SrcSCEV, SrcBase);
3733
+ const SCEV *DstEv = SE->getMinusSCEV (DstSCEV, DstBase);
3734
+ const SCEV *Param = nullptr ;
3735
+
3736
+ if (Src != Dst) {
3737
+ // Check that memory access offsets are multiples of element sizes.
3738
+ if (!checkOffsets (SrcEv, Param) || !checkOffsets (DstEv, Param)) {
3739
+ LLVM_DEBUG (dbgs () << " can't analyze SCEV with different offsets\n " );
3740
+ return std::make_unique<Dependence>(Src, Dst);
3741
+ }
3742
+ }
3743
+
3648
3744
// establish loop nesting levels
3649
3745
establishNestingLevels (Src, Dst);
3650
3746
LLVM_DEBUG (dbgs () << " common nesting levels = " << CommonLevels << " \n " );
0 commit comments