diff --git a/llvm/include/llvm/CodeGen/MachinePassManager.h b/llvm/include/llvm/CodeGen/MachinePassManager.h
new file mode 100644
--- /dev/null
+++ b/llvm/include/llvm/CodeGen/MachinePassManager.h
@@ -0,0 +1,220 @@
+//===- PassManager.h --- Pass management for CodeGen ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This header defines the pass manager interface for codegen. The codegen
+// pipeline consists of only machine function passes. There is no container
+// relationship between IR module/function and machine function in terms of pass
+// manager organization. So there is no need for adaptor classes (for example
+// ModuleToMachineFunctionAdaptor). Since invalidation could only happen among
+// machine function passes, there is no proxy classes to handle cross-IR-unit
+// invalidation. IR analysis results are provided for machine function passes by
+// their respective analysis managers such as ModuleAnalysisManager and
+// FunctionAnalysisManager.
+//
+// `doInitilization`/`doFinalization` are available like they do in legacy pass
+// manager. This is for machine function passes to work on module level
+// constructs. One such pass is AsmPrinter.
+//
+// Machine pass could also run over the module (call it machine module pass
+// here). Passes using this API includes MachineOutliner, MachineDebugify etc..
+//
+// TODO: Add MachineFunctionProperties support.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_PASS_MANAGER_H
+#define LLVM_CODEGEN_PASS_MANAGER_H
+
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/type_traits.h"
+
+namespace llvm {
+class Module;
+
+extern template class AnalysisManager<MachineFunction>;
+
+/// A AnalysisManager<MachineFunction> that also exposes IR analysis results.
+class MachineFunctionAnalysisManager : public AnalysisManager<MachineFunction> {
+public:
+  using Base = AnalysisManager<MachineFunction>;
+
+  MachineFunctionAnalysisManager() : Base(false), FAM(nullptr), MAM(nullptr) {}
+  MachineFunctionAnalysisManager(FunctionAnalysisManager &FAM,
+                                 ModuleAnalysisManager &MAM,
+                                 bool DebugLogging = false)
+      : Base(DebugLogging), FAM(&FAM), MAM(&MAM) {}
+  MachineFunctionAnalysisManager(MachineFunctionAnalysisManager &&) = default;
+  MachineFunctionAnalysisManager &
+  operator=(MachineFunctionAnalysisManager &&) = default;
+
+  // Register additional IR function analysis
+  template <typename PassBuilderT>
+  bool registerFunctionAnalysisPass(PassBuilderT &&PassBuilder) {
+    return FAM->registerPass(PassBuilder);
+  }
+
+  // Register additional IR module analysis
+  template <typename PassBuilderT>
+  bool registerModuleAnalysisPass(PassBuilderT &&PassBuilder) {
+    return MAM->registerPass(PassBuilder);
+  }
+
+  // Query IR function analysis
+  template <typename PassT>
+  typename PassT::Result &getResult(const Function &F) {
+    return FAM->getResult<PassT>(const_cast<Function &>(F));
+  }
+  template <typename PassT>
+  typename PassT::Result *getCachedResult(const Function &F) {
+    return FAM->getCachedResult<PassT>(const_cast<Function &>(F));
+  }
+
+  // Query IR module analysis
+  template <typename PassT> typename PassT::Result &getResult(const Module &M) {
+    return MAM->getResult<PassT>(const_cast<Module &>(M));
+  }
+  template <typename PassT>
+  typename PassT::Result *getCachedResult(const Module &M) {
+    return MAM->getCachedResult<PassT>(const_cast<Module &>(M));
+  }
+
+  // Query machine function analysis
+  using Base::getCachedResult;
+  using Base::getResult;
+
+private:
+  // FIXME: Add LoopAnalysisManager or CGSCCAnalysisManager if needed.
+  FunctionAnalysisManager *FAM;
+  ModuleAnalysisManager *MAM;
+};
+
+extern template class PassManager<MachineFunction>;
+
+class MachineFunctionPassManager
+    : public PassManager<MachineFunction, MachineFunctionAnalysisManager> {
+  using Base = PassManager<MachineFunction, MachineFunctionAnalysisManager>;
+
+public:
+  MachineFunctionPassManager(bool DebugLogging = false,
+                             bool RequireCodeGenSCCOrder = false)
+      : Base(DebugLogging), RequireCodeGenSCCOrder(RequireCodeGenSCCOrder) {}
+  MachineFunctionPassManager(MachineFunctionPassManager &&) = default;
+  MachineFunctionPassManager &
+  operator=(MachineFunctionPassManager &&) = default;
+
+  /// Entry point for codegen.
+  Error run(Module &M, MachineFunctionAnalysisManager &MFAM);
+
+  template <typename PassT> void addPass(PassT &&Pass) {
+    Base::addPass(std::forward<PassT>(Pass));
+    PassConceptT *P = Passes.back().get();
+    addDoInitialization<PassT>(P);
+    addDoFinalization<PassT>(P);
+
+    // Add machine module pass.
+    // Machine module pass need to define a method:
+    // `Error run(Module &, MachineFunctionAnalysisManager &)`.
+    // FIXME: machine module passes still need the usual machine function pass
+    //        interface, namely,
+    //        `PreservedAnalyses run(MachineFunction &,
+    //                               MachineFunctionAnalysisManager &)`
+    //        But this interface wouldn't be executed. It is just a placeholder
+    //        to satisfy the pass manager type-erased inteface. This
+    //        special-casing of machine module pass is due to its limited use
+    //        cases and the unnecessary complexity it may bring to the machine
+    //        pass manager.
+    addRunOnModule<PassT>(P);
+  }
+
+private:
+  template <typename PassT>
+  using has_init_t = decltype(std::declval<PassT &>().doInitialization(
+      std::declval<Module &>(),
+      std::declval<MachineFunctionAnalysisManager &>()));
+
+  template <typename PassT>
+  std::enable_if_t<!is_detected<has_init_t, PassT>::value>
+  addDoInitialization(PassConceptT *Pass) {}
+
+  template <typename PassT>
+  std::enable_if_t<is_detected<has_init_t, PassT>::value>
+  addDoInitialization(PassConceptT *Pass) {
+    using PassModelT =
+        detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
+                          MachineFunctionAnalysisManager>;
+    auto *P = static_cast<PassModelT *>(Pass);
+    InitializationFuncs.emplace_back(
+        [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
+          return P->Pass.doInitialization(M, MFAM);
+        });
+  }
+
+  template <typename PassT>
+  using has_fini_t = decltype(std::declval<PassT &>().doFinalization(
+      std::declval<Module &>(),
+      std::declval<MachineFunctionAnalysisManager &>()));
+
+  template <typename PassT>
+  std::enable_if_t<!is_detected<has_fini_t, PassT>::value>
+  addDoFinalization(PassConceptT *Pass) {}
+
+  template <typename PassT>
+  std::enable_if_t<is_detected<has_fini_t, PassT>::value>
+  addDoFinalization(PassConceptT *Pass) {
+    using PassModelT =
+        detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
+                          MachineFunctionAnalysisManager>;
+    auto *P = static_cast<PassModelT *>(Pass);
+    FinalizationFuncs.emplace_back(
+        [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
+          return P->Pass.doFinalization(M, MFAM);
+        });
+  }
+
+  template <typename PassT>
+  using is_machine_module_pass_t = decltype(std::declval<PassT &>().run(
+      std::declval<Module &>(),
+      std::declval<MachineFunctionAnalysisManager &>()));
+
+  template <typename PassT>
+  std::enable_if_t<!is_detected<is_machine_module_pass_t, PassT>::value>
+  addRunOnModule(PassConceptT *Pass) {}
+
+  template <typename PassT>
+  std::enable_if_t<is_detected<is_machine_module_pass_t, PassT>::value>
+  addRunOnModule(PassConceptT *Pass) {
+    using PassModelT =
+        detail::PassModel<MachineFunction, PassT, PreservedAnalyses,
+                          MachineFunctionAnalysisManager>;
+    auto *P = static_cast<PassModelT *>(Pass);
+    HasRunOnModulePasses.emplace(
+        Passes.size() - 1,
+        [=](Module &M, MachineFunctionAnalysisManager &MFAM) {
+          return P->Pass.run(M, MFAM);
+        });
+  }
+
+  using FuncTy = Error(Module &, MachineFunctionAnalysisManager &);
+  SmallVector<llvm::unique_function<FuncTy>, 4> InitializationFuncs;
+  SmallVector<llvm::unique_function<FuncTy>, 4> FinalizationFuncs;
+
+  // A set of `Passes` indexes where matching pass has defined `run(Module&,..)`
+  using PassIndex = decltype(Passes)::size_type;
+  std::map<PassIndex, llvm::unique_function<FuncTy>> HasRunOnModulePasses;
+
+  // Force codegen to run according to the callgraph.
+  bool RequireCodeGenSCCOrder;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_CODEGEN_PASS_MANAGER_H
diff --git a/llvm/include/llvm/IR/PassManager.h b/llvm/include/llvm/IR/PassManager.h
--- a/llvm/include/llvm/IR/PassManager.h
+++ b/llvm/include/llvm/IR/PassManager.h
@@ -560,6 +560,8 @@
   }
 
   static bool isSkippable() { return false; }
+
+protected:
   using PassConceptT =
       detail::PassConcept<IRUnitT, AnalysisManagerT, ExtraArgTs...>;
 
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -92,6 +92,7 @@
   MachineOperand.cpp
   MachineOptimizationRemarkEmitter.cpp
   MachineOutliner.cpp
+  MachinePassManager.cpp
   MachinePipeliner.cpp
   MachinePostDominators.cpp
   MachineRegionInfo.cpp
diff --git a/llvm/lib/CodeGen/LLVMBuild.txt b/llvm/lib/CodeGen/LLVMBuild.txt
--- a/llvm/lib/CodeGen/LLVMBuild.txt
+++ b/llvm/lib/CodeGen/LLVMBuild.txt
@@ -21,4 +21,4 @@
 type = Library
 name = CodeGen
 parent = Libraries
-required_libraries = Analysis BitReader BitWriter Core MC ProfileData Scalar Support Target TransformUtils
+required_libraries = Analysis BitReader BitWriter Core MC Passes ProfileData Scalar Support Target TransformUtils
diff --git a/llvm/lib/CodeGen/MachinePassManager.cpp b/llvm/lib/CodeGen/MachinePassManager.cpp
new file mode 100644
--- /dev/null
+++ b/llvm/lib/CodeGen/MachinePassManager.cpp
@@ -0,0 +1,90 @@
+//===---------- MachinePassManager.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the pass management machinery for machine functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MachinePassManager.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/PassManagerImpl.h"
+
+using namespace llvm;
+
+namespace llvm {
+template class AllAnalysesOn<MachineFunction>;
+template class AnalysisManager<MachineFunction>;
+template class PassManager<MachineFunction>;
+
+Error MachineFunctionPassManager::run(Module &M,
+                                      MachineFunctionAnalysisManager &MFAM) {
+  // MachineModuleAnalysis is a module analysis pass that is never invalidated
+  // because we don't run any module pass in codegen pipeline. This is very
+  // important because the codegen state is stored in MMI which is the analysis
+  // result of MachineModuleAnalysis. MMI should not be recomputed.
+  auto &MMI = MFAM.getResult<MachineModuleAnalysis>(M);
+
+  // TODO: implement RequireCodeGenSCCOrder
+  (void)RequireCodeGenSCCOrder;
+
+  if (DebugLogging)
+    dbgs() << "Starting " << getTypeName<MachineFunction>()
+           << " pass manager run.\n";
+
+  for (auto &F : InitializationFuncs)
+    if (auto Err = F(M, MFAM))
+      return Err;
+
+  for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
+    auto *P = Passes[Idx].get();
+
+    // Run machine moulde passes
+    if (HasRunOnModulePasses.count(Idx)) {
+      if (DebugLogging)
+        dbgs() << "Running pass: " << P->name() << " on " << M.getName()
+               << "\n";
+      if (auto Err = HasRunOnModulePasses.at(Idx)(M, MFAM))
+        return Err;
+      else
+        continue;
+    }
+
+    for (Function &F : M) {
+      // Do not codegen any 'available_externally' functions at all, they have
+      // definitions outside the translation unit.
+      if (F.hasAvailableExternallyLinkage())
+        continue;
+
+      MachineFunction &MF = MMI.getOrCreateMachineFunction(F);
+      PassInstrumentation PI = MFAM.getResult<PassInstrumentationAnalysis>(MF);
+      if (!PI.runBeforePass<MachineFunction>(*P, MF))
+        continue;
+
+      if (DebugLogging)
+        dbgs() << "Running pass: " << P->name() << " on " << MF.getName()
+               << "\n";
+
+      // TODO: EmitSizeRemarks
+      PreservedAnalyses PassPA = P->run(MF, MFAM);
+      PI.runAfterPass(*P, MF);
+      MFAM.invalidate(MF, PassPA);
+    }
+  }
+
+  for (auto &F : FinalizationFuncs)
+    if (auto Err = F(M, MFAM))
+      return Err;
+
+  if (DebugLogging)
+    dbgs() << "Finished " << getTypeName<MachineFunction>()
+           << " pass manager run.\n";
+
+  return Error::success();
+}
+
+} // namespace llvm
diff --git a/llvm/unittests/CodeGen/CMakeLists.txt b/llvm/unittests/CodeGen/CMakeLists.txt
--- a/llvm/unittests/CodeGen/CMakeLists.txt
+++ b/llvm/unittests/CodeGen/CMakeLists.txt
@@ -7,6 +7,7 @@
   Core
   MC
   MIRParser
