Skip to content

Commit

Permalink
[coroutines][PR40979] Ignore unreachable uses across suspend points
Browse files Browse the repository at this point in the history
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
  • Loading branch information
modocache committed Mar 11, 2019
1 parent 76d6612 commit d7b6813
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
2 changes: 2 additions & 0 deletions llvm/lib/Transforms/Coroutines/CoroSplit.cpp
Expand Up @@ -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;
Expand Down
50 changes: 50 additions & 0 deletions llvm/test/Transforms/Coroutines/coro-frame-unreachable.ll
@@ -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*)

0 comments on commit d7b6813

Please sign in to comment.