diff --git a/llvm/include/llvm-c/Transforms/Coroutines.h b/llvm/include/llvm-c/Transforms/Coroutines.h --- a/llvm/include/llvm-c/Transforms/Coroutines.h +++ b/llvm/include/llvm-c/Transforms/Coroutines.h @@ -31,7 +31,7 @@ * @{ */ -/** See llvm::createCoroEarlyPass function. */ +/** See llvm::createCoroEarlyLegacyPass function. */ void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM); /** See llvm::createCoroSplitPass function. */ 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 @@ -20,7 +20,7 @@ void addCoroutinePassesToExtensionPoints(PassManagerBuilder &Builder); /// Lower coroutine intrinsics that are not needed by later passes. -Pass *createCoroEarlyPass(); +Pass *createCoroEarlyLegacyPass(); /// Split up coroutines into multiple functions driving their state machines. Pass *createCoroSplitPass(); diff --git a/llvm/include/llvm/Transforms/Coroutines/CoroEarly.h b/llvm/include/llvm/Transforms/Coroutines/CoroEarly.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Transforms/Coroutines/CoroEarly.h @@ -0,0 +1,31 @@ +//===---- CoroEarly.h - Lower early coroutine intrinsics --------*- 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 +// +//===----------------------------------------------------------------------===// +// +// \file +// This file provides the interface to the early coroutine intrinsic lowering +// pass. This pass lowers coroutine intrinsics that hide the details of the +// exact calling convention for coroutine resume and destroy functions and +// details of the structure of the coroutine frame. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_COROUTINES_COROEARLY_H +#define LLVM_TRANSFORMS_COROUTINES_COROEARLY_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class Function; + +struct CoroEarlyPass : PassInfoMixin { + PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +}; +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_COROUTINES_COROEARLY_H diff --git a/llvm/lib/Passes/LLVMBuild.txt b/llvm/lib/Passes/LLVMBuild.txt --- a/llvm/lib/Passes/LLVMBuild.txt +++ b/llvm/lib/Passes/LLVMBuild.txt @@ -18,4 +18,4 @@ type = Library name = Passes parent = Libraries -required_libraries = AggressiveInstCombine Analysis CodeGen Core IPO InstCombine Scalar Support Target TransformUtils Vectorize Instrumentation +required_libraries = AggressiveInstCombine Analysis CodeGen Core Coroutines IPO InstCombine Scalar Support Target TransformUtils Vectorize Instrumentation diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -67,6 +67,7 @@ #include "llvm/Support/Regex.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h" +#include "llvm/Transforms/Coroutines/CoroEarly.h" #include "llvm/Transforms/IPO/AlwaysInliner.h" #include "llvm/Transforms/IPO/ArgumentPromotion.h" #include "llvm/Transforms/IPO/Attributor.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -166,6 +166,7 @@ FUNCTION_PASS("callsite-splitting", CallSiteSplittingPass()) FUNCTION_PASS("consthoist", ConstantHoistingPass()) FUNCTION_PASS("chr", ControlHeightReductionPass()) +FUNCTION_PASS("coro-early", CoroEarlyPass()) FUNCTION_PASS("correlated-propagation", CorrelatedValuePropagationPass()) FUNCTION_PASS("dce", DCEPass()) FUNCTION_PASS("div-rem-pairs", DivRemPairsPass()) diff --git a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp --- a/llvm/lib/Transforms/Coroutines/CoroEarly.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroEarly.cpp @@ -5,11 +5,8 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// -// This pass lowers coroutine intrinsics that hide the details of the exact -// calling convention for coroutine resume and destroy functions and details of -// the structure of the coroutine frame. -//===----------------------------------------------------------------------===// +#include "llvm/Transforms/Coroutines/CoroEarly.h" #include "CoroInternal.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/IRBuilder.h" @@ -22,7 +19,7 @@ #define DEBUG_TYPE "coro-early" namespace { -// Created on demand if CoroEarly pass has work to do. +// Created on demand if the coro-early pass has work to do. class Lowerer : public coro::LowererBase { IRBuilder<> Builder; PointerType *const AnyResumeFnPtrTy; @@ -219,16 +216,33 @@ return Changed; } -//===----------------------------------------------------------------------===// -// Top Level Driver -//===----------------------------------------------------------------------===// +static bool declaresCoroEarlyIntrinsics(const Module &M) { + return coro::declaresIntrinsics(M, {"llvm.coro.id", + "llvm.coro.destroy", + "llvm.coro.done", + "llvm.coro.end", + "llvm.coro.noop", + "llvm.coro.free", + "llvm.coro.promise", + "llvm.coro.resume", + "llvm.coro.suspend"}); +} -namespace { +PreservedAnalyses CoroEarlyPass::run(Function &F, FunctionAnalysisManager &) { + Module &M = *F.getParent(); + if (!declaresCoroEarlyIntrinsics(M) || !Lowerer(M).lowerEarlyIntrinsics(F)) + return PreservedAnalyses::all(); + + PreservedAnalyses PA; + PA.preserveSet(); + return PA; +} -struct CoroEarly : public FunctionPass { +namespace { +struct CoroEarlyLegacy : public FunctionPass { static char ID; // Pass identification, replacement for typeid. - CoroEarly() : FunctionPass(ID) { - initializeCoroEarlyPass(*PassRegistry::getPassRegistry()); + CoroEarlyLegacy() : FunctionPass(ID) { + initializeCoroEarlyLegacyPass(*PassRegistry::getPassRegistry()); } std::unique_ptr L; @@ -236,17 +250,7 @@ // 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 (coro::declaresIntrinsics(M, {"llvm.coro.id", - "llvm.coro.id.retcon", - "llvm.coro.id.retcon.once", - "llvm.coro.destroy", - "llvm.coro.done", - "llvm.coro.end", - "llvm.coro.noop", - "llvm.coro.free", - "llvm.coro.promise", - "llvm.coro.resume", - "llvm.coro.suspend"})) + if (declaresCoroEarlyIntrinsics(M)) L = std::make_unique(M); return false; } @@ -267,8 +271,8 @@ }; } -char CoroEarly::ID = 0; -INITIALIZE_PASS(CoroEarly, "coro-early", "Lower early coroutine intrinsics", - false, false) +char CoroEarlyLegacy::ID = 0; +INITIALIZE_PASS(CoroEarlyLegacy, "coro-early", + "Lower early coroutine intrinsics", false, false) -Pass *llvm::createCoroEarlyPass() { return new CoroEarly(); } +Pass *llvm::createCoroEarlyLegacyPass() { return new CoroEarlyLegacy(); } diff --git a/llvm/lib/Transforms/Coroutines/CoroInternal.h b/llvm/lib/Transforms/Coroutines/CoroInternal.h --- a/llvm/lib/Transforms/Coroutines/CoroInternal.h +++ b/llvm/lib/Transforms/Coroutines/CoroInternal.h @@ -21,7 +21,7 @@ class CallGraphSCC; class PassRegistry; -void initializeCoroEarlyPass(PassRegistry &); +void initializeCoroEarlyLegacyPass(PassRegistry &); void initializeCoroSplitPass(PassRegistry &); void initializeCoroElidePass(PassRegistry &); void initializeCoroCleanupPass(PassRegistry &); @@ -43,7 +43,8 @@ namespace coro { -bool declaresIntrinsics(Module &M, std::initializer_list); +bool declaresIntrinsics(const Module &M, + const std::initializer_list); void replaceAllCoroAllocs(CoroBeginInst *CB, bool Replacement); void replaceAllCoroFrees(CoroBeginInst *CB, Value *Replacement); void replaceCoroFree(CoroIdInst *CoroId, bool Elide); 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 @@ -43,7 +43,7 @@ using namespace llvm; void llvm::initializeCoroutines(PassRegistry &Registry) { - initializeCoroEarlyPass(Registry); + initializeCoroEarlyLegacyPass(Registry); initializeCoroSplitPass(Registry); initializeCoroElidePass(Registry); initializeCoroCleanupPass(Registry); @@ -60,7 +60,7 @@ static void addCoroutineEarlyPasses(const PassManagerBuilder &Builder, legacy::PassManagerBase &PM) { - PM.add(createCoroEarlyPass()); + PM.add(createCoroEarlyLegacyPass()); } static void addCoroutineScalarOptimizerPasses(const PassManagerBuilder &Builder, @@ -151,8 +151,8 @@ // Verifies if a module has named values listed. Also, in debug mode verifies // that names are intrinsic names. -bool coro::declaresIntrinsics(Module &M, - std::initializer_list List) { +bool coro::declaresIntrinsics(const Module &M, + const std::initializer_list List) { for (StringRef Name : List) { assert(isCoroutineIntrinsicName(Name) && "not a coroutine intrinsic"); if (M.getNamedValue(Name)) @@ -635,7 +635,7 @@ } void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createCoroEarlyPass()); + unwrap(PM)->add(createCoroEarlyLegacyPass()); } void LLVMAddCoroSplitPass(LLVMPassManagerRef PM) { diff --git a/llvm/test/Transforms/Coroutines/coro-early.ll b/llvm/test/Transforms/Coroutines/coro-early.ll --- a/llvm/test/Transforms/Coroutines/coro-early.ll +++ b/llvm/test/Transforms/Coroutines/coro-early.ll @@ -1,6 +1,7 @@ ; Tests that CoroEarly pass correctly lowers coro.resume, coro.destroy ; and other intrinsics managed by this pass. ; RUN: opt < %s -S -coro-early | FileCheck %s +; RUN: opt < %s -S -passes=coro-early | FileCheck %s ; CHECK: %NoopCoro.Frame = type { void (%NoopCoro.Frame*)*, void (%NoopCoro.Frame*)* } ; CHECK: @NoopCoro.Frame.Const = private constant %NoopCoro.Frame { void (%NoopCoro.Frame*)* @NoopCoro.ResumeDestroy, void (%NoopCoro.Frame*)* @NoopCoro.ResumeDestroy }