[llvm] r273961 - [PM] Improve the debugging and logging facilities of the CGSCC bits of

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 27 16:26:08 PDT 2016


Author: chandlerc
Date: Mon Jun 27 18:26:08 2016
New Revision: 273961

URL: http://llvm.org/viewvc/llvm-project?rev=273961&view=rev
Log:
[PM] Improve the debugging and logging facilities of the CGSCC bits of
the new pass manager.

This adds operator<< overloads for the various bits of the
LazyCallGraph, dump methods for use from the debugger, and debug logging
using them to the CGSCC pass manager.

Having this was essential for debugging the call graph update patch, and
I've extracted what I could from that patch here to minimize the delta.

Modified:
    llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h
    llvm/trunk/include/llvm/Analysis/LazyCallGraph.h
    llvm/trunk/lib/Analysis/LazyCallGraph.cpp
    llvm/trunk/lib/Passes/PassBuilder.cpp
    llvm/trunk/test/Other/new-pass-manager.ll

Modified: llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h?rev=273961&r1=273960&r2=273961&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h (original)
+++ llvm/trunk/include/llvm/Analysis/CGSCCPassManager.h Mon Jun 27 18:26:08 2016
@@ -67,19 +67,20 @@ template <typename CGSCCPassT>
 class ModuleToPostOrderCGSCCPassAdaptor
     : public PassInfoMixin<ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>> {
 public:
-  explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass)
-      : Pass(std::move(Pass)) {}
+  explicit ModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass, bool DebugLogging = false)
+      : Pass(std::move(Pass)), DebugLogging(DebugLogging) {}
   // We have to explicitly define all the special member functions because MSVC
   // refuses to generate them.
   ModuleToPostOrderCGSCCPassAdaptor(
       const ModuleToPostOrderCGSCCPassAdaptor &Arg)
-      : Pass(Arg.Pass) {}
+      : Pass(Arg.Pass), DebugLogging(Arg.DebugLogging) {}
   ModuleToPostOrderCGSCCPassAdaptor(ModuleToPostOrderCGSCCPassAdaptor &&Arg)
-      : Pass(std::move(Arg.Pass)) {}
+      : Pass(std::move(Arg.Pass)), DebugLogging(Arg.DebugLogging) {}
   friend void swap(ModuleToPostOrderCGSCCPassAdaptor &LHS,
                    ModuleToPostOrderCGSCCPassAdaptor &RHS) {
     using std::swap;
     swap(LHS.Pass, RHS.Pass);
+    swap(LHS.DebugLogging, RHS.DebugLogging);
   }
   ModuleToPostOrderCGSCCPassAdaptor &
   operator=(ModuleToPostOrderCGSCCPassAdaptor RHS) {
@@ -97,8 +98,11 @@ public:
     LazyCallGraph &CG = AM.getResult<LazyCallGraphAnalysis>(M);
 
     PreservedAnalyses PA = PreservedAnalyses::all();
-    for (LazyCallGraph::RefSCC &OuterC : CG.postorder_ref_sccs())
-      for (LazyCallGraph::SCC &C : OuterC) {
+    for (LazyCallGraph::RefSCC &RC : CG.postorder_ref_sccs()) {
+      if (DebugLogging)
+        dbgs() << "Running an SCC pass across the RefSCC: " << RC << "\n";
+
+      for (LazyCallGraph::SCC &C : RC) {
         PreservedAnalyses PassPA = Pass.run(C, CGAM);
 
         // We know that the CGSCC pass couldn't have invalidated any other
@@ -115,6 +119,7 @@ public:
         // analyses will eventually occur when the module pass completes.
         PA.intersect(std::move(PassPA));
       }
+    }
 
     // By definition we preserve the proxy. This precludes *any* invalidation
     // of CGSCC analyses by the proxy, but that's OK because we've taken
@@ -126,14 +131,15 @@ public:
 
 private:
   CGSCCPassT Pass;
+  bool DebugLogging;
 };
 
 /// \brief A function to deduce a function pass type and wrap it in the
 /// templated adaptor.
 template <typename CGSCCPassT>
 ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>
-createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass) {
-  return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass));
+createModuleToPostOrderCGSCCPassAdaptor(CGSCCPassT Pass, bool DebugLogging = false) {
+  return ModuleToPostOrderCGSCCPassAdaptor<CGSCCPassT>(std::move(Pass), DebugLogging);
 }
 
 extern template class InnerAnalysisManagerProxy<FunctionAnalysisManager,
