Index: llvm/trunk/include/llvm/Passes/PassBuilder.h
===================================================================
--- llvm/trunk/include/llvm/Passes/PassBuilder.h
+++ llvm/trunk/include/llvm/Passes/PassBuilder.h
@@ -35,6 +35,92 @@
   TargetMachine *TM;
 
 public:
+  /// \brief LLVM-provided high-level optimization levels.
+  ///
+  /// This enumerates the LLVM-provided high-level optimization levels. Each
+  /// level has a specific goal and rationale.
+  enum OptimizationLevel {
+    /// Disable as many optimizations as possible. This doesn't completely
+    /// disable the optimizer in many cases as there are correctness issues
+    /// such as always_inline functions.
+    O0,
+
+    /// Optimize quickly without destroying debuggability.
+    ///
+    /// FIXME: The current and historical behavior of this level does *not*
+    /// agree with this goal, but we would like to move toward this goal in the
+    /// future.
+    ///
+    /// This level is tuned to produce a result from the optimizer as quickly
+    /// as possible and to avoid destroying debuggability. This tends to result
+    /// in a very good development mode where the compiled code will be
+    /// immediately executed as part of testing. As a consequence, where
+    /// possible, we would like to produce efficient-to-execute code, but not
+    /// if it significantly slows down compilation or would prevent even basic
+    /// debugging of the resulting binary.
+    ///
+    /// As an example, complex loop transformations such as versioning,
+    /// vectorization, or fusion might not make sense here due to the degree to
+    /// which the executed code would differ from the source code, and the
+    /// potential compile time cost.
+    O1,
+
+    /// Optimize for fast execution as much as possible without triggering
+    /// significant incremental compile time or code size growth.
+    ///
+    /// The key idea is that optimizations at this level should "pay for
+    /// themselves". So if an optimization increases compile time by 5% or
+    /// increases code size by 5% for a particular benchmark, that benchmark
+    /// should also be one which sees a 5% runtime improvement. If the compile
+    /// time or code size penalties happen on average across a diverse range of
+    /// LLVM users' benchmarks, then the improvements should as well.
+    ///
+    /// And no matter what, the compile time needs to not grow superlinearly
+    /// with the size of input to LLVM so that users can control the runtime of
+    /// the optimizer in this mode.
+    ///
+    /// This is expected to be a good default optimization level for the vast
+    /// majority of users.
+    O2,
+
+    /// Optimize for fast execution as much as possible.
+    ///
+    /// This mode is significantly more aggressive in trading off compile time
+    /// and code size to get execution time improvements. The core idea is that
+    /// this mode should include any optimization that helps execution time on
+    /// balance across a diverse collection of benchmarks, even if it increases
+    /// code size or compile time for some benchmarks without corresponding
+    /// improvements to execution time.
+    ///
+    /// Despite being willing to trade more compile time off to get improved
+    /// execution time, this mode still tries to avoid superlinear growth in
+    /// order to make even significantly slower compile times at least scale
+    /// reasonably. This does not preclude very substantial constant factor
+    /// costs though.
+    O3,
+
+    /// Similar to \c O2 but tries to optimize for small code size instead of
+    /// fast execution without triggering significant incremental execution
+    /// time slowdowns.
+    ///
+    /// The logic here is exactly the same as \c O2, but with code size and
+    /// execution time metrics swapped.
+    ///
+    /// A consequence of the different core goal is that this should in general
+    /// produce substantially smaller executables that still run in
+    /// a reasonable amount of time.
+    Os,
+
+    /// A very specialized mode that will optimize for code size at any and all
+    /// costs.
+    ///
+    /// This is useful primarily when there are absolute size limitations and
+    /// any effort taken to reduce the size is worth it regardless of the
+    /// execution time impact. You should expect this level to produce rather
+    /// slow, but very small, code.
+    Oz
+  };
+
   explicit PassBuilder(TargetMachine *TM = nullptr) : TM(TM) {}
 
   /// \brief Registers all available module analysis passes.
@@ -68,6 +154,36 @@
   /// additional analyses.
   void registerLoopAnalyses(LoopAnalysisManager &LAM);
 
