[llvm] r261594 - [PM] Improve the API and comments around the analysis manager proxies.

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 22 16:05:00 PST 2016


Author: chandlerc
Date: Mon Feb 22 18:05:00 2016
New Revision: 261594

URL: http://llvm.org/viewvc/llvm-project?rev=261594&view=rev
Log:
[PM] Improve the API and comments around the analysis manager proxies.

These are really handles that ensure the analyses get cleared at
appropriate places, and as such copying doesn't really make sense.
Instead, they should look more like unique ownership objects. Make that
the case.

Relatedly, if you create a temporary of one and move out of it
its destructor shouldn't actually clear anything. I don't think there is
any code that can trigger this currently, but it seems like a more
robust implementation.

If folks want, I can add a unittest that forces this to be exercised,
but that seems somewhat pointless -- whether a temporary is ever created
in the innards of AnalysisManager is not really something we should be
adding a reliance on, but I didn't want to leave a timebomb in the code
here.

If anyone has a cleaner way to represent this, I'm all ears, but
I wanted to assure myself that this wasn't in fact responsible for
another bug I'm chasing down (it wasn't) and figured I'd commit that.

Modified:
    llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h
    llvm/trunk/include/llvm/IR/PassManager.h
    llvm/trunk/lib/Analysis/CGSCCPassManager.cpp
    llvm/trunk/lib/IR/PassManager.cpp

Modified: llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h?rev=261594&r1=261593&r2=261594&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h (original)
+++ llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h Mon Feb 22 18:05:00 2016
@@ -49,17 +49,26 @@ typedef AnalysisManager<LazyCallGraph::S
 /// never use a CGSCC analysis manager from within (transitively) a module
 /// pass manager unless your parent module pass has received a proxy result
 /// object for it.
