55 changes: 26 additions & 29 deletions llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll
Original file line number Diff line number Diff line change
Expand Up @@ -4,73 +4,70 @@
%"struct.task::promise_type" = type { i8 }
%struct.awaitable = type { i8 }
%struct.big_structure = type { [500 x i8] }
declare i8* @malloc(i64)
declare void @consume(%struct.big_structure*)
declare ptr @malloc(i64)
declare void @consume(ptr)
define void @a(i1 zeroext %cond) presplitcoroutine {
entry:
%__promise = alloca %"struct.task::promise_type", align 1
%a = alloca %struct.big_structure, align 1
%ref.tmp7 = alloca %struct.awaitable, align 1
%b = alloca %struct.big_structure, align 1
%ref.tmp18 = alloca %struct.awaitable, align 1
%0 = getelementptr inbounds %"struct.task::promise_type", %"struct.task::promise_type"* %__promise, i64 0, i32 0
%1 = call token @llvm.coro.id(i32 16, i8* nonnull %0, i8* bitcast (void (i1)* @a to i8*), i8* null)
%0 = call token @llvm.coro.id(i32 16, ptr nonnull %__promise, ptr @a, ptr null)
br label %init.ready
init.ready:
%2 = call noalias nonnull i8* @llvm.coro.begin(token %1, i8* null)
call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %0)
%1 = call noalias nonnull ptr @llvm.coro.begin(token %0, ptr null)
call void @llvm.lifetime.start.p0(i64 1, ptr nonnull %__promise)
br i1 %cond, label %if.then, label %if.else
if.then:
%3 = getelementptr inbounds %struct.big_structure, %struct.big_structure* %a, i64 0, i32 0, i64 0
call void @llvm.lifetime.start.p0i8(i64 500, i8* nonnull %3)
call void @consume(%struct.big_structure* nonnull %a)
%save = call token @llvm.coro.save(i8* null)
call void @llvm.lifetime.start.p0(i64 500, ptr nonnull %a)
call void @consume(ptr nonnull %a)
%save = call token @llvm.coro.save(ptr null)
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %coro.ret [
i8 0, label %await.ready
i8 1, label %cleanup1
]
await.ready:
call void @llvm.lifetime.end.p0i8(i64 500, i8* nonnull %3)
call void @llvm.lifetime.end.p0(i64 500, ptr nonnull %a)
br label %cleanup1
if.else:
%4 = getelementptr inbounds %struct.big_structure, %struct.big_structure* %b, i64 0, i32 0, i64 0
call void @llvm.lifetime.start.p0i8(i64 500, i8* nonnull %4)
call void @consume(%struct.big_structure* nonnull %b)
%save2 = call token @llvm.coro.save(i8* null)
call void @llvm.lifetime.start.p0(i64 500, ptr nonnull %b)
call void @consume(ptr nonnull %b)
%save2 = call token @llvm.coro.save(ptr null)
%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %coro.ret [
i8 0, label %await2.ready
i8 1, label %cleanup2
]
await2.ready:
call void @llvm.lifetime.end.p0i8(i64 500, i8* nonnull %4)
call void @llvm.lifetime.end.p0(i64 500, ptr nonnull %b)
br label %cleanup2
cleanup1:
call void @llvm.lifetime.end.p0i8(i64 500, i8* nonnull %3)
call void @llvm.lifetime.end.p0(i64 500, ptr nonnull %a)
br label %cleanup
cleanup2:
call void @llvm.lifetime.end.p0i8(i64 500, i8* nonnull %4)
call void @llvm.lifetime.end.p0(i64 500, ptr nonnull %b)
br label %cleanup
cleanup:
call i8* @llvm.coro.free(token %1, i8* %2)
call ptr @llvm.coro.free(token %0, ptr %1)
br label %coro.ret
coro.ret:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; check that there is only one %struct.big_structure in the frame.
; CHECK: %a.Frame = type { void (%a.Frame*)*, void (%a.Frame*)*, %"struct.task::promise_type", %struct.big_structure, i1 }
; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1 }

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*)
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
declare i1 @llvm.coro.alloc(token) #3
declare i64 @llvm.coro.size.i64() #5
declare i8* @llvm.coro.begin(token, i8* writeonly) #3
declare token @llvm.coro.save(i8*) #3
declare i8* @llvm.coro.frame() #5
declare ptr @llvm.coro.begin(token, ptr writeonly) #3
declare token @llvm.coro.save(ptr) #3
declare ptr @llvm.coro.frame() #5
declare i8 @llvm.coro.suspend(token, i1) #3
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #2
declare i1 @llvm.coro.end(i8*, i1) #3
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #4
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #4
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #2
declare i1 @llvm.coro.end(ptr, i1) #3
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #4
declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #4
58 changes: 28 additions & 30 deletions llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-03.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,77 +2,75 @@
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s

%struct.big_structure = type { [500 x i8] }
declare void @consume(%struct.big_structure*)
declare void @consume(ptr)

; Function Attrs: noinline optnone uwtable
define i8* @f(i1 %cond) presplitcoroutine {
define ptr @f(i1 %cond) presplitcoroutine {
entry:
%data = alloca %struct.big_structure, align 1
%data2 = alloca %struct.big_structure, align 1
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call i8* @malloc(i32 %size)
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc)
%alloc = call ptr @malloc(i32 %size)
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
br i1 %cond, label %then, label %else

then:
%0 = bitcast %struct.big_structure* %data to i8*
call void @llvm.lifetime.start.p0i8(i64 500, i8* nonnull %0)
call void @consume(%struct.big_structure* %data)
call void @llvm.lifetime.start.p0(i64 500, ptr nonnull %data)
call void @consume(ptr %data)
%suspend.value = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %suspend.value, label %coro.ret [i8 0, label %resume
i8 1, label %cleanup1]

resume:
call void @llvm.lifetime.end.p0i8(i64 500, i8* nonnull %0)
call void @llvm.lifetime.end.p0(i64 500, ptr nonnull %data)
br label %cleanup1

cleanup1:
call void @llvm.lifetime.end.p0i8(i64 500, i8* nonnull %0)
call void @llvm.lifetime.end.p0(i64 500, ptr nonnull %data)
br label %cleanup

else:
%1 = bitcast %struct.big_structure* %data2 to i8*
call void @llvm.lifetime.start.p0i8(i64 500, i8* nonnull %1)
call void @consume(%struct.big_structure* %data2)
call void @llvm.lifetime.start.p0(i64 500, ptr nonnull %data2)
call void @consume(ptr %data2)
%suspend.value2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %suspend.value2, label %coro.ret [i8 0, label %resume2
i8 1, label %cleanup2]

resume2:
call void @llvm.lifetime.end.p0i8(i64 500, i8* nonnull %1)
call void @llvm.lifetime.end.p0(i64 500, ptr nonnull %data2)
br label %cleanup2

cleanup2:
call void @llvm.lifetime.end.p0i8(i64 500, i8* nonnull %1)
call void @llvm.lifetime.end.p0(i64 500, ptr nonnull %data2)
br label %cleanup

cleanup:
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
call void @free(i8* %mem)
%mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
call void @free(ptr %mem)
br label %coro.ret
coro.ret:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
ret i8* %hdl
call i1 @llvm.coro.end(ptr %hdl, i1 0)
ret ptr %hdl
}

; CHECK-LABEL: @f(
; CHECK: call i8* @malloc(i32 1024)
; CHECK: call ptr @malloc(i32 1024)

declare i8* @llvm.coro.free(token, i8*)
declare ptr @llvm.coro.free(token, ptr)
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 void @llvm.coro.resume(ptr)
declare void @llvm.coro.destroy(ptr)

declare token @llvm.coro.id(i32, i8*, i8*, i8*)
declare token @llvm.coro.id(i32, ptr, ptr, ptr)
declare i1 @llvm.coro.alloc(token)
declare i8* @llvm.coro.begin(token, i8*)
declare i1 @llvm.coro.end(i8*, i1)
declare ptr @llvm.coro.begin(token, ptr)
declare i1 @llvm.coro.end(ptr, i1)

declare noalias i8* @malloc(i32)
declare noalias ptr @malloc(i32)
declare double @print(double)
declare void @free(i8*)
declare void @free(ptr)

declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
36 changes: 18 additions & 18 deletions llvm/test/Transforms/Coroutines/coro-frame-unreachable.ll
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
; Check that coro-split doesn't choke on intrinsics in unreachable blocks
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S

define i8* @f(i1 %arg) presplitcoroutine personality i32 0 {
define ptr @f(i1 %arg) presplitcoroutine 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)
store i1 %arg, ptr %arg.addr
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call i8* @malloc(i32 %size)
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc)
%alloc = call ptr @malloc(i32 %size)
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
br label %cont

cont:
Expand All @@ -19,32 +19,32 @@ resume:
br label %cleanup

cleanup:
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
call void @free(i8* %mem)
%mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
call void @free(ptr %mem)
br label %suspend

suspend:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
ret i8* %hdl
call i1 @llvm.coro.end(ptr %hdl, i1 0)
ret ptr %hdl

no.predecessors:
%argval = load i1, i1* %arg.addr
%argval = load i1, ptr %arg.addr
call void @print(i1 %argval)
br label %suspend

}

declare i8* @llvm.coro.free(token, i8*)
declare ptr @llvm.coro.free(token, ptr)
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 void @llvm.coro.resume(ptr)
declare void @llvm.coro.destroy(ptr)

declare token @llvm.coro.id(i32, i8*, i8*, i8*)
declare token @llvm.coro.id(i32, ptr, ptr, ptr)
declare i1 @llvm.coro.alloc(token)
declare i8* @llvm.coro.begin(token, i8*)
declare i1 @llvm.coro.end(i8*, i1)
declare ptr @llvm.coro.begin(token, ptr)
declare i1 @llvm.coro.end(ptr, i1)

declare noalias i8* @malloc(i32)
declare noalias ptr @malloc(i32)
declare void @print(i1)
declare void @free(i8*)
declare void @free(ptr)
12 changes: 6 additions & 6 deletions llvm/test/Transforms/Coroutines/coro-inline.ll
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,25 @@
; Function Attrs: alwaysinline ssp uwtable
define void @ff() #0 {
entry:
%id = call token @llvm.coro.id(i32 16, i8* null, i8* null, i8* null)
%begin = call i8* @llvm.coro.begin(token %id, i8* null)
%id = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr null)
%begin = call ptr @llvm.coro.begin(token %id, ptr null)
ret void
}

