Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Coroutines] ABI Objects to improve code separation between different ABIs, users and utilities. #109338

Merged

Conversation

TylerNowicki
Copy link
Collaborator

  • Adds an ABI object class hierarchy to implement the coroutine ABIs (Switch, Asyc, and Retcon{Once})
  • The ABI object improves the separation of the code related to users, ABIs and utilities.
  • No code changes are required by any existing users.
  • Each ABI overrides delegate methods for initialization, building the coroutine frame and splitting the coroutine, other methods may be added later.
  • CoroSplit invokes a generator lambda to instantiate the ABI object and calls the ABI object to carry out its primary operations. In a follow-up change this will be used to instantiated customized ABIs according to a new intrinsic llvm.coro.begin.custom.abi.
  • Note, in a follow-up change additional constructors will be added to the ABI objects (Switch, Asyc, and AnyRetcon) to allow a set of generator lambdas to be passed in from a CoroSplit constructor that will also be added. The init() method is separate from the constructor to avoid duplication of its code. It is a virtual method so it can be invoked by CreateAndInitABI or potentially CoroSplit::run(). I wasn't sure if we should call init() from within CoroSplit::run(), CreateAndInitABI, or perhaps hard code a call in each constructor. One consideration is that init() can change the IR, so perhaps it should appear in CoroSplit::run(), but this looks a bit odd. Invoking init() in the constructor would result in the call appearing 4 times per ABI (after adding the new constructors). Invoking it in CreateAndInitABI seems to be a balance between these.

See RFC for more info:
https://discourse.llvm.org/t/rfc-abi-objects-for-coroutines/81057

* Define an ABI object for Switch, Retcon, and Async lowerings
* Perform initialization of each type of lowering as part of ABI
  initialization.
* Make buildCoroutineFrame and splitCoroutine interfaces to the ABI.
@llvmbot
Copy link
Collaborator

llvmbot commented Sep 19, 2024

@llvm/pr-subscribers-coroutines

@llvm/pr-subscribers-llvm-transforms

Author: Tyler Nowicki (TylerNowicki)

Changes
  • Adds an ABI object class hierarchy to implement the coroutine ABIs (Switch, Asyc, and Retcon{Once})
  • The ABI object improves the separation of the code related to users, ABIs and utilities.
  • No code changes are required by any existing users.
  • Each ABI overrides delegate methods for initialization, building the coroutine frame and splitting the coroutine, other methods may be added later.
  • CoroSplit invokes a generator lambda to instantiate the ABI object and calls the ABI object to carry out its primary operations. In a follow-up change this will be used to instantiated customized ABIs according to a new intrinsic llvm.coro.begin.custom.abi.
  • Note, in a follow-up change additional constructors will be added to the ABI objects (Switch, Asyc, and AnyRetcon) to allow a set of generator lambdas to be passed in from a CoroSplit constructor that will also be added. The init() method is separate from the constructor to avoid duplication of its code. It is a virtual method so it can be invoked by CreateAndInitABI or potentially CoroSplit::run(). I wasn't sure if we should call init() from within CoroSplit::run(), CreateAndInitABI, or perhaps hard code a call in each constructor. One consideration is that init() can change the IR, so perhaps it should appear in CoroSplit::run(), but this looks a bit odd. Invoking init() in the constructor would result in the call appearing 4 times per ABI (after adding the new constructors). Invoking it in CreateAndInitABI seems to be a balance between these.

See RFC for more info:
https://discourse.llvm.org/t/rfc-abi-objects-for-coroutines/81057


Full diff: https://github.com/llvm/llvm-project/pull/109338.diff

7 Files Affected:

  • (modified) llvm/include/llvm/Transforms/Coroutines/CoroSplit.h (+11-4)
  • (added) llvm/lib/Transforms/Coroutines/ABI.h (+109)
  • (modified) llvm/lib/Transforms/Coroutines/CoroFrame.cpp (+3-4)
  • (modified) llvm/lib/Transforms/Coroutines/CoroInternal.h (-3)
  • (modified) llvm/lib/Transforms/Coroutines/CoroShape.h (-1)
  • (modified) llvm/lib/Transforms/Coroutines/CoroSplit.cpp (+81-36)
  • (modified) llvm/lib/Transforms/Coroutines/Coroutines.cpp (+20-23)
diff --git a/llvm/include/llvm/Transforms/Coroutines/CoroSplit.h b/llvm/include/llvm/Transforms/Coroutines/CoroSplit.h
index a2be1099ff68fc..944ce602d4c108 100644
--- a/llvm/include/llvm/Transforms/Coroutines/CoroSplit.h
+++ b/llvm/include/llvm/Transforms/Coroutines/CoroSplit.h
@@ -21,19 +21,26 @@
 
 namespace llvm {
 
+namespace coro {
+class BaseABI;
+class Shape;
+} // namespace coro
+
 struct CoroSplitPass : PassInfoMixin<CoroSplitPass> {
-  const std::function<bool(Instruction &)> MaterializableCallback;
+  // BaseABITy generates an instance of a coro ABI.
+  using BaseABITy = std::function<coro::BaseABI *(Function &, coro::Shape &)>;
 
   CoroSplitPass(bool OptimizeFrame = false);
   CoroSplitPass(std::function<bool(Instruction &)> MaterializableCallback,
-                bool OptimizeFrame = false)
-      : MaterializableCallback(MaterializableCallback),
-        OptimizeFrame(OptimizeFrame) {}
+                bool OptimizeFrame = false);
 
   PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM,
                         LazyCallGraph &CG, CGSCCUpdateResult &UR);
   static bool isRequired() { return true; }
 
+  // Generator for an ABI transformer
+  BaseABITy CreateAndInitABI;
+
   // Would be true if the Optimization level isn't O0.
   bool OptimizeFrame;
 };