@@ -159,18 +165,19 @@ template <typename FunctionPassT>
 class CGSCCToFunctionPassAdaptor
     : public PassInfoMixin<CGSCCToFunctionPassAdaptor<FunctionPassT>> {
 public:
-  explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass)
-      : Pass(std::move(Pass)) {}
+  explicit CGSCCToFunctionPassAdaptor(FunctionPassT Pass, bool DebugLogging = false)
+      : Pass(std::move(Pass)), DebugLogging(DebugLogging) {}
   // We have to explicitly define all the special member functions because MSVC
   // refuses to generate them.
   CGSCCToFunctionPassAdaptor(const CGSCCToFunctionPassAdaptor &Arg)
-      : Pass(Arg.Pass) {}
+      : Pass(Arg.Pass), DebugLogging(Arg.DebugLogging) {}
   CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg)
-      : Pass(std::move(Arg.Pass)) {}
+      : Pass(std::move(Arg.Pass)), DebugLogging(Arg.DebugLogging) {}
   friend void swap(CGSCCToFunctionPassAdaptor &LHS,
                    CGSCCToFunctionPassAdaptor &RHS) {
     using std::swap;
     swap(LHS.Pass, RHS.Pass);
+    swap(LHS.DebugLogging, RHS.DebugLogging);
   }
   CGSCCToFunctionPassAdaptor &operator=(CGSCCToFunctionPassAdaptor RHS) {
     swap(*this, RHS);
@@ -183,6 +190,9 @@ public:
     FunctionAnalysisManager &FAM =
         AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager();
 
+    if (DebugLogging)
+      dbgs() << "Running function passes across an SCC: " << C << "\n";
+
     PreservedAnalyses PA = PreservedAnalyses::all();
     for (LazyCallGraph::Node &N : C) {
       PreservedAnalyses PassPA = Pass.run(N.getFunction(), FAM);
@@ -211,14 +221,16 @@ public:
 
 private:
   FunctionPassT Pass;
+  bool DebugLogging;
 };
 
 /// \brief A function to deduce a function pass type and wrap it in the
 /// templated adaptor.
 template <typename FunctionPassT>
 CGSCCToFunctionPassAdaptor<FunctionPassT>
-createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) {
-  return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass));
+createCGSCCToFunctionPassAdaptor(FunctionPassT Pass, bool DebugLogging = false) {
+  return CGSCCToFunctionPassAdaptor<FunctionPassT>(std::move(Pass),
+                                                   DebugLogging);
 }
 }
 

Modified: llvm/trunk/include/llvm/Analysis/LazyCallGraph.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/LazyCallGraph.h?rev=273961&r1=273960&r2=273961&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/LazyCallGraph.h (original)
+++ llvm/trunk/include/llvm/Analysis/LazyCallGraph.h Mon Jun 27 18:26:08 2016
@@ -48,6 +48,7 @@
 #include "llvm/IR/Module.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Support/Allocator.h"
+#include "llvm/Support/raw_ostream.h"
 #include <iterator>
 #include <utility>
 
@@ -222,6 +223,12 @@ public:
     /// Internal helper to remove the edge to the given function.
     void removeEdgeInternal(Function &ChildF);
 
+    /// Print the name of this node's function.
+    friend raw_ostream &operator<<(raw_ostream &OS, const Node &N);
+
+    /// Dump the name of this node's function to stderr.
+    void dump() const;
+
   public:
     LazyCallGraph &getGraph() const { return *G; }
 
@@ -353,6 +360,15 @@ public:
       Nodes.clear();
     }
 
