diff --git a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h --- a/llvm/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/llvm/include/llvm/Analysis/LoopAccessAnalysis.h @@ -785,6 +785,9 @@ const LoopAccessInfo &getInfo(Loop &L); void clear() { LoopAccessInfoMap.clear(); } + + bool invalidate(Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv); }; /// This analysis provides dependence information for the memory accesses diff --git a/llvm/lib/Analysis/LoopAccessAnalysis.cpp b/llvm/lib/Analysis/LoopAccessAnalysis.cpp --- a/llvm/lib/Analysis/LoopAccessAnalysis.cpp +++ b/llvm/lib/Analysis/LoopAccessAnalysis.cpp @@ -2704,6 +2704,28 @@ AU.setPreservesAll(); } +bool LoopAccessInfoManager::invalidate( + Function &F, const PreservedAnalyses &PA, + FunctionAnalysisManager::Invalidator &Inv) { + // Check whether our analysis is preserved. + auto PAC = PA.getChecker(); + if (!PAC.preserved() && !PAC.preservedSet>()) + // If not, give up now. + return true; + + // Check whether the analyses we depend on became invalid for any reason. + // Skip checking TargetLibraryAnalysis as it is immutable and can't become + // invalid. + if (Inv.invalidate(F, PA) || + Inv.invalidate(F, PA) || + Inv.invalidate(F, PA) || + Inv.invalidate(F, PA)) + return true; + + // Otherwise this analysis result remains valid. + return false; +} + LoopAccessInfoManager LoopAccessAnalysis::run(Function &F, FunctionAnalysisManager &AM) { return LoopAccessInfoManager( diff --git a/llvm/test/Analysis/LoopAccessAnalysis/invalidation.ll b/llvm/test/Analysis/LoopAccessAnalysis/invalidation.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/LoopAccessAnalysis/invalidation.ll @@ -0,0 +1,75 @@ +; Test that access-info gets invalidated when the analyses it depends on are +; invalidated. + +; RUN: opt < %s -disable-output -debug-pass-manager -passes='function(require,invalidate),print,function(invalidate)' 2>&1 | FileCheck %s --check-prefix=CHECK-AA +; +; CHECK-AA: Running pass: RequireAnalysisPass +; CHECK-AA-NEXT: Running analysis: LoopAccessAnalysis on foo +; CHECK-AA-DAG: Running analysis: ScalarEvolutionAnalysis on foo +; CHECK-AA-DAG: Running analysis: DominatorTreeAnalysis on foo +; CHECK-AA-DAG: Running analysis: LoopAnalysis on foo +; CHECK-AA-DAG: Running analysis: AAManager on foo +; CHECK-AA: Running pass: InvalidateAnalysisPass +; CHECK-AA-NEXT: Invalidating analysis: AAManager on foo +; CHECK-AA-NEXT: Invalidating analysis: LoopAccessAnalysis on foo +; CHECK-AA-NEXT: Running pass: LoopAccessInfoPrinterPass on foo +; CHECK-AA-NEXT: Running analysis: LoopAccessAnalysis on foo +; CHECK-AA-NEXT: Running analysis: AAManager on foo +; CHECK-AA-NEXT: Loop access info in function +; CHECK-AA: Running pass: InvalidateAnalysisPass on foo +; CHECK-AA-NEXT: Invalidating analysis: LoopAccessAnalysis on foo + + +; RUN: opt < %s -disable-output -debug-pass-manager -passes='function(require,invalidate),print' 2>&1 | FileCheck %s --check-prefix=CHECK-SCEV +; +; CHECK-SCEV: Running pass: RequireAnalysisPass +; CHECK-SCEV: Running analysis: LoopAccessAnalysis on foo +; CHECK-SCEV-DAG: Running analysis: ScalarEvolutionAnalysis on foo +; CHECK-SCEV-DAG: Running analysis: DominatorTreeAnalysis on foo +; CHECK-SCEV-DAG: Running analysis: LoopAnalysis on foo +; CHECK-SCEV-DAG: Running analysis: AAManager on foo +; CHECK-SCEV: Running pass: InvalidateAnalysisPass +; CHECK-SCEV-NEXT: Invalidating analysis: ScalarEvolutionAnalysis on foo +; CHECK-SCEV-NEXT: Invalidating analysis: LoopAccessAnalysis on foo +; CHECK-SCEV-NEXT: Running pass: LoopAccessInfoPrinterPass on foo +; CHECK-SCEV-NEXT: Running analysis: LoopAccessAnalysis on foo +; CHECK-SCEV-NEXT: Running analysis: ScalarEvolutionAnalysis on foo +; CHECK-SCEV-NEXT: Loop access info in function + +; RUN: opt < %s -disable-output -debug-pass-manager -passes='function(require,invalidate),print' 2>&1 | FileCheck %s --check-prefix=CHECK-DT +; +; CHECK-DT: Running pass: RequireAnalysisPass +; CHECK-DT: Running analysis: LoopAccessAnalysis on foo +; CHECK-DT-DAG: Running analysis: ScalarEvolutionAnalysis on foo +; CHECK-DT-DAG: Running analysis: DominatorTreeAnalysis on foo +; CHECK-DT-DAG: Running analysis: LoopAnalysis on foo +; CHECK-DT-DAG: Running analysis: AAManager on foo +; CHECK-DT: Running pass: InvalidateAnalysisPass +; CHECK-DT-NEXT: Invalidating analysis: DominatorTreeAnalysis on foo +; CHECK-DT-DAG: Invalidating analysis: ScalarEvolutionAnalysis on foo +; CHECK-DT-DAG: Invalidating analysis: BasicAA on foo +; CHECK-DT-DAG: Invalidating analysis: AAManager on foo +; CHECK-DT-DAG: Invalidating analysis: LoopAccessAnalysis on foo +; CHECK-DT-NEXT: Running pass: LoopAccessInfoPrinterPass on foo +; CHECK-DT-NEXT: Running analysis: LoopAccessAnalysis on foo +; CHECK-DT-DAG: Running analysis: ScalarEvolutionAnalysis on foo +; CHECK-DT-DAG: Running analysis: DominatorTreeAnalysis on foo +; CHECK-DT-DAG: Running analysis: AAManager on foo +; CHECK-DT-DAG: Running analysis: BasicAA on foo +; CHECK-DT-NEXT: Loop access info in function + + +define void @foo(ptr nocapture writeonly %a, ptr nocapture writeonly %b) #0 { +entry: + br label %for.cond1 + +for.cond1: + store i16 0, ptr %b, align 1 + store i16 0, ptr %a, align 1 + br i1 true, label %for.end6, label %for.cond1 + +for.end6: + ret void +} + +attributes #0 = { nofree norecurse nosync nounwind memory(argmem: write) }