summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/Other/pass-pipeline-parsing.ll2
-rw-r--r--tools/opt/CMakeLists.txt2
-rw-r--r--tools/opt/NewPMDriver.cpp46
-rw-r--r--tools/opt/NewPMDriver.h42
-rw-r--r--tools/opt/Passes.cpp93
-rw-r--r--tools/opt/Passes.h56
-rw-r--r--tools/opt/opt.cpp21
7 files changed, 261 insertions, 1 deletions
diff --git a/test/Other/pass-pipeline-parsing.ll b/test/Other/pass-pipeline-parsing.ll
new file mode 100644
index 0000000000..c490f56ba8
--- /dev/null
+++ b/test/Other/pass-pipeline-parsing.ll
@@ -0,0 +1,2 @@
+; RUN: opt -disable-output -passes=no-op-module,no-op-module %s
+; RUN: opt -disable-output -passes='module(no-op-module,no-op-module)' %s
diff --git a/tools/opt/CMakeLists.txt b/tools/opt/CMakeLists.txt
index f96f9b35ef..c007e0fa2e 100644
--- a/tools/opt/CMakeLists.txt
+++ b/tools/opt/CMakeLists.txt
@@ -23,6 +23,8 @@ set(LLVM_NO_DEAD_STRIP 1)
add_llvm_tool(opt
AnalysisWrappers.cpp
GraphPrinters.cpp
+ NewPMDriver.cpp
+ Passes.cpp
PrintSCC.cpp
opt.cpp
)
diff --git a/tools/opt/NewPMDriver.cpp b/tools/opt/NewPMDriver.cpp
new file mode 100644
index 0000000000..e577995e26
--- /dev/null
+++ b/tools/opt/NewPMDriver.cpp
@@ -0,0 +1,46 @@
+//===- NewPMDriver.cpp - Driver for opt with new PM -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file is just a split of the code that logically belongs in opt.cpp but
+/// that includes the new pass manager headers.
+///
+//===----------------------------------------------------------------------===//
+
+#include "NewPMDriver.h"
+#include "Passes.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+using namespace llvm;
+
+bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
+ tool_output_file *Out, StringRef PassPipeline,
+ bool NoOutput) {
+ // Before executing passes, print the final values of the LLVM options.
+ cl::PrintOptionValues();
+
+ ModulePassManager MPM;
+ if (!parsePassPipeline(MPM, PassPipeline)) {
+ errs() << Arg0 << ": unable to parse pass pipeline description.\n";
+ return false;
+ }
+
+ // Now that we have all of the passes ready, run them.
+ MPM.run(&M);
+
+ // Declare success.
+ if (!NoOutput)
+ Out->keep();
+ return true;
+}
diff --git a/tools/opt/NewPMDriver.h b/tools/opt/NewPMDriver.h
new file mode 100644
index 0000000000..17ac75be54
--- /dev/null
+++ b/tools/opt/NewPMDriver.h
@@ -0,0 +1,42 @@
+//===- NewPMDriver.h - Function to drive opt with the new PM ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// A single function which is called to drive the opt behavior for the new
+/// PassManager.
+///
+/// This is only in a separate TU with a header to avoid including all of the
+/// old pass manager headers and the new pass manager headers into the same
+/// file. Eventually all of the routines here will get folded back into
+/// opt.cpp.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_OPT_NEW_PM_DRIVER_H
+#define LLVM_TOOLS_OPT_NEW_PM_DRIVER_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+class LLVMContext;
+class Module;
+class tool_output_file;
+
+/// \brief Driver function to run the new pass manager over a module.
+///
+/// This function only exists factored away from opt.cpp in order to prevent
+/// inclusion of the new pass manager headers and the old headers into the same
+/// file. It's interface is consequentially somewhat ad-hoc, but will go away
+/// when the transition finishes.
+bool runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M,
+ tool_output_file *Out, StringRef PassPipeline,
+ bool NoOutput);
+}
+
+#endif
diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp
new file mode 100644
index 0000000000..49751269df
--- /dev/null
+++ b/tools/opt/Passes.cpp
@@ -0,0 +1,93 @@
+//===- Passes.cpp - Parsing, selection, and running of passes -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file provides the infrastructure to parse and build a custom pass
+/// manager based on a commandline flag. It also provides helpers to aid in
+/// analyzing, debugging, and testing pass structures.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Passes.h"
+#include "llvm/IR/PassManager.h"
+
+using namespace llvm;
+
+namespace {
+
+ /// \brief No-op module pass which does nothing.
+struct NoOpModulePass {
+ PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); }
+};
+
+} // End anonymous namespace.
+
+// FIXME: Factor all of the parsing logic into a .def file that we include
+// under different macros.
+static bool isModulePassName(StringRef Name) {
+ if (Name == "no-op-module") return true;
+
+ return false;
+}
+
+static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) {
+ assert(isModulePassName(Name));
+ if (Name == "no-op-module") {
+ MPM.addPass(NoOpModulePass());
+ return true;
+ }
+ return false;
+}
+
+static bool parseModulePassPipeline(ModulePassManager &MPM,
+ StringRef &PipelineText) {
+ for (;;) {
+ // Parse nested pass managers by recursing.
+ if (PipelineText.startswith("module(")) {
+ PipelineText = PipelineText.substr(strlen("module("));
+ if (!parseModulePassPipeline(MPM, PipelineText))
+ return false;
+ assert(!PipelineText.empty() && PipelineText[0] == ')');
+ PipelineText = PipelineText.substr(1);
+ } else {
+ // Otherwise try to parse a pass name.
+ size_t End = PipelineText.find_first_of(",)");
+ if (!parseModulePassName(MPM, PipelineText.substr(0, End)))
+ return false;
+
+ PipelineText = PipelineText.substr(End);
+ }
+
+ if (PipelineText.empty() || PipelineText[0] == ')')
+ return true;
+
+ assert(PipelineText[0] == ',');
+ PipelineText = PipelineText.substr(1);
+ }
+}
+
+// Primary pass pipeline description parsing routine.
+// FIXME: Should this routine accept a TargetMachine or require the caller to
+// pre-populate the analysis managers with target-specific stuff?
+bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText) {
+ // Look at the first entry to figure out which layer to start parsing at.
+ if (PipelineText.startswith("module("))
+ return parseModulePassPipeline(MPM, PipelineText);
+
+ // FIXME: Support parsing function pass manager nests.
+
+ // This isn't a direct pass manager name, look for the end of a pass name.
+ StringRef FirstName = PipelineText.substr(0, PipelineText.find_first_of(","));
+ if (isModulePassName(FirstName))
+ return parseModulePassPipeline(MPM, PipelineText);
+
+ // FIXME: Support parsing function pass names.
+
+ return false;
+}
diff --git a/tools/opt/Passes.h b/tools/opt/Passes.h
new file mode 100644
index 0000000000..6016b74c80
--- /dev/null
+++ b/tools/opt/Passes.h
@@ -0,0 +1,56 @@
+//===- Passes.h - Parsing, selection, and running of passes -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// Interfaces for producing common pass manager configurations and parsing
+/// textual pass specifications.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_OPT_PASSES_H
+#define LLVM_TOOLS_OPT_PASSES_H
+
+#include "llvm/ADT/StringRef.h"
+
+namespace llvm {
+class ModulePassManager;
+
+/// \brief Parse a textual pass pipeline description into a \c ModulePassManager.
+///
+/// The format of the textual pass pipeline description looks something like:
+///
+/// module(function(instcombine,sroa),dce,cgscc(inliner,function(...)),...)
+///
+/// Pass managers have ()s describing the nest structure of passes. All passes
+/// are comma separated. As a special shortcut, if the very first pass is not
+/// a module pass (as a module pass manager is), this will automatically form
+/// the shortest stack of pass managers that allow inserting that first pass.
+/// So, assuming function passes 'fpassN', CGSCC passes 'cgpassN', and loop passes
+/// 'lpassN', all of these are valid:
+///
+/// fpass1,fpass2,fpass3
+/// cgpass1,cgpass2,cgpass3
+/// lpass1,lpass2,lpass3
+///
+/// And they are equivalent to the following (resp.):
+///
+/// module(function(fpass1,fpass2,fpass3))
+/// module(cgscc(cgpass1,cgpass2,cgpass3))
+/// module(function(loop(lpass1,lpass2,lpass3)))
+///
+/// This shortcut is especially useful for debugging and testing small pass
+/// combinations. Note that these shortcuts don't introduce any other magic. If
+/// the sequence of passes aren't all the exact same kind of pass, it will be
+/// an error. You cannot mix different levels implicitly, you must explicitly
+/// form a pass manager in which to nest passes.
+bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText);
+
+}
+
+#endif
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 9e76451229..5138ef68c0 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/LLVMContext.h"
+#include "NewPMDriver.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/CallGraph.h"
@@ -24,6 +24,7 @@
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/DebugInfo.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PrintModulePass.h"
#include "llvm/IRReader/IRReader.h"
@@ -55,6 +56,15 @@ using namespace llvm;
static cl::list<const PassInfo*, bool, PassNameParser>
PassList(cl::desc("Optimizations available:"));
+// This flag specifies a textual description of the optimization pass pipeline
+// to run over the module. This flag switches opt to use the new pass manager
+// infrastructure, completely disabling all of the flags specific to the old
+// pass management.
+static cl::opt<std::string> PassPipeline(
+ "passes",
+ cl::desc("A textual description of the pass pipeline for optimizing"),
+ cl::Hidden);
+
// Other command line options...
//
static cl::opt<std::string>
@@ -660,6 +670,15 @@ int main(int argc, char **argv) {
if (CheckBitcodeOutputToConsole(Out->os(), !Quiet))
NoOutput = true;
+ if (PassPipeline.getNumOccurrences() > 0)
+ // The user has asked to use the new pass manager and provided a pipeline
+ // string. Hand off the rest of the functionality to the new code for that
+ // layer.
+ return runPassPipeline(argv[0], Context, *M.get(), Out.get(), PassPipeline,
+ NoOutput)
+ ? 0
+ : 1;
+
// Create a PassManager to hold and optimize the collection of passes we are
// about to build.
//