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 @@ -170,6 +170,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" @@ -219,9 +216,23 @@ return Changed; } -//===----------------------------------------------------------------------===// -// Top Level Driver -//===----------------------------------------------------------------------===// +static bool declaresCoroEarlyIntrinsics(const Module &M) { + return 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"}); +} + +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; +} namespace { @@ -236,17 +247,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; } 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 }