Skip to content

Commit 0a72fac

Browse files
Merge pull request #10274 from nate-chandler/general-coro/20250317/1
[Coro] Delete ret.popless before rewritten return.
2 parents 410454f + 8abe108 commit 0a72fac

File tree

2 files changed

+80
-1
lines changed

2 files changed

+80
-1
lines changed

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,18 @@ static void addSwiftSelfAttrs(AttributeList &Attrs, LLVMContext &Context,
966966
Attrs = Attrs.addParamAttributes(Context, ParamIndex, ParamAttrs);
967967
}
968968

969+
static void eraseIntrinsicRetPoplessBefore(ReturnInst *Return) {
970+
if (Return == &*Return->getParent()->begin())
971+
return;
972+
auto *Prev = &*std::prev(Return->getIterator());
973+
auto *Intr = dyn_cast<IntrinsicInst>(Prev);
974+
if (!Intr)
975+
return;
976+
if (Intr->getIntrinsicID() != Intrinsic::ret_popless)
977+
return;
978+
Intr->eraseFromParent();
979+
}
980+
969981
/// Clone the body of the original function into a resume function of
970982
/// some sort.
971983
void CoroCloner::create() {
@@ -1125,8 +1137,10 @@ void CoroCloner::create() {
11251137
case coro::ABI::RetconOnce:
11261138
case coro::ABI::RetconOnceDynamic:
11271139
// Remove old returns.
1128-
for (ReturnInst *Return : Returns)
1140+
for (ReturnInst *Return : Returns) {
1141+
eraseIntrinsicRetPoplessBefore(Return);
11291142
changeToUnreachable(Return);
1143+
}
11301144
break;
11311145

11321146
// With multi-suspend continuations, we'll already have eliminated the
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split)' -S | FileCheck %s
2+
3+
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
4+
target triple = "arm64-apple-macos99.99"
5+
6+
7+
@func_cfp = constant <{ i32, i32 }>
8+
<{ i32 trunc (
9+
i64 sub (
10+
i64 ptrtoint (ptr @func to i64),
11+
i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @func_cfp, i32 0, i32 1) to i64)
12+
)
13+
to i32),
14+
i32 64
15+
}>
16+
17+
18+
%func_int = type <{ i64 }>
19+
%func_obj = type <{ %func_int, ptr }>
20+
%func_guts = type <{ %func_obj }>
21+
%func_impl = type <{ %func_guts }>
22+
%func_self = type <{ %func_impl }>
23+
24+
declare swiftcorocc void @func_continuation_prototype(ptr noalias, ptr)
25+
26+
; CHECK-LABEL: @func.resume.0(
27+
; CHECK-SAME: ptr noalias %0,
28+
; CHECK-SAME: ptr %1
29+
; CHECK-SAME: ) {
30+
; CHECK: coro.return.popless:
31+
; CHECK-NEXT: unreachable
32+
; CHECK: coro.return.normal:
33+
; CHECK-NEXT: unreachable
34+
; CHECK: }
35+
36+
define swiftcorocc { ptr, ptr } @func(ptr noalias %buffer, ptr %allocator, ptr nocapture swiftself dereferenceable(16) %2) {
37+
entry:
38+
%3 = call token @llvm.coro.id.retcon.once.dynamic(
39+
i32 -1,
40+
i32 16,
41+
ptr @func_cfp,
42+
ptr %allocator,
43+
ptr %buffer,
44+
ptr @func_continuation_prototype,
45+
ptr @allocate,
46+
ptr @deallocate
47+
)
48+
%handle = call ptr @llvm.coro.begin(token %3, ptr null)
49+
%yielded = getelementptr inbounds %func_self, ptr %2, i32 0, i32 0
50+
call ptr (...) @llvm.coro.suspend.retcon.p0(ptr %yielded)
51+
br i1 false, label %unwind, label %normal
52+
53+
normal:
54+
br label %coro.end
55+
56+
unwind:
57+
br label %coro.end
58+
59+
coro.end:
60+
%8 = call i1 @llvm.coro.end(ptr %handle, i1 false, token none)
61+
unreachable
62+
}
63+
64+
declare swiftcorocc noalias ptr @allocate(i32 %size)
65+
declare void @deallocate(ptr %ptr)

0 commit comments

Comments
 (0)