+    /// Print a short descrtiption useful for debugging or logging.
+    ///
+    /// We print the function names in the SCC wrapped in '()'s and skipping
+    /// the middle functions if there are a large number.
+    friend raw_ostream &operator<<(raw_ostream &OS, const SCC &C);
+
+    /// Dump a short description of this SCC to stderr.
+    void dump() const;
+
 #ifndef NDEBUG
     /// Verify invariants about the SCC.
     ///
@@ -373,25 +389,15 @@ public:
 
     RefSCC &getOuterRefSCC() const { return *OuterRefSCC; }
 
-    /// Short name useful for debugging or logging.
+    /// Provide a short name by printing this SCC to a std::string.
     ///
-    /// We use the name of the first function in the SCC to name the SCC for
-    /// the purposes of debugging and logging.
+    /// This copes with the fact that we don't have a name per-se for an SCC
+    /// while still making the use of this in debugging and logging useful.
     std::string getName() const {
       std::string Name;
-      int i = 0;
-      for (Node &N : *this) {
-        if (i > 0)
-          Name += ", ";
-        // Elide the inner elements if there are too many.
-        if (i > 8) {
-          Name += "..., ";
-          Name += Nodes.back()->getFunction().getName().str();
-          break;
-        }
-        Name += N.getFunction().getName().str();
-        ++i;
-      }
+      raw_string_ostream OS(Name);
+      OS << *this;
+      OS.flush();
       return Name;
     }
   };
@@ -426,6 +432,15 @@ public:
     /// formRefSCCFast on the graph itself.
     RefSCC(LazyCallGraph &G);
 
+    /// Print a short description useful for debugging or logging.
+    ///
+    /// We print the SCCs wrapped in '[]'s and skipping the middle SCCs if
+    /// there are a large number.
+    friend raw_ostream &operator<<(raw_ostream &OS, const RefSCC &RC);
+
+    /// Dump a short description of this RefSCC to stderr.
+    void dump() const;
+
 #ifndef NDEBUG
     /// Verify invariants about the RefSCC and all its SCCs.
     ///
@@ -477,12 +492,16 @@ public:
     /// Test if this RefSCC is a descendant of \a C.
     bool isDescendantOf(const RefSCC &C) const;
 
-    /// Short name useful for debugging or logging.
+    /// Provide a short name by printing this SCC to a std::string.
     ///
-    /// We use the name of the first function in the SCC to name the SCC for
-    /// the purposes of debugging and logging.
-    StringRef getName() const {
-      return begin()->begin()->getFunction().getName();
+    /// This copes with the fact that we don't have a name per-se for an SCC
+    /// while still making the use of this in debugging and logging useful.
+    std::string getName() const {
+      std::string Name;
+      raw_string_ostream OS(Name);
+      OS << *this;
+      OS.flush();
+      return Name;
     }
 
     ///@{

Modified: llvm/trunk/lib/Analysis/LazyCallGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LazyCallGraph.cpp?rev=273961&r1=273960&r2=273961&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/LazyCallGraph.cpp (original)
+++ llvm/trunk/lib/Analysis/LazyCallGraph.cpp Mon Jun 27 18:26:08 2016
@@ -120,6 +120,14 @@ void LazyCallGraph::Node::removeEdgeInte
   EdgeIndexMap.erase(IndexMapI);
 }
 
