Skip to content

Commit 5c7dcd7

Browse files
author
Yuanfang Chen
committed
[Coroutine] Update promise object's final layout index
promise is a header field but it is not guaranteed that it would be the third field of the frame due to `performOptimizedStructLayout`. Reviewed By: lxfind Differential Revision: https://reviews.llvm.org/D94137
1 parent 055644c commit 5c7dcd7

File tree

2 files changed

+66
-7
lines changed

2 files changed

+66
-7
lines changed

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,15 @@ static StructType *buildFrameType(Function &F, coro::Shape &Shape,
758758
// Because multiple allocas may own the same field slot,
759759
// we add allocas to field here.
760760
B.addFieldForAllocas(F, FrameData, Shape);
761+
// Add PromiseAlloca to Allocas list so that
762+
// 1. updateLayoutIndex could update its index after
763+
// `performOptimizedStructLayout`
764+
// 2. it is processed in insertSpills.
765+
if (Shape.ABI == coro::ABI::Switch && PromiseAlloca)
766+
// We assume that the promise alloca won't be modified before
767+
// CoroBegin and no alias will be create before CoroBegin.
768+
FrameData.Allocas.emplace_back(
769+
PromiseAlloca, DenseMap<Instruction *, llvm::Optional<APInt>>{}, false);
761770
// Create an entry for every spilled value.
762771
for (auto &S : FrameData.Spills) {
763772
FieldIDType Id = B.addField(S.first->getType(), None);
@@ -2288,13 +2297,6 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
22882297
Shape.ABI == coro::ABI::Async)
22892298
sinkSpillUsesAfterCoroBegin(F, FrameData, Shape.CoroBegin);
22902299
Shape.FrameTy = buildFrameType(F, Shape, FrameData);
2291-
// Add PromiseAlloca to Allocas list so that it is processed in insertSpills.
2292-
if (Shape.ABI == coro::ABI::Switch && Shape.SwitchLowering.PromiseAlloca)
2293-
// We assume that the promise alloca won't be modified before
2294-
// CoroBegin and no alias will be create before CoroBegin.
2295-
FrameData.Allocas.emplace_back(
2296-
Shape.SwitchLowering.PromiseAlloca,
2297-
DenseMap<Instruction *, llvm::Optional<APInt>>{}, false);
22982300
Shape.FramePtr = insertSpills(FrameData, Shape);
22992301
lowerLocalAllocas(LocalAllocas, DeadInstructions);
23002302

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
; Check that promise object is reloaded from the correct index of the coro frame.
2+
; RUN: opt < %s -coro-split -S | FileCheck %s
3+
; RUN: opt < %s -passes=coro-split -S | FileCheck %s
4+
5+
%"class.task::promise_type" = type { [64 x i8] }
6+
7+
declare void @consume(i32*)
8+
declare void @consume2(%"class.task::promise_type"*)
9+
10+
define i8* @f() "coroutine.presplit"="1" {
11+
entry:
12+
%data = alloca i32, align 4
13+
%__promise = alloca %"class.task::promise_type", align 64
14+
%pv = bitcast %"class.task::promise_type"* %__promise to i8*
15+
%id = call token @llvm.coro.id(i32 0, i8* %pv, i8* null, i8* null)
16+
%size = call i32 @llvm.coro.size.i32()
17+
%alloc = call i8* @malloc(i32 %size)
18+
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc)
19+
call void @consume(i32* %data)
20+
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
21+
switch i8 %0, label %suspend [i8 0, label %resume
22+
i8 1, label %cleanup]
23+
resume:
24+
call void @consume(i32* %data)
25+
call void @consume2(%"class.task::promise_type"* %__promise)
26+
br label %cleanup
27+
28+
cleanup:
29+
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
30+
call void @free(i8* %mem)
31+
br label %suspend
32+
suspend:
33+
call i1 @llvm.coro.end(i8* %hdl, i1 0)
34+
ret i8* %hdl
35+
}
36+
37+
; CHECK-LABEL: %f.Frame = type { void (%f.Frame*)*, void (%f.Frame*)*, i32, i1, [43 x i8], %"class.task::promise_type" }
38+
39+
; CHECK-LABEL: @f.resume(
40+
; CHECK: %[[DATA:.+]] = getelementptr inbounds %f.Frame, %f.Frame* %FramePtr, i32 0, i32 5
41+
; CHECK: call void @consume2(%"class.task::promise_type"* %[[DATA]])
42+
; CHECK: ret void
43+
44+
declare i8* @llvm.coro.free(token, i8*)
45+
declare i32 @llvm.coro.size.i32()
46+
declare i8 @llvm.coro.suspend(token, i1)
47+
declare void @llvm.coro.resume(i8*)
48+
declare void @llvm.coro.destroy(i8*)
49+
50+
declare token @llvm.coro.id(i32, i8*, i8*, i8*)
51+
declare i1 @llvm.coro.alloc(token)
52+
declare i8* @llvm.coro.begin(token, i8*)
53+
declare i1 @llvm.coro.end(i8*, i1)
54+
55+
declare noalias i8* @malloc(i32)
56+
declare double @print(double)
57+
declare void @free(i8*)

0 commit comments

Comments
 (0)