From 3903379fcef4404405428e0ba7c5767fd7d1c7a0 Mon Sep 17 00:00:00 2001 From: tnowicki Date: Tue, 19 Nov 2024 17:59:24 -0500 Subject: [PATCH 1/4] [Coroutines][NFC] Refactor CoroCloner * Move CoroCloner to its own header. For now the header is located in lib/Transforms/Coroutines * Change private to protected to allow inheritance * Create CoroSwitchCloner and move some of the switch specific code into this cloner. * This continus previous work done to CoroFrame. The goal is to isolate the cloner code required for each ABI as much as is reasonable. The base class should include a useful set of helpers and base implementations. More changes will follow. --- llvm/lib/Transforms/Coroutines/CoroCloner.h | 147 ++++++++++++++++++ llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 149 ++----------------- 2 files changed, 163 insertions(+), 133 deletions(-) create mode 100644 llvm/lib/Transforms/Coroutines/CoroCloner.h diff --git a/llvm/lib/Transforms/Coroutines/CoroCloner.h b/llvm/lib/Transforms/Coroutines/CoroCloner.h new file mode 100644 index 0000000000000..e4e3976924e59 --- /dev/null +++ b/llvm/lib/Transforms/Coroutines/CoroCloner.h @@ -0,0 +1,147 @@ +// +// 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 +// +//===----------------------------------------------------------------------===// +// Helper class for splitting a coroutine into separate functions. For example +// the returned-continuation coroutine is split into separate continuation +// functions. +//===----------------------------------------------------------------------===// + +#pragma once + +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/Support/TimeProfiler.h" +#include "llvm/Transforms/Coroutines/ABI.h" +#include "llvm/Transforms/Coroutines/CoroInstr.h" +#include "llvm/Transforms/Utils/ValueMapper.h" + +using namespace llvm; + +class CoroCloner { +public: + enum class Kind { + /// The shared resume function for a switch lowering. + SwitchResume, + + /// The shared unwind function for a switch lowering. + SwitchUnwind, + + /// The shared cleanup function for a switch lowering. + SwitchCleanup, + + /// An individual continuation function. + Continuation, + + /// An async resume function. + Async, + }; + +protected: + Function &OrigF; + const Twine &Suffix; + coro::Shape &Shape; + Kind FKind; + IRBuilder<> Builder; + TargetTransformInfo &TTI; + + ValueToValueMapTy VMap; + Function *NewF = nullptr; + Value *NewFramePtr = nullptr; + + + /// The active suspend instruction; meaningful only for continuation and async + /// ABIs. + AnyCoroSuspendInst *ActiveSuspend = nullptr; + + /// Create a cloner for a continuation lowering. + CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, + Function *NewF, AnyCoroSuspendInst *ActiveSuspend, + TargetTransformInfo &TTI) + : OrigF(OrigF), Suffix(Suffix), Shape(Shape), + FKind(Shape.ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation), + Builder(OrigF.getContext()), TTI(TTI), NewF(NewF), ActiveSuspend(ActiveSuspend) { + assert(Shape.ABI == coro::ABI::Retcon || + Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async); + assert(NewF && "need existing function for continuation"); + assert(ActiveSuspend && "need active suspend point for continuation"); + } + +public: + CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, + Kind FKind, TargetTransformInfo &TTI) : + OrigF(OrigF), Suffix(Suffix), Shape(Shape), FKind(FKind), Builder(OrigF.getContext()), TTI(TTI) { + } + + virtual ~CoroCloner() { } + + /// Create a clone for a continuation lowering. + static Function *createClone(Function &OrigF, const Twine &Suffix, + coro::Shape &Shape, Function *NewF, + AnyCoroSuspendInst *ActiveSuspend, + TargetTransformInfo &TTI) { + assert(Shape.ABI == coro::ABI::Retcon || + Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async); + TimeTraceScope FunctionScope("CoroCloner"); + + CoroCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI); + Cloner.create(); + return Cloner.getFunction(); + } + + Function *getFunction() const { + assert(NewF != nullptr && "declaration not yet set"); + return NewF; + } + + virtual void create(); + +protected: + bool isSwitchDestroyFunction() { + switch (FKind) { + case Kind::Async: + case Kind::Continuation: + case Kind::SwitchResume: + return false; + case Kind::SwitchUnwind: + case Kind::SwitchCleanup: + return true; + } + llvm_unreachable("Unknown CoroCloner::Kind enum"); + } + + void replaceEntryBlock(); + Value *deriveNewFramePointer(); + void replaceRetconOrAsyncSuspendUses(); + void replaceCoroSuspends(); + void replaceCoroEnds(); + void replaceSwiftErrorOps(); + void salvageDebugInfo(); + void handleFinalSuspend(); +}; + + +class CoroSwitchCloner : public CoroCloner { +protected: + /// Create a cloner for a switch lowering. + CoroSwitchCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, + Kind FKind, TargetTransformInfo &TTI) + : CoroCloner(OrigF, Suffix, Shape, FKind, TTI) { } + + void create() override; + +public: + /// Create a clone for a switch lowering. + static Function *createClone(Function &OrigF, const Twine &Suffix, + coro::Shape &Shape, Kind FKind, + TargetTransformInfo &TTI) { + assert(Shape.ABI == coro::ABI::Switch); + TimeTraceScope FunctionScope("CoroCloner"); + + CoroSwitchCloner Cloner(OrigF, Suffix, Shape, FKind, TTI); + Cloner.create(); + return Cloner.getFunction(); + } +}; diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 8a5bae9f6f0d4..147de7726d31b 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -20,6 +20,7 @@ #include "llvm/Transforms/Coroutines/CoroSplit.h" #include "CoroInternal.h" +#include "CoroCloner.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PriorityWorklist.h" #include "llvm/ADT/STLExtras.h" @@ -44,10 +45,8 @@ #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Dominators.h" -#include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" @@ -61,17 +60,13 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/TimeProfiler.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Coroutines/ABI.h" -#include "llvm/Transforms/Coroutines/CoroInstr.h" #include "llvm/Transforms/Coroutines/MaterializationUtils.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/CallGraphUpdater.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/Local.h" -#include "llvm/Transforms/Utils/ValueMapper.h" #include #include #include @@ -82,122 +77,6 @@ using namespace llvm; #define DEBUG_TYPE "coro-split" -namespace { - -/// A little helper class for building -class CoroCloner { -public: - enum class Kind { - /// The shared resume function for a switch lowering. - SwitchResume, - - /// The shared unwind function for a switch lowering. - SwitchUnwind, - - /// The shared cleanup function for a switch lowering. - SwitchCleanup, - - /// An individual continuation function. - Continuation, - - /// An async resume function. - Async, - }; - -private: - Function &OrigF; - Function *NewF; - const Twine &Suffix; - coro::Shape &Shape; - Kind FKind; - ValueToValueMapTy VMap; - IRBuilder<> Builder; - Value *NewFramePtr = nullptr; - - /// The active suspend instruction; meaningful only for continuation and async - /// ABIs. - AnyCoroSuspendInst *ActiveSuspend = nullptr; - - TargetTransformInfo &TTI; - - /// Create a cloner for a switch lowering. - CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, - Kind FKind, TargetTransformInfo &TTI) - : OrigF(OrigF), NewF(nullptr), Suffix(Suffix), Shape(Shape), FKind(FKind), - Builder(OrigF.getContext()), TTI(TTI) { - assert(Shape.ABI == coro::ABI::Switch); - } - - /// Create a cloner for a continuation lowering. - CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, - Function *NewF, AnyCoroSuspendInst *ActiveSuspend, - TargetTransformInfo &TTI) - : OrigF(OrigF), NewF(NewF), Suffix(Suffix), Shape(Shape), - FKind(Shape.ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation), - Builder(OrigF.getContext()), ActiveSuspend(ActiveSuspend), TTI(TTI) { - assert(Shape.ABI == coro::ABI::Retcon || - Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async); - assert(NewF && "need existing function for continuation"); - assert(ActiveSuspend && "need active suspend point for continuation"); - } - -public: - /// Create a clone for a switch lowering. - static Function *createClone(Function &OrigF, const Twine &Suffix, - coro::Shape &Shape, Kind FKind, - TargetTransformInfo &TTI) { - TimeTraceScope FunctionScope("CoroCloner"); - - CoroCloner Cloner(OrigF, Suffix, Shape, FKind, TTI); - Cloner.create(); - return Cloner.getFunction(); - } - - /// Create a clone for a continuation lowering. - static Function *createClone(Function &OrigF, const Twine &Suffix, - coro::Shape &Shape, Function *NewF, - AnyCoroSuspendInst *ActiveSuspend, - TargetTransformInfo &TTI) { - TimeTraceScope FunctionScope("CoroCloner"); - - CoroCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI); - Cloner.create(); - return Cloner.getFunction(); - } - - Function *getFunction() const { - assert(NewF != nullptr && "declaration not yet set"); - return NewF; - } - - void create(); - -private: - bool isSwitchDestroyFunction() { - switch (FKind) { - case Kind::Async: - case Kind::Continuation: - case Kind::SwitchResume: - return false; - case Kind::SwitchUnwind: - case Kind::SwitchCleanup: - return true; - } - llvm_unreachable("Unknown CoroCloner::Kind enum"); - } - - void replaceEntryBlock(); - Value *deriveNewFramePointer(); - void replaceRetconOrAsyncSuspendUses(); - void replaceCoroSuspends(); - void replaceCoroEnds(); - void replaceSwiftErrorOps(); - void salvageDebugInfo(); - void handleFinalSuspend(); -}; - -} // end anonymous namespace - // FIXME: // Lower the intrinisc in CoroEarly phase if coroutine frame doesn't escape // and it is known that other transformations, for example, sanitizers @@ -985,11 +864,7 @@ static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context, /// Clone the body of the original function into a resume function of /// some sort. void CoroCloner::create() { - // Create the new function if we don't already have one. - if (!NewF) { - NewF = createCloneDeclaration(OrigF, Shape, Suffix, - OrigF.getParent()->end(), ActiveSuspend); - } + assert(NewF); // Replace all args with dummy instructions. If an argument is the old frame // pointer, the dummy will be replaced by the new frame pointer once it is @@ -1213,12 +1088,20 @@ void CoroCloner::create() { // Salvage debug info that points into the coroutine frame. salvageDebugInfo(); +} + +void CoroSwitchCloner::create() { + // Create a new function matching the original type + NewF = createCloneDeclaration(OrigF, Shape, Suffix, + OrigF.getParent()->end(), ActiveSuspend); + + // Clone the function + CoroCloner::create(); // Eliminate coro.free from the clones, replacing it with 'null' in cleanup, // to suppress deallocation code. - if (Shape.ABI == coro::ABI::Switch) - coro::replaceCoroFree(cast(VMap[Shape.CoroBegin->getId()]), - /*Elide=*/FKind == CoroCloner::Kind::SwitchCleanup); + coro::replaceCoroFree(cast(VMap[Shape.CoroBegin->getId()]), + /*Elide=*/FKind == CoroCloner::Kind::SwitchCleanup); } static void updateAsyncFuncPointerContextSize(coro::Shape &Shape) { @@ -1495,11 +1378,11 @@ struct SwitchCoroutineSplitter { // setting new entry block and replacing coro.suspend an appropriate value // to force resume or cleanup pass for every suspend point. createResumeEntryBlock(F, Shape); - auto *ResumeClone = CoroCloner::createClone( + auto *ResumeClone = CoroSwitchCloner::createClone( F, ".resume", Shape, CoroCloner::Kind::SwitchResume, TTI); - auto *DestroyClone = CoroCloner::createClone( + auto *DestroyClone = CoroSwitchCloner::createClone( F, ".destroy", Shape, CoroCloner::Kind::SwitchUnwind, TTI); - auto *CleanupClone = CoroCloner::createClone( + auto *CleanupClone = CoroSwitchCloner::createClone( F, ".cleanup", Shape, CoroCloner::Kind::SwitchCleanup, TTI); postSplitCleanup(*ResumeClone); From a2150ba115a05cd7542639d00ee7e11f0612f29d Mon Sep 17 00:00:00 2001 From: tnowicki Date: Tue, 19 Nov 2024 18:08:48 -0500 Subject: [PATCH 2/4] [Coroutines] Clang format --- llvm/lib/Transforms/Coroutines/CoroCloner.h | 15 +++++++-------- llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 8 ++++---- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/Coroutines/CoroCloner.h b/llvm/lib/Transforms/Coroutines/CoroCloner.h index e4e3976924e59..5f861d60facbb 100644 --- a/llvm/lib/Transforms/Coroutines/CoroCloner.h +++ b/llvm/lib/Transforms/Coroutines/CoroCloner.h @@ -51,7 +51,6 @@ class CoroCloner { Function *NewF = nullptr; Value *NewFramePtr = nullptr; - /// The active suspend instruction; meaningful only for continuation and async /// ABIs. AnyCoroSuspendInst *ActiveSuspend = nullptr; @@ -62,7 +61,8 @@ class CoroCloner { TargetTransformInfo &TTI) : OrigF(OrigF), Suffix(Suffix), Shape(Shape), FKind(Shape.ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation), - Builder(OrigF.getContext()), TTI(TTI), NewF(NewF), ActiveSuspend(ActiveSuspend) { + Builder(OrigF.getContext()), TTI(TTI), NewF(NewF), + ActiveSuspend(ActiveSuspend) { assert(Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async); assert(NewF && "need existing function for continuation"); @@ -71,11 +71,11 @@ class CoroCloner { public: CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, - Kind FKind, TargetTransformInfo &TTI) : - OrigF(OrigF), Suffix(Suffix), Shape(Shape), FKind(FKind), Builder(OrigF.getContext()), TTI(TTI) { - } + Kind FKind, TargetTransformInfo &TTI) + : OrigF(OrigF), Suffix(Suffix), Shape(Shape), FKind(FKind), + Builder(OrigF.getContext()), TTI(TTI) {} - virtual ~CoroCloner() { } + virtual ~CoroCloner() {} /// Create a clone for a continuation lowering. static Function *createClone(Function &OrigF, const Twine &Suffix, @@ -122,13 +122,12 @@ class CoroCloner { void handleFinalSuspend(); }; - class CoroSwitchCloner : public CoroCloner { protected: /// Create a cloner for a switch lowering. CoroSwitchCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, Kind FKind, TargetTransformInfo &TTI) - : CoroCloner(OrigF, Suffix, Shape, FKind, TTI) { } + : CoroCloner(OrigF, Suffix, Shape, FKind, TTI) {} void create() override; diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 147de7726d31b..184cd61810fa7 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -19,8 +19,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Transforms/Coroutines/CoroSplit.h" -#include "CoroInternal.h" #include "CoroCloner.h" +#include "CoroInternal.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PriorityWorklist.h" #include "llvm/ADT/STLExtras.h" @@ -1092,8 +1092,8 @@ void CoroCloner::create() { void CoroSwitchCloner::create() { // Create a new function matching the original type - NewF = createCloneDeclaration(OrigF, Shape, Suffix, - OrigF.getParent()->end(), ActiveSuspend); + NewF = createCloneDeclaration(OrigF, Shape, Suffix, OrigF.getParent()->end(), + ActiveSuspend); // Clone the function CoroCloner::create(); @@ -1101,7 +1101,7 @@ void CoroSwitchCloner::create() { // Eliminate coro.free from the clones, replacing it with 'null' in cleanup, // to suppress deallocation code. coro::replaceCoroFree(cast(VMap[Shape.CoroBegin->getId()]), - /*Elide=*/FKind == CoroCloner::Kind::SwitchCleanup); + /*Elide=*/FKind == CoroCloner::Kind::SwitchCleanup); } static void updateAsyncFuncPointerContextSize(coro::Shape &Shape) { From 207da54bb28271b4463636e27c3b69321670cb19 Mon Sep 17 00:00:00 2001 From: tnowicki Date: Thu, 28 Nov 2024 12:00:40 -0500 Subject: [PATCH 3/4] SWDEV-303548 - Put everything in the coro namespace and fixup class names --- llvm/lib/Transforms/Coroutines/CoroCloner.h | 93 +++++++++++--------- llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 2 +- llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 44 ++++----- 3 files changed, 74 insertions(+), 65 deletions(-) diff --git a/llvm/lib/Transforms/Coroutines/CoroCloner.h b/llvm/lib/Transforms/Coroutines/CoroCloner.h index 5f861d60facbb..d1887980fb3bc 100644 --- a/llvm/lib/Transforms/Coroutines/CoroCloner.h +++ b/llvm/lib/Transforms/Coroutines/CoroCloner.h @@ -9,7 +9,8 @@ // functions. //===----------------------------------------------------------------------===// -#pragma once +#ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H +#define LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" @@ -18,32 +19,33 @@ #include "llvm/Transforms/Coroutines/CoroInstr.h" #include "llvm/Transforms/Utils/ValueMapper.h" -using namespace llvm; +namespace llvm { -class CoroCloner { -public: - enum class Kind { - /// The shared resume function for a switch lowering. - SwitchResume, +namespace coro { + +enum class CloneKind { + /// The shared resume function for a switch lowering. + SwitchResume, - /// The shared unwind function for a switch lowering. - SwitchUnwind, + /// The shared unwind function for a switch lowering. + SwitchUnwind, - /// The shared cleanup function for a switch lowering. - SwitchCleanup, + /// The shared cleanup function for a switch lowering. + SwitchCleanup, - /// An individual continuation function. - Continuation, + /// An individual continuation function. + Continuation, - /// An async resume function. - Async, - }; + /// An async resume function. + Async, +}; +class BaseCloner { protected: Function &OrigF; const Twine &Suffix; coro::Shape &Shape; - Kind FKind; + CloneKind FKind; IRBuilder<> Builder; TargetTransformInfo &TTI; @@ -56,37 +58,38 @@ class CoroCloner { AnyCoroSuspendInst *ActiveSuspend = nullptr; /// Create a cloner for a continuation lowering. - CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, + BaseCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, Function *NewF, AnyCoroSuspendInst *ActiveSuspend, TargetTransformInfo &TTI) : OrigF(OrigF), Suffix(Suffix), Shape(Shape), - FKind(Shape.ABI == coro::ABI::Async ? Kind::Async : Kind::Continuation), + FKind(Shape.ABI == ABI::Async ? CloneKind::Async + : CloneKind::Continuation), Builder(OrigF.getContext()), TTI(TTI), NewF(NewF), ActiveSuspend(ActiveSuspend) { - assert(Shape.ABI == coro::ABI::Retcon || - Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async); + assert(Shape.ABI == ABI::Retcon || Shape.ABI == ABI::RetconOnce || + Shape.ABI == ABI::Async); assert(NewF && "need existing function for continuation"); assert(ActiveSuspend && "need active suspend point for continuation"); } public: - CoroCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, - Kind FKind, TargetTransformInfo &TTI) + BaseCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, + CloneKind FKind, TargetTransformInfo &TTI) : OrigF(OrigF), Suffix(Suffix), Shape(Shape), FKind(FKind), Builder(OrigF.getContext()), TTI(TTI) {} - virtual ~CoroCloner() {} + virtual ~BaseCloner() {} /// Create a clone for a continuation lowering. static Function *createClone(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, Function *NewF, AnyCoroSuspendInst *ActiveSuspend, TargetTransformInfo &TTI) { - assert(Shape.ABI == coro::ABI::Retcon || - Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async); - TimeTraceScope FunctionScope("CoroCloner"); + assert(Shape.ABI == ABI::Retcon || Shape.ABI == ABI::RetconOnce || + Shape.ABI == ABI::Async); + TimeTraceScope FunctionScope("BaseCloner"); - CoroCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI); + BaseCloner Cloner(OrigF, Suffix, Shape, NewF, ActiveSuspend, TTI); Cloner.create(); return Cloner.getFunction(); } @@ -101,15 +104,15 @@ class CoroCloner { protected: bool isSwitchDestroyFunction() { switch (FKind) { - case Kind::Async: - case Kind::Continuation: - case Kind::SwitchResume: + case CloneKind::Async: + case CloneKind::Continuation: + case CloneKind::SwitchResume: return false; - case Kind::SwitchUnwind: - case Kind::SwitchCleanup: + case CloneKind::SwitchUnwind: + case CloneKind::SwitchCleanup: return true; } - llvm_unreachable("Unknown CoroCloner::Kind enum"); + llvm_unreachable("Unknown ClonerKind enum"); } void replaceEntryBlock(); @@ -122,25 +125,31 @@ class CoroCloner { void handleFinalSuspend(); }; -class CoroSwitchCloner : public CoroCloner { +class SwitchCloner : public BaseCloner { protected: /// Create a cloner for a switch lowering. - CoroSwitchCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, - Kind FKind, TargetTransformInfo &TTI) - : CoroCloner(OrigF, Suffix, Shape, FKind, TTI) {} + SwitchCloner(Function &OrigF, const Twine &Suffix, coro::Shape &Shape, + CloneKind FKind, TargetTransformInfo &TTI) + : BaseCloner(OrigF, Suffix, Shape, FKind, TTI) {} void create() override; public: /// Create a clone for a switch lowering. static Function *createClone(Function &OrigF, const Twine &Suffix, - coro::Shape &Shape, Kind FKind, + coro::Shape &Shape, CloneKind FKind, TargetTransformInfo &TTI) { - assert(Shape.ABI == coro::ABI::Switch); - TimeTraceScope FunctionScope("CoroCloner"); + assert(Shape.ABI == ABI::Switch); + TimeTraceScope FunctionScope("SwitchCloner"); - CoroSwitchCloner Cloner(OrigF, Suffix, Shape, FKind, TTI); + SwitchCloner Cloner(OrigF, Suffix, Shape, FKind, TTI); Cloner.create(); return Cloner.getFunction(); } }; + +} // end namespace coro + +} // end namespace llvm + +#endif // LLVM_LIB_TRANSFORMS_COROUTINES_COROCLONER_H diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 441a83310c632..ee8563351121c 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -1133,7 +1133,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { bool AllowUnresolved = false; // This dbg.declare is preserved for all coro-split function // fragments. It will be unreachable in the main function, and - // processed by coro::salvageDebugInfo() by CoroCloner. + // processed by coro::salvageDebugInfo() by BaseCloner. if (UseNewDbgInfoFormat) { DbgVariableRecord *NewDVR = new DbgVariableRecord( ValueAsMetadata::get(CurrentReload), DDI->getVariable(), diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 184cd61810fa7..3808147fc2600 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -402,7 +402,7 @@ static void replaceCoroEnd(AnyCoroEndInst *End, const coro::Shape &Shape, // is possible since the coroutine is considered suspended at the final suspend // point if promise.unhandled_exception() exits via an exception), we can // remove the last case. -void CoroCloner::handleFinalSuspend() { +void coro::BaseCloner::handleFinalSuspend() { assert(Shape.ABI == coro::ABI::Switch && Shape.SwitchLowering.HasFinalSuspend); @@ -466,7 +466,7 @@ static Function *createCloneDeclaration(Function &OrigF, coro::Shape &Shape, /// arguments to the continuation function. /// /// This assumes that the builder has a meaningful insertion point. -void CoroCloner::replaceRetconOrAsyncSuspendUses() { +void coro::BaseCloner::replaceRetconOrAsyncSuspendUses() { assert(Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce || Shape.ABI == coro::ABI::Async); @@ -514,7 +514,7 @@ void CoroCloner::replaceRetconOrAsyncSuspendUses() { NewS->replaceAllUsesWith(Aggr); } -void CoroCloner::replaceCoroSuspends() { +void coro::BaseCloner::replaceCoroSuspends() { Value *SuspendResult; switch (Shape.ABI) { @@ -551,7 +551,7 @@ void CoroCloner::replaceCoroSuspends() { } } -void CoroCloner::replaceCoroEnds() { +void coro::BaseCloner::replaceCoroEnds() { for (AnyCoroEndInst *CE : Shape.CoroEnds) { // We use a null call graph because there's no call graph node for // the cloned function yet. We'll just be rebuilding that later. @@ -630,11 +630,11 @@ collectDbgVariableIntrinsics(Function &F) { return {Intrinsics, DbgVariableRecords}; } -void CoroCloner::replaceSwiftErrorOps() { +void coro::BaseCloner::replaceSwiftErrorOps() { ::replaceSwiftErrorOps(*NewF, Shape, &VMap); } -void CoroCloner::salvageDebugInfo() { +void coro::BaseCloner::salvageDebugInfo() { auto [Worklist, DbgVariableRecords] = collectDbgVariableIntrinsics(*NewF); SmallDenseMap ArgToAllocaMap; @@ -671,7 +671,7 @@ void CoroCloner::salvageDebugInfo() { for_each(DbgVariableRecords, RemoveOne); } -void CoroCloner::replaceEntryBlock() { +void coro::BaseCloner::replaceEntryBlock() { // In the original function, the AllocaSpillBlock is a block immediately // following the allocation of the frame object which defines GEPs for // all the allocas that have been moved into the frame, and it ends by @@ -739,7 +739,7 @@ void CoroCloner::replaceEntryBlock() { } /// Derive the value of the new frame pointer. -Value *CoroCloner::deriveNewFramePointer() { +Value *coro::BaseCloner::deriveNewFramePointer() { // Builder should be inserting to the front of the new entry block. switch (Shape.ABI) { @@ -863,7 +863,7 @@ static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context, /// Clone the body of the original function into a resume function of /// some sort. -void CoroCloner::create() { +void coro::BaseCloner::create() { assert(NewF); // Replace all args with dummy instructions. If an argument is the old frame @@ -1090,18 +1090,18 @@ void CoroCloner::create() { salvageDebugInfo(); } -void CoroSwitchCloner::create() { +void coro::SwitchCloner::create() { // Create a new function matching the original type NewF = createCloneDeclaration(OrigF, Shape, Suffix, OrigF.getParent()->end(), ActiveSuspend); // Clone the function - CoroCloner::create(); + coro::BaseCloner::create(); // Eliminate coro.free from the clones, replacing it with 'null' in cleanup, // to suppress deallocation code. coro::replaceCoroFree(cast(VMap[Shape.CoroBegin->getId()]), - /*Elide=*/FKind == CoroCloner::Kind::SwitchCleanup); + /*Elide=*/FKind == coro::CloneKind::SwitchCleanup); } static void updateAsyncFuncPointerContextSize(coro::Shape &Shape) { @@ -1378,12 +1378,12 @@ struct SwitchCoroutineSplitter { // setting new entry block and replacing coro.suspend an appropriate value // to force resume or cleanup pass for every suspend point. createResumeEntryBlock(F, Shape); - auto *ResumeClone = CoroSwitchCloner::createClone( - F, ".resume", Shape, CoroCloner::Kind::SwitchResume, TTI); - auto *DestroyClone = CoroSwitchCloner::createClone( - F, ".destroy", Shape, CoroCloner::Kind::SwitchUnwind, TTI); - auto *CleanupClone = CoroSwitchCloner::createClone( - F, ".cleanup", Shape, CoroCloner::Kind::SwitchCleanup, TTI); + auto *ResumeClone = coro::SwitchCloner::createClone( + F, ".resume", Shape, coro::CloneKind::SwitchResume, TTI); + auto *DestroyClone = coro::SwitchCloner::createClone( + F, ".destroy", Shape, coro::CloneKind::SwitchUnwind, TTI); + auto *CleanupClone = coro::SwitchCloner::createClone( + F, ".cleanup", Shape, coro::CloneKind::SwitchCleanup, TTI); postSplitCleanup(*ResumeClone); postSplitCleanup(*DestroyClone); @@ -1772,8 +1772,8 @@ void coro::AsyncABI::splitCoroutine(Function &F, coro::Shape &Shape, auto *Suspend = CS; auto *Clone = Clones[Idx]; - CoroCloner::createClone(F, "resume." + Twine(Idx), Shape, Clone, Suspend, - TTI); + coro::BaseCloner::createClone(F, "resume." + Twine(Idx), Shape, Clone, + Suspend, TTI); } } @@ -1903,8 +1903,8 @@ void coro::AnyRetconABI::splitCoroutine(Function &F, coro::Shape &Shape, auto Suspend = CS; auto Clone = Clones[Idx]; - CoroCloner::createClone(F, "resume." + Twine(Idx), Shape, Clone, Suspend, - TTI); + coro::BaseCloner::createClone(F, "resume." + Twine(Idx), Shape, Clone, + Suspend, TTI); } } From 7b062e13ac1aa5b9d1893e0851177810c45e6ae3 Mon Sep 17 00:00:00 2001 From: tnowicki Date: Thu, 28 Nov 2024 13:51:51 -0500 Subject: [PATCH 4/4] SWDEV-303548 - Fixed comment --- llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index ee8563351121c..d3732fec603f6 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -1133,7 +1133,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { bool AllowUnresolved = false; // This dbg.declare is preserved for all coro-split function // fragments. It will be unreachable in the main function, and - // processed by coro::salvageDebugInfo() by BaseCloner. + // processed by coro::salvageDebugInfo() by the Cloner. if (UseNewDbgInfoFormat) { DbgVariableRecord *NewDVR = new DbgVariableRecord( ValueAsMetadata::get(CurrentReload), DDI->getVariable(),