; Function Attrs: alwaysinline ssp uwtable
define void @foo() #0 {
entry:
%id1 = call token @llvm.coro.id(i32 16, i8* null, i8* null, i8* null)
%begin = call i8* @llvm.coro.begin(token %id1, i8* null)
%id1 = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr null)
%begin = call ptr @llvm.coro.begin(token %id1, ptr null)
call void @ff()
ret void
}
; CHECK-LABEL: define void @foo()
; CHECK: call void @ff()


declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*)
declare i8* @llvm.coro.begin(token, i8* writeonly)
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
declare ptr @llvm.coro.begin(token, ptr writeonly)

attributes #0 = { alwaysinline ssp uwtable presplitcoroutine "use-sample-profile" }

Expand Down
34 changes: 17 additions & 17 deletions llvm/test/Transforms/Coroutines/coro-materialize.ll
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
; Verifies that we materialize instruction across suspend points
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s

define i8* @f(i32 %n) presplitcoroutine {
define ptr @f(i32 %n) presplitcoroutine {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call i8* @malloc(i32 %size)
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc)
%alloc = call ptr @malloc(i32 %size)
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)

%inc1 = add i32 %n, 1
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
Expand All @@ -24,29 +24,29 @@ resume2:
br label %cleanup

cleanup:
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
call void @free(i8* %mem)
%mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
call void @free(ptr %mem)
br label %suspend
suspend:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
ret i8* %hdl
call i1 @llvm.coro.end(ptr %hdl, i1 0)
ret ptr %hdl
}

