Skip to content

Commit 854ae3c

Browse files
committed
Coro: Remove coro_end and coro_suspend_retcon in private unprocessed functions
We might emit functions that are private and never called. The coro split pass only processes functions that might be called. Remove intrinsics that we can't generate code for. rdar://84619859
1 parent ec45ce2 commit 854ae3c

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

llvm/lib/Transforms/Coroutines/CoroCleanup.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn) {
5555

5656
bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) {
5757
bool Changed = false;
58-
58+
bool IsPrivateAndUnprocessed = F.hasFnAttribute(CORO_PRESPLIT_ATTR) &&
59+
F.hasLocalLinkage();
5960
for (auto IB = inst_begin(F), E = inst_end(F); IB != E;) {
6061
Instruction &I = *IB++;
6162
if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
@@ -84,6 +85,12 @@ bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) {
8485
case Intrinsic::coro_subfn_addr:
8586
lowerSubFn(Builder, cast<CoroSubFnInst>(II));
8687
break;
88+
case Intrinsic::coro_end:
89+
case Intrinsic::coro_suspend_retcon:
90+
if (IsPrivateAndUnprocessed) {
91+
II->replaceAllUsesWith(UndefValue::get(II->getType()));
92+
} else continue;
93+
break;
8794
case Intrinsic::coro_async_size_replace:
8895
auto *Target = cast<ConstantStruct>(
8996
cast<GlobalVariable>(II->getArgOperand(0)->stripPointerCasts())
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2+
; RUN: opt < %s -enable-coroutines -passes='default<O0>' -S | FileCheck %s
3+
4+
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
5+
target triple = "x86_64-apple-macosx10.12.0"
6+
7+
; CHECK: define internal { i8*, i32 } @f(i8* %buffer, i32* %array)
8+
; CHECK-NEXT: entry:
9+
; CHECK-NEXT: unreachable
10+
11+
define internal {i8*, i32} @f(i8* %buffer, i32* %array) {
12+
entry:
13+
%id = call token @llvm.coro.id.retcon.once(i32 8, i32 8, i8* %buffer, i8* bitcast (void (i8*, i1)* @prototype to i8*), i8* bitcast (i8* (i32)* @allocate to i8*), i8* bitcast (void (i8*)* @deallocate to i8*))
14+
%hdl = call i8* @llvm.coro.begin(token %id, i8* null)
15+
%load = load i32, i32* %array
16+
%load.pos = icmp sgt i32 %load, 0
17+
br i1 %load.pos, label %pos, label %neg
18+
19+
pos:
20+
%unwind0 = call i1 (...) @llvm.coro.suspend.retcon.i1(i32 %load)
21+
br i1 %unwind0, label %cleanup, label %pos.cont
22+
23+
pos.cont:
24+
store i32 0, i32* %array, align 4
25+
br label %cleanup
26+
27+
neg:
28+
%unwind1 = call i1 (...) @llvm.coro.suspend.retcon.i1(i32 0)
29+
br i1 %unwind1, label %cleanup, label %neg.cont
30+
31+
neg.cont:
32+
store i32 10, i32* %array, align 4
33+
br label %cleanup
34+
35+
cleanup:
36+
call i1 @llvm.coro.end(i8* %hdl, i1 0)
37+
unreachable
38+
}
39+
40+
; Unfortunately, we don't seem to fully optimize this right now due
41+
; to some sort of phase-ordering thing.
42+
43+
declare token @llvm.coro.id.retcon.once(i32, i32, i8*, i8*, i8*, i8*)
44+
declare i8* @llvm.coro.begin(token, i8*)
45+
declare i1 @llvm.coro.suspend.retcon.i1(...)
46+
declare i1 @llvm.coro.end(i8*, i1)
47+
declare i8* @llvm.coro.prepare.retcon(i8*)
48+
49+
declare void @prototype(i8*, i1 zeroext)
50+
51+
declare noalias i8* @allocate(i32 %size)
52+
declare void @deallocate(i8* %ptr)
53+
54+
declare void @print(i32)
55+

0 commit comments

Comments
 (0)