mirror of
https://github.com/intel/llvm.git
synced 2026-02-05 04:46:27 +08:00
[Coroutines][6/6] Clang schedules new passes
Summary: Depends on https://reviews.llvm.org/D71902. The last in a series of six patches that ports the LLVM coroutines passes to the new pass manager infrastructure. This patch has Clang schedule the new coroutines passes when the `-fexperimental-new-pass-manager` option is used. With this and the previous 5 patches, Clang is capable of building and successfully running the test suite of large coroutines projects such as https://github.com/lewissbaker/cppcoro with `ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER=On`. Reviewers: GorNishanov, lewissbaker, chandlerc, junparser Subscribers: EricWF, cfe-commits, llvm-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D71903
This commit is contained in:
@@ -49,6 +49,10 @@
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "llvm/Transforms/Coroutines.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/AlwaysInliner.h"
|
||||
#include "llvm/Transforms/IPO/LowerTypeTests.h"
|
||||
@@ -957,6 +961,22 @@ static PassBuilder::OptimizationLevel mapToLevel(const CodeGenOptions &Opts) {
|
||||
}
|
||||
}
|
||||
|
||||
static void addCoroutinePassesAtO0(ModulePassManager &MPM,
|
||||
const LangOptions &LangOpts,
|
||||
const CodeGenOptions &CodeGenOpts) {
|
||||
if (!LangOpts.Coroutines)
|
||||
return;
|
||||
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(CoroEarlyPass()));
|
||||
|
||||
CGSCCPassManager CGPM(CodeGenOpts.DebugPassManager);
|
||||
CGPM.addPass(CoroSplitPass());
|
||||
CGPM.addPass(createCGSCCToFunctionPassAdaptor(CoroElidePass()));
|
||||
MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM)));
|
||||
|
||||
MPM.addPass(createModuleToFunctionPassAdaptor(CoroCleanupPass()));
|
||||
}
|
||||
|
||||
static void addSanitizersAtO0(ModulePassManager &MPM,
|
||||
const Triple &TargetTriple,
|
||||
const LangOptions &LangOpts,
|
||||
@@ -1076,6 +1096,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
|
||||
PTO.LoopInterleaving = CodeGenOpts.UnrollLoops;
|
||||
PTO.LoopVectorization = CodeGenOpts.VectorizeLoop;
|
||||
PTO.SLPVectorization = CodeGenOpts.VectorizeSLP;
|
||||
PTO.Coroutines = LangOpts.Coroutines;
|
||||
|
||||
PassInstrumentationCallbacks PIC;
|
||||
StandardInstrumentations SI;
|
||||
@@ -1279,6 +1300,7 @@ void EmitAssemblyHelper::EmitAssemblyWithNewPassManager(
|
||||
}
|
||||
|
||||
if (CodeGenOpts.OptimizationLevel == 0) {
|
||||
addCoroutinePassesAtO0(MPM, LangOpts, CodeGenOpts);
|
||||
addSanitizersAtO0(MPM, TargetTriple, LangOpts, CodeGenOpts);
|
||||
}
|
||||
}
|
||||
|
||||
57
clang/test/CodeGenCoroutines/coro-newpm-pipeline.cpp
Normal file
57
clang/test/CodeGenCoroutines/coro-newpm-pipeline.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
// Tests that coroutine passes are added to and run by the new pass manager
|
||||
// pipeline, at -O0 and above.
|
||||
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null \
|
||||
// RUN: -fexperimental-new-pass-manager -fdebug-pass-manager -fcoroutines-ts \
|
||||
// RUN: -O0 %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm-bc -o /dev/null \
|
||||
// RUN: -fexperimental-new-pass-manager -fdebug-pass-manager -fcoroutines-ts \
|
||||
// RUN: -O1 %s 2>&1 | FileCheck %s
|
||||
//
|
||||
// CHECK: Starting llvm::Module pass manager run.
|
||||
// CHECK: Running pass:{{.*}}CoroEarlyPass
|
||||
//
|
||||
// The first coro-split pass enqueues a second run of the entire CGSCC pipeline.
|
||||
// CHECK: Starting CGSCC pass manager run.
|
||||
// CHECK: Running pass: CoroSplitPass on (_Z3foov)
|
||||
// CHECK: Running pass:{{.*}}CoroElidePass{{.*}} on (_Z3foov)
|
||||
// CHECK: Finished CGSCC pass manager run.
|
||||
//
|
||||
// The second coro-split pass splits coroutine 'foo' into funclets
|
||||
// 'foo.resume', 'foo.destroy', and 'foo.cleanup'.
|
||||
// CHECK: Starting CGSCC pass manager run.
|
||||
// CHECK: Running pass: CoroSplitPass on (_Z3foov)
|
||||
// CHECK: Running pass:{{.*}}CoroElidePass{{.*}} on (_Z3foov)
|
||||
// CHECK: Finished CGSCC pass manager run.
|
||||
//
|
||||
// CHECK: Running pass:{{.*}}CoroCleanupPass
|
||||
// CHECK: Finished llvm::Module pass manager run.
|
||||
|
||||
namespace std {
|
||||
namespace experimental {
|
||||
|
||||
struct handle {};
|
||||
|
||||
struct awaitable {
|
||||
bool await_ready() { return true; }
|
||||
void await_suspend(handle) {}
|
||||
bool await_resume() { return true; }
|
||||
};
|
||||
|
||||
template <typename T> struct coroutine_handle {
|
||||
static handle from_address(void *address) { return {}; }
|
||||
};
|
||||
|
||||
template <typename T = void> struct coroutine_traits {
|
||||
struct promise_type {
|
||||
awaitable initial_suspend() { return {}; }
|
||||
awaitable final_suspend() { return {}; }
|
||||
void return_void() {}
|
||||
T get_return_object() { return T(); }
|
||||
void unhandled_exception() {}
|
||||
};
|
||||
};
|
||||
} // namespace experimental
|
||||
} // namespace std
|
||||
|
||||
void foo() { co_return; }
|
||||
Reference in New Issue
Block a user