<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Sat, Jan 11, 2014 at 3:16 AM, Chandler Carruth <span dir="ltr"><<a href="mailto:chandlerc@gmail.com" target="_blank">chandlerc@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: chandlerc<br>
Date: Sat Jan 11 02:16:35 2014<br>
New Revision: 198998<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=198998&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=198998&view=rev</a><br>
Log:<br>
[PM] Add (very skeletal) support to opt for running the new pass<br>
manager. I cannot emphasize enough that this is a WIP. =] I expect it<br>
to change a great deal as things stabilize, but I think its really<br>
important to get *some* functionality here so that the infrastructure<br>
can be tested more traditionally from the commandline.<br>
<br>
The current design is looking something like this:<br>
<br>
  ./bin/opt -passes='module(pass_a,pass_b,function(pass_c,pass_d))'<br></blockquote><div><br></div><div>Neat, I really like this direction.</div><div><br></div><div>-- Sean Silva</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
So rather than custom-parsed flags, there is a single flag with a string<br>
argument that is parsed into the pass pipeline structure. This makes it<br>
really easy to have nice structural properties that are very explicit.<br>
There is one obvious and important shortcut. You can start off the<br>
pipeline with a pass, and the minimal context of pass managers will be<br>
built around the entire specified pipeline. This makes the common case<br>
for tests super easy:<br>
<br>
  ./bin/opt -passes=instcombine,sroa,gvn<br>
<br>
But this won't introduce any of the complexity of the fully inferred old<br>
system -- we only ever do this for the *entire* argument, and we only<br>
look at the first pass. If the other passes don't fit in the pass<br>
manager selected it is a hard error.<br>
<br>
The other interesting aspect here is that I'm not relying on any<br>
registration facilities. Such facilities may be unavoidable for<br>
supporting plugins, but I have alternative ideas for plugins that I'd<br>
like to try first. My plan is essentially to build everything without<br>
registration until we hit an absolute requirement.<br>
<br>
Instead of registration of pass names, there will be a library dedicated<br>
to parsing pass names and the pass pipeline strings described above.<br>
Currently, this is directly embedded into opt for simplicity as it is<br>
very early, but I plan to eventually pull this into a library that opt,<br>
bugpoint, and even Clang can depend on. It should end up as a good home<br>
for things like the existing PassManagerBuilder as well.<br>
<br>
There are a bunch of FIXMEs in the code for the parts of this that are<br>
just stubbed out to make the patch more incremental. A quick list of<br>
what's coming up directly after this:<br>
- Support for function passes and building the structured nesting.<br>
- Support for printing the pass structure, and FileCheck tests of all of<br>
  this code.<br>
- The .def-file based pass name parsing.<br>
- IR priting passes and the corresponding tests.<br>
<br>
Some obvious things that I'm not going to do right now, but am<br>
definitely planning on as the pass manager work gets a bit further:<br>
- Pull the parsing into library, including the builders.<br>
- Thread the rest of the target stuff into the new pass manager.<br>
- Wire support for the new pass manager up to llc.<br>
- Plugin support.<br>
<br>
Some things that I'd like to have, but are significantly lower on my<br>
priority list. I'll get to these eventually, but they may also be places<br>
where others want to contribute:<br>
- Adding nice error reporting for broken pass pipeline descriptions.<br>
- Typo-correction for pass names.<br>
<br>
Added:<br>
    llvm/trunk/test/Other/pass-pipeline-parsing.ll<br>
    llvm/trunk/tools/opt/NewPMDriver.cpp<br>
    llvm/trunk/tools/opt/NewPMDriver.h<br>
    llvm/trunk/tools/opt/Passes.cpp<br>
    llvm/trunk/tools/opt/Passes.h<br>
Modified:<br>
    llvm/trunk/tools/opt/CMakeLists.txt<br>
    llvm/trunk/tools/opt/opt.cpp<br>
