[llvm] r290595 - [PM] Teach the AAManager and AAResults layer (the worst offender for

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 27 00:44:40 PST 2016


Author: chandlerc
Date: Tue Dec 27 02:44:39 2016
New Revision: 290595

URL: http://llvm.org/viewvc/llvm-project?rev=290595&view=rev
Log:
[PM] Teach the AAManager and AAResults layer (the worst offender for
inter-analysis dependencies) to use the new invalidation infrastructure.

This teaches it to invalidate itself when any of the peer function
AA results that it uses become invalid. We do this by just tracking the
originating IDs. I've kept it in a somewhat clunky API since some users
of AAResults are outside the new PM right now. We can clean this API up
if/when those users go away.

Secondly, it uses the registration on the outer analysis manager proxy
to trigger deferred invalidation when a module analysis result becomes
invalid.

I've included test cases that specifically try to trigger use-after-free
in both of these cases and they would crash or hang pretty horribly for
me even without ASan. Now they work nicely.

The `InvalidateAnalysis` utility pass required some tweaking to be
useful in this context and it still is pretty garbage. I'd like to
switch it back to the previous implementation and teach the explicit
invalidate method on the AnalysisManager to take care of correctly
triggering indirect invalidation, but I wanted to go ahead and send this
out so folks could see how all of this stuff works together in practice.
And, you know, that it does actually work. =]

Differential Revision: https://reviews.llvm.org/D27205

Modified:
    llvm/trunk/include/llvm/Analysis/AliasAnalysis.h
    llvm/trunk/include/llvm/IR/PassManager.h
    llvm/trunk/lib/Analysis/AliasAnalysis.cpp
    llvm/trunk/test/Other/new-pass-manager.ll

Modified: llvm/trunk/include/llvm/Analysis/AliasAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/AliasAnalysis.h?rev=290595&r1=290594&r2=290595&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/AliasAnalysis.h (original)
+++ llvm/trunk/include/llvm/Analysis/AliasAnalysis.h Tue Dec 27 02:44:39 2016
@@ -197,6 +197,20 @@ public:
     AAs.emplace_back(new Model<AAResultT>(AAResult, *this));
   }
 
+  /// Register a function analysis ID that the results aggregation depends on.
+  ///
+  /// This is used in the new pass manager to implement the invalidation logic
+  /// where we must invalidate the results aggregation if any of our component
+  /// analyses become invalid.
+  void addAADependencyID(AnalysisKey *ID) { AADeps.push_back(ID); }
+
+  /// Handle invalidation events in the new pass manager.
+  ///
+  /// The aggregation is invalidated if any of the underlying analyses is
+  /// invalidated.
+  bool invalidate(Function &F, const PreservedAnalyses &PA,
+                  FunctionAnalysisManager::Invalidator &Inv);
+
   //===--------------------------------------------------------------------===//
   /// \name Alias Queries
   /// @{
@@ -609,6 +623,8 @@ private:
   const TargetLibraryInfo &TLI;
 
   std::vector<std::unique_ptr<Concept>> AAs;
+
+  std::vector<AnalysisKey *> AADeps;
 };
 
 /// Temporary typedef for legacy code that uses a generic \c AliasAnalysis
@@ -922,15 +938,19 @@ private:
                                       FunctionAnalysisManager &AM,
                                       AAResults &AAResults) {
     AAResults.addAAResult(AM.template getResult<AnalysisT>(F));
+    AAResults.addAADependencyID(AnalysisT::ID());
   }
 
   template <typename AnalysisT>
   static void getModuleAAResultImpl(Function &F, FunctionAnalysisManager &AM,
                                     AAResults &AAResults) {
-    auto &MAM =
-        AM.getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
-    if (auto *R = MAM.template getCachedResult<AnalysisT>(*F.getParent()))
+    auto &MAMProxy = AM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
+    auto &MAM = MAMProxy.getManager();
+    if (auto *R = MAM.template getCachedResult<AnalysisT>(*F.getParent())) {
       AAResults.addAAResult(*R);
+      MAMProxy
+          .template registerOuterAnalysisInvalidation<AnalysisT, AAManager>();
+    }
   }
 };
 

Modified: llvm/trunk/include/llvm/IR/PassManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=290595&r1=290594&r2=290595&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PassManager.h (original)
+++ llvm/trunk/include/llvm/IR/PassManager.h Tue Dec 27 02:44:39 2016
@@ -1218,11 +1218,9 @@ struct InvalidateAnalysisPass
   /// context requires.
   template <typename IRUnitT, typename AnalysisManagerT, typename... ExtraArgTs>
   PreservedAnalyses run(IRUnitT &Arg, AnalysisManagerT &AM, ExtraArgTs &&...) {
-    // We have to directly invalidate the analysis result as we can't
-    // enumerate all other analyses and use the preserved set to control it.
-    AM.template invalidate<AnalysisT>(Arg);
-
-    return PreservedAnalyses::all();
+    auto PA = PreservedAnalyses::all();
+    PA.abandon<AnalysisT>();
+    return PA;
   }
 };
 