; See that we only spilled one value
; CHECK: %f.Frame = type { void (%f.Frame*)*, void (%f.Frame*)*, i32, i1 }
; CHECK: %f.Frame = type { ptr, ptr, i32, i1 }
; CHECK-LABEL: @f(

declare i8* @llvm.coro.free(token, i8*)
declare ptr @llvm.coro.free(token, ptr)
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 void @llvm.coro.resume(ptr)
declare void @llvm.coro.destroy(ptr)

declare token @llvm.coro.id(i32, i8*, i8*, i8*)
declare token @llvm.coro.id(i32, ptr, ptr, ptr)
declare i1 @llvm.coro.alloc(token)
declare i8* @llvm.coro.begin(token, i8*)
declare i1 @llvm.coro.end(i8*, i1)
declare ptr @llvm.coro.begin(token, ptr)
declare i1 @llvm.coro.end(ptr, i1)

declare noalias i8* @malloc(i32)
declare noalias ptr @malloc(i32)
declare void @print(i32)
declare void @free(i8*)
declare void @free(ptr)
32 changes: 16 additions & 16 deletions llvm/test/Transforms/Coroutines/coro-noalias-param.ll
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
; RUN: opt < %s -S -passes=coro-early | FileCheck %s
%struct.A = type <{ i64, i64, i32, [4 x i8] }>

define void @f(%struct.A* nocapture readonly noalias align 8 %a) presplitcoroutine {
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
define void @f(ptr nocapture readonly noalias align 8 %a) presplitcoroutine {
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call i8* @malloc(i32 %size)
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc)
%alloc = call ptr @malloc(i32 %size)
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
call void @print(i32 0)
%s1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %s1, label %suspend [i8 0, label %resume
Expand All @@ -15,26 +15,26 @@ resume:
br label %cleanup

cleanup:
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
call void @free(i8* %mem)
%mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
call void @free(ptr %mem)
br label %suspend
suspend:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
call i1 @llvm.coro.end(ptr %hdl, i1 0)
ret void
}

; check that the noalias attribute is removed from the argument
; CHECK: define void @f(%struct.A* nocapture readonly align 8 %a)
; CHECK: define void @f(ptr nocapture readonly align 8 %a)

declare token @llvm.coro.id(i32, i8*, i8*, i8*)
declare i8* @llvm.coro.begin(token, i8*)
declare i8* @llvm.coro.free(token, i8*)
declare token @llvm.coro.id(i32, ptr, ptr, ptr)
declare ptr @llvm.coro.begin(token, ptr)
declare ptr @llvm.coro.free(token, ptr)
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 i1 @llvm.coro.end(i8*, i1)
declare void @llvm.coro.resume(ptr)
declare void @llvm.coro.destroy(ptr)
declare i1 @llvm.coro.end(ptr, i1)

declare noalias i8* @malloc(i32)
declare noalias ptr @malloc(i32)
declare void @print(i32)
declare void @free(i8*)
declare void @free(ptr)
16 changes: 8 additions & 8 deletions llvm/test/Transforms/Coroutines/coro-noop.ll
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
; Tests that CoroEarly pass correctly lowers coro.noop
; RUN: opt < %s -S -passes=coro-early | FileCheck %s

; CHECK: %NoopCoro.Frame = type { void (%NoopCoro.Frame*)*, void (%NoopCoro.Frame*)* }
; CHECK: @NoopCoro.Frame.Const = private constant %NoopCoro.Frame { void (%NoopCoro.Frame*)* @__NoopCoro_ResumeDestroy, void (%NoopCoro.Frame*)* @__NoopCoro_ResumeDestroy }
; CHECK: %NoopCoro.Frame = type { ptr, ptr }
; CHECK: @NoopCoro.Frame.Const = private constant %NoopCoro.Frame { ptr @__NoopCoro_ResumeDestroy, ptr @__NoopCoro_ResumeDestroy }


; CHECK-LABEL: @noop(
define i8* @noop() {
define ptr @noop() {
; CHECK-NEXT: entry
entry:
; CHECK-NEXT: ret i8* bitcast (%NoopCoro.Frame* @NoopCoro.Frame.Const to i8*)
%n = call i8* @llvm.coro.noop()
ret i8* %n
; CHECK-NEXT: ret ptr @NoopCoro.Frame.Const
%n = call ptr @llvm.coro.noop()
ret ptr %n
}

declare i8* @llvm.coro.noop()
declare ptr @llvm.coro.noop()

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4}
Expand All @@ -26,7 +26,7 @@ declare i8* @llvm.coro.noop()
!4 = !{i32 2, !"Debug Info Version", i32 3}


; CHECK: define private fastcc void @__NoopCoro_ResumeDestroy(%NoopCoro.Frame* %0) !dbg ![[RESUME:[0-9]+]] {
; CHECK: define private fastcc void @__NoopCoro_ResumeDestroy(ptr %0) !dbg ![[RESUME:[0-9]+]] {
; CHECK-NEXT: entry
; CHECK-NEXT: ret void

Expand Down
28 changes: 14 additions & 14 deletions llvm/test/Transforms/Coroutines/coro-retcon-once-private.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ target triple = "x86_64-apple-macosx10.12.0"

; CHECK-NOT: define

define internal {i8*, i32} @f(i8* %buffer, i32* %array) {
define internal {ptr, i32} @f(ptr %buffer, ptr %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
%id = call token @llvm.coro.id.retcon.once(i32 8, i32 8, ptr %buffer, ptr @prototype, ptr @allocate, ptr @deallocate)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
%load = load i32, ptr %array
%load.pos = icmp sgt i32 %load, 0
br i1 %load.pos, label %pos, label %neg

Expand All @@ -18,29 +18,29 @@ pos:
br i1 %unwind0, label %cleanup, label %pos.cont

pos.cont:
store i32 0, i32* %array, align 4
store i32 0, ptr %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
store i32 10, ptr %array, align 4
br label %cleanup

cleanup:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
call i1 @llvm.coro.end(ptr %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 token @llvm.coro.id.retcon.once(i32, i32, ptr, ptr, ptr, ptr)
declare ptr @llvm.coro.begin(token, ptr)
declare i1 @llvm.coro.suspend.retcon.i1(...)
declare i1 @llvm.coro.end(i8*, i1)
declare i8* @llvm.coro.prepare.retcon(i8*)
declare i1 @llvm.coro.end(ptr, i1)
declare ptr @llvm.coro.prepare.retcon(ptr)

declare void @prototype(i8*, i1 zeroext)
declare void @prototype(ptr, i1 zeroext)

declare noalias i8* @allocate(i32 %size)
declare void @deallocate(i8* %ptr)
declare noalias ptr @allocate(i32 %size)
declare void @deallocate(ptr %ptr)
64 changes: 29 additions & 35 deletions llvm/test/Transforms/Coroutines/coro-retcon-once-value2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -3,68 +3,62 @@
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.12.0"

define {i8*, i32*} @f(i8* %buffer, i32* %ptr) presplitcoroutine {
define {ptr, ptr} @f(ptr %buffer, ptr %ptr) presplitcoroutine {
entry:
%temp = alloca i32, align 4
%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)
%oldvalue = load i32, i32* %ptr
store i32 %oldvalue, i32* %temp
%unwind = call i1 (...) @llvm.coro.suspend.retcon.i1(i32* %temp)
%id = call token @llvm.coro.id.retcon.once(i32 8, i32 8, ptr %buffer, ptr @prototype, ptr @allocate, ptr @deallocate)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
%oldvalue = load i32, ptr %ptr
store i32 %oldvalue, ptr %temp
%unwind = call i1 (...) @llvm.coro.suspend.retcon.i1(ptr %temp)
br i1 %unwind, label %cleanup, label %cont

cont:
%newvalue = load i32, i32* %temp
store i32 %newvalue, i32* %ptr
%newvalue = load i32, ptr %temp
store i32 %newvalue, ptr %ptr
br label %cleanup

cleanup:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
call i1 @llvm.coro.end(ptr %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 token @llvm.coro.id.retcon.once(i32, i32, ptr, ptr, ptr, ptr)
declare ptr @llvm.coro.begin(token, ptr)
declare i1 @llvm.coro.suspend.retcon.i1(...)
declare i1 @llvm.coro.end(i8*, i1)
declare i1 @llvm.coro.end(ptr, i1)

declare void @prototype(i8*, i1 zeroext)
declare void @prototype(ptr, i1 zeroext)

declare noalias i8* @allocate(i32 %size)
declare fastcc void @deallocate(i8* %ptr)
declare noalias ptr @allocate(i32 %size)
declare fastcc void @deallocate(ptr %ptr)

declare void @print(i32)
; CHECK-LABEL: @f(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = call i8* @allocate(i32 16)
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8* [[BUFFER:%.*]] to i8**
; CHECK-NEXT: store i8* [[TMP0]], i8** [[TMP1]], align 8
; CHECK-NEXT: [[FRAMEPTR:%.*]] = bitcast i8* [[TMP0]] to %f.Frame*
; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], %f.Frame* [[FRAMEPTR]], i32 0, i32 1
; CHECK-NEXT: [[PTR_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], %f.Frame* [[FRAMEPTR]], i32 0, i32 0
; CHECK-NEXT: store i32* [[PTR:%.*]], i32** [[PTR_SPILL_ADDR]], align 8
; CHECK-NEXT: [[OLDVALUE:%.*]] = load i32, i32* [[PTR]], align 4
; CHECK-NEXT: store i32 [[OLDVALUE]], i32* [[TEMP]], align 4
; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { i8*, i32* } { i8* bitcast (void (i8*, i1)* @f.resume.0 to i8*), i32* undef }, i32* [[TEMP]], 1
; CHECK-NEXT: ret { i8*, i32* } [[TMP2]]
; CHECK-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 16)
; CHECK-NEXT: store ptr [[TMP0]], ptr [[BUFFER:%.*]], align 8
; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[TMP0]], i32 0, i32 1
; CHECK-NEXT: store ptr [[PTR:%.*]], ptr [[TMP0]], align 8
; CHECK-NEXT: [[OLDVALUE:%.*]] = load i32, ptr [[PTR]], align 4
; CHECK-NEXT: store i32 [[OLDVALUE]], ptr [[TEMP]], align 4
; CHECK-NEXT: [[TMP2:%.*]] = insertvalue { ptr, ptr } { ptr @f.resume.0, ptr undef }, ptr [[TEMP]], 1
; CHECK-NEXT: ret { ptr, ptr } [[TMP2]]
;
;
; CHECK-LABEL: @f.resume.0(
; CHECK-NEXT: entryresume.0:
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP0:%.*]] to %f.Frame**
; CHECK-NEXT: [[FRAMEPTR:%.*]] = load %f.Frame*, %f.Frame** [[TMP2]], align 8
; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], %f.Frame* [[FRAMEPTR]], i32 0, i32 1
; CHECK-NEXT: [[FRAMEPTR:%.*]] = load ptr, ptr [[TMP0:%.*]], align 8
; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[FRAMEPTR]], i32 0, i32 1
; CHECK-NEXT: br i1 [[TMP1:%.*]], label [[COROEND:%.*]], label [[CONT:%.*]]
; CHECK: cont:
; CHECK-NEXT: [[PTR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], %f.Frame* [[FRAMEPTR]], i32 0, i32 0
; CHECK-NEXT: [[PTR_RELOAD:%.*]] = load i32*, i32** [[PTR_RELOAD_ADDR]], align 8
; CHECK-NEXT: [[NEWVALUE:%.*]] = load i32, i32* [[TEMP]], align 4
; CHECK-NEXT: store i32 [[NEWVALUE]], i32* [[PTR_RELOAD]], align 4
; CHECK-NEXT: [[PTR_RELOAD:%.*]] = load ptr, ptr [[FRAMEPTR]], align 8
; CHECK-NEXT: [[NEWVALUE:%.*]] = load i32, ptr [[TEMP]], align 4
; CHECK-NEXT: store i32 [[NEWVALUE]], ptr [[PTR_RELOAD]], align 4
; CHECK-NEXT: br label [[COROEND]]
; CHECK: CoroEnd:
; CHECK-NEXT: [[TMP3:%.*]] = bitcast %f.Frame* [[FRAMEPTR]] to i8*
; CHECK-NEXT: call fastcc void @deallocate(i8* [[TMP3]])
; CHECK-NEXT: call fastcc void @deallocate(ptr [[FRAMEPTR]])
; CHECK-NEXT: ret void
;
28 changes: 14 additions & 14 deletions llvm/test/Transforms/Coroutines/coro-retcon-unreachable.ll
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,41 @@ target datalayout = "E-p:64:64"
%T4red215EmptyCollectionV = type opaque
%TSi = type <{ i64 }>

define hidden swiftcc { i8*, %swift.opaque* } @no_suspends(i8* %buffer, i64 %arg) #1 {
define hidden swiftcc { ptr, ptr } @no_suspends(ptr %buffer, i64 %arg) #1 {
; CHECK-LABEL: @no_suspends(
; CHECK-NEXT: AllocaSpillBB:
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 32, i32 8, i8* [[BUFFER:%.*]], i8* bitcast (void (i8*, i1)* @prototype to i8*), i8* bitcast (i8* (i64)* @malloc to i8*), i8* bitcast (void (i8*)* @free to i8*))
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id.retcon.once(i32 32, i32 8, ptr [[BUFFER:%.*]], ptr @prototype, ptr @malloc, ptr @free)
; CHECK-NEXT: call void @print(i64 [[ARG:%.*]])
; CHECK-NEXT: call void @llvm.trap()
; CHECK-NEXT: unreachable
;
%id = call token @llvm.coro.id.retcon.once(i32 32, i32 8, i8* %buffer, i8* bitcast (void (i8*, i1)* @prototype to i8*), i8* bitcast (i8* (i64)* @malloc to i8*), i8* bitcast (void (i8*)* @free to i8*))
%begin = call i8* @llvm.coro.begin(token %id, i8* null)
%id = call token @llvm.coro.id.retcon.once(i32 32, i32 8, ptr %buffer, ptr @prototype, ptr @malloc, ptr @free)
%begin = call ptr @llvm.coro.begin(token %id, ptr null)
call void @print(i64 %arg)
call void @llvm.trap()
unreachable

bb1:
call void @print(i64 %arg)
call i1 @llvm.coro.end(i8* %begin, i1 false)
call i1 @llvm.coro.end(ptr %begin, i1 false)
unreachable
}

declare swiftcc void @prototype(i8* noalias dereferenceable(32), i1)
declare swiftcc void @prototype(ptr noalias dereferenceable(32), i1)
declare void @print(i64)

declare noalias i8* @malloc(i64) #5
declare void @free(i8* nocapture) #5
declare noalias ptr @malloc(i64) #5
declare void @free(ptr nocapture) #5

declare token @llvm.coro.id.retcon.once(i32, i32, i8*, i8*, i8*, i8*) #5
declare i8* @llvm.coro.begin(token, i8* writeonly) #5
declare token @llvm.coro.id.retcon.once(i32, i32, ptr, ptr, ptr, ptr) #5
declare ptr @llvm.coro.begin(token, ptr writeonly) #5
declare token @llvm.coro.alloca.alloc.i64(i64, i32) #5
declare i8* @llvm.coro.alloca.get(token) #5
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #6
declare ptr @llvm.coro.alloca.get(token) #5
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #6
declare i1 @llvm.coro.suspend.retcon.i1(...) #5
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #6
declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #6
declare void @llvm.coro.alloca.free(token) #5
declare i1 @llvm.coro.end(i8*, i1) #5
declare i1 @llvm.coro.end(ptr, i1) #5

declare void @llvm.trap()

Expand Down
56 changes: 25 additions & 31 deletions llvm/test/Transforms/Coroutines/coro-retcon-value.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@
; First example from Doc/Coroutines.rst (two block loop) converted to retcon
; RUN: opt < %s -passes='default<O2>' -S | FileCheck %s

define {i8*, i32} @f(i8* %buffer, i32 %n) {
define {ptr, i32} @f(ptr %buffer, i32 %n) {
; CHECK-LABEL: @f(
; CHECK-NEXT: coro.return:
; CHECK-NEXT: [[N_VAL_SPILL_ADDR:%.*]] = bitcast i8* [[BUFFER:%.*]] to i32*
; CHECK-NEXT: store i32 [[N:%.*]], i32* [[N_VAL_SPILL_ADDR]], align 4
; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { i8*, i32 } { i8* bitcast ({ i8*, i32 } (i8*, i8)* @f.resume.0 to i8*), i32 undef }, i32 [[N]], 1
; CHECK-NEXT: ret { i8*, i32 } [[TMP0]]
; CHECK-NEXT: store i32 [[N:%.*]], ptr [[BUFFER:%.*]], align 4
; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { ptr, i32 } { ptr @f.resume.0, i32 undef }, i32 [[N]], 1
; CHECK-NEXT: ret { ptr, i32 } [[TMP0]]
;
entry:
%id = call token @llvm.coro.id.retcon(i32 8, i32 4, i8* %buffer, i8* bitcast ({i8*, i32} (i8*, i8)* @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)
%id = call token @llvm.coro.id.retcon(i32 8, i32 4, ptr %buffer, ptr @prototype, ptr @allocate, ptr @deallocate)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
br label %loop

loop:
Expand All @@ -26,7 +25,7 @@ resume:
br label %loop

cleanup:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
call i1 @llvm.coro.end(ptr %hdl, i1 0)
unreachable
}

Expand All @@ -42,40 +41,35 @@ define i32 @main() {
;
entry:
%0 = alloca [8 x i8], align 4
%buffer = bitcast [8 x i8]* %0 to i8*
%prepare = call i8* @llvm.coro.prepare.retcon(i8* bitcast ({i8*, i32} (i8*, i32)* @f to i8*))
%f = bitcast i8* %prepare to {i8*, i32} (i8*, i32)*
%result0 = call {i8*, i32} %f(i8* %buffer, i32 4)
%value0 = extractvalue {i8*, i32} %result0, 1
%prepare = call ptr @llvm.coro.prepare.retcon(ptr @f)
%result0 = call {ptr, i32} %prepare(ptr %0, i32 4)
%value0 = extractvalue {ptr, i32} %result0, 1
call void @print(i32 %value0)
%cont0 = extractvalue {i8*, i32} %result0, 0
%cont0.cast = bitcast i8* %cont0 to {i8*, i32} (i8*, i8)*
%result1 = call {i8*, i32} %cont0.cast(i8* %buffer, i8 zeroext 0)
%value1 = extractvalue {i8*, i32} %result1, 1
%cont0 = extractvalue {ptr, i32} %result0, 0
%result1 = call {ptr, i32} %cont0(ptr %0, i8 zeroext 0)
%value1 = extractvalue {ptr, i32} %result1, 1
call void @print(i32 %value1)
%cont1 = extractvalue {i8*, i32} %result1, 0
%cont1.cast = bitcast i8* %cont1 to {i8*, i32} (i8*, i8)*
%result2 = call {i8*, i32} %cont1.cast(i8* %buffer, i8 zeroext 0)
%value2 = extractvalue {i8*, i32} %result2, 1
%cont1 = extractvalue {ptr, i32} %result1, 0
%result2 = call {ptr, i32} %cont1(ptr %0, i8 zeroext 0)
%value2 = extractvalue {ptr, i32} %result2, 1
call void @print(i32 %value2)
%cont2 = extractvalue {i8*, i32} %result2, 0
%cont2.cast = bitcast i8* %cont2 to {i8*, i32} (i8*, i8)*
call {i8*, i32} %cont2.cast(i8* %buffer, i8 zeroext 1)
%cont2 = extractvalue {ptr, i32} %result2, 0
call {ptr, i32} %cont2(ptr %0, i8 zeroext 1)
ret i32 0
}

; Unfortunately, we don't seem to fully optimize this right now due
; to some sort of phase-ordering thing.

declare token @llvm.coro.id.retcon(i32, i32, i8*, i8*, i8*, i8*)
declare i8* @llvm.coro.begin(token, i8*)
declare token @llvm.coro.id.retcon(i32, i32, ptr, ptr, ptr, ptr)
declare ptr @llvm.coro.begin(token, ptr)
declare i8 @llvm.coro.suspend.retcon.i8(...)
declare i1 @llvm.coro.end(i8*, i1)
declare i8* @llvm.coro.prepare.retcon(i8*)
declare i1 @llvm.coro.end(ptr, i1)
declare ptr @llvm.coro.prepare.retcon(ptr)

declare {i8*, i32} @prototype(i8*, i8 zeroext)
declare {ptr, i32} @prototype(ptr, i8 zeroext)

declare noalias i8* @allocate(i32 %size)
declare void @deallocate(i8* %ptr)
declare noalias ptr @allocate(i32 %size)
declare void @deallocate(ptr %ptr)

declare void @print(i32)
38 changes: 19 additions & 19 deletions llvm/test/Transforms/Coroutines/coro-split-01.ll
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
; Tests that a coroutine is split, inlined into the caller and devirtualized.
; RUN: opt < %s -S -passes='default<O2>' | FileCheck %s

define i8* @f() presplitcoroutine {
define ptr @f() presplitcoroutine {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)
br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin
dyn.alloc:
%size = call i32 @llvm.coro.size.i32()
%alloc = call i8* @malloc(i32 %size)
%alloc = call ptr @malloc(i32 %size)
br label %coro.begin
coro.begin:
%phi = phi i8* [ null, %entry ], [ %alloc, %dyn.alloc ]
%hdl = call i8* @llvm.coro.begin(token %id, i8* %phi)
%phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]
%hdl = call ptr @llvm.coro.begin(token %id, ptr %phi)
call void @print(i32 0)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
Expand All @@ -22,35 +22,35 @@ resume:
br label %cleanup

cleanup:
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
call void @free(i8* %mem)
%mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
call void @free(ptr %mem)
br label %suspend
suspend:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
ret i8* %hdl
call i1 @llvm.coro.end(ptr %hdl, i1 0)
ret ptr %hdl
}
define i32 @main() {
entry:
%hdl = call i8* @f()
call void @llvm.coro.resume(i8* %hdl)
%hdl = call ptr @f()
call void @llvm.coro.resume(ptr %hdl)
ret i32 0
; CHECK-LABEL: @main(
; CHECK: call void @print(i32 0)
; CHECK: call void @print(i32 1)
; CHECK: ret i32 0
}

declare i8* @llvm.coro.free(token, i8*)
declare ptr @llvm.coro.free(token, ptr)
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 void @llvm.coro.resume(ptr)
declare void @llvm.coro.destroy(ptr)

declare token @llvm.coro.id(i32, i8*, i8*, i8*)
declare token @llvm.coro.id(i32, ptr, ptr, ptr)
declare i1 @llvm.coro.alloc(token)
declare i8* @llvm.coro.begin(token, i8*)
declare i1 @llvm.coro.end(i8*, i1)
declare ptr @llvm.coro.begin(token, ptr)
declare i1 @llvm.coro.end(ptr, i1)

declare noalias i8* @malloc(i32)
declare noalias ptr @malloc(i32)
declare void @print(i32)
declare void @free(i8*)
declare void @free(ptr)
48 changes: 24 additions & 24 deletions llvm/test/Transforms/Coroutines/coro-split-alloc.ll
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
; Tests that coro-split passes initialized values to coroutine frame allocator.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s

define i8* @f(i32 %argument) presplitcoroutine {
define ptr @f(i32 %argument) presplitcoroutine {
entry:
%argument.addr = alloca i32, align 4
%incremented = add i32 %argument, 1
store i32 %incremented, i32* %argument.addr, align 4
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
store i32 %incremented, ptr %argument.addr, align 4
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%need.alloc = call i1 @llvm.coro.alloc(token %id)
br i1 %need.alloc, label %dyn.alloc, label %begin

dyn.alloc:
%size = call i32 @llvm.coro.size.i32()
%allocator_argument = load i32, i32* %argument.addr, align 4
%alloc = call i8* @custom_alloctor(i32 %size, i32 %allocator_argument)
%allocator_argument = load i32, ptr %argument.addr, align 4
%alloc = call ptr @custom_alloctor(i32 %size, i32 %allocator_argument)
br label %begin

begin:
%phi = phi i8* [ null, %entry ], [ %alloc, %dyn.alloc ]
%hdl = call i8* @llvm.coro.begin(token %id, i8* %phi)
%print_argument = load i32, i32* %argument.addr, align 4
%phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]
%hdl = call ptr @llvm.coro.begin(token %id, ptr %phi)
%print_argument = load i32, ptr %argument.addr, align 4
call void @print(i32 %print_argument)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
Expand All @@ -29,36 +29,36 @@ resume:
br label %cleanup

cleanup:
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
call void @free(i8* %mem)
%mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
call void @free(ptr %mem)
br label %suspend
suspend:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
ret i8* %hdl
call i1 @llvm.coro.end(ptr %hdl, i1 0)
ret ptr %hdl
}

; CHECK-LABEL: @f(
; CHECK: %argument.addr = alloca i32
; CHECK: %incremented = add i32 %argument, 1
; CHECK-NEXT: store i32 %incremented, i32* %argument.addr
; CHECK-NEXT: store i32 %incremented, ptr %argument.addr
; CHECK-LABEL: dyn.alloc:
; CHECK: %allocator_argument = load i32, i32* %argument.addr
; CHECK: %alloc = call i8* @custom_alloctor(i32 24, i32 %allocator_argument)
; CHECK: %allocator_argument = load i32, ptr %argument.addr
; CHECK: %alloc = call ptr @custom_alloctor(i32 24, i32 %allocator_argument)
; CHECK-LABEL: begin:
; CHECK: %print_argument = load i32, i32* %argument.addr
; CHECK: %print_argument = load i32, ptr %argument.addr
; CHECK: call void @print(i32 %print_argument)

declare i8* @llvm.coro.free(token, i8*)
declare ptr @llvm.coro.free(token, ptr)
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 void @llvm.coro.resume(ptr)
declare void @llvm.coro.destroy(ptr)

declare token @llvm.coro.id(i32, i8*, i8*, i8*)
declare token @llvm.coro.id(i32, ptr, ptr, ptr)
declare i1 @llvm.coro.alloc(token)
declare i8* @llvm.coro.begin(token, i8*)
declare i1 @llvm.coro.end(i8*, i1)
declare ptr @llvm.coro.begin(token, ptr)
declare i1 @llvm.coro.end(ptr, i1)

declare noalias i8* @custom_alloctor(i32, i32)
declare noalias ptr @custom_alloctor(i32, i32)
declare void @print(i32)
declare void @free(i8*)
declare void @free(ptr)
40 changes: 20 additions & 20 deletions llvm/test/Transforms/Coroutines/coro-split-dbg.ll
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
declare void @bar(...) local_unnamed_addr #2

; Function Attrs: nounwind uwtable
define i8* @f() #3 !dbg !16 {
define ptr @f() #3 !dbg !16 {
entry:
%0 = tail call token @llvm.coro.id(i32 0, i8* null, i8* bitcast (i8* ()* @f to i8*), i8* null), !dbg !26
%0 = tail call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr null), !dbg !26
%1 = tail call i64 @llvm.coro.size.i64(), !dbg !26
%call = tail call i8* @malloc(i64 %1), !dbg !26
%2 = tail call i8* @llvm.coro.begin(token %0, i8* %call) #9, !dbg !26
tail call void @llvm.dbg.value(metadata i8* %2, metadata !21, metadata !12), !dbg !26
%call = tail call ptr @malloc(i64 %1), !dbg !26
%2 = tail call ptr @llvm.coro.begin(token %0, ptr %call) #9, !dbg !26
tail call void @llvm.dbg.value(metadata ptr %2, metadata !21, metadata !12), !dbg !26
br label %for.cond, !dbg !27

for.cond: ; preds = %for.cond, %entry
tail call void @llvm.dbg.value(metadata i32 undef, metadata !22, metadata !12), !dbg !28
tail call void @llvm.dbg.value(metadata i32 undef, metadata !11, metadata !12) #7, !dbg !29
tail call void (...) @bar() #7, !dbg !33
%3 = tail call token @llvm.coro.save(i8* null), !dbg !34
%3 = tail call token @llvm.coro.save(ptr null), !dbg !34
%4 = tail call i8 @llvm.coro.suspend(token %3, i1 false), !dbg !34
%conv = sext i8 %4 to i32, !dbg !34
switch i32 %conv, label %coro_Suspend [
Expand All @@ -33,32 +33,32 @@ for.cond: ; preds = %for.cond, %entry
], !dbg !34

coro_Cleanup: ; preds = %for.cond
%5 = tail call i8* @llvm.coro.free(token %0, i8* %2), !dbg !35
tail call void @free(i8* nonnull %5), !dbg !36
%5 = tail call ptr @llvm.coro.free(token %0, ptr %2), !dbg !35
tail call void @free(ptr nonnull %5), !dbg !36
br label %coro_Suspend, !dbg !36

coro_Suspend: ; preds = %for.cond, %if.then, %coro_Cleanup
tail call i1 @llvm.coro.end(i8* null, i1 false) #9, !dbg !38
ret i8* %2, !dbg !39
tail call i1 @llvm.coro.end(ptr null, i1 false) #9, !dbg !38
ret ptr %2, !dbg !39
}

; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #4
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #4

; Function Attrs: argmemonly nounwind readonly
declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #5
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #5

; Function Attrs: nounwind
declare noalias i8* @malloc(i64) local_unnamed_addr #6
declare noalias ptr @malloc(i64) local_unnamed_addr #6
declare i64 @llvm.coro.size.i64() #1
declare i8* @llvm.coro.begin(token, i8* writeonly) #7
declare token @llvm.coro.save(i8*) #7
declare ptr @llvm.coro.begin(token, ptr writeonly) #7
declare token @llvm.coro.save(ptr) #7
declare i8 @llvm.coro.suspend(token, i1) #7
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #4
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #5
declare void @free(i8* nocapture) local_unnamed_addr #6
declare i1 @llvm.coro.end(i8*, i1) #7
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #5
declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #4
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #5
declare void @free(ptr nocapture) local_unnamed_addr #6
declare i1 @llvm.coro.end(ptr, i1) #7
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #5

declare void @llvm.dbg.value(metadata, metadata, metadata) #1

Expand Down
53 changes: 24 additions & 29 deletions llvm/test/Transforms/Coroutines/coro-split-musttail-ppc64le.ll
Original file line number Diff line number Diff line change
Expand Up @@ -7,66 +7,61 @@

define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%addr1 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv1 = bitcast i8* %addr1 to void (i8*)*
call fastcc void %pv1(i8* null)
%save = call token @llvm.coro.save(ptr null)
%addr1 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr1(ptr null)

%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %exit [
i8 0, label %await.ready
i8 1, label %exit
]
await.ready:
%save2 = call token @llvm.coro.save(i8* null)
%addr2 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv2 = bitcast i8* %addr2 to void (i8*)*
call fastcc void %pv2(i8* null)
%save2 = call token @llvm.coro.save(ptr null)
%addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr2(ptr null)

%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %exit
i8 1, label %exit
]
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; Verify that in the initial function resume is not marked with musttail.
; CHECK-LABEL: @f(
; CHECK: %[[addr1:.+]] = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
; CHECK-NEXT: %[[pv1:.+]] = bitcast i8* %[[addr1]] to void (i8*)*
; CHECK-NOT: musttail call fastcc void %[[pv1]](i8* null)
; CHECK: %[[addr1:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
; CHECK-NOT: musttail call fastcc void %[[addr1]](ptr null)

; Verify that ppc target not using PC-Relative addressing in the resume part resume call is not marked with musttail.
; CHECK-LABEL: @f.resume(
; CHECK: %[[addr2:.+]] = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
; CHECK-NEXT: %[[pv2:.+]] = bitcast i8* %[[addr2]] to void (i8*)*
; CHECK-NEXT: call fastcc void %[[pv2]](i8* null)
; CHECK: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
; CHECK-NEXT: call fastcc void %[[addr2]](ptr null)

; Verify that ppc target using PC-Relative addressing in the resume part resume call is marked with musttail.
; CHECK-PCREL-LABEL: @f.resume(
; CHECK-PCREL: %[[addr2:.+]] = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
; CHECK-PCREL-NEXT: %[[pv2:.+]] = bitcast i8* %[[addr2]] to void (i8*)*
; CHECK-PCREL-NEXT: musttail call fastcc void %[[pv2]](i8* null)
; CHECK-PCREL: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
; CHECK-PCREL-NEXT: musttail call fastcc void %[[addr2]](ptr null)
; CHECK-PCREL-NEXT: ret void

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)

attributes #0 = { presplitcoroutine }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
48 changes: 22 additions & 26 deletions llvm/test/Transforms/Coroutines/coro-split-musttail.ll
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,56 @@

define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%addr1 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv1 = bitcast i8* %addr1 to void (i8*)*
call fastcc void %pv1(i8* null)
%save = call token @llvm.coro.save(ptr null)
%addr1 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr1(ptr null)

%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %exit [
i8 0, label %await.ready
i8 1, label %exit
]
await.ready:
%save2 = call token @llvm.coro.save(i8* null)
%addr2 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv2 = bitcast i8* %addr2 to void (i8*)*
call fastcc void %pv2(i8* null)
%save2 = call token @llvm.coro.save(ptr null)
%addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr2(ptr null)

%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %exit
i8 1, label %exit
]
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; Verify that in the initial function resume is not marked with musttail.
; CHECK-LABEL: @f(
; CHECK: %[[addr1:.+]] = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
; CHECK-NEXT: %[[pv1:.+]] = bitcast i8* %[[addr1]] to void (i8*)*
; CHECK-NOT: musttail call fastcc void %[[pv1]](i8* null)
; CHECK: %[[addr1:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
; CHECK-NOT: musttail call fastcc void %[[addr1]](ptr null)

; Verify that in the resume part resume call is marked with musttail.
; CHECK-LABEL: @f.resume(
; CHECK: %[[addr2:.+]] = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
; CHECK-NEXT: %[[pv2:.+]] = bitcast i8* %[[addr2]] to void (i8*)*
; CHECK-NEXT: musttail call fastcc void %[[pv2]](i8* null)
; CHECK: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
; CHECK-NEXT: musttail call fastcc void %[[addr2]](ptr null)
; CHECK-NEXT: ret void

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)

attributes #0 = { presplitcoroutine }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
80 changes: 36 additions & 44 deletions llvm/test/Transforms/Coroutines/coro-split-musttail1.ll
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,40 @@

define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%addr1 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv1 = bitcast i8* %addr1 to void (i8*)*
call fastcc void %pv1(i8* null)
%save = call token @llvm.coro.save(ptr null)
%addr1 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr1(ptr null)

%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %exit [
i8 0, label %await.suspend
i8 1, label %exit
]
await.suspend:
%save2 = call token @llvm.coro.save(i8* null)
%save2 = call token @llvm.coro.save(ptr null)
%br0 = call i8 @switch_result()
switch i8 %br0, label %unreach [
i8 0, label %await.resume3
i8 1, label %await.resume1
i8 2, label %await.resume2
]
await.resume1:
%hdl = call i8* @g()
%addr2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
%pv2 = bitcast i8* %addr2 to void (i8*)*
call fastcc void %pv2(i8* %hdl)
%hdl = call ptr @g()
%addr2 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)
call fastcc void %addr2(ptr %hdl)
br label %final.suspend
await.resume2:
%hdl2 = call i8* @h()
%addr3 = call i8* @llvm.coro.subfn.addr(i8* %hdl2, i8 0)
%pv3 = bitcast i8* %addr3 to void (i8*)*
call fastcc void %pv3(i8* %hdl2)
%hdl2 = call ptr @h()
%addr3 = call ptr @llvm.coro.subfn.addr(ptr %hdl2, i8 0)
call fastcc void %addr3(ptr %hdl2)
br label %final.suspend
await.resume3:
%addr4 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv4 = bitcast i8* %addr4 to void (i8*)*
call fastcc void %pv4(i8* null)
%addr4 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr4(ptr null)
br label %final.suspend
final.suspend:
%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
Expand All @@ -52,51 +48,47 @@ final.suspend:
pre.exit:
br label %exit
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
unreach:
unreachable
}

; Verify that in the initial function resume is not marked with musttail.
; CHECK-LABEL: @f(
; CHECK: %[[addr1:.+]] = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
; CHECK-NEXT: %[[pv1:.+]] = bitcast i8* %[[addr1]] to void (i8*)*
; CHECK-NOT: musttail call fastcc void %[[pv1]](i8* null)
; CHECK: %[[addr1:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
; CHECK-NOT: musttail call fastcc void %[[addr1]](ptr null)

; Verify that in the resume part resume call is marked with musttail.
; CHECK-LABEL: @f.resume(
; CHECK: %[[hdl:.+]] = call i8* @g()
; CHECK-NEXT: %[[addr2:.+]] = call i8* @llvm.coro.subfn.addr(i8* %[[hdl]], i8 0)
; CHECK-NEXT: %[[pv2:.+]] = bitcast i8* %[[addr2]] to void (i8*)*
; CHECK-NEXT: musttail call fastcc void %[[pv2]](i8* %[[hdl]])
; CHECK: %[[hdl:.+]] = call ptr @g()
; CHECK-NEXT: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[hdl]], i8 0)
; CHECK-NEXT: musttail call fastcc void %[[addr2]](ptr %[[hdl]])
; CHECK-NEXT: ret void
; CHECK: %[[hdl2:.+]] = call i8* @h()
; CHECK-NEXT: %[[addr3:.+]] = call i8* @llvm.coro.subfn.addr(i8* %[[hdl2]], i8 0)
; CHECK-NEXT: %[[pv3:.+]] = bitcast i8* %[[addr3]] to void (i8*)*
; CHECK-NEXT: musttail call fastcc void %[[pv3]](i8* %[[hdl2]])
; CHECK: %[[hdl2:.+]] = call ptr @h()
; CHECK-NEXT: %[[addr3:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[hdl2]], i8 0)
; CHECK-NEXT: musttail call fastcc void %[[addr3]](ptr %[[hdl2]])
; CHECK-NEXT: ret void
; CHECK: %[[addr4:.+]] = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
; CHECK-NEXT: %[[pv4:.+]] = bitcast i8* %[[addr4]] to void (i8*)*
; CHECK-NEXT: musttail call fastcc void %[[pv4]](i8* null)
; CHECK: %[[addr4:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
; CHECK-NEXT: musttail call fastcc void %[[addr4]](ptr null)
; CHECK-NEXT: ret void



declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)
declare i8 @switch_result()
declare i8* @g()
declare i8* @h()
declare ptr @g()
declare ptr @h()

attributes #0 = { presplitcoroutine }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
38 changes: 18 additions & 20 deletions llvm/test/Transforms/Coroutines/coro-split-musttail10.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,47 @@ target triple = "wasm64-unknown-unknown"

define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%addr1 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv1 = bitcast i8* %addr1 to void (i8*)*
call fastcc void %pv1(i8* null)
%save = call token @llvm.coro.save(ptr null)
%addr1 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr1(ptr null)

%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %exit [
i8 0, label %await.ready
i8 1, label %exit
]
await.ready:
%save2 = call token @llvm.coro.save(i8* null)
%addr2 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv2 = bitcast i8* %addr2 to void (i8*)*
call fastcc void %pv2(i8* null)
%save2 = call token @llvm.coro.save(ptr null)
%addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr2(ptr null)

%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %exit
i8 1, label %exit
]
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; CHECK: musttail call

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)

attributes #0 = { presplitcoroutine "target-features"="+tail-call" }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
38 changes: 18 additions & 20 deletions llvm/test/Transforms/Coroutines/coro-split-musttail11.ll
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,47 @@ target triple = "wasm32-unknown-unknown"

define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%addr1 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv1 = bitcast i8* %addr1 to void (i8*)*
call fastcc void %pv1(i8* null)
%save = call token @llvm.coro.save(ptr null)
%addr1 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr1(ptr null)

%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %exit [
i8 0, label %await.ready
i8 1, label %exit
]
await.ready:
%save2 = call token @llvm.coro.save(i8* null)
%addr2 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv2 = bitcast i8* %addr2 to void (i8*)*
call fastcc void %pv2(i8* null)
%save2 = call token @llvm.coro.save(ptr null)
%addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr2(ptr null)

%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %exit
i8 1, label %exit
]
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; CHECK: musttail call

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)

attributes #0 = { presplitcoroutine "target-features"="+tail-call" }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
40 changes: 20 additions & 20 deletions llvm/test/Transforms/Coroutines/coro-split-musttail2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,64 @@
; musttail call.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s

define void @fakeresume1(i8*) {
define void @fakeresume1(ptr) {
entry:
ret void;
}

define void @fakeresume2(i64* align 8) {
define void @fakeresume2(ptr align 8) {
entry:
ret void;
}

define void @g() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
call fastcc void @fakeresume1(i8* null)
%save = call token @llvm.coro.save(ptr null)
call fastcc void @fakeresume1(ptr null)

%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %exit [
i8 0, label %await.ready
i8 1, label %exit
]
await.ready:
%save2 = call token @llvm.coro.save(i8* null)
call fastcc void @fakeresume2(i64* align 8 null)
%save2 = call token @llvm.coro.save(ptr null)
call fastcc void @fakeresume2(ptr align 8 null)

%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %exit
i8 1, label %exit
]
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; Verify that in the initial function resume is not marked with musttail.
; CHECK-LABEL: @g(
; CHECK-NOT: musttail call fastcc void @fakeresume1(i8* null)
; CHECK-NOT: musttail call fastcc void @fakeresume1(ptr null)

; Verify that in the resume part resume call is marked with musttail.
; CHECK-LABEL: @g.resume(
; CHECK: musttail call fastcc void @fakeresume2(i64* align 8 null)
; CHECK: musttail call fastcc void @fakeresume2(ptr align 8 null)
; CHECK-NEXT: ret void

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)

attributes #0 = { presplitcoroutine }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
80 changes: 36 additions & 44 deletions llvm/test/Transforms/Coroutines/coro-split-musttail3.ll
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,38 @@

define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%addr1 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv1 = bitcast i8* %addr1 to void (i8*)*
call fastcc void %pv1(i8* null)
%save = call token @llvm.coro.save(ptr null)
%addr1 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr1(ptr null)

%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
%cmp = icmp eq i8 %suspend, 0
br i1 %cmp, label %await.suspend, label %exit
await.suspend:
%save2 = call token @llvm.coro.save(i8* null)
%save2 = call token @llvm.coro.save(ptr null)
%br0 = call i8 @switch_result()
switch i8 %br0, label %unreach [
i8 0, label %await.resume3
i8 1, label %await.resume1
i8 2, label %await.resume2
]
await.resume1:
%hdl = call i8* @g()
%addr2 = call i8* @llvm.coro.subfn.addr(i8* %hdl, i8 0)
%pv2 = bitcast i8* %addr2 to void (i8*)*
call fastcc void %pv2(i8* %hdl)
%hdl = call ptr @g()
%addr2 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)
call fastcc void %addr2(ptr %hdl)
br label %final.suspend
await.resume2:
%hdl2 = call i8* @h()
%addr3 = call i8* @llvm.coro.subfn.addr(i8* %hdl2, i8 0)
%pv3 = bitcast i8* %addr3 to void (i8*)*
call fastcc void %pv3(i8* %hdl2)
%hdl2 = call ptr @h()
%addr3 = call ptr @llvm.coro.subfn.addr(ptr %hdl2, i8 0)
call fastcc void %addr3(ptr %hdl2)
br label %final.suspend
await.resume3:
%addr4 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv4 = bitcast i8* %addr4 to void (i8*)*
call fastcc void %pv4(i8* null)
%addr4 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr4(ptr null)
br label %final.suspend
final.suspend:
%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
Expand All @@ -48,51 +44,47 @@ final.suspend:
pre.exit:
br label %exit
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
unreach:
unreachable
}

; Verify that in the initial function resume is not marked with musttail.
; CHECK-LABEL: @f(
; CHECK: %[[addr1:.+]] = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
; CHECK-NEXT: %[[pv1:.+]] = bitcast i8* %[[addr1]] to void (i8*)*
; CHECK-NOT: musttail call fastcc void %[[pv1]](i8* null)
; CHECK: %[[addr1:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
; CHECK-NOT: musttail call fastcc void %[[addr1]](ptr null)

; Verify that in the resume part resume call is marked with musttail.
; CHECK-LABEL: @f.resume(
; CHECK: %[[hdl:.+]] = call i8* @g()
; CHECK-NEXT: %[[addr2:.+]] = call i8* @llvm.coro.subfn.addr(i8* %[[hdl]], i8 0)
; CHECK-NEXT: %[[pv2:.+]] = bitcast i8* %[[addr2]] to void (i8*)*
; CHECK-NEXT: musttail call fastcc void %[[pv2]](i8* %[[hdl]])
; CHECK: %[[hdl:.+]] = call ptr @g()
; CHECK-NEXT: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[hdl]], i8 0)
; CHECK-NEXT: musttail call fastcc void %[[addr2]](ptr %[[hdl]])
; CHECK-NEXT: ret void
; CHECK: %[[hdl2:.+]] = call i8* @h()
; CHECK-NEXT: %[[addr3:.+]] = call i8* @llvm.coro.subfn.addr(i8* %[[hdl2]], i8 0)
; CHECK-NEXT: %[[pv3:.+]] = bitcast i8* %[[addr3]] to void (i8*)*
; CHECK-NEXT: musttail call fastcc void %[[pv3]](i8* %[[hdl2]])
; CHECK: %[[hdl2:.+]] = call ptr @h()
; CHECK-NEXT: %[[addr3:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[hdl2]], i8 0)
; CHECK-NEXT: musttail call fastcc void %[[addr3]](ptr %[[hdl2]])
; CHECK-NEXT: ret void
; CHECK: %[[addr4:.+]] = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
; CHECK-NEXT: %[[pv4:.+]] = bitcast i8* %[[addr4]] to void (i8*)*
; CHECK-NEXT: musttail call fastcc void %[[pv4]](i8* null)
; CHECK: %[[addr4:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
; CHECK-NEXT: musttail call fastcc void %[[addr4]](ptr null)
; CHECK-NEXT: ret void



declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)
declare i8 @switch_result()
declare i8* @g()
declare i8* @h()
declare ptr @g()
declare ptr @h()

attributes #0 = { presplitcoroutine }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
40 changes: 20 additions & 20 deletions llvm/test/Transforms/Coroutines/coro-split-musttail4.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,62 @@
; while the user of the coro.suspend is a icmpinst.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s

define void @fakeresume1(i8*) {
define void @fakeresume1(ptr) {
entry:
ret void;
}

define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%save = call token @llvm.coro.save(ptr null)

%init_suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %init_suspend, label %coro.end [
i8 0, label %await.ready
i8 1, label %coro.end
]
await.ready:
%save2 = call token @llvm.coro.save(i8* null)
%save2 = call token @llvm.coro.save(ptr null)

call fastcc void @fakeresume1(i8* align 8 null)
call fastcc void @fakeresume1(ptr align 8 null)
%suspend = call i8 @llvm.coro.suspend(token %save2, i1 true)
%switch = icmp ult i8 %suspend, 2
br i1 %switch, label %cleanup, label %coro.end

cleanup:
%free.handle = call i8* @llvm.coro.free(token %id, i8* %vFrame)
%.not = icmp eq i8* %free.handle, null
%free.handle = call ptr @llvm.coro.free(token %id, ptr %vFrame)
%.not = icmp eq ptr %free.handle, null
br i1 %.not, label %coro.end, label %coro.free

coro.free:
call void @delete(i8* nonnull %free.handle) #2
call void @delete(ptr nonnull %free.handle) #2
br label %coro.end

coro.end:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; CHECK-LABEL: @f.resume(
; CHECK: musttail call fastcc void @fakeresume1(
; CHECK-NEXT: ret void

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare void @delete(i8* nonnull) #2
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)
declare void @delete(ptr nonnull) #2

attributes #0 = { presplitcoroutine }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
46 changes: 23 additions & 23 deletions llvm/test/Transforms/Coroutines/coro-split-musttail5.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,59 @@
; to convert a resuming call to a musttail call.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s

declare void @fakeresume1(i64* align 8)
declare void @fakeresume1(ptr align 8)

define void @g() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%alloc.var = alloca i8
call void @llvm.lifetime.start.p0i8(i64 1, i8* %alloc.var)
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
call void @llvm.lifetime.start.p0(i64 1, ptr %alloc.var)
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%save = call token @llvm.coro.save(ptr null)
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)

switch i8 %suspend, label %exit [
i8 0, label %await.suspend
i8 1, label %exit
]
await.suspend:
%save2 = call token @llvm.coro.save(i8* null)
call fastcc void @fakeresume1(i64* align 8 null)
%save2 = call token @llvm.coro.save(ptr null)
call fastcc void @fakeresume1(ptr align 8 null)
%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %await.ready
i8 1, label %exit
]
await.ready:
call void @consume(i8* %alloc.var)
call void @llvm.lifetime.end.p0i8(i64 1, i8* %alloc.var)
call void @consume(ptr %alloc.var)
call void @llvm.lifetime.end.p0(i64 1, ptr %alloc.var)
br label %exit
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; Verify that in the resume part resume call is marked with musttail.
; CHECK-LABEL: @g.resume(
; CHECK: musttail call fastcc void @fakeresume1(i64* align 8 null)
; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null)
; CHECK-NEXT: ret void

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare void @consume(i8*)
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)
declare void @consume(ptr)
declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
declare void @llvm.lifetime.end.p0(i64, ptr nocapture)

attributes #0 = { presplitcoroutine }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
78 changes: 38 additions & 40 deletions llvm/test/Transforms/Coroutines/coro-split-musttail6.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,111 +5,109 @@
; optimize.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s

declare void @fakeresume1(i64* align 8)
declare void @fakeresume1(ptr align 8)

define void @g() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%alloc.var = alloca i64
%alloca.var.i8 = bitcast i64* %alloc.var to i8*
call void @llvm.lifetime.start.p0i8(i64 1, i8* %alloca.var.i8)
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
call void @llvm.lifetime.start.p0(i64 1, ptr %alloc.var)
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%save = call token @llvm.coro.save(ptr null)
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)

switch i8 %suspend, label %exit [
i8 0, label %await.suspend
i8 1, label %exit
]
await.suspend:
%save2 = call token @llvm.coro.save(i8* null)
call fastcc void @fakeresume1(i64* align 8 null)
%save2 = call token @llvm.coro.save(ptr null)
call fastcc void @fakeresume1(ptr align 8 null)
%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %await.ready
i8 1, label %exit
]
await.ready:
call void @consume(i64* %alloc.var)
call void @llvm.lifetime.end.p0i8(i64 1, i8* %alloca.var.i8)
call void @consume(ptr %alloc.var)
call void @llvm.lifetime.end.p0(i64 1, ptr %alloc.var)
br label %exit
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; Verify that in the resume part resume call is marked with musttail.
; CHECK-LABEL: @g.resume(
; CHECK: musttail call fastcc void @fakeresume1(i64* align 8 null)
; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null)
; CHECK-NEXT: ret void

; It has a cleanup bb.
define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%alloc.var = alloca i64
%alloca.var.i8 = bitcast i64* %alloc.var to i8*
call void @llvm.lifetime.start.p0i8(i64 1, i8* %alloca.var.i8)
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
call void @llvm.lifetime.start.p0(i64 1, ptr %alloc.var)
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%save = call token @llvm.coro.save(ptr null)
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)

switch i8 %suspend, label %exit [
i8 0, label %await.suspend
i8 1, label %exit
]
await.suspend:
%save2 = call token @llvm.coro.save(i8* null)
call fastcc void @fakeresume1(i64* align 8 null)
%save2 = call token @llvm.coro.save(ptr null)
call fastcc void @fakeresume1(ptr align 8 null)
%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %await.ready
i8 1, label %cleanup
]
await.ready:
call void @consume(i64* %alloc.var)
call void @llvm.lifetime.end.p0i8(i64 1, i8* %alloca.var.i8)
call void @consume(ptr %alloc.var)
call void @llvm.lifetime.end.p0(i64 1, ptr %alloc.var)
br label %exit

cleanup:
%free.handle = call i8* @llvm.coro.free(token %id, i8* %vFrame)
%.not = icmp eq i8* %free.handle, null
%free.handle = call ptr @llvm.coro.free(token %id, ptr %vFrame)
%.not = icmp eq ptr %free.handle, null
br i1 %.not, label %exit, label %coro.free

coro.free:
call void @delete(i8* nonnull %free.handle) #2
call void @delete(ptr nonnull %free.handle) #2
br label %exit

exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; FIXME: The fakeresume1 here should be marked as musttail.
; Verify that in the resume part resume call is marked with musttail.
; CHECK-LABEL: @f.resume(
; CHECK: musttail call fastcc void @fakeresume1(i64* align 8 null)
; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null)
; CHECK-NEXT: ret void

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare void @delete(i8* nonnull) #2
declare void @consume(i64*)
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)
declare void @delete(ptr nonnull) #2
declare void @consume(ptr)
declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
declare void @llvm.lifetime.end.p0(i64, ptr nocapture)

attributes #0 = { presplitcoroutine }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
80 changes: 38 additions & 42 deletions llvm/test/Transforms/Coroutines/coro-split-musttail7.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,113 +5,109 @@
; which makes the optimization harder.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s

declare void @fakeresume1(i64* align 8)
declare void @fakeresume1(ptr align 8)

define void @g() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%alloc.var = alloca i64
%alloca.var.i8 = bitcast i64* %alloc.var to i8*
call void @llvm.lifetime.start.p0i8(i64 1, i8* %alloca.var.i8)
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
call void @llvm.lifetime.start.p0(i64 1, ptr %alloc.var)
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%save = call token @llvm.coro.save(ptr null)
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)

switch i8 %suspend, label %exit [
i8 0, label %await.suspend
i8 1, label %exit
]
await.suspend:
%save2 = call token @llvm.coro.save(i8* null)
call fastcc void @fakeresume1(i64* align 8 null)
%save2 = call token @llvm.coro.save(ptr null)
call fastcc void @fakeresume1(ptr align 8 null)
%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %await.ready
i8 1, label %exit
]
await.ready:
call void @consume(i64* %alloc.var)
call void @llvm.lifetime.end.p0i8(i64 1, i8* %alloca.var.i8)
call void @consume(ptr %alloc.var)
call void @llvm.lifetime.end.p0(i64 1, ptr %alloc.var)
br label %exit
exit:
%.unused = getelementptr inbounds i8, i8* %vFrame, i32 0
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; Verify that in the resume part resume call is marked with musttail.
; CHECK-LABEL: @g.resume(
; CHECK: musttail call fastcc void @fakeresume1(i64* align 8 null)
; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null)
; CHECK-NEXT: ret void

; It has a cleanup bb.
define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%alloc.var = alloca i64
%alloca.var.i8 = bitcast i64* %alloc.var to i8*
call void @llvm.lifetime.start.p0i8(i64 1, i8* %alloca.var.i8)
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
call void @llvm.lifetime.start.p0(i64 1, ptr %alloc.var)
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%save = call token @llvm.coro.save(ptr null)
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)

switch i8 %suspend, label %exit [
i8 0, label %await.suspend
i8 1, label %exit
]
await.suspend:
%save2 = call token @llvm.coro.save(i8* null)
call fastcc void @fakeresume1(i64* align 8 null)
%save2 = call token @llvm.coro.save(ptr null)
call fastcc void @fakeresume1(ptr align 8 null)
%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %await.ready
i8 1, label %cleanup
]
await.ready:
call void @consume(i64* %alloc.var)
call void @llvm.lifetime.end.p0i8(i64 1, i8* %alloca.var.i8)
call void @consume(ptr %alloc.var)
call void @llvm.lifetime.end.p0(i64 1, ptr %alloc.var)
br label %exit

cleanup:
%free.handle = call i8* @llvm.coro.free(token %id, i8* %vFrame)
%.not = icmp eq i8* %free.handle, null
%free.handle = call ptr @llvm.coro.free(token %id, ptr %vFrame)
%.not = icmp eq ptr %free.handle, null
br i1 %.not, label %exit, label %coro.free

coro.free:
call void @delete(i8* nonnull %free.handle) #2
call void @delete(ptr nonnull %free.handle) #2
br label %exit

exit:
%.unused = getelementptr inbounds i8, i8* %vFrame, i32 0
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; FIXME: The fakeresume1 here should be marked as musttail.
; Verify that in the resume part resume call is marked with musttail.
; CHECK-LABEL: @f.resume(
; CHECK: musttail call fastcc void @fakeresume1(i64* align 8 null)
; CHECK: musttail call fastcc void @fakeresume1(ptr align 8 null)
; CHECK-NEXT: ret void

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare void @delete(i8* nonnull) #2
declare void @consume(i64*)
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture)
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)
declare void @delete(ptr nonnull) #2
declare void @consume(ptr)
declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
declare void @llvm.lifetime.end.p0(i64, ptr nocapture)

attributes #0 = { presplitcoroutine }
attributes #1 = { argmemonly nounwind readonly }
Expand Down
38 changes: 18 additions & 20 deletions llvm/test/Transforms/Coroutines/coro-split-musttail8.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,47 @@ target triple = "wasm32-unknown-unknown"

define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%addr1 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv1 = bitcast i8* %addr1 to void (i8*)*
call fastcc void %pv1(i8* null)
%save = call token @llvm.coro.save(ptr null)
%addr1 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr1(ptr null)

%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %exit [
i8 0, label %await.ready
i8 1, label %exit
]
await.ready:
%save2 = call token @llvm.coro.save(i8* null)
%addr2 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv2 = bitcast i8* %addr2 to void (i8*)*
call fastcc void %pv2(i8* null)
%save2 = call token @llvm.coro.save(ptr null)
%addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr2(ptr null)

%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %exit
i8 1, label %exit
]
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; CHECK-NOT: musttail

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)
declare void @print()