+///
+/// Note that the proxy's result is a move-only object and represents ownership
+/// of the validity of the analyses in the \c CGSCCAnalysisManager it provides.
 class CGSCCAnalysisManagerModuleProxy {
 public:
   class Result {
   public:
     explicit Result(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {}
-    // We have to explicitly define all the special member functions because
-    // MSVC refuses to generate them.
-    Result(const Result &Arg) : CGAM(Arg.CGAM) {}
-    Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {}
-    Result &operator=(Result RHS) {
-      std::swap(CGAM, RHS.CGAM);
+    Result(Result &&Arg) : CGAM(std::move(Arg.CGAM)) {
+      // We have to null out the analysis manager in the moved-from state
+      // because we are taking ownership of its responsibilty to clear the
+      // analysis state.
+      Arg.CGAM = nullptr;
+    }
+    Result &operator=(Result &&RHS) {
+      CGAM = RHS.CGAM;
+      // We have to null out the analysis manager in the moved-from state
+      // because we are taking ownership of its responsibilty to clear the
+      // analysis state.
+      RHS.CGAM = nullptr;
       return *this;
     }
     ~Result();
@@ -275,17 +284,27 @@ createModuleToPostOrderCGSCCPassAdaptor(
 /// never use a function analysis manager from within (transitively) a CGSCC
 /// pass manager unless your parent CGSCC pass has received a proxy result
 /// object for it.
+///
+/// Note that the proxy's result is a move-only object and represents ownership
+/// of the validity of the analyses in the \c FunctionAnalysisManager it
+/// provides.
 class FunctionAnalysisManagerCGSCCProxy {
 public:
   class Result {
   public:
     explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
-    // We have to explicitly define all the special member functions because
-    // MSVC refuses to generate them.
-    Result(const Result &Arg) : FAM(Arg.FAM) {}
-    Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {}
-    Result &operator=(Result RHS) {
-      std::swap(FAM, RHS.FAM);
+    Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {
+      // We have to null out the analysis manager in the moved-from state
+      // because we are taking ownership of the responsibilty to clear the
+      // analysis state.
+      Arg.FAM = nullptr;
+    }
+    Result &operator=(Result &&RHS) {
+      FAM = RHS.FAM;
+      // We have to null out the analysis manager in the moved-from state
+      // because we are taking ownership of the responsibilty to clear the
+      // analysis state.
+      RHS.FAM = nullptr;
       return *this;
     }
     ~Result();

Modified: llvm/trunk/include/llvm/IR/PassManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/PassManager.h?rev=261594&r1=261593&r2=261594&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/PassManager.h (original)
+++ llvm/trunk/include/llvm/IR/PassManager.h Mon Feb 22 18:05:00 2016
@@ -618,6 +618,10 @@ typedef AnalysisManager<Function> Functi
 /// never use a function analysis manager from within (transitively) a module
 /// pass manager unless your parent module pass has received a proxy result
 /// object for it.
+///
+/// Note that the proxy's result is a move-only object and represents ownership
+/// of the validity of the analyses in the \c FunctionAnalysisManager it
+/// provides.
 class FunctionAnalysisManagerModuleProxy {
 public:
   class Result;
@@ -665,12 +669,18 @@ private:
 class FunctionAnalysisManagerModuleProxy::Result {
 public:
   explicit Result(FunctionAnalysisManager &FAM) : FAM(&FAM) {}
-  // We have to explicitly define all the special member functions because MSVC
-  // refuses to generate them.
-  Result(const Result &Arg) : FAM(Arg.FAM) {}
-  Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {}
-  Result &operator=(Result RHS) {
-    std::swap(FAM, RHS.FAM);
+  Result(Result &&Arg) : FAM(std::move(Arg.FAM)) {
+    // We have to null out the analysis manager in the moved-from state
+    // because we are taking ownership of the responsibilty to clear the
+    // analysis state.
+    Arg.FAM = nullptr;
+  }
+  Result &operator=(Result &&RHS) {
+    FAM = RHS.FAM;
+    // We have to null out the analysis manager in the moved-from state
+    // because we are taking ownership of the responsibilty to clear the
+    // analysis state.
+    RHS.FAM = nullptr;
     return *this;
   }
   ~Result();

Modified: llvm/trunk/lib/Analysis/CGSCCPassManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/CGSCCPassManager.cpp?rev=261594&r1=261593&r2=261594&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/CGSCCPassManager.cpp (original)
+++ llvm/trunk/lib/Analysis/CGSCCPassManager.cpp Mon Feb 22 18:05:00 2016
@@ -22,6 +22,10 @@ CGSCCAnalysisManagerModuleProxy::run(Mod
 }
 
 CGSCCAnalysisManagerModuleProxy::Result::~Result() {
+  // CGAM is cleared in a moved from state where there is nothing to do.
+  if (!CGAM)
+    return;
+
   // Clear out the analysis manager if we're being destroyed -- it means we
   // didn't even see an invalidate call when we got invalidated.
   CGAM->clear();
@@ -51,6 +55,10 @@ FunctionAnalysisManagerCGSCCProxy::run(L
 }
 
 FunctionAnalysisManagerCGSCCProxy::Result::~Result() {
+  // FAM is cleared in a moved from state where there is nothing to do.
+  if (!FAM)
+    return;
+
   // Clear out the analysis manager if we're being destroyed -- it means we
   // didn't even see an invalidate call when we got invalidated.
   FAM->clear();

Modified: llvm/trunk/lib/IR/PassManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/PassManager.cpp?rev=261594&r1=261593&r2=261594&view=diff
==============================================================================
--- llvm/trunk/lib/IR/PassManager.cpp (original)
+++ llvm/trunk/lib/IR/PassManager.cpp Mon Feb 22 18:05:00 2016
@@ -22,6 +22,10 @@ FunctionAnalysisManagerModuleProxy::run(
 }
 
 FunctionAnalysisManagerModuleProxy::Result::~Result() {
+  // FAM is cleared in a moved from state where there is nothing to do.
+  if (!FAM)
+    return;
+
   // Clear out the analysis manager if we're being destroyed -- it means we
   // didn't even see an invalidate call when we got invalidated.
   FAM->clear();




More information about the llvm-commits mailing list