<br>
Added: llvm/trunk/test/Other/pass-pipeline-parsing.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/pass-pipeline-parsing.ll?rev=198998&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Other/pass-pipeline-parsing.ll?rev=198998&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/test/Other/pass-pipeline-parsing.ll (added)<br>
+++ llvm/trunk/test/Other/pass-pipeline-parsing.ll Sat Jan 11 02:16:35 2014<br>
@@ -0,0 +1,2 @@<br>
+; RUN: opt -disable-output -passes=no-op-module,no-op-module %s<br>
+; RUN: opt -disable-output -passes='module(no-op-module,no-op-module)' %s<br>
<br>
Modified: llvm/trunk/tools/opt/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/CMakeLists.txt?rev=198998&r1=198997&r2=198998&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/CMakeLists.txt?rev=198998&r1=198997&r2=198998&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/tools/opt/CMakeLists.txt (original)<br>
+++ llvm/trunk/tools/opt/CMakeLists.txt Sat Jan 11 02:16:35 2014<br>
@@ -23,6 +23,8 @@ set(LLVM_NO_DEAD_STRIP 1)<br>
 add_llvm_tool(opt<br>
   AnalysisWrappers.cpp<br>
   GraphPrinters.cpp<br>
+  NewPMDriver.cpp<br>
+  Passes.cpp<br>
   PrintSCC.cpp<br>
   opt.cpp<br>
   )<br>