diff --git a/llvm/lib/Transforms/Coroutines/ABI.h b/llvm/lib/Transforms/Coroutines/ABI.h
new file mode 100644
index 00000000000000..20ef06f50c2faa
--- /dev/null
+++ b/llvm/lib/Transforms/Coroutines/ABI.h
@@ -0,0 +1,109 @@
+//===- ABI.h - Coroutine ABI Transformers ---------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+// This file declares the pass that analyzes a function for coroutine intrs and
+// a transformer class that contains methods for handling different steps of
+// coroutine lowering.
+//===----------------------------------------------------------------------===//
+
+#ifndef LIB_TRANSFORMS_COROUTINES_ABI_H
+#define LIB_TRANSFORMS_COROUTINES_ABI_H
+
+#include "CoroShape.h"
+#include "MaterializationUtils.h"
+#include "SuspendCrossingInfo.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+
+namespace llvm {
+
+class Function;
+
+namespace coro {
+
+// This interface/API is to provide an object oriented way to implement ABI
+// functionality. This is intended to replace use of the ABI enum to perform
+// ABI operations. The ABIs (e.g. Switch, Async, Retcon{Once}) are the common
+// ABIs.
+
+class LLVM_LIBRARY_VISIBILITY BaseABI {
+public:
+  BaseABI(Function &F, Shape &S)
+      : F(F), Shape(S), IsMaterializable(coro::isTriviallyMaterializable) {}
+
+  BaseABI(Function &F, coro::Shape &S,
+          std::function<bool(Instruction &)> IsMaterializable)
+      : F(F), Shape(S), IsMaterializable(IsMaterializable) {}
+
+  // Initialize the coroutine ABI
+  virtual void init() = 0;
+
+  // Allocate the coroutine frame and do spill/reload as needed.
+  virtual void buildCoroutineFrame();
+
+  // Perform the function splitting according to the ABI.
+  virtual void splitCoroutine(Function &F, coro::Shape &Shape,
+                              SmallVectorImpl<Function *> &Clones,
+                              TargetTransformInfo &TTI) = 0;
+
+  Function &F;
+  coro::Shape &Shape;
+
+  // Callback used by coro::BaseABI::buildCoroutineFrame for rematerialization.
+  // It is provided to coro::doMaterializations(..).
+  std::function<bool(Instruction &I)> IsMaterializable;
+};
+
+class LLVM_LIBRARY_VISIBILITY SwitchABI : public BaseABI {
+public:
+  SwitchABI(Function &F, coro::Shape &S) : BaseABI(F, S) {}
+
+  SwitchABI(Function &F, coro::Shape &S,
+            std::function<bool(Instruction &)> IsMaterializable)
+      : BaseABI(F, S, IsMaterializable) {}
+
+  void init() override;
+
+  void splitCoroutine(Function &F, coro::Shape &Shape,
+                      SmallVectorImpl<Function *> &Clones,
+                      TargetTransformInfo &TTI) override;
+};
+
+class LLVM_LIBRARY_VISIBILITY AsyncABI : public BaseABI {
+public:
+  AsyncABI(Function &F, coro::Shape &S) : BaseABI(F, S) {}
+
+  AsyncABI(Function &F, coro::Shape &S,
+           std::function<bool(Instruction &)> IsMaterializable)
+      : BaseABI(F, S, IsMaterializable) {}
+
+  void init() override;
+
+  void splitCoroutine(Function &F, coro::Shape &Shape,
+                      SmallVectorImpl<Function *> &Clones,
+                      TargetTransformInfo &TTI) override;
+};
+
+class LLVM_LIBRARY_VISIBILITY AnyRetconABI : public BaseABI {
+public:
+  AnyRetconABI(Function &F, coro::Shape &S) : BaseABI(F, S) {}
+
+  AnyRetconABI(Function &F, coro::Shape &S,
+               std::function<bool(Instruction &)> IsMaterializable)
+      : BaseABI(F, S, IsMaterializable) {}
+
+  void init() override;
+
+  void splitCoroutine(Function &F, coro::Shape &Shape,
+                      SmallVectorImpl<Function *> &Clones,
+                      TargetTransformInfo &TTI) override;
+};
+
+} // end namespace coro
+
+} // end namespace llvm
+
+#endif // LLVM_TRANSFORMS_COROUTINES_ABI_H
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index c08f56b024dfc7..021b1f7a4156b9 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -15,6 +15,7 @@
 // the value into the coroutine frame.
 //===----------------------------------------------------------------------===//
 
+#include "ABI.h"
 #include "CoroInternal.h"
 #include "MaterializationUtils.h"
 #include "SpillUtils.h"
@@ -2055,11 +2056,9 @@ void coro::normalizeCoroutine(Function &F, coro::Shape &Shape,
   rewritePHIs(F);
 }
 
