[coroutines][PR40979] Ignore unreachable uses across suspend points

Summary:
Depends on https://reviews.llvm.org/D59069.

https://bugs.llvm.org/show_bug.cgi?id=40979 describes a bug in which the
-coro-split pass would assert that a use was across a suspend point from
a definition. Normally this would mean that a value would "spill" across
a suspend point and thus need to be stored in the coroutine frame. However,
in this case the use was unreachable, and so it would not be necessary
to store the definition on the frame.

To prevent the assert, simply remove unreachable basic blocks from a
coroutine function before computing spills. This avoids the assert
reported in PR40979.

Reviewers: GorNishanov, tks2103

Reviewed By: GorNishanov

Subscribers: EricWF, jdoerfert, llvm-commits, lewissbaker

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D59068

llvm-svn: 355852
This commit is contained in:
Brian Gesiak 2019-03-11 18:31:28 +00:00
parent 76d66123b2
commit d7b68132d8
2 changed files with 52 additions and 0 deletions

View File

@ -777,6 +777,8 @@ static void relocateInstructionBefore(CoroBeginInst *CoroBegin, Function &F) {
}
static void splitCoroutine(Function &F, CallGraph &CG, CallGraphSCC &SCC) {
EliminateUnreachableBlocks(F);
coro::Shape Shape(F);
if (!Shape.CoroBegin)
return;

View File

@ -0,0 +1,50 @@
; Check that coro-split doesn't choke on intrinsics in unreachable blocks
; RUN: opt < %s -coro-split -S
define i8* @f(i1 %arg) "coroutine.presplit"="1" personality i32 0 {
entry:
%arg.addr = alloca i1
store i1 %arg, i1* %arg.addr
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call i8* @malloc(i32 %size)
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc)
br label %cont
cont:
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
i8 1, label %cleanup]
resume:
br label %cleanup
cleanup:
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
call void @free(i8* %mem)
br label %suspend
suspend:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
ret i8* %hdl
no.predecessors:
%argval = load i1, i1* %arg.addr
call void @print(i1 %argval)
br label %suspend
}
declare i8* @llvm.coro.free(token, i8*)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
declare void @llvm.coro.resume(i8*)
declare void @llvm.coro.destroy(i8*)
declare token @llvm.coro.id(i32, i8*, i8*, i8*)
declare i1 @llvm.coro.alloc(token)
declare i8* @llvm.coro.begin(token, i8*)
declare i1 @llvm.coro.end(i8*, i1)
declare noalias i8* @malloc(i32)
declare void @print(i1)
declare void @free(i8*)