+  Passes
   SelectionDAG
   Support
   Target
@@ -20,6 +21,7 @@
   MachineInstrBundleIteratorTest.cpp
   MachineInstrTest.cpp
   MachineOperandTest.cpp
+  PassManagerTest.cpp
   ScalableVectorMVTsTest.cpp
   TypeTraitsTest.cpp
   TargetOptionsTest.cpp
diff --git a/llvm/unittests/CodeGen/PassManagerTest.cpp b/llvm/unittests/CodeGen/PassManagerTest.cpp
new file mode 100644
--- /dev/null
+++ b/llvm/unittests/CodeGen/PassManagerTest.cpp
@@ -0,0 +1,249 @@
+//===- llvm/unittest/CodeGen/PassManager.cpp - PassManager tests ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/Analysis/LoopAnalysisManager.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachinePassManager.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
+public:
+  struct Result {
+    Result(int Count) : InstructionCount(Count) {}
+    int InstructionCount;
+  };
+
+  /// Run the analysis pass over the function and return a result.
+  Result run(Function &F, FunctionAnalysisManager &AM) {
+    int Count = 0;
+    for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI)
+      for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
+           ++II)
+        ++Count;
+    return Result(Count);
+  }
+
+private:
+  friend AnalysisInfoMixin<TestFunctionAnalysis>;
+  static AnalysisKey Key;
+};
+
+AnalysisKey TestFunctionAnalysis::Key;
+
+class TestMachineFunctionAnalysis
+    : public AnalysisInfoMixin<TestMachineFunctionAnalysis> {
+public:
+  struct Result {
+    Result(int Count) : InstructionCount(Count) {}
+    int InstructionCount;
+  };
+
+  /// Run the analysis pass over the machine function and return a result.
+  Result run(MachineFunction &MF, MachineFunctionAnalysisManager::Base &AM) {
+    auto &MFAM = static_cast<MachineFunctionAnalysisManager &>(AM);
+    // Query function analysis result.
+    TestFunctionAnalysis::Result &FAR =
+        MFAM.getResult<TestFunctionAnalysis>(MF.getFunction());
+    // + 5
+    return FAR.InstructionCount;
+  }
+
+private:
+  friend AnalysisInfoMixin<TestMachineFunctionAnalysis>;
+  static AnalysisKey Key;
+};
+
+AnalysisKey TestMachineFunctionAnalysis::Key;
+
+struct TestMachineFunctionPass : public PassInfoMixin<TestMachineFunctionPass> {
+  TestMachineFunctionPass(int &Count, int &BeforeInitialization,
+                          int &BeforeFinalization,
+                          int &MachineFunctionPassCount)
+      : Count(Count), BeforeInitialization(BeforeInitialization),
+        BeforeFinalization(BeforeFinalization),
+        MachineFunctionPassCount(MachineFunctionPassCount) {}
+
+  Error doInitialization(Module &M, MachineFunctionAnalysisManager &MFAM) {
+    // + 1
+    ++Count;
+    BeforeInitialization = Count;
+    return Error::success();
+  }
+  Error doFinalization(Module &M, MachineFunctionAnalysisManager &MFAM) {
+    // + 1
+    ++Count;
+    BeforeFinalization = Count;
+    return Error::success();
+  }
+
+  PreservedAnalyses run(MachineFunction &MF,
+                        MachineFunctionAnalysisManager &MFAM) {
+    // Query function analysis result.
+    TestFunctionAnalysis::Result &FAR =
+        MFAM.getResult<TestFunctionAnalysis>(MF.getFunction());
+    // + 5
+    Count += FAR.InstructionCount;
+
+    // Query module analysis result.
+    MachineModuleInfo &MMI =
+        MFAM.getResult<MachineModuleAnalysis>(*MF.getFunction().getParent());
+    // + 3
+    Count += (MMI.getModule() == MF.getFunction().getParent());
+
+    // Query machine function analysis result.
+    TestMachineFunctionAnalysis::Result &MFAR =
+        MFAM.getResult<TestMachineFunctionAnalysis>(MF);
+    // + 5
+    Count += MFAR.InstructionCount;
+
+    MachineFunctionPassCount = Count;
+
+    return PreservedAnalyses::none();
+  }
+
+  int &Count;
+  int &BeforeInitialization;
+  int &BeforeFinalization;
+  int &MachineFunctionPassCount;
+};
+
+struct TestMachineModulePass : public PassInfoMixin<TestMachineModulePass> {
+  TestMachineModulePass(int &Count, int &MachineModulePassCount)
+      : Count(Count), MachineModulePassCount(MachineModulePassCount) {}
+
+  Error run(Module &M, MachineFunctionAnalysisManager &MFAM) {
+    MachineModuleInfo &MMI = MFAM.getResult<MachineModuleAnalysis>(M);
+    // + 1
+    Count += (MMI.getModule() == &M);
+    MachineModulePassCount = Count;
+    return Error::success();
+  }
+
+  PreservedAnalyses run(MachineFunction &MF,
+                        MachineFunctionAnalysisManager &AM) {
+    llvm_unreachable("This should never be reached. This function is a "
+                     "placeholder to make machine pass manager "
+                     "less intrusive with this feature.");
+  }
+
+  int &Count;
+  int &MachineModulePassCount;
+};
+
+std::unique_ptr<Module> parseIR(LLVMContext &Context, const char *IR) {
+  SMDiagnostic Err;
+  return parseAssemblyString(IR, Err, Context);
+}
+
+class PassManagerTest : public ::testing::Test {
+protected:
+  LLVMContext Context;
+  std::unique_ptr<Module> M;
+  std::unique_ptr<TargetMachine> TM;
+
+public:
+  PassManagerTest()
+      : M(parseIR(Context, "define void @f() {\n"
+                           "entry:\n"
+                           "  call void @g()\n"
+                           "  call void @h()\n"
+                           "  ret void\n"
+                           "}\n"
+                           "define void @g() {\n"
+                           "  ret void\n"
+                           "}\n"
+                           "define void @h() {\n"
+                           "  ret void\n"
+                           "}\n")) {
+    // MachineModuleAnalysis needs a TargetMachine instance.
+    llvm::InitializeAllTargets();
+
+    std::string Error;
+    const Target *TheTarget =
+        TargetRegistry::lookupTarget("x86_64-unknown-linux", Error);
+    // If we didn't build x86, do not run the test.
+    if (!TheTarget)
+      return;
+
+    TargetOptions Options;
+    TM.reset(TheTarget->createTargetMachine("x86_64-unknown-linux", "", "",
+                                            Options, None));
+  }
+};
+
+TEST_F(PassManagerTest, Basic) {
+  LLVMTargetMachine *LLVMTM = static_cast<LLVMTargetMachine *>(TM.get());
+  M->setDataLayout(TM->createDataLayout());
+
+  LoopAnalysisManager LAM(/*DebugLogging*/ true);
+  FunctionAnalysisManager FAM(/*DebugLogging*/ true);
+  CGSCCAnalysisManager CGAM(/*DebugLogging*/ true);
+  ModuleAnalysisManager MAM(/*DebugLogging*/ true);
+  PassBuilder PB(TM.get());
+  PB.registerModuleAnalyses(MAM);
+  PB.registerFunctionAnalyses(FAM);
+  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+  FAM.registerPass([&] { return TestFunctionAnalysis(); });
+  FAM.registerPass([&] { return PassInstrumentationAnalysis(); });
+  MAM.registerPass([&] { return MachineModuleAnalysis(LLVMTM); });
+  MAM.registerPass([&] { return PassInstrumentationAnalysis(); });
+
+  MachineFunctionAnalysisManager MFAM;
+  {
+    // Test move assignment.
+    MachineFunctionAnalysisManager NestedMFAM(FAM, MAM,
+                                              /*DebugLogging*/ true);
+    NestedMFAM.registerPass([&] { return PassInstrumentationAnalysis(); });
+    NestedMFAM.registerPass([&] { return TestMachineFunctionAnalysis(); });
+    MFAM = std::move(NestedMFAM);
+  }
+
+  int Count = 0;
+  int BeforeInitialization;
+  int BeforeFinalization;
+  int TestMachineFunctionCount;
+  int TestMachineModuleCount1;
+  int TestMachineModuleCount2;
+
+  MachineFunctionPassManager MFPM;
+  {
+    // Test move assignment.
+    MachineFunctionPassManager NestedMFPM(/*DebugLogging*/ true);
+    NestedMFPM.addPass(TestMachineModulePass(Count, TestMachineModuleCount1));
+    NestedMFPM.addPass(TestMachineFunctionPass(Count, BeforeInitialization,
+                                               BeforeFinalization,
+                                               TestMachineFunctionCount));
+    NestedMFPM.addPass(TestMachineModulePass(Count, TestMachineModuleCount2));
+    MFPM = std::move(NestedMFPM);
+  }
+
+  cantFail(MFPM.run(*M, MFAM));
+
+  EXPECT_EQ(1, BeforeInitialization);
+  EXPECT_EQ(2, TestMachineModuleCount1);
+  EXPECT_EQ(15, TestMachineFunctionCount);
+  EXPECT_EQ(16, TestMachineModuleCount2);
+  EXPECT_EQ(17, BeforeFinalization);
+  EXPECT_EQ(17, Count);
+}
+
+} // namespace