+  /// \brief Add a per-module default optimization pipeline to a pass manager.
+  ///
+  /// This provides a good default optimization pipeline for per-module
+  /// optimization and code generation without any link-time optimization. It
+  /// typically correspond to frontend "-O[123]" options for optimization
+  /// levels \c O1, \c O2 and \c O3 resp.
+  void addPerModuleDefaultPipeline(ModulePassManager &MPM,
+                                   OptimizationLevel Level,
+                                   bool DebugLogging = false);
+
+  /// \brief Add a pre-link, LTO-targeting default optimization pipeline to
+  /// a pass manager.
+  ///
+  /// This adds the pre-link optimizations tuned to work well with a later LTO
+  /// run. It works to minimize the IR which needs to be analyzed without
+  /// making irreversible decisions which could be made better during the LTO
+  /// run.
+  void addLTOPreLinkDefaultPipeline(ModulePassManager &MPM,
+                                    OptimizationLevel Level,
+                                    bool DebugLogging = false);
+
+  /// \brief Add an LTO default optimization pipeline to a pass manager.
+  ///
+  /// This provides a good default optimization pipeline for link-time
+  /// optimization and code generation. It is particularly tuned to fit well
+  /// when IR coming into the LTO phase was first run through \c
+  /// addPreLinkLTODefaultPipeline, and the two coordinate closely.
+  void addLTODefaultPipeline(ModulePassManager &MPM, OptimizationLevel Level,
+                             bool DebugLogging = false);
+
   /// \brief Parse a textual pass pipeline description into a \c ModulePassManager.
   ///
   /// The format of the textual pass pipeline description looks something like:
@@ -117,7 +233,8 @@
   bool parseAAPipeline(AAManager &AA, StringRef PipelineText);
 
 private:
-  bool parseModulePassName(ModulePassManager &MPM, StringRef Name);
+  bool parseModulePassName(ModulePassManager &MPM, StringRef Name,
+                           bool DebugLogging);
   bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name);
   bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name);
   bool parseLoopPassName(LoopPassManager &LPM, StringRef Name);
Index: llvm/trunk/lib/Passes/PassBuilder.cpp
===================================================================
--- llvm/trunk/lib/Passes/PassBuilder.cpp
+++ llvm/trunk/lib/Passes/PassBuilder.cpp
@@ -16,6 +16,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Passes/PassBuilder.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/AliasAnalysisEvaluator.h"
 #include "llvm/Analysis/AssumptionCache.h"
@@ -38,6 +39,7 @@
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/Regex.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
 #include "llvm/Transforms/IPO/FunctionAttrs.h"
@@ -53,6 +55,8 @@
 
 using namespace llvm;
 
+static Regex DefaultAliasRegex("^(default|lto-pre-link|lto)<(O[0123sz])>$");
+
 namespace {
 
 /// \brief No-op module pass which does nothing.
@@ -135,8 +139,43 @@
 #include "PassRegistry.def"
 }
 
+void PassBuilder::addPerModuleDefaultPipeline(ModulePassManager &MPM,
+                                              OptimizationLevel Level,
+                                              bool DebugLogging) {
+  // FIXME: Finish fleshing this out to match the legacy pipelines.
+  FunctionPassManager EarlyFPM(DebugLogging);
+  EarlyFPM.addPass(SimplifyCFGPass());
+  EarlyFPM.addPass(SROA());
+  EarlyFPM.addPass(EarlyCSEPass());
+  EarlyFPM.addPass(LowerExpectIntrinsicPass());
+
+  MPM.addPass(createModuleToFunctionPassAdaptor(std::move(EarlyFPM)));
+}
+
+void PassBuilder::addLTOPreLinkDefaultPipeline(ModulePassManager &MPM,
+                                               OptimizationLevel Level,
+                                               bool DebugLogging) {
+  // FIXME: We should use a customized pre-link pipeline!
+  addPerModuleDefaultPipeline(MPM, Level, DebugLogging);
+}
+
+void PassBuilder::addLTODefaultPipeline(ModulePassManager &MPM,
+                                        OptimizationLevel Level,
+                                        bool DebugLogging) {
+  // FIXME: Finish fleshing this out to match the legacy LTO pipelines.
+  FunctionPassManager LateFPM(DebugLogging);
+  LateFPM.addPass(InstCombinePass());
+  LateFPM.addPass(SimplifyCFGPass());
+
+  MPM.addPass(createModuleToFunctionPassAdaptor(std::move(LateFPM)));
+}
+
 #ifndef NDEBUG
 static bool isModulePassName(StringRef Name) {
+  // Manually handle aliases for pre-configured pipeline fragments.
+  if (Name.startswith("default") || Name.startswith("lto"))
+    return DefaultAliasRegex.match(Name);
+
 #define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) return true;
 #define MODULE_ANALYSIS(NAME, CREATE_PASS)                                     \
   if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">")           \
