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

Differential Revision: https://reviews.llvm.org/D114021
This commit is contained in:
Arnold Schwaighofer 2021-11-16 10:57:06 -08:00
parent 11982eed2b
commit 7d11c5dac2
2 changed files with 58 additions and 0 deletions

View File

@ -56,6 +56,9 @@ static void lowerSubFn(IRBuilder<> &Builder, CoroSubFnInst *SubFn) {
bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) { bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) {
bool Changed = false; bool Changed = false;
bool IsPrivateAndUnprocessed =
F.hasFnAttribute(CORO_PRESPLIT_ATTR) && F.hasLocalLinkage();
for (Instruction &I : llvm::make_early_inc_range(instructions(F))) { for (Instruction &I : llvm::make_early_inc_range(instructions(F))) {
if (auto *II = dyn_cast<IntrinsicInst>(&I)) { if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
switch (II->getIntrinsicID()) { switch (II->getIntrinsicID()) {
@ -83,6 +86,13 @@ bool Lowerer::lowerRemainingCoroIntrinsics(Function &F) {
case Intrinsic::coro_subfn_addr: case Intrinsic::coro_subfn_addr:
lowerSubFn(Builder, cast<CoroSubFnInst>(II)); lowerSubFn(Builder, cast<CoroSubFnInst>(II));
break; break;
case Intrinsic::coro_end:
case Intrinsic::coro_suspend_retcon:
if (IsPrivateAndUnprocessed) {
II->replaceAllUsesWith(UndefValue::get(II->getType()));
} else
continue;
break;
case Intrinsic::coro_async_size_replace: case Intrinsic::coro_async_size_replace:
auto *Target = cast<ConstantStruct>( auto *Target = cast<ConstantStruct>(
cast<GlobalVariable>(II->getArgOperand(0)->stripPointerCasts()) cast<GlobalVariable>(II->getArgOperand(0)->stripPointerCasts())

View File

@ -0,0 +1,48 @@
; RUN: opt < %s -enable-coroutines -passes='default<O0>' -S | FileCheck %s
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"
; CHECK: define internal { i8*, i32 } @f(i8* %buffer, i32* %array)
; CHECK-NEXT: entry:
; CHECK-NEXT: unreachable
define internal {i8*, i32} @f(i8* %buffer, i32* %array) {
entry:
%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*))
%hdl = call i8* @llvm.coro.begin(token %id, i8* null)
%load = load i32, i32* %array
%load.pos = icmp sgt i32 %load, 0
br i1 %load.pos, label %pos, label %neg
pos:
%unwind0 = call i1 (...) @llvm.coro.suspend.retcon.i1(i32 %load)
br i1 %unwind0, label %cleanup, label %pos.cont
pos.cont:
store i32 0, i32* %array, align 4
br label %cleanup
neg:
%unwind1 = call i1 (...) @llvm.coro.suspend.retcon.i1(i32 0)
br i1 %unwind1, label %cleanup, label %neg.cont
neg.cont:
store i32 10, i32* %array, align 4
br label %cleanup
cleanup:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
unreachable
}
declare token @llvm.coro.id.retcon.once(i32, i32, i8*, i8*, i8*, i8*)
declare i8* @llvm.coro.begin(token, i8*)
declare i1 @llvm.coro.suspend.retcon.i1(...)
declare i1 @llvm.coro.end(i8*, i1)
declare i8* @llvm.coro.prepare.retcon(i8*)
declare void @prototype(i8*, i1 zeroext)
declare noalias i8* @allocate(i32 %size)
declare void @deallocate(i8* %ptr)