attributes #0 = { presplitcoroutine }
Expand Down
38 changes: 18 additions & 20 deletions llvm/test/Transforms/Coroutines/coro-split-musttail9.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,47 @@ target triple = "wasm64-unknown-unknown"

define void @f() #0 {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)

%save = call token @llvm.coro.save(i8* null)
%addr1 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv1 = bitcast i8* %addr1 to void (i8*)*
call fastcc void %pv1(i8* null)
%save = call token @llvm.coro.save(ptr null)
%addr1 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr1(ptr null)

%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %exit [
i8 0, label %await.ready
i8 1, label %exit
]
await.ready:
%save2 = call token @llvm.coro.save(i8* null)
%addr2 = call i8* @llvm.coro.subfn.addr(i8* null, i8 0)
%pv2 = bitcast i8* %addr2 to void (i8*)*
call fastcc void %pv2(i8* null)
%save2 = call token @llvm.coro.save(ptr null)
%addr2 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
call fastcc void %addr2(ptr null)

%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %exit [
i8 0, label %exit
i8 1, label %exit
]
exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; CHECK-NOT: musttail

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*) #1
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
declare i1 @llvm.coro.alloc(token) #2
declare i64 @llvm.coro.size.i64() #3
declare i8* @llvm.coro.begin(token, i8* writeonly) #2
declare token @llvm.coro.save(i8*) #2
declare i8* @llvm.coro.frame() #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #2
declare token @llvm.coro.save(ptr) #2
declare ptr @llvm.coro.frame() #3
declare i8 @llvm.coro.suspend(token, i1) #2
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #1
declare i1 @llvm.coro.end(i8*, i1) #2
declare i8* @llvm.coro.subfn.addr(i8* nocapture readonly, i8) #1
declare i8* @malloc(i64)
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
declare i1 @llvm.coro.end(ptr, i1) #2
declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
declare ptr @malloc(i64)
declare void @print()

