[llvm-branch-commits] [llvm] [LLVM][Coroutines] Create `.noalloc` variant of switch ABI coroutine ramp functions during CoroSplit (PR #99283)

Adrian Vogelsgesang via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Jul 19 07:28:51 PDT 2024


================
@@ -1967,22 +2047,13 @@ splitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones,
   for (DbgVariableRecord *DVR : DbgVariableRecords)
     coro::salvageDebugInfo(ArgToAllocaMap, *DVR, Shape.OptimizeFrame,
                            false /*UseEntryValue*/);
-  return Shape;
-}
 
-/// Remove calls to llvm.coro.end in the original function.
-static void removeCoroEndsFromRampFunction(const coro::Shape &Shape) {
-  if (Shape.ABI != coro::ABI::Switch) {
-    for (auto *End : Shape.CoroEnds) {
-      replaceCoroEnd(End, Shape, Shape.FramePtr, /*in resume*/ false, nullptr);
-    }
-  } else {
-    for (llvm::AnyCoroEndInst *End : Shape.CoroEnds) {
-      auto &Context = End->getContext();
-      End->replaceAllUsesWith(ConstantInt::getFalse(Context));
-      End->eraseFromParent();
-    }
+  removeCoroEndsFromRampFunction(Shape);
+
+  if (!isNoSuspendCoroutine && Shape.ABI == coro::ABI::Switch) {
----------------
vogelsgesang wrote:

Additionally, we should only create this `noalloc` variant, if the coroutines promise type itself is marked as "elidable".

**Example**

```
struct [[coro_must_elide]] ElidedTask { ... }
struct NonElidedTask { ... }

ElidedTask foo();
NonElidedTask bar();

NonElidedTask foobar() {
    co_await foo();
    co_await bar();
}
```

**Current behavior**: We create `foo.noalloc`, `bar.noalloc` and `foobar.alloc`.

`foo.noalloc` gets actually called. However, `bar.noalloc` and `foobar.alloc` are dead code. The `.noalloc` variants will never be used, as the `NonElidedTask` is not marked with `[[coro_must_elide]]`.

I think we should avoid generating this dead code

https://github.com/llvm/llvm-project/pull/99283


More information about the llvm-branch-commits mailing list