Modified: llvm/trunk/lib/Analysis/AliasAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/AliasAnalysis.cpp?rev=290595&r1=290594&r2=290595&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/AliasAnalysis.cpp (original)
+++ llvm/trunk/lib/Analysis/AliasAnalysis.cpp Tue Dec 27 02:44:39 2016
@@ -53,7 +53,8 @@ using namespace llvm;
 static cl::opt<bool> DisableBasicAA("disable-basicaa", cl::Hidden,
                                     cl::init(false));
 
-AAResults::AAResults(AAResults &&Arg) : TLI(Arg.TLI), AAs(std::move(Arg.AAs)) {
+AAResults::AAResults(AAResults &&Arg)
+    : TLI(Arg.TLI), AAs(std::move(Arg.AAs)), AADeps(std::move(Arg.AADeps)) {
   for (auto &AA : AAs)
     AA->setAAResults(this);
 }
@@ -69,6 +70,25 @@ AAResults::~AAResults() {
 #endif
 }
 
+bool AAResults::invalidate(Function &F, const PreservedAnalyses &PA,
+                           FunctionAnalysisManager::Invalidator &Inv) {
+  if (PA.areAllPreserved())
+    return false; // Nothing to do, everything is still valid.
+
+  // Check if the AA manager itself has been invalidated.
+  auto PAC = PA.getChecker<AAManager>();
+  if (!PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>())
+    return true; // The manager needs to be blown away, clear everything.
+
+  // Check all of the dependencies registered.
+  for (AnalysisKey *ID : AADeps)
+    if (Inv.invalidate(ID, F, PA))
+      return true;
+
+  // Everything we depend on is still fine, so are we. Nothing to invalidate.
+  return false;
+}
+
 //===----------------------------------------------------------------------===//
 // Default chaining methods
 //===----------------------------------------------------------------------===//

Modified: llvm/trunk/test/Other/new-pass-manager.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/new-pass-manager.ll?rev=290595&r1=290594&r2=290595&view=diff
==============================================================================
--- llvm/trunk/test/Other/new-pass-manager.ll (original)
+++ llvm/trunk/test/Other/new-pass-manager.ll Tue Dec 27 02:44:39 2016
@@ -49,7 +49,7 @@
 ; CHECK-MODULE-PRINT: Running pass: VerifierPass
 ; CHECK-MODULE-PRINT: Running pass: PrintModulePass
 ; CHECK-MODULE-PRINT: ModuleID
-; CHECK-MODULE-PRINT: define void @foo(i1 %x)
+; CHECK-MODULE-PRINT: define void @foo(i1 %x, i8* %p1, i8* %p2)
 ; CHECK-MODULE-PRINT: Running pass: VerifierPass
 ; CHECK-MODULE-PRINT: Finished llvm::Module pass manager run
 
@@ -58,7 +58,7 @@
 ; CHECK-MODULE-VERIFY: Starting llvm::Module pass manager run
 ; CHECK-MODULE-VERIFY: Running pass: PrintModulePass
 ; CHECK-MODULE-VERIFY: ModuleID
-; CHECK-MODULE-VERIFY: define void @foo(i1 %x)
+; CHECK-MODULE-VERIFY: define void @foo(i1 %x, i8* %p1, i8* %p2)
 ; CHECK-MODULE-VERIFY: Running pass: VerifierPass
 ; CHECK-MODULE-VERIFY: Finished llvm::Module pass manager run
 
@@ -71,7 +71,7 @@
 ; CHECK-FUNCTION-PRINT: Starting llvm::Function pass manager run
 ; CHECK-FUNCTION-PRINT: Running pass: PrintFunctionPass
 ; CHECK-FUNCTION-PRINT-NOT: ModuleID
-; CHECK-FUNCTION-PRINT: define void @foo(i1 %x)
+; CHECK-FUNCTION-PRINT: define void @foo(i1 %x, i8* %p1, i8* %p2)
 ; CHECK-FUNCTION-PRINT: Finished llvm::Function pass manager run
 ; CHECK-FUNCTION-PRINT: Running pass: VerifierPass
 ; CHECK-FUNCTION-PRINT: Finished llvm::Module pass manager run
@@ -82,17 +82,19 @@
 ; CHECK-FUNCTION-VERIFY: Starting llvm::Function pass manager run
 ; CHECK-FUNCTION-VERIFY: Running pass: PrintFunctionPass
 ; CHECK-FUNCTION-VERIFY-NOT: ModuleID
-; CHECK-FUNCTION-VERIFY: define void @foo(i1 %x)
+; CHECK-FUNCTION-VERIFY: define void @foo(i1 %x, i8* %p1, i8* %p2)
 ; CHECK-FUNCTION-VERIFY: Running pass: VerifierPass
 ; CHECK-FUNCTION-VERIFY: Finished llvm::Function pass manager run
 ; CHECK-FUNCTION-VERIFY: Finished llvm::Module pass manager run
 
 ; RUN: opt -S -o - -passes='no-op-module,no-op-module' %s \
 ; RUN:     | FileCheck %s --check-prefix=CHECK-NOOP
-; CHECK-NOOP: define void @foo(i1 %x) {
+; CHECK-NOOP: define void @foo(i1 %x, i8* %p1, i8* %p2) {
 ; CHECK-NOOP: entry:
+; CHECK-NOOP:   store i8 42, i8* %p1
 ; CHECK-NOOP:   br i1 %x, label %loop, label %exit
 ; CHECK-NOOP: loop:
+; CHECK-NOOP:   %tmp1 = load i8, i8* %p2
 ; CHECK-NOOP:   br label %loop
 ; CHECK-NOOP: exit:
 ; CHECK-NOOP:   ret void
@@ -323,6 +325,42 @@
 ; CHECK-AA-DEFAULT: Finished llvm::Module pass manager run
 
 ; RUN: opt -disable-output -disable-verify -debug-pass-manager %s 2>&1 \
+; RUN:     -passes='require<aa>,invalidate<basic-aa>,aa-eval' -aa-pipeline='basic-aa' \
+; RUN:     | FileCheck %s --check-prefix=CHECK-AA-FUNCTION-INVALIDATE
+; CHECK-AA-FUNCTION-INVALIDATE: Starting llvm::Function pass manager run
+; CHECK-AA-FUNCTION-INVALIDATE: Running pass: RequireAnalysisPass
+; CHECK-AA-FUNCTION-INVALIDATE: Running analysis: AAManager
+; CHECK-AA-FUNCTION-INVALIDATE: Running analysis: BasicAA
+; CHECK-AA-FUNCTION-INVALIDATE: Running pass: InvalidateAnalysisPass
+; CHECK-AA-FUNCTION-INVALIDATE: Invalidating analysis: BasicAA
+; CHECK-AA-FUNCTION-INVALIDATE: Invalidating analysis: AAManager
+; CHECK-AA-FUNCTION-INVALIDATE: Running pass: AAEvaluator
+; CHECK-AA-FUNCTION-INVALIDATE: Running analysis: AAManager
+; CHECK-AA-FUNCTION-INVALIDATE: Running analysis: BasicAA
+; CHECK-AA-FUNCTION-INVALIDATE: Finished llvm::Function pass manager run
+
+; RUN: opt -disable-output -disable-verify -debug-pass-manager %s 2>&1 \
+; RUN:     -passes='require<globals-aa>,function(require<aa>),invalidate<globals-aa>,require<globals-aa>,function(aa-eval)' -aa-pipeline='globals-aa' \
+; RUN:     | FileCheck %s --check-prefix=CHECK-AA-MODULE-INVALIDATE
+; CHECK-AA-MODULE-INVALIDATE: Starting llvm::Module pass manager run
+; CHECK-AA-MODULE-INVALIDATE: Running pass: RequireAnalysisPass
+; CHECK-AA-MODULE-INVALIDATE: Running analysis: GlobalsAA
+; CHECK-AA-MODULE-INVALIDATE: Starting llvm::Function pass manager run
+; CHECK-AA-MODULE-INVALIDATE: Running pass: RequireAnalysisPass
+; CHECK-AA-MODULE-INVALIDATE: Running analysis: AAManager
+; CHECK-AA-MODULE-INVALIDATE: Finished llvm::Function pass manager run
+; CHECK-AA-MODULE-INVALIDATE: Running pass: InvalidateAnalysisPass
+; CHECK-AA-MODULE-INVALIDATE: Invalidating analysis: AAManager
+; CHECK-AA-MODULE-INVALIDATE: Invalidating analysis: GlobalsAA
+; CHECK-AA-MODULE-INVALIDATE: Running pass: RequireAnalysisPass
+; CHECK-AA-MODULE-INVALIDATE: Running analysis: GlobalsAA
+; CHECK-AA-MODULE-INVALIDATE: Starting llvm::Function pass manager run
+; CHECK-AA-MODULE-INVALIDATE: Running pass: AAEvaluator
+; CHECK-AA-MODULE-INVALIDATE: Running analysis: AAManager
+; CHECK-AA-MODULE-INVALIDATE: Finished llvm::Function pass manager run
+; CHECK-AA-MODULE-INVALIDATE: Finished llvm::Module pass manager run
+
+; RUN: opt -disable-output -disable-verify -debug-pass-manager %s 2>&1 \
 ; RUN:     -passes='require<memdep>' \
 ; RUN:     | FileCheck %s --check-prefix=CHECK-MEMDEP
 ; CHECK-MEMDEP: Starting llvm::Module pass manager run
@@ -526,11 +564,13 @@
 ; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Function pass manager run
 ; CHECK-REPEAT-LOOP-PASS-NEXT: Finished llvm::Module pass manager run
 
-define void @foo(i1 %x) {
+define void @foo(i1 %x, i8* %p1, i8* %p2) {
 entry:
+  store i8 42, i8* %p1
   br i1 %x, label %loop, label %exit
 
 loop:
+  %tmp1 = load i8, i8* %p2
   br label %loop
 
 exit:




More information about the llvm-commits mailing list