attributes #0 = { presplitcoroutine }
Expand Down
52 changes: 25 additions & 27 deletions llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,28 @@
; sink them to the places after the suspend block.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s

%"struct.std::coroutine_handle" = type { i8* }
%"struct.std::coroutine_handle" = type { ptr }
%"struct.std::coroutine_handle.0" = type { %"struct.std::coroutine_handle" }
%"struct.lean_future<int>::Awaiter" = type { i32, %"struct.std::coroutine_handle.0" }

declare i1 @getcond()
declare i8* @malloc(i64)
declare ptr @malloc(i64)
declare void @print(i32)

define void @a() presplitcoroutine {
entry:
%ref.tmp7 = alloca %"struct.lean_future<int>::Awaiter", align 8
%testval = alloca i32
%cast = bitcast i32* %testval to i8*
; lifetime of %testval starts here, but not used until await.ready.
call void @llvm.lifetime.start.p0i8(i64 4, i8* %cast)
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%alloc = call i8* @malloc(i64 16) #3
%vFrame = call noalias nonnull i8* @llvm.coro.begin(token %id, i8* %alloc)
call void @llvm.lifetime.start.p0(i64 4, ptr %testval)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%alloc = call ptr @malloc(i64 16) #3
%vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)
%testcond = call i1 @getcond()
br i1 %testcond, label %if.suspend, label %else.direct

