Index: include/llvm/Analysis/LoopAccessAnalysis.h =================================================================== --- include/llvm/Analysis/LoopAccessAnalysis.h +++ include/llvm/Analysis/LoopAccessAnalysis.h @@ -29,6 +29,7 @@ class Value; class DataLayout; +class DependenceInfo; class ScalarEvolution; class Loop; class SCEV; @@ -193,8 +194,9 @@ const SmallVectorImpl &Instrs) const; }; - MemoryDepChecker(PredicatedScalarEvolution &PSE, const Loop *L) - : PSE(PSE), InnermostLoop(L), AccessIdx(0), + MemoryDepChecker(PredicatedScalarEvolution &PSE, DependenceInfo *DI, + const Loop *L) + : PSE(PSE), DI(DI), InnermostLoop(L), AccessIdx(0), ShouldRetryWithRuntimeCheck(false), SafeForVectorization(true), RecordDependences(true) {} @@ -272,6 +274,7 @@ /// example we might assume a unit stride for a pointer in order to prove /// that a memory access is strided and doesn't wrap. PredicatedScalarEvolution &PSE; + DependenceInfo *DI; const Loop *InnermostLoop; /// \brief Maps access locations (ptr, read/write) to program order. @@ -511,7 +514,8 @@ /// PSE must be emitted in order for the results of this analysis to be valid. class LoopAccessInfo { public: - LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL, + LoopAccessInfo(Loop *L, ScalarEvolution *SE, DependenceInfo *DI, + const DataLayout &DL, const TargetLibraryInfo *TLI, AliasAnalysis *AA, DominatorTree *DT, LoopInfo *LI); @@ -770,6 +774,7 @@ AliasAnalysis *AA; DominatorTree *DT; LoopInfo *LI; + DependenceInfo *DI; }; /// \brief LoopAccessInfoAnalysis Index: lib/Analysis/LoopAccessAnalysis.cpp =================================================================== --- lib/Analysis/LoopAccessAnalysis.cpp +++ lib/Analysis/LoopAccessAnalysis.cpp @@ -12,6 +12,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Analysis/DependenceAnalysis.h" #include "llvm/Analysis/LoopAccessAnalysis.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPassManager.h" @@ -89,6 +90,10 @@ cl::desc("Enable conflict detection in loop-access analysis"), cl::init(true)); +static cl::opt + UseDA("use-da-for-loop-accesses", cl::Hidden, cl::init(false), + cl::desc("Use da in loop-accesses")); + bool VectorizerParams::isInterleaveForced() { return ::VectorizationInterleave.getNumOccurrences() > 0; } @@ -1212,7 +1217,38 @@ std::swap(StrideAPtr, StrideBPtr); } - const SCEV *Dist = PSE.getSE()->getMinusSCEV(Sink, Src); + const SCEV *Dist = nullptr; + if (UseDA) { + DEBUG(dbgs() << "LAA: DA checking " << *InstMap[AIdx] << + " vs. " << *InstMap[BIdx] << "\n"); + auto Dep = DI->depends(InstMap[AIdx], InstMap[BIdx], false); + if (!Dep) { + DEBUG(dbgs() << "LAA: DA returned no dependence!\n"); + return Dependence::NoDep; + } + + DEBUG(dbgs() << "LAA: DA returned dependence: "; Dep->dump(dbgs()); + dbgs() << "\n"); + if (Dep->getLevels() > 0) { + Dist = Dep->getDistance(Dep->getLevels()); + if (Dist) { + Type *ATy = APtr->getType()->getPointerElementType(); + Dist = PSE.getSE()->getMulExpr(Dist, + PSE.getSE()->getSizeOfExpr(Dist->getType(), ATy)); + + DEBUG(dbgs() << "LAA: DA distance after sizeof adjustment: " << + *Dist << "\n"); + + // The code below assumes that we've computed a distance as + // (Sink - Src), but DependenceAnalysis returns a distance as + // (Src - Sink). + Dist = PSE.getSE()->getNegativeSCEV(Dist); + } + } + } + + if (!Dist) + Dist = PSE.getSE()->getMinusSCEV(Sink, Src); DEBUG(dbgs() << "LAA: Src Scev: " << *Src << "Sink Scev: " << *Sink << "(Induction step: " << StrideAPtr << ")\n"); @@ -1919,12 +1955,13 @@ } LoopAccessInfo::LoopAccessInfo(Loop *L, ScalarEvolution *SE, + DependenceInfo *DI, const DataLayout &DL, const TargetLibraryInfo *TLI, AliasAnalysis *AA, DominatorTree *DT, LoopInfo *LI) : PSE(llvm::make_unique(*SE, *L)), PtrRtChecking(llvm::make_unique(SE)), - DepChecker(llvm::make_unique(*PSE, L)), TheLoop(L), + DepChecker(llvm::make_unique(*PSE, DI, L)), TheLoop(L), DL(&DL), TLI(TLI), AA(AA), DT(DT), LI(LI), NumLoads(0), NumStores(0), MaxSafeDepDistBytes(-1U), CanVecMem(false), StoreToLoopInvariantAddress(false) { @@ -1977,7 +2014,7 @@ if (!LAI) { const DataLayout &DL = L->getHeader()->getModule()->getDataLayout(); - LAI = llvm::make_unique(L, SE, DL, TLI, AA, DT, LI); + LAI = llvm::make_unique(L, SE, DI, DL, TLI, AA, DT, LI); } return *LAI.get(); } @@ -2000,6 +2037,8 @@ AA = &getAnalysis().getAAResults(); DT = &getAnalysis().getDomTree(); LI = &getAnalysis().getLoopInfo(); + if (UseDA) + DI = &getAnalysis().getDI(); return false; } @@ -2009,6 +2048,8 @@ AU.addRequired(); AU.addRequired(); AU.addRequired(); + if (UseDA) + AU.addRequired(); AU.setPreservesAll(); } @@ -2019,6 +2060,7 @@ INITIALIZE_PASS_BEGIN(LoopAccessAnalysis, LAA_NAME, laa_name, false, true) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) +INITIALIZE_PASS_DEPENDENCY(DependenceAnalysisWrapperPass) INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) @@ -2037,7 +2079,8 @@ auto *DT = &FAM.getResult(F); auto *LI = &FAM.getResult(F); const DataLayout &DL = F.getParent()->getDataLayout(); - return LoopAccessInfo(&L, SE, DL, TLI, AA, DT, LI); + auto *DI = UseDA ? &FAM.getResult(F) : nullptr; + return LoopAccessInfo(&L, SE, DI, DL, TLI, AA, DT, LI); } PreservedAnalyses LoopAccessInfoPrinterPass::run(Loop &L, Index: test/Analysis/LoopAccessAnalysis/use-da.ll =================================================================== --- /dev/null +++ test/Analysis/LoopAccessAnalysis/use-da.ll @@ -0,0 +1,48 @@ +; RUN: opt -loop-accesses -analyze -use-da-for-loop-accesses < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; void test(int * restrict a, int * restrict b, long n) { +; for (long i = 0; i < n; ++i) { +; a[i + n] = i; +; b[i] = a[i + 2*n]; +; } +; } + +; Function Attrs: norecurse nounwind uwtable +define void @test(i32* noalias nocapture %a, i32* noalias nocapture %b, i64 %n) #0 { +entry: + %cmp11 = icmp sgt i64 %n, 0 + br i1 %cmp11, label %for.body.lr.ph, label %for.cond.cleanup + +; CHECK-LABEL: for function 'test' +; CHECK-NOT: Memory dependences are safe with run-time checks +; CHECK: Memory dependences are safe +; CHECK: Dependences: +; CHECK-NEXT: Run-time memory checks: + +for.body.lr.ph: ; preds = %entry + %mul = shl i64 %n, 1 + br label %for.body + +for.cond.cleanup: ; preds = %for.body, %entry + ret void + +for.body: ; preds = %for.body, %for.body.lr.ph + %i.014 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.body ] + %conv = trunc i64 %i.014 to i32 + %add = add nsw i64 %i.014, %n + %arrayidx = getelementptr inbounds i32, i32* %a, i64 %add + store i32 %conv, i32* %arrayidx, align 4 + %add1 = add nsw i64 %i.014, %mul + %arrayidx2 = getelementptr inbounds i32, i32* %a, i64 %add1 + %0 = load i32, i32* %arrayidx2, align 4 + %arrayidx3 = getelementptr inbounds i32, i32* %b, i64 %i.014 + store i32 %0, i32* %arrayidx3, align 4 + %inc = add nuw nsw i64 %i.014, 1 + %exitcond = icmp eq i64 %inc, %n + br i1 %exitcond, label %for.cond.cleanup, label %for.body +} + +attributes #0 = { norecurse nounwind uwtable "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" } +