<br>
Added: llvm/trunk/tools/opt/NewPMDriver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/NewPMDriver.cpp?rev=198998&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/NewPMDriver.cpp?rev=198998&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/tools/opt/NewPMDriver.cpp (added)<br>
+++ llvm/trunk/tools/opt/NewPMDriver.cpp Sat Jan 11 02:16:35 2014<br>
@@ -0,0 +1,46 @@<br>
+//===- NewPMDriver.cpp - Driver for opt with new PM -----------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+/// \file<br>
+///<br>
+/// This file is just a split of the code that logically belongs in opt.cpp but<br>
+/// that includes the new pass manager headers.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "NewPMDriver.h"<br>
+#include "Passes.h"<br>
+#include "llvm/ADT/StringRef.h"<br>
+#include "llvm/IR/LLVMContext.h"<br>
+#include "llvm/IR/Module.h"<br>
+#include "llvm/IR/PassManager.h"<br>
+#include "llvm/Support/CommandLine.h"<br>
+#include "llvm/Support/ToolOutputFile.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,<br>
+                           tool_output_file *Out, StringRef PassPipeline,<br>
+                           bool NoOutput) {<br>
+  // Before executing passes, print the final values of the LLVM options.<br>
+  cl::PrintOptionValues();<br>
+<br>
+  ModulePassManager MPM;<br>
+  if (!parsePassPipeline(MPM, PassPipeline)) {<br>
+    errs() << Arg0 << ": unable to parse pass pipeline description.\n";<br>
+    return false;<br>
+  }<br>
+<br>
+  // Now that we have all of the passes ready, run them.<br>
+  MPM.run(&M);<br>
+<br>
+  // Declare success.<br>
+  if (!NoOutput)<br>
+    Out->keep();<br>
+  return true;<br>
+}<br>
<br>
Added: llvm/trunk/tools/opt/NewPMDriver.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/NewPMDriver.h?rev=198998&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/NewPMDriver.h?rev=198998&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/tools/opt/NewPMDriver.h (added)<br>
+++ llvm/trunk/tools/opt/NewPMDriver.h Sat Jan 11 02:16:35 2014<br>
@@ -0,0 +1,42 @@<br>
+//===- NewPMDriver.h - Function to drive opt with the new PM ----*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+/// \file<br>
+///<br>
+/// A single function which is called to drive the opt behavior for the new<br>
+/// PassManager.<br>
+///<br>
+/// This is only in a separate TU with a header to avoid including all of the<br>
+/// old pass manager headers and the new pass manager headers into the same<br>
+/// file. Eventually all of the routines here will get folded back into<br>
+/// opt.cpp.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_TOOLS_OPT_NEW_PM_DRIVER_H<br>
+#define LLVM_TOOLS_OPT_NEW_PM_DRIVER_H<br>
+<br>
+#include "llvm/ADT/StringRef.h"<br>
+<br>
+namespace llvm {<br>
+class LLVMContext;<br>
+class Module;<br>
+class tool_output_file;<br>
+<br>
+/// \brief Driver function to run the new pass manager over a module.<br>
+///<br>
+/// This function only exists factored away from opt.cpp in order to prevent<br>
+/// inclusion of the new pass manager headers and the old headers into the same<br>
+/// file. It's interface is consequentially somewhat ad-hoc, but will go away<br>
+/// when the transition finishes.<br>
+bool runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,<br>
+                     tool_output_file *Out, StringRef PassPipeline,<br>
+                     bool NoOutput);<br>
+}<br>
+<br>
+#endif<br>
<br>
Added: llvm/trunk/tools/opt/Passes.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/Passes.cpp?rev=198998&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/Passes.cpp?rev=198998&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/tools/opt/Passes.cpp (added)<br>
+++ llvm/trunk/tools/opt/Passes.cpp Sat Jan 11 02:16:35 2014<br>
@@ -0,0 +1,93 @@<br>
+//===- Passes.cpp - Parsing, selection, and running of passes -------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+/// \file<br>
+///<br>
+/// This file provides the infrastructure to parse and build a custom pass<br>
+/// manager based on a commandline flag. It also provides helpers to aid in<br>
+/// analyzing, debugging, and testing pass structures.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "Passes.h"<br>
+#include "llvm/IR/PassManager.h"<br>
+<br>
+using namespace llvm;<br>
+<br>
+namespace {<br>
+<br>
+  /// \brief No-op module pass which does nothing.<br>
+struct NoOpModulePass {<br>
+  PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); }<br>
+};<br>
+<br>
+} // End anonymous namespace.<br>
+<br>
+// FIXME: Factor all of the parsing logic into a .def file that we include<br>
+// under different macros.<br>
+static bool isModulePassName(StringRef Name) {<br>
+  if (Name == "no-op-module") return true;<br>
+<br>
+  return false;<br>
+}<br>
+<br>
+static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) {<br>
+  assert(isModulePassName(Name));<br>
+  if (Name == "no-op-module") {<br>
+    MPM.addPass(NoOpModulePass());<br>
+    return true;<br>
+  }<br>
+  return false;<br>
+}<br>
+<br>
+static bool parseModulePassPipeline(ModulePassManager &MPM,<br>
+                                    StringRef &PipelineText) {<br>
+  for (;;) {<br>
+    // Parse nested pass managers by recursing.<br>
+    if (PipelineText.startswith("module(")) {<br>
+      PipelineText = PipelineText.substr(strlen("module("));<br>
+      if (!parseModulePassPipeline(MPM, PipelineText))<br>
+        return false;<br>
+      assert(!PipelineText.empty() && PipelineText[0] == ')');<br>
+      PipelineText = PipelineText.substr(1);<br>
+    } else {<br>
+      // Otherwise try to parse a pass name.<br>
+      size_t End = PipelineText.find_first_of(",)");<br>
+      if (!parseModulePassName(MPM, PipelineText.substr(0, End)))<br>
+        return false;<br>
+<br>
+      PipelineText = PipelineText.substr(End);<br>
+    }<br>
+<br>
+    if (PipelineText.empty() || PipelineText[0] == ')')<br>
+      return true;<br>
+<br>
+    assert(PipelineText[0] == ',');<br>
+    PipelineText = PipelineText.substr(1);<br>
+  }<br>
+}<br>
+<br>
+// Primary pass pipeline description parsing routine.<br>
+// FIXME: Should this routine accept a TargetMachine or require the caller to<br>
+// pre-populate the analysis managers with target-specific stuff?<br>
+bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText) {<br>
+  // Look at the first entry to figure out which layer to start parsing at.<br>
+  if (PipelineText.startswith("module("))<br>
+    return parseModulePassPipeline(MPM, PipelineText);<br>
+<br>
+  // FIXME: Support parsing function pass manager nests.<br>
+<br>
+  // This isn't a direct pass manager name, look for the end of a pass name.<br>
+  StringRef FirstName = PipelineText.substr(0, PipelineText.find_first_of(","));<br>
+  if (isModulePassName(FirstName))<br>
+    return parseModulePassPipeline(MPM, PipelineText);<br>
+<br>
+  // FIXME: Support parsing function pass names.<br>
+<br>
+  return false;<br>
+}<br>
<br>
Added: llvm/trunk/tools/opt/Passes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/Passes.h?rev=198998&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/Passes.h?rev=198998&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/tools/opt/Passes.h (added)<br>
+++ llvm/trunk/tools/opt/Passes.h Sat Jan 11 02:16:35 2014<br>
@@ -0,0 +1,56 @@<br>
+//===- Passes.h - Parsing, selection, and running of passes -----*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+/// \file<br>
+///<br>
+/// Interfaces for producing common pass manager configurations and parsing<br>
+/// textual pass specifications.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_TOOLS_OPT_PASSES_H<br>
+#define LLVM_TOOLS_OPT_PASSES_H<br>
+<br>
+#include "llvm/ADT/StringRef.h"<br>
+<br>
+namespace llvm {<br>
+class ModulePassManager;<br>
+<br>
+/// \brief Parse a textual pass pipeline description into a \c ModulePassManager.<br>
+///<br>
+/// The format of the textual pass pipeline description looks something like:<br>
+///<br>
+///   module(function(instcombine,sroa),dce,cgscc(inliner,function(...)),...)<br>
+///<br>
+/// Pass managers have ()s describing the nest structure of passes. All passes<br>
+/// are comma separated. As a special shortcut, if the very first pass is not<br>
+/// a module pass (as a module pass manager is), this will automatically form<br>
+/// the shortest stack of pass managers that allow inserting that first pass.<br>
+/// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop passes<br>
+/// 'lpassN', all of these are valid:<br>
+///<br>
+///   fpass1,fpass2,fpass3<br>
+///   cgpass1,cgpass2,cgpass3<br>
+///   lpass1,lpass2,lpass3<br>
+///<br>
+/// And they are equivalent to the following (resp.):<br>
+///<br>
+///   module(function(fpass1,fpass2,fpass3))<br>
+///   module(cgscc(cgpass1,cgpass2,cgpass3))<br>
+///   module(function(loop(lpass1,lpass2,lpass3)))<br>
+///<br>
+/// This shortcut is especially useful for debugging and testing small pass<br>
+/// combinations. Note that these shortcuts don't introduce any other magic. If<br>
+/// the sequence of passes aren't all the exact same kind of pass, it will be<br>
+/// an error. You cannot mix different levels implicitly, you must explicitly<br>
+/// form a pass manager in which to nest passes.<br>
+bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText);<br>
+<br>
+}<br>
+<br>
+#endif<br>
<br>
Modified: llvm/trunk/tools/opt/opt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/opt.cpp?rev=198998&r1=198997&r2=198998&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/opt.cpp?rev=198998&r1=198997&r2=198998&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/tools/opt/opt.cpp (original)<br>
+++ llvm/trunk/tools/opt/opt.cpp Sat Jan 11 02:16:35 2014<br>
@@ -12,7 +12,7 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
<br>
-#include "llvm/IR/LLVMContext.h"<br>
+#include "NewPMDriver.h"<br>
 #include "llvm/ADT/StringSet.h"<br>
 #include "llvm/ADT/Triple.h"<br>
 #include "llvm/Analysis/CallGraph.h"<br>