if.suspend:
%save = call token @llvm.coro.save(i8* null)
%Result.i19 = getelementptr inbounds %"struct.lean_future<int>::Awaiter", %"struct.lean_future<int>::Awaiter"* %ref.tmp7, i64 0, i32 0
%save = call token @llvm.coro.save(ptr null)
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %exit [
i8 0, label %await.ready
Expand All @@ -36,40 +34,40 @@ else.direct:
br label %after.await

await.ready:
%StrayCoroSave = call token @llvm.coro.save(i8* null)
%val = load i32, i32* %Result.i19
%test = load i32, i32* %testval
%StrayCoroSave = call token @llvm.coro.save(ptr null)
%val = load i32, ptr %ref.tmp7
%test = load i32, ptr %testval
call void @print(i32 %test)
call void @print(i32 %val)
br label %after.await

after.await:
%test1 = load i32, i32* %testval
%test1 = load i32, ptr %testval
call void @print(i32 %test1)
call void @llvm.lifetime.end.p0i8(i64 4, i8* %cast)
call void @llvm.lifetime.end.p0(i64 4, ptr %testval)
br label %exit

exit:
call i1 @llvm.coro.end(i8* null, i1 false)
call i1 @llvm.coro.end(ptr null, i1 false)
ret void
}

; CHECK-LABEL: @a.resume(
; CHECK: %[[VAL:testval.+]] = getelementptr inbounds %a.Frame
; CHECK-NOT: call void @llvm.lifetime.start.p0i8(i64 4, i8* %{{.*}})
; CHECK: %test = load i32, i32* %[[VAL]]
; CHECK-NOT: call void @llvm.lifetime.start.p0(i64 4, ptr %{{.*}})
; CHECK: %test = load i32, ptr %[[VAL]]

declare token @llvm.coro.id(i32, i8* readnone, i8* nocapture readonly, i8*)
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
declare i1 @llvm.coro.alloc(token) #3
declare noalias nonnull i8* @"\01??2@YAPEAX_K@Z"(i64) local_unnamed_addr
declare noalias nonnull ptr @"\01??2@YAPEAX_K@Z"(i64) local_unnamed_addr
declare i64 @llvm.coro.size.i64() #5
declare i8* @llvm.coro.begin(token, i8* writeonly) #3
declare ptr @llvm.coro.begin(token, ptr writeonly) #3
declare void @"\01?puts@@YAXZZ"(...)
declare token @llvm.coro.save(i8*) #3
declare i8* @llvm.coro.frame() #5
declare token @llvm.coro.save(ptr) #3
declare ptr @llvm.coro.frame() #5
declare i8 @llvm.coro.suspend(token, i1) #3
declare void @"\01??3@YAXPEAX@Z"(i8*) local_unnamed_addr #10
declare i8* @llvm.coro.free(token, i8* nocapture readonly) #2
declare i1 @llvm.coro.end(i8*, i1) #3
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #4
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) #4
declare void @"\01??3@YAXPEAX@Z"(ptr) local_unnamed_addr #10
declare ptr @llvm.coro.free(token, ptr nocapture readonly) #2
declare i1 @llvm.coro.end(ptr, i1) #3
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #4
declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #4
42 changes: 21 additions & 21 deletions llvm/test/Transforms/Coroutines/ex0.ll
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
; First example from Doc/Coroutines.rst (two block loop)
; RUN: opt < %s -aa-pipeline=basic-aa -passes='default<O2>' -preserve-alignment-assumptions-during-inlining=false -S | FileCheck %s