@@ -177,7 +216,34 @@
   return false;
 }
 
-bool PassBuilder::parseModulePassName(ModulePassManager &MPM, StringRef Name) {
+bool PassBuilder::parseModulePassName(ModulePassManager &MPM, StringRef Name,
+                                      bool DebugLogging) {
+  // Manually handle aliases for pre-configured pipeline fragments.
+  if (Name.startswith("default") || Name.startswith("lto")) {
+    SmallVector<StringRef, 3> Matches;
+    if (!DefaultAliasRegex.match(Name, &Matches))
+      return false;
+    assert(Matches.size() == 3 && "Must capture two matched strings!");
+
+    auto L = StringSwitch<OptimizationLevel>(Matches[2])
+                 .Case("O0", O0)
+                 .Case("O1", O1)
+                 .Case("O2", O2)
+                 .Case("O3", O3)
+                 .Case("Os", Os)
+                 .Case("Oz", Oz);
+
+    if (Matches[1] == "default") {
+      addPerModuleDefaultPipeline(MPM, L, DebugLogging);
+    } else if (Matches[1] == "lto-pre-link") {
+      addLTOPreLinkDefaultPipeline(MPM, L, DebugLogging);
+    } else {
+      assert(Matches[1] == "lto" && "Not one of the matched options!");
+      addLTODefaultPipeline(MPM, L, DebugLogging);
+    }
+    return true;
+  }
+
 #define MODULE_PASS(NAME, CREATE_PASS)                                         \
   if (Name == NAME) {                                                          \
     MPM.addPass(CREATE_PASS);                                                  \
@@ -475,7 +541,7 @@
     } else {
       // Otherwise try to parse a pass name.
       size_t End = PipelineText.find_first_of(",)");
-      if (!parseModulePassName(MPM, PipelineText.substr(0, End)))
+      if (!parseModulePassName(MPM, PipelineText.substr(0, End), DebugLogging))
         return false;
       if (VerifyEachPass)
         MPM.addPass(VerifierPass());
Index: llvm/trunk/test/Other/new-pass-manager.ll
===================================================================
--- llvm/trunk/test/Other/new-pass-manager.ll
+++ llvm/trunk/test/Other/new-pass-manager.ll
@@ -315,6 +315,37 @@
 ; CHECK-AA: Running analysis: BasicAA
 ; CHECK-AA: Finished llvm::Module pass manager run
 
+; RUN: opt -disable-output -disable-verify -debug-pass-manager \
+; RUN:     -passes='default<O0>' %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-O2
+; RUN: opt -disable-output -disable-verify -debug-pass-manager \
+; RUN:     -passes='default<O1>' %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-O2
+; RUN: opt -disable-output -disable-verify -debug-pass-manager \
+; RUN:     -passes='default<O2>' %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-O2
+; RUN: opt -disable-output -disable-verify -debug-pass-manager \
+; RUN:     -passes='default<Os>' %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-O2
+; RUN: opt -disable-output -disable-verify -debug-pass-manager \
+; RUN:     -passes='default<Oz>' %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-O2
+; RUN: opt -disable-output -disable-verify -debug-pass-manager \
+; RUN:     -passes='lto-pre-link<O2>' %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-O2
+; CHECK-O2: Starting llvm::Module pass manager run
+; CHECK-O2: Running pass: SimplifyCFGPass
+; CHECK-O2: Running pass: SROA
+; CHECK-O2: Running pass: EarlyCSEPass
+; CHECK-O2: Running pass: LowerExpectIntrinsicPass
+
+; RUN: opt -disable-output -disable-verify -debug-pass-manager \
+; RUN:     -passes='lto<O2>' %s 2>&1 \
+; RUN:     | FileCheck %s --check-prefix=CHECK-LTO-O2
+; CHECK-LTO-O2: Starting llvm::Module pass manager run
+; CHECK-LTO-O2: Running pass: InstCombinePass
+; CHECK-LTO-O2: Running pass: SimplifyCFGPass
+
 define void @foo() {
   ret void
 }