-void coro::buildCoroutineFrame(
-    Function &F, Shape &Shape,
-    const std::function<bool(Instruction &)> &MaterializableCallback) {
+void coro::BaseABI::buildCoroutineFrame() {
   SuspendCrossingInfo Checker(F, Shape.CoroSuspends, Shape.CoroEnds);
-  doRematerializations(F, Checker, MaterializableCallback);
+  doRematerializations(F, Checker, IsMaterializable);
 
   const DominatorTree DT(F);
   if (Shape.ABI != coro::ABI::Async && Shape.ABI != coro::ABI::Retcon &&
diff --git a/llvm/lib/Transforms/Coroutines/CoroInternal.h b/llvm/lib/Transforms/Coroutines/CoroInternal.h
index fcbd31878bdea7..88d0f83c98c9ec 100644
--- a/llvm/lib/Transforms/Coroutines/CoroInternal.h
+++ b/llvm/lib/Transforms/Coroutines/CoroInternal.h
@@ -62,9 +62,6 @@ struct LowererBase {
 bool defaultMaterializable(Instruction &V);
 void normalizeCoroutine(Function &F, coro::Shape &Shape,
                         TargetTransformInfo &TTI);
-void buildCoroutineFrame(
-    Function &F, Shape &Shape,
-    const std::function<bool(Instruction &)> &MaterializableCallback);
 CallInst *createMustTailCall(DebugLoc Loc, Function *MustTailCallFn,
                              TargetTransformInfo &TTI,
                              ArrayRef<Value *> Arguments, IRBuilder<> &);
diff --git a/llvm/lib/Transforms/Coroutines/CoroShape.h b/llvm/lib/Transforms/Coroutines/CoroShape.h
index dcfe94ca076bd8..f4fb4baa6df314 100644
--- a/llvm/lib/Transforms/Coroutines/CoroShape.h
+++ b/llvm/lib/Transforms/Coroutines/CoroShape.h
@@ -275,7 +275,6 @@ struct LLVM_LIBRARY_VISIBILITY Shape {
       invalidateCoroutine(F, CoroFrames);
       return;
     }
-    initABI();
     cleanCoroutine(CoroFrames, UnusedCoroSaves);
   }
 };
diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
index 382bdfff1926f7..a17e16cc8e2233 100644
--- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
@@ -19,6 +19,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Transforms/Coroutines/CoroSplit.h"
+#include "ABI.h"
 #include "CoroInstr.h"
 #include "CoroInternal.h"
 #include "llvm/ADT/DenseMap.h"
@@ -1779,9 +1780,9 @@ CallInst *coro::createMustTailCall(DebugLoc Loc, Function *MustTailCallFn,
   return TailCall;
 }
 
-static void splitAsyncCoroutine(Function &F, coro::Shape &Shape,
-                                SmallVectorImpl<Function *> &Clones,
-                                TargetTransformInfo &TTI) {
+void coro::AsyncABI::splitCoroutine(Function &F, coro::Shape &Shape,
+                                    SmallVectorImpl<Function *> &Clones,
+                                    TargetTransformInfo &TTI) {
   assert(Shape.ABI == coro::ABI::Async);
   assert(Clones.empty());
   // Reset various things that the optimizer might have decided it
@@ -1874,9 +1875,9 @@ static void splitAsyncCoroutine(Function &F, coro::Shape &Shape,
   }
 }
 
-static void splitRetconCoroutine(Function &F, coro::Shape &Shape,
-                                 SmallVectorImpl<Function *> &Clones,
-                                 TargetTransformInfo &TTI) {
+void coro::AnyRetconABI::splitCoroutine(Function &F, coro::Shape &Shape,
+                                        SmallVectorImpl<Function *> &Clones,
+                                        TargetTransformInfo &TTI) {
   assert(Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce);
   assert(Clones.empty());
 
@@ -2044,26 +2045,27 @@ static bool hasSafeElideCaller(Function &F) {
   return false;
 }
 
-static coro::Shape
-splitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
-               TargetTransformInfo &TTI, bool OptimizeFrame,
-               std::function<bool(Instruction &)> MaterializableCallback) {
-  PrettyStackTraceFunction prettyStackTrace(F);
+void coro::SwitchABI::splitCoroutine(Function &F, coro::Shape &Shape,
+                                     SmallVectorImpl<Function *> &Clones,
+                                     TargetTransformInfo &TTI) {
+  SwitchCoroutineSplitter::split(F, Shape, Clones, TTI);
+}
 
-  // The suspend-crossing algorithm in buildCoroutineFrame get tripped
-  // up by uses in unreachable blocks, so remove them as a first pass.
-  removeUnreachableBlocks(F);
+static void doSplitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
+                             coro::BaseABI &ABI, TargetTransformInfo &TTI) {
+  PrettyStackTraceFunction prettyStackTrace(F);
 
-  coro::Shape Shape(F, OptimizeFrame);
-  if (!Shape.CoroBegin)
-    return Shape;
+  auto &Shape = ABI.Shape;
+  assert(Shape.CoroBegin);
 
   lowerAwaitSuspends(F, Shape);
 
   simplifySuspendPoints(Shape);
+
   normalizeCoroutine(F, Shape, TTI);
-  buildCoroutineFrame(F, Shape, MaterializableCallback);
+  ABI.buildCoroutineFrame();
   replaceFrameSizeAndAlignment(Shape);
+
   bool isNoSuspendCoroutine = Shape.CoroSuspends.empty();
 
   bool shouldCreateNoAllocVariant = !isNoSuspendCoroutine &&
@@ -2075,18 +2077,7 @@ splitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
   if (isNoSuspendCoroutine) {
     handleNoSuspendCoroutine(Shape);
   } else {
-    switch (Shape.ABI) {
-    case coro::ABI::Switch:
-      SwitchCoroutineSplitter::split(F, Shape, Clones, TTI);
-      break;
-    case coro::ABI::Async:
-      splitAsyncCoroutine(F, Shape, Clones, TTI);
-      break;
-    case coro::ABI::Retcon:
-    case coro::ABI::RetconOnce:
-      splitRetconCoroutine(F, Shape, Clones, TTI);
-      break;
-    }
+    ABI.splitCoroutine(F, Shape, Clones, TTI);
   }
 
   // Replace all the swifterror operations in the original function.
@@ -2107,8 +2098,6 @@ splitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
 
   if (shouldCreateNoAllocVariant)
     SwitchCoroutineSplitter::createNoAllocVariant(F, Shape, Clones);
-
-  return Shape;
 }
 
 static LazyCallGraph::SCC &updateCallGraphAfterCoroutineSplit(
@@ -2207,8 +2196,53 @@ static void addPrepareFunction(const Module &M,
     Fns.push_back(PrepareFn);
 }
 
+static coro::BaseABI *CreateNewABI(Function &F, coro::Shape &S) {
+  switch (S.ABI) {
+  case coro::ABI::Switch:
+    return new coro::SwitchABI(F, S);
+  case coro::ABI::Async:
+    return new coro::AsyncABI(F, S);
+  case coro::ABI::Retcon:
+    return new coro::AnyRetconABI(F, S);
+  case coro::ABI::RetconOnce:
+    return new coro::AnyRetconABI(F, S);
+  }
+  llvm_unreachable("Unknown ABI");
+}
+
 CoroSplitPass::CoroSplitPass(bool OptimizeFrame)
-    : MaterializableCallback(coro::defaultMaterializable),
+    : CreateAndInitABI([](Function &F, coro::Shape &S) {
+        coro::BaseABI *ABI = CreateNewABI(F, S);
+        ABI->init();
+        return ABI;
+      }),
+      OptimizeFrame(OptimizeFrame) {}
+
+static coro::BaseABI *
+CreateNewABIIsMat(Function &F, coro::Shape &S,
+                  std::function<bool(Instruction &)> IsMatCallback) {
+  switch (S.ABI) {
+  case coro::ABI::Switch:
+    return new coro::SwitchABI(F, S, IsMatCallback);
+  case coro::ABI::Async:
+    return new coro::AsyncABI(F, S, IsMatCallback);
+  case coro::ABI::Retcon:
+    return new coro::AnyRetconABI(F, S, IsMatCallback);
+  case coro::ABI::RetconOnce:
+    return new coro::AnyRetconABI(F, S, IsMatCallback);
+  }
+  llvm_unreachable("Unknown ABI");
+}
+
+// For back compatibility, constructor takes a materializable callback and
+// creates a generator for an ABI with a modified materializable callback.
+CoroSplitPass::CoroSplitPass(std::function<bool(Instruction &)> IsMatCallback,
+                             bool OptimizeFrame)
+    : CreateAndInitABI([=](Function &F, coro::Shape &S) {
+        coro::BaseABI *ABI = CreateNewABIIsMat(F, S, IsMatCallback);
+        ABI->init();
+        return ABI;
+      }),
       OptimizeFrame(OptimizeFrame) {}
 
 PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
@@ -2241,12 +2275,23 @@ PreservedAnalyses CoroSplitPass::run(LazyCallGraph::SCC &C,
     Function &F = N->getFunction();
     LLVM_DEBUG(dbgs() << "CoroSplit: Processing coroutine '" << F.getName()
                       << "\n");
+
+    // The suspend-crossing algorithm in buildCoroutineFrame gets tripped up
+    // by unreachable blocks, so remove them as a first pass. Remove the
+    // unreachable blocks before collecting intrinsics into Shape.
+    removeUnreachableBlocks(F);
+
+    coro::Shape Shape(F, OptimizeFrame);
+    if (!Shape.CoroBegin)
+      continue;
+
     F.setSplittedCoroutine();
 
+    std::unique_ptr<coro::BaseABI> ABI(CreateAndInitABI(F, Shape));
+
     SmallVector<Function *, 4> Clones;
-    coro::Shape Shape =
-        splitCoroutine(F, Clones, FAM.getResult<TargetIRAnalysis>(F),
-                       OptimizeFrame, MaterializableCallback);
+    auto &TTI = FAM.getResult<TargetIRAnalysis>(F);
+    doSplitCoroutine(F, Clones, *ABI, TTI);
     CurrentSCC = &updateCallGraphAfterCoroutineSplit(
         *N, Shape, Clones, *CurrentSCC, CG, AM, UR, FAM);
 
diff --git a/llvm/lib/Transforms/Coroutines/Coroutines.cpp b/llvm/lib/Transforms/Coroutines/Coroutines.cpp
index ef0abd2d823bbd..c7a04b8fd965b7 100644
--- a/llvm/lib/Transforms/Coroutines/Coroutines.cpp
+++ b/llvm/lib/Transforms/Coroutines/Coroutines.cpp
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "ABI.h"
 #include "CoroInstr.h"
 #include "CoroInternal.h"
 #include "CoroShape.h"
@@ -372,11 +373,10 @@ void coro::Shape::invalidateCoroutine(
   }
 }
 
-// Perform semantic checking and initialization of the ABI
-void coro::Shape::initABI() {
-  switch (ABI) {
-  case coro::ABI::Switch: {
-    for (auto *AnySuspend : CoroSuspends) {
+void coro::SwitchABI::init() {
+  assert(Shape.ABI == coro::ABI::Switch);
+  {
+    for (auto *AnySuspend : Shape.CoroSuspends) {
       auto Suspend = dyn_cast<CoroSuspendInst>(AnySuspend);
       if (!Suspend) {
 #ifndef NDEBUG
@@ -386,21 +386,22 @@ void coro::Shape::initABI() {
       }
 
       if (!Suspend->getCoroSave())
-        createCoroSave(CoroBegin, Suspend);
+        createCoroSave(Shape.CoroBegin, Suspend);
     }
-    break;
   }
-  case coro::ABI::Async: {
-    break;
-  };
-  case coro::ABI::Retcon:
-  case coro::ABI::RetconOnce: {
+}
+
+void coro::AsyncABI::init() { assert(Shape.ABI == coro::ABI::Async); }
+
+void coro::AnyRetconABI::init() {
+  assert(Shape.ABI == coro::ABI::Retcon || Shape.ABI == coro::ABI::RetconOnce);
+  {
     // Determine the result value types, and make sure they match up with
     // the values passed to the suspends.
-    auto ResultTys = getRetconResultTypes();
-    auto ResumeTys = getRetconResumeTypes();
+    auto ResultTys = Shape.getRetconResultTypes();
+    auto ResumeTys = Shape.getRetconResumeTypes();
 
-    for (auto *AnySuspend : CoroSuspends) {
+    for (auto *AnySuspend : Shape.CoroSuspends) {
       auto Suspend = dyn_cast<CoroSuspendRetconInst>(AnySuspend);
       if (!Suspend) {
 #ifndef NDEBUG
@@ -427,7 +428,7 @@ void coro::Shape::initABI() {
 
 #ifndef NDEBUG
           Suspend->dump();
-          RetconLowering.ResumePrototype->getFunctionType()->dump();
+          Shape.RetconLowering.ResumePrototype->getFunctionType()->dump();
 #endif
           report_fatal_error("argument to coro.suspend.retcon does not "
                              "match corresponding prototype function result");
@@ -436,7 +437,7 @@ void coro::Shape::initABI() {
       if (SI != SE || RI != RE) {
 #ifndef NDEBUG
         Suspend->dump();
-        RetconLowering.ResumePrototype->getFunctionType()->dump();
+        Shape.RetconLowering.ResumePrototype->getFunctionType()->dump();
 #endif
         report_fatal_error("wrong number of arguments to coro.suspend.retcon");
       }
@@ -455,7 +456,7 @@ void coro::Shape::initABI() {
       if (SuspendResultTys.size() != ResumeTys.size()) {
 #ifndef NDEBUG
         Suspend->dump();
-        RetconLowering.ResumePrototype->getFunctionType()->dump();
+        Shape.RetconLowering.ResumePrototype->getFunctionType()->dump();
 #endif
         report_fatal_error("wrong number of results from coro.suspend.retcon");
       }
@@ -463,17 +464,13 @@ void coro::Shape::initABI() {
         if (SuspendResultTys[I] != ResumeTys[I]) {
 #ifndef NDEBUG
           Suspend->dump();
-          RetconLowering.ResumePrototype->getFunctionType()->dump();
+          Shape.RetconLowering.ResumePrototype->getFunctionType()->dump();
 #endif
           report_fatal_error("result from coro.suspend.retcon does not "
                              "match corresponding prototype function param");
         }
       }
     }
-    break;
-  }
-  default:
-    llvm_unreachable("coro.begin is not dependent on a coro.id call");
   }
 }
 

Copy link
Member

@ChuanqiXu9 ChuanqiXu9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with nits

struct CoroSplitPass : PassInfoMixin<CoroSplitPass> {
const std::function<bool(Instruction &)> MaterializableCallback;
// BaseABITy generates an instance of a coro ABI.
using BaseABITy = std::function<coro::BaseABI *(Function &, coro::Shape &)>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move the definition and its use closer. And also BaseABITy may not be good name. If it is only used once, maybe it is not to not give it a name right now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -0,0 +1,109 @@
//===- ABI.h - Coroutine ABI Transformers ---------------------*- C++ -*---===//
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought the name ABI Transformers will transform ABIs to ABIs. But it is not the case right? I feel the name may not necessary here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this! I had originally used the name Transformers instead of ABI object, so the SwitchABI would be the SwitchTransformer. But that was a bit confusing (as you point out) and in the end it made more sense to drop 'Transformer'. I missed this one...

// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// This file declares the pass that analyzes a function for coroutine intrs and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a pass.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I improved the file description.

static coro::BaseABI *CreateNewABI(Function &F, coro::Shape &S) {
switch (S.ABI) {
case coro::ABI::Switch:
return new coro::SwitchABI(F, S);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's try to use std::unique_ptr here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. To do this I had to propagate unique_ptr to a few other lines and make use of std::move in a couple of places.

OptimizeFrame(OptimizeFrame) {}

static coro::BaseABI *
CreateNewABIIsMat(Function &F, coro::Shape &S,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
CreateNewABIIsMat(Function &F, coro::Shape &S,
CreateNewABI(Function &F, coro::Shape &S,

or make IsMatCallback a default argument

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks for pointing this out. I provided the trivial remat operation here instead of the ABI constructor. This means only one constructor is needed for the ABI, which is great!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also means we only need one CreateNewABI function.

std::function<bool(Instruction &)> IsMatCallback) {
switch (S.ABI) {
case coro::ABI::Switch:
return new coro::SwitchABI(F, S, IsMatCallback);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's try to use std::unique_ptr here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@TylerNowicki TylerNowicki merged commit 2e41479 into llvm:main Sep 20, 2024
8 checks passed
@TylerNowicki TylerNowicki deleted the users/tylernowicki/coro-refactor6.1 branch September 20, 2024 20:54
@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 20, 2024

LLVM Buildbot has detected a new failure on builder clang-hip-vega20 running on hip-vega20-0 while building llvm at step 3 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/123/builds/6058

Here is the relevant piece of the build log for the reference
Step 3 (annotate) failure: '../llvm-zorg/zorg/buildbot/builders/annotated/hip-build.sh --jobs=' (failure)
...
[38/40] : && /buildbot/hip-vega20-0/clang-hip-vega20/llvm/bin/clang++ -O3 -DNDEBUG  External/HIP/CMakeFiles/memmove-hip-6.0.2.dir/memmove.hip.o -o External/HIP/memmove-hip-6.0.2  --rocm-path=/buildbot/Externals/hip/rocm-6.0.2 --hip-link -rtlib=compiler-rt -unwindlib=libgcc -frtlib-add-rpath && cd /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP && /usr/local/bin/cmake -E create_symlink /buildbot/llvm-test-suite/External/HIP/memmove.reference_output /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/memmove.reference_output-hip-6.0.2
[39/40] /buildbot/hip-vega20-0/clang-hip-vega20/llvm/bin/clang++ -DNDEBUG  -O3 -DNDEBUG   -w -Werror=date-time --rocm-path=/buildbot/Externals/hip/rocm-6.0.2 --offload-arch=gfx908 --offload-arch=gfx90a --offload-arch=gfx1030 --offload-arch=gfx1100 -xhip -mfma -MD -MT External/HIP/CMakeFiles/TheNextWeek-hip-6.0.2.dir/workload/ray-tracing/TheNextWeek/main.cc.o -MF External/HIP/CMakeFiles/TheNextWeek-hip-6.0.2.dir/workload/ray-tracing/TheNextWeek/main.cc.o.d -o External/HIP/CMakeFiles/TheNextWeek-hip-6.0.2.dir/workload/ray-tracing/TheNextWeek/main.cc.o -c /buildbot/llvm-test-suite/External/HIP/workload/ray-tracing/TheNextWeek/main.cc
[40/40] : && /buildbot/hip-vega20-0/clang-hip-vega20/llvm/bin/clang++ -O3 -DNDEBUG  External/HIP/CMakeFiles/TheNextWeek-hip-6.0.2.dir/workload/ray-tracing/TheNextWeek/main.cc.o -o External/HIP/TheNextWeek-hip-6.0.2  --rocm-path=/buildbot/Externals/hip/rocm-6.0.2 --hip-link -rtlib=compiler-rt -unwindlib=libgcc -frtlib-add-rpath && cd /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP && /usr/local/bin/cmake -E create_symlink /buildbot/llvm-test-suite/External/HIP/TheNextWeek.reference_output /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/TheNextWeek.reference_output-hip-6.0.2
+ build_step 'Testing HIP test-suite'
+ echo '@@@BUILD_STEP Testing HIP test-suite@@@'
@@@BUILD_STEP Testing HIP test-suite@@@
+ ninja -v check-hip-simple
[0/1] cd /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP && /buildbot/hip-vega20-0/clang-hip-vega20/llvm/bin/llvm-lit -sv empty-hip-6.0.2.test with-fopenmp-hip-6.0.2.test saxpy-hip-6.0.2.test memmove-hip-6.0.2.test InOneWeekend-hip-6.0.2.test TheNextWeek-hip-6.0.2.test blender.test
-- Testing: 7 tests, 7 workers --
Testing:  0.. 10.. 20.. 30.. 40
FAIL: test-suite :: External/HIP/InOneWeekend-hip-6.0.2.test (4 of 7)
******************** TEST 'test-suite :: External/HIP/InOneWeekend-hip-6.0.2.test' FAILED ********************

/buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/tools/timeit-target --timeout 7200 --limit-core 0 --limit-cpu 7200 --limit-file-size 209715200 --limit-rss-size 838860800 --append-exitstatus --redirect-output /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/Output/InOneWeekend-hip-6.0.2.test.out --redirect-input /dev/null --summary /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/Output/InOneWeekend-hip-6.0.2.test.time /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/InOneWeekend-hip-6.0.2
cd /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP ; /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/tools/fpcmp-target /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/Output/InOneWeekend-hip-6.0.2.test.out InOneWeekend.reference_output-hip-6.0.2

+ cd /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP
+ /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/tools/fpcmp-target /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/Output/InOneWeekend-hip-6.0.2.test.out InOneWeekend.reference_output-hip-6.0.2
/buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/tools/fpcmp-target: Comparison failed, textual difference between 'M' and 'i'

Input 1:
Memory access fault by GPU node-1 (Agent handle: 0x55c373c60ac0) on address (nil). Reason: Page not present or supervisor privilege.
exit 134

Input 2:
image width = 1200 height = 675
block size = (16, 16) grid size = (75, 43)
Start rendering by GPU.
Done.
gpu.ppm and ref.ppm are the same.
exit 0

********************
/usr/bin/strip: /bin/bash.stripped: Bad file descriptor
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90.. 
********************
Failed Tests (1):
  test-suite :: External/HIP/InOneWeekend-hip-6.0.2.test


Testing Time: 331.20s

Total Discovered Tests: 7
  Passed: 6 (85.71%)
  Failed: 1 (14.29%)
FAILED: External/HIP/CMakeFiles/check-hip-simple-hip-6.0.2 
cd /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP && /buildbot/hip-vega20-0/clang-hip-vega20/llvm/bin/llvm-lit -sv empty-hip-6.0.2.test with-fopenmp-hip-6.0.2.test saxpy-hip-6.0.2.test memmove-hip-6.0.2.test InOneWeekend-hip-6.0.2.test TheNextWeek-hip-6.0.2.test blender.test
ninja: build stopped: subcommand failed.
Step 12 (Testing HIP test-suite) failure: Testing HIP test-suite (failure)
@@@BUILD_STEP Testing HIP test-suite@@@
+ ninja -v check-hip-simple
[0/1] cd /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP && /buildbot/hip-vega20-0/clang-hip-vega20/llvm/bin/llvm-lit -sv empty-hip-6.0.2.test with-fopenmp-hip-6.0.2.test saxpy-hip-6.0.2.test memmove-hip-6.0.2.test InOneWeekend-hip-6.0.2.test TheNextWeek-hip-6.0.2.test blender.test
-- Testing: 7 tests, 7 workers --
Testing:  0.. 10.. 20.. 30.. 40
FAIL: test-suite :: External/HIP/InOneWeekend-hip-6.0.2.test (4 of 7)
******************** TEST 'test-suite :: External/HIP/InOneWeekend-hip-6.0.2.test' FAILED ********************

/buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/tools/timeit-target --timeout 7200 --limit-core 0 --limit-cpu 7200 --limit-file-size 209715200 --limit-rss-size 838860800 --append-exitstatus --redirect-output /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/Output/InOneWeekend-hip-6.0.2.test.out --redirect-input /dev/null --summary /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/Output/InOneWeekend-hip-6.0.2.test.time /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/InOneWeekend-hip-6.0.2
cd /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP ; /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/tools/fpcmp-target /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/Output/InOneWeekend-hip-6.0.2.test.out InOneWeekend.reference_output-hip-6.0.2

+ cd /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP
+ /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/tools/fpcmp-target /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP/Output/InOneWeekend-hip-6.0.2.test.out InOneWeekend.reference_output-hip-6.0.2
/buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/tools/fpcmp-target: Comparison failed, textual difference between 'M' and 'i'

Input 1:
Memory access fault by GPU node-1 (Agent handle: 0x55c373c60ac0) on address (nil). Reason: Page not present or supervisor privilege.
exit 134

Input 2:
image width = 1200 height = 675
block size = (16, 16) grid size = (75, 43)
Start rendering by GPU.
Done.
gpu.ppm and ref.ppm are the same.
exit 0

********************
/usr/bin/strip: /bin/bash.stripped: Bad file descriptor
Testing:  0.. 10.. 20.. 30.. 40.. 50.. 60.. 70.. 80.. 90.. 
********************
Failed Tests (1):
  test-suite :: External/HIP/InOneWeekend-hip-6.0.2.test


Testing Time: 331.20s

Total Discovered Tests: 7
  Passed: 6 (85.71%)
  Failed: 1 (14.29%)
FAILED: External/HIP/CMakeFiles/check-hip-simple-hip-6.0.2 
cd /buildbot/hip-vega20-0/clang-hip-vega20/test-suite-build/External/HIP && /buildbot/hip-vega20-0/clang-hip-vega20/llvm/bin/llvm-lit -sv empty-hip-6.0.2.test with-fopenmp-hip-6.0.2.test saxpy-hip-6.0.2.test memmove-hip-6.0.2.test InOneWeekend-hip-6.0.2.test TheNextWeek-hip-6.0.2.test blender.test
ninja: build stopped: subcommand failed.
program finished with exit code 1
elapsedTime=477.298976

@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 20, 2024

LLVM Buildbot has detected a new failure on builder llvm-clang-aarch64-darwin running on doug-worker-5 while building llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/6194

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang :: CodeGenCoroutines/coro-always-inline.cpp' FAILED ********************
Exit Code: 2

Command Output (stderr):
--
RUN: at line 1: /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang -cc1 -internal-isystem /Users/buildbot/buildbot-root/aarch64-darwin/build/lib/clang/20/include -nostdsysteminc -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++20    -O0 /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenCoroutines/coro-always-inline.cpp -o - | /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenCoroutines/coro-always-inline.cpp
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang -cc1 -internal-isystem /Users/buildbot/buildbot-root/aarch64-darwin/build/lib/clang/20/include -nostdsysteminc -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++20 -O0 /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenCoroutines/coro-always-inline.cpp -o -
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenCoroutines/coro-always-inline.cpp
/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenCoroutines/coro-always-inline.cpp:44:41: warning: this coroutine may be split into pieces; not every piece is guaranteed to be inlined [-Walways-inline-coroutine]
   44 | __attribute__((__always_inline__)) void bar() {
      |                                         ^
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.	Program arguments: /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang -cc1 -internal-isystem /Users/buildbot/buildbot-root/aarch64-darwin/build/lib/clang/20/include -nostdsysteminc -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++20 -O0 /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenCoroutines/coro-always-inline.cpp -o -
1.	<eof> parser at end of file
2.	Optimizer
3.	Running pass "coro-cond(coro-early,cgscc(coro-split),coro-cleanup,globaldce)" on module "/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenCoroutines/coro-always-inline.cpp"
4.	Running pass "cgscc(coro-split)" on module "/Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenCoroutines/coro-always-inline.cpp"
 #0 0x000000010220f930 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x101617930)
 #1 0x000000010220d9b4 llvm::sys::RunSignalHandlers() (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x1016159b4)
 #2 0x000000010220ffec SignalHandler(int) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x101617fec)
 #3 0x00000001941a2584 (/usr/lib/system/libsystem_platform.dylib+0x18047a584)
 #4 0x00000001034bb04c llvm::CoroSplitPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x1028c304c)
 #5 0x0000000100f6d7c4 llvm::PassManager<llvm::LazyCallGraph::SCC, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager<llvm::LazyCallGraph::SCC, llvm::LazyCallGraph&>&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x1003757c4)
 #6 0x0000000100f6ec84 llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x100376c84)
 #7 0x000000010191808c llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x100d2008c)
 #8 0x000000010191808c llvm::PassManager<llvm::Module, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x100d2008c)
 #9 0x000000010263b778 (anonymous namespace)::EmitAssemblyHelper::RunOptimizationPipeline(clang::BackendAction, std::__1::unique_ptr<llvm::raw_pwrite_stream, std::__1::default_delete<llvm::raw_pwrite_stream>>&, std::__1::unique_ptr<llvm::ToolOutputFile, std::__1::default_delete<llvm::ToolOutputFile>>&, clang::BackendConsumer*) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x101a43778)
#10 0x0000000102633b9c clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::HeaderSearchOptions const&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>, std::__1::unique_ptr<llvm::raw_pwrite_stream, std::__1::default_delete<llvm::raw_pwrite_stream>>, clang::BackendConsumer*) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x101a3bb9c)
#11 0x0000000102a07508 clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x101e0f508)
#12 0x0000000103f2dc8c clang::ParseAST(clang::Sema&, bool, bool) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x103335c8c)
#13 0x0000000102d94808 clang::FrontendAction::Execute() (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x10219c808)
#14 0x0000000102d1d8d0 clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x1021258d0)
#15 0x0000000102e21928 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x102229928)
#16 0x0000000100c001e4 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x1000081e4)
#17 0x0000000100bfd714 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&, llvm::ToolContext const&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x100005714)
#18 0x0000000100bfcce8 clang_main(int, char**, llvm::ToolContext const&) (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x100004ce8)
#19 0x0000000100c08fb8 main (/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/clang-20+0x100010fb8)
#20 0x0000000193de7154 
FileCheck error: '<stdin>' is empty.
FileCheck command line:  /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/clang/test/CodeGenCoroutines/coro-always-inline.cpp

--

********************


thurstond added a commit that referenced this pull request Sep 20, 2024
…ifferent ABIs, users and utilities. (#109338)"

This reverts commit 2e41479.

Reason: buildbot breakage
(https://lab.llvm.org/buildbot/#/builders/51/builds/4105)
(This was the only new CL.)

/home/b/sanitizer-aarch64-linux/build/llvm-project/llvm/lib/Transforms/Coroutines/ABI.h:71:31: error: 'llvm::coro::AsyncABI' has virtual functions but non-virtual destructor [-Werror,-Wnon-virtual-dtor]
   71 | class LLVM_LIBRARY_VISIBILITY AsyncABI : public BaseABI {

   etc.
TylerNowicki added a commit to TylerNowicki/llvm-project that referenced this pull request Sep 21, 2024
… ABIs, users and utilities. (llvm#109338)

* Adds an ABI object class hierarchy to implement the coroutine ABIs
(Switch, Asyc, and Retcon{Once})
* The ABI object improves the separation of the code related to users,
ABIs and utilities.
* No code changes are required by any existing users.
* Each ABI overrides delegate methods for initialization, building the
coroutine frame and splitting the coroutine, other methods may be added
later.
* CoroSplit invokes a generator lambda to instantiate the ABI object and
calls the ABI object to carry out its primary operations.

See RFC for more info:
https://discourse.llvm.org/t/rfc-abi-objects-for-coroutines/81057
TylerNowicki added a commit that referenced this pull request Oct 3, 2024
… ABIs, users and utilities. (#109713)

This patch re-lands #109338 and
fixes the various test failures.

--- Original description ---

* Adds an ABI object class hierarchy to implement the coroutine ABIs
(Switch, Asyc, and Retcon{Once})
* The ABI object improves the separation of the code related to users,
ABIs and utilities.
* No code changes are required by any existing users.
* Each ABI overrides delegate methods for initialization, building the
coroutine frame and splitting the coroutine, other methods may be added
later.
* CoroSplit invokes a generator lambda to instantiate the ABI object and
calls the ABI object to carry out its primary operations. In a follow-up
change this will be used to instantiated customized ABIs according to a
new intrinsic llvm.coro.begin.custom.abi.
* Note, in a follow-up change additional constructors will be added to
the ABI objects (Switch, Asyc, and AnyRetcon) to allow a set of
generator lambdas to be passed in from a CoroSplit constructor that will
also be added. The init() method is separate from the constructor to
avoid duplication of its code. It is a virtual method so it can be
invoked by CreateAndInitABI or potentially CoroSplit::run(). I wasn't
sure if we should call init() from within CoroSplit::run(),
CreateAndInitABI, or perhaps hard code a call in each constructor. One
consideration is that init() can change the IR, so perhaps it should
appear in CoroSplit::run(), but this looks a bit odd. Invoking init() in
the constructor would result in the call appearing 4 times per ABI
(after adding the new constructors). Invoking it in CreateAndInitABI
seems to be a balance between these.

See RFC for more info:
https://discourse.llvm.org/t/rfc-abi-objects-for-coroutines/81057
xgupta pushed a commit to xgupta/llvm-project that referenced this pull request Oct 4, 2024
… ABIs, users and utilities. (llvm#109338)

* Adds an ABI object class hierarchy to implement the coroutine ABIs
(Switch, Asyc, and Retcon{Once})
* The ABI object improves the separation of the code related to users,
ABIs and utilities.
* No code changes are required by any existing users.
* Each ABI overrides delegate methods for initialization, building the
coroutine frame and splitting the coroutine, other methods may be added
later.
* CoroSplit invokes a generator lambda to instantiate the ABI object and
calls the ABI object to carry out its primary operations.

See RFC for more info:
https://discourse.llvm.org/t/rfc-abi-objects-for-coroutines/81057
xgupta pushed a commit to xgupta/llvm-project that referenced this pull request Oct 4, 2024
…ifferent ABIs, users and utilities. (llvm#109338)"

This reverts commit 2e41479.

Reason: buildbot breakage
(https://lab.llvm.org/buildbot/#/builders/51/builds/4105)
(This was the only new CL.)

/home/b/sanitizer-aarch64-linux/build/llvm-project/llvm/lib/Transforms/Coroutines/ABI.h:71:31: error: 'llvm::coro::AsyncABI' has virtual functions but non-virtual destructor [-Werror,-Wnon-virtual-dtor]
   71 | class LLVM_LIBRARY_VISIBILITY AsyncABI : public BaseABI {

   etc.
xgupta pushed a commit to xgupta/llvm-project that referenced this pull request Oct 4, 2024
… ABIs, users and utilities. (llvm#109713)

This patch re-lands llvm#109338 and
fixes the various test failures.

--- Original description ---

* Adds an ABI object class hierarchy to implement the coroutine ABIs
(Switch, Asyc, and Retcon{Once})
* The ABI object improves the separation of the code related to users,
ABIs and utilities.
* No code changes are required by any existing users.
* Each ABI overrides delegate methods for initialization, building the
coroutine frame and splitting the coroutine, other methods may be added
later.
* CoroSplit invokes a generator lambda to instantiate the ABI object and
calls the ABI object to carry out its primary operations. In a follow-up
change this will be used to instantiated customized ABIs according to a
new intrinsic llvm.coro.begin.custom.abi.
* Note, in a follow-up change additional constructors will be added to
the ABI objects (Switch, Asyc, and AnyRetcon) to allow a set of
generator lambdas to be passed in from a CoroSplit constructor that will
also be added. The init() method is separate from the constructor to
avoid duplication of its code. It is a virtual method so it can be
invoked by CreateAndInitABI or potentially CoroSplit::run(). I wasn't
sure if we should call init() from within CoroSplit::run(),
CreateAndInitABI, or perhaps hard code a call in each constructor. One
consideration is that init() can change the IR, so perhaps it should
appear in CoroSplit::run(), but this looks a bit odd. Invoking init() in
the constructor would result in the call appearing 4 times per ABI
(after adding the new constructors). Invoking it in CreateAndInitABI
seems to be a balance between these.

See RFC for more info:
https://discourse.llvm.org/t/rfc-abi-objects-for-coroutines/81057
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants