[llvm] [Coroutines][NFC] Refactor CoroCloner (PR #116885)

Tyler Nowicki via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 28 10:52:07 PST 2024


https://github.com/TylerNowicki updated https://github.com/llvm/llvm-project/pull/116885

>From 3903379fcef4404405428e0ba7c5767fd7d1c7a0 Mon Sep 17 00:00:00 2001
From: tnowicki <tyler.nowicki at amd.com>
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 00000000000000..e4e3976924e59a
--- /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 8a5bae9f6f0d4b..147de7726d31be 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 <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -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<CoroIdInst>(VMap[Shape.CoroBegin->getId()]),
-                          /*Elide=*/FKind == CoroCloner::Kind::SwitchCleanup);
+  coro::replaceCoroFree(cast<CoroIdInst>(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 <tyler.nowicki at amd.com>
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 e4e3976924e59a..5f861d60facbb5 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 147de7726d31be..184cd61810fa71 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<CoroIdInst>(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 <tyler.nowicki at amd.com>
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 5f861d60facbb5..d1887980fb3bcb 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 441a83310c6326..ee8563351121cf 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 184cd61810fa71..3808147fc26009 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<Argument *, AllocaInst *, 4> 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<CoroIdInst>(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 <tyler.nowicki at amd.com>
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 ee8563351121cf..d3732fec603f6f 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(),



More information about the llvm-commits mailing list