Index: llvm/include/llvm/Transforms/Coroutines/CoroEarly.h =================================================================== --- llvm/include/llvm/Transforms/Coroutines/CoroEarly.h +++ llvm/include/llvm/Transforms/Coroutines/CoroEarly.h @@ -21,10 +21,10 @@ namespace llvm { -class Function; +class Module; struct CoroEarlyPass : PassInfoMixin { - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); static bool isRequired() { return true; } }; } // end namespace llvm Index: llvm/lib/Passes/PassBuilderPipelines.cpp =================================================================== --- llvm/lib/Passes/PassBuilderPipelines.cpp +++ llvm/lib/Passes/PassBuilderPipelines.cpp @@ -853,6 +853,7 @@ // Do basic inference of function attributes from known properties of system // libraries and other oracles. MPM.addPass(InferFunctionAttrsPass()); + MPM.addPass(CoroEarlyPass()); // Create an early function pass manager to cleanup the output of the // frontend. @@ -863,7 +864,6 @@ EarlyFPM.addPass(SimplifyCFGPass()); EarlyFPM.addPass(SROAPass()); EarlyFPM.addPass(EarlyCSEPass()); - EarlyFPM.addPass(CoroEarlyPass()); if (Level == OptimizationLevel::O3) EarlyFPM.addPass(CallSiteSplittingPass()); @@ -1825,7 +1825,7 @@ } ModulePassManager CoroPM; - CoroPM.addPass(createModuleToFunctionPassAdaptor(CoroEarlyPass())); + CoroPM.addPass(CoroEarlyPass()); CGSCCPassManager CGPM; CGPM.addPass(CoroSplitPass()); CoroPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); Index: llvm/lib/Passes/PassRegistry.def =================================================================== --- llvm/lib/Passes/PassRegistry.def +++ llvm/lib/Passes/PassRegistry.def @@ -50,6 +50,7 @@ MODULE_PASS("cg-profile", CGProfilePass()) MODULE_PASS("check-debugify", NewPMCheckDebugifyPass()) MODULE_PASS("constmerge", ConstantMergePass()) +MODULE_PASS("coro-early", CoroEarlyPass()) MODULE_PASS("cross-dso-cfi", CrossDSOCFIPass()) MODULE_PASS("deadargelim", DeadArgumentEliminationPass()) MODULE_PASS("debugify", NewPMDebugifyPass()) @@ -249,7 +250,6 @@ FUNCTION_PASS("consthoist", ConstantHoistingPass()) FUNCTION_PASS("constraint-elimination", ConstraintEliminationPass()) FUNCTION_PASS("chr", ControlHeightReductionPass()) -FUNCTION_PASS("coro-early", CoroEarlyPass()) FUNCTION_PASS("coro-elide", CoroElidePass()) FUNCTION_PASS("coro-cleanup", CoroCleanupPass()) FUNCTION_PASS("correlated-propagation", CorrelatedValuePropagationPass()) Index: llvm/lib/Transforms/Coroutines/CoroEarly.cpp =================================================================== --- llvm/lib/Transforms/Coroutines/CoroEarly.cpp +++ llvm/lib/Transforms/Coroutines/CoroEarly.cpp @@ -238,9 +238,15 @@ "llvm.coro.suspend"}); } -PreservedAnalyses CoroEarlyPass::run(Function &F, FunctionAnalysisManager &) { - Module &M = *F.getParent(); - if (!declaresCoroEarlyIntrinsics(M) || !Lowerer(M).lowerEarlyIntrinsics(F)) +PreservedAnalyses CoroEarlyPass::run(Module &M, ModuleAnalysisManager &) { + if (!declaresCoroEarlyIntrinsics(M)) + return PreservedAnalyses::all(); + + Lowerer L(M); + bool Changed = false; + for (auto &F : M) + Changed |= L.lowerEarlyIntrinsics(F); + if (Changed) return PreservedAnalyses::all(); PreservedAnalyses PA; Index: llvm/test/Other/new-pm-defaults.ll =================================================================== --- llvm/test/Other/new-pm-defaults.ll +++ llvm/test/Other/new-pm-defaults.ll @@ -96,6 +96,7 @@ ; CHECK-O-NEXT: Running pass: InferFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis +; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O-NEXT: Running pass: LowerExpectIntrinsicPass ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running analysis: TargetIRAnalysis @@ -104,7 +105,6 @@ ; CHECK-O-NEXT: Running analysis: DominatorTreeAnalysis ; CHECK-O-NEXT: Running pass: EarlyCSEPass ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis -; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O3-NEXT: Running pass: CallSiteSplittingPass ; CHECK-O-NEXT: Running pass: OpenMPOptPass ; CHECK-EP-PIPELINE-EARLY-SIMPLIFICATION-NEXT: Running pass: NoOpModulePass Index: llvm/test/Other/new-pm-thinlto-defaults.ll =================================================================== --- llvm/test/Other/new-pm-thinlto-defaults.ll +++ llvm/test/Other/new-pm-thinlto-defaults.ll @@ -62,6 +62,7 @@ ; CHECK-O-NEXT: Running pass: InferFunctionAttrsPass ; CHECK-PRELINK-O-NODIS-NEXT: Running analysis: InnerAnalysisManagerProxy ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis +; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O-NEXT: Running pass: LowerExpectIntrinsicPass ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running analysis: TargetIRAnalysis @@ -70,7 +71,6 @@ ; CHECK-O-NEXT: Running analysis: DominatorTreeAnalysis ; CHECK-O-NEXT: Running pass: EarlyCSEPass ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis -; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O3-NEXT: Running pass: CallSiteSplittingPass ; CHECK-O-NEXT: Running pass: OpenMPOptPass ; CHECK-POSTLINK-O-NEXT: Running pass: LowerTypeTestsPass Index: llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll =================================================================== --- llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll +++ llvm/test/Other/new-pm-thinlto-postlink-pgo-defaults.ll @@ -32,6 +32,7 @@ ; CHECK-O-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis ; CHECK-O-NEXT: Running pass: InferFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis +; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O-NEXT: Running pass: LowerExpectIntrinsicPass ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running analysis: TargetIRAnalysis @@ -40,7 +41,6 @@ ; CHECK-O-NEXT: Running analysis: DominatorTreeAnalysis ; CHECK-O-NEXT: Running pass: EarlyCSEPass ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis -; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O3-NEXT: Running pass: CallSiteSplittingPass ; CHECK-O-NEXT: Running pass: OpenMPOptPass ; CHECK-O-NEXT: Running pass: LowerTypeTestsPass Index: llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll =================================================================== --- llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll +++ llvm/test/Other/new-pm-thinlto-postlink-samplepgo-defaults.ll @@ -34,6 +34,7 @@ ; CHECK-O-NEXT: Running pass: InferFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis +; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O-NEXT: Running pass: LowerExpectIntrinsicPass ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running analysis: TargetIRAnalysis @@ -42,7 +43,6 @@ ; CHECK-O-NEXT: Running analysis: DominatorTreeAnalysis ; CHECK-O-NEXT: Running pass: EarlyCSEPass ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis -; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O3-NEXT: Running pass: CallSiteSplittingPass ; CHECK-O-NEXT: Running pass: InstCombinePass on foo ; CHECK-O-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis on foo Index: llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll =================================================================== --- llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll +++ llvm/test/Other/new-pm-thinlto-prelink-pgo-defaults.ll @@ -33,6 +33,7 @@ ; CHECK-O-NEXT: Running pass: InferFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: InnerAnalysisManagerProxy ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis +; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O-NEXT: Running pass: LowerExpectIntrinsicPass ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running analysis: TargetIRAnalysis @@ -41,7 +42,6 @@ ; CHECK-O-NEXT: Running analysis: DominatorTreeAnalysis ; CHECK-O-NEXT: Running pass: EarlyCSEPass ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis -; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O3-NEXT: Running pass: CallSiteSplittingPass ; CHECK-O-NEXT: Running pass: OpenMPOptPass ; CHECK-O-NEXT: Running pass: IPSCCPPass Index: llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll =================================================================== --- llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll +++ llvm/test/Other/new-pm-thinlto-prelink-samplepgo-defaults.ll @@ -32,6 +32,7 @@ ; CHECK-EP-PIPELINE-START-NEXT: Running pass: NoOpModulePass ; CHECK-O-NEXT: Running pass: InferFunctionAttrsPass ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis +; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O-NEXT: Running pass: LowerExpectIntrinsicPass ; CHECK-O-NEXT: Running pass: SimplifyCFGPass ; CHECK-O-NEXT: Running analysis: TargetIRAnalysis @@ -40,7 +41,6 @@ ; CHECK-O-NEXT: Running analysis: DominatorTreeAnalysis ; CHECK-O-NEXT: Running pass: EarlyCSEPass ; CHECK-O-NEXT: Running analysis: TargetLibraryAnalysis -; CHECK-O-NEXT: Running pass: CoroEarlyPass ; CHECK-O3-NEXT: Running pass: CallSiteSplittingPass ; CHECK-O-NEXT: Running pass: InstCombinePass on foo ; CHECK-O-NEXT: Running analysis: OptimizationRemarkEmitterAnalysis on foo Index: llvm/test/Transforms/Coroutines/coro-debug-O2.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-debug-O2.ll +++ llvm/test/Transforms/Coroutines/coro-debug-O2.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -passes='function(coro-early),cgscc(coro-split,coro-split),function(sroa)' --reuse-storage-in-coroutine-frame -S | FileCheck %s +; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split),function(sroa)' --reuse-storage-in-coroutine-frame -S | FileCheck %s ; Checks whether the dbg.declare for `__promise` remains valid under O2. Index: llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll +++ llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -passes='function(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s +; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s ; Checks whether the dbg.declare for `__coro_frame` are created. Index: llvm/test/Transforms/Coroutines/coro-debug-dbg.addr-swift.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-debug-dbg.addr-swift.ll +++ llvm/test/Transforms/Coroutines/coro-debug-dbg.addr-swift.ll @@ -5,7 +5,7 @@ ; create the debug_value for us, make sure that we propagate llvm.dbg.addr into ; the beginning coroutine and all other funclets. -; RUN: opt %s -passes='function(coro-early),cgscc(coro-split,simplifycfg)' -S | FileCheck %s +; RUN: opt %s -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -S | FileCheck %s ; CHECK-LABEL: define swifttailcc void @"$s10async_args14withGenericArgyyxnYalF"(%swift.context* swiftasync %0, %swift.opaque* noalias %1, %swift.type* %T){{.*}} { ; CHECK: call void @llvm.dbg.declare(metadata %swift.context** [[CORO_CTX:%[a-z0-9\.]+]], Index: llvm/test/Transforms/Coroutines/coro-debug-dbg.addr.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-debug-dbg.addr.ll +++ llvm/test/Transforms/Coroutines/coro-debug-dbg.addr.ll @@ -5,7 +5,7 @@ ; create the debug_value for us, make sure that we propagate llvm.dbg.addr into ; the beginning coroutine and all other funclets. -; RUN: opt < %s -passes='function(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s +; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s ; This file is based on coro-debug-frame-variable.ll. ; CHECK: define internal fastcc void @f.resume(%f.Frame* noalias nonnull align 16 dereferenceable(80) %FramePtr) !dbg ![[RESUME_FN_DBG_NUM:[0-9]+]] Index: llvm/test/Transforms/Coroutines/coro-debug-dbg.values-not_used_in_frame.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-debug-dbg.values-not_used_in_frame.ll +++ llvm/test/Transforms/Coroutines/coro-debug-dbg.values-not_used_in_frame.ll @@ -1,5 +1,5 @@ ; Tests whether resume function would remain dbg.value infomation if corresponding values are not used in the frame. -; RUN: opt < %s -passes='function(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s +; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s ; ; This file is based on coro-debug-frame-variable.ll. ; CHECK: define internal fastcc void @f.resume(%f.Frame* noalias nonnull align 16 dereferenceable(80) %FramePtr) !dbg ![[RESUME_FN_DBG_NUM:[0-9]+]] Index: llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll +++ llvm/test/Transforms/Coroutines/coro-debug-dbg.values.ll @@ -1,5 +1,5 @@ ; Tests whether resume function would remain dbg.value infomation. -; RUN: opt < %s -passes='function(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s +; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s ; ; This file is based on coro-debug-frame-variable.ll. ; CHECK: define internal fastcc void @f.resume(%f.Frame* noalias nonnull align 16 dereferenceable(80) %FramePtr) !dbg ![[RESUME_FN_DBG_NUM:[0-9]+]] Index: llvm/test/Transforms/Coroutines/coro-retcon-unreachable.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-retcon-unreachable.ll +++ llvm/test/Transforms/Coroutines/coro-retcon-unreachable.ll @@ -1,5 +1,5 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -passes='function(coro-early),cgscc(coro-split),function(simplifycfg,early-cse)' -S | FileCheck %s +; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),function(simplifycfg,early-cse)' -S | FileCheck %s target datalayout = "E-p:64:64" %swift.type = type { i64 } Index: llvm/test/Transforms/Coroutines/coro-split-recursive.ll =================================================================== --- llvm/test/Transforms/Coroutines/coro-split-recursive.ll +++ llvm/test/Transforms/Coroutines/coro-split-recursive.ll @@ -1,5 +1,5 @@ -; RUN: opt -passes='function(coro-early),cgscc(coro-split)' -opaque-pointers=0 -S < %s | FileCheck %s -; RUN: opt -passes='function(coro-early),cgscc(coro-split)' -opaque-pointers=1 -S < %s | FileCheck %s +; RUN: opt -passes='module(coro-early),cgscc(coro-split)' -opaque-pointers=0 -S < %s | FileCheck %s +; RUN: opt -passes='module(coro-early),cgscc(coro-split)' -opaque-pointers=1 -S < %s | FileCheck %s declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) Index: llvm/test/Transforms/Coroutines/smoketest.ll =================================================================== --- llvm/test/Transforms/Coroutines/smoketest.ll +++ llvm/test/Transforms/Coroutines/smoketest.ll @@ -10,7 +10,7 @@ ; RUN: opt < %s -disable-output -passes='default' -enable-coroutines \ ; RUN: -debug-pass-manager 2>&1 | FileCheck %s --check-prefixes=CHECK-ALL,CHECK-OPT ; RUN: opt < %s -disable-output -debug-pass-manager \ -; RUN: -passes='function(coro-early),function(coro-elide),cgscc(coro-split),function(coro-cleanup)' 2>&1 \ +; RUN: -passes='module(coro-early),function(coro-elide),cgscc(coro-split),function(coro-cleanup)' 2>&1 \ ; RUN: | FileCheck %s --check-prefixes=CHECK-ALL,CHECK-OPT ; note that we run CoroElidePass before CoroSplitPass. This is because CoroElidePass is part of