diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 6 | ||||
-rw-r--r-- | llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll | 69 |
2 files changed, 72 insertions, 3 deletions
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 85e9003ec3c..d192fa699f3 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -673,8 +673,8 @@ static bool materializable(Instruction &V) { // Check for structural coroutine intrinsics that should not be spilled into // the coroutine frame. static bool isCoroutineStructureIntrinsic(Instruction &I) { - return isa<CoroIdInst>(&I) || isa<CoroBeginInst>(&I) || - isa<CoroSaveInst>(&I) || isa<CoroSuspendInst>(&I); + return isa<CoroIdInst>(&I) || isa<CoroSaveInst>(&I) || + isa<CoroSuspendInst>(&I); } // For every use of the value that is across suspend point, recreate that value @@ -839,7 +839,7 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) { for (Instruction &I : instructions(F)) { // Values returned from coroutine structure intrinsics should not be part // of the Coroutine Frame. - if (isCoroutineStructureIntrinsic(I)) + if (isCoroutineStructureIntrinsic(I) || &I == Shape.CoroBegin) continue; // The Coroutine Promise always included into coroutine frame, no need to // check for suspend crossing. diff --git a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll new file mode 100644 index 00000000000..e57e2f28ed3 --- /dev/null +++ b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll @@ -0,0 +1,69 @@ +; Check that we can spills coro.begin from an inlined inner coroutine. +; RUN: opt < %s -coro-split -S | FileCheck %s + +%g.Frame = type { void (%g.Frame*)*, void (%g.Frame*)*, i32, i1, i32 } + +@g.resumers = private constant [3 x void (%g.Frame*)*] [void (%g.Frame*)* @g.dummy, void (%g.Frame*)* @g.dummy, void (%g.Frame*)* @g.dummy] + +declare void @g.dummy(%g.Frame*) + +define i8* @f() "coroutine.presplit"="1" { +entry: + %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) + + %innerid = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* bitcast ([3 x void (%g.Frame*)*]* @g.resumers to i8*)) + %innerhdl = call noalias nonnull i8* @llvm.coro.begin(token %innerid, i8* null) + %gframe = bitcast i8* %innerhdl to %g.Frame* + + %tok = call i8 @llvm.coro.suspend(token none, i1 false) + switch i8 %tok, label %suspend [i8 0, label %resume + i8 1, label %cleanup] +resume: + %gvar.addr = getelementptr inbounds %g.Frame, %g.Frame* %gframe, i32 0, i32 4 + %gvar = load i32, i32* %gvar.addr + call void @print.i32(i32 %gvar) + 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 +} + +; See if the i8* for coro.begin was added to f.Frame +; CHECK-LABEL: %f.Frame = type { void (%f.Frame*)*, void (%f.Frame*)*, i1, i1, i8* } + +; See if the g's coro.begin was spilled into the frame +; CHECK-LABEL: @f( +; CHECK: %innerid = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* bitcast ([3 x void (%g.Frame*)*]* @g.resumers to i8*)) +; CHECK: %innerhdl = call noalias nonnull i8* @llvm.coro.begin(token %innerid, i8* null) +; CHECK: %[[spilladdr:.+]] = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 0, i32 4 +; CHECK: store i8* %innerhdl, i8** %[[spilladdr]] + +; See if the coro.begin was loaded from the frame +; CHECK-LABEL: @f.resume( +; CHECK: %[[innerhdlAddr:.+]] = getelementptr inbounds %f.Frame, %f.Frame* %{{.+}}, i32 0, i32 4 +; CHECK: %[[innerhdl:.+]] = load i8*, i8** %[[innerhdlAddr]] +; CHECK: %[[gframe:.+]] = bitcast i8* %[[innerhdl]] to %g.Frame* +; CHECK: %[[gvarAddr:.+]] = getelementptr inbounds %g.Frame, %g.Frame* %[[gframe]], i32 0, i32 4 +; CHECK: %[[gvar:.+]] = load i32, i32* %[[gvarAddr]] +; CHECK: call void @print.i32(i32 %[[gvar]]) + +declare i8* @llvm.coro.free(token, i8*) +declare i32 @llvm.coro.size.i32() +declare i8 @llvm.coro.suspend(token, i1) + +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.i32(i32) +declare void @free(i8*) |