@@ -24,6 +24,7 @@<br>
 #include "llvm/CodeGen/CommandFlags.h"<br>
 #include "llvm/DebugInfo.h"<br>
 #include "llvm/IR/DataLayout.h"<br>
+#include "llvm/IR/LLVMContext.h"<br>
 #include "llvm/IR/Module.h"<br>
 #include "llvm/IR/PrintModulePass.h"<br>
 #include "llvm/IRReader/IRReader.h"<br>
@@ -55,6 +56,15 @@ using namespace llvm;<br>
 static cl::list<const PassInfo*, bool, PassNameParser><br>
 PassList(cl::desc("Optimizations available:"));<br>
<br>
+// This flag specifies a textual description of the optimization pass pipeline<br>
+// to run over the module. This flag switches opt to use the new pass manager<br>
+// infrastructure, completely disabling all of the flags specific to the old<br>
+// pass management.<br>
+static cl::opt<std::string> PassPipeline(<br>
+    "passes",<br>
+    cl::desc("A textual description of the pass pipeline for optimizing"),<br>
+    cl::Hidden);<br>
+<br>
 // Other command line options...<br>
 //<br>
 static cl::opt<std::string><br>
@@ -660,6 +670,15 @@ int main(int argc, char **argv) {<br>
     if (CheckBitcodeOutputToConsole(Out->os(), !Quiet))<br>
       NoOutput = true;<br>
<br>
+  if (PassPipeline.getNumOccurrences() > 0)<br>
+    // The user has asked to use the new pass manager and provided a pipeline<br>
+    // string. Hand off the rest of the functionality to the new code for that<br>
+    // layer.<br>
+    return runPassPipeline(argv[0], Context, *M.get(), Out.get(), PassPipeline,<br>
+                           NoOutput)<br>
+               ? 0<br>
+               : 1;<br>
+<br>
   // Create a PassManager to hold and optimize the collection of passes we are<br>
   // about to build.<br>
   //<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div></div>