diff --git a/llvm/include/llvm/Transforms/Coroutines.h b/llvm/include/llvm/Transforms/Coroutines.h
--- a/llvm/include/llvm/Transforms/Coroutines.h
+++ b/llvm/include/llvm/Transforms/Coroutines.h
@@ -14,11 +14,15 @@
 namespace llvm {
 
 class Pass;
+class PassBuilder;
 class PassManagerBuilder;
 
 /// Add all coroutine passes to appropriate extension points.
 void addCoroutinePassesToExtensionPoints(PassManagerBuilder &Builder);
 
+/// Register a callback to parse coroutines passes in a pass pipeline.
+void registerCoroutinesPasses(PassBuilder &Builder);
+
 /// Lower coroutine intrinsics that are not needed by later passes.
 Pass *createCoroEarlyLegacyPass();
 
diff --git a/llvm/lib/Transforms/Coroutines/Coroutines.cpp b/llvm/lib/Transforms/Coroutines/Coroutines.cpp
--- a/llvm/lib/Transforms/Coroutines/Coroutines.cpp
+++ b/llvm/lib/Transforms/Coroutines/Coroutines.cpp
@@ -31,8 +31,13 @@
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Type.h"
 #include "llvm/InitializePasses.h"
+#include "llvm/Passes/PassBuilder.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Transforms/Coroutines/CoroCleanup.h"
+#include "llvm/Transforms/Coroutines/CoroEarly.h"
+#include "llvm/Transforms/Coroutines/CoroElide.h"
+#include "llvm/Transforms/Coroutines/CoroSplit.h"
 #include "llvm/Transforms/IPO.h"
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 #include "llvm/Transforms/Utils/Local.h"
@@ -91,6 +96,22 @@
                        addCoroutineOptimizerLastPasses);
 }
 
+void llvm::registerCoroutinesPasses(PassBuilder &Builder) {
+  Builder.registerPipelineParsingCallback(
+      [](StringRef Name, ModulePassManager &MPM,
+         ArrayRef<PassBuilder::PipelineElement>) {
+        if (Name == "coroutines") {
+          MPM.addPass(createModuleToFunctionPassAdaptor(CoroEarlyPass()));
+          MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(CoroSplitPass()));
+          MPM.addPass(createModuleToFunctionPassAdaptor(CoroElidePass()));
+          MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(CoroSplitPass()));
+          MPM.addPass(createModuleToFunctionPassAdaptor(CoroCleanupPass()));
+          return true;
+        }
+        return false;
+      });
+}
+
 // Construct the lowerer base class and initialize its members.
 coro::LowererBase::LowererBase(Module &M)
     : TheModule(M), Context(M.getContext()),
diff --git a/llvm/test/Transforms/Coroutines/coro-cleanup.ll b/llvm/test/Transforms/Coroutines/coro-cleanup.ll
--- a/llvm/test/Transforms/Coroutines/coro-cleanup.ll
+++ b/llvm/test/Transforms/Coroutines/coro-cleanup.ll
@@ -1,5 +1,6 @@
 ; Make sure that all library helper coro intrinsics are lowered.
 ; RUN: opt < %s -O0 -enable-coroutines -S | FileCheck %s
+; RUN: opt < %s -passes='coroutines' -S | FileCheck %s
 
 ; CHECK-LABEL: @uses_library_support_coro_intrinsics(
 ; CHECK-NOT:     @llvm.coro
diff --git a/llvm/test/Transforms/Coroutines/restart-trigger.ll b/llvm/test/Transforms/Coroutines/restart-trigger.ll
--- a/llvm/test/Transforms/Coroutines/restart-trigger.ll
+++ b/llvm/test/Transforms/Coroutines/restart-trigger.ll
@@ -3,6 +3,7 @@
 ; REQUIRES: asserts
 ; RUN: opt < %s -S -O0 -enable-coroutines -debug-only=coro-split 2>&1 | FileCheck %s
 ; RUN: opt < %s -S -O1 -enable-coroutines -debug-only=coro-split 2>&1 | FileCheck %s
+; RUN: opt < %s -S -passes=coroutines -debug-only=coro-split 2>&1 | FileCheck %s
 
 ; CHECK:      CoroSplit: Processing coroutine 'f' state: 0
 ; CHECK-NEXT: CoroSplit: Processing coroutine 'f' state: 1
diff --git a/llvm/test/Transforms/Coroutines/smoketest.ll b/llvm/test/Transforms/Coroutines/smoketest.ll
--- a/llvm/test/Transforms/Coroutines/smoketest.ll
+++ b/llvm/test/Transforms/Coroutines/smoketest.ll
@@ -9,6 +9,11 @@
 ; RUN:     -coro-early -coro-split -coro-elide -coro-cleanup 2>&1 | FileCheck %s
 ; RUN: opt < %s -disable-output -debug-pass=Arguments 2>&1 \
 ; RUN:     | FileCheck %s -check-prefix=NOCORO
+; RUN: opt < %s -disable-output -passes=coroutines -debug-pass-manager 2>&1 \
+; RUN:     | FileCheck %s -check-prefix=NEWPM
+; RUN: opt < %s -disable-output \
+; RUN:     -passes='coroutines,function(coro-early),cgscc(coro-split),function(coro-elide,coro-cleanup)' \
+; RUN:     -debug-pass-manager 2>&1 | FileCheck %s -check-prefix=NEWPM
 
 ; CHECK: coro-early
 ; CHECK: coro-split
@@ -20,6 +25,11 @@
 ; NOCORO-NOT: coro-elide
 ; NOCORO-NOT: coro-cleanup
 
+; NEWPM: CoroEarlyPass
+; NEWPM: CoroSplitPass
+; NEWPM: CoroElidePass
+; NEWPM: CoroCleanupPass
+
 define void @foo() {
   ret void
 }
diff --git a/llvm/tools/opt/NewPMDriver.cpp b/llvm/tools/opt/NewPMDriver.cpp
--- a/llvm/tools/opt/NewPMDriver.cpp
+++ b/llvm/tools/opt/NewPMDriver.cpp
@@ -32,6 +32,7 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/Coroutines.h"
 #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
 #include "llvm/Transforms/Scalar/LoopPassManager.h"
 #include "llvm/Transforms/Utils/Debugify.h"
@@ -290,6 +291,9 @@
         return false;
       });
 
+  // Register a callback that creates coroutines lowering passes as needed.
+  registerCoroutinesPasses(PB);
+
 #ifdef LINK_POLLY_INTO_TOOLS
   polly::RegisterPollyPasses(PB);
 #endif