define i8* @f(i32 %n) presplitcoroutine {
define ptr @f(i32 %n) presplitcoroutine {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call i8* @malloc(i32 %size)
%hdl = call i8* @llvm.coro.begin(token %id, i8* %alloc)
%alloc = call ptr @malloc(i32 %size)
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
br label %loop

loop:
Expand All @@ -20,21 +20,21 @@ resume:
br label %loop

cleanup:
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
call void @free(i8* %mem)
%mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
call void @free(ptr %mem)
br label %suspend
suspend:
call i1 @llvm.coro.end(i8* %hdl, i1 0)
ret i8* %hdl
call i1 @llvm.coro.end(ptr %hdl, i1 0)
ret ptr %hdl
}

; CHECK-LABEL: @main(
define i32 @main() {
entry:
%hdl = call i8* @f(i32 4)
call void @llvm.coro.resume(i8* %hdl)
call void @llvm.coro.resume(i8* %hdl)
call void @llvm.coro.destroy(i8* %hdl)
%hdl = call ptr @f(i32 4)
call void @llvm.coro.resume(ptr %hdl)
call void @llvm.coro.resume(ptr %hdl)
call void @llvm.coro.destroy(ptr %hdl)
ret i32 0
; CHECK: entry:
; CHECK: call void @print(i32 4)
Expand All @@ -43,17 +43,17 @@ entry:
; CHECK: ret i32 0
}

declare token @llvm.coro.id(i32, i8*, i8*, i8*)
declare i8* @llvm.coro.alloc(token)
declare i8* @llvm.coro.free(token, i8*)
declare token @llvm.coro.id(i32, ptr, ptr, ptr)
declare ptr @llvm.coro.alloc(token)
declare ptr @llvm.coro.free(token, ptr)
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 void @llvm.coro.resume(ptr)
declare void @llvm.coro.destroy(ptr)

declare i8* @llvm.coro.begin(token, i8*)
declare i1 @llvm.coro.end(i8*, i1)
declare ptr @llvm.coro.begin(token, ptr)
declare i1 @llvm.coro.end(ptr, i1)

declare noalias i8* @malloc(i32)
declare noalias ptr @malloc(i32)
declare void @print(i32)
declare void @free(i8*)
declare void @free(ptr)
40 changes: 20 additions & 20 deletions llvm/test/Transforms/Coroutines/ex1.ll
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
; First example from Doc/Coroutines.rst (one block loop)
; RUN: opt < %s -aa-pipeline=basic-aa -passes='default<O2>' -preserve-alignment-assumptions-during-inlining=false -S | FileCheck %s

define i8* @f(i32 %n) presplitcoroutine {
define ptr @f(i32 %n) presplitcoroutine {
entry:
%id = call token @llvm.coro.id(i32 0, i8* null, i8* null, i8* null)
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
%alloc = call i8* @malloc(i32 %size)
%hdl = call noalias i8* @llvm.coro.begin(token %id, i8* %alloc)
%alloc = call ptr @malloc(i32 %size)
%hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %alloc)
br label %loop
loop:
%n.val = phi i32 [ %n, %entry ], [ %inc, %loop ]
Expand All @@ -16,21 +16,21 @@ loop:
switch i8 %0, label %suspend [i8 0, label %loop
i8 1, label %cleanup]
cleanup:
%mem = call i8* @llvm.coro.free(token %id, i8* %hdl)
call void @free(i8* %mem)
%mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
call void @free(ptr %mem)
br label %suspend
suspend:
call i1 @llvm.coro.end(i8* %hdl, i1 false)
ret i8* %hdl
call i1 @llvm.coro.end(ptr %hdl, i1 false)
ret ptr %hdl
}

; CHECK-LABEL: @main(
define i32 @main() {
entry:
%hdl = call i8* @f(i32 4)
call void @llvm.coro.resume(i8* %hdl)
call void @llvm.coro.resume(i8* %hdl)
call void @llvm.coro.destroy(i8* %hdl)
%hdl = call ptr @f(i32 4)
call void @llvm.coro.resume(ptr %hdl)
call void @llvm.coro.resume(ptr %hdl)
call void @llvm.coro.destroy(ptr %hdl)
ret i32 0
; CHECK-NEXT: entry:
; CHECK: call void @print(i32 4)
Expand All @@ -39,16 +39,16 @@ entry:
; CHECK: ret i32 0
}

declare i8* @malloc(i32)
declare void @free(i8*)
declare ptr @malloc(i32)
declare void @free(ptr)
declare void @print(i32)

declare token @llvm.coro.id(i32, i8*, i8*, i8*)
declare token @llvm.coro.id(i32, ptr, ptr, ptr)
declare i32 @llvm.coro.size.i32()
declare i8* @llvm.coro.begin(token, i8*)
declare ptr @llvm.coro.begin(token, ptr)
declare i8 @llvm.coro.suspend(token, i1)
declare i8* @llvm.coro.free(token, i8*)
declare i1 @llvm.coro.end(i8*, i1)
declare ptr @llvm.coro.free(token, ptr)
declare i1 @llvm.coro.end(ptr, i1)

declare void @llvm.coro.resume(i8*)
declare void @llvm.coro.destroy(i8*)
declare void @llvm.coro.resume(ptr)
declare void @llvm.coro.destroy(ptr)
Loading