@@ -3634,7 +3634,9 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
36343634 const SCEV *DstSCEV = SE->getSCEV (DstPtr);
36353635 LLVM_DEBUG (dbgs () << " SrcSCEV = " << *SrcSCEV << " \n " );
36363636 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) {
36383640 // If two pointers have different bases, trying to analyze indexes won't
36393641 // work; we can't compare them to each other. This can happen, for example,
36403642 // if one is produced by an LCSSA PHI node.
@@ -3645,6 +3647,100 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst) {
36453647 return std::make_unique<Dependence>(Src, Dst);
36463648 }
36473649
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+
36483744 // establish loop nesting levels
36493745 establishNestingLevels (Src, Dst);
36503746 LLVM_DEBUG (dbgs () << " common nesting levels = " << CommonLevels << " \n " );
0 commit comments