Index: llvm/bindings/go/llvm/transforms_pmbuilder.go =================================================================== --- llvm/bindings/go/llvm/transforms_pmbuilder.go +++ llvm/bindings/go/llvm/transforms_pmbuilder.go @@ -66,7 +66,3 @@ func (pmb PassManagerBuilder) UseInlinerWithThreshold(threshold uint) { C.LLVMPassManagerBuilderUseInlinerWithThreshold(pmb.C, C.uint(threshold)) } - -func (pmb PassManagerBuilder) AddCoroutinePassesToExtensionPoints() { - C.LLVMPassManagerBuilderAddCoroutinePassesToExtensionPoints(pmb.C); -} Index: llvm/include/llvm-c/Transforms/Coroutines.h =================================================================== --- llvm/include/llvm-c/Transforms/Coroutines.h +++ /dev/null @@ -1,56 +0,0 @@ -/*===-- Coroutines.h - Coroutines Library C Interface -----------*- 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 declares the C interface to libLLVMCoroutines.a, which *| -|* implements various scalar transformations of the LLVM IR. *| -|* *| -|* Many exotic languages can interoperate with C code but have a harder time *| -|* with C++ due to name mangling. So in addition to C, this interface enables *| -|* tools written in such languages. *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#ifndef LLVM_C_TRANSFORMS_COROUTINES_H -#define LLVM_C_TRANSFORMS_COROUTINES_H - -#include "llvm-c/ExternC.h" -#include "llvm-c/Types.h" -#include "llvm-c/Transforms/PassManagerBuilder.h" - -LLVM_C_EXTERN_C_BEGIN - -/** - * @defgroup LLVMCTransformsCoroutines Coroutine transformations - * @ingroup LLVMCTransforms - * - * @{ - */ - -/** See llvm::createCoroEarlyLegacyPass function. */ -void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM); - -/** See llvm::createCoroSplitLegacyPass function. */ -void LLVMAddCoroSplitPass(LLVMPassManagerRef PM); - -/** See llvm::createCoroElideLegacyPass function. */ -void LLVMAddCoroElidePass(LLVMPassManagerRef PM); - -/** See llvm::createCoroCleanupLegacyPass function. */ -void LLVMAddCoroCleanupPass(LLVMPassManagerRef PM); - -/** See llvm::addCoroutinePassesToExtensionPoints. */ -void LLVMPassManagerBuilderAddCoroutinePassesToExtensionPoints(LLVMPassManagerBuilderRef PMB); - -/** - * @} - */ - -LLVM_C_EXTERN_C_END - -#endif Index: llvm/include/llvm/InitializePasses.h =================================================================== --- llvm/include/llvm/InitializePasses.h +++ llvm/include/llvm/InitializePasses.h @@ -48,9 +48,6 @@ /// Initialize all passes linked into the Analysis library. void initializeAnalysis(PassRegistry&); -/// Initialize all passes linked into the Coroutines library. -void initializeCoroutines(PassRegistry&); - /// Initialize all passes linked into the CodeGen library. void initializeCodeGen(PassRegistry&); Index: llvm/include/llvm/Transforms/Coroutines.h =================================================================== --- llvm/include/llvm/Transforms/Coroutines.h +++ /dev/null @@ -1,37 +0,0 @@ -//===-- Coroutines.h - Coroutine Transformations ----------------*- 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 -// -//===----------------------------------------------------------------------===// -// Declare accessor functions for coroutine lowering passes. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_TRANSFORMS_COROUTINES_H -#define LLVM_TRANSFORMS_COROUTINES_H - -namespace llvm { - -class Pass; -class PassManagerBuilder; - -/// Add all coroutine passes to appropriate extension points. -void addCoroutinePassesToExtensionPoints(PassManagerBuilder &Builder); - -/// Lower coroutine intrinsics that are not needed by later passes. -Pass *createCoroEarlyLegacyPass(); - -/// Split up coroutines into multiple functions driving their state machines. -Pass *createCoroSplitLegacyPass(bool IsOptimizing = false); - -/// Analyze coroutines use sites, devirtualize resume/destroy calls and elide -/// heap allocation for coroutine frame where possible. -Pass *createCoroElideLegacyPass(); - -/// Lower all remaining coroutine intrinsics. -Pass *createCoroCleanupLegacyPass(); - -} - -#endif Index: llvm/lib/Transforms/Coroutines/CoroCleanup.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroCleanup.cpp +++ llvm/lib/Transforms/Coroutines/CoroCleanup.cpp @@ -141,41 +141,3 @@ return PreservedAnalyses::none(); } - -namespace { - -struct CoroCleanupLegacy : FunctionPass { - static char ID; // Pass identification, replacement for typeid - - CoroCleanupLegacy() : FunctionPass(ID) { - initializeCoroCleanupLegacyPass(*PassRegistry::getPassRegistry()); - } - - std::unique_ptr<Lowerer> L; - - // This pass has work to do only if we find intrinsics we are going to lower - // in the module. - bool doInitialization(Module &M) override { - if (declaresCoroCleanupIntrinsics(M)) - L = std::make_unique<Lowerer>(M); - return false; - } - - bool runOnFunction(Function &F) override { - if (L) - return L->lowerRemainingCoroIntrinsics(F); - return false; - } - void getAnalysisUsage(AnalysisUsage &AU) const override { - if (!L) - AU.setPreservesAll(); - } - StringRef getPassName() const override { return "Coroutine Cleanup"; } -}; -} - -char CoroCleanupLegacy::ID = 0; -INITIALIZE_PASS(CoroCleanupLegacy, "coro-cleanup", - "Lower all coroutine related intrinsics", false, false) - -Pass *llvm::createCoroCleanupLegacyPass() { return new CoroCleanupLegacy(); } Index: llvm/lib/Transforms/Coroutines/CoroEarly.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroEarly.cpp +++ llvm/lib/Transforms/Coroutines/CoroEarly.cpp @@ -247,43 +247,3 @@ PA.preserveSet<CFGAnalyses>(); return PA; } - -namespace { - -struct CoroEarlyLegacy : public FunctionPass { - static char ID; // Pass identification, replacement for typeid. - CoroEarlyLegacy() : FunctionPass(ID) { - initializeCoroEarlyLegacyPass(*PassRegistry::getPassRegistry()); - } - - std::unique_ptr<Lowerer> L; - - // This pass has work to do only if we find intrinsics we are going to lower - // in the module. - bool doInitialization(Module &M) override { - if (declaresCoroEarlyIntrinsics(M)) - L = std::make_unique<Lowerer>(M); - return false; - } - - bool runOnFunction(Function &F) override { - if (!L) - return false; - - return L->lowerEarlyIntrinsics(F); - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - } - StringRef getPassName() const override { - return "Lower early coroutine intrinsics"; - } -}; -} - -char CoroEarlyLegacy::ID = 0; -INITIALIZE_PASS(CoroEarlyLegacy, "coro-early", - "Lower early coroutine intrinsics", false, false) - -Pass *llvm::createCoroEarlyLegacyPass() { return new CoroEarlyLegacy(); } Index: llvm/lib/Transforms/Coroutines/CoroElide.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroElide.cpp +++ llvm/lib/Transforms/Coroutines/CoroElide.cpp @@ -370,26 +370,6 @@ return true; } -// See if there are any coro.subfn.addr instructions referring to coro.devirt -// trigger, if so, replace them with a direct call to devirt trigger function. -static bool replaceDevirtTrigger(Function &F) { - SmallVector<CoroSubFnInst *, 1> DevirtAddr; - for (auto &I : instructions(F)) - if (auto *SubFn = dyn_cast<CoroSubFnInst>(&I)) - if (SubFn->getIndex() == CoroSubFnInst::RestartTrigger) - DevirtAddr.push_back(SubFn); - - if (DevirtAddr.empty()) - return false; - - Module &M = *F.getParent(); - Function *DevirtFn = M.getFunction(CORO_DEVIRT_TRIGGER_FN); - assert(DevirtFn && "coro.devirt.fn not found"); - replaceWithConstant(DevirtFn, DevirtAddr); - - return true; -} - static bool declaresCoroElideIntrinsics(Module &M) { return coro::declaresIntrinsics(M, {"llvm.coro.id", "llvm.coro.id.async"}); } @@ -415,62 +395,3 @@ return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); } - -namespace { -struct CoroElideLegacy : FunctionPass { - static char ID; - CoroElideLegacy() : FunctionPass(ID) { - initializeCoroElideLegacyPass(*PassRegistry::getPassRegistry()); - } - - std::unique_ptr<Lowerer> L; - - bool doInitialization(Module &M) override { - if (declaresCoroElideIntrinsics(M)) - L = std::make_unique<Lowerer>(M); - return false; - } - - bool runOnFunction(Function &F) override { - if (!L) - return false; - - bool Changed = false; - - if (F.hasFnAttribute(CORO_PRESPLIT_ATTR)) - Changed = replaceDevirtTrigger(F); - - L->CoroIds.clear(); - L->collectPostSplitCoroIds(&F); - // If we did not find any coro.id, there is nothing to do. - if (L->CoroIds.empty()) - return Changed; - - AAResults &AA = getAnalysis<AAResultsWrapperPass>().getAAResults(); - DominatorTree &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - - for (auto *CII : L->CoroIds) - Changed |= L->processCoroId(CII, AA, DT); - - return Changed; - } - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.addRequired<AAResultsWrapperPass>(); - AU.addRequired<DominatorTreeWrapperPass>(); - } - StringRef getPassName() const override { return "Coroutine Elision"; } -}; -} - -char CoroElideLegacy::ID = 0; -INITIALIZE_PASS_BEGIN( - CoroElideLegacy, "coro-elide", - "Coroutine frame allocation elision and indirect calls replacement", false, - false) -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) -INITIALIZE_PASS_END( - CoroElideLegacy, "coro-elide", - "Coroutine frame allocation elision and indirect calls replacement", false, - false) - -Pass *llvm::createCoroElideLegacyPass() { return new CoroElideLegacy(); } Index: llvm/lib/Transforms/Coroutines/CoroInternal.h =================================================================== --- llvm/lib/Transforms/Coroutines/CoroInternal.h +++ llvm/lib/Transforms/Coroutines/CoroInternal.h @@ -21,11 +21,6 @@ class CallGraphSCC; class PassRegistry; -void initializeCoroEarlyLegacyPass(PassRegistry &); -void initializeCoroSplitLegacyPass(PassRegistry &); -void initializeCoroElideLegacyPass(PassRegistry &); -void initializeCoroCleanupLegacyPass(PassRegistry &); - // CoroEarly pass marks every function that has coro.begin with a string // attribute "coroutine.presplit"="0". CoroSplit pass processes the coroutine // twice. First, it lets it go through complete IPO optimization pipeline as a @@ -54,8 +49,7 @@ bool declaresIntrinsics(const Module &M, const std::initializer_list<StringRef>); void replaceCoroFree(CoroIdInst *CoroId, bool Elide); -void updateCallGraph(Function &Caller, ArrayRef<Function *> Funcs, - CallGraph &CG, CallGraphSCC &SCC); + /// Recover a dbg.declare prepared by the frontend and emit an alloca /// holding a pointer to the coroutine frame. void salvageDebugInfo( Index: llvm/lib/Transforms/Coroutines/CoroSplit.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -1079,13 +1079,6 @@ return Cloner.getFunction(); } -/// Remove calls to llvm.coro.end in the original function. -static void removeCoroEnds(const coro::Shape &Shape, CallGraph *CG) { - for (auto End : Shape.CoroEnds) { - replaceCoroEnd(End, Shape, Shape.FramePtr, /*in resume*/ false, CG); - } -} - static void updateAsyncFuncPointerContextSize(coro::Shape &Shape) { assert(Shape.ABI == coro::ABI::Async); @@ -1957,20 +1950,6 @@ return Shape; } -static void -updateCallGraphAfterCoroutineSplit(Function &F, const coro::Shape &Shape, - const SmallVectorImpl<Function *> &Clones, - CallGraph &CG, CallGraphSCC &SCC) { - if (!Shape.CoroBegin) - return; - - removeCoroEnds(Shape, &CG); - postSplitCleanup(F); - - // Update call graph and add the functions we created to the SCC. - coro::updateCallGraph(F, Clones, CG, SCC); -} - static void updateCallGraphAfterCoroutineSplit( LazyCallGraph::Node &N, const coro::Shape &Shape, const SmallVectorImpl<Function *> &Clones, LazyCallGraph::SCC &C, @@ -2013,70 +1992,6 @@ updateCGAndAnalysisManagerForFunctionPass(CG, C, N, AM, UR, FAM); } -// When we see the coroutine the first time, we insert an indirect call to a -// devirt trigger function and mark the coroutine that it is now ready for -// split. -// Async lowering uses this after it has split the function to restart the -// pipeline. -static void prepareForSplit(Function &F, CallGraph &CG, - bool MarkForAsyncRestart = false) { - Module &M = *F.getParent(); - LLVMContext &Context = F.getContext(); -#ifndef NDEBUG - Function *DevirtFn = M.getFunction(CORO_DEVIRT_TRIGGER_FN); - assert(DevirtFn && "coro.devirt.trigger function not found"); -#endif - - F.addFnAttr(CORO_PRESPLIT_ATTR, MarkForAsyncRestart - ? ASYNC_RESTART_AFTER_SPLIT - : PREPARED_FOR_SPLIT); - - // Insert an indirect call sequence that will be devirtualized by CoroElide - // pass: - // %0 = call i8* @llvm.coro.subfn.addr(i8* null, i8 -1) - // %1 = bitcast i8* %0 to void(i8*)* - // call void %1(i8* null) - coro::LowererBase Lowerer(M); - Instruction *InsertPt = - MarkForAsyncRestart ? F.getEntryBlock().getFirstNonPHIOrDbgOrLifetime() - : F.getEntryBlock().getTerminator(); - auto *Null = ConstantPointerNull::get(Type::getInt8PtrTy(Context)); - auto *DevirtFnAddr = - Lowerer.makeSubFnCall(Null, CoroSubFnInst::RestartTrigger, InsertPt); - FunctionType *FnTy = FunctionType::get(Type::getVoidTy(Context), - {Type::getInt8PtrTy(Context)}, false); - auto *IndirectCall = CallInst::Create(FnTy, DevirtFnAddr, Null, "", InsertPt); - - // Update CG graph with an indirect call we just added. - CG[&F]->addCalledFunction(IndirectCall, CG.getCallsExternalNode()); -} - -// Make sure that there is a devirtualization trigger function that the -// coro-split pass uses to force a restart of the CGSCC pipeline. If the devirt -// trigger function is not found, we will create one and add it to the current -// SCC. -static void createDevirtTriggerFunc(CallGraph &CG, CallGraphSCC &SCC) { - Module &M = CG.getModule(); - if (M.getFunction(CORO_DEVIRT_TRIGGER_FN)) - return; - - LLVMContext &C = M.getContext(); - auto *FnTy = FunctionType::get(Type::getVoidTy(C), Type::getInt8PtrTy(C), - /*isVarArg=*/false); - Function *DevirtFn = - Function::Create(FnTy, GlobalValue::LinkageTypes::PrivateLinkage, - CORO_DEVIRT_TRIGGER_FN, &M); - DevirtFn->addFnAttr(Attribute::AlwaysInline); - auto *Entry = BasicBlock::Create(C, "entry", DevirtFn); - ReturnInst::Create(C, Entry); - - auto *Node = CG.getOrInsertFunction(DevirtFn); - - SmallVector<CallGraphNode *, 8> Nodes(SCC.begin(), SCC.end()); - Nodes.push_back(Node); - SCC.initialize(Nodes); -} - /// Replace a call to llvm.coro.prepare.retcon. static void replacePrepare(CallInst *Prepare, LazyCallGraph &CG, LazyCallGraph::SCC &C) { @@ -2113,59 +2028,6 @@ Cast->eraseFromParent(); } } -/// Replace a call to llvm.coro.prepare.retcon. -static void replacePrepare(CallInst *Prepare, CallGraph &CG) { - auto CastFn = Prepare->getArgOperand(0); // as an i8* - auto Fn = CastFn->stripPointerCasts(); // as its original type - - // Find call graph nodes for the preparation. - CallGraphNode *PrepareUserNode = nullptr, *FnNode = nullptr; - if (auto ConcreteFn = dyn_cast<Function>(Fn)) { - PrepareUserNode = CG[Prepare->getFunction()]; - FnNode = CG[ConcreteFn]; - } - - // Attempt to peephole this pattern: - // %0 = bitcast [[TYPE]] @some_function to i8* - // %1 = call @llvm.coro.prepare.retcon(i8* %0) - // %2 = bitcast %1 to [[TYPE]] - // ==> - // %2 = @some_function - for (Use &U : llvm::make_early_inc_range(Prepare->uses())) { - // Look for bitcasts back to the original function type. - auto *Cast = dyn_cast<BitCastInst>(U.getUser()); - if (!Cast || Cast->getType() != Fn->getType()) continue; - - // Check whether the replacement will introduce new direct calls. - // If so, we'll need to update the call graph. - if (PrepareUserNode) { - for (auto &Use : Cast->uses()) { - if (auto *CB = dyn_cast<CallBase>(Use.getUser())) { - if (!CB->isCallee(&Use)) - continue; - PrepareUserNode->removeCallEdgeFor(*CB); - PrepareUserNode->addCalledFunction(CB, FnNode); - } - } - } - - // Replace and remove the cast. - Cast->replaceAllUsesWith(Fn); - Cast->eraseFromParent(); - } - - // Replace any remaining uses with the function as an i8*. - // This can never directly be a callee, so we don't need to update CG. - Prepare->replaceAllUsesWith(CastFn); - Prepare->eraseFromParent(); - - // Kill dead bitcasts. - while (auto *Cast = dyn_cast<BitCastInst>(CastFn)) { - if (!Cast->use_empty()) break; - CastFn = Cast->getOperand(0); - Cast->eraseFromParent(); - } -} static bool replaceAllPrepares(Function *PrepareFn, LazyCallGraph &CG, LazyCallGraph::SCC &C) { @@ -2180,30 +2042,6 @@ return Changed; } -/// Remove calls to llvm.coro.prepare.retcon, a barrier meant to prevent -/// IPO from operating on calls to a retcon coroutine before it's been -/// split. This is only safe to do after we've split all retcon -/// coroutines in the module. We can do that this in this pass because -/// this pass does promise to split all retcon coroutines (as opposed to -/// switch coroutines, which are lowered in multiple stages). -static bool replaceAllPrepares(Function *PrepareFn, CallGraph &CG) { - bool Changed = false; - for (Use &P : llvm::make_early_inc_range(PrepareFn->uses())) { - // Intrinsics can only be used in calls. - auto *Prepare = cast<CallInst>(P.getUser()); - replacePrepare(Prepare, CG); - Changed = true; - } - - return Changed; -} - -static bool declaresCoroSplitIntrinsics(const Module &M) { - return coro::declaresIntrinsics(M, {"llvm.coro.begin", - "llvm.coro.prepare.retcon", - "llvm.coro.prepare.async"}); -} - static void addPrepareFunction(const Module &M, SmallVectorImpl<Function *> &Fns, StringRef Name) { @@ -2271,122 +2109,3 @@ return PreservedAnalyses::none(); } - -namespace { - -// We present a coroutine to LLVM as an ordinary function with suspension -// points marked up with intrinsics. We let the optimizer party on the coroutine -// as a single function for as long as possible. Shortly before the coroutine is -// eligible to be inlined into its callers, we split up the coroutine into parts -// corresponding to initial, resume and destroy invocations of the coroutine, -// add them to the current SCC and restart the IPO pipeline to optimize the -// coroutine subfunctions we extracted before proceeding to the caller of the -// coroutine. -struct CoroSplitLegacy : public CallGraphSCCPass { - static char ID; // Pass identification, replacement for typeid - - CoroSplitLegacy(bool OptimizeFrame = false) - : CallGraphSCCPass(ID), OptimizeFrame(OptimizeFrame) { - initializeCoroSplitLegacyPass(*PassRegistry::getPassRegistry()); - } - - bool Run = false; - bool OptimizeFrame; - - // A coroutine is identified by the presence of coro.begin intrinsic, if - // we don't have any, this pass has nothing to do. - bool doInitialization(CallGraph &CG) override { - Run = declaresCoroSplitIntrinsics(CG.getModule()); - return CallGraphSCCPass::doInitialization(CG); - } - - bool runOnSCC(CallGraphSCC &SCC) override { - if (!Run) - return false; - - // Check for uses of llvm.coro.prepare.retcon. - SmallVector<Function *, 2> PrepareFns; - auto &M = SCC.getCallGraph().getModule(); - addPrepareFunction(M, PrepareFns, "llvm.coro.prepare.retcon"); - addPrepareFunction(M, PrepareFns, "llvm.coro.prepare.async"); - - // Find coroutines for processing. - SmallVector<Function *, 4> Coroutines; - for (CallGraphNode *CGN : SCC) - if (auto *F = CGN->getFunction()) - if (F->hasFnAttribute(CORO_PRESPLIT_ATTR)) - Coroutines.push_back(F); - - if (Coroutines.empty() && PrepareFns.empty()) - return false; - - CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph(); - - if (Coroutines.empty()) { - bool Changed = false; - for (auto *PrepareFn : PrepareFns) - Changed |= replaceAllPrepares(PrepareFn, CG); - return Changed; - } - - createDevirtTriggerFunc(CG, SCC); - - // Split all the coroutines. - for (Function *F : Coroutines) { - Attribute Attr = F->getFnAttribute(CORO_PRESPLIT_ATTR); - StringRef Value = Attr.getValueAsString(); - LLVM_DEBUG(dbgs() << "CoroSplit: Processing coroutine '" << F->getName() - << "' state: " << Value << "\n"); - // Async lowering marks coroutines to trigger a restart of the pipeline - // after it has split them. - if (Value == ASYNC_RESTART_AFTER_SPLIT) { - F->removeFnAttr(CORO_PRESPLIT_ATTR); - continue; - } - if (Value == UNPREPARED_FOR_SPLIT) { - prepareForSplit(*F, CG); - continue; - } - F->removeFnAttr(CORO_PRESPLIT_ATTR); - - SmallVector<Function *, 4> Clones; - const coro::Shape Shape = splitCoroutine(*F, Clones, OptimizeFrame); - updateCallGraphAfterCoroutineSplit(*F, Shape, Clones, CG, SCC); - if (Shape.ABI == coro::ABI::Async) { - // Restart SCC passes. - // Mark function for CoroElide pass. It will devirtualize causing a - // restart of the SCC pipeline. - prepareForSplit(*F, CG, true /*MarkForAsyncRestart*/); - } - } - - for (auto *PrepareFn : PrepareFns) - replaceAllPrepares(PrepareFn, CG); - - return true; - } - - void getAnalysisUsage(AnalysisUsage &AU) const override { - CallGraphSCCPass::getAnalysisUsage(AU); - } - - StringRef getPassName() const override { return "Coroutine Splitting"; } -}; - -} // end anonymous namespace - -char CoroSplitLegacy::ID = 0; - -INITIALIZE_PASS_BEGIN( - CoroSplitLegacy, "coro-split", - "Split coroutine into a set of functions driving its state machine", false, - false) -INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) -INITIALIZE_PASS_END( - CoroSplitLegacy, "coro-split", - "Split coroutine into a set of functions driving its state machine", false, - false) - -Pass *llvm::createCoroSplitLegacyPass(bool OptimizeFrame) { - return new CoroSplitLegacy(OptimizeFrame); -} Index: llvm/lib/Transforms/Coroutines/Coroutines.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/Coroutines.cpp +++ llvm/lib/Transforms/Coroutines/Coroutines.cpp @@ -41,55 +41,6 @@ using namespace llvm; -void llvm::initializeCoroutines(PassRegistry &Registry) { - initializeCoroEarlyLegacyPass(Registry); - initializeCoroSplitLegacyPass(Registry); - initializeCoroElideLegacyPass(Registry); - initializeCoroCleanupLegacyPass(Registry); -} - -static void addCoroutineOpt0Passes(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - PM.add(createCoroSplitLegacyPass()); - PM.add(createCoroElideLegacyPass()); - - PM.add(createBarrierNoopPass()); - PM.add(createCoroCleanupLegacyPass()); -} - -static void addCoroutineEarlyPasses(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - PM.add(createCoroEarlyLegacyPass()); -} - -static void addCoroutineScalarOptimizerPasses(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - PM.add(createCoroElideLegacyPass()); -} - -static void addCoroutineSCCPasses(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - PM.add(createCoroSplitLegacyPass(Builder.OptLevel != 0)); -} - -static void addCoroutineOptimizerLastPasses(const PassManagerBuilder &Builder, - legacy::PassManagerBase &PM) { - PM.add(createCoroCleanupLegacyPass()); -} - -void llvm::addCoroutinePassesToExtensionPoints(PassManagerBuilder &Builder) { - Builder.addExtension(PassManagerBuilder::EP_EarlyAsPossible, - addCoroutineEarlyPasses); - Builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0, - addCoroutineOpt0Passes); - Builder.addExtension(PassManagerBuilder::EP_CGSCCOptimizerLate, - addCoroutineSCCPasses); - Builder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate, - addCoroutineScalarOptimizerPasses); - Builder.addExtension(PassManagerBuilder::EP_OptimizerLast, - addCoroutineOptimizerLastPasses); -} - // Construct the lowerer base class and initialize its members. coro::LowererBase::LowererBase(Module &M) : TheModule(M), Context(M.getContext()), @@ -202,46 +153,6 @@ } } -// FIXME: This code is stolen from CallGraph::addToCallGraph(Function *F), which -// happens to be private. It is better for this functionality exposed by the -// CallGraph. -static void buildCGN(CallGraph &CG, CallGraphNode *Node) { - Function *F = Node->getFunction(); - - // Look for calls by this function. - for (Instruction &I : instructions(F)) - if (auto *Call = dyn_cast<CallBase>(&I)) { - const Function *Callee = Call->getCalledFunction(); - if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID())) - // Indirect calls of intrinsics are not allowed so no need to check. - // We can be more precise here by using TargetArg returned by - // Intrinsic::isLeaf. - Node->addCalledFunction(Call, CG.getCallsExternalNode()); - else if (!Callee->isIntrinsic()) - Node->addCalledFunction(Call, CG.getOrInsertFunction(Callee)); - } -} - -// Rebuild CGN after we extracted parts of the code from ParentFunc into -// NewFuncs. Builds CGNs for the NewFuncs and adds them to the current SCC. -void coro::updateCallGraph(Function &ParentFunc, ArrayRef<Function *> NewFuncs, - CallGraph &CG, CallGraphSCC &SCC) { - // Rebuild CGN from scratch for the ParentFunc - auto *ParentNode = CG[&ParentFunc]; - ParentNode->removeAllCalledFunctions(); - buildCGN(CG, ParentNode); - - SmallVector<CallGraphNode *, 8> Nodes(SCC.begin(), SCC.end()); - - for (Function *F : NewFuncs) { - CallGraphNode *Callee = CG.getOrInsertFunction(F); - Nodes.push_back(Callee); - buildCGN(CG, Callee); - } - - SCC.initialize(Nodes); -} - static void clear(coro::Shape &Shape) { Shape.CoroBegin = nullptr; Shape.CoroEnds.clear(); @@ -746,25 +657,3 @@ "match the tail arguments", MustTailCallFunc); } - -void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createCoroEarlyLegacyPass()); -} - -void LLVMAddCoroSplitPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createCoroSplitLegacyPass()); -} - -void LLVMAddCoroElidePass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createCoroElideLegacyPass()); -} - -void LLVMAddCoroCleanupPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createCoroCleanupLegacyPass()); -} - -void -LLVMPassManagerBuilderAddCoroutinePassesToExtensionPoints(LLVMPassManagerBuilderRef PMB) { - PassManagerBuilder *Builder = unwrap(PMB); - addCoroutinePassesToExtensionPoints(*Builder); -} Index: llvm/test/Transforms/Coroutines/coro-cleanup-lowering.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-cleanup-lowering.ll +++ llvm/test/Transforms/Coroutines/coro-cleanup-lowering.ll @@ -1,5 +1,4 @@ ; Make sure that all library helper coro intrinsics are lowered. -; RUN: opt < %s -coro-cleanup -S | FileCheck %s ; RUN: opt < %s -passes=coro-cleanup -S | FileCheck %s ; CHECK-LABEL: @uses_library_support_coro_intrinsics( Index: llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp =================================================================== --- llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp +++ llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp @@ -191,7 +191,6 @@ PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); - initializeCoroutines(Registry); initializeScalarOpts(Registry); initializeObjCARCOpts(Registry); initializeVectorization(Registry); Index: llvm/tools/opt/opt.cpp =================================================================== --- llvm/tools/opt/opt.cpp +++ llvm/tools/opt/opt.cpp @@ -371,9 +371,6 @@ if (TM) TM->adjustPassManager(Builder); - if (Coroutines) - addCoroutinePassesToExtensionPoints(Builder); - switch (PGOKindFlag) { case InstrGen: Builder.EnablePGOInstrGen = true; @@ -539,7 +536,6 @@ // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); - initializeCoroutines(Registry); initializeScalarOpts(Registry); initializeObjCARCOpts(Registry); initializeVectorization(Registry);