+raw_ostream &llvm::operator<<(raw_ostream &OS, const LazyCallGraph::Node &N) {
+  return OS << N.F.getName();
+}
+
+void LazyCallGraph::Node::dump() const {
+  dbgs() << *this << '\n';
+}
+
 LazyCallGraph::LazyCallGraph(Module &M) : NextDFSNumber(0) {
   DEBUG(dbgs() << "Building CG for module: " << M.getModuleIdentifier()
                << "\n");
@@ -173,6 +181,28 @@ LazyCallGraph &LazyCallGraph::operator=(
   return *this;
 }
 
+raw_ostream &llvm::operator<<(raw_ostream &OS, const LazyCallGraph::SCC &C) {
+  OS << '(';
+  int i = 0;
+  for (LazyCallGraph::Node &N : C) {
+    if (i > 0)
+      OS << ", ";
+    // Elide the inner elements if there are too many.
+    if (i > 8) {
+      OS << "..., " << *C.Nodes.back();
+      break;
+    }
+    OS << N;
+    ++i;
+  }
+  OS << ')';
+  return OS;
+}
+
+void LazyCallGraph::SCC::dump() const {
+  dbgs() << *this << '\n';
+}
+
 #ifndef NDEBUG
 void LazyCallGraph::SCC::verify() {
   assert(OuterRefSCC && "Can't have a null RefSCC!");
@@ -194,6 +224,29 @@ void LazyCallGraph::SCC::verify() {
 
 LazyCallGraph::RefSCC::RefSCC(LazyCallGraph &G) : G(&G) {}
 
+raw_ostream &llvm::operator<<(raw_ostream &OS,
+                              const LazyCallGraph::RefSCC &RC) {
+  OS << '[';
+  int i = 0;
+  for (LazyCallGraph::SCC &C : RC) {
+    if (i > 0)
+      OS << ", ";
+    // Elide the inner elements if there are too many.
+    if (i > 4) {
+      OS << "..., " << *RC.SCCs.back();
+      break;
+    }
+    OS << C;
+    ++i;
+  }
+  OS << ']';
+  return OS;
+}
+
+void LazyCallGraph::RefSCC::dump() const {
+  dbgs() << *this << '\n';
+}
+
 #ifndef NDEBUG
 void LazyCallGraph::RefSCC::verify() {
   assert(G && "Can't have a null graph!");

Modified: llvm/trunk/lib/Passes/PassBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Passes/PassBuilder.cpp?rev=273961&r1=273960&r2=273961&view=diff
==============================================================================
--- llvm/trunk/lib/Passes/PassBuilder.cpp (original)
+++ llvm/trunk/lib/Passes/PassBuilder.cpp Mon Jun 27 18:26:08 2016
@@ -561,7 +561,8 @@ bool PassBuilder::parseCGSCCPassPipeline
       PipelineText = PipelineText.substr(1);
 
       // Add the nested pass manager with the appropriate adaptor.
-      CGPM.addPass(createCGSCCToFunctionPassAdaptor(std::move(NestedFPM)));
+      CGPM.addPass(
+          createCGSCCToFunctionPassAdaptor(std::move(NestedFPM), DebugLogging));
     } else {
       // Otherwise try to parse a pass name.
       size_t End = PipelineText.find_first_of(",)");
@@ -627,8 +628,8 @@ bool PassBuilder::parseModulePassPipelin
       PipelineText = PipelineText.substr(1);
 
       // Add the nested pass manager with the appropriate adaptor.
-      MPM.addPass(
-          createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM)));
+      MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM),
+                                                          DebugLogging));
     } else if (PipelineText.startswith("function(")) {
       FunctionPassManager NestedFPM(DebugLogging);
 
@@ -689,7 +690,7 @@ bool PassBuilder::parsePassPipeline(Modu
                                 DebugLogging) ||
         !PipelineText.empty())
       return false;
-    MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
+    MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM), DebugLogging));
     return true;
   }
 

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=273961&r1=273960&r2=273961&view=diff
==============================================================================
--- llvm/trunk/test/Other/new-pass-manager.ll (original)
+++ llvm/trunk/test/Other/new-pass-manager.ll Mon Jun 27 18:26:08 2016
@@ -22,6 +22,7 @@
 ; CHECK-CGSCC-PASS-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor
 ; CHECK-CGSCC-PASS-NEXT: Running analysis: InnerAnalysisManagerProxy<{{.*}}>
 ; CHECK-CGSCC-PASS-NEXT: Running analysis: LazyCallGraphAnalysis
+; CHECK-CGSCC-PASS-NEXT: Running an SCC pass across the RefSCC: [(foo)]
 ; CHECK-CGSCC-PASS-NEXT: Starting llvm::LazyCallGraph::SCC pass manager run
 ; CHECK-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass
 ; CHECK-CGSCC-PASS-NEXT: Finished llvm::LazyCallGraph::SCC pass manager run




More information about the llvm-commits mailing list