[clang] [llvm] [Coroutines] Replace struct alloca frame with byte array and ptradd (PR #178359)
Jameson Nash via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 13 14:19:17 PST 2026
https://github.com/vtjnash updated https://github.com/llvm/llvm-project/pull/178359
>From 2a083fe6f54426c85f1df3c43fbc52d301fe2e6d Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash at gmail.com>
Date: Tue, 27 Jan 2026 20:09:21 +0000
Subject: [PATCH 1/7] [NFCI][Coroutines] update tests to autogenerated
formatting
---
llvm/test/Transforms/Coroutines/ArgAddr.ll | 25 +-
.../Transforms/Coroutines/coro-align16.ll | 21 +-
.../Transforms/Coroutines/coro-align32.ll | 21 +-
.../Transforms/Coroutines/coro-align64-02.ll | 21 +-
.../Transforms/Coroutines/coro-align64.ll | 21 +-
.../Transforms/Coroutines/coro-align8-02.ll | 21 +-
.../test/Transforms/Coroutines/coro-align8.ll | 21 +-
.../Coroutines/coro-alloc-with-param-O0.ll | 33 +-
.../Coroutines/coro-alloc-with-param-O2.ll | 29 +-
.../Transforms/Coroutines/coro-alloca-01.ll | 34 +-
.../Transforms/Coroutines/coro-alloca-02.ll | 25 +-
.../Transforms/Coroutines/coro-alloca-03.ll | 27 +-
.../Transforms/Coroutines/coro-alloca-04.ll | 27 +-
.../Transforms/Coroutines/coro-alloca-06.ll | 32 +-
.../Transforms/Coroutines/coro-alloca-07.ll | 57 +-
.../Transforms/Coroutines/coro-alloca-08.ll | 50 +-
.../Coroutines/coro-alloca-outside-frame.ll | 8 +-
.../Coroutines/coro-alloca-with-addrspace.ll | 73 +-
.../Coroutines/coro-async-dyn-align.ll | 104 +-
llvm/test/Transforms/Coroutines/coro-async.ll | 733 +++++++++-----
.../coro-await-suspend-lower-invoke.ll | 56 +-
.../Coroutines/coro-await-suspend-lower.ll | 44 +-
.../Transforms/Coroutines/coro-byval-param.ll | 35 +-
.../Transforms/Coroutines/coro-catchswitch.ll | 58 +-
.../Coroutines/coro-debug-coro-frame.ll | 894 +++++++++++++-----
.../Coroutines/coro-eh-aware-edge-split-01.ll | 48 +-
.../Coroutines/coro-eh-aware-edge-split-02.ll | 46 +-
.../Coroutines/coro-frame-arrayalloca.ll | 39 +-
.../Coroutines/coro-frame-reuse-alloca-01.ll | 36 +-
.../Coroutines/coro-frame-reuse-alloca-02.ll | 37 +-
.../Coroutines/coro-frame-reuse-alloca-04.ll | 42 +-
.../Coroutines/coro-frame-reuse-alloca-05.ll | 39 +-
llvm/test/Transforms/Coroutines/coro-frame.ll | 35 +-
.../Transforms/Coroutines/coro-materialize.ll | 177 +++-
.../Transforms/Coroutines/coro-padding.ll | 28 +-
.../Transforms/Coroutines/coro-param-copy.ll | 70 +-
.../Coroutines/coro-retcon-remat.ll | 18 +
.../Coroutines/coro-spill-after-phi.ll | 1 +
.../Coroutines/coro-spill-corobegin.ll | 33 +-
.../coro-spill-defs-before-corobegin.ll | 41 +-
.../Coroutines/coro-spill-promise-02.ll | 36 +-
.../Coroutines/coro-spill-promise.ll | 24 +-
.../Coroutines/coro-spill-suspend.ll | 32 +-
.../coro-split-dbg-nested-struct.ll | 55 +-
.../Coroutines/coro-split-sink-lifetime-01.ll | 80 +-
.../Coroutines/coro-split-sink-lifetime-02.ll | 38 +-
.../Coroutines/coro-split-tbaa-md.ll | 40 +-
.../Transforms/Coroutines/coro-zero-alloca.ll | 32 +-
48 files changed, 2539 insertions(+), 958 deletions(-)
diff --git a/llvm/test/Transforms/Coroutines/ArgAddr.ll b/llvm/test/Transforms/Coroutines/ArgAddr.ll
index 9328c67459077..b8a478c86a767 100644
--- a/llvm/test/Transforms/Coroutines/ArgAddr.ll
+++ b/llvm/test/Transforms/Coroutines/ArgAddr.ll
@@ -1,13 +1,15 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Need to move users of allocas that were moved into the coroutine frame after
; coro.begin.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
define nonnull ptr @f(i32 %n) presplitcoroutine {
-; CHECK-LABEL: @f(
-; CHECK-NEXT: entry:
+; CHECK-LABEL: define nonnull ptr @f(
+; CHECK-SAME: i32 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
; CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4
-; CHECK-NEXT: store i32 [[N:%.*]], ptr [[N_ADDR]], align 4
+; CHECK-NEXT: store i32 [[N]], ptr [[N_ADDR]], align 4
; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i32 24)
; CHECK-NEXT: [[TMP0:%.*]] = tail call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[CALL]])
; CHECK-NEXT: store ptr @f.resume, ptr [[TMP0]], align 8
@@ -16,6 +18,14 @@ define nonnull ptr @f(i32 %n) presplitcoroutine {
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[TMP0]], i32 0, i32 2
; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[N_ADDR]], align 4
; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4
+; CHECK-NEXT: call void @ctor(ptr [[TMP1]])
+; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP1]], align 4
+; CHECK-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP3]], -1
+; CHECK-NEXT: store i32 [[DEC]], ptr [[TMP1]], align 4
+; CHECK-NEXT: call void @print(i32 [[TMP3]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[TMP0]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[TMP0]]
;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null);
@@ -49,8 +59,15 @@ coro_Suspend:
ret ptr %1
}
-; CHECK-LABEL: @main
define i32 @main() {
+; CHECK-LABEL: define i32 @main() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[HDL:%.*]] = call ptr @f(i32 4)
+; CHECK-NEXT: call void @llvm.coro.resume(ptr [[HDL]])
+; CHECK-NEXT: call void @llvm.coro.resume(ptr [[HDL]])
+; CHECK-NEXT: call void @llvm.coro.destroy(ptr [[HDL]])
+; CHECK-NEXT: ret i32 0
+;
entry:
%hdl = call ptr @f(i32 4)
call void @llvm.coro.resume(ptr %hdl)
diff --git a/llvm/test/Transforms/Coroutines/coro-align16.ll b/llvm/test/Transforms/Coroutines/coro-align16.ll
index afdca77e8af3e..bfc16e033c0bb 100644
--- a/llvm/test/Transforms/Coroutines/coro-align16.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align16.ll
@@ -1,7 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, i64, i1 }
+
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 16, i32 40)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i64, align 16
%y = alloca i64
@@ -12,7 +27,7 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @capture_call(ptr %x)
call void @capture_call(ptr %y)
@@ -29,10 +44,6 @@ suspend:
}
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-; CHECK: %f.Frame = type { ptr, ptr, i64, i64, i1 }
-; CHECK-LABEL: define ptr @f()
-; CHECK: %[[ALLOC:.+]] = call ptr @aligned_alloc(i32 16, i32 40)
-; CHECK-NEXT: call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %[[ALLOC]])
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-align32.ll b/llvm/test/Transforms/Coroutines/coro-align32.ll
index 9e82ec83011f5..7cdaef8b0d813 100644
--- a/llvm/test/Transforms/Coroutines/coro-align32.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align32.ll
@@ -1,7 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, i1, i1, [6 x i8], i32, [12 x i8], i32 }
+
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 32, i32 56)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i64, align 16
%y = alloca i32, align 32
@@ -14,7 +29,7 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @capture_call(ptr %x)
call void @capture_call(ptr %y)
@@ -33,10 +48,6 @@ suspend:
}
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-; CHECK: %f.Frame = type { ptr, ptr, i64, i1, i1, [6 x i8], i32, [12 x i8], i32 }
-; CHECK-LABEL: define ptr @f()
-; CHECK: %[[ALLOC:.+]] = call ptr @aligned_alloc(i32 32, i32 56)
-; CHECK-NEXT: call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %[[ALLOC]])
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-align64-02.ll b/llvm/test/Transforms/Coroutines/coro-align64-02.ll
index 13c0cbe0e24da..80a8cdf827e23 100644
--- a/llvm/test/Transforms/Coroutines/coro-align64-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align64-02.ll
@@ -1,7 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i1, [15 x i8], i64, [24 x i8], i1 }
+
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 64, i32 72)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i1, align 64
%y = alloca i64, align 32
@@ -12,7 +27,7 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @capture_call(ptr %x)
call void @capture_call(ptr %y)
@@ -29,10 +44,6 @@ suspend:
}
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-; CHECK: %f.Frame = type { ptr, ptr, i1, [15 x i8], i64, [24 x i8], i1 }
-; CHECK-LABEL: define ptr @f()
-; CHECK: %[[ALLOC:.+]] = call ptr @aligned_alloc(i32 64, i32 72)
-; CHECK-NEXT: call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %[[ALLOC]])
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-align64.ll b/llvm/test/Transforms/Coroutines/coro-align64.ll
index f6cf8f40b2b41..6717093780f68 100644
--- a/llvm/test/Transforms/Coroutines/coro-align64.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align64.ll
@@ -1,7 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, i1, [39 x i8], i1 }
+
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 64, i32 72)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i1, align 64
%y = alloca i64
@@ -12,7 +27,7 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @capture_call(ptr %x)
call void @capture_call(ptr %y)
@@ -29,10 +44,6 @@ suspend:
}
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-; CHECK: %f.Frame = type { ptr, ptr, i64, i1, [39 x i8], i1 }
-; CHECK-LABEL: define ptr @f()
-; CHECK: %[[ALLOC:.+]] = call ptr @aligned_alloc(i32 64, i32 72)
-; CHECK-NEXT: call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %[[ALLOC]])
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-align8-02.ll b/llvm/test/Transforms/Coroutines/coro-align8-02.ll
index 0a6723a41256e..bfdf36de31ee8 100644
--- a/llvm/test/Transforms/Coroutines/coro-align8-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align8-02.ll
@@ -1,7 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i1 }
+
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 8, i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -10,7 +25,7 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
br label %cleanup
@@ -25,10 +40,6 @@ suspend:
}
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-; CHECK: %f.Frame = type { ptr, ptr, i1 }
-; CHECK-LABEL: define ptr @f()
-; CHECK: %[[ALLOC:.+]] = call ptr @aligned_alloc(i32 8, i32 24)
-; CHECK-NEXT: call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %[[ALLOC]])
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-align8.ll b/llvm/test/Transforms/Coroutines/coro-align8.ll
index ac083378803ec..045b3ed2f774e 100644
--- a/llvm/test/Transforms/Coroutines/coro-align8.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align8.ll
@@ -1,7 +1,22 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, i1 }
+
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 8, i32 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i64
%y = alloca i64
@@ -12,7 +27,7 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @capture_call(ptr %x)
call void @nocapture_call(ptr %y)
@@ -29,10 +44,6 @@ suspend:
}
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-; CHECK: %f.Frame = type { ptr, ptr, i64, i1 }
-; CHECK-LABEL: define ptr @f()
-; CHECK: %[[ALLOC:.+]] = call ptr @aligned_alloc(i32 8, i32 32)
-; CHECK-NEXT: call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %[[ALLOC]])
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
index 851f8a7e4e293..979772ee2290b 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
@@ -1,9 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that we can handle the case when both alloc function and
; the user body consume the same argument.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f_copy.Frame = type { ptr, ptr, i64, i1 }
+
; using copy of this (as it would happen under -O0)
define ptr @f_copy(i64 %this_arg) presplitcoroutine {
+; CHECK-LABEL: define ptr @f_copy(
+; CHECK-SAME: i64 [[THIS_ARG:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca i64, align 8
+; CHECK-NEXT: store i64 [[THIS_ARG]], ptr [[THIS_ADDR]], align 4
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_copy.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @myAlloc(i64 [[THIS_ARG]], i32 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f_copy.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_COPY_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f_copy.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[THIS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_COPY_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i64 [[THIS_ARG]], ptr [[THIS_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_COPY_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%this.addr = alloca i64
store i64 %this_arg, ptr %this.addr
@@ -14,7 +34,7 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @print2(i64 %this)
br label %cleanup
@@ -29,21 +49,10 @@ suspend:
}
; See if %this was added to the frame
-; CHECK: %f_copy.Frame = type { ptr, ptr, i64, i1 }
; See that %this is spilled into the frame
-; CHECK-LABEL: define ptr @f_copy(i64 %this_arg)
-; CHECK: %this.addr = alloca i64, align 8
-; CHECK: store i64 %this_arg, ptr %this.addr, align 4
-; CHECK: %this.spill.addr = getelementptr inbounds %f_copy.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: store i64 %this_arg, ptr %this.spill.addr
-; CHECK: ret ptr %hdl
; See that %this was loaded from the frame
-; CHECK-LABEL: @f_copy.resume(
-; CHECK: %this.reload = load i64, ptr %this.reload.addr
-; CHECK: call void @print2(i64 %this.reload)
-; CHECK: ret void
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
index ee2215efd1cd9..ea317f9b5bb54 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
@@ -1,9 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that we can handle the case when both alloc function and
; the user body consume the same argument.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f_direct.Frame = type { ptr, ptr, i64, i1 }
+
; using this directly (as it would happen under -O2)
define ptr @f_direct(i64 %this) presplitcoroutine {
+; CHECK-LABEL: define ptr @f_direct(
+; CHECK-SAME: i64 [[THIS:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_direct.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @myAlloc(i64 [[THIS]], i32 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f_direct.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_DIRECT_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f_direct.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[THIS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_DIRECT_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_DIRECT_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -11,7 +29,7 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @print2(i64 %this)
br label %cleanup
@@ -26,19 +44,10 @@ suspend:
}
; See if %this was added to the frame
-; CHECK: %f_direct.Frame = type { ptr, ptr, i64, i1 }
; See that %this is spilled into the frame
-; CHECK-LABEL: define ptr @f_direct(i64 %this)
-; CHECK: %this.spill.addr = getelementptr inbounds %f_direct.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: store i64 %this, ptr %this.spill.addr
-; CHECK: ret ptr %hdl
; See that %this was loaded from the frame
-; CHECK-LABEL: @f_direct.resume(
-; CHECK: %this.reload = load i64, ptr %this.reload.addr
-; CHECK: call void @print2(i64 %this.reload)
-; CHECK: ret void
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-01.ll b/llvm/test/Transforms/Coroutines/coro-alloca-01.ll
index f0c0bb31d40f5..c7350277d2947 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-01.ll
@@ -1,8 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that CoroSplit can succesfully determine allocas should live on the frame
; if their aliases are used across suspension points through PHINode.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, i64, ptr, i1 }
+
define ptr @f(i1 %n) presplitcoroutine {
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i1 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 48)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: br i1 [[N]], label %[[MERGE:.*]], label %[[MERGE_FROM_FLAG_FALSE:.*]]
+; CHECK: [[MERGE_FROM_FLAG_FALSE]]:
+; CHECK-NEXT: br label %[[MERGE]]
+; CHECK: [[MERGE]]:
+; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr [ [[Y_RELOAD_ADDR]], %[[MERGE_FROM_FLAG_FALSE]] ], [ [[X_RELOAD_ADDR]], %[[ENTRY]] ]
+; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store ptr [[ALIAS_PHI]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i64
%y = alloca i64
@@ -22,7 +47,7 @@ merge:
%alias_phi = phi ptr [ %x, %flag_true ], [ %y, %flag_false ]
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @print(ptr %alias_phi)
br label %cleanup
@@ -38,13 +63,6 @@ suspend:
}
; both %x and %y, as well as %alias_phi would all go to the frame.
-; CHECK: %f.Frame = type { ptr, ptr, i64, i64, ptr, i1 }
-; CHECK-LABEL: @f(
-; CHECK: %x.reload.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: %y.reload.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 3
-; CHECK: %alias_phi = phi ptr [ %y.reload.addr, %merge.from.flag_false ], [ %x.reload.addr, %entry ]
-; CHECK: %alias_phi.spill.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 4
-; CHECK: store ptr %alias_phi, ptr %alias_phi.spill.addr, align 8
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-02.ll b/llvm/test/Transforms/Coroutines/coro-alloca-02.ll
index 832132d451776..e760bd59a2e4c 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-02.ll
@@ -1,8 +1,26 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that if an alloca is escaped through storing the address,
; the alloac will be put on the frame.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
+
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store ptr [[X_RELOAD_ADDR]], ptr [[Y_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i64
%y = alloca ptr
@@ -13,7 +31,7 @@ entry:
store ptr %x, ptr %y
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
%x1 = load ptr, ptr %y
call void @print(ptr %x1)
@@ -29,11 +47,6 @@ suspend:
ret ptr %hdl
}
-; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
-; CHECK-LABEL: define ptr @f()
-; CHECK: %x.reload.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: %y.reload.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 3
-; CHECK: store ptr %x.reload.addr, ptr %y.reload.addr, align 8
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-03.ll b/llvm/test/Transforms/Coroutines/coro-alloca-03.ll
index 5148d87bbc2b2..69b9abfbb0d0f 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-03.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-03.ll
@@ -1,7 +1,26 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that allocas escaped through function calls will live on the frame.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, i1 }
+
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[Y:%.*]] = alloca i64, align 8
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: call void @capture_call(ptr [[X_RELOAD_ADDR]])
+; CHECK-NEXT: call void @nocapture_call(ptr [[Y]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i64
%y = alloca i64
@@ -13,7 +32,7 @@ entry:
call void @nocapture_call(ptr %y)
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
br label %cleanup
@@ -28,12 +47,6 @@ suspend:
}
; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-; CHECK: %f.Frame = type { ptr, ptr, i64, i1 }
-; CHECK-LABEL: define ptr @f()
-; CHECK: %y = alloca i64, align 8
-; CHECK: %x.reload.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: call void @capture_call(ptr %x.reload.addr)
-; CHECK: call void @nocapture_call(ptr %y)
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-04.ll b/llvm/test/Transforms/Coroutines/coro-alloca-04.ll
index 9df1fd4326899..12b104c9a9ad5 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-04.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-04.ll
@@ -1,8 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that CoroSplit can succesfully determine allocas should live on the frame
; if their aliases are used across suspension points through PHINode.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
+
define ptr @f(i1 %n) presplitcoroutine {
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i1 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store ptr [[TMP0]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR2]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i64
br i1 %n, label %flag_true, label %flag_false
@@ -21,7 +40,7 @@ merge:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @print(ptr %alias_phi)
br label %cleanup
@@ -37,12 +56,6 @@ suspend:
}
; both %x and %alias_phi would go to the frame.
-; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
-; CHECK-LABEL: @f(
-; CHECK: store ptr @f.destroy, ptr %destroy.addr
-; CHECK-NEXT: %0 = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: %alias_phi.spill.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 3
-; CHECK-NEXT: store ptr %0, ptr %alias_phi.spill.addr
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-06.ll b/llvm/test/Transforms/Coroutines/coro-alloca-06.ll
index 22997fbbcdfd7..ffca0534b5ec0 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-06.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-06.ll
@@ -1,10 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Test that in some simple cases allocas will not live on the frame even
; though their pointers are stored.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%handle = type { ptr }
+; CHECK: %f.Frame = type { ptr, ptr, i1 }
+
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = alloca [[HANDLE:%.*]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = alloca ptr, align 8
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TMP2:%.*]] = call ptr @await_suspend()
+; CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP0]], align 8
+; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TMP1]])
+; CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8
+; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TMP1]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%0 = alloca %"handle", align 8
%1 = alloca ptr, align 8
@@ -41,17 +63,7 @@ suspend:
ret ptr %hdl
}
-; CHECK: %f.Frame = type { ptr, ptr, i1 }
-; CHECK-LABEL: @f(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = alloca [[HANDLE:%.*]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = alloca ptr, align 8
-; CHECK: [[TMP2:%.*]] = call ptr @await_suspend()
-; CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP0]], align 8
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TMP1]])
-; CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TMP1]])
;
declare ptr @llvm.coro.free(token, ptr)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-07.ll b/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
index ac07dc33707c7..83eba2458af84 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
@@ -1,8 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that CoroSplit can succesfully determine allocas should live on the frame
; if their aliases are used across suspension points through PHINode.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, i64, ptr, i1 }
+
define ptr @f(i1 %n) presplitcoroutine {
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i1 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 48)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: br i1 [[N]], label %[[MERGE:.*]], label %[[MERGE_FROM_FLAG_FALSE:.*]]
+; CHECK: [[MERGE_FROM_FLAG_FALSE]]:
+; CHECK-NEXT: br label %[[MERGE]]
+; CHECK: [[MERGE]]:
+; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr [ [[Y_RELOAD_ADDR]], %[[MERGE_FROM_FLAG_FALSE]] ], [ [[X_RELOAD_ADDR]], %[[ENTRY]] ]
+; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store ptr [[ALIAS_PHI]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
+; CHECK-NEXT: store i8 1, ptr [[ALIAS_PHI]], align 1
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i64
%y = alloca i64
@@ -25,7 +51,7 @@ merge:
store i8 1, ptr %alias_phi
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @print(ptr %alias_phi)
br label %cleanup
@@ -58,35 +84,6 @@ declare noalias ptr @malloc(i32)
declare void @free(ptr)
; Verify that both x and y are put in the frame.
-; CHECK: %f.Frame = type { ptr, ptr, i64, i64, ptr, i1 }
-; CHECK-LABEL: @f(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 48)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%f.Frame]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: br i1 [[N:%.*]], label [[MERGE:%.*]], label [[MERGE_FROM_FLAG_FALSE:%.*]]
-; CHECK: merge.from.flag_false:
-; CHECK-NEXT: br label [[MERGE:%.*]]
-; CHECK: merge:
-; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr [ [[Y_RELOAD_ADDR]], [[MERGE_FROM_FLAG_FALSE]] ], [ [[X_RELOAD_ADDR]], [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
-; CHECK-NEXT: store ptr [[ALIAS_PHI]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
-; CHECK-NEXT: store i8 1, ptr [[ALIAS_PHI]], align 1
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
;
;
-; CHECK-LABEL: @f.resume(
-; CHECK-NEXT: entry.resume:
-; CHECK-NEXT: [[ALIAS_PHI_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 4
-; CHECK-NEXT: [[ALIAS_PHI_RELOAD:%.*]] = load ptr, ptr [[ALIAS_PHI_RELOAD_ADDR]], align 8
-; CHECK-NEXT: call void @print(ptr [[ALIAS_PHI_RELOAD]])
-; CHECK-NEXT: call void @free(ptr [[FRAMEPTR:%.*]])
-; CHECK-NEXT: ret void
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-08.ll b/llvm/test/Transforms/Coroutines/coro-alloca-08.ll
index dab55c5f0cd41..929b63b18d18f 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-08.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-08.ll
@@ -1,9 +1,13 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%"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" }
+; CHECK: %foo.Frame = type { ptr, ptr, i1 }
+; CHECK: %bar.Frame = type { ptr, ptr, i1 }
+
declare ptr @malloc(i64)
%i8.array = type { [100 x i8] }
@@ -12,6 +16,22 @@ declare void @consume.i8.array(ptr)
; The lifetime of testval starts and ends before coro.suspend. Even though consume.i8.array
; might capture it, we can safely say it won't live across suspension.
define void @foo() presplitcoroutine {
+; CHECK-LABEL: define void @foo() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TESTVAL:%.*]] = alloca [[I8_ARRAY:%.*]], align 8
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @foo.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
+; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @foo.resume, ptr [[VFRAME]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[FOO_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: store ptr @foo.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
+; CHECK-NEXT: call void @consume.i8.array(ptr [[TESTVAL]])
+; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TESTVAL]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret void
+;
entry:
%testval = alloca %i8.array
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -25,8 +45,8 @@ entry:
%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
- i8 1, label %exit
+ i8 0, label %await.ready
+ i8 1, label %exit
]
await.ready:
%StrayCoroSave = call token @llvm.coro.save(ptr null)
@@ -39,6 +59,26 @@ exit:
; The lifetime of testval starts after coro.suspend. So it will never live across suspension
; points.
define void @bar() presplitcoroutine {
+; CHECK-LABEL: define void @bar() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TESTVAL:%.*]] = alloca [[I8_ARRAY:%.*]], align 8
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @bar.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
+; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @bar.resume, ptr [[VFRAME]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: store ptr @bar.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: br i1 false, label %[[AWAIT_READY:.*]], label %[[AFTERCOROEND:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
+; CHECK-NEXT: call void @consume.i8.array(ptr [[TESTVAL]])
+; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TESTVAL]])
+; CHECK-NEXT: br label %[[AFTERCOROEND]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+;
entry:
%testval = alloca %i8.array
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -47,8 +87,8 @@ entry:
%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
- i8 1, label %exit
+ i8 0, label %await.ready
+ i8 1, label %exit
]
await.ready:
%StrayCoroSave = call token @llvm.coro.save(ptr null)
@@ -64,8 +104,6 @@ exit:
}
; Verify that for both foo and bar, testval isn't put on the frame.
-; CHECK: %foo.Frame = type { ptr, ptr, i1 }
-; CHECK: %bar.Frame = type { ptr, ptr, i1 }
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
declare i1 @llvm.coro.alloc(token) #3
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll b/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll
index e93e97fb06643..2207e00439509 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll
@@ -1,7 +1,10 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that CoroSplit can succesfully skip allocas that shall not live on the frame
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S -o %t.ll
; RUN: FileCheck --input-file=%t.ll %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
+
define ptr @f(i1 %n) presplitcoroutine {
entry:
%x = alloca i64, !coro.outside.frame !{}
@@ -22,7 +25,7 @@ merge:
%alias_phi = phi ptr [ %x, %flag_true ], [ %y, %flag_false ]
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @print(ptr %alias_phi)
br label %cleanup
@@ -38,7 +41,6 @@ suspend:
}
; %y and %alias_phi would all go to the frame, but not %x
-; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
; CHECK-LABEL: @f(
; CHECK: %x = alloca i64, align 8, !coro.outside.frame !0
; CHECK-NOT: %x.reload.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
@@ -58,4 +60,4 @@ declare void @llvm.coro.end(ptr, i1, token)
declare void @print(ptr)
declare noalias ptr @malloc(i32)
-declare void @free(ptr)
\ No newline at end of file
+declare void @free(ptr)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll b/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll
index 12057a953701c..007af29f1fad8 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll
@@ -1,6 +1,72 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='cgscc(coro-split)' -S | FileCheck %s
define ptr @f(i1 %n) presplitcoroutine {
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i1 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[X:%.*]] = alloca i64, align 8, addrspace(5)
+; CHECK-NEXT: [[Y:%.*]] = alloca i64, align 8, addrspace(5)
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 48)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
+; CHECK: [[ALLOCASPILLBB]]:
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = addrspacecast ptr [[TMP0]] to ptr addrspace(5)
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = addrspacecast ptr [[TMP1]] to ptr addrspace(5)
+; CHECK-NEXT: br label %[[POSTSPILL:.*]]
+; CHECK: [[POSTSPILL]]:
+; CHECK-NEXT: br i1 [[N]], label %[[FLAG_TRUE:.*]], label %[[FLAG_FALSE:.*]]
+; CHECK: [[FLAG_TRUE]]:
+; CHECK-NEXT: br label %[[MERGE_FROM_FLAG_TRUE:.*]]
+; CHECK: [[MERGE_FROM_FLAG_TRUE]]:
+; CHECK-NEXT: [[X_MERGE:%.*]] = phi ptr addrspace(5) [ [[X_RELOAD_ADDR]], %[[FLAG_TRUE]] ]
+; CHECK-NEXT: br label %[[MERGE:.*]]
+; CHECK: [[FLAG_FALSE]]:
+; CHECK-NEXT: br label %[[MERGE_FROM_FLAG_FALSE:.*]]
+; CHECK: [[MERGE_FROM_FLAG_FALSE]]:
+; CHECK-NEXT: [[Y_MERGE:%.*]] = phi ptr addrspace(5) [ [[Y_RELOAD_ADDR]], %[[FLAG_FALSE]] ]
+; CHECK-NEXT: br label %[[MERGE]]
+; CHECK: [[MERGE]]:
+; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr addrspace(5) [ [[X_MERGE]], %[[MERGE_FROM_FLAG_TRUE]] ], [ [[Y_MERGE]], %[[MERGE_FROM_FLAG_FALSE]] ]
+; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store ptr addrspace(5) [[ALIAS_PHI]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
+; CHECK-NEXT: br label %[[COROSAVE:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
+; CHECK: [[COROSUSPEND]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 -1, label %[[SUSPEND:.*]] [
+; CHECK-NEXT: i8 0, label %[[RESUME:.*]]
+; CHECK-NEXT: i8 1, label %[[CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[RESUME]]:
+; CHECK-NEXT: [[ALIAS_PHI_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[ALIAS_PHI_RELOAD:%.*]] = load ptr addrspace(5), ptr [[ALIAS_PHI_RELOAD_ADDR]], align 8
+; CHECK-NEXT: call void @print(ptr addrspace(5) [[ALIAS_PHI_RELOAD]])
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[MEM:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[HDL]])
+; CHECK-NEXT: call void @free(ptr [[MEM]])
+; CHECK-NEXT: br label %[[SUSPEND]]
+; CHECK: [[SUSPEND]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = alloca i64, addrspace(5)
%y = alloca i64, addrspace(5)
@@ -20,7 +86,7 @@ merge:
%alias_phi = phi ptr addrspace(5) [ %x, %flag_true ], [ %y, %flag_false ]
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @print(ptr addrspace(5) %alias_phi)
br label %cleanup
@@ -35,11 +101,6 @@ suspend:
ret ptr %hdl
}
-; CHECK-LABEL: @f(
-; CHECK: [[X_ADDR:%[0-9]+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: %x.reload.addr = addrspacecast ptr [[X_ADDR]] to ptr addrspace(5)
-; CHECK: [[Y_ADDR:%[0-9]+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 3
-; CHECK: %y.reload.addr = addrspacecast ptr [[Y_ADDR]] to ptr addrspace(5)
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll b/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll
index ffcafca891199..802d1e432bf5c 100644
--- a/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll
+++ b/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -O0 -S | FileCheck %s
target datalayout = "p:64:64:64"
@@ -8,17 +9,19 @@ target datalayout = "p:64:64:64"
%async.ctxt = type { ptr, ptr }
+; CHECK: %my_async_function.Frame = type { i64, [48 x i8], i64, i64, [16 x i8], ptr, i64, ptr }
+
@my_other_async_function_fp = external global <{ i32, i32 }>
declare void @my_other_async_function(ptr %async.ctxt)
@my_async_function_fp = constant <{ i32, i32 }>
<{ i32 trunc (
- i64 sub (
- i64 ptrtoint (ptr @my_async_function to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 32
+ i64 sub (
+ i64 ptrtoint (ptr @my_async_function to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 32
}>
declare void @opaque(ptr)
@@ -34,46 +37,73 @@ declare swiftcc void @asyncSuspend(ptr)
declare {ptr} @llvm.coro.suspend.async(i32, ptr, ptr, ...)
define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) {
+; CHECK-LABEL: define swiftcc void @my_async_function.my_other_async_function_fp.apply(
+; CHECK-SAME: ptr [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]]) {
+; CHECK-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]])
+; CHECK-NEXT: ret void
+;
tail call swiftcc void %fnPtr(ptr %async.ctxt)
ret void
}
define ptr @__swift_async_resume_project_context(ptr %ctxt) {
+; CHECK-LABEL: define ptr @__swift_async_resume_project_context(
+; CHECK-SAME: ptr [[CTXT:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
+; CHECK-NEXT: ret ptr [[RESUME_CTXT]]
+;
entry:
%resume_ctxt = load ptr, ptr %ctxt, align 8
ret ptr %resume_ctxt
}
-; CHECK: %my_async_function.Frame = type { i64, [48 x i8], i64, i64, [16 x i8], ptr, i64, ptr }
-; CHECK: define swiftcc void @my_async_function
-; CHECK: [[T0:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr %async.ctx.frameptr, i32 0, i32 3
-; CHECK: [[T1:%.*]] = ptrtoint ptr [[T0]] to i64
-; CHECK: [[T2:%.*]] = add i64 [[T1]], 31
-; CHECK: [[T3:%.*]] = and i64 [[T2]], -32
-; CHECK: [[T4:%.*]] = inttoptr i64 [[T3]] to ptr
-; CHECK: [[FP:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr %async.ctx.frameptr, i32 0, i32 0
-; CHECK: [[T6:%.*]] = ptrtoint ptr [[FP]] to i64
-; CHECK: [[T7:%.*]] = add i64 [[T6]], 63
-; CHECK: [[T8:%.*]] = and i64 [[T7]], -64
-; CHECK: [[T9:%.*]] = inttoptr i64 [[T8]] to ptr
-; CHECK: store i64 2, ptr [[T4]]
-; CHECK: store i64 3, ptr [[T9]]
define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) presplitcoroutine {
+; CHECK-LABEL: define swiftcc void @my_async_function(
+; CHECK-SAME: ptr swiftasync [[ASYNC_CTXT:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 32
+; CHECK-NEXT: [[STACK:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 6
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
+; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 31
+; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], -32
+; CHECK-NEXT: [[STACK3:%.*]] = inttoptr i64 [[TMP3]] to ptr
+; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-NEXT: [[TMP5:%.*]] = ptrtoint ptr [[TMP4]] to i64
+; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[TMP5]], 63
+; CHECK-NEXT: [[TMP7:%.*]] = and i64 [[TMP6]], -64
+; CHECK-NEXT: [[STACK4:%.*]] = inttoptr i64 [[TMP7]] to ptr
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 5
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: store i64 0, ptr [[STACK]], align 4
+; CHECK-NEXT: store i64 1, ptr [[STACK2]], align 4
+; CHECK-NEXT: store i64 2, ptr [[STACK3]], align 4
+; CHECK-NEXT: store i64 3, ptr [[STACK4]], align 4
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr null, ptr null)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 7
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]])
+; CHECK-NEXT: ret void
+;
entry:
- %tmp = alloca i64, align 8
- %tmp2 = alloca i64, align 16
- %tmp3 = alloca i64, align 32
- %tmp4 = alloca i64, align 64
+ %stack = alloca i64, align 8
+ %stack2 = alloca i64, align 16
+ %stack3 = alloca i64, align 32
+ %stack4 = alloca i64, align 64
%id = call token @llvm.coro.id.async(i32 32, i32 16, i32 0,
- ptr @my_async_function_fp)
+ ptr @my_async_function_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
- store i64 0, ptr %tmp
- store i64 1, ptr %tmp2
- store i64 2, ptr %tmp3
- store i64 3, ptr %tmp4
+ store i64 0, ptr %stack
+ store i64 1, ptr %stack2
+ store i64 2, ptr %stack3
+ store i64 3, ptr %stack4
%callee_context = call ptr @llvm.coro.async.context.alloc(ptr null, ptr null)
%callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
@@ -81,14 +111,14 @@ entry:
store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
%res = call {ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
- ptr %resume.func_ptr,
- ptr @__swift_async_resume_project_context,
- ptr @my_async_function.my_other_async_function_fp.apply,
- ptr @asyncSuspend, ptr %callee_context)
- call void @opaque(ptr %tmp)
- call void @opaque(ptr %tmp2)
- call void @opaque(ptr %tmp3)
- call void @opaque(ptr %tmp4)
+ ptr %resume.func_ptr,
+ ptr @__swift_async_resume_project_context,
+ ptr @my_async_function.my_other_async_function_fp.apply,
+ ptr @asyncSuspend, ptr %callee_context)
+ call void @opaque(ptr %stack)
+ call void @opaque(ptr %stack2)
+ call void @opaque(ptr %stack3)
+ call void @opaque(ptr %stack4)
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
tail call swiftcc void @asyncReturn(ptr %async.ctxt)
call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)
diff --git a/llvm/test/Transforms/Coroutines/coro-async.ll b/llvm/test/Transforms/Coroutines/coro-async.ll
index f94c6c11aa8b1..d1e5465784729 100644
--- a/llvm/test/Transforms/Coroutines/coro-async.ll
+++ b/llvm/test/Transforms/Coroutines/coro-async.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='default<O2>' -S | FileCheck --check-prefixes=CHECK %s
; RUN: opt < %s -O0 -S | FileCheck --check-prefixes=CHECK-O0 %s
target datalayout = "p:64:64:64"
@@ -19,25 +20,35 @@ declare void @my_other_async_function(ptr %async.ctxt)
@my_async_function_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @my_async_function to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @my_async_function to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
@my_async_function_pa_fp = constant <{ i32, i32 }>
<{ i32 trunc (
- i64 sub (
- i64 ptrtoint (ptr @my_async_function_pa to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_pa_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 8
+ i64 sub (
+ i64 ptrtoint (ptr @my_async_function_pa to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_pa_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 8
}>
; Function that implements the dispatch to the callee function.
define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) {
+; CHECK-LABEL: define swiftcc void @my_async_function.my_other_async_function_fp.apply(
+; CHECK-SAME: ptr readonly captures(none) [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @my_async_function.my_other_async_function_fp.apply(
+; CHECK-O0-SAME: ptr [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor)
ret void
}
@@ -46,12 +57,36 @@ declare void @some_user(i64)
declare void @some_may_write(ptr)
define ptr @__swift_async_resume_project_context(ptr %ctxt) {
+; CHECK-LABEL: define ptr @__swift_async_resume_project_context(
+; CHECK-SAME: ptr readonly captures(none) [[CTXT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
+; CHECK-NEXT: ret ptr [[RESUME_CTXT]]
+;
+; CHECK-O0-LABEL: define ptr @__swift_async_resume_project_context(
+; CHECK-O0-SAME: ptr [[CTXT:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
+; CHECK-O0-NEXT: ret ptr [[RESUME_CTXT]]
+;
entry:
%resume_ctxt = load ptr, ptr %ctxt, align 8
ret ptr %resume_ctxt
}
define ptr @resume_context_projection(ptr %ctxt) {
+; CHECK-LABEL: define ptr @resume_context_projection(
+; CHECK-SAME: ptr readonly captures(none) [[CTXT:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
+; CHECK-NEXT: ret ptr [[RESUME_CTXT]]
+;
+; CHECK-O0-LABEL: define ptr @resume_context_projection(
+; CHECK-O0-SAME: ptr [[CTXT:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
+; CHECK-O0-NEXT: ret ptr [[RESUME_CTXT]]
+;
entry:
%resume_ctxt = load ptr, ptr %ctxt, align 8
ret ptr %resume_ctxt
@@ -59,6 +94,54 @@ entry:
define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine !dbg !1 {
+; CHECK-LABEL: define swiftcc void @my_async_function(
+; CHECK-SAME: ptr swiftasync initializes((152, 160)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) !dbg [[DBG3:![0-9]+]] {
+; CHECK-NEXT: [[CORO_RETURN:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
+; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: store i64 1, ptr [[PROJ_2]], align 8
+; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR]])
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 160
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
+; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6:![0-9]+]]
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @my_async_function(
+; CHECK-O0-SAME: ptr swiftasync [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) !dbg [[DBG3:![0-9]+]] {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
+; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: [[VECTOR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 4
+; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[PROJ_1:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
+; CHECK-O0-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
+; CHECK-O0-NEXT: store i64 0, ptr [[PROJ_1]], align 8
+; CHECK-O0-NEXT: store i64 1, ptr [[PROJ_2]], align 8
+; CHECK-O0-NEXT: call void @some_may_write(ptr [[PROJ_1]])
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 5
+; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-O0-NEXT: [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr [[VECTOR]], align 16
+; CHECK-O0-NEXT: [[VECTOR_SPILL_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1, !dbg [[DBG6:![0-9]+]]
+; CHECK-O0-NEXT: store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_SPILL_ADDR]], align 16, !dbg [[DBG6]]
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
+; CHECK-O0-NEXT: ret void
+;
entry:
%tmp = alloca { i64, i64 }, align 8
%vector = alloca <4 x double>, align 16
@@ -66,13 +149,13 @@ entry:
%proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @my_async_function_fp)
+ ptr @my_async_function_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
store i64 0, ptr %proj.1, align 8
store i64 1, ptr %proj.2, align 8
call void @some_may_write(ptr %proj.1)
- ; Begin lowering: apply %my_other_async_function(%args...)
+ ; Begin lowering: apply %my_other_async_function(%args...)
; setup callee context
%callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
@@ -88,10 +171,10 @@ entry:
store ptr %async.ctxt, ptr %callee_context
%vector_spill = load <4 x double>, ptr %vector, align 16
%res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
- ptr %resume.func_ptr,
- ptr @__swift_async_resume_project_context,
- ptr @my_async_function.my_other_async_function_fp.apply,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !5
+ ptr %resume.func_ptr,
+ ptr @__swift_async_resume_project_context,
+ ptr @my_async_function.my_other_async_function_fp.apply,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !5
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
%continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1
@@ -106,78 +189,89 @@ entry:
}
define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) {
+; CHECK-LABEL: define void @my_async_function_pa(
+; CHECK-SAME: ptr initializes((152, 160)) [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 152
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 144
+; CHECK-NEXT: store ptr [[CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[PROJ_2_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 136
+; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR_I]], align 8
+; CHECK-NEXT: store i64 1, ptr [[PROJ_2_I]], align 8
+; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR_I]])
+; CHECK-NEXT: [[CALLEE_CONTEXT_I:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 160
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT_I]], ptr [[CALLEE_CONTEXT_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT_I]], i64 8
+; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I]], align 8
+; CHECK-NEXT: store ptr [[CTXT]], ptr [[CALLEE_CONTEXT_I]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT_I]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define void @my_async_function_pa(
+; CHECK-O0-SAME: ptr [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: call swiftcc void @my_async_function(ptr [[CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
call void @llvm.coro.async.size.replace(ptr @my_async_function_pa_fp, ptr @my_async_function_fp)
call swiftcc void @my_async_function(ptr %ctxt, ptr %task, ptr %actor)
ret void
}
; Make sure we update the async function pointer
-; CHECK: @my_async_function_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }
-; CHECK: @my_async_function_pa_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }
-; CHECK: @my_async_function2_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }
-
-; CHECK-LABEL: define swiftcc void @my_async_function(ptr swiftasync initializes((152, 160)) %async.ctxt, ptr %task, ptr %actor)
-; CHECK-O0-LABEL: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor)
-; CHECK-SAME: !dbg ![[SP1:[0-9]+]] {
-; CHECK: coro.return:
-; CHECK: [[FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 128
-; CHECK: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 152
-; CHECK: store ptr %actor, ptr [[ACTOR_SPILL_ADDR]]
-; CHECK: [[ADDR1:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 144
-; CHECK: store ptr %async.ctxt, ptr [[ADDR1]]
-; CHECK: [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 136
-; CHECK: store i64 0, ptr [[FRAMEPTR]]
-; CHECK: store i64 1, ptr [[ALLOCA_PRJ2]]
-; CHECK: tail call void @some_may_write(ptr nonnull [[FRAMEPTR]])
-; CHECK: [[CALLEE_CTXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr %task, ptr nonnull @my_other_async_function_fp)
-; CHECK: [[CALLEE_CTXT_SPILL:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 160
-; CHECK: store ptr [[CALLEE_CTXT]], ptr [[CALLEE_CTXT_SPILL]]
-; CHECK: [[TYPED_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CTXT]], i64 8
-; CHECK: store ptr @my_async_functionTQ0_, ptr [[TYPED_RETURN_TO_CALLER_ADDR]]
-; CHECK: store ptr %async.ctxt, ptr [[CALLEE_CTXT]]
+
; Make sure the spill is underaligned to the max context alignment (16).
-; CHECK-O0: [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr {{.*}}
-; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1
-; CHECK-O0: store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_ADDR]], align 16
-; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor)
-; CHECK: ret void
-; CHECK: }
-
-; CHECK-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr readonly swiftasync captures(none) %0, ptr %1, ptr readnone captures(none) %2)
-; CHECK-O0-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr swiftasync %0, ptr %1, ptr %2)
-; CHECK-SAME: !dbg ![[SP2:[0-9]+]] {
-; CHECK: entryresume.0:
-; CHECK: [[CALLER_CONTEXT:%.*]] = load ptr, ptr %0
-; CHECK: [[FRAME_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 128
-; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1
-; CHECK-O0: load <4 x double>, ptr [[VECTOR_SPILL_ADDR]], align 16
-; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 160
-; CHECK: [[CALLEE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]]
-; CHECK: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 152
-; CHECK: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]]
-; CHECK: [[ADDR1:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 144
-; CHECK: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ADDR1]]
-; CHECK: [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 136
-; CHECK: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CTXT_RELOAD]])
-; CHECK: [[VAL1:%.*]] = load i64, ptr [[FRAME_PTR]]
-; CHECK: tail call void @some_user(i64 [[VAL1]])
-; CHECK: [[VAL2:%.*]] = load i64, ptr [[ALLOCA_PRJ2]]
-; CHECK: tail call void @some_user(i64 [[VAL2]])
-; CHECK: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr %1, ptr [[ACTOR_RELOAD]])
-; CHECK: ret void
-; CHECK: }
+
@my_async_function2_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @my_async_function2 to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function2_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @my_async_function2 to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function2_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) presplitcoroutine "frame-pointer"="all" !dbg !6 {
+; CHECK-LABEL: define swiftcc void @my_async_function2(
+; CHECK-SAME: ptr [[TASK:%.*]], ptr [[ACTOR:%.*]], ptr [[ASYNC_CTXT:%.*]]) #[[ATTR1:[0-9]+]] !dbg [[DBG9:![0-9]+]] {
+; CHECK-NEXT: [[CORO_RETURN:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-NEXT: store ptr [[TASK]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
+; CHECK-NEXT: store ptr @my_async_function2.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG10:![0-9]+]]
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @my_async_function2(
+; CHECK-O0-SAME: ptr [[TASK:%.*]], ptr [[ACTOR:%.*]], ptr [[ASYNC_CTXT:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG9:![0-9]+]] {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
+; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[TASK_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: store ptr [[TASK]], ptr [[TASK_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @my_async_function2.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG10:![0-9]+]]
+; CHECK-O0-NEXT: ret void
+;
entry:
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 2, ptr @my_async_function2_fp)
@@ -190,10 +284,10 @@ entry:
store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
store ptr %async.ctxt, ptr %callee_context
%res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 2,
- ptr %resume.func_ptr,
- ptr @resume_context_projection,
- ptr @my_async_function.my_other_async_function_fp.apply,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !9
+ ptr %resume.func_ptr,
+ ptr @resume_context_projection,
+ ptr @my_async_function.my_other_async_function_fp.apply,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !9
%continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 0
@@ -202,10 +296,10 @@ entry:
store ptr %resume.func_ptr.1, ptr %callee_context.return_to_caller.addr.1
store ptr %async.ctxt, ptr %callee_context
%res.2 = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
- ptr %resume.func_ptr.1,
- ptr @resume_context_projection,
- ptr @my_async_function.my_other_async_function_fp.apply,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
+ ptr %resume.func_ptr.1,
+ ptr @resume_context_projection,
+ ptr @my_async_function.my_other_async_function_fp.apply,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
%continuation_actor_arg = extractvalue {ptr, ptr, ptr} %res.2, 1
@@ -215,58 +309,73 @@ entry:
unreachable
}
-; CHECK-LABEL: define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt)
-; CHECK-SAME: #[[FRAMEPOINTER:[0-9]+]]
-; CHECK-SAME: !dbg ![[SP3:[0-9]+]]
-; CHECK: store ptr %async.ctxt,
-; CHECK: store ptr %actor,
-; CHECK: store ptr %task,
-; CHECK: [[CALLEE_CTXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(
-; CHECK: store ptr [[CALLEE_CTXT]],
-; CHECK: store ptr @my_async_function2.resume.0,
-; CHECK: store ptr %async.ctxt,
-; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor)
-; CHECK: ret void
-
-; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.0(ptr %0, ptr readnone captures(none) %1, ptr readonly captures(none) %2)
-; CHECK-SAME: #[[FRAMEPOINTER]]
-; CHECK-SAME: !dbg ![[SP4:[0-9]+]]
-; CHECK: [[CALLEE_CTXT:%.*]] = load ptr, ptr %2
-; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CTXT]], i64 152
-; CHECK: store ptr @my_async_function2.resume.1,
-; CHECK: [[CALLLE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]]
-; CHECK: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CTXT_RELOAD]]
-; CHECK: ret void
-
-; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.1(ptr readonly captures(none) %0, ptr %1, ptr readnone captures(none) %2)
-; CHECK-SAME: #[[FRAMEPOINTER]]
-; CHECK: tail call swiftcc void @asyncReturn({{.*}}%1)
-; CHECK: ret void
+
+
define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) {
+; CHECK-LABEL: define swiftcc void @top_level_caller(
+; CHECK-SAME: ptr initializes((152, 160)) [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 152
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 144
+; CHECK-NEXT: store ptr [[CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[PROJ_2_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 136
+; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR_I]], align 8
+; CHECK-NEXT: store i64 1, ptr [[PROJ_2_I]], align 8
+; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR_I]])
+; CHECK-NEXT: [[CALLEE_CONTEXT_I:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 160
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT_I]], ptr [[CALLEE_CONTEXT_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT_I]], i64 8
+; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I]], align 8
+; CHECK-NEXT: store ptr [[CTXT]], ptr [[CALLEE_CONTEXT_I]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT_I]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @top_level_caller(
+; CHECK-O0-SAME: ptr [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: call swiftcc void @my_async_function(ptr [[CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
%prepare = call ptr @llvm.coro.prepare.async(ptr @my_async_function)
call swiftcc void %prepare(ptr %ctxt, ptr %task, ptr %actor)
ret void
}
-; CHECK-LABEL: define swiftcc void @top_level_caller(ptr initializes((152, 160)) %ctxt, ptr %task, ptr %actor)
-; CHECK: store ptr @my_async_functionTQ0_
-; CHECK: store ptr %ctxt
-; CHECK: tail call swiftcc void @asyncSuspend
-; CHECK: ret void
@dont_crash_on_cf_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @my_async_function to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @my_async_function to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
define swiftcc void @dont_crash_on_cf_dispatch(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) {
+; CHECK-LABEL: define swiftcc void @dont_crash_on_cf_dispatch(
+; CHECK-SAME: ptr readonly captures(none) [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-NEXT: br i1 [[ISNULL]], label %[[COMMON_RET:.*]], label %[[IS_NOT_NULL:.*]]
+; CHECK: [[COMMON_RET]]:
+; CHECK-NEXT: ret void
+; CHECK: [[IS_NOT_NULL]]:
+; CHECK-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: br label %[[COMMON_RET]]
+;
+; CHECK-O0-LABEL: define swiftcc void @dont_crash_on_cf_dispatch(
+; CHECK-O0-SAME: ptr [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-O0-NEXT: br i1 [[ISNULL]], label %[[IS_NULL:.*]], label %[[IS_NOT_NULL:.*]]
+; CHECK-O0: [[IS_NULL]]:
+; CHECK-O0-NEXT: ret void
+; CHECK-O0: [[IS_NOT_NULL]]:
+; CHECK-O0-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
%isNull = icmp eq ptr %task, null
br i1 %isNull, label %is_null, label %is_not_null
@@ -279,9 +388,52 @@ is_not_null:
}
define swiftcc void @dont_crash_on_cf(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
+; CHECK-LABEL: define swiftcc void @dont_crash_on_cf(
+; CHECK-SAME: ptr initializes((136, 144)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[CORO_RETURN:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
+; CHECK-NEXT: store ptr @dont_crash_on_cf.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
+; CHECK: [[IS_NOT_NULL_I]]:
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
+; CHECK: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @dont_crash_on_cf(
+; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
+; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @dont_crash_on_cf.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-O0-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-O0-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
+; CHECK-O0: [[IS_NOT_NULL_I]]:
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
+; CHECK-O0: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
+; CHECK-O0-NEXT: ret void
+;
entry:
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @dont_crash_on_cf_fp)
+ ptr @dont_crash_on_cf_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
%callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
%callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
@@ -289,10 +441,10 @@ entry:
store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
store ptr %async.ctxt, ptr %callee_context
%res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
- ptr %resume.func_ptr,
- ptr @resume_context_projection,
- ptr @dont_crash_on_cf_dispatch,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
+ ptr %resume.func_ptr,
+ ptr @resume_context_projection,
+ ptr @dont_crash_on_cf_dispatch,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
%continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1
@@ -303,23 +455,76 @@ entry:
@multiple_coro_end_async_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @multiple_coro_end_async to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @multiple_coro_end_async_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @multiple_coro_end_async to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @multiple_coro_end_async_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
define swiftcc void @must_tail_call_return(ptr %async.ctxt, ptr %task, ptr %actor) {
+; CHECK-LABEL: define swiftcc void @must_tail_call_return(
+; CHECK-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @must_tail_call_return(
+; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
musttail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %task, ptr %actor)
ret void
}
define swiftcc void @multiple_coro_end_async(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
+; CHECK-LABEL: define swiftcc void @multiple_coro_end_async(
+; CHECK-SAME: ptr initializes((136, 144)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-NEXT: [[CORO_RETURN:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
+; CHECK-NEXT: store ptr @multiple_coro_end_async.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
+; CHECK: [[IS_NOT_NULL_I]]:
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
+; CHECK: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @multiple_coro_end_async(
+; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
+; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @multiple_coro_end_async.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-O0-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-O0-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
+; CHECK-O0: [[IS_NOT_NULL_I]]:
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
+; CHECK-O0: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
+; CHECK-O0-NEXT: ret void
+;
entry:
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @dont_crash_on_cf_fp)
+ ptr @dont_crash_on_cf_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
%callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
%callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
@@ -327,10 +532,10 @@ entry:
store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
store ptr %async.ctxt, ptr %callee_context
%res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
- ptr %resume.func_ptr,
- ptr @resume_context_projection,
- ptr @dont_crash_on_cf_dispatch,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
+ ptr %resume.func_ptr,
+ ptr @resume_context_projection,
+ ptr @dont_crash_on_cf_dispatch,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
%continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1
@@ -344,40 +549,81 @@ is_equal:
is_not_equal:
call void (ptr, i1, ...) @llvm.coro.end.async(
- ptr %hdl, i1 0,
- ptr @must_tail_call_return,
- ptr %async.ctxt, ptr %continuation_task_arg, ptr null)
+ ptr %hdl, i1 0,
+ ptr @must_tail_call_return,
+ ptr %async.ctxt, ptr %continuation_task_arg, ptr null)
unreachable
}
-; CHECK-LABEL: define internal swiftcc void @multiple_coro_end_async.resume.0(
-; CHECK: musttail call swiftcc void @asyncReturn(
-; CHECK: ret void
@polymorphic_suspend_return_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @polymorphic_suspend_return to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @polymorphic_suspend_return_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 64 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @polymorphic_suspend_return to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @polymorphic_suspend_return_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 64 ; Initial async context size without space for frame
}>
define swiftcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
+; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(
+; CHECK-SAME: ptr swiftasync initializes((152, 160)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-NEXT: [[CORO_RETURN:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
+; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: store i64 1, ptr [[PROJ_2]], align 8
+; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR]])
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 160
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
+; CHECK-NEXT: store ptr @polymorphic_suspend_return.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @polymorphic_suspend_return(
+; CHECK-O0-SAME: ptr swiftasync [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
+; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[PROJ_1:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
+; CHECK-O0-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
+; CHECK-O0-NEXT: store i64 0, ptr [[PROJ_1]], align 8
+; CHECK-O0-NEXT: store i64 1, ptr [[PROJ_2]], align 8
+; CHECK-O0-NEXT: call void @some_may_write(ptr [[PROJ_1]])
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @polymorphic_suspend_return.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
entry:
%tmp = alloca { i64, i64 }, align 8
%proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0
%proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @polymorphic_suspend_return_fp)
+ ptr @polymorphic_suspend_return_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
store i64 0, ptr %proj.1, align 8
store i64 1, ptr %proj.2, align 8
call void @some_may_write(ptr %proj.1)
- ; Begin lowering: apply %my_other_async_function(%args...)
+ ; Begin lowering: apply %my_other_async_function(%args...)
; setup callee context
%callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
@@ -392,11 +638,11 @@ entry:
; store caller context into callee context
store ptr %async.ctxt, ptr %callee_context
%res = call {ptr, ptr, ptr, ptr} (i32, ptr, ptr, ...)
- @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32 256, ;; swiftasync at 0 and swiftself at 1 in resume function
- ptr %resume.func_ptr,
- ptr @resume_context_projection,
- ptr @my_async_function.my_other_async_function_fp.apply,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
+ @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32 256, ;; swiftasync at 0 and swiftself at 1 in resume function
+ ptr %resume.func_ptr,
+ ptr @resume_context_projection,
+ ptr @my_async_function.my_other_async_function_fp.apply,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
%continuation_task_arg = extractvalue {ptr, ptr, ptr, ptr} %res, 3
@@ -410,52 +656,76 @@ entry:
unreachable
}
-; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(ptr swiftasync initializes((152, 160)) %async.ctxt, ptr %task, ptr %actor)
-; CHECK-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(ptr {{.*}}swiftasync{{.*}} %0, ptr {{.*}}swiftself{{.*}} %1, ptr {{.*}}%2, ptr {{.*}}%3)
-; CHECK: }
@no_coro_suspend_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @no_coro_suspend to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @no_coro_suspend to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
define swiftcc void @no_coro_suspend(ptr %async.ctx) presplitcoroutine {
+; CHECK-LABEL: define swiftcc void @no_coro_suspend(
+; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
+; CHECK-NEXT: [[COROEND:.*:]]
+; CHECK-NEXT: [[SOME_ALLOCA:%.*]] = alloca i64, align 8
+; CHECK-NEXT: call void @some_may_write(ptr nonnull [[SOME_ALLOCA]])
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @no_coro_suspend(
+; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[SOME_ALLOCA:%.*]] = alloca i64, align 8
+; CHECK-O0-NEXT: call void @some_may_write(ptr [[SOME_ALLOCA]])
+; CHECK-O0-NEXT: ret void
+;
entry:
%some_alloca = alloca i64
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @no_coro_suspend_fp)
+ ptr @no_coro_suspend_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
call void @some_may_write(ptr %some_alloca)
call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)
unreachable
}
-; CHECK-LABEL: define swiftcc void @no_coro_suspend
-; CHECK: [[ALLOCA:%.*]] = alloca i64
-; CHECK: call void @some_may_write(ptr {{.*}}[[ALLOCA]])
@no_coro_suspend_swifterror_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @no_coro_suspend_swifterror to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_swifterror_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @no_coro_suspend_swifterror to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_swifterror_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
declare void @do_with_swifterror(ptr swifterror)
define swiftcc void @no_coro_suspend_swifterror(ptr %async.ctx) presplitcoroutine {
+; CHECK-LABEL: define swiftcc void @no_coro_suspend_swifterror(
+; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
+; CHECK-NEXT: [[COROEND:.*:]]
+; CHECK-NEXT: [[SOME_ALLOCA:%.*]] = alloca swifterror ptr, align 8
+; CHECK-NEXT: store ptr null, ptr [[SOME_ALLOCA]], align 8
+; CHECK-NEXT: call void @do_with_swifterror(ptr nonnull swifterror [[SOME_ALLOCA]])
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @no_coro_suspend_swifterror(
+; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[SOME_ALLOCA:%.*]] = alloca swifterror ptr, align 8
+; CHECK-O0-NEXT: store ptr null, ptr [[SOME_ALLOCA]], align 8
+; CHECK-O0-NEXT: call void @do_with_swifterror(ptr swifterror [[SOME_ALLOCA]])
+; CHECK-O0-NEXT: ret void
+;
entry:
%some_alloca = alloca swifterror ptr
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @no_coro_suspend_swifterror_fp)
+ ptr @no_coro_suspend_swifterror_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
store ptr null, ptr %some_alloca, align 8
call void @do_with_swifterror(ptr swifterror %some_alloca)
@@ -463,25 +733,35 @@ entry:
unreachable
}
- ; CHECK-LABEL: define swiftcc void @no_coro_suspend_swifterror
- ; CHECK: [[ALLOCA:%.*]] = alloca swifterror ptr
- ; CHECK: store ptr null, ptr [[ALLOCA]]
- ; CHECK: call void @do_with_swifterror(ptr {{.*}}swifterror{{.*}} [[ALLOCA]])
@undefined_coro_async_resume_fp = constant <{ i32, i32 }>
<{ i32 trunc (
- i64 sub (
- i64 ptrtoint (ptr @undefined_coro_async_resume to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @undefined_coro_async_resume_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 24
+ i64 sub (
+ i64 ptrtoint (ptr @undefined_coro_async_resume to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @undefined_coro_async_resume_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 24
}>
declare void @crash()
declare void @use(ptr)
define swiftcc void @undefined_coro_async_resume(ptr %async.ctx) presplitcoroutine {
+; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume(
+; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
+; CHECK-NEXT: [[COROEND:.*:]]
+; CHECK-NEXT: tail call void @use(ptr null)
+; CHECK-NEXT: tail call void @crash()
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swiftcc void @undefined_coro_async_resume(
+; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: call void @use(ptr null)
+; CHECK-O0-NEXT: call void @crash()
+; CHECK-O0-NEXT: ret void
+;
entry:
%id = call token @llvm.coro.id.async(i32 24, i32 16, i32 0, ptr @undefined_coro_async_resume_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
@@ -491,16 +771,32 @@ entry:
call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 false)
unreachable
}
-; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume
-; CHECK-NOT: @llvm.coro.async.resume
-; CHECK: call void @use(ptr null)
-; CHECK: ret
@simpleFuncTu = global <{i32, i32}> <{
i32 trunc (i64 sub (i64 ptrtoint (ptr @simpleFunc to i64),
- i64 ptrtoint (ptr @simpleFuncTu to i64)) to i32), i32 16 }>
+ i64 ptrtoint (ptr @simpleFuncTu to i64)) to i32), i32 16 }>
define swifttailcc void @simpleFunc(ptr swiftasync %0) presplitcoroutine {
+; CHECK-LABEL: define swifttailcc void @simpleFunc(
+; CHECK-SAME: ptr swiftasync [[TMP0:%.*]]) {
+; CHECK-NEXT: [[AFTERMUSTTAILCALL_BEFORE_COROEND:.*:]]
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 8
+; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-NEXT: musttail call swifttailcc void [[TMP2]](ptr swiftasync [[TMP0]])
+; CHECK-NEXT: ret void
+;
+; CHECK-O0-LABEL: define swifttailcc void @simpleFunc(
+; CHECK-O0-SAME: ptr swiftasync [[TMP0:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[TMP1:%.*]] = alloca ptr, align 8
+; CHECK-O0-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8
+; CHECK-O0-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds <{ ptr, ptr }>, ptr [[TMP2]], i32 0, i32 1
+; CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8
+; CHECK-O0-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-O0-NEXT: musttail call swifttailcc void [[TMP4]](ptr swiftasync [[TMP5]])
+; CHECK-O0-NEXT: ret void
+;
entry:
%1 = alloca ptr, align 8
%2 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @simpleFuncTu)
@@ -514,10 +810,6 @@ entry:
unreachable
}
-; CHECK-LABEL: define swifttailcc void @simpleFunc(ptr swiftasync %0) {
-; CHECK-NOT: define
-; CHECK: [[RESUME:%.*]] = load ptr
-; CHECK: musttail call swifttailcc void [[RESUME]]
define internal swifttailcc void @simpleFunc.0(ptr %0, ptr %1) alwaysinline {
entry:
@@ -544,31 +836,42 @@ declare ptr @hide(ptr)
!llvm.module.flags = !{!0}
!0 = !{i32 2, !"Debug Info Version", i32 3}
-; CHECK: ![[SP1]] = distinct !DISubprogram(name: "my_async_function",
-; CHECK-SAME: linkageName: "my_async_function",
-; CHECK-SAME: scopeLine: 1
!1 = distinct !DISubprogram(name: "my_async_function",
- linkageName: "my_async_function",
- scope: !2, file: !3, line: 1, type: !4,
- scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
-; CHECK: ![[SP2]] = distinct !DISubprogram(name: "my_async_function",
-; CHECK-SAME: linkageName: "my_async_functionTQ0_",
-; CHECK-SAME: scopeLine: 2
+ linkageName: "my_async_function",
+ scope: !2, file: !3, line: 1, type: !4,
+ scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
!2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, emissionKind: FullDebug)
!3 = !DIFile(filename: "/tmp/1.swift", directory: "/")
!4 = !DISubroutineType(types: !{})
!5 = !DILocation(line: 2, column: 0, scope: !1)
-; CHECK: ![[SP3]] = distinct !DISubprogram(name: "my_async_function2",
-; CHECK-SAME: linkageName: "my_async_function2",
-; CHECK-SAME: scopeLine: 1
!6 = distinct !DISubprogram(name: "my_async_function2",
- linkageName: "my_async_function2",
- scope: !2, file: !3, line: 1, type: !4,
- scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
-; CHECK: ![[SP4]] = distinct !DISubprogram(name: "my_async_function2",
-; CHECK-SAME: linkageName: "my_async_function2.resume.0",
-; CHECK-SAME: scopeLine: 1
+ linkageName: "my_async_function2",
+ scope: !2, file: !3, line: 1, type: !4,
+ scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
!7 = !DILexicalBlockFile(scope: !6, file: !8, discriminator: 0)
!8 = !DIFile(filename: "/tmp/fake.cpp", directory: "/")
!9 = !DILocation(line: 2, column: 0, scope: !7)
+;.
+; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_Swift, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+; CHECK: [[META1]] = !DIFile(filename: "{{.*}}1.swift", directory: {{.*}})
+; CHECK: [[DBG3]] = distinct !DISubprogram(name: "my_async_function", linkageName: "my_async_function", scope: [[META0]], file: [[META1]], line: 1, type: [[META4:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
+; CHECK: [[META4]] = !DISubroutineType(types: [[META5:![0-9]+]])
+; CHECK: [[META5]] = !{}
+; CHECK: [[DBG6]] = !DILocation(line: 2, scope: [[DBG3]])
+; CHECK: [[DBG9]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
+; CHECK: [[DBG10]] = !DILocation(line: 2, scope: [[META11:![0-9]+]])
+; CHECK: [[META11]] = !DILexicalBlockFile(scope: [[DBG9]], file: [[META12:![0-9]+]], discriminator: 0)
+; CHECK: [[META12]] = !DIFile(filename: "{{.*}}fake.cpp", directory: {{.*}})
+;.
+; CHECK-O0: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_Swift, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
+; CHECK-O0: [[META1]] = !DIFile(filename: "{{.*}}1.swift", directory: {{.*}})
+; CHECK-O0: [[DBG3]] = distinct !DISubprogram(name: "my_async_function", linkageName: "my_async_function", scope: [[META0]], file: [[META1]], line: 1, type: [[META4:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
+; CHECK-O0: [[META4]] = !DISubroutineType(types: [[META5:![0-9]+]])
+; CHECK-O0: [[META5]] = !{}
+; CHECK-O0: [[DBG6]] = !DILocation(line: 2, scope: [[DBG3]])
+; CHECK-O0: [[DBG9]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
+; CHECK-O0: [[DBG10]] = !DILocation(line: 2, scope: [[META11:![0-9]+]])
+; CHECK-O0: [[META11]] = !DILexicalBlockFile(scope: [[DBG9]], file: [[META12:![0-9]+]], discriminator: 0)
+; CHECK-O0: [[META12]] = !DIFile(filename: "{{.*}}fake.cpp", directory: {{.*}})
+;.
diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
index 67d179a8f9b04..487061d217f34 100644
--- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
+++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
@@ -1,11 +1,25 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that invoke <type> @llvm.coro.await.suspend lowers to invoke @helper
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),simplifycfg' -S | FileCheck %s
%Awaiter = type {}
-; CHECK: define {{[^@]*}} @f.resume(ptr {{[^%]*}} %[[HDL:.+]])
-; CHECK: %[[AWAITER:.+]] = getelementptr inbounds %f.Frame, ptr %[[HDL]], i32 0, i32 0
define void @f() presplitcoroutine personality i32 0 {
+; CHECK-LABEL: define void @f() personality i32 0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[AWAITER:%.*]] = alloca [[AWAITER:%.*]], align 8
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR12]], align 1
+; CHECK-NEXT: ret void
+;
entry:
%awaiter = alloca %Awaiter
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -15,60 +29,48 @@ entry:
; Initial suspend so that all 3 await_suspend invocations are inside f.resume
%suspend.init = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %suspend.init, label %ret [
- i8 0, label %step
- i8 1, label %cleanup
+ i8 0, label %step
+ i8 1, label %cleanup
]
-; CHECK: invoke void @await_suspend_wrapper_void(ptr %[[AWAITER]], ptr %[[HDL]])
-; CHECK-NEXT: to label %[[STEP_CONT:[^ ]+]] unwind label %[[PAD:[^ ]+]]
step:
%save = call token @llvm.coro.save(ptr null)
invoke void @llvm.coro.await.suspend.void(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_void)
- to label %step.continue unwind label %pad
+ to label %step.continue unwind label %pad
; CHECK [[STEP_CONT]]:
step.continue:
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %ret [
- i8 0, label %step1
- i8 1, label %cleanup
+ i8 0, label %step1
+ i8 1, label %cleanup
]
-; CHECK: %[[RESUME:.+]] = invoke i1 @await_suspend_wrapper_bool(ptr %[[AWAITER]], ptr %[[HDL]])
-; CHECK-NEXT: to label %[[STEP1_CONT:[^ ]+]] unwind label %[[PAD]]
step1:
%save1 = call token @llvm.coro.save(ptr null)
%resume.bool = invoke i1 @llvm.coro.await.suspend.bool(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_bool)
- to label %step1.continue unwind label %pad
+ to label %step1.continue unwind label %pad
-; CHECK: [[STEP1_CONT]]:
-; CHECK-NEXT: br i1 %[[RESUME]], label %{{[^,]+}}, label %[[STEP2:.+]]
step1.continue:
br i1 %resume.bool, label %suspend.cond, label %step2
suspend.cond:
%suspend1 = call i8 @llvm.coro.suspend(token %save1, i1 false)
switch i8 %suspend1, label %ret [
- i8 0, label %step2
- i8 1, label %cleanup
+ i8 0, label %step2
+ i8 1, label %cleanup
]
-; CHECK: [[STEP2]]:
-; CHECK: %[[NEXT_HDL:.+]] = invoke ptr @await_suspend_wrapper_handle(ptr %[[AWAITER]], ptr %[[HDL]])
-; CHECK-NEXT: to label %[[STEP2_CONT:[^ ]+]] unwind label %[[PAD]]
step2:
%save2 = call token @llvm.coro.save(ptr null)
invoke void @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_handle)
- to label %step2.continue unwind label %pad
+ to label %step2.continue unwind label %pad
-; CHECK: [[STEP2_CONT]]:
-; CHECK-NEXT: %[[NEXT_RESUME:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[NEXT_HDL]], i8 0)
-; CHECK-NEXT: musttail call {{.*}} void %[[NEXT_RESUME]](ptr %[[NEXT_HDL]])
step2.continue:
%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %ret [
- i8 0, label %step3
- i8 1, label %cleanup
+ i8 0, label %step3
+ i8 1, label %cleanup
]
step3:
@@ -76,7 +78,7 @@ step3:
pad:
%lp = landingpad { ptr, i32 }
- catch ptr null
+ catch ptr null
%exn = extractvalue { ptr, i32 } %lp, 0
call ptr @__cxa_begin_catch(ptr %exn)
call void @__cxa_end_catch()
@@ -93,8 +95,6 @@ ret:
}
; check that we were haven't accidentally went out of @f.resume body
-; CHECK-LABEL: @f.destroy(
-; CHECK-LABEL: @f.cleanup(
declare void @await_suspend_wrapper_void(ptr, ptr)
declare i1 @await_suspend_wrapper_bool(ptr, ptr)
diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
index 72a158abffc6b..25c7a81d26dc0 100644
--- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
+++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
@@ -1,11 +1,25 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests lowerings of different versions of coro.await.suspend
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),simplifycfg' -S | FileCheck %s
%Awaiter = type {}
-; CHECK: define {{[^@]*}} @f.resume(ptr {{[^%]*}} %[[HDL:.+]])
-; CHECK: %[[AWAITER:.+]] = getelementptr inbounds %f.Frame, ptr %[[HDL]], i32 0, i32 0
define void @f() presplitcoroutine {
+; CHECK-LABEL: define void @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[AWAITER:%.*]] = alloca [[AWAITER:%.*]], align 8
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR12]], align 1
+; CHECK-NEXT: ret void
+;
entry:
%awaiter = alloca %Awaiter
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -14,23 +28,19 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%suspend.init = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %suspend.init, label %ret [
- i8 0, label %step
- i8 1, label %cleanup
+ i8 0, label %step
+ i8 1, label %cleanup
]
-; CHECK: call void @await_suspend_wrapper_void(ptr %[[AWAITER]], ptr %[[HDL]])
-; CHECK-NEXT: br label %{{.*}}
step:
%save = call token @llvm.coro.save(ptr null)
call void @llvm.coro.await.suspend.void(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_void)
%suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
switch i8 %suspend, label %ret [
- i8 0, label %step1
- i8 1, label %cleanup
+ i8 0, label %step1
+ i8 1, label %cleanup
]
-; CHECK: %[[RESUME:.+]] = call i1 @await_suspend_wrapper_bool(ptr %[[AWAITER]], ptr %[[HDL]])
-; CHECK-NEXT: br i1 %[[RESUME]], label %{{[^,]+}}, label %[[STEP2:.+]]
step1:
%save1 = call token @llvm.coro.save(ptr null)
%resume.bool = call i1 @llvm.coro.await.suspend.bool(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_bool)
@@ -39,21 +49,17 @@ step1:
suspend.cond:
%suspend1 = call i8 @llvm.coro.suspend(token %save1, i1 false)
switch i8 %suspend1, label %ret [
- i8 0, label %step2
- i8 1, label %cleanup
+ i8 0, label %step2
+ i8 1, label %cleanup
]
-; CHECK: [[STEP2]]:
-; CHECK: %[[NEXT_HDL:.+]] = call ptr @await_suspend_wrapper_handle(ptr %[[AWAITER]], ptr %[[HDL]])
-; CHECK-NEXT: %[[CONT:.+]] = call ptr @llvm.coro.subfn.addr(ptr %[[NEXT_HDL]], i8 0)
-; CHECK-NEXT: musttail call {{.*}} void %[[CONT]](ptr %[[NEXT_HDL]])
step2:
%save2 = call token @llvm.coro.save(ptr null)
call void @llvm.coro.await.suspend.handle(ptr %awaiter, ptr %hdl, ptr @await_suspend_wrapper_handle)
%suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
switch i8 %suspend2, label %ret [
- i8 0, label %step3
- i8 1, label %cleanup
+ i8 0, label %step3
+ i8 1, label %cleanup
]
step3:
@@ -70,8 +76,6 @@ ret:
}
; check that we were haven't accidentally went out of @f.resume body
-; CHECK-LABEL: @f.destroy(
-; CHECK-LABEL: @f.cleanup(
declare void @await_suspend_wrapper_void(ptr, ptr)
declare i1 @await_suspend_wrapper_bool(ptr, ptr)
diff --git a/llvm/test/Transforms/Coroutines/coro-byval-param.ll b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
index 95bb7be73b04f..4575c0af8ee11 100644
--- a/llvm/test/Transforms/Coroutines/coro-byval-param.ll
+++ b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
@@ -1,9 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%promise_type = type { i8 }
%struct.A = type <{ i64, i64, i32, [4 x i8] }>
+; CHECK: %foo.Frame = type { ptr, ptr, %promise_type, i1, [6 x i8], %struct.A }
+
; Function Attrs: noinline ssp uwtable mustprogress
define ptr @foo(ptr nocapture readonly byval(%struct.A) align 8 %a1) #0 {
+; CHECK-LABEL: define ptr @foo(
+; CHECK-SAME: ptr readonly byval([[STRUCT_A:%.*]]) align 8 [[A1:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @foo, ptr @foo.resumers)
+; CHECK-NEXT: [[TMP1:%.*]] = call i1 @llvm.coro.alloc(token [[TMP0]])
+; CHECK-NEXT: br i1 [[TMP1]], label %[[CORO_ALLOC:.*]], label %[[CORO_INIT:.*]]
+; CHECK: [[CORO_ALLOC]]:
+; CHECK-NEXT: [[CALL:%.*]] = call noalias nonnull ptr @_Znwm(i64 48) #[[ATTR11:[0-9]+]]
+; CHECK-NEXT: br label %[[CORO_INIT]]
+; CHECK: [[CORO_INIT]]:
+; CHECK-NEXT: [[TMP2:%.*]] = phi ptr [ [[CALL]], %[[CORO_ALLOC]] ], [ null, %[[ENTRY]] ]
+; CHECK-NEXT: [[TMP3:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr [[TMP2]])
+; CHECK-NEXT: store ptr @foo.resume, ptr [[TMP3]], align 8
+; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], ptr @foo.destroy, ptr @foo.cleanup
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[FOO_FRAME:%.*]], ptr [[TMP3]], i32 0, i32 1
+; CHECK-NEXT: store ptr [[TMP4]], ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[TMP3]], i32 0, i32 2
+; CHECK-NEXT: [[A1_SPILL_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[TMP3]], i32 0, i32 5
+; CHECK-NEXT: [[TMP5:%.*]] = load [[STRUCT_A]], ptr [[A1]], align 1
+; CHECK-NEXT: store [[STRUCT_A]] [[TMP5]], ptr [[A1_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALL2:%.*]] = call ptr @_ZN4task12promise_type17get_return_objectEv(ptr nonnull dereferenceable(1) [[__PROMISE_RELOAD_ADDR]])
+; CHECK-NEXT: call void @initial_suspend(ptr nonnull dereferenceable(1) [[__PROMISE_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds nuw [[FOO_FRAME]], ptr [[TMP3]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR5]], align 1
+; CHECK-NEXT: call fastcc void @_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr [[TMP3]]) #[[ATTR2:[0-9]+]]
+; CHECK-NEXT: ret ptr [[CALL2]]
+;
entry:
%__promise = alloca %promise_type, align 1
%a2 = alloca %struct.A, align 8
@@ -26,8 +56,8 @@ coro.init: ; preds = %coro.alloc, %entry
call fastcc void @_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr %4) #2
%6 = call i8 @llvm.coro.suspend(token %5, i1 false)
switch i8 %6, label %coro.ret [
- i8 0, label %init.ready
- i8 1, label %cleanup33
+ i8 0, label %init.ready
+ i8 1, label %cleanup33
]
init.ready: ; preds = %coro.init
@@ -58,7 +88,6 @@ coro.ret: ; preds = %coro.free, %cleanup
; check that the frame contains the entire struct, instead of just the struct pointer,
; and that the alignment is taken into account.
-; CHECK: %foo.Frame = type { ptr, ptr, %promise_type, i1, [6 x i8], %struct.A }
; Function Attrs: argmemonly nounwind readonly
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
diff --git a/llvm/test/Transforms/Coroutines/coro-catchswitch.ll b/llvm/test/Transforms/Coroutines/coro-catchswitch.ll
index 06f1435dc966c..ec55954cea194 100644
--- a/llvm/test/Transforms/Coroutines/coro-catchswitch.ll
+++ b/llvm/test/Transforms/Coroutines/coro-catchswitch.ll
@@ -1,11 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Verifies that we can insert the spill for a PHI preceding the catchswitch
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc"
-; CHECK-LABEL: define void @f(
define void @f(i1 %cond) presplitcoroutine personality i32 0 {
+; CHECK-LABEL: define void @f(
+; CHECK-SAME: i1 [[COND:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 8, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 16)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 4
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 4
+; CHECK-NEXT: br i1 [[COND]], label %[[IF_ELSE:.*]], label %[[IF_THEN:.*]]
+; CHECK: [[IF_THEN]]:
+; CHECK-NEXT: invoke void @may_throw1()
+; CHECK-NEXT: to label %[[AFTERCOROEND:.*]] unwind label %[[CATCH_DISPATCH:.*]]
+; CHECK: [[IF_ELSE]]:
+; CHECK-NEXT: invoke void @may_throw2()
+; CHECK-NEXT: to label %[[AFTERCOROEND]] unwind label %[[CATCH_DISPATCH]]
+; CHECK: [[CATCH_DISPATCH]]:
+; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ 1, %[[IF_THEN]] ], [ 2, %[[IF_ELSE]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = cleanuppad within none []
+; CHECK-NEXT: [[VAL_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[VAL]], ptr [[VAL_SPILL_ADDR]], align 4
+; CHECK-NEXT: cleanupret from [[TMP0]] unwind label %[[BB1:.*]]
+; CHECK: [[BB1]]:
+; CHECK-NEXT: [[SWITCH:%.*]] = catchswitch within none [label %[[CATCH:.*]]] unwind to caller
+; CHECK: [[CATCH]]:
+; CHECK-NEXT: [[PAD:%.*]] = catchpad within [[SWITCH]] [ptr null, i32 64, ptr null]
+; CHECK-NEXT: catchret from [[PAD]] to label %[[COROSAVE:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR3:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR3]], align 1
+; CHECK-NEXT: br i1 false, label %[[RESUME:.*]], label %[[AFTERCOROEND]]
+; CHECK: [[RESUME]]:
+; CHECK-NEXT: [[VAL_RELOAD:%.*]] = load i32, ptr [[VAL_SPILL_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[VAL_RELOAD]])
+; CHECK-NEXT: br label %[[AFTERCOROEND]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+;
entry:
%id = call token @llvm.coro.id(i32 8, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -15,11 +53,11 @@ entry:
if.then:
invoke void @may_throw1()
- to label %coro.ret unwind label %catch.dispatch
+ to label %coro.ret unwind label %catch.dispatch
if.else:
invoke void @may_throw2()
- to label %coro.ret unwind label %catch.dispatch
+ to label %coro.ret unwind label %catch.dispatch
catch.dispatch: ; preds = %if.else, %if.then
%val = phi i32 [ 1, %if.then ], [ 2, %if.else ]
@@ -28,15 +66,7 @@ catch.dispatch: ; preds = %if.else, %if.then
; Verifies that we split out the PHI into a separate block
; added a cleanuppad spill cleanupret unwinding into the catchswitch.
-; CHECK: catch.dispatch:
-; CHECK: %val = phi i32 [ 1, %if.then ], [ 2, %if.else ]
-; CHECK: %[[Pad:.+]] = cleanuppad within none []
-; CHECK: %val.spill.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: store i32 %val, ptr %val.spill.addr
-; CHECK: cleanupret from %[[Pad]] unwind label %[[Switch:.+]]
-; CHECK: [[Switch]]:
-; CHECK: %switch = catchswitch within none [label %catch] unwind to caller
catch: ; preds = %catch.dispatch
%pad = catchpad within %switch [ptr null, i32 64, ptr null]
@@ -45,8 +75,8 @@ catch: ; preds = %catch.dispatch
suspend:
%sp = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp, label %coro.ret [
- i8 0, label %resume
- i8 1, label %coro.ret
+ i8 0, label %resume
+ i8 1, label %coro.ret
]
resume: ; preds = %await2.suspend
@@ -55,7 +85,7 @@ resume: ; preds = %await2.suspend
coro.ret:
call void @llvm.coro.end(ptr %hdl, i1 0, token none)
- ret void
+ ret void
cleanuppad:
%cpad = cleanuppad within none []
diff --git a/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll b/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
index f2aedefcfd381..21b9c63f814dd 100644
--- a/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
@@ -1,64 +1,10 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s
; Checks whether the dbg.declare for `__coro_frame` are created.
-; CHECK-LABEL: define void @f(
-; CHECK: coro.init:
-; CHECK: %[[begin:.*]] = call noalias nonnull ptr @llvm.coro.begin(
-; CHECK: #dbg_declare(ptr %[[begin]], ![[CORO_FRAME:[0-9]+]], !DIExpression(),
;
-; CHECK: define internal fastcc void @f.resume(
-; CHECK: entry.resume:
-; CHECK: %[[FramePtr_RESUME:.*]] = alloca ptr
-; CHECK: #dbg_declare(ptr %[[FramePtr_RESUME]], ![[CORO_FRAME_IN_RESUME:[0-9]+]], !DIExpression(DW_OP_deref)
;
-; CHECK-DAG: ![[FILE:[0-9]+]] = !DIFile(filename: "coro-debug.cpp"
-; CHECK-DAG: ![[RAMP:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov",
-; CHECK-DAG: ![[CORO_FRAME]] = !DILocalVariable(name: "__coro_frame", scope: ![[RAMP]], file: ![[FILE]], line: [[CORO_FRAME_LINE:[0-9]+]], type: ![[FRAME_TYPE:[0-9]+]], flags: DIFlagArtificial)
-; CHECK-DAG: ![[FRAME_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "f.coro_frame_ty", {{.*}}elements: ![[ELEMENTS:[0-9]+]]
-; CHECK-DAG: ![[ELEMENTS]] = !{![[RESUME_FN:[0-9]+]], ![[DESTROY_FN:[0-9]+]], ![[PROMISE:[0-9]+]], ![[VECTOR_TYPE:[0-9]+]], ![[INT64_0:[0-9]+]], ![[DOUBLE_1:[0-9]+]], ![[INT64_PTR:[0-9]+]], ![[INT32_2:[0-9]+]], ![[INT32_3:[0-9]+]], ![[UNALIGNED_UNKNOWN:[0-9]+]], ![[STRUCT:[0-9]+]], ![[CORO_INDEX:[0-9]+]], ![[SMALL_UNKNOWN:[0-9]+]]
-; CHECK-DAG: ![[RESUME_FN]] = !DIDerivedType(tag: DW_TAG_member, name: "__resume_fn"{{.*}}, baseType: ![[RESUME_FN_TYPE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
-; CHECK-DAG: ![[RESUME_FN_TYPE]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
-; CHECK-DAG: ![[DESTROY_FN]] = !DIDerivedType(tag: DW_TAG_member, name: "__destroy_fn"{{.*}}, baseType: ![[RESUME_FN_TYPE]]{{.*}}, flags: DIFlagArtificial
-; CHECK-DAG: ![[PROMISE]] = !DIDerivedType(tag: DW_TAG_member, name: "__promise",{{.*}}baseType: ![[PROMISE_BASE:[0-9]+]]
-; CHECK-DAG: ![[PROMISE_BASE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "promise_type"
-; CHECK-DAG: ![[VECTOR_TYPE]] = !DIDerivedType(tag: DW_TAG_member, name: "_0",{{.*}}baseType: ![[VECTOR_TYPE_BASE:[0-9]+]], size: 128
-; CHECK-DAG: ![[VECTOR_TYPE_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE:[0-9]+]], size: 128, align: 16, elements: ![[VECTOR_TYPE_BASE_ELEMENTS:[0-9]+]])
-; CHECK-DAG: ![[UNKNOWN_TYPE_BASE]] = !DIBasicType(name: "UnknownType", size: 8, encoding: DW_ATE_unsigned_char, flags: DIFlagArtificial)
-; CHECK-DAG: ![[VECTOR_TYPE_BASE_ELEMENTS]] = !{![[VECTOR_TYPE_BASE_SUBRANGE:[0-9]+]]}
-; CHECK-DAG: ![[VECTOR_TYPE_BASE_SUBRANGE]] = !DISubrange(count: 16, lowerBound: 0)
-; CHECK-DAG: ![[INT64_0]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I64_BASE:[0-9]+]],{{.*}}, flags: DIFlagArtificial
-; CHECK-DAG: ![[I64_BASE]] = !DIBasicType(name: "__int_64", size: 64, encoding: DW_ATE_signed, flags: DIFlagArtificial)
-; CHECK-DAG: ![[DOUBLE_1]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[DOUBLE_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
-; CHECK-DAG: ![[DOUBLE_BASE]] = !DIBasicType(name: "__double_", size: 64, encoding: DW_ATE_float, flags: DIFlagArtificial)
-; CHECK-DAG: ![[INT32_2]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I32_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
-; CHECK-DAG: ![[I32_BASE]] = !DIBasicType(name: "__int_32", size: 32, encoding: DW_ATE_signed, flags: DIFlagArtificial)
-; CHECK-DAG: ![[INT32_3]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_5", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I32_BASE]]
-; CHECK-DAG: ![[UNALIGNED_UNKNOWN]] = !DIDerivedType(tag: DW_TAG_member, name: "_6",{{.*}}baseType: ![[UNALIGNED_UNKNOWN_BASE:[0-9]+]], size: 9
-; CHECK-DAG: ![[UNALIGNED_UNKNOWN_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE]], size: 16,{{.*}} elements: ![[UNALIGNED_UNKNOWN_ELEMENTS:[0-9]+]])
-; CHECK-DAG: ![[UNALIGNED_UNKNOWN_ELEMENTS]] = !{![[UNALIGNED_UNKNOWN_SUBRANGE:[0-9]+]]}
-; CHECK-DAG: ![[UNALIGNED_UNKNOWN_SUBRANGE]] = !DISubrange(count: 2, lowerBound: 0)
-; CHECK-DAG: ![[STRUCT]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_7", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[STRUCT_BASE:[0-9]+]]
-; CHECK-DAG: ![[STRUCT_BASE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure"{{.*}}, align: 64, flags: DIFlagArtificial, elements: ![[STRUCT_ELEMENTS:[0-9]+]]
-; CHECK-DAG: ![[STRUCT_ELEMENTS]] = !{![[MEM_TYPE:[0-9]+]]}
-; CHECK-DAG: ![[MEM_TYPE]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[MEM_TYPE_BASE:[0-9]+]], size: 4000
-; CHECK-DAG: ![[MEM_TYPE_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE]], size: 4000,
-; CHECK-DAG: ![[CORO_INDEX]] = !DIDerivedType(tag: DW_TAG_member, name: "__coro_index"
-; CHECK-DAG: ![[SMALL_UNKNOWN]] = !DIDerivedType(tag: DW_TAG_member, name: "UnknownType_8",{{.*}} baseType: ![[UNKNOWN_TYPE_BASE]], size: 5
-; CHECK-DAG: ![[PROMISE_VAR:[0-9]+]] = !DILocalVariable(name: "__promise", scope: ![[RAMP_SCOPE:[0-9]+]], file: ![[FILE]]
-; CHECK-DAG: ![[RAMP_SCOPE]] = distinct !DILexicalBlock(scope: ![[RAMP]], file: ![[FILE]], line: 23
-; CHECK-DAG: ![[BAR_FUNC:[0-9]+]] = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv",
-; CHECK-DAG: ![[BAR_SCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[BAR_FUNC]], file: !1
-; CHECK-DAG: ![[FRAME_TYPE_IN_BAR:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar.coro_frame_ty", file: ![[FILE]], line: [[BAR_LINE:[0-9]+]]{{.*}}elements: ![[ELEMENTS_IN_BAR:[0-9]+]]
-; CHECK-DAG: ![[ELEMENTS_IN_BAR]] = !{![[RESUME_FN_IN_BAR:[0-9]+]], ![[DESTROY_FN_IN_BAR:[0-9]+]], ![[PROMISE_IN_BAR:[0-9]+]], ![[VECTOR_TYPE_IN_BAR:[0-9]+]], ![[INT64_IN_BAR:[0-9]+]], ![[DOUBLE_IN_BAR:[0-9]+]], ![[INT64_PTR_IN_BAR:[0-9]+]], ![[INT32_IN_BAR:[0-9]+]], ![[STRUCT_IN_BAR:[0-9]+]], ![[CORO_INDEX_IN_BAR:[0-9]+]]
-; CHECK-DAG: ![[PROMISE_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__promise",{{.*}}baseType: ![[PROMISE_BASE]]
-; CHECK-DAG: ![[VECTOR_TYPE_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "_0", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[VECTOR_TYPE_BASE]]
-; CHECK-DAG: ![[INT64_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[I64_BASE]]
-; CHECK-DAG: ![[DOUBLE_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[DOUBLE_BASE]]
-; CHECK-DAG: ![[INT32_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[I32_BASE]]
-; CHECK-DAG: ![[STRUCT_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_5", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[STRUCT_BASE_IN_BAR:[0-9]+]]
-; CHECK-DAG: ![[STRUCT_BASE_IN_BAR]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]],{{.*}}, align: 64
-; CHECK-DAG: ![[CORO_FRAME_IN_RESUME]] = !DILocalVariable(name: "__coro_frame",{{.*}}type: ![[FRAME_TYPE]]
%promise_type = type { i32, i32, double }
@@ -77,268 +23,663 @@ declare void @pdouble(ptr)
declare void @pi64p(ptr)
define void @f(i32 %a, i32 %b, i64 %c, double %d, ptr %e) presplitcoroutine !dbg !8 {
+; CHECK-LABEL: define void @f(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i64 [[C:%.*]], double [[D:%.*]], ptr [[E:%.*]]) !dbg [[DBG6:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[__PROMISE:%.*]] = alloca [[PROMISE_TYPE:%.*]], align 8
+; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[B_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
+; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
+; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
+; CHECK-NEXT: store i32 [[A]], ptr [[A_ALLOC]], align 4
+; CHECK-NEXT: store i32 [[B]], ptr [[B_ALLOC]], align 4
+; CHECK-NEXT: store i64 [[C]], ptr [[C_ALLOC]], align 4
+; CHECK-NEXT: store double [[D]], ptr [[D_ALLOC]], align 8
+; CHECK-NEXT: store ptr [[E]], ptr [[E_ALLOC]], align 8
+; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
+; CHECK-NEXT: call void @produce(ptr [[STRUCT_DATA]])
+; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
+; CHECK-NEXT: call void @produce_vector(ptr [[UNRESOLVED_DATA]])
+; CHECK-NEXT: [[UNRESOLVED_DATA2:%.*]] = alloca <5 x i1>, align 1
+; CHECK-NEXT: call void @produce_vectori5(ptr [[UNRESOLVED_DATA2]])
+; CHECK-NEXT: [[UNRESOLVED_DATA3:%.*]] = alloca <9 x i1>, align 2
+; CHECK-NEXT: call void @produce_vectori9(ptr [[UNRESOLVED_DATA3]])
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr @f, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
+; CHECK-NEXT: br i1 [[ALLOC]], label %[[CORO_ALLOC:.*]], label %[[CORO_INIT_FROM_ENTRY:.*]]
+; CHECK: [[CORO_INIT_FROM_ENTRY]]:
+; CHECK-NEXT: [[DOTCORO_INIT:%.*]] = phi ptr [ null, %[[ENTRY]] ]
+; CHECK-NEXT: br label %[[CORO_INIT:.*]]
+; CHECK: [[CORO_ALLOC]]:
+; CHECK-NEXT: [[MEMORY:%.*]] = call ptr @new(i64 592)
+; CHECK-NEXT: br label %[[CORO_INIT_FROM_CORO_ALLOC:.*]]
+; CHECK: [[CORO_INIT_FROM_CORO_ALLOC]]:
+; CHECK-NEXT: [[MEMORY_CORO_INIT:%.*]] = phi ptr [ [[MEMORY]], %[[CORO_ALLOC]] ]
+; CHECK-NEXT: br label %[[CORO_INIT]]
+; CHECK: [[CORO_INIT]]:
+; CHECK-NEXT: [[PHI_ENTRY_ALLOC:%.*]] = phi ptr [ [[DOTCORO_INIT]], %[[CORO_INIT_FROM_ENTRY]] ], [ [[MEMORY_CORO_INIT]], %[[CORO_INIT_FROM_CORO_ALLOC]] ]
+; CHECK-NEXT: [[BEGIN:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI_ENTRY_ALLOC]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META52:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16), [[META54:![0-9]+]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META9:![0-9]+]], !DIExpression(), [[META55:![0-9]+]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[ALLOC]], ptr @f.destroy, ptr @f.cleanup
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 1
+; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ALLOC]], align 4
+; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4
+; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[B_ALLOC]], align 4
+; CHECK-NEXT: store i32 [[TMP4]], ptr [[TMP3]], align 4
+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[C_ALLOC]], align 4
+; CHECK-NEXT: store i64 [[TMP6]], ptr [[TMP5]], align 4
+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[TMP8:%.*]] = load double, ptr [[D_ALLOC]], align 8
+; CHECK-NEXT: store double [[TMP8]], ptr [[TMP7]], align 8
+; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E_ALLOC]], align 8
+; CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP9]], align 8
+; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
+; CHECK-NEXT: [[TMP12:%.*]] = load [[STRUCT_BIG_STRUCTURE]], ptr [[STRUCT_DATA]], align 1
+; CHECK-NEXT: store [[STRUCT_BIG_STRUCTURE]] [[TMP12]], ptr [[TMP11]], align 1
+; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[TMP14:%.*]] = load <4 x i32>, ptr [[UNRESOLVED_DATA]], align 16
+; CHECK-NEXT: store <4 x i32> [[TMP14]], ptr [[TMP13]], align 16
+; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
+; CHECK-NEXT: [[TMP16:%.*]] = load <5 x i1>, ptr [[UNRESOLVED_DATA2]], align 1
+; CHECK-NEXT: store <5 x i1> [[TMP16]], ptr [[TMP15]], align 1
+; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: [[TMP18:%.*]] = load <9 x i1>, ptr [[UNRESOLVED_DATA3]], align 2
+; CHECK-NEXT: store <9 x i1> [[TMP18]], ptr [[TMP17]], align 2
+; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
+; CHECK: [[ALLOCASPILLBB]]:
+; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[B_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
+; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[UNRESOLVED_DATA2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
+; CHECK-NEXT: [[UNRESOLVED_DATA3_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 2
+; CHECK-NEXT: br label %[[POSTSPILL:.*]]
+; CHECK: [[POSTSPILL]]:
+; CHECK-NEXT: [[READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY]], label %[[INIT_READY:.*]], label %[[COROSAVE:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
+; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR13]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE:.*]]
+; CHECK: [[AFTERCOROSAVE]]:
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
+; CHECK: [[COROSUSPEND]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET:.*]] [
+; CHECK-NEXT: i8 0, label %[[INIT_READY]]
+; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[INIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP:.*]]
+; CHECK: [[INIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
+; CHECK: [[AFTERCOROSAVE2]]:
+; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
+; CHECK: [[COROSUSPEND3]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
+; CHECK: [[AFTERCOROSUSPEND4]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
+; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AWAIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
+; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
+; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
+; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
+; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vectori5(ptr [[UNRESOLVED_DATA2_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vectori9(ptr [[UNRESOLVED_DATA3_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[B_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @return_void()
+; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
+; CHECK: [[CORO_FINAL]]:
+; CHECK-NEXT: call void @final_suspend()
+; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
+; CHECK: [[COROSAVE5]]:
+; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
+; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
+; CHECK: [[AFTERCOROSAVE6]]:
+; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
+; CHECK: [[COROSUSPEND7]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
+; CHECK: [[RESUME_2_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
+; CHECK: [[AFTERCOROSUSPEND8]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
+; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[FINAL_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[FINAL_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
+; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
+; CHECK-NEXT: [[FREE_MEMORY:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[BEGIN]])
+; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[FREE_MEMORY]], null
+; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
+; CHECK: [[CORO_FREE]]:
+; CHECK-NEXT: call void @delete(ptr [[FREE_MEMORY]])
+; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
+; CHECK: [[AFTER_CORO_FREE]]:
+; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
+; CHECK-NEXT: i32 2, label %[[CORO_RET]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: br label %[[CORO_RET]]
+; CHECK: [[CORO_RET]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+;
entry:
- %__promise = alloca %promise_type, align 8
- %a.alloc = alloca i32, align 4
- %b.alloc = alloca i32, align 4
- %c.alloc = alloca i64, align 4
- %d.alloc = alloca double, align 4
- %e.alloc = alloca ptr, align 4
- store i32 %a, ptr %a.alloc
- store i32 %b, ptr %b.alloc
- store i64 %c, ptr %c.alloc
- store double %d, ptr %d.alloc
- store ptr %e, ptr %e.alloc
- %struct.data = alloca %struct.big_structure, align 1
- call void @produce(ptr %struct.data)
- ; We treat vector type as unresolved type now for test coverage.
- %unresolved_data = alloca <4 x i32>
- call void @produce_vector(ptr %unresolved_data)
- %unresolved_data2 = alloca <5 x i1>
- call void @produce_vectori5(ptr %unresolved_data2)
- %unresolved_data3 = alloca <9 x i1>
- call void @produce_vectori9(ptr %unresolved_data3)
- %id = call token @llvm.coro.id(i32 16, ptr %__promise, ptr null, ptr null)
- %alloc = call i1 @llvm.coro.alloc(token %id)
- br i1 %alloc, label %coro.alloc, label %coro.init
+ %__promise = alloca %promise_type, align 8
+ %a.alloc = alloca i32, align 4
+ %b.alloc = alloca i32, align 4
+ %c.alloc = alloca i64, align 4
+ %d.alloc = alloca double, align 4
+ %e.alloc = alloca ptr, align 4
+ store i32 %a, ptr %a.alloc
+ store i32 %b, ptr %b.alloc
+ store i64 %c, ptr %c.alloc
+ store double %d, ptr %d.alloc
+ store ptr %e, ptr %e.alloc
+ %struct.data = alloca %struct.big_structure, align 1
+ call void @produce(ptr %struct.data)
+ ; We treat vector type as unresolved type now for test coverage.
+ %unresolved_data = alloca <4 x i32>
+ call void @produce_vector(ptr %unresolved_data)
+ %unresolved_data2 = alloca <5 x i1>
+ call void @produce_vectori5(ptr %unresolved_data2)
+ %unresolved_data3 = alloca <9 x i1>
+ call void @produce_vectori9(ptr %unresolved_data3)
+ %id = call token @llvm.coro.id(i32 16, ptr %__promise, ptr null, ptr null)
+ %alloc = call i1 @llvm.coro.alloc(token %id)
+ br i1 %alloc, label %coro.alloc, label %coro.init
coro.alloc: ; preds = %entry
- %size = call i64 @llvm.coro.size.i64()
- %memory = call ptr @new(i64 %size)
- br label %coro.init
+ %size = call i64 @llvm.coro.size.i64()
+ %memory = call ptr @new(i64 %size)
+ br label %coro.init
coro.init: ; preds = %coro.alloc, %entry
- %phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ]
- %begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc)
- call void @llvm.dbg.declare(metadata ptr %__promise, metadata !6, metadata !DIExpression()), !dbg !18
- %ready = call i1 @await_ready()
- br i1 %ready, label %init.ready, label %init.suspend
+ %phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ]
+ %begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc)
+ call void @llvm.dbg.declare(metadata ptr %__promise, metadata !6, metadata !DIExpression()), !dbg !18
+ %ready = call i1 @await_ready()
+ br i1 %ready, label %init.ready, label %init.suspend
init.suspend: ; preds = %coro.init
- %save = call token @llvm.coro.save(ptr null)
- call void @await_suspend()
- %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
- switch i8 %suspend, label %coro.ret [
- i8 0, label %init.ready
- i8 1, label %init.cleanup
- ]
+ %save = call token @llvm.coro.save(ptr null)
+ call void @await_suspend()
+ %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
+ switch i8 %suspend, label %coro.ret [
+ i8 0, label %init.ready
+ i8 1, label %init.cleanup
+ ]
init.cleanup: ; preds = %init.suspend
- br label %cleanup
+ br label %cleanup
init.ready: ; preds = %init.suspend, %coro.init
- call void @await_resume()
- %ready.again = call zeroext i1 @await_ready()
- br i1 %ready.again, label %await.ready, label %await.suspend
+ call void @await_resume()
+ %ready.again = call zeroext i1 @await_ready()
+ br i1 %ready.again, label %await.ready, label %await.suspend
await.suspend: ; preds = %init.ready
- %save.again = call token @llvm.coro.save(ptr null)
- %from.address = call ptr @from_address(ptr %begin)
- call void @await_suspend()
- %suspend.again = call i8 @llvm.coro.suspend(token %save.again, i1 false)
- switch i8 %suspend.again, label %coro.ret [
- i8 0, label %await.ready
- i8 1, label %await.cleanup
- ]
+ %save.again = call token @llvm.coro.save(ptr null)
+ %from.address = call ptr @from_address(ptr %begin)
+ call void @await_suspend()
+ %suspend.again = call i8 @llvm.coro.suspend(token %save.again, i1 false)
+ switch i8 %suspend.again, label %coro.ret [
+ i8 0, label %await.ready
+ i8 1, label %await.cleanup
+ ]
await.cleanup: ; preds = %await.suspend
- br label %cleanup
+ br label %cleanup
await.ready: ; preds = %await.suspend, %init.ready
- call void @await_resume()
- store i32 1, ptr %__promise, align 8
- %j.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 1
- store i32 2, ptr %j.i, align 4
- %k.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 2
- store double 3.000000e+00, ptr %k.i, align 8
- call void @consume(ptr %struct.data)
- call void @consume_vector(ptr %unresolved_data)
- call void @consume_vectori5(ptr %unresolved_data2)
- call void @consume_vectori9(ptr %unresolved_data3)
- call void @pi32(ptr %a.alloc)
- call void @pi32(ptr %b.alloc)
- call void @pi64(ptr %c.alloc)
- call void @pdouble(ptr %d.alloc)
- call void @pi64p(ptr %e.alloc)
- call void @return_void()
- br label %coro.final
+ call void @await_resume()
+ store i32 1, ptr %__promise, align 8
+ %j.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 1
+ store i32 2, ptr %j.i, align 4
+ %k.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 2
+ store double 3.000000e+00, ptr %k.i, align 8
+ call void @consume(ptr %struct.data)
+ call void @consume_vector(ptr %unresolved_data)
+ call void @consume_vectori5(ptr %unresolved_data2)
+ call void @consume_vectori9(ptr %unresolved_data3)
+ call void @pi32(ptr %a.alloc)
+ call void @pi32(ptr %b.alloc)
+ call void @pi64(ptr %c.alloc)
+ call void @pdouble(ptr %d.alloc)
+ call void @pi64p(ptr %e.alloc)
+ call void @return_void()
+ br label %coro.final
coro.final: ; preds = %await.ready
- call void @final_suspend()
- %coro.final.await_ready = call i1 @await_ready()
- br i1 %coro.final.await_ready, label %final.ready, label %final.suspend
+ call void @final_suspend()
+ %coro.final.await_ready = call i1 @await_ready()
+ br i1 %coro.final.await_ready, label %final.ready, label %final.suspend
final.suspend: ; preds = %coro.final
- %final.suspend.coro.save = call token @llvm.coro.save(ptr null)
- %final.suspend.from_address = call ptr @from_address(ptr %begin)
- call void @await_suspend()
- %final.suspend.coro.suspend = call i8 @llvm.coro.suspend(token %final.suspend.coro.save, i1 true)
- switch i8 %final.suspend.coro.suspend, label %coro.ret [
- i8 0, label %final.ready
- i8 1, label %final.cleanup
- ]
+ %final.suspend.coro.save = call token @llvm.coro.save(ptr null)
+ %final.suspend.from_address = call ptr @from_address(ptr %begin)
+ call void @await_suspend()
+ %final.suspend.coro.suspend = call i8 @llvm.coro.suspend(token %final.suspend.coro.save, i1 true)
+ switch i8 %final.suspend.coro.suspend, label %coro.ret [
+ i8 0, label %final.ready
+ i8 1, label %final.cleanup
+ ]
final.cleanup: ; preds = %final.suspend
- br label %cleanup
+ br label %cleanup
final.ready: ; preds = %final.suspend, %coro.final
- call void @await_resume()
- br label %cleanup
+ call void @await_resume()
+ br label %cleanup
cleanup: ; preds = %final.ready, %final.cleanup, %await.cleanup, %init.cleanup
- %cleanup.dest.slot.0 = phi i32 [ 0, %final.ready ], [ 2, %final.cleanup ], [ 2, %await.cleanup ], [ 2, %init.cleanup ]
- %free.memory = call ptr @llvm.coro.free(token %id, ptr %begin)
- %free = icmp ne ptr %free.memory, null
- br i1 %free, label %coro.free, label %after.coro.free
+ %cleanup.dest.slot.0 = phi i32 [ 0, %final.ready ], [ 2, %final.cleanup ], [ 2, %await.cleanup ], [ 2, %init.cleanup ]
+ %free.memory = call ptr @llvm.coro.free(token %id, ptr %begin)
+ %free = icmp ne ptr %free.memory, null
+ br i1 %free, label %coro.free, label %after.coro.free
coro.free: ; preds = %cleanup
- call void @delete(ptr %free.memory)
- br label %after.coro.free
+ call void @delete(ptr %free.memory)
+ br label %after.coro.free
after.coro.free: ; preds = %coro.free, %cleanup
- switch i32 %cleanup.dest.slot.0, label %unreachable [
- i32 0, label %cleanup.cont
- i32 2, label %coro.ret
- ]
+ switch i32 %cleanup.dest.slot.0, label %unreachable [
+ i32 0, label %cleanup.cont
+ i32 2, label %coro.ret
+ ]
cleanup.cont: ; preds = %after.coro.free
- br label %coro.ret
+ br label %coro.ret
coro.ret: ; preds = %cleanup.cont, %after.coro.free, %final.suspend, %await.suspend, %init.suspend
- call void @llvm.coro.end(ptr null, i1 false, token none)
- ret void
+ call void @llvm.coro.end(ptr null, i1 false, token none)
+ ret void
unreachable: ; preds = %after.coro.free
- unreachable
+ unreachable
}
; bar is used to check that we wouldn't create duplicate DIType
define void @bar(i32 %a, i64 %c, double %d, ptr %e) presplitcoroutine !dbg !19 {
+; CHECK-LABEL: define void @bar(
+; CHECK-SAME: i32 [[A:%.*]], i64 [[C:%.*]], double [[D:%.*]], ptr [[E:%.*]]) !dbg [[DBG56:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[__PROMISE:%.*]] = alloca [[PROMISE_TYPE:%.*]], align 8
+; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
+; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
+; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
+; CHECK-NEXT: store i32 [[A]], ptr [[A_ALLOC]], align 4
+; CHECK-NEXT: store i64 [[C]], ptr [[C_ALLOC]], align 4
+; CHECK-NEXT: store double [[D]], ptr [[D_ALLOC]], align 8
+; CHECK-NEXT: store ptr [[E]], ptr [[E_ALLOC]], align 8
+; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
+; CHECK-NEXT: call void @produce(ptr [[STRUCT_DATA]])
+; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
+; CHECK-NEXT: call void @produce_vector(ptr [[UNRESOLVED_DATA]])
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr @bar, ptr @bar.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
+; CHECK-NEXT: br i1 [[ALLOC]], label %[[CORO_ALLOC:.*]], label %[[CORO_INIT_FROM_ENTRY:.*]]
+; CHECK: [[CORO_INIT_FROM_ENTRY]]:
+; CHECK-NEXT: [[DOTCORO_INIT:%.*]] = phi ptr [ null, %[[ENTRY]] ]
+; CHECK-NEXT: br label %[[CORO_INIT:.*]]
+; CHECK: [[CORO_ALLOC]]:
+; CHECK-NEXT: [[MEMORY:%.*]] = call ptr @new(i64 592)
+; CHECK-NEXT: br label %[[CORO_INIT_FROM_CORO_ALLOC:.*]]
+; CHECK: [[CORO_INIT_FROM_CORO_ALLOC]]:
+; CHECK-NEXT: [[MEMORY_CORO_INIT:%.*]] = phi ptr [ [[MEMORY]], %[[CORO_ALLOC]] ]
+; CHECK-NEXT: br label %[[CORO_INIT]]
+; CHECK: [[CORO_INIT]]:
+; CHECK-NEXT: [[PHI_ENTRY_ALLOC:%.*]] = phi ptr [ [[DOTCORO_INIT]], %[[CORO_INIT_FROM_ENTRY]] ], [ [[MEMORY_CORO_INIT]], %[[CORO_INIT_FROM_CORO_ALLOC]] ]
+; CHECK-NEXT: [[BEGIN:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI_ENTRY_ALLOC]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META74:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16), [[META76:![0-9]+]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META58:![0-9]+]], !DIExpression(), [[META77:![0-9]+]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr @bar.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[ALLOC]], ptr @bar.destroy, ptr @bar.cleanup
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 1
+; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ALLOC]], align 4
+; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4
+; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[C_ALLOC]], align 4
+; CHECK-NEXT: store i64 [[TMP4]], ptr [[TMP3]], align 4
+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[TMP6:%.*]] = load double, ptr [[D_ALLOC]], align 8
+; CHECK-NEXT: store double [[TMP6]], ptr [[TMP5]], align 8
+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[E_ALLOC]], align 8
+; CHECK-NEXT: store ptr [[TMP8]], ptr [[TMP7]], align 8
+; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[TMP10:%.*]] = load [[STRUCT_BIG_STRUCTURE]], ptr [[STRUCT_DATA]], align 1
+; CHECK-NEXT: store [[STRUCT_BIG_STRUCTURE]] [[TMP10]], ptr [[TMP9]], align 1
+; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[TMP12:%.*]] = load <4 x i32>, ptr [[UNRESOLVED_DATA]], align 16
+; CHECK-NEXT: store <4 x i32> [[TMP12]], ptr [[TMP11]], align 16
+; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
+; CHECK: [[ALLOCASPILLBB]]:
+; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 2
+; CHECK-NEXT: br label %[[POSTSPILL:.*]]
+; CHECK: [[POSTSPILL]]:
+; CHECK-NEXT: [[READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY]], label %[[INIT_READY:.*]], label %[[COROSAVE:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR13]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE:.*]]
+; CHECK: [[AFTERCOROSAVE]]:
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
+; CHECK: [[COROSUSPEND]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET:.*]] [
+; CHECK-NEXT: i8 0, label %[[INIT_READY]]
+; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[INIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP:.*]]
+; CHECK: [[INIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
+; CHECK: [[AFTERCOROSAVE2]]:
+; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
+; CHECK: [[COROSUSPEND3]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
+; CHECK: [[AFTERCOROSUSPEND4]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
+; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AWAIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
+; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
+; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
+; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
+; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @return_void()
+; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
+; CHECK: [[CORO_FINAL]]:
+; CHECK-NEXT: call void @final_suspend()
+; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
+; CHECK: [[COROSAVE5]]:
+; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
+; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
+; CHECK: [[AFTERCOROSAVE6]]:
+; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
+; CHECK: [[COROSUSPEND7]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
+; CHECK: [[RESUME_2_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
+; CHECK: [[AFTERCOROSUSPEND8]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
+; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[FINAL_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[FINAL_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
+; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
+; CHECK-NEXT: [[FREE_MEMORY:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[BEGIN]])
+; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[FREE_MEMORY]], null
+; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
+; CHECK: [[CORO_FREE]]:
+; CHECK-NEXT: call void @delete(ptr [[FREE_MEMORY]])
+; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
+; CHECK: [[AFTER_CORO_FREE]]:
+; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
+; CHECK-NEXT: i32 2, label %[[CORO_RET]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: br label %[[CORO_RET]]
+; CHECK: [[CORO_RET]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+;
entry:
- %__promise = alloca %promise_type, align 8
- %a.alloc = alloca i32, align 4
- %c.alloc = alloca i64, align 4
- %d.alloc = alloca double, align 4
- %e.alloc = alloca ptr, align 4
- store i32 %a, ptr %a.alloc
- store i64 %c, ptr %c.alloc
- store double %d, ptr %d.alloc
- store ptr %e, ptr %e.alloc
- %struct.data = alloca %struct.big_structure, align 1
- call void @produce(ptr %struct.data)
- ; We treat vector type as unresolved type now for test coverage.
- %unresolved_data = alloca <4 x i32>
- call void @produce_vector(ptr %unresolved_data)
- %id = call token @llvm.coro.id(i32 16, ptr %__promise, ptr null, ptr null)
- %alloc = call i1 @llvm.coro.alloc(token %id)
- br i1 %alloc, label %coro.alloc, label %coro.init
+ %__promise = alloca %promise_type, align 8
+ %a.alloc = alloca i32, align 4
+ %c.alloc = alloca i64, align 4
+ %d.alloc = alloca double, align 4
+ %e.alloc = alloca ptr, align 4
+ store i32 %a, ptr %a.alloc
+ store i64 %c, ptr %c.alloc
+ store double %d, ptr %d.alloc
+ store ptr %e, ptr %e.alloc
+ %struct.data = alloca %struct.big_structure, align 1
+ call void @produce(ptr %struct.data)
+ ; We treat vector type as unresolved type now for test coverage.
+ %unresolved_data = alloca <4 x i32>
+ call void @produce_vector(ptr %unresolved_data)
+ %id = call token @llvm.coro.id(i32 16, ptr %__promise, ptr null, ptr null)
+ %alloc = call i1 @llvm.coro.alloc(token %id)
+ br i1 %alloc, label %coro.alloc, label %coro.init
coro.alloc: ; preds = %entry
- %size = call i64 @llvm.coro.size.i64()
- %memory = call ptr @new(i64 %size)
- br label %coro.init
+ %size = call i64 @llvm.coro.size.i64()
+ %memory = call ptr @new(i64 %size)
+ br label %coro.init
coro.init: ; preds = %coro.alloc, %entry
- %phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ]
- %begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc)
- call void @llvm.dbg.declare(metadata ptr %__promise, metadata !21, metadata !DIExpression()), !dbg !22
- %ready = call i1 @await_ready()
- br i1 %ready, label %init.ready, label %init.suspend
+ %phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ]
+ %begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc)
+ call void @llvm.dbg.declare(metadata ptr %__promise, metadata !21, metadata !DIExpression()), !dbg !22
+ %ready = call i1 @await_ready()
+ br i1 %ready, label %init.ready, label %init.suspend
init.suspend: ; preds = %coro.init
- %save = call token @llvm.coro.save(ptr null)
- call void @await_suspend()
- %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
- switch i8 %suspend, label %coro.ret [
- i8 0, label %init.ready
- i8 1, label %init.cleanup
- ]
+ %save = call token @llvm.coro.save(ptr null)
+ call void @await_suspend()
+ %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
+ switch i8 %suspend, label %coro.ret [
+ i8 0, label %init.ready
+ i8 1, label %init.cleanup
+ ]
init.cleanup: ; preds = %init.suspend
- br label %cleanup
+ br label %cleanup
init.ready: ; preds = %init.suspend, %coro.init
- call void @await_resume()
- %ready.again = call zeroext i1 @await_ready()
- br i1 %ready.again, label %await.ready, label %await.suspend
+ call void @await_resume()
+ %ready.again = call zeroext i1 @await_ready()
+ br i1 %ready.again, label %await.ready, label %await.suspend
await.suspend: ; preds = %init.ready
- %save.again = call token @llvm.coro.save(ptr null)
- %from.address = call ptr @from_address(ptr %begin)
- call void @await_suspend()
- %suspend.again = call i8 @llvm.coro.suspend(token %save.again, i1 false)
- switch i8 %suspend.again, label %coro.ret [
- i8 0, label %await.ready
- i8 1, label %await.cleanup
- ]
+ %save.again = call token @llvm.coro.save(ptr null)
+ %from.address = call ptr @from_address(ptr %begin)
+ call void @await_suspend()
+ %suspend.again = call i8 @llvm.coro.suspend(token %save.again, i1 false)
+ switch i8 %suspend.again, label %coro.ret [
+ i8 0, label %await.ready
+ i8 1, label %await.cleanup
+ ]
await.cleanup: ; preds = %await.suspend
- br label %cleanup
+ br label %cleanup
await.ready: ; preds = %await.suspend, %init.ready
- call void @await_resume()
- store i32 1, ptr %__promise, align 8
- %j.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 1
- store i32 2, ptr %j.i, align 4
- %k.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 2
- store double 3.000000e+00, ptr %k.i, align 8
- call void @consume(ptr %struct.data)
- call void @consume_vector(ptr %unresolved_data)
- call void @pi32(ptr %a.alloc)
- call void @pi64(ptr %c.alloc)
- call void @pdouble(ptr %d.alloc)
- call void @pi64p(ptr %e.alloc)
- call void @return_void()
- br label %coro.final
+ call void @await_resume()
+ store i32 1, ptr %__promise, align 8
+ %j.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 1
+ store i32 2, ptr %j.i, align 4
+ %k.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 2
+ store double 3.000000e+00, ptr %k.i, align 8
+ call void @consume(ptr %struct.data)
+ call void @consume_vector(ptr %unresolved_data)
+ call void @pi32(ptr %a.alloc)
+ call void @pi64(ptr %c.alloc)
+ call void @pdouble(ptr %d.alloc)
+ call void @pi64p(ptr %e.alloc)
+ call void @return_void()
+ br label %coro.final
coro.final: ; preds = %await.ready
- call void @final_suspend()
- %coro.final.await_ready = call i1 @await_ready()
- br i1 %coro.final.await_ready, label %final.ready, label %final.suspend
+ call void @final_suspend()
+ %coro.final.await_ready = call i1 @await_ready()
+ br i1 %coro.final.await_ready, label %final.ready, label %final.suspend
final.suspend: ; preds = %coro.final
- %final.suspend.coro.save = call token @llvm.coro.save(ptr null)
- %final.suspend.from_address = call ptr @from_address(ptr %begin)
- call void @await_suspend()
- %final.suspend.coro.suspend = call i8 @llvm.coro.suspend(token %final.suspend.coro.save, i1 true)
- switch i8 %final.suspend.coro.suspend, label %coro.ret [
- i8 0, label %final.ready
- i8 1, label %final.cleanup
- ]
+ %final.suspend.coro.save = call token @llvm.coro.save(ptr null)
+ %final.suspend.from_address = call ptr @from_address(ptr %begin)
+ call void @await_suspend()
+ %final.suspend.coro.suspend = call i8 @llvm.coro.suspend(token %final.suspend.coro.save, i1 true)
+ switch i8 %final.suspend.coro.suspend, label %coro.ret [
+ i8 0, label %final.ready
+ i8 1, label %final.cleanup
+ ]
final.cleanup: ; preds = %final.suspend
- br label %cleanup
+ br label %cleanup
final.ready: ; preds = %final.suspend, %coro.final
- call void @await_resume()
- br label %cleanup
+ call void @await_resume()
+ br label %cleanup
cleanup: ; preds = %final.ready, %final.cleanup, %await.cleanup, %init.cleanup
- %cleanup.dest.slot.0 = phi i32 [ 0, %final.ready ], [ 2, %final.cleanup ], [ 2, %await.cleanup ], [ 2, %init.cleanup ]
- %free.memory = call ptr @llvm.coro.free(token %id, ptr %begin)
- %free = icmp ne ptr %free.memory, null
- br i1 %free, label %coro.free, label %after.coro.free
+ %cleanup.dest.slot.0 = phi i32 [ 0, %final.ready ], [ 2, %final.cleanup ], [ 2, %await.cleanup ], [ 2, %init.cleanup ]
+ %free.memory = call ptr @llvm.coro.free(token %id, ptr %begin)
+ %free = icmp ne ptr %free.memory, null
+ br i1 %free, label %coro.free, label %after.coro.free
coro.free: ; preds = %cleanup
- call void @delete(ptr %free.memory)
- br label %after.coro.free
+ call void @delete(ptr %free.memory)
+ br label %after.coro.free
after.coro.free: ; preds = %coro.free, %cleanup
- switch i32 %cleanup.dest.slot.0, label %unreachable [
- i32 0, label %cleanup.cont
- i32 2, label %coro.ret
- ]
+ switch i32 %cleanup.dest.slot.0, label %unreachable [
+ i32 0, label %cleanup.cont
+ i32 2, label %coro.ret
+ ]
cleanup.cont: ; preds = %after.coro.free
- br label %coro.ret
+ br label %coro.ret
coro.ret: ; preds = %cleanup.cont, %after.coro.free, %final.suspend, %await.suspend, %init.suspend
- call void @llvm.coro.end(ptr null, i1 false, token none)
- ret void
+ call void @llvm.coro.end(ptr null, i1 false, token none)
+ ret void
unreachable: ; preds = %after.coro.free
- unreachable
+ unreachable
}
@@ -390,3 +731,80 @@ declare void @final_suspend()
!20 = distinct !DILexicalBlock(scope: !19, file: !1, line: 23, column: 12)
!21 = !DILocalVariable(name: "__promise", scope: !20, file: !1, line: 55, type: !10)
!22 = !DILocation(line: 10, scope: !20)
+;.
+; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: [[META2:![0-9]+]], retainedTypes: [[META2]], splitDebugInlining: false, nameTableKind: None)
+; CHECK: [[META1]] = !DIFile(filename: "{{.*}}coro-debug.cpp", directory: {{.*}})
+; CHECK: [[META2]] = !{}
+; CHECK: [[DBG6]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: [[DBG6]], file: [[META1]], line: 23, type: [[META7:![0-9]+]], scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META8:![0-9]+]])
+; CHECK: [[META7]] = !DISubroutineType(types: [[META2]])
+; CHECK: [[META8]] = !{[[META9]]}
+; CHECK: [[META9]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG6]], file: [[META1]], line: 23, type: [[META10:![0-9]+]], flags: DIFlagArtificial)
+; CHECK: [[META10]] = !DICompositeType(tag: DW_TAG_structure_type, name: "f.coro_frame_ty", file: [[META1]], line: 23, size: 4736, align: 128, flags: DIFlagArtificial, elements: [[META11:![0-9]+]])
+; CHECK: [[META11]] = !{[[META12:![0-9]+]], [[META14:![0-9]+]], [[META15:![0-9]+]], [[META24:![0-9]+]], [[META29:![0-9]+]], [[META31:![0-9]+]], [[META33:![0-9]+]], [[META35:![0-9]+]], [[META37:![0-9]+]], [[META38:![0-9]+]], [[META42:![0-9]+]], [[META49:![0-9]+]], [[META51:![0-9]+]]}
+; CHECK: [[META12]] = !DIDerivedType(tag: DW_TAG_member, name: "__resume_fn", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META13:![0-9]+]], size: 64, align: 64, flags: DIFlagArtificial)
+; CHECK: [[META13]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+; CHECK: [[META14]] = !DIDerivedType(tag: DW_TAG_member, name: "__destroy_fn", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META13]], size: 64, align: 64, offset: 64, flags: DIFlagArtificial)
+; CHECK: [[META15]] = !DIDerivedType(tag: DW_TAG_member, name: "__promise", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META16:![0-9]+]], size: 128, align: 64, offset: 128, flags: DIFlagArtificial)
+; CHECK: [[META16]] = !DIDerivedType(tag: DW_TAG_typedef, name: "promise_type", scope: [[DBG6]], file: [[META1]], line: 15, baseType: [[META17:![0-9]+]])
+; CHECK: [[META17]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "promise_type", scope: [[DBG6]], file: [[META1]], line: 10, size: 128, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: [[META18:![0-9]+]], identifier: "_ZTSN4coro12promise_typeE")
+; CHECK: [[META18]] = !{[[META19:![0-9]+]], [[META21:![0-9]+]], [[META22:![0-9]+]]}
+; CHECK: [[META19]] = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: [[DBG6]], file: [[META1]], line: 10, baseType: [[META20:![0-9]+]], size: 32)
+; CHECK: [[META20]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+; CHECK: [[META21]] = !DIDerivedType(tag: DW_TAG_member, name: "j", scope: [[DBG6]], file: [[META1]], line: 10, baseType: [[META20]], size: 32, offset: 32)
+; CHECK: [[META22]] = !DIDerivedType(tag: DW_TAG_member, name: "k", scope: [[DBG6]], file: [[META1]], line: 10, baseType: [[META23:![0-9]+]], size: 64, offset: 64)
+; CHECK: [[META23]] = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float)
+; CHECK: [[META24]] = !DIDerivedType(tag: DW_TAG_member, name: "_0", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META25:![0-9]+]], size: 128, align: 128, offset: 256, flags: DIFlagArtificial)
+; CHECK: [[META25]] = !DICompositeType(tag: DW_TAG_array_type, baseType: [[META26:![0-9]+]], size: 128, align: 16, elements: [[META27:![0-9]+]])
+; CHECK: [[META26]] = !DIBasicType(name: "UnknownType", size: 8, encoding: DW_ATE_unsigned_char, flags: DIFlagArtificial)
+; CHECK: [[META27]] = !{[[META28:![0-9]+]]}
+; CHECK: [[META28]] = !DISubrange(count: 16, lowerBound: 0)
+; CHECK: [[META29]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META30:![0-9]+]], size: 64, align: 32, offset: 384, flags: DIFlagArtificial)
+; CHECK: [[META30]] = !DIBasicType(name: "__int_64", size: 64, encoding: DW_ATE_signed, flags: DIFlagArtificial)
+; CHECK: [[META31]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META32:![0-9]+]], size: 64, align: 32, offset: 448, flags: DIFlagArtificial)
+; CHECK: [[META32]] = !DIBasicType(name: "__double_", size: 64, encoding: DW_ATE_float, flags: DIFlagArtificial)
+; CHECK: [[META33]] = !DIDerivedType(tag: DW_TAG_member, name: "PointerType_3", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META34:![0-9]+]], size: 64, align: 32, offset: 512, flags: DIFlagArtificial)
+; CHECK: [[META34]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "PointerType", baseType: null, size: 64, align: 64)
+; CHECK: [[META35]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META36:![0-9]+]], size: 32, align: 32, offset: 576, flags: DIFlagArtificial)
+; CHECK: [[META36]] = !DIBasicType(name: "__int_32", size: 32, encoding: DW_ATE_signed, flags: DIFlagArtificial)
+; CHECK: [[META37]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_5", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META36]], size: 32, align: 32, offset: 608, flags: DIFlagArtificial)
+; CHECK: [[META38]] = !DIDerivedType(tag: DW_TAG_member, name: "_6", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META39:![0-9]+]], size: 9, align: 16, offset: 640, flags: DIFlagArtificial)
+; CHECK: [[META39]] = !DICompositeType(tag: DW_TAG_array_type, baseType: [[META26]], size: 16, align: 2, elements: [[META40:![0-9]+]])
+; CHECK: [[META40]] = !{[[META41:![0-9]+]]}
+; CHECK: [[META41]] = !DISubrange(count: 2, lowerBound: 0)
+; CHECK: [[META42]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_7", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META43:![0-9]+]], size: 4000, align: 8, offset: 656, flags: DIFlagArtificial)
+; CHECK: [[META43]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure", scope: [[META10]], file: [[META1]], line: 23, size: 4000, align: 64, flags: DIFlagArtificial, elements: [[META44:![0-9]+]])
+; CHECK: [[META44]] = !{[[META45:![0-9]+]]}
+; CHECK: [[META45]] = !DIDerivedType(tag: DW_TAG_member, scope: [[META43]], file: [[META1]], line: 23, baseType: [[META46:![0-9]+]], size: 4000, align: 1, flags: DIFlagArtificial)
+; CHECK: [[META46]] = !DICompositeType(tag: DW_TAG_array_type, baseType: [[META26]], size: 4000, align: 1, elements: [[META47:![0-9]+]])
+; CHECK: [[META47]] = !{[[META48:![0-9]+]]}
+; CHECK: [[META48]] = !DISubrange(count: 500, lowerBound: 0)
+; CHECK: [[META49]] = !DIDerivedType(tag: DW_TAG_member, name: "__coro_index", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META50:![0-9]+]], size: 2, align: 8, offset: 4656, flags: DIFlagArtificial)
+; CHECK: [[META50]] = !DIBasicType(name: "__coro_index", size: 8, encoding: DW_ATE_unsigned_char)
+; CHECK: [[META51]] = !DIDerivedType(tag: DW_TAG_member, name: "UnknownType_8", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META26]], size: 5, align: 8, offset: 4664, flags: DIFlagArtificial)
+; CHECK: [[META52]] = !DILocalVariable(name: "__promise", scope: [[META53:![0-9]+]], file: [[META1]], line: 24, type: [[META16]])
+; CHECK: [[META53]] = distinct !DILexicalBlock(scope: [[DBG6]], file: [[META1]], line: 23, column: 12)
+; CHECK: [[META54]] = !DILocation(line: 8, scope: [[META53]])
+; CHECK: [[META55]] = !DILocation(line: 23, column: 1, scope: [[DBG6]])
+; CHECK: [[DBG56]] = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: [[DBG56]], file: [[META1]], line: 54, type: [[META7]], scopeLine: 54, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META57:![0-9]+]])
+; CHECK: [[META57]] = !{[[META58]]}
+; CHECK: [[META58]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG56]], file: [[META1]], line: 54, type: [[META59:![0-9]+]], flags: DIFlagArtificial)
+; CHECK: [[META59]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar.coro_frame_ty", file: [[META1]], line: 54, size: 4736, align: 128, flags: DIFlagArtificial, elements: [[META60:![0-9]+]])
+; CHECK: [[META60]] = !{[[META61:![0-9]+]], [[META62:![0-9]+]], [[META63:![0-9]+]], [[META64:![0-9]+]], [[META65:![0-9]+]], [[META66:![0-9]+]], [[META67:![0-9]+]], [[META68:![0-9]+]], [[META69:![0-9]+]], [[META73:![0-9]+]]}
+; CHECK: [[META61]] = !DIDerivedType(tag: DW_TAG_member, name: "__resume_fn", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META13]], size: 64, align: 64, flags: DIFlagArtificial)
+; CHECK: [[META62]] = !DIDerivedType(tag: DW_TAG_member, name: "__destroy_fn", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META13]], size: 64, align: 64, offset: 64, flags: DIFlagArtificial)
+; CHECK: [[META63]] = !DIDerivedType(tag: DW_TAG_member, name: "__promise", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META16]], size: 128, align: 64, offset: 128, flags: DIFlagArtificial)
+; CHECK: [[META64]] = !DIDerivedType(tag: DW_TAG_member, name: "_0", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META25]], size: 128, align: 128, offset: 256, flags: DIFlagArtificial)
+; CHECK: [[META65]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META30]], size: 64, align: 32, offset: 384, flags: DIFlagArtificial)
+; CHECK: [[META66]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META32]], size: 64, align: 32, offset: 448, flags: DIFlagArtificial)
+; CHECK: [[META67]] = !DIDerivedType(tag: DW_TAG_member, name: "PointerType_3", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META34]], size: 64, align: 32, offset: 512, flags: DIFlagArtificial)
+; CHECK: [[META68]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META36]], size: 32, align: 32, offset: 576, flags: DIFlagArtificial)
+; CHECK: [[META69]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_5", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META70:![0-9]+]], size: 4000, align: 8, offset: 608, flags: DIFlagArtificial)
+; CHECK: [[META70]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure", scope: [[META59]], file: [[META1]], line: 54, size: 4000, align: 64, flags: DIFlagArtificial, elements: [[META71:![0-9]+]])
+; CHECK: [[META71]] = !{[[META72:![0-9]+]]}
+; CHECK: [[META72]] = !DIDerivedType(tag: DW_TAG_member, scope: [[META70]], file: [[META1]], line: 54, baseType: [[META46]], size: 4000, align: 1, flags: DIFlagArtificial)
+; CHECK: [[META73]] = !DIDerivedType(tag: DW_TAG_member, name: "__coro_index", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META50]], size: 2, align: 8, offset: 4608, flags: DIFlagArtificial)
+; CHECK: [[META74]] = !DILocalVariable(name: "__promise", scope: [[META75:![0-9]+]], file: [[META1]], line: 55, type: [[META16]])
+; CHECK: [[META75]] = distinct !DILexicalBlock(scope: [[DBG56]], file: [[META1]], line: 23, column: 12)
+; CHECK: [[META76]] = !DILocation(line: 10, scope: [[META75]])
+; CHECK: [[META77]] = !DILocation(line: 54, column: 1, scope: [[DBG56]])
+;.
diff --git a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
index 0b9bce5f9ad77..95686acecfd1e 100644
--- a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
@@ -1,11 +1,30 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that we can handle edge splits leading into a landingpad
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
-; CHECK-LABEL: define internal fastcc void @g.resume(
define void @g(i1 %cond, i32 %x, i32 %y) presplitcoroutine personality i32 0 {
+; CHECK-LABEL: define void @g(
+; CHECK-SAME: i1 [[COND:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr @g.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @g.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[G_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @g.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[Y_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i32 [[Y]], ptr [[Y_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[COND_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: store i1 [[COND]], ptr [[COND_SPILL_ADDR]], align 1
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[G_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret void
+;
entry:
%id = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr null)
%size = tail call i64 @llvm.coro.size.i64()
@@ -13,8 +32,8 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%sp = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp, label %coro.ret [
- i8 0, label %resume
- i8 1, label %cleanup
+ i8 0, label %resume
+ i8 1, label %cleanup
]
resume:
@@ -22,30 +41,15 @@ resume:
invoke1:
invoke void @may_throw1()
- to label %unreach unwind label %pad.with.phi
+ to label %unreach unwind label %pad.with.phi
invoke2:
invoke void @may_throw2()
- to label %unreach unwind label %pad.with.phi
+ to label %unreach unwind label %pad.with.phi
; Verify that we created cleanuppads on every edge and inserted a reload of the spilled value
-; CHECK: pad.with.phi.from.invoke2:
-; CHECK: %0 = cleanuppad within none []
-; CHECK: %y.reload.addr = getelementptr inbounds %g.Frame, ptr %hdl, i32 0, i32 3
-; CHECK: %y.reload = load i32, ptr %y.reload.addr
-; CHECK: cleanupret from %0 unwind label %pad.with.phi
-
-; CHECK: pad.with.phi.from.invoke1:
-; CHECK: %1 = cleanuppad within none []
-; CHECK: %x.reload.addr = getelementptr inbounds %g.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: %x.reload = load i32, ptr %x.reload.addr
-; CHECK: cleanupret from %1 unwind label %pad.with.phi
-
-; CHECK: pad.with.phi:
-; CHECK: %val = phi i32 [ %x.reload, %pad.with.phi.from.invoke1 ], [ %y.reload, %pad.with.phi.from.invoke2 ]
-; CHECK: %tok = cleanuppad within none []
-; CHECK: call void @use_val(i32 %val)
-; CHECK: cleanupret from %tok unwind to caller
+
+
pad.with.phi:
%val = phi i32 [ %x, %invoke1 ], [ %y, %invoke2 ]
diff --git a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
index 6202df1fe00e6..7aa2cf5617d88 100644
--- a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
@@ -1,11 +1,30 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that we can handle edge splits leading into a landingpad
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
-; CHECK-LABEL: define internal fastcc void @h.resume(
define void @h(i1 %cond, i32 %x, i32 %y) presplitcoroutine personality i32 0 {
+; CHECK-LABEL: define void @h(
+; CHECK-SAME: i1 [[COND:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr @h.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @h.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[H_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @h.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[Y_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i32 [[Y]], ptr [[Y_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[COND_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: store i1 [[COND]], ptr [[COND_SPILL_ADDR]], align 1
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[H_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret void
+;
entry:
%id = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr null)
%size = tail call i64 @llvm.coro.size.i64()
@@ -13,8 +32,8 @@ entry:
%hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)
%sp = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp, label %coro.ret [
- i8 0, label %resume
- i8 1, label %cleanup
+ i8 0, label %resume
+ i8 1, label %cleanup
]
resume:
@@ -22,28 +41,15 @@ resume:
invoke1:
invoke void @may_throw1()
- to label %coro.ret unwind label %pad.with.phi
+ to label %coro.ret unwind label %pad.with.phi
invoke2:
invoke void @may_throw2()
- to label %coro.ret unwind label %pad.with.phi
+ to label %coro.ret unwind label %pad.with.phi
; Verify that we created cleanuppads on every edge and inserted a reload of the spilled value
-; CHECK: pad.with.phi.from.invoke2:
-; CHECK: %0 = cleanuppad within none []
-; CHECK: %y.reload.addr = getelementptr inbounds %h.Frame, ptr %hdl, i32 0, i32 3
-; CHECK: %y.reload = load i32, ptr %y.reload.addr
-; CHECK: cleanupret from %0 unwind label %pad.with.phi
-
-; CHECK: pad.with.phi.from.invoke1:
-; CHECK: %1 = cleanuppad within none []
-; CHECK: %x.reload.addr = getelementptr inbounds %h.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: %x.reload = load i32, ptr %x.reload.addr
-; CHECK: cleanupret from %1 unwind label %pad.with.phi
-
-; CHECK: pad.with.phi:
-; CHECK: %val = phi i32 [ %x.reload, %pad.with.phi.from.invoke1 ], [ %y.reload, %pad.with.phi.from.invoke2 ]
-; CHECK: %switch = catchswitch within none [label %catch] unwind to caller
+
+
pad.with.phi:
%val = phi i32 [ %x, %invoke1 ], [ %y, %invoke2 ]
%switch = catchswitch within none [label %catch] unwind to caller
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll b/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
index 722ff81bc0cad..566fd1d2d9174 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
@@ -1,10 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that we can handle spills of array allocas
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK-LABEL: %f.Frame = type { ptr, ptr, double, double, [4 x i32], i1 }
+
declare void @consume.double.ptr(ptr)
declare void @consume.i32.ptr(ptr)
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 56)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[PREFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4, i32 0
+; CHECK-NEXT: [[SUFFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: call void @consume.double.ptr(ptr [[PREFIX_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume.i32.ptr(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume.double.ptr(ptr [[SUFFIX_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%prefix = alloca double
%data = alloca i32, i32 4
@@ -18,7 +39,7 @@ entry:
call void @consume.double.ptr(ptr %suffix)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @consume.double.ptr(ptr %prefix)
call void @consume.i32.ptr(ptr %data)
@@ -35,26 +56,10 @@ suspend:
}
; See if the array alloca was stored as an array field.
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, double, double, [4 x i32], i1 }
; See if we used correct index to access prefix, data, suffix (@f)
-; CHECK-LABEL: @f(
-; CHECK: %[[PREFIX:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK-NEXT: %[[DATA:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 4
-; CHECK-NEXT: %[[SUFFIX:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 3
-; CHECK-NEXT: call void @consume.double.ptr(ptr %[[PREFIX:.+]])
-; CHECK-NEXT: call void @consume.i32.ptr(ptr %[[DATA:.+]])
-; CHECK-NEXT: call void @consume.double.ptr(ptr %[[SUFFIX:.+]])
-; CHECK: ret ptr
; See if we used correct index to access prefix, data, suffix (@f.resume)
-; CHECK-LABEL: @f.resume(
-; CHECK: %[[PREFIX:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: %[[DATA:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 4
-; CHECK: %[[SUFFIX:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 3
-; CHECK: call void @consume.double.ptr(ptr %[[PREFIX]])
-; CHECK-NEXT: call void @consume.i32.ptr(ptr %[[DATA]])
-; CHECK-NEXT: call void @consume.double.ptr(ptr %[[SUFFIX]])
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll
index e7c28d92674ba..4481a30a32dfa 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll
@@ -1,12 +1,39 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that variables in a Corotuine whose lifetime range is not overlapping each other
; re-use the same slot in Coroutine frame.
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
+
+; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1 }
+
%"struct.task::promise_type" = type { i8 }
%struct.awaitable = type { i8 }
%struct.big_structure = type { [500 x i8] }
declare ptr @malloc(i64)
declare void @consume(ptr)
define void @a(i1 zeroext %cond) presplitcoroutine {
+; CHECK-LABEL: define void @a(
+; CHECK-SAME: i1 zeroext [[COND:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @a, ptr @a.resumers)
+; CHECK-NEXT: [[TMP1:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr null)
+; CHECK-NEXT: store ptr @a.resume, ptr [[TMP1]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[TMP1]], i32 0, i32 1
+; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[TMP1]], i32 0, i32 3
+; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK: [[IF_THEN]]:
+; CHECK-NEXT: call void @consume(ptr nonnull [[A_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[IF_ELSE]]:
+; CHECK-NEXT: call void @consume(ptr nonnull [[A_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR5]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROEND]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+;
entry:
%__promise = alloca %"struct.task::promise_type", align 1
%a = alloca %struct.big_structure, align 1
@@ -25,8 +52,8 @@ if.then:
%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
+ i8 0, label %await.ready
+ i8 1, label %cleanup1
]
await.ready:
call void @llvm.lifetime.end.p0(ptr nonnull %a)
@@ -37,8 +64,8 @@ if.else:
%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
+ i8 0, label %await2.ready
+ i8 1, label %cleanup2
]
await2.ready:
call void @llvm.lifetime.end.p0(ptr nonnull %b)
@@ -58,7 +85,6 @@ coro.ret:
}
; check that there is only one %struct.big_structure in the frame.
-; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1 }
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
declare i1 @llvm.coro.alloc(token) #3
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-02.ll b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-02.ll
index b75995f3eaa8a..87fea63ce0b39 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-02.ll
@@ -1,6 +1,10 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that variables of different type in a Corotuine whose lifetime range is not overlapping each other
; re-use the same slot in Coroutine frame.
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
+
+; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1 }
+
%"struct.task::promise_type" = type { i8 }
%struct.awaitable = type { i8 }
%struct.big_structure = type { [500 x i8] }
@@ -9,6 +13,29 @@ declare ptr @malloc(i64)
declare void @consume(ptr)
declare void @consume.2(ptr)
define void @a(i1 zeroext %cond) presplitcoroutine {
+; CHECK-LABEL: define void @a(
+; CHECK-SAME: i1 zeroext [[COND:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @a, ptr @a.resumers)
+; CHECK-NEXT: [[TMP1:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr null)
+; CHECK-NEXT: store ptr @a.resume, ptr [[TMP1]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[TMP1]], i32 0, i32 1
+; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[TMP1]], i32 0, i32 3
+; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK: [[IF_THEN]]:
+; CHECK-NEXT: call void @consume(ptr nonnull [[A_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[IF_ELSE]]:
+; CHECK-NEXT: call void @consume.2(ptr nonnull [[A_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR5]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROEND]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+;
entry:
%__promise = alloca %"struct.task::promise_type", align 1
%a = alloca %struct.big_structure, align 1
@@ -27,8 +54,8 @@ if.then:
%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
+ i8 0, label %await.ready
+ i8 1, label %cleanup1
]
await.ready:
call void @llvm.lifetime.end.p0(ptr nonnull %a)
@@ -39,8 +66,8 @@ if.else:
%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
+ i8 0, label %await2.ready
+ i8 1, label %cleanup2
]
await2.ready:
call void @llvm.lifetime.end.p0(ptr nonnull %b)
@@ -58,8 +85,6 @@ coro.ret:
call void @llvm.coro.end(ptr null, i1 false, token none)
ret void
}
-; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1 }
-; CHECK-LABEL: @a.resume(
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
declare i1 @llvm.coro.alloc(token) #3
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-04.ll b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-04.ll
index 81a5dcc1d3858..db2458c71a731 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-04.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-04.ll
@@ -1,6 +1,10 @@
-; Tests that variables of different type with incompatible alignment in a Corotuine whose lifetime
-; range is not overlapping each other should not re-use the same slot in Coroutine frame.
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; Tests that variables of different type with incompatible alignment in a Corotuine whose lifetime
+; range is not overlapping each other should not re-use the same slot in Coroutine frame.
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
+
+; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1, [26 x i8], %struct.big_structure.2 }
+
%"struct.task::promise_type" = type { i8 }
%struct.awaitable = type { i8 }
%struct.big_structure = type { [500 x i8] }
@@ -9,6 +13,30 @@ declare ptr @malloc(i64)
declare void @consume(ptr)
declare void @consume.2(ptr)
define void @a(i1 zeroext %cond) presplitcoroutine {
+; CHECK-LABEL: define void @a(
+; CHECK-SAME: i1 zeroext [[COND:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @a, ptr @a.resumers)
+; CHECK-NEXT: [[TMP1:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr null)
+; CHECK-NEXT: store ptr @a.resume, ptr [[TMP1]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[TMP1]], i32 0, i32 1
+; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[TMP1]], i32 0, i32 3
+; CHECK-NEXT: [[B_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[TMP1]], i32 0, i32 6
+; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK: [[IF_THEN]]:
+; CHECK-NEXT: call void @consume(ptr nonnull [[A_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[IF_ELSE]]:
+; CHECK-NEXT: call void @consume.2(ptr nonnull [[B_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR5]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROEND]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+;
entry:
%__promise = alloca %"struct.task::promise_type", align 1
%a = alloca %struct.big_structure, align 1
@@ -27,8 +55,8 @@ if.then:
%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
+ i8 0, label %await.ready
+ i8 1, label %cleanup1
]
await.ready:
call void @llvm.lifetime.end.p0(ptr nonnull %a)
@@ -39,8 +67,8 @@ if.else:
%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
+ i8 0, label %await2.ready
+ i8 1, label %cleanup2
]
await2.ready:
call void @llvm.lifetime.end.p0(ptr nonnull %b)
@@ -58,8 +86,6 @@ coro.ret:
call void @llvm.coro.end(ptr null, i1 false, token none)
ret void
}
-; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1, [26 x i8], %struct.big_structure.2 }
-; CHECK-LABEL: @a.resume(
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
declare i1 @llvm.coro.alloc(token) #3
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-05.ll b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-05.ll
index 6caa41f32f26e..1815df83b227b 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-05.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-05.ll
@@ -1,6 +1,10 @@
-; Tests that variables of different type with incompatible alignment in a Corotuine whose
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; Tests that variables of different type with incompatible alignment in a Corotuine whose
; lifetime range is not overlapping each other re-use the same slot in CorotuineFrame.
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
+
+; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", i1, [14 x i8], %struct.big_structure }
+
%"struct.task::promise_type" = type { i8 }
%struct.awaitable = type { i8 }
%struct.big_structure = type { [500 x i8] }
@@ -9,6 +13,29 @@ declare ptr @malloc(i64)
declare void @consume(ptr)
declare void @consume.2(ptr)
define void @a(i1 zeroext %cond) presplitcoroutine {
+; CHECK-LABEL: define void @a(
+; CHECK-SAME: i1 zeroext [[COND:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @a, ptr @a.resumers)
+; CHECK-NEXT: [[TMP1:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr null)
+; CHECK-NEXT: store ptr @a.resume, ptr [[TMP1]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[TMP1]], i32 0, i32 1
+; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[TMP1]], i32 0, i32 5
+; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
+; CHECK: [[IF_THEN]]:
+; CHECK-NEXT: call void @consume(ptr nonnull [[A_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[IF_ELSE]]:
+; CHECK-NEXT: call void @consume.2(ptr nonnull [[A_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 3
+; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR5]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROEND]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+;
entry:
%__promise = alloca %"struct.task::promise_type", align 1
%a = alloca %struct.big_structure, align 32
@@ -27,8 +54,8 @@ if.then:
%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
+ i8 0, label %await.ready
+ i8 1, label %cleanup1
]
await.ready:
call void @llvm.lifetime.end.p0(ptr nonnull %a)
@@ -39,8 +66,8 @@ if.else:
%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
+ i8 0, label %await2.ready
+ i8 1, label %cleanup2
]
await2.ready:
call void @llvm.lifetime.end.p0(ptr nonnull %b)
@@ -58,8 +85,6 @@ coro.ret:
call void @llvm.coro.end(ptr null, i1 false, token none)
ret void
}
-; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", i1, [14 x i8], %struct.big_structure }
-; CHECK-LABEL: @a.resume(
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
declare i1 @llvm.coro.alloc(token) #3
diff --git a/llvm/test/Transforms/Coroutines/coro-frame.ll b/llvm/test/Transforms/Coroutines/coro-frame.ll
index d25d335fe63c6..5f9aaeae334ba 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame.ll
@@ -1,7 +1,30 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that we can handle spills of the result of the invoke instruction
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK-LABEL: %f.Frame = type { ptr, ptr, double, i64, i1 }
+
define ptr @f(i64 %this) presplitcoroutine personality i32 0 {
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i64 [[THIS:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca i64, align 8
+; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS_ADDR]], align 4
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[THIS1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS1_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[R:%.*]] = call double @print(double 0.000000e+00)
+; CHECK-NEXT: [[R_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store double [[R]], ptr [[R_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%this.addr = alloca i64
store i64 %this, ptr %this.addr
@@ -15,7 +38,7 @@ entry:
cont:
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call double @print(double %r)
call void @print2(i64 %this1)
@@ -34,20 +57,10 @@ pad:
}
; See if the float was added to the frame
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, double, i64, i1 }
; See if the float was spilled into the frame
-; CHECK-LABEL: @f(
-; CHECK: %r = call double @print(
-; CHECK: %r.spill.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: store double %r, ptr %r.spill.addr
-; CHECK: ret ptr %hdl
; See if the float was loaded from the frame
-; CHECK-LABEL: @f.resume(ptr noundef nonnull align 8
-; CHECK: %r.reload = load double, ptr %r.reload.addr
-; CHECK: call double @print(double %r.reload)
-; CHECK: ret void
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-materialize.ll b/llvm/test/Transforms/Coroutines/coro-materialize.ll
index f55db35edb3ea..c584664f542a6 100644
--- a/llvm/test/Transforms/Coroutines/coro-materialize.ll
+++ b/llvm/test/Transforms/Coroutines/coro-materialize.ll
@@ -1,20 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Verifies that we materialize instruction across suspend points
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
; See that we only spilled one value for f
+; Check other variants where different levels of materialization are achieved
+
; CHECK: %f.Frame = type { ptr, ptr, i32, i1 }
; CHECK: %f_optnone.Frame = type { ptr, ptr, i32, i32, i1 }
-; Check other variants where different levels of materialization are achieved
; CHECK: %f_multiple_remat.Frame = type { ptr, ptr, i32, i1 }
; CHECK: %f_common_def.Frame = type { ptr, ptr, i32, i1 }
; CHECK: %f_common_def_multi_result.Frame = type { ptr, ptr, i32, i1 }
-; CHECK-LABEL: @f(
-; CHECK-LABEL: @f_optnone
-; CHECK-LABEL: @f_multiple_remat(
-; CHECK-LABEL: @f_common_def(
-; CHECK-LABEL: @f_common_def_multi_result(
define ptr @f(i32 %n) presplitcoroutine {
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i32 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[N_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[N]], ptr [[N_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR12]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -24,12 +36,12 @@ entry:
%inc1 = add i32 %n, 1
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%inc2 = add i32 %inc1, 1
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
call void @print(i32 %inc1)
@@ -47,6 +59,76 @@ suspend:
; Checks that we won't transform functions with optnone.
define ptr @f_optnone(i32 %n) presplitcoroutine optnone noinline {
+; CHECK-LABEL: define ptr @f_optnone(
+; CHECK-SAME: i32 [[N:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_optnone.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_OPTNONE_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: store ptr @f_optnone.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f_optnone.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
+; CHECK: [[ALLOCASPILLBB]]:
+; CHECK-NEXT: br label %[[POSTSPILL:.*]]
+; CHECK: [[POSTSPILL]]:
+; CHECK-NEXT: [[INC1:%.*]] = add i32 [[N]], 1
+; CHECK-NEXT: [[INC1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[INC1]], ptr [[INC1_SPILL_ADDR]], align 4
+; CHECK-NEXT: br label %[[COROSAVE:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR6:%.*]] = getelementptr inbounds nuw [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR6]], align 1
+; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
+; CHECK: [[COROSUSPEND]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 -1, label %[[SUSPEND:.*]] [
+; CHECK-NEXT: i8 0, label %[[RESUME1:.*]]
+; CHECK-NEXT: i8 1, label %[[CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[RESUME1]]:
+; CHECK-NEXT: [[INC1_RELOAD_ADDR4:%.*]] = getelementptr inbounds [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INC1_RELOAD5:%.*]] = load i32, ptr [[INC1_RELOAD_ADDR4]], align 4
+; CHECK-NEXT: [[INC2:%.*]] = add i32 [[INC1_RELOAD5]], 1
+; CHECK-NEXT: [[INC2_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i32 [[INC2]], ptr [[INC2_SPILL_ADDR]], align 4
+; CHECK-NEXT: br label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR7:%.*]] = getelementptr inbounds nuw [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR7]], align 1
+; CHECK-NEXT: br label %[[COROSUSPEND2:.*]]
+; CHECK: [[COROSUSPEND2]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND3:.*]]
+; CHECK: [[AFTERCOROSUSPEND3]]:
+; CHECK-NEXT: switch i8 -1, label %[[SUSPEND]] [
+; CHECK-NEXT: i8 0, label %[[RESUME2:.*]]
+; CHECK-NEXT: i8 1, label %[[CLEANUP]]
+; CHECK-NEXT: ]
+; CHECK: [[RESUME2]]:
+; CHECK-NEXT: [[INC2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INC2_RELOAD:%.*]] = load i32, ptr [[INC2_RELOAD_ADDR]], align 4
+; CHECK-NEXT: [[INC1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INC1_RELOAD:%.*]] = load i32, ptr [[INC1_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[INC1_RELOAD]])
+; CHECK-NEXT: call void @print(i32 [[INC2_RELOAD]])
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[MEM:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[HDL]])
+; CHECK-NEXT: call void @free(ptr [[MEM]])
+; CHECK-NEXT: br label %[[SUSPEND]]
+; CHECK: [[SUSPEND]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -56,12 +138,12 @@ entry:
%inc1 = add i32 %n, 1
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%inc2 = add i32 %inc1, 1
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
call void @print(i32 %inc1)
@@ -78,6 +160,26 @@ suspend:
}
define ptr @f_multiple_remat(i32 %n) presplitcoroutine {
+; CHECK-LABEL: define ptr @f_multiple_remat(
+; CHECK-SAME: i32 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_multiple_remat.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f_multiple_remat.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_MULTIPLE_REMAT_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f_multiple_remat.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[N_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_MULTIPLE_REMAT_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[N]], ptr [[N_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[INC1:%.*]] = add i32 [[N]], 1
+; CHECK-NEXT: [[INC2:%.*]] = add i32 [[INC1]], 2
+; CHECK-NEXT: [[INC3:%.*]] = add i32 [[INC2]], 3
+; CHECK-NEXT: [[INC4:%.*]] = add i32 [[INC3]], 4
+; CHECK-NEXT: [[INC5:%.*]] = add i32 [[INC4]], 5
+; CHECK-NEXT: [[INDEX_ADDR22:%.*]] = getelementptr inbounds nuw [[F_MULTIPLE_REMAT_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR22]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -92,12 +194,12 @@ entry:
%inc6 = add i32 %inc5, 5
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%inc7 = add i32 %inc6, 1
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
call void @print(i32 %inc1)
@@ -114,6 +216,25 @@ suspend:
}
define ptr @f_common_def(i32 %n) presplitcoroutine {
+; CHECK-LABEL: define ptr @f_common_def(
+; CHECK-SAME: i32 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_common_def.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f_common_def.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_COMMON_DEF_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f_common_def.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[N_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_COMMON_DEF_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[N]], ptr [[N_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[INC1:%.*]] = add i32 [[N]], 1
+; CHECK-NEXT: [[INC3:%.*]] = add i32 [[N]], 3
+; CHECK-NEXT: [[INC4:%.*]] = add i32 [[INC3]], [[INC1]]
+; CHECK-NEXT: [[INC5:%.*]] = add i32 [[INC4]], [[INC1]]
+; CHECK-NEXT: [[INDEX_ADDR20:%.*]] = getelementptr inbounds nuw [[F_COMMON_DEF_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR20]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -128,12 +249,12 @@ entry:
%inc6 = add i32 %inc5, 5
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%inc7 = add i32 %inc6, 1
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
call void @print(i32 %inc1)
@@ -150,6 +271,30 @@ suspend:
}
define ptr @f_common_def_multi_result(i32 %n) presplitcoroutine {
+; CHECK-LABEL: define ptr @f_common_def_multi_result(
+; CHECK-SAME: i32 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_common_def_multi_result.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f_common_def_multi_result.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_COMMON_DEF_MULTI_RESULT_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f_common_def_multi_result.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[N_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_COMMON_DEF_MULTI_RESULT_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[N]], ptr [[N_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[INC1:%.*]] = add i32 [[N]], 1
+; CHECK-NEXT: [[INC2:%.*]] = add i32 [[INC1]], 2
+; CHECK-NEXT: [[INC3:%.*]] = add i32 [[N]], 3
+; CHECK-NEXT: [[INC4:%.*]] = add i32 [[INC3]], [[INC1]]
+; CHECK-NEXT: [[INC5:%.*]] = add i32 [[INC4]], [[INC1]]
+; CHECK-NEXT: [[INC6:%.*]] = add i32 [[INC5]], 4
+; CHECK-NEXT: [[INC8:%.*]] = add i32 [[INC4]], [[INC2]]
+; CHECK-NEXT: [[INC9:%.*]] = add i32 [[INC8]], 5
+; CHECK-NEXT: [[INC10:%.*]] = add i32 [[INC9]], 6
+; CHECK-NEXT: [[INDEX_ADDR27:%.*]] = getelementptr inbounds nuw [[F_COMMON_DEF_MULTI_RESULT_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR27]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -169,12 +314,12 @@ entry:
%inc11 = add i32 %inc10, 7
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%inc12 = add i32 %inc7, 1
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
call void @print(i32 %inc11)
diff --git a/llvm/test/Transforms/Coroutines/coro-padding.ll b/llvm/test/Transforms/Coroutines/coro-padding.ll
index 1de12a4f44a57..c48b8961168e8 100644
--- a/llvm/test/Transforms/Coroutines/coro-padding.ll
+++ b/llvm/test/Transforms/Coroutines/coro-padding.ll
@@ -1,12 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that we will insert the correct padding if natural alignment of the
; spilled data does not match the alignment specified in alloca instruction.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%PackedStruct = type <{ i64 }>
+; CHECK-LABEL: %f.Frame = type { ptr, ptr, i1, [15 x i8], %PackedStruct }
+
declare void @consume(ptr)
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%data = alloca %PackedStruct, align 32
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -16,7 +33,7 @@ entry:
call void @consume(ptr %data)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @consume(ptr %data)
br label %cleanup
@@ -31,19 +48,10 @@ suspend:
}
; See if the padding was inserted before PackedStruct
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, i1, [15 x i8], %PackedStruct }
; See if we used correct index to access packed struct (padding is field 3)
-; CHECK-LABEL: @f(
-; CHECK: %[[DATA:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 4
-; CHECK-NEXT: call void @consume(ptr %[[DATA]])
-; CHECK: ret ptr
; See if we used correct index to access packed struct (padding is field 3)
-; CHECK-LABEL: @f.resume(
-; CHECK: %[[DATA:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 4
-; CHECK-NEXT: call void @consume(ptr %[[DATA]])
-; CHECK: ret void
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-param-copy.ll b/llvm/test/Transforms/Coroutines/coro-param-copy.ll
index f0e816bba9584..4d8d7f607a34f 100644
--- a/llvm/test/Transforms/Coroutines/coro-param-copy.ll
+++ b/llvm/test/Transforms/Coroutines/coro-param-copy.ll
@@ -1,8 +1,46 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that we create copy the data from the alloca into the coroutine
; frame slot if it was written to.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i64, i64, i64, i64, i1 }
+
define ptr @f() presplitcoroutine {
+; See that we added both x and y to the frame.
+;
+; Then see that all of the uses prior to coro-begin stays put.
+;
+; Then see that we only copy the x as y was not modified prior to coro.begin.
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
+; CHECK-NEXT: [[X_ADDR:%.*]] = alloca i64, align 8
+; CHECK-NEXT: call void @use(ptr [[X_ADDR]])
+; CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i64, align 8
+; CHECK-NEXT: [[FLAG:%.*]] = call i1 @check()
+; CHECK-NEXT: br i1 [[FLAG]], label %[[FLAG_TRUE:.*]], label %[[FLAG_MERGE:.*]]
+; CHECK: [[FLAG_TRUE]]:
+; CHECK-NEXT: call void @use(ptr [[Z_ADDR]])
+; CHECK-NEXT: br label %[[FLAG_MERGE]]
+; CHECK: [[FLAG_MERGE]]:
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @myAlloc(i32 56)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[X_ADDR]], align 4
+; CHECK-NEXT: store i64 [[TMP1]], ptr [[TMP0]], align 4
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[Z_ADDR]], align 4
+; CHECK-NEXT: store i64 [[TMP3]], ptr [[TMP2]], align 4
+; CHECK-NEXT: [[Y_ADDR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr [[Y_ADDR_RELOAD_ADDR]], i8 1, i32 4, i1 false)
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 6
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%a.addr = alloca i64 ; read-only before coro.begin
%a = load i64, ptr %a.addr ; cannot modify the value, don't need to copy
@@ -11,7 +49,7 @@ entry:
call void @use(ptr %x.addr) ; uses %x.addr before coro.begin
%y.addr = alloca i64
-
+
%z.addr = alloca i64
%flag = call i1 @check()
br i1 %flag, label %flag_true, label %flag_merge
@@ -28,7 +66,7 @@ flag_merge:
call void @llvm.memset.p0.i32(ptr %y.addr, i8 1, i32 4, i1 false)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @use(ptr %a.addr)
call void @use(ptr %x.addr)
@@ -45,34 +83,6 @@ suspend:
ret ptr %hdl
}
-; See that we added both x and y to the frame.
-; CHECK: %f.Frame = type { ptr, ptr, i64, i64, i64, i64, i1 }
-
-; See that all of the uses prior to coro-begin stays put.
-; CHECK-LABEL: define ptr @f() {
-; CHECK-NEXT: entry:
-; CHECK-NEXT: %a.addr = alloca i64
-; CHECK-NEXT: %x.addr = alloca i64
-; CHECK-NEXT: call void @use(ptr %x.addr)
-; CHECK-NEXT: %z.addr = alloca i64
-
-; See that we only copy the x as y was not modified prior to coro.begin.
-; CHECK: store ptr @f.destroy, ptr %destroy.addr
-; The next 3 instructions are to copy data in %x.addr from stack to frame.
-; CHECK-NEXT: %0 = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 3
-; CHECK-NEXT: %1 = load i64, ptr %x.addr, align 4
-; CHECK-NEXT: store i64 %1, ptr %0, align 4
-; The next 3 instructions are to copy data in %z.addr from stack to frame.
-; CHECK-NEXT: [[T2:%.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 5
-; CHECK-NEXT: [[T3:%.+]] = load i64, ptr %z.addr, align 4
-; CHECK-NEXT: store i64 [[T3]], ptr [[T2]], align 4
-; The next instruction is to recreate %y.cast in the original IR.
-; CHECK-NEXT: %y.addr.reload.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 4
-; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr %y.addr.reload.addr, i8 1, i32 4, i1 false)
-; CHECK-NEXT: %index.addr1 = getelementptr inbounds nuw %f.Frame, ptr %hdl, i32 0, i32 6
-; CHECK-NEXT: store i1 false, ptr %index.addr1, align 1
-; CHECK-NEXT: ret ptr %hdl
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll b/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll
index 160754e7d11c3..eeba55b8f23a4 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll
@@ -1,10 +1,28 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that a remat that inserts rematerialized instructions in the single predecessor block works
; as expected
; RUN: opt < %s -O0 -S | FileCheck %s
+
; CHECK: %f.Frame = type { i32 }
define { ptr, i32 } @f(ptr %buffer, i32 %n) {
+; CHECK-LABEL: define { ptr, i32 } @f(
+; CHECK-SAME: ptr [[BUFFER:%.*]], i32 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[N_VAL_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[BUFFER]], i32 0, i32 0
+; CHECK-NEXT: store i32 [[N]], ptr [[N_VAL_SPILL_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[N]])
+; CHECK-NEXT: [[INC1:%.*]] = add i32 [[N]], 1
+; CHECK-NEXT: [[INC2:%.*]] = add i32 [[INC1]], 2
+; CHECK-NEXT: [[INC3:%.*]] = add i32 [[INC2]], 3
+; CHECK-NEXT: [[INC4:%.*]] = add i32 [[INC3]], 4
+; CHECK-NEXT: [[INC5:%.*]] = add i32 [[INC4]], 5
+; CHECK-NEXT: [[INC6:%.*]] = add i32 [[INC5]], 6
+; CHECK-NEXT: [[TMP0:%.*]] = insertvalue { ptr, i32 } poison, ptr @f.resume.0, 0
+; CHECK-NEXT: [[TMP1:%.*]] = insertvalue { ptr, i32 } [[TMP0]], i32 [[INC6]], 1
+; CHECK-NEXT: ret { ptr, i32 } [[TMP1]]
+;
entry:
%id = call token @llvm.coro.id.retcon(i32 8, i32 4, ptr %buffer, ptr @f_prototype, ptr @allocate, ptr @deallocate)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-after-phi.ll b/llvm/test/Transforms/Coroutines/coro-spill-after-phi.ll
index 273ac7c5293d9..6694fa79b8858 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-after-phi.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-after-phi.ll
@@ -3,6 +3,7 @@
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse,simplifycfg' -S | FileCheck %s
; Verifies that the both phis are stored correctly in the coroutine frame
+
; CHECK: %f.Frame = type { ptr, ptr, i32, i32, i1 }
define ptr @f(i1 %n) presplitcoroutine {
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
index bfc48adfed22a..4b4805d660344 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
@@ -1,8 +1,11 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that we can spills coro.begin from an inlined inner coroutine.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%g.Frame = type { ptr, ptr, i32, i1, i32 }
+; CHECK-LABEL: %f.Frame = type { ptr, ptr, ptr, i1 }
+
@g.resumers = private constant [3 x ptr] [ptr @g.dummy, ptr @g.dummy, ptr @g.dummy]
declare void @g.dummy(ptr)
@@ -10,6 +13,22 @@ declare void @g.dummy(ptr)
declare ptr @g()
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INNERID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @g, ptr @g.resumers)
+; CHECK-NEXT: [[INNERHDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[INNERID]], ptr null)
+; CHECK-NEXT: [[INNERHDL_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store ptr [[INNERHDL]], ptr [[INNERHDL_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -21,7 +40,7 @@ entry:
%tok = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %tok, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
%gvar.addr = getelementptr inbounds %g.Frame, ptr %innerhdl, i32 0, i32 4
%gvar = load i32, ptr %gvar.addr
@@ -38,22 +57,10 @@ suspend:
}
; See if the ptr for coro.begin was added to f.Frame
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, ptr, i1 }
; See if the g's coro.begin was spilled into the frame
-; CHECK-LABEL: @f(
-; CHECK: %innerid = call token @llvm.coro.id(i32 0, ptr null, ptr @g, ptr @g.resumers)
-; CHECK: %innerhdl = call noalias nonnull ptr @llvm.coro.begin(token %innerid, ptr null)
-; CHECK: %[[spilladdr:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: store ptr %innerhdl, ptr %[[spilladdr]]
; See if the coro.begin was loaded from the frame
-; CHECK-LABEL: @f.resume(
-; CHECK: %[[innerhdlAddr:.+]] = getelementptr inbounds %f.Frame, ptr %{{.+}}, i32 0, i32 2
-; CHECK: %[[innerhdl:.+]] = load ptr, ptr %[[innerhdlAddr]]
-; CHECK: %[[gvarAddr:.+]] = getelementptr inbounds %g.Frame, ptr %[[innerhdl]], i32 0, i32 4
-; CHECK: %[[gvar:.+]] = load i32, ptr %[[gvarAddr]]
-; CHECK: call void @print.i32(i32 %[[gvar]])
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-defs-before-corobegin.ll b/llvm/test/Transforms/Coroutines/coro-spill-defs-before-corobegin.ll
index 16df22b19fd11..7f14693052bd0 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-defs-before-corobegin.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-defs-before-corobegin.ll
@@ -1,7 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Verifies that phi and invoke definitions before CoroBegin are spilled properly.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse,simplifycfg' -S | FileCheck %s
+; CHECK: %f.Frame = type { ptr, ptr, i32, i32, i1 }
+
define ptr @f(i1 %n) presplitcoroutine personality i32 0 {
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i1 [[N:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 32)
+; CHECK-NEXT: [[FLAG:%.*]] = call i1 @check(ptr [[ALLOC]])
+; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[FLAG]], i32 0, i32 1
+; CHECK-NEXT: [[VALUE_INVOKE:%.*]] = call i32 @calc()
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[VALUE_INVOKE_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i32 [[VALUE_INVOKE]], ptr [[VALUE_INVOKE_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[VALUE_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[SPEC_SELECT]], ptr [[VALUE_PHI_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[TMP0:%.*]] = call i32 @print(i32 [[SPEC_SELECT]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @print(i32 [[VALUE_INVOKE]])
+; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR2]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -25,7 +50,7 @@ normal:
call i32 @print(i32 %value_invoke)
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call i32 @print(i32 %value_phi)
call i32 @print(i32 %value_invoke)
@@ -41,25 +66,13 @@ suspend:
lpad:
%lpval = landingpad { ptr, i32 }
- cleanup
+ cleanup
resume { ptr, i32 } %lpval
}
; Verifies that the both value_phi and value_invoke are stored correctly in the coroutine frame
-; CHECK: %f.Frame = type { ptr, ptr, i32, i32, i1 }
-; CHECK-LABEL: @f(
-; CHECK: %alloc = call ptr @malloc(i32 32)
-; CHECK-NEXT: %flag = call i1 @check(ptr %alloc)
-; CHECK-NEXT: %spec.select = select i1 %flag, i32 0, i32 1
-; CHECK-NEXT: %value_invoke = call i32 @calc()
-; CHECK-NEXT: %hdl = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)
-; CHECK: store ptr @f.destroy, ptr %destroy.addr
-; CHECK-NEXT: %value_invoke.spill.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 3
-; CHECK-NEXT: store i32 %value_invoke, ptr %value_invoke.spill.addr
-; CHECK-NEXT: %value_phi.spill.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK-NEXT: store i32 %spec.select, ptr %value_phi.spill.addr
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll b/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
index a3888f0eff562..946cf6991dc23 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
@@ -1,12 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that we would take care of the value written to promise before @llvm.coro.begin.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%"class.task::promise_type" = type { [64 x i8] }
+; CHECK-LABEL: %f.Frame = type { ptr, ptr, i32, i1, [43 x i8], %"class.task::promise_type" }
+
declare void @consume(ptr)
declare void @consume2(ptr)
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[__PROMISE:%.*]] = alloca %"class.task::promise_type", align 64
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: call void @consume2(ptr [[__PROMISE]])
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 128)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[TMP1:%.*]] = load %"class.task::promise_type", ptr [[__PROMISE]], align 1
+; CHECK-NEXT: store %"class.task::promise_type" [[TMP1]], ptr [[TMP0]], align 1
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%data = alloca i32, align 4
%__promise = alloca %"class.task::promise_type", align 64
@@ -18,7 +40,7 @@ entry:
call void @consume(ptr %data)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @consume(ptr %data)
call void @consume2(ptr %__promise)
@@ -33,20 +55,8 @@ suspend:
ret ptr %hdl
}
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, i32, i1, [43 x i8], %"class.task::promise_type" }
-; CHECK-LABEL: @f(
-; CHECK: %__promise = alloca %"class.task::promise_type"
-; CHECK: call void @consume2(ptr %__promise)
-; CHECK: call{{.*}}@llvm.coro.begin
-; CHECK: %[[PROMISE_ADDR:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 5
-; CHECK: %[[PROMISE_VALUE:.+]] = load %"class.task::promise_type", ptr %__promise
-; CHECK: store %"class.task::promise_type" %[[PROMISE_VALUE]], ptr %[[PROMISE_ADDR]]
-; CHECK-LABEL: @f.resume(
-; CHECK: %[[DATA:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 5
-; CHECK: call void @consume2(ptr %[[DATA]])
-; CHECK: ret void
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-promise.ll b/llvm/test/Transforms/Coroutines/coro-spill-promise.ll
index 344d77bd54930..861b29098581f 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-promise.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-promise.ll
@@ -1,12 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that promise object is reloaded from the correct index of the coro frame.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%"class.task::promise_type" = type { [64 x i8] }
+; CHECK-LABEL: %f.Frame = type { ptr, ptr, i32, i1, [43 x i8], %"class.task::promise_type" }
+
declare void @consume(ptr)
declare void @consume2(ptr)
define ptr @f() presplitcoroutine {
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 128)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%data = alloca i32, align 4
%__promise = alloca %"class.task::promise_type", align 64
@@ -17,7 +34,7 @@ entry:
call void @consume(ptr %data)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @consume(ptr %data)
call void @consume2(ptr %__promise)
@@ -32,12 +49,7 @@ suspend:
ret ptr %hdl
}
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, i32, i1, [43 x i8], %"class.task::promise_type" }
-; CHECK-LABEL: @f.resume(
-; CHECK: %[[DATA:.+]] = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 5
-; CHECK: call void @consume2(ptr %[[DATA]])
-; CHECK: ret void
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll b/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
index 6a80f3637fd10..ba6a2a7d6bb3b 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
@@ -1,27 +1,35 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Check that the return value of @llvm.coro.suspend gets spilled to the frame
; if it may be used across suspend points.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
; %sp1 should be part of the frame (the i8 value).
-; CHECK: %f.Frame = type { ptr, ptr, i1, i8 }
; If the coro resumes, %sp1 is set to 0.
-; CHECK-LABEL: define{{.*}} void @f.resume
-; CHECK: AfterCoroSuspend:
-; CHECK: %sp1.spill.addr = getelementptr inbounds %f.Frame
-; CHECK: store i8 0, ptr %sp1.spill.addr
; In the coro destroy function, %sp1 is reloaded from the frame. Its value
; depends on whether the coroutine was resumed or not.
-; CHECK-LABEL: define{{.*}} void @f.destroy
-; CHECK: cleanup:
-; CHECK: %sp1.reload.addr = getelementptr inbounds %f.Frame
-; CHECK: %sp1.reload = load i8, ptr %sp1.reload.addr
-; CHECK: call void @print(i8 %sp1.reload)
+; CHECK: %f.Frame = type { ptr, ptr, i1, i8 }
+
define ptr @f(i32 %n) presplitcoroutine {
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i32 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
+; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i8 -1, ptr [[SP1_SPILL_ADDR]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -30,12 +38,12 @@ entry:
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
br label %cleanup
diff --git a/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll b/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
index 12dfa16991326..665be555763fc 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='cgscc(coro-split)' -S | FileCheck %s
; Test that nested structs in coroutine frames have correct debug info scoping.
@@ -10,6 +11,18 @@
%"class.Promise" = type { %"struct.Outer" }
define void @test_coro_function() presplitcoroutine !dbg !10 {
+; CHECK-LABEL: define void @test_coro_function(
+; CHECK-SAME: ) !dbg [[DBG3:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[__PROMISE:%.*]] = alloca [[CLASS_PROMISE:%.*]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
+; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
+; CHECK: [[ALLOCASPILLBB]]:
+; CHECK-NEXT: #dbg_declare(ptr null, [[META7:![0-9]+]], !DIExpression(), [[META30:![0-9]+]])
+; CHECK-NEXT: br label %[[POSTSPILL:.*]]
+; CHECK: [[POSTSPILL]]:
+; CHECK-NEXT: ret void
+;
entry:
%__promise = alloca %"class.Promise", align 8
%0 = call token @llvm.coro.id(i32 0, ptr %__promise, ptr null, ptr null)
@@ -18,33 +31,23 @@ entry:
ret void
}
-; CHECK: define void @test_coro_function()
; Check that frame debug info is generated
-; CHECK: ![[FRAME_TYPE:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{{.*}}.coro_frame_ty"
; Key validation: Check that nested structs have the correct scope hierarchy
; 1. Promise should be scoped to the frame
-; CHECK: ![[PROMISE:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "class_Promise", scope: ![[FRAME_TYPE]]
; 2. Members of Promise should be scoped to Promise (check this before Outer since it comes first in output)
-; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "struct_Outer", scope: ![[PROMISE]]
; 3. Outer should be scoped to Promise (not the frame!)
-; CHECK: ![[OUTER:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_Outer", scope: ![[PROMISE]]
; 4. First Outer member should be scoped to Outer
-; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "struct_Inner", scope: ![[OUTER]]
; 5. Inner should be scoped to Outer (proper nesting)
-; CHECK: ![[INNER:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_Inner", scope: ![[OUTER]]
; 6. Members of Inner should be scoped to Inner
-; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__int_32", scope: ![[INNER]]
-; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "PointerType", scope: ![[INNER]]
; 7. Second Outer member comes after Inner (due to output order)
-; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__int_64", scope: ![[OUTER]]
declare token @llvm.coro.id(i32, ptr readnone, ptr readonly, ptr)
declare ptr @llvm.coro.begin(token, ptr writeonly)
@@ -59,3 +62,35 @@ declare token @llvm.coro.save(ptr)
!10 = distinct !DISubprogram(name: "test_coro_function", scope: !1, file: !1, line: 1, type: !11, spFlags: DISPFlagDefinition, unit: !0)
!11 = !DISubroutineType(types: !12)
!12 = !{null}
+;.
+; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META1:![0-9]+]], producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+; CHECK: [[META1]] = !DIFile(filename: "{{.*}}test.cpp", directory: {{.*}})
+; CHECK: [[DBG3]] = distinct !DISubprogram(name: "test_coro_function", scope: [[META1]], file: [[META1]], line: 1, type: [[META4:![0-9]+]], spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META6:![0-9]+]])
+; CHECK: [[META4]] = !DISubroutineType(types: [[META5:![0-9]+]])
+; CHECK: [[META5]] = !{null}
+; CHECK: [[META6]] = !{[[META7]]}
+; CHECK: [[META7]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG3]], file: [[META1]], line: 1, type: [[META8:![0-9]+]], flags: DIFlagArtificial)
+; CHECK: [[META8]] = !DICompositeType(tag: DW_TAG_structure_type, name: "test_coro_function.coro_frame_ty", file: [[META1]], line: 1, size: 384, align: 64, flags: DIFlagArtificial, elements: [[META9:![0-9]+]])
+; CHECK: [[META9]] = !{[[META10:![0-9]+]], [[META12:![0-9]+]], [[META13:![0-9]+]], [[META28:![0-9]+]]}
+; CHECK: [[META10]] = !DIDerivedType(tag: DW_TAG_member, name: "__resume_fn", scope: [[META8]], file: [[META1]], line: 1, baseType: [[META11:![0-9]+]], size: 64, align: 64, flags: DIFlagArtificial)
+; CHECK: [[META11]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+; CHECK: [[META12]] = !DIDerivedType(tag: DW_TAG_member, name: "__destroy_fn", scope: [[META8]], file: [[META1]], line: 1, baseType: [[META11]], size: 64, align: 64, offset: 64, flags: DIFlagArtificial)
+; CHECK: [[META13]] = !DIDerivedType(tag: DW_TAG_member, name: "class_Promise_0", scope: [[META8]], file: [[META1]], line: 1, baseType: [[META14:![0-9]+]], size: 192, align: 64, offset: 128, flags: DIFlagArtificial)
+; CHECK: [[META14]] = !DICompositeType(tag: DW_TAG_structure_type, name: "class_Promise", scope: [[META8]], file: [[META1]], line: 1, size: 192, align: 64, flags: DIFlagArtificial, elements: [[META15:![0-9]+]])
+; CHECK: [[META15]] = !{[[META16:![0-9]+]]}
+; CHECK: [[META16]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_Outer", scope: [[META14]], file: [[META1]], line: 1, baseType: [[META17:![0-9]+]], size: 192, align: 64, flags: DIFlagArtificial)
+; CHECK: [[META17]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_Outer", scope: [[META14]], file: [[META1]], line: 1, size: 192, align: 64, flags: DIFlagArtificial, elements: [[META18:![0-9]+]])
+; CHECK: [[META18]] = !{[[META19:![0-9]+]], [[META26:![0-9]+]]}
+; CHECK: [[META19]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_Inner", scope: [[META17]], file: [[META1]], line: 1, baseType: [[META20:![0-9]+]], size: 128, align: 64, flags: DIFlagArtificial)
+; CHECK: [[META20]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_Inner", scope: [[META17]], file: [[META1]], line: 1, size: 128, align: 64, flags: DIFlagArtificial, elements: [[META21:![0-9]+]])
+; CHECK: [[META21]] = !{[[META22:![0-9]+]], [[META24:![0-9]+]]}
+; CHECK: [[META22]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32", scope: [[META20]], file: [[META1]], line: 1, baseType: [[META23:![0-9]+]], size: 32, flags: DIFlagArtificial)
+; CHECK: [[META23]] = !DIBasicType(name: "__int_32", size: 32, encoding: DW_ATE_signed, flags: DIFlagArtificial)
+; CHECK: [[META24]] = !DIDerivedType(tag: DW_TAG_member, name: "PointerType", scope: [[META20]], file: [[META1]], line: 1, baseType: [[META25:![0-9]+]], size: 64, align: 64, offset: 64, flags: DIFlagArtificial)
+; CHECK: [[META25]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "PointerType", baseType: null, size: 64, align: 64)
+; CHECK: [[META26]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64", scope: [[META17]], file: [[META1]], line: 1, baseType: [[META27:![0-9]+]], size: 64, offset: 128, flags: DIFlagArtificial)
+; CHECK: [[META27]] = !DIBasicType(name: "__int_64", size: 64, encoding: DW_ATE_signed, flags: DIFlagArtificial)
+; CHECK: [[META28]] = !DIDerivedType(tag: DW_TAG_member, name: "__coro_index", scope: [[META8]], file: [[META1]], line: 1, baseType: [[META29:![0-9]+]], size: 64, align: 32, offset: 320, flags: DIFlagArtificial)
+; CHECK: [[META29]] = !DIBasicType(name: "__coro_index", size: 64, encoding: DW_ATE_unsigned_char)
+; CHECK: [[META30]] = !DILocation(line: 1, column: 1, scope: [[DBG3]])
+;.
diff --git a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
index 848cf8b3e461f..b2a6555373ec1 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
@@ -1,18 +1,35 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that coro-split will optimize the lifetime.start maker of each local variable,
; sink them to the places after the suspend block.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse,simplifycfg' -S | FileCheck %s
-; CHECK: %a.Frame = type { ptr, ptr, i1 }
-; CHECK: %a_optnone.Frame = type { ptr, ptr, i32, i1 }
%"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" }
+; CHECK: %a.Frame = type { ptr, ptr, i1 }
+; CHECK: %a_optnone.Frame = type { ptr, ptr, i32, i1 }
+
declare ptr @malloc(i64)
declare void @print(i32)
define void @a() presplitcoroutine {
+; CHECK-LABEL: define void @a() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
+; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @a.resume, ptr [[VFRAME]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
+; CHECK-NEXT: ret void
+;
entry:
%ref.tmp7 = alloca %"struct.lean_future<int>::Awaiter", align 8
%testval = alloca i32
@@ -25,8 +42,8 @@ entry:
%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
- i8 1, label %exit
+ i8 0, label %await.ready
+ i8 1, label %exit
]
await.ready:
%StrayCoroSave = call token @llvm.coro.save(ptr null)
@@ -41,17 +58,50 @@ exit:
ret void
}
-; CHECK-LABEL: @a.resume(
-; CHECK: %testval = alloca i32, align 4
-; CHECK: call void @llvm.lifetime.start.p0(ptr %testval)
-; CHECK-NEXT: %val = load i32, ptr %ref.tmp7
-; CHECK-NEXT: %test = load i32, ptr %testval
-; CHECK-NEXT: call void @print(i32 %test)
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr %testval)
-; CHECK-NEXT: call void @print(i32 %val)
-; CHECK-NEXT: ret void
define void @a_optnone() presplitcoroutine optnone noinline {
+; CHECK-LABEL: define void @a_optnone(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a_optnone.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
+; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 0
+; CHECK-NEXT: store ptr @a_optnone.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: store ptr @a_optnone.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
+; CHECK: [[ALLOCASPILLBB]]:
+; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: br label %[[POSTSPILL:.*]]
+; CHECK: [[POSTSPILL]]:
+; CHECK-NEXT: br label %[[COROSAVE:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
+; CHECK: [[COROSUSPEND]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 -1, 0
+; CHECK-NEXT: br i1 [[COND]], label %[[AWAIT_READY:.*]], label %[[EXIT:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+;
entry:
%ref.tmp7 = alloca %"struct.lean_future<int>::Awaiter", align 8
%testval = alloca i32
@@ -64,8 +114,8 @@ entry:
%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
- i8 1, label %exit
+ i8 0, label %await.ready
+ i8 1, label %exit
]
await.ready:
%StrayCoroSave = call token @llvm.coro.save(ptr null)
diff --git a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
index 26037043a26ed..23e5cb80de012 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
@@ -1,3 +1,4 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that coro-split will optimize the lifetime.start maker of each local variable,
; sink them to the places after the suspend block.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
@@ -11,6 +12,35 @@ declare ptr @malloc(i64)
declare void @print(i32)
define void @a() presplitcoroutine {
+; CHECK-LABEL: define void @a() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
+; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @a.resume, ptr [[VFRAME]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: [[TESTCOND:%.*]] = call i1 @getcond()
+; CHECK-NEXT: br i1 [[TESTCOND]], label %[[COROSAVE:.*]], label %[[AFTER_AWAIT:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: br i1 false, label %[[AWAIT_READY:.*]], label %[[AFTERCOROEND:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: br label %[[AFTER_AWAIT]]
+; CHECK: [[AFTER_AWAIT]]:
+; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST1]])
+; CHECK-NEXT: br label %[[AFTERCOROEND]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+;
entry:
%ref.tmp7 = alloca %"struct.lean_future<int>::Awaiter", align 8
%testval = alloca i32
@@ -26,8 +56,8 @@ if.suspend:
%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
- i8 1, label %exit
+ i8 0, label %await.ready
+ i8 1, label %exit
]
else.direct:
@@ -52,10 +82,6 @@ exit:
ret void
}
-; CHECK-LABEL: @a.resume(
-; CHECK: %[[VAL:testval.+]] = getelementptr inbounds %a.Frame
-; CHECK-NOT: call void @llvm.lifetime.start.p0(ptr %{{.*}})
-; CHECK: %test = load i32, ptr %[[VAL]]
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
declare i1 @llvm.coro.alloc(token) #3
diff --git a/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll b/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
index 7eadf089d0cc0..a61e877bf8040 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
@@ -1,9 +1,32 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that coro-split pass generates TBAA metadata on coroutine frame slot reloads.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK-LABEL: @f.resume(
-; CHECK-SAME: %[[HDL:[A-Za-z0-9_]+]]
define ptr @f(ptr %p) presplitcoroutine {
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4, !tbaa [[INT_TBAA0:![0-9]+]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[NEED_ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
+; CHECK-NEXT: br i1 [[NEED_ALLOC]], label %[[DYN_ALLOC:.*]], label %[[BEGIN:.*]]
+; CHECK: [[DYN_ALLOC]]:
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: br label %[[BEGIN]]
+; CHECK: [[BEGIN]]:
+; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOC]], %[[DYN_ALLOC]] ], [ null, %[[ENTRY]] ]
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[NEED_ALLOC]], ptr @f.destroy, ptr @f.cleanup
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 0)
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
entry:
%x = load i32, ptr %p, !tbaa !3
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -21,11 +44,9 @@ begin:
call void @print(i32 0)
%0 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %0, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @print(i32 %x)
- ; CHECK: %[[X_RELOAD_ADDR:.+]] = getelementptr inbounds %f.Frame, ptr %[[HDL]], i32 0, i32 {{[0-9]+}}
- ; CHECK: %{{.+}} = load i32, ptr %[[X_RELOAD_ADDR]], align 4, !tbaa ![[COROUTINE_SLOT_TAG:[0-9]+]]
br label %cleanup
cleanup:
@@ -37,9 +58,6 @@ suspend:
ret ptr %hdl
}
-; CHECK: ![[COROUTINE_SLOT_ROOT:.+]] = !{!"Simple C++ TBAA"}
-; CHECK: ![[COROUTINE_SLOT_TAG]] = !{![[COROUTINE_SLOT_SCALAR:[0-9]+]], ![[COROUTINE_SLOT_SCALAR]], i64 0}
-; CHECK: ![[COROUTINE_SLOT_SCALAR]] = !{!"f.Frame Slot", ![[COROUTINE_SLOT_ROOT]], i64 0}
!0 = !{!"Simple C++ TBAA"}
!1 = !{!"omnipotent char", !0, i64 0}
!2 = !{!"int", !1, i64 0}
@@ -60,3 +78,9 @@ declare void @llvm.coro.end(ptr, i1, token)
declare noalias ptr @malloc(i32) allockind("alloc,uninitialized") "alloc-family"="malloc"
declare void @print(i32)
declare void @free(ptr) willreturn allockind("free") "alloc-family"="malloc"
+;.
+; CHECK: [[INT_TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
+; CHECK: [[META1]] = !{!"int", [[META2:![0-9]+]], i64 0}
+; CHECK: [[META2]] = !{!"omnipotent char", [[META3:![0-9]+]], i64 0}
+; CHECK: [[META3]] = !{!"Simple C++ TBAA"}
+;.
diff --git a/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll b/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll
index d1d826c7f1009..2b4a6c85998b3 100644
--- a/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll
+++ b/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll
@@ -1,5 +1,8 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; CHECK: %foo.Frame = type { ptr, ptr, i32, i16, i1 }
+
declare ptr @malloc(i64)
declare void @free(ptr)
declare void @usePointer(ptr)
@@ -14,6 +17,18 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly)
declare token @llvm.coro.save(ptr)
define void @foo() presplitcoroutine {
+; CHECK-LABEL: define void @foo() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[CORO_ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @foo.resumers)
+; CHECK-NEXT: [[CORO_ALLOC:%.*]] = call ptr @malloc(i64 24)
+; CHECK-NEXT: [[CORO_STATE:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[CORO_ID]], ptr [[CORO_ALLOC]])
+; CHECK-NEXT: store ptr @foo.resume, ptr [[CORO_STATE]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[FOO_FRAME:%.*]], ptr [[CORO_STATE]], i32 0, i32 1
+; CHECK-NEXT: store ptr @foo.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[FOO_FRAME]], ptr [[CORO_STATE]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret void
+;
entry:
%a0 = alloca [0 x i8]
%a1 = alloca i32
@@ -28,8 +43,8 @@ entry:
%coro.save = call token @llvm.coro.save(ptr %coro.state)
%call.suspend = call i8 @llvm.coro.suspend(token %coro.save, i1 false)
switch i8 %call.suspend, label %suspend [
- i8 0, label %wakeup
- i8 1, label %cleanup
+ i8 0, label %wakeup
+ i8 1, label %cleanup
]
wakeup: ; preds = %entry
@@ -51,17 +66,4 @@ cleanup: ; preds = %wakeup, %entry
br label %suspend
}
-; CHECK: %foo.Frame = type { ptr, ptr, i32, i16, i1 }
-; CHECK-LABEL: @foo.resume(
-; CHECK-NEXT: entry.resume:
-; CHECK-NEXT: [[A1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME:%foo.Frame]], ptr [[FRAMEPTR:%.*]], i32 0, i32 2
-; CHECK-NEXT: [[A4_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[FRAMEPTR]], i32 0, i32 3
-; CHECK-NEXT: call void @usePointer(ptr [[FRAMEPTR]])
-; CHECK-NEXT: call void @usePointer(ptr [[A1_RELOAD_ADDR]])
-; CHECK-NEXT: call void @usePointer(ptr [[FRAMEPTR]])
-; CHECK-NEXT: call void @usePointer(ptr [[FRAMEPTR]])
-; CHECK-NEXT: call void @usePointer(ptr [[A4_RELOAD_ADDR]])
-; CHECK-NEXT: call void @usePointer2(ptr [[FRAMEPTR]])
-; CHECK-NEXT: call void @free(ptr [[FRAMEPTR]])
-; CHECK-NEXT: ret void
>From bff97c3cc94a56a59f15d17f9db42d5fd21f1a2c Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash at gmail.com>
Date: Wed, 28 Jan 2026 15:33:57 +0000
Subject: [PATCH 2/7] add include-generated-funcs where require to preserve
test intent
---
.../Coroutines/coro-alloc-with-param-O0.ll | 61 +-
.../Coroutines/coro-alloc-with-param-O2.ll | 57 +-
.../Transforms/Coroutines/coro-alloca-07.ll | 71 +-
llvm/test/Transforms/Coroutines/coro-async.ll | 1077 ++++++----
.../coro-await-suspend-lower-invoke.ll | 105 +-
.../Coroutines/coro-await-suspend-lower.ll | 94 +-
.../Coroutines/coro-debug-coro-frame.ll | 1748 +++++++++++++----
.../Coroutines/coro-eh-aware-edge-split-01.ll | 85 +-
.../Coroutines/coro-eh-aware-edge-split-02.ll | 87 +-
.../Coroutines/coro-frame-arrayalloca.ll | 66 +-
llvm/test/Transforms/Coroutines/coro-frame.ll | 70 +-
.../Transforms/Coroutines/coro-padding.ll | 54 +-
.../Coroutines/coro-spill-corobegin.ll | 61 +-
.../Coroutines/coro-spill-promise-02.ll | 66 +-
.../Coroutines/coro-spill-promise.ll | 56 +-
.../Coroutines/coro-spill-suspend.ll | 109 +-
.../Coroutines/coro-split-sink-lifetime-01.ll | 232 ++-
.../Coroutines/coro-split-sink-lifetime-02.ll | 114 +-
.../Coroutines/coro-split-tbaa-md.ll | 73 +-
.../Transforms/Coroutines/coro-zero-alloca.ll | 56 +-
20 files changed, 3158 insertions(+), 1184 deletions(-)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
index 979772ee2290b..eea25cef71dea 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
@@ -1,29 +1,11 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we can handle the case when both alloc function and
; the user body consume the same argument.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f_copy.Frame = type { ptr, ptr, i64, i1 }
; using copy of this (as it would happen under -O0)
define ptr @f_copy(i64 %this_arg) presplitcoroutine {
-; CHECK-LABEL: define ptr @f_copy(
-; CHECK-SAME: i64 [[THIS_ARG:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca i64, align 8
-; CHECK-NEXT: store i64 [[THIS_ARG]], ptr [[THIS_ADDR]], align 4
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_copy.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @myAlloc(i64 [[THIS_ARG]], i32 32)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f_copy.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_COPY_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f_copy.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[THIS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_COPY_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i64 [[THIS_ARG]], ptr [[THIS_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_COPY_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%this.addr = alloca i64
store i64 %this_arg, ptr %this.addr
@@ -69,3 +51,44 @@ declare noalias ptr @myAlloc(i64, i32)
declare double @print(double)
declare void @print2(i64)
declare void @free(ptr)
+; CHECK-LABEL: define ptr @f_copy(
+; CHECK-SAME: i64 [[THIS_ARG:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca i64, align 8
+; CHECK-NEXT: store i64 [[THIS_ARG]], ptr [[THIS_ADDR]], align 4
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_copy.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @myAlloc(i64 [[THIS_ARG]], i32 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f_copy.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_COPY_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f_copy.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[THIS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_COPY_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i64 [[THIS_ARG]], ptr [[THIS_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_COPY_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f_copy.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[THIS_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_COPY_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[THIS_RELOAD:%.*]] = load i64, ptr [[THIS_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print2(i64 [[THIS_RELOAD]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f_copy.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f_copy.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
index ea317f9b5bb54..6ffaaba189fdb 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
@@ -1,27 +1,11 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we can handle the case when both alloc function and
; the user body consume the same argument.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f_direct.Frame = type { ptr, ptr, i64, i1 }
; using this directly (as it would happen under -O2)
define ptr @f_direct(i64 %this) presplitcoroutine {
-; CHECK-LABEL: define ptr @f_direct(
-; CHECK-SAME: i64 [[THIS:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_direct.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @myAlloc(i64 [[THIS]], i32 32)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f_direct.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_DIRECT_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f_direct.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[THIS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_DIRECT_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_DIRECT_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -64,3 +48,42 @@ declare noalias ptr @myAlloc(i64, i32)
declare double @print(double)
declare void @print2(i64)
declare void @free(ptr)
+; CHECK-LABEL: define ptr @f_direct(
+; CHECK-SAME: i64 [[THIS:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_direct.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @myAlloc(i64 [[THIS]], i32 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f_direct.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_DIRECT_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f_direct.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[THIS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_DIRECT_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_DIRECT_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f_direct.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[THIS_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_DIRECT_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[THIS_RELOAD:%.*]] = load i64, ptr [[THIS_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print2(i64 [[THIS_RELOAD]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f_direct.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f_direct.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-07.ll b/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
index 83eba2458af84..a23966457c0ec 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
@@ -1,34 +1,10 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Tests that CoroSplit can succesfully determine allocas should live on the frame
; if their aliases are used across suspension points through PHINode.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i64, i64, ptr, i1 }
define ptr @f(i1 %n) presplitcoroutine {
-; CHECK-LABEL: define ptr @f(
-; CHECK-SAME: i1 [[N:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*]]:
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 48)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: br i1 [[N]], label %[[MERGE:.*]], label %[[MERGE_FROM_FLAG_FALSE:.*]]
-; CHECK: [[MERGE_FROM_FLAG_FALSE]]:
-; CHECK-NEXT: br label %[[MERGE]]
-; CHECK: [[MERGE]]:
-; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr [ [[Y_RELOAD_ADDR]], %[[MERGE_FROM_FLAG_FALSE]] ], [ [[X_RELOAD_ADDR]], %[[ENTRY]] ]
-; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
-; CHECK-NEXT: store ptr [[ALIAS_PHI]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
-; CHECK-NEXT: store i8 1, ptr [[ALIAS_PHI]], align 1
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%x = alloca i64
%y = alloca i64
@@ -85,5 +61,50 @@ declare void @free(ptr)
; Verify that both x and y are put in the frame.
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i1 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 48)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: br i1 [[N]], label %[[MERGE:.*]], label %[[MERGE_FROM_FLAG_FALSE:.*]]
+; CHECK: [[MERGE_FROM_FLAG_FALSE]]:
+; CHECK-NEXT: br label %[[MERGE]]
+; CHECK: [[MERGE]]:
+; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr [ [[Y_RELOAD_ADDR]], %[[MERGE_FROM_FLAG_FALSE]] ], [ [[X_RELOAD_ADDR]], %[[ENTRY]] ]
+; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store ptr [[ALIAS_PHI]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
+; CHECK-NEXT: store i8 1, ptr [[ALIAS_PHI]], align 1
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(48) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[ALIAS_PHI_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[ALIAS_PHI_RELOAD:%.*]] = load ptr, ptr [[ALIAS_PHI_RELOAD_ADDR]], align 8
+; CHECK-NEXT: call void @print(ptr [[ALIAS_PHI_RELOAD]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(48) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(48) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/Coroutines/coro-async.ll b/llvm/test/Transforms/Coroutines/coro-async.ll
index d1e5465784729..86b631604a2e5 100644
--- a/llvm/test/Transforms/Coroutines/coro-async.ll
+++ b/llvm/test/Transforms/Coroutines/coro-async.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; RUN: opt < %s -passes='default<O2>' -S | FileCheck --check-prefixes=CHECK %s
; RUN: opt < %s -O0 -S | FileCheck --check-prefixes=CHECK-O0 %s
target datalayout = "p:64:64:64"
@@ -39,16 +39,6 @@ declare void @my_other_async_function(ptr %async.ctxt)
; Function that implements the dispatch to the callee function.
define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) {
-; CHECK-LABEL: define swiftcc void @my_async_function.my_other_async_function_fp.apply(
-; CHECK-SAME: ptr readonly captures(none) [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @my_async_function.my_other_async_function_fp.apply(
-; CHECK-O0-SAME: ptr [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor)
ret void
}
@@ -57,36 +47,12 @@ declare void @some_user(i64)
declare void @some_may_write(ptr)
define ptr @__swift_async_resume_project_context(ptr %ctxt) {
-; CHECK-LABEL: define ptr @__swift_async_resume_project_context(
-; CHECK-SAME: ptr readonly captures(none) [[CTXT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
-; CHECK-NEXT: ret ptr [[RESUME_CTXT]]
-;
-; CHECK-O0-LABEL: define ptr @__swift_async_resume_project_context(
-; CHECK-O0-SAME: ptr [[CTXT:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
-; CHECK-O0-NEXT: ret ptr [[RESUME_CTXT]]
-;
entry:
%resume_ctxt = load ptr, ptr %ctxt, align 8
ret ptr %resume_ctxt
}
define ptr @resume_context_projection(ptr %ctxt) {
-; CHECK-LABEL: define ptr @resume_context_projection(
-; CHECK-SAME: ptr readonly captures(none) [[CTXT:%.*]]) local_unnamed_addr #[[ATTR0]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
-; CHECK-NEXT: ret ptr [[RESUME_CTXT]]
-;
-; CHECK-O0-LABEL: define ptr @resume_context_projection(
-; CHECK-O0-SAME: ptr [[CTXT:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
-; CHECK-O0-NEXT: ret ptr [[RESUME_CTXT]]
-;
entry:
%resume_ctxt = load ptr, ptr %ctxt, align 8
ret ptr %resume_ctxt
@@ -94,54 +60,6 @@ entry:
define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine !dbg !1 {
-; CHECK-LABEL: define swiftcc void @my_async_function(
-; CHECK-SAME: ptr swiftasync initializes((152, 160)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) !dbg [[DBG3:![0-9]+]] {
-; CHECK-NEXT: [[CORO_RETURN:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
-; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: store i64 1, ptr [[PROJ_2]], align 8
-; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR]])
-; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 160
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
-; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6:![0-9]+]]
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @my_async_function(
-; CHECK-O0-SAME: ptr swiftasync [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) !dbg [[DBG3:![0-9]+]] {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
-; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: [[VECTOR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 4
-; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[PROJ_1:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
-; CHECK-O0-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
-; CHECK-O0-NEXT: store i64 0, ptr [[PROJ_1]], align 8
-; CHECK-O0-NEXT: store i64 1, ptr [[PROJ_2]], align 8
-; CHECK-O0-NEXT: call void @some_may_write(ptr [[PROJ_1]])
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 5
-; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-O0-NEXT: [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr [[VECTOR]], align 16
-; CHECK-O0-NEXT: [[VECTOR_SPILL_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1, !dbg [[DBG6:![0-9]+]]
-; CHECK-O0-NEXT: store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_SPILL_ADDR]], align 16, !dbg [[DBG6]]
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
-; CHECK-O0-NEXT: ret void
-;
entry:
%tmp = alloca { i64, i64 }, align 8
%vector = alloca <4 x double>, align 16
@@ -189,31 +107,6 @@ entry:
}
define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) {
-; CHECK-LABEL: define void @my_async_function_pa(
-; CHECK-SAME: ptr initializes((152, 160)) [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 152
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 144
-; CHECK-NEXT: store ptr [[CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[PROJ_2_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 136
-; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR_I]], align 8
-; CHECK-NEXT: store i64 1, ptr [[PROJ_2_I]], align 8
-; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR_I]])
-; CHECK-NEXT: [[CALLEE_CONTEXT_I:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 160
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT_I]], ptr [[CALLEE_CONTEXT_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT_I]], i64 8
-; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I]], align 8
-; CHECK-NEXT: store ptr [[CTXT]], ptr [[CALLEE_CONTEXT_I]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT_I]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define void @my_async_function_pa(
-; CHECK-O0-SAME: ptr [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: call swiftcc void @my_async_function(ptr [[CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
call void @llvm.coro.async.size.replace(ptr @my_async_function_pa_fp, ptr @my_async_function_fp)
call swiftcc void @my_async_function(ptr %ctxt, ptr %task, ptr %actor)
ret void
@@ -235,43 +128,6 @@ define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) {
}>
define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) presplitcoroutine "frame-pointer"="all" !dbg !6 {
-; CHECK-LABEL: define swiftcc void @my_async_function2(
-; CHECK-SAME: ptr [[TASK:%.*]], ptr [[ACTOR:%.*]], ptr [[ASYNC_CTXT:%.*]]) #[[ATTR1:[0-9]+]] !dbg [[DBG9:![0-9]+]] {
-; CHECK-NEXT: [[CORO_RETURN:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-NEXT: store ptr [[TASK]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
-; CHECK-NEXT: store ptr @my_async_function2.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG10:![0-9]+]]
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @my_async_function2(
-; CHECK-O0-SAME: ptr [[TASK:%.*]], ptr [[ACTOR:%.*]], ptr [[ASYNC_CTXT:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG9:![0-9]+]] {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
-; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[TASK_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: store ptr [[TASK]], ptr [[TASK_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @my_async_function2.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG10:![0-9]+]]
-; CHECK-O0-NEXT: ret void
-;
entry:
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 2, ptr @my_async_function2_fp)
@@ -313,31 +169,6 @@ entry:
define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) {
-; CHECK-LABEL: define swiftcc void @top_level_caller(
-; CHECK-SAME: ptr initializes((152, 160)) [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 152
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 144
-; CHECK-NEXT: store ptr [[CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[PROJ_2_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 136
-; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR_I]], align 8
-; CHECK-NEXT: store i64 1, ptr [[PROJ_2_I]], align 8
-; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR_I]])
-; CHECK-NEXT: [[CALLEE_CONTEXT_I:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 160
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT_I]], ptr [[CALLEE_CONTEXT_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT_I]], i64 8
-; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I]], align 8
-; CHECK-NEXT: store ptr [[CTXT]], ptr [[CALLEE_CONTEXT_I]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT_I]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @top_level_caller(
-; CHECK-O0-SAME: ptr [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: call swiftcc void @my_async_function(ptr [[CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
%prepare = call ptr @llvm.coro.prepare.async(ptr @my_async_function)
call swiftcc void %prepare(ptr %ctxt, ptr %task, ptr %actor)
ret void
@@ -356,26 +187,6 @@ define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) {
define swiftcc void @dont_crash_on_cf_dispatch(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) {
-; CHECK-LABEL: define swiftcc void @dont_crash_on_cf_dispatch(
-; CHECK-SAME: ptr readonly captures(none) [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-NEXT: br i1 [[ISNULL]], label %[[COMMON_RET:.*]], label %[[IS_NOT_NULL:.*]]
-; CHECK: [[COMMON_RET]]:
-; CHECK-NEXT: ret void
-; CHECK: [[IS_NOT_NULL]]:
-; CHECK-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: br label %[[COMMON_RET]]
-;
-; CHECK-O0-LABEL: define swiftcc void @dont_crash_on_cf_dispatch(
-; CHECK-O0-SAME: ptr [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-O0-NEXT: br i1 [[ISNULL]], label %[[IS_NULL:.*]], label %[[IS_NOT_NULL:.*]]
-; CHECK-O0: [[IS_NULL]]:
-; CHECK-O0-NEXT: ret void
-; CHECK-O0: [[IS_NOT_NULL]]:
-; CHECK-O0-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
%isNull = icmp eq ptr %task, null
br i1 %isNull, label %is_null, label %is_not_null
@@ -388,49 +199,6 @@ is_not_null:
}
define swiftcc void @dont_crash_on_cf(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
-; CHECK-LABEL: define swiftcc void @dont_crash_on_cf(
-; CHECK-SAME: ptr initializes((136, 144)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: [[CORO_RETURN:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
-; CHECK-NEXT: store ptr @dont_crash_on_cf.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
-; CHECK: [[IS_NOT_NULL_I]]:
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
-; CHECK: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @dont_crash_on_cf(
-; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
-; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @dont_crash_on_cf.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-O0-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-O0-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
-; CHECK-O0: [[IS_NOT_NULL_I]]:
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
-; CHECK-O0: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
-; CHECK-O0-NEXT: ret void
-;
entry:
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
ptr @dont_crash_on_cf_fp)
@@ -464,64 +232,11 @@ entry:
}>
define swiftcc void @must_tail_call_return(ptr %async.ctxt, ptr %task, ptr %actor) {
-; CHECK-LABEL: define swiftcc void @must_tail_call_return(
-; CHECK-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @must_tail_call_return(
-; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
musttail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %task, ptr %actor)
ret void
}
define swiftcc void @multiple_coro_end_async(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
-; CHECK-LABEL: define swiftcc void @multiple_coro_end_async(
-; CHECK-SAME: ptr initializes((136, 144)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-NEXT: [[CORO_RETURN:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
-; CHECK-NEXT: store ptr @multiple_coro_end_async.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
-; CHECK: [[IS_NOT_NULL_I]]:
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
-; CHECK: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @multiple_coro_end_async(
-; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
-; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @multiple_coro_end_async.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-O0-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-O0-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
-; CHECK-O0: [[IS_NOT_NULL_I]]:
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
-; CHECK-O0: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
-; CHECK-O0-NEXT: ret void
-;
entry:
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
ptr @dont_crash_on_cf_fp)
@@ -567,50 +282,6 @@ is_not_equal:
}>
define swiftcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
-; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(
-; CHECK-SAME: ptr swiftasync initializes((152, 160)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-NEXT: [[CORO_RETURN:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
-; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: store i64 1, ptr [[PROJ_2]], align 8
-; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR]])
-; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 160
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
-; CHECK-NEXT: store ptr @polymorphic_suspend_return.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @polymorphic_suspend_return(
-; CHECK-O0-SAME: ptr swiftasync [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
-; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[PROJ_1:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
-; CHECK-O0-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
-; CHECK-O0-NEXT: store i64 0, ptr [[PROJ_1]], align 8
-; CHECK-O0-NEXT: store i64 1, ptr [[PROJ_2]], align 8
-; CHECK-O0-NEXT: call void @some_may_write(ptr [[PROJ_1]])
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @polymorphic_suspend_return.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
entry:
%tmp = alloca { i64, i64 }, align 8
%proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0
@@ -668,20 +339,6 @@ entry:
}>
define swiftcc void @no_coro_suspend(ptr %async.ctx) presplitcoroutine {
-; CHECK-LABEL: define swiftcc void @no_coro_suspend(
-; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
-; CHECK-NEXT: [[COROEND:.*:]]
-; CHECK-NEXT: [[SOME_ALLOCA:%.*]] = alloca i64, align 8
-; CHECK-NEXT: call void @some_may_write(ptr nonnull [[SOME_ALLOCA]])
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @no_coro_suspend(
-; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[SOME_ALLOCA:%.*]] = alloca i64, align 8
-; CHECK-O0-NEXT: call void @some_may_write(ptr [[SOME_ALLOCA]])
-; CHECK-O0-NEXT: ret void
-;
entry:
%some_alloca = alloca i64
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
@@ -706,22 +363,6 @@ entry:
declare void @do_with_swifterror(ptr swifterror)
define swiftcc void @no_coro_suspend_swifterror(ptr %async.ctx) presplitcoroutine {
-; CHECK-LABEL: define swiftcc void @no_coro_suspend_swifterror(
-; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
-; CHECK-NEXT: [[COROEND:.*:]]
-; CHECK-NEXT: [[SOME_ALLOCA:%.*]] = alloca swifterror ptr, align 8
-; CHECK-NEXT: store ptr null, ptr [[SOME_ALLOCA]], align 8
-; CHECK-NEXT: call void @do_with_swifterror(ptr nonnull swifterror [[SOME_ALLOCA]])
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @no_coro_suspend_swifterror(
-; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[SOME_ALLOCA:%.*]] = alloca swifterror ptr, align 8
-; CHECK-O0-NEXT: store ptr null, ptr [[SOME_ALLOCA]], align 8
-; CHECK-O0-NEXT: call void @do_with_swifterror(ptr swifterror [[SOME_ALLOCA]])
-; CHECK-O0-NEXT: ret void
-;
entry:
%some_alloca = alloca swifterror ptr
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
@@ -748,20 +389,6 @@ declare void @crash()
declare void @use(ptr)
define swiftcc void @undefined_coro_async_resume(ptr %async.ctx) presplitcoroutine {
-; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume(
-; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
-; CHECK-NEXT: [[COROEND:.*:]]
-; CHECK-NEXT: tail call void @use(ptr null)
-; CHECK-NEXT: tail call void @crash()
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swiftcc void @undefined_coro_async_resume(
-; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: call void @use(ptr null)
-; CHECK-O0-NEXT: call void @crash()
-; CHECK-O0-NEXT: ret void
-;
entry:
%id = call token @llvm.coro.id.async(i32 24, i32 16, i32 0, ptr @undefined_coro_async_resume_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
@@ -777,26 +404,6 @@ entry:
i64 ptrtoint (ptr @simpleFuncTu to i64)) to i32), i32 16 }>
define swifttailcc void @simpleFunc(ptr swiftasync %0) presplitcoroutine {
-; CHECK-LABEL: define swifttailcc void @simpleFunc(
-; CHECK-SAME: ptr swiftasync [[TMP0:%.*]]) {
-; CHECK-NEXT: [[AFTERMUSTTAILCALL_BEFORE_COROEND:.*:]]
-; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 8
-; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
-; CHECK-NEXT: musttail call swifttailcc void [[TMP2]](ptr swiftasync [[TMP0]])
-; CHECK-NEXT: ret void
-;
-; CHECK-O0-LABEL: define swifttailcc void @simpleFunc(
-; CHECK-O0-SAME: ptr swiftasync [[TMP0:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[TMP1:%.*]] = alloca ptr, align 8
-; CHECK-O0-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8
-; CHECK-O0-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
-; CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds <{ ptr, ptr }>, ptr [[TMP2]], i32 0, i32 1
-; CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8
-; CHECK-O0-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP1]], align 8
-; CHECK-O0-NEXT: musttail call swifttailcc void [[TMP4]](ptr swiftasync [[TMP5]])
-; CHECK-O0-NEXT: ret void
-;
entry:
%1 = alloca ptr, align 8
%2 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @simpleFuncTu)
@@ -852,6 +459,676 @@ declare ptr @hide(ptr)
!7 = !DILexicalBlockFile(scope: !6, file: !8, discriminator: 0)
!8 = !DIFile(filename: "/tmp/fake.cpp", directory: "/")
!9 = !DILocation(line: 2, column: 0, scope: !7)
+; CHECK-LABEL: define swiftcc void @my_async_function.my_other_async_function_fp.apply(
+; CHECK-SAME: ptr readonly captures(none) [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define ptr @__swift_async_resume_project_context(
+; CHECK-SAME: ptr readonly captures(none) [[CTXT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
+; CHECK-NEXT: ret ptr [[RESUME_CTXT]]
+;
+;
+; CHECK-LABEL: define ptr @resume_context_projection(
+; CHECK-SAME: ptr readonly captures(none) [[CTXT:%.*]]) local_unnamed_addr #[[ATTR0]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
+; CHECK-NEXT: ret ptr [[RESUME_CTXT]]
+;
+;
+; CHECK-LABEL: define swiftcc void @my_async_function(
+; CHECK-SAME: ptr swiftasync initializes((152, 160)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) !dbg [[DBG3:![0-9]+]] {
+; CHECK-NEXT: [[CORO_RETURN:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
+; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: store i64 1, ptr [[PROJ_2]], align 8
+; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR]])
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 160
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
+; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6:![0-9]+]]
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal swiftcc void @my_async_functionTQ0_(
+; CHECK-SAME: ptr readonly swiftasync captures(none) [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr readnone captures(none) [[TMP2:%.*]]) !dbg [[DBG7:![0-9]+]] {
+; CHECK-NEXT: [[ENTRYRESUME_0:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8, !dbg [[DBG8:![0-9]+]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 128
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 160
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 152
+; CHECK-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[PROJ_21:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 136
+; CHECK-NEXT: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CONTEXT_RELOAD]])
+; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: tail call void @some_user(i64 [[VAL]])
+; CHECK-NEXT: [[VAL_2:%.*]] = load i64, ptr [[PROJ_21]], align 8
+; CHECK-NEXT: tail call void @some_user(i64 [[VAL_2]])
+; CHECK-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP1]], ptr [[ACTOR_RELOAD]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define void @my_async_function_pa(
+; CHECK-SAME: ptr initializes((152, 160)) [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 152
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 144
+; CHECK-NEXT: store ptr [[CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[PROJ_2_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 136
+; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR_I]], align 8
+; CHECK-NEXT: store i64 1, ptr [[PROJ_2_I]], align 8
+; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR_I]])
+; CHECK-NEXT: [[CALLEE_CONTEXT_I:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 160
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT_I]], ptr [[CALLEE_CONTEXT_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT_I]], i64 8
+; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I]], align 8
+; CHECK-NEXT: store ptr [[CTXT]], ptr [[CALLEE_CONTEXT_I]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT_I]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define swiftcc void @my_async_function2(
+; CHECK-SAME: ptr [[TASK:%.*]], ptr [[ACTOR:%.*]], ptr [[ASYNC_CTXT:%.*]]) #[[ATTR1:[0-9]+]] !dbg [[DBG9:![0-9]+]] {
+; CHECK-NEXT: [[CORO_RETURN:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-NEXT: store ptr [[TASK]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
+; CHECK-NEXT: store ptr @my_async_function2.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG10:![0-9]+]]
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.0(
+; CHECK-SAME: ptr [[TMP0:%.*]], ptr readnone captures(none) [[TMP1:%.*]], ptr readonly captures(none) [[TMP2:%.*]]) #[[ATTR1]] !dbg [[DBG13:![0-9]+]] {
+; CHECK-NEXT: [[ENTRYRESUME_0:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP2]], align 8, !dbg [[DBG14:![0-9]+]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 128
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR10:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 152
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD11:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR10]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD_ADDR4:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD5:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR4]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR3:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT_RELOAD11]], i64 8
+; CHECK-NEXT: [[CONTINUATION_TASK_ARG_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 160
+; CHECK-NEXT: store ptr [[TMP0]], ptr [[CONTINUATION_TASK_ARG_SPILL_ADDR]], align 8
+; CHECK-NEXT: store ptr @my_async_function2.resume.1, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR3]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT_RELOAD5]], ptr [[CALLEE_CONTEXT_RELOAD11]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD9:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR10]], align 8
+; CHECK-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 136
+; CHECK-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[TASK_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT_RELOAD9]], ptr [[TASK_RELOAD]], ptr [[ACTOR_RELOAD]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.1(
+; CHECK-SAME: ptr readonly captures(none) [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr readnone captures(none) [[TMP2:%.*]]) #[[ATTR1]] !dbg [[DBG16:![0-9]+]] {
+; CHECK-NEXT: [[ENTRYRESUME_1:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
+; CHECK-NEXT: [[CONTINUATION_TASK_ARG_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 160
+; CHECK-NEXT: [[CONTINUATION_TASK_ARG_RELOAD:%.*]] = load ptr, ptr [[CONTINUATION_TASK_ARG_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR6:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 152
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD7:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR6]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
+; CHECK-NEXT: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CONTEXT_RELOAD7]])
+; CHECK-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[CONTINUATION_TASK_ARG_RELOAD]], ptr [[TMP1]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define swiftcc void @top_level_caller(
+; CHECK-SAME: ptr initializes((152, 160)) [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 152
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 144
+; CHECK-NEXT: store ptr [[CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[PROJ_2_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 136
+; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR_I]], align 8
+; CHECK-NEXT: store i64 1, ptr [[PROJ_2_I]], align 8
+; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR_I]])
+; CHECK-NEXT: [[CALLEE_CONTEXT_I:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 160
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT_I]], ptr [[CALLEE_CONTEXT_SPILL_ADDR_I]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT_I]], i64 8
+; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I]], align 8
+; CHECK-NEXT: store ptr [[CTXT]], ptr [[CALLEE_CONTEXT_I]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT_I]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define swiftcc void @dont_crash_on_cf_dispatch(
+; CHECK-SAME: ptr readonly captures(none) [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-NEXT: br i1 [[ISNULL]], label %[[COMMON_RET:.*]], label %[[IS_NOT_NULL:.*]]
+; CHECK: [[COMMON_RET]]:
+; CHECK-NEXT: ret void
+; CHECK: [[IS_NOT_NULL]]:
+; CHECK-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: br label %[[COMMON_RET]]
+;
+;
+; CHECK-LABEL: define swiftcc void @dont_crash_on_cf(
+; CHECK-SAME: ptr initializes((136, 144)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: [[CORO_RETURN:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
+; CHECK-NEXT: store ptr @dont_crash_on_cf.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
+; CHECK: [[IS_NOT_NULL_I]]:
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
+; CHECK: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal swiftcc void @dont_crash_on_cf.resume.0(
+; CHECK-SAME: ptr readonly captures(none) [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr readnone captures(none) [[TMP2:%.*]]) {
+; CHECK-NEXT: [[ENTRYRESUME_0:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 128
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 136
+; CHECK-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CONTEXT_RELOAD]])
+; CHECK-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP1]], ptr [[ACTOR_RELOAD]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define swiftcc void @must_tail_call_return(
+; CHECK-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
+; CHECK-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define swiftcc void @multiple_coro_end_async(
+; CHECK-SAME: ptr initializes((136, 144)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-NEXT: [[CORO_RETURN:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
+; CHECK-NEXT: store ptr @multiple_coro_end_async.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
+; CHECK: [[IS_NOT_NULL_I]]:
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
+; CHECK: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal swiftcc void @multiple_coro_end_async.resume.0(
+; CHECK-SAME: ptr readonly captures(none) [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr readnone captures(none) [[TMP2:%.*]]) {
+; CHECK-NEXT: [[ENTRYRESUME_0:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 128
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
+; CHECK-NEXT: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CONTEXT_RELOAD]])
+; CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[TMP1]], null
+; CHECK-NEXT: br i1 [[EQ]], label %[[COROEND:.*]], label %[[AFTERMUSTTAILCALL_BEFORE_COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 136
+; CHECK-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD4:%.*]] = load ptr, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD4]], ptr null, ptr [[ACTOR_RELOAD]])
+; CHECK-NEXT: ret void
+; CHECK: [[AFTERMUSTTAILCALL_BEFORE_COROEND]]:
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr nonnull [[TMP1]], ptr null)
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(
+; CHECK-SAME: ptr swiftasync initializes((152, 160)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-NEXT: [[CORO_RETURN:.*:]]
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
+; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
+; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
+; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: store i64 1, ptr [[PROJ_2]], align 8
+; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR]])
+; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 160
+; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
+; CHECK-NEXT: store ptr @polymorphic_suspend_return.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(
+; CHECK-SAME: ptr readonly swiftasync captures(none) [[TMP0:%.*]], ptr readnone swiftself captures(none) [[TMP1:%.*]], ptr readnone captures(none) [[TMP2:%.*]], ptr [[TMP3:%.*]]) {
+; CHECK-NEXT: [[ENTRYRESUME_0:.*:]]
+; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 128
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 160
+; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 152
+; CHECK-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
+; CHECK-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[PROJ_21:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 136
+; CHECK-NEXT: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CONTEXT_RELOAD]])
+; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
+; CHECK-NEXT: tail call void @some_user(i64 [[VAL]])
+; CHECK-NEXT: [[VAL_2:%.*]] = load i64, ptr [[PROJ_21]], align 8
+; CHECK-NEXT: tail call void @some_user(i64 [[VAL_2]])
+; CHECK-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP3]], ptr [[ACTOR_RELOAD]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define swiftcc void @no_coro_suspend(
+; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
+; CHECK-NEXT: [[COROEND:.*:]]
+; CHECK-NEXT: [[SOME_ALLOCA:%.*]] = alloca i64, align 8
+; CHECK-NEXT: call void @some_may_write(ptr nonnull [[SOME_ALLOCA]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define swiftcc void @no_coro_suspend_swifterror(
+; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
+; CHECK-NEXT: [[COROEND:.*:]]
+; CHECK-NEXT: [[SOME_ALLOCA:%.*]] = alloca swifterror ptr, align 8
+; CHECK-NEXT: store ptr null, ptr [[SOME_ALLOCA]], align 8
+; CHECK-NEXT: call void @do_with_swifterror(ptr nonnull swifterror [[SOME_ALLOCA]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume(
+; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
+; CHECK-NEXT: [[COROEND:.*:]]
+; CHECK-NEXT: tail call void @use(ptr null)
+; CHECK-NEXT: tail call void @crash()
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define swifttailcc void @simpleFunc(
+; CHECK-SAME: ptr swiftasync [[TMP0:%.*]]) {
+; CHECK-NEXT: [[AFTERMUSTTAILCALL_BEFORE_COROEND:.*:]]
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 8
+; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-NEXT: musttail call swifttailcc void [[TMP2]](ptr swiftasync [[TMP0]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @my_async_function.my_other_async_function_fp.apply(
+; CHECK-O0-SAME: ptr [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define ptr @__swift_async_resume_project_context(
+; CHECK-O0-SAME: ptr [[CTXT:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
+; CHECK-O0-NEXT: ret ptr [[RESUME_CTXT]]
+;
+;
+; CHECK-O0-LABEL: define ptr @resume_context_projection(
+; CHECK-O0-SAME: ptr [[CTXT:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
+; CHECK-O0-NEXT: ret ptr [[RESUME_CTXT]]
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @my_async_function(
+; CHECK-O0-SAME: ptr swiftasync [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) !dbg [[DBG3:![0-9]+]] {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
+; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: [[VECTOR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 4
+; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[PROJ_1:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
+; CHECK-O0-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
+; CHECK-O0-NEXT: store i64 0, ptr [[PROJ_1]], align 8
+; CHECK-O0-NEXT: store i64 1, ptr [[PROJ_2]], align 8
+; CHECK-O0-NEXT: call void @some_may_write(ptr [[PROJ_1]])
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 5
+; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-O0-NEXT: [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr [[VECTOR]], align 16
+; CHECK-O0-NEXT: [[VECTOR_SPILL_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1, !dbg [[DBG6:![0-9]+]]
+; CHECK-O0-NEXT: store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_SPILL_ADDR]], align 16, !dbg [[DBG6]]
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define internal swiftcc void @my_async_functionTQ0_(
+; CHECK-O0-SAME: ptr swiftasync [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) !dbg [[DBG7:![0-9]+]] {
+; CHECK-O0-NEXT: [[ENTRYRESUME_0:.*:]]
+; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8, !dbg [[DBG8:![0-9]+]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
+; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: [[VECTOR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: [[VECTOR_SPILL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: [[VECTOR_SPILL_RELOAD:%.*]] = load <4 x double>, ptr [[VECTOR_SPILL_RELOAD_ADDR]], align 16
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 5
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 4
+; CHECK-O0-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[PROJ_22:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
+; CHECK-O0-NEXT: [[PROJ_11:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
+; CHECK-O0-NEXT: call void @llvm.coro.async.context.dealloc(ptr [[CALLEE_CONTEXT_RELOAD]])
+; CHECK-O0-NEXT: [[VAL:%.*]] = load i64, ptr [[PROJ_11]], align 4
+; CHECK-O0-NEXT: call void @some_user(i64 [[VAL]])
+; CHECK-O0-NEXT: [[VAL_2:%.*]] = load i64, ptr [[PROJ_22]], align 4
+; CHECK-O0-NEXT: call void @some_user(i64 [[VAL_2]])
+; CHECK-O0-NEXT: store <4 x double> [[VECTOR_SPILL_RELOAD]], ptr [[VECTOR]], align 16
+; CHECK-O0-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP1]], ptr [[ACTOR_RELOAD]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define void @my_async_function_pa(
+; CHECK-O0-SAME: ptr [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: call swiftcc void @my_async_function(ptr [[CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @my_async_function2(
+; CHECK-O0-SAME: ptr [[TASK:%.*]], ptr [[ACTOR:%.*]], ptr [[ASYNC_CTXT:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG9:![0-9]+]] {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
+; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[TASK_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: store ptr [[TASK]], ptr [[TASK_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @my_async_function2.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG10:![0-9]+]]
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define internal swiftcc void @my_async_function2.resume.0(
+; CHECK-O0-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) #[[ATTR0]] !dbg [[DBG13:![0-9]+]] {
+; CHECK-O0-NEXT: [[ENTRYRESUME_0:.*:]]
+; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP2]], align 8, !dbg [[DBG14:![0-9]+]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR7:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD8:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR7]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR3:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD4:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR3]], align 8
+; CHECK-O0-NEXT: [[CONTINUATION_TASK_ARG_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 4
+; CHECK-O0-NEXT: store ptr [[TMP0]], ptr [[CONTINUATION_TASK_ARG_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_1:%.*]] = getelementptr inbounds [[ASYNC_CTXT:%.*]], ptr [[CALLEE_CONTEXT_RELOAD8]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @my_async_function2.resume.1, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_1]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT_RELOAD4]], ptr [[CALLEE_CONTEXT_RELOAD8]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR5:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD6:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR5]], align 8
+; CHECK-O0-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[TASK_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: [[TASK_RELOAD:%.*]] = load ptr, ptr [[TASK_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT_RELOAD6]], ptr [[TASK_RELOAD]], ptr [[ACTOR_RELOAD]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define internal swiftcc void @my_async_function2.resume.1(
+; CHECK-O0-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) #[[ATTR0]] !dbg [[DBG16:![0-9]+]] {
+; CHECK-O0-NEXT: [[ENTRYRESUME_1:.*:]]
+; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
+; CHECK-O0-NEXT: [[CONTINUATION_TASK_ARG_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 4
+; CHECK-O0-NEXT: [[CONTINUATION_TASK_ARG_RELOAD:%.*]] = load ptr, ptr [[CONTINUATION_TASK_ARG_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: call void @llvm.coro.async.context.dealloc(ptr [[CALLEE_CONTEXT_RELOAD]])
+; CHECK-O0-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[CONTINUATION_TASK_ARG_RELOAD]], ptr [[TMP1]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @top_level_caller(
+; CHECK-O0-SAME: ptr [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: call swiftcc void @my_async_function(ptr [[CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @dont_crash_on_cf_dispatch(
+; CHECK-O0-SAME: ptr [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-O0-NEXT: br i1 [[ISNULL]], label %[[IS_NULL:.*]], label %[[IS_NOT_NULL:.*]]
+; CHECK-O0: [[IS_NULL]]:
+; CHECK-O0-NEXT: ret void
+; CHECK-O0: [[IS_NOT_NULL]]:
+; CHECK-O0-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @dont_crash_on_cf(
+; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
+; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @dont_crash_on_cf.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-O0-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-O0-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
+; CHECK-O0: [[IS_NOT_NULL_I]]:
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
+; CHECK-O0: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define internal swiftcc void @dont_crash_on_cf.resume.0(
+; CHECK-O0-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRYRESUME_0:.*:]]
+; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: call void @llvm.coro.async.context.dealloc(ptr [[CALLEE_CONTEXT_RELOAD]])
+; CHECK-O0-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP1]], ptr [[ACTOR_RELOAD]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @must_tail_call_return(
+; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @multiple_coro_end_async(
+; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
+; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @multiple_coro_end_async.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-O0-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
+; CHECK-O0-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
+; CHECK-O0: [[IS_NOT_NULL_I]]:
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
+; CHECK-O0: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define internal swiftcc void @multiple_coro_end_async.resume.0(
+; CHECK-O0-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRYRESUME_0:.*:]]
+; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: call void @llvm.coro.async.context.dealloc(ptr [[CALLEE_CONTEXT_RELOAD]])
+; CHECK-O0-NEXT: [[EQ:%.*]] = icmp eq ptr [[TMP1]], null
+; CHECK-O0-NEXT: br i1 [[EQ]], label %[[IS_EQUAL:.*]], label %[[MUSTTAILCALL_BEFORE_COROEND:.*]]
+; CHECK-O0: [[IS_EQUAL]]:
+; CHECK-O0-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR3:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD4:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR3]], align 8
+; CHECK-O0-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD4]], ptr [[TMP1]], ptr [[ACTOR_RELOAD]])
+; CHECK-O0-NEXT: ret void
+; CHECK-O0: [[MUSTTAILCALL_BEFORE_COROEND]]:
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP1]], ptr null)
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @polymorphic_suspend_return(
+; CHECK-O0-SAME: ptr swiftasync [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
+; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[PROJ_1:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
+; CHECK-O0-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
+; CHECK-O0-NEXT: store i64 0, ptr [[PROJ_1]], align 8
+; CHECK-O0-NEXT: store i64 1, ptr [[PROJ_2]], align 8
+; CHECK-O0-NEXT: call void @some_may_write(ptr [[PROJ_1]])
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
+; CHECK-O0-NEXT: store ptr @polymorphic_suspend_return.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
+; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
+; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(
+; CHECK-O0-SAME: ptr swiftasync [[TMP0:%.*]], ptr swiftself [[TMP1:%.*]], ptr [[TMP2:%.*]], ptr [[TMP3:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRYRESUME_0:.*:]]
+; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
+; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
+; CHECK-O0-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
+; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
+; CHECK-O0-NEXT: [[PROJ_22:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
+; CHECK-O0-NEXT: [[PROJ_11:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
+; CHECK-O0-NEXT: call void @llvm.coro.async.context.dealloc(ptr [[CALLEE_CONTEXT_RELOAD]])
+; CHECK-O0-NEXT: [[VAL:%.*]] = load i64, ptr [[PROJ_11]], align 4
+; CHECK-O0-NEXT: call void @some_user(i64 [[VAL]])
+; CHECK-O0-NEXT: [[VAL_2:%.*]] = load i64, ptr [[PROJ_22]], align 4
+; CHECK-O0-NEXT: call void @some_user(i64 [[VAL_2]])
+; CHECK-O0-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP3]], ptr [[ACTOR_RELOAD]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @no_coro_suspend(
+; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[SOME_ALLOCA:%.*]] = alloca i64, align 8
+; CHECK-O0-NEXT: call void @some_may_write(ptr [[SOME_ALLOCA]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @no_coro_suspend_swifterror(
+; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[SOME_ALLOCA:%.*]] = alloca swifterror ptr, align 8
+; CHECK-O0-NEXT: store ptr null, ptr [[SOME_ALLOCA]], align 8
+; CHECK-O0-NEXT: call void @do_with_swifterror(ptr swifterror [[SOME_ALLOCA]])
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swiftcc void @undefined_coro_async_resume(
+; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: call void @use(ptr null)
+; CHECK-O0-NEXT: call void @crash()
+; CHECK-O0-NEXT: ret void
+;
+;
+; CHECK-O0-LABEL: define swifttailcc void @simpleFunc(
+; CHECK-O0-SAME: ptr swiftasync [[TMP0:%.*]]) {
+; CHECK-O0-NEXT: [[ENTRY:.*:]]
+; CHECK-O0-NEXT: [[TMP1:%.*]] = alloca ptr, align 8
+; CHECK-O0-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8
+; CHECK-O0-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds <{ ptr, ptr }>, ptr [[TMP2]], i32 0, i32 1
+; CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8
+; CHECK-O0-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP1]], align 8
+; CHECK-O0-NEXT: musttail call swifttailcc void [[TMP4]](ptr swiftasync [[TMP5]])
+; CHECK-O0-NEXT: ret void
+;
;.
; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_Swift, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
; CHECK: [[META1]] = !DIFile(filename: "{{.*}}1.swift", directory: {{.*}})
@@ -859,10 +1136,16 @@ declare ptr @hide(ptr)
; CHECK: [[META4]] = !DISubroutineType(types: [[META5:![0-9]+]])
; CHECK: [[META5]] = !{}
; CHECK: [[DBG6]] = !DILocation(line: 2, scope: [[DBG3]])
+; CHECK: [[DBG7]] = distinct !DISubprogram(name: "my_async_function", linkageName: "my_async_functionTQ0_", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 2, spFlags: DISPFlagDefinition, unit: [[META0]])
+; CHECK: [[DBG8]] = !DILocation(line: 2, scope: [[DBG7]])
; CHECK: [[DBG9]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
; CHECK: [[DBG10]] = !DILocation(line: 2, scope: [[META11:![0-9]+]])
; CHECK: [[META11]] = !DILexicalBlockFile(scope: [[DBG9]], file: [[META12:![0-9]+]], discriminator: 0)
; CHECK: [[META12]] = !DIFile(filename: "{{.*}}fake.cpp", directory: {{.*}})
+; CHECK: [[DBG13]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2.resume.0", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
+; CHECK: [[DBG14]] = !DILocation(line: 2, scope: [[META15:![0-9]+]])
+; CHECK: [[META15]] = !DILexicalBlockFile(scope: [[DBG13]], file: [[META12]], discriminator: 0)
+; CHECK: [[DBG16]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2.resume.1", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
;.
; CHECK-O0: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_Swift, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
; CHECK-O0: [[META1]] = !DIFile(filename: "{{.*}}1.swift", directory: {{.*}})
@@ -870,8 +1153,14 @@ declare ptr @hide(ptr)
; CHECK-O0: [[META4]] = !DISubroutineType(types: [[META5:![0-9]+]])
; CHECK-O0: [[META5]] = !{}
; CHECK-O0: [[DBG6]] = !DILocation(line: 2, scope: [[DBG3]])
+; CHECK-O0: [[DBG7]] = distinct !DISubprogram(name: "my_async_function", linkageName: "my_async_functionTQ0_", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 2, spFlags: DISPFlagDefinition, unit: [[META0]])
+; CHECK-O0: [[DBG8]] = !DILocation(line: 2, scope: [[DBG7]])
; CHECK-O0: [[DBG9]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
; CHECK-O0: [[DBG10]] = !DILocation(line: 2, scope: [[META11:![0-9]+]])
; CHECK-O0: [[META11]] = !DILexicalBlockFile(scope: [[DBG9]], file: [[META12:![0-9]+]], discriminator: 0)
; CHECK-O0: [[META12]] = !DIFile(filename: "{{.*}}fake.cpp", directory: {{.*}})
+; CHECK-O0: [[DBG13]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2.resume.0", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
+; CHECK-O0: [[DBG14]] = !DILocation(line: 2, scope: [[META15:![0-9]+]])
+; CHECK-O0: [[META15]] = !DILexicalBlockFile(scope: [[DBG13]], file: [[META12]], discriminator: 0)
+; CHECK-O0: [[DBG16]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2.resume.1", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
;.
diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
index 487061d217f34..6db68c3b32edb 100644
--- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
+++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
@@ -1,25 +1,10 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Tests that invoke <type> @llvm.coro.await.suspend lowers to invoke @helper
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),simplifycfg' -S | FileCheck %s
%Awaiter = type {}
define void @f() presplitcoroutine personality i32 0 {
-; CHECK-LABEL: define void @f() personality i32 0 {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[AWAITER:%.*]] = alloca [[AWAITER:%.*]], align 8
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR12]], align 1
-; CHECK-NEXT: ret void
-;
entry:
%awaiter = alloca %Awaiter
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -120,3 +105,91 @@ declare void @__cxa_end_catch()
declare noalias ptr @malloc(i32)
declare void @free(ptr)
+; CHECK-LABEL: define void @f() personality i32 0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[AWAITER:%.*]] = alloca [[AWAITER:%.*]], align 8
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR12]], align 1
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_RESUME:.*]]:
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i2 0, label %[[COROSAVE1:.*]]
+; CHECK-NEXT: i2 1, label %[[AFTERCOROSUSPEND3:.*]]
+; CHECK-NEXT: i2 -2, label %[[AFTERCOROSUSPEND7:.*]]
+; CHECK-NEXT: i2 -1, label %[[CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR13]], align 1
+; CHECK-NEXT: invoke void @await_suspend_wrapper_void(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
+; CHECK-NEXT: to label %[[AFTERCOROSUSPEND3]] unwind label %[[PAD:.*]]
+; CHECK: [[AFTERCOROSUSPEND3]]:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i8 [ -1, %[[COROSAVE1]] ], [ 0, %[[ENTRY_RESUME]] ]
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[COND]], label %[[COROSAVE4:.*]], label %[[COROEND:.*]]
+; CHECK: [[COROSAVE4]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i2 -2, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: [[TMP1:%.*]] = invoke i1 @await_suspend_wrapper_bool(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
+; CHECK-NEXT: to label %[[STEP1_CONTINUE:.*]] unwind label %[[PAD]]
+; CHECK: [[STEP1_CONTINUE]]:
+; CHECK-NEXT: br i1 [[TMP1]], label %[[AFTERCOROSUSPEND7]], label %[[COROSAVE8:.*]]
+; CHECK: [[AFTERCOROSUSPEND7]]:
+; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ -1, %[[STEP1_CONTINUE]] ], [ 0, %[[ENTRY_RESUME]] ]
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i8 [[TMP2]], 0
+; CHECK-NEXT: br i1 [[COND1]], label %[[COROSAVE8]], label %[[COROEND]]
+; CHECK: [[COROSAVE8]]:
+; CHECK-NEXT: [[INDEX_ADDR15:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i2 -1, ptr [[INDEX_ADDR15]], align 1
+; CHECK-NEXT: [[TMP3:%.*]] = invoke ptr @await_suspend_wrapper_handle(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
+; CHECK-NEXT: to label %[[STEP2_CONTINUE:.*]] unwind label %[[PAD]]
+; CHECK: [[STEP2_CONTINUE]]:
+; CHECK-NEXT: [[TMP4:%.*]] = call ptr @llvm.coro.subfn.addr(ptr [[TMP3]], i8 0)
+; CHECK-NEXT: musttail call fastcc void [[TMP4]](ptr [[TMP3]])
+; CHECK-NEXT: ret void
+; CHECK: [[PAD]]:
+; CHECK-NEXT: [[LP:%.*]] = landingpad { ptr, i32 }
+; CHECK-NEXT: catch ptr null
+; CHECK-NEXT: [[EXN:%.*]] = extractvalue { ptr, i32 } [[LP]], 0
+; CHECK-NEXT: [[TMP5:%.*]] = call ptr @__cxa_begin_catch(ptr [[EXN]])
+; CHECK-NEXT: call void @__cxa_end_catch()
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: br label %[[COROEND]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
index 25c7a81d26dc0..bc7064e787fac 100644
--- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
+++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
@@ -1,25 +1,10 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Tests lowerings of different versions of coro.await.suspend
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split),simplifycfg' -S | FileCheck %s
%Awaiter = type {}
define void @f() presplitcoroutine {
-; CHECK-LABEL: define void @f() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[AWAITER:%.*]] = alloca [[AWAITER:%.*]], align 8
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR12]], align 1
-; CHECK-NEXT: ret void
-;
entry:
%awaiter = alloca %Awaiter
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -97,3 +82,80 @@ declare void @llvm.coro.end(ptr, i1, token)
declare noalias ptr @malloc(i32)
declare void @free(ptr)
+; CHECK-LABEL: define void @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[AWAITER:%.*]] = alloca [[AWAITER:%.*]], align 8
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR12]], align 1
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*]]:
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i2 0, label %[[COROSAVE1:.*]]
+; CHECK-NEXT: i2 1, label %[[AFTERCOROSUSPEND3:.*]]
+; CHECK-NEXT: i2 -2, label %[[AFTERCOROSUSPEND7:.*]]
+; CHECK-NEXT: i2 -1, label %[[CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR13]], align 1
+; CHECK-NEXT: call void @await_suspend_wrapper_void(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND3]]
+; CHECK: [[AFTERCOROSUSPEND3]]:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i8 [ -1, %[[COROSAVE1]] ], [ 0, %[[ENTRY_RESUME]] ]
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[COND]], label %[[COROSAVE4:.*]], label %[[COROEND:.*]]
+; CHECK: [[COROSAVE4]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i2 -2, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: [[TMP1:%.*]] = call i1 @await_suspend_wrapper_bool(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
+; CHECK-NEXT: br i1 [[TMP1]], label %[[AFTERCOROSUSPEND7]], label %[[COROSAVE8:.*]]
+; CHECK: [[AFTERCOROSUSPEND7]]:
+; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ -1, %[[COROSAVE4]] ], [ 0, %[[ENTRY_RESUME]] ]
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i8 [[TMP2]], 0
+; CHECK-NEXT: br i1 [[COND1]], label %[[COROSAVE8]], label %[[COROEND]]
+; CHECK: [[COROSAVE8]]:
+; CHECK-NEXT: [[INDEX_ADDR15:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i2 -1, ptr [[INDEX_ADDR15]], align 1
+; CHECK-NEXT: [[TMP3:%.*]] = call ptr @await_suspend_wrapper_handle(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
+; CHECK-NEXT: [[TMP4:%.*]] = call ptr @llvm.coro.subfn.addr(ptr [[TMP3]], i8 0)
+; CHECK-NEXT: musttail call fastcc void [[TMP4]](ptr [[TMP3]])
+; CHECK-NEXT: ret void
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: br label %[[COROEND]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll b/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
index 21b9c63f814dd..b4a4506a9da6b 100644
--- a/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
@@ -1,10 +1,8 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s
; Checks whether the dbg.declare for `__coro_frame` are created.
-;
-;
%promise_type = type { i32, i32, double }
@@ -23,214 +21,6 @@ declare void @pdouble(ptr)
declare void @pi64p(ptr)
define void @f(i32 %a, i32 %b, i64 %c, double %d, ptr %e) presplitcoroutine !dbg !8 {
-; CHECK-LABEL: define void @f(
-; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i64 [[C:%.*]], double [[D:%.*]], ptr [[E:%.*]]) !dbg [[DBG6:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*]]:
-; CHECK-NEXT: [[__PROMISE:%.*]] = alloca [[PROMISE_TYPE:%.*]], align 8
-; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
-; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: store i32 [[A]], ptr [[A_ALLOC]], align 4
-; CHECK-NEXT: store i32 [[B]], ptr [[B_ALLOC]], align 4
-; CHECK-NEXT: store i64 [[C]], ptr [[C_ALLOC]], align 4
-; CHECK-NEXT: store double [[D]], ptr [[D_ALLOC]], align 8
-; CHECK-NEXT: store ptr [[E]], ptr [[E_ALLOC]], align 8
-; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
-; CHECK-NEXT: call void @produce(ptr [[STRUCT_DATA]])
-; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
-; CHECK-NEXT: call void @produce_vector(ptr [[UNRESOLVED_DATA]])
-; CHECK-NEXT: [[UNRESOLVED_DATA2:%.*]] = alloca <5 x i1>, align 1
-; CHECK-NEXT: call void @produce_vectori5(ptr [[UNRESOLVED_DATA2]])
-; CHECK-NEXT: [[UNRESOLVED_DATA3:%.*]] = alloca <9 x i1>, align 2
-; CHECK-NEXT: call void @produce_vectori9(ptr [[UNRESOLVED_DATA3]])
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr @f, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
-; CHECK-NEXT: br i1 [[ALLOC]], label %[[CORO_ALLOC:.*]], label %[[CORO_INIT_FROM_ENTRY:.*]]
-; CHECK: [[CORO_INIT_FROM_ENTRY]]:
-; CHECK-NEXT: [[DOTCORO_INIT:%.*]] = phi ptr [ null, %[[ENTRY]] ]
-; CHECK-NEXT: br label %[[CORO_INIT:.*]]
-; CHECK: [[CORO_ALLOC]]:
-; CHECK-NEXT: [[MEMORY:%.*]] = call ptr @new(i64 592)
-; CHECK-NEXT: br label %[[CORO_INIT_FROM_CORO_ALLOC:.*]]
-; CHECK: [[CORO_INIT_FROM_CORO_ALLOC]]:
-; CHECK-NEXT: [[MEMORY_CORO_INIT:%.*]] = phi ptr [ [[MEMORY]], %[[CORO_ALLOC]] ]
-; CHECK-NEXT: br label %[[CORO_INIT]]
-; CHECK: [[CORO_INIT]]:
-; CHECK-NEXT: [[PHI_ENTRY_ALLOC:%.*]] = phi ptr [ [[DOTCORO_INIT]], %[[CORO_INIT_FROM_ENTRY]] ], [ [[MEMORY_CORO_INIT]], %[[CORO_INIT_FROM_CORO_ALLOC]] ]
-; CHECK-NEXT: [[BEGIN:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI_ENTRY_ALLOC]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META52:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16), [[META54:![0-9]+]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META9:![0-9]+]], !DIExpression(), [[META55:![0-9]+]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[ALLOC]], ptr @f.destroy, ptr @f.cleanup
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 1
-; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ALLOC]], align 4
-; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4
-; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[B_ALLOC]], align 4
-; CHECK-NEXT: store i32 [[TMP4]], ptr [[TMP3]], align 4
-; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[C_ALLOC]], align 4
-; CHECK-NEXT: store i64 [[TMP6]], ptr [[TMP5]], align 4
-; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[TMP8:%.*]] = load double, ptr [[D_ALLOC]], align 8
-; CHECK-NEXT: store double [[TMP8]], ptr [[TMP7]], align 8
-; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E_ALLOC]], align 8
-; CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP9]], align 8
-; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
-; CHECK-NEXT: [[TMP12:%.*]] = load [[STRUCT_BIG_STRUCTURE]], ptr [[STRUCT_DATA]], align 1
-; CHECK-NEXT: store [[STRUCT_BIG_STRUCTURE]] [[TMP12]], ptr [[TMP11]], align 1
-; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[TMP14:%.*]] = load <4 x i32>, ptr [[UNRESOLVED_DATA]], align 16
-; CHECK-NEXT: store <4 x i32> [[TMP14]], ptr [[TMP13]], align 16
-; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
-; CHECK-NEXT: [[TMP16:%.*]] = load <5 x i1>, ptr [[UNRESOLVED_DATA2]], align 1
-; CHECK-NEXT: store <5 x i1> [[TMP16]], ptr [[TMP15]], align 1
-; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: [[TMP18:%.*]] = load <9 x i1>, ptr [[UNRESOLVED_DATA3]], align 2
-; CHECK-NEXT: store <9 x i1> [[TMP18]], ptr [[TMP17]], align 2
-; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
-; CHECK: [[ALLOCASPILLBB]]:
-; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[B_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
-; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[UNRESOLVED_DATA2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
-; CHECK-NEXT: [[UNRESOLVED_DATA3_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 2
-; CHECK-NEXT: br label %[[POSTSPILL:.*]]
-; CHECK: [[POSTSPILL]]:
-; CHECK-NEXT: [[READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY]], label %[[INIT_READY:.*]], label %[[COROSAVE:.*]]
-; CHECK: [[COROSAVE]]:
-; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
-; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR13]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE:.*]]
-; CHECK: [[AFTERCOROSAVE]]:
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
-; CHECK: [[COROSUSPEND]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET:.*]] [
-; CHECK-NEXT: i8 0, label %[[INIT_READY]]
-; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[INIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP:.*]]
-; CHECK: [[INIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
-; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
-; CHECK: [[AFTERCOROSAVE2]]:
-; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
-; CHECK: [[COROSUSPEND3]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
-; CHECK: [[AFTERCOROSUSPEND4]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
-; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[AWAIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
-; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
-; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
-; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
-; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vectori5(ptr [[UNRESOLVED_DATA2_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vectori9(ptr [[UNRESOLVED_DATA3_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[B_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @return_void()
-; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
-; CHECK: [[CORO_FINAL]]:
-; CHECK-NEXT: call void @final_suspend()
-; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
-; CHECK: [[COROSAVE5]]:
-; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
-; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
-; CHECK: [[AFTERCOROSAVE6]]:
-; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
-; CHECK: [[COROSUSPEND7]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
-; CHECK: [[RESUME_2_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
-; CHECK: [[AFTERCOROSUSPEND8]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
-; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[FINAL_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[FINAL_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
-; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
-; CHECK-NEXT: [[FREE_MEMORY:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[BEGIN]])
-; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[FREE_MEMORY]], null
-; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
-; CHECK: [[CORO_FREE]]:
-; CHECK-NEXT: call void @delete(ptr [[FREE_MEMORY]])
-; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
-; CHECK: [[AFTER_CORO_FREE]]:
-; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
-; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
-; CHECK-NEXT: i32 2, label %[[CORO_RET]]
-; CHECK-NEXT: ]
-; CHECK: [[CLEANUP_CONT]]:
-; CHECK-NEXT: br label %[[CORO_RET]]
-; CHECK: [[CORO_RET]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
-; CHECK: [[AFTERCOROEND]]:
-; CHECK-NEXT: ret void
-; CHECK: [[UNREACHABLE]]:
-; CHECK-NEXT: unreachable
-;
entry:
%__promise = alloca %promise_type, align 8
%a.alloc = alloca i32, align 4
@@ -369,193 +159,6 @@ unreachable: ; preds = %after.coro.free
; bar is used to check that we wouldn't create duplicate DIType
define void @bar(i32 %a, i64 %c, double %d, ptr %e) presplitcoroutine !dbg !19 {
-; CHECK-LABEL: define void @bar(
-; CHECK-SAME: i32 [[A:%.*]], i64 [[C:%.*]], double [[D:%.*]], ptr [[E:%.*]]) !dbg [[DBG56:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*]]:
-; CHECK-NEXT: [[__PROMISE:%.*]] = alloca [[PROMISE_TYPE:%.*]], align 8
-; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
-; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: store i32 [[A]], ptr [[A_ALLOC]], align 4
-; CHECK-NEXT: store i64 [[C]], ptr [[C_ALLOC]], align 4
-; CHECK-NEXT: store double [[D]], ptr [[D_ALLOC]], align 8
-; CHECK-NEXT: store ptr [[E]], ptr [[E_ALLOC]], align 8
-; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
-; CHECK-NEXT: call void @produce(ptr [[STRUCT_DATA]])
-; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
-; CHECK-NEXT: call void @produce_vector(ptr [[UNRESOLVED_DATA]])
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr @bar, ptr @bar.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
-; CHECK-NEXT: br i1 [[ALLOC]], label %[[CORO_ALLOC:.*]], label %[[CORO_INIT_FROM_ENTRY:.*]]
-; CHECK: [[CORO_INIT_FROM_ENTRY]]:
-; CHECK-NEXT: [[DOTCORO_INIT:%.*]] = phi ptr [ null, %[[ENTRY]] ]
-; CHECK-NEXT: br label %[[CORO_INIT:.*]]
-; CHECK: [[CORO_ALLOC]]:
-; CHECK-NEXT: [[MEMORY:%.*]] = call ptr @new(i64 592)
-; CHECK-NEXT: br label %[[CORO_INIT_FROM_CORO_ALLOC:.*]]
-; CHECK: [[CORO_INIT_FROM_CORO_ALLOC]]:
-; CHECK-NEXT: [[MEMORY_CORO_INIT:%.*]] = phi ptr [ [[MEMORY]], %[[CORO_ALLOC]] ]
-; CHECK-NEXT: br label %[[CORO_INIT]]
-; CHECK: [[CORO_INIT]]:
-; CHECK-NEXT: [[PHI_ENTRY_ALLOC:%.*]] = phi ptr [ [[DOTCORO_INIT]], %[[CORO_INIT_FROM_ENTRY]] ], [ [[MEMORY_CORO_INIT]], %[[CORO_INIT_FROM_CORO_ALLOC]] ]
-; CHECK-NEXT: [[BEGIN:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI_ENTRY_ALLOC]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META74:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16), [[META76:![0-9]+]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META58:![0-9]+]], !DIExpression(), [[META77:![0-9]+]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr @bar.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[ALLOC]], ptr @bar.destroy, ptr @bar.cleanup
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 1
-; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ALLOC]], align 4
-; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4
-; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[C_ALLOC]], align 4
-; CHECK-NEXT: store i64 [[TMP4]], ptr [[TMP3]], align 4
-; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[TMP6:%.*]] = load double, ptr [[D_ALLOC]], align 8
-; CHECK-NEXT: store double [[TMP6]], ptr [[TMP5]], align 8
-; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[E_ALLOC]], align 8
-; CHECK-NEXT: store ptr [[TMP8]], ptr [[TMP7]], align 8
-; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[TMP10:%.*]] = load [[STRUCT_BIG_STRUCTURE]], ptr [[STRUCT_DATA]], align 1
-; CHECK-NEXT: store [[STRUCT_BIG_STRUCTURE]] [[TMP10]], ptr [[TMP9]], align 1
-; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[TMP12:%.*]] = load <4 x i32>, ptr [[UNRESOLVED_DATA]], align 16
-; CHECK-NEXT: store <4 x i32> [[TMP12]], ptr [[TMP11]], align 16
-; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
-; CHECK: [[ALLOCASPILLBB]]:
-; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 2
-; CHECK-NEXT: br label %[[POSTSPILL:.*]]
-; CHECK: [[POSTSPILL]]:
-; CHECK-NEXT: [[READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY]], label %[[INIT_READY:.*]], label %[[COROSAVE:.*]]
-; CHECK: [[COROSAVE]]:
-; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR13]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE:.*]]
-; CHECK: [[AFTERCOROSAVE]]:
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
-; CHECK: [[COROSUSPEND]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET:.*]] [
-; CHECK-NEXT: i8 0, label %[[INIT_READY]]
-; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[INIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP:.*]]
-; CHECK: [[INIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
-; CHECK: [[AFTERCOROSAVE2]]:
-; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
-; CHECK: [[COROSUSPEND3]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
-; CHECK: [[AFTERCOROSUSPEND4]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
-; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[AWAIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
-; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
-; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
-; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
-; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @return_void()
-; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
-; CHECK: [[CORO_FINAL]]:
-; CHECK-NEXT: call void @final_suspend()
-; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
-; CHECK: [[COROSAVE5]]:
-; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
-; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
-; CHECK: [[AFTERCOROSAVE6]]:
-; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
-; CHECK: [[COROSUSPEND7]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
-; CHECK: [[RESUME_2_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
-; CHECK: [[AFTERCOROSUSPEND8]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
-; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[FINAL_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[FINAL_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
-; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
-; CHECK-NEXT: [[FREE_MEMORY:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[BEGIN]])
-; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[FREE_MEMORY]], null
-; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
-; CHECK: [[CORO_FREE]]:
-; CHECK-NEXT: call void @delete(ptr [[FREE_MEMORY]])
-; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
-; CHECK: [[AFTER_CORO_FREE]]:
-; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
-; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
-; CHECK-NEXT: i32 2, label %[[CORO_RET]]
-; CHECK-NEXT: ]
-; CHECK: [[CLEANUP_CONT]]:
-; CHECK-NEXT: br label %[[CORO_RET]]
-; CHECK: [[CORO_RET]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
-; CHECK: [[AFTERCOROEND]]:
-; CHECK-NEXT: ret void
-; CHECK: [[UNREACHABLE]]:
-; CHECK-NEXT: unreachable
-;
entry:
%__promise = alloca %promise_type, align 8
%a.alloc = alloca i32, align 4
@@ -731,6 +334,1313 @@ declare void @final_suspend()
!20 = distinct !DILexicalBlock(scope: !19, file: !1, line: 23, column: 12)
!21 = !DILocalVariable(name: "__promise", scope: !20, file: !1, line: 55, type: !10)
!22 = !DILocation(line: 10, scope: !20)
+; CHECK-LABEL: define void @f(
+; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i64 [[C:%.*]], double [[D:%.*]], ptr [[E:%.*]]) !dbg [[DBG6:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[__PROMISE:%.*]] = alloca [[PROMISE_TYPE:%.*]], align 8
+; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[B_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
+; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
+; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
+; CHECK-NEXT: store i32 [[A]], ptr [[A_ALLOC]], align 4
+; CHECK-NEXT: store i32 [[B]], ptr [[B_ALLOC]], align 4
+; CHECK-NEXT: store i64 [[C]], ptr [[C_ALLOC]], align 4
+; CHECK-NEXT: store double [[D]], ptr [[D_ALLOC]], align 8
+; CHECK-NEXT: store ptr [[E]], ptr [[E_ALLOC]], align 8
+; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
+; CHECK-NEXT: call void @produce(ptr [[STRUCT_DATA]])
+; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
+; CHECK-NEXT: call void @produce_vector(ptr [[UNRESOLVED_DATA]])
+; CHECK-NEXT: [[UNRESOLVED_DATA2:%.*]] = alloca <5 x i1>, align 1
+; CHECK-NEXT: call void @produce_vectori5(ptr [[UNRESOLVED_DATA2]])
+; CHECK-NEXT: [[UNRESOLVED_DATA3:%.*]] = alloca <9 x i1>, align 2
+; CHECK-NEXT: call void @produce_vectori9(ptr [[UNRESOLVED_DATA3]])
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr @f, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
+; CHECK-NEXT: br i1 [[ALLOC]], label %[[CORO_ALLOC:.*]], label %[[CORO_INIT_FROM_ENTRY:.*]]
+; CHECK: [[CORO_INIT_FROM_ENTRY]]:
+; CHECK-NEXT: [[DOTCORO_INIT:%.*]] = phi ptr [ null, %[[ENTRY]] ]
+; CHECK-NEXT: br label %[[CORO_INIT:.*]]
+; CHECK: [[CORO_ALLOC]]:
+; CHECK-NEXT: [[MEMORY:%.*]] = call ptr @new(i64 592)
+; CHECK-NEXT: br label %[[CORO_INIT_FROM_CORO_ALLOC:.*]]
+; CHECK: [[CORO_INIT_FROM_CORO_ALLOC]]:
+; CHECK-NEXT: [[MEMORY_CORO_INIT:%.*]] = phi ptr [ [[MEMORY]], %[[CORO_ALLOC]] ]
+; CHECK-NEXT: br label %[[CORO_INIT]]
+; CHECK: [[CORO_INIT]]:
+; CHECK-NEXT: [[PHI_ENTRY_ALLOC:%.*]] = phi ptr [ [[DOTCORO_INIT]], %[[CORO_INIT_FROM_ENTRY]] ], [ [[MEMORY_CORO_INIT]], %[[CORO_INIT_FROM_CORO_ALLOC]] ]
+; CHECK-NEXT: [[BEGIN:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI_ENTRY_ALLOC]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META52:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16), [[META54:![0-9]+]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META9:![0-9]+]], !DIExpression(), [[META55:![0-9]+]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[ALLOC]], ptr @f.destroy, ptr @f.cleanup
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 1
+; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ALLOC]], align 4
+; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4
+; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[B_ALLOC]], align 4
+; CHECK-NEXT: store i32 [[TMP4]], ptr [[TMP3]], align 4
+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[C_ALLOC]], align 4
+; CHECK-NEXT: store i64 [[TMP6]], ptr [[TMP5]], align 4
+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[TMP8:%.*]] = load double, ptr [[D_ALLOC]], align 8
+; CHECK-NEXT: store double [[TMP8]], ptr [[TMP7]], align 8
+; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E_ALLOC]], align 8
+; CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP9]], align 8
+; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
+; CHECK-NEXT: [[TMP12:%.*]] = load [[STRUCT_BIG_STRUCTURE]], ptr [[STRUCT_DATA]], align 1
+; CHECK-NEXT: store [[STRUCT_BIG_STRUCTURE]] [[TMP12]], ptr [[TMP11]], align 1
+; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[TMP14:%.*]] = load <4 x i32>, ptr [[UNRESOLVED_DATA]], align 16
+; CHECK-NEXT: store <4 x i32> [[TMP14]], ptr [[TMP13]], align 16
+; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
+; CHECK-NEXT: [[TMP16:%.*]] = load <5 x i1>, ptr [[UNRESOLVED_DATA2]], align 1
+; CHECK-NEXT: store <5 x i1> [[TMP16]], ptr [[TMP15]], align 1
+; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: [[TMP18:%.*]] = load <9 x i1>, ptr [[UNRESOLVED_DATA3]], align 2
+; CHECK-NEXT: store <9 x i1> [[TMP18]], ptr [[TMP17]], align 2
+; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
+; CHECK: [[ALLOCASPILLBB]]:
+; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[B_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
+; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[UNRESOLVED_DATA2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
+; CHECK-NEXT: [[UNRESOLVED_DATA3_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 2
+; CHECK-NEXT: br label %[[POSTSPILL:.*]]
+; CHECK: [[POSTSPILL]]:
+; CHECK-NEXT: [[READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY]], label %[[INIT_READY:.*]], label %[[COROSAVE:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
+; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR13]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE:.*]]
+; CHECK: [[AFTERCOROSAVE]]:
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
+; CHECK: [[COROSUSPEND]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET:.*]] [
+; CHECK-NEXT: i8 0, label %[[INIT_READY]]
+; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[INIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP:.*]]
+; CHECK: [[INIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
+; CHECK: [[AFTERCOROSAVE2]]:
+; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
+; CHECK: [[COROSUSPEND3]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
+; CHECK: [[AFTERCOROSUSPEND4]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
+; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AWAIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
+; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
+; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
+; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
+; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vectori5(ptr [[UNRESOLVED_DATA2_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vectori9(ptr [[UNRESOLVED_DATA3_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[B_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @return_void()
+; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
+; CHECK: [[CORO_FINAL]]:
+; CHECK-NEXT: call void @final_suspend()
+; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
+; CHECK: [[COROSAVE5]]:
+; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
+; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
+; CHECK: [[AFTERCOROSAVE6]]:
+; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
+; CHECK: [[COROSUSPEND7]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
+; CHECK: [[RESUME_2_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
+; CHECK: [[AFTERCOROSUSPEND8]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
+; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[FINAL_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[FINAL_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
+; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
+; CHECK-NEXT: [[FREE_MEMORY:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[BEGIN]])
+; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[FREE_MEMORY]], null
+; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
+; CHECK: [[CORO_FREE]]:
+; CHECK-NEXT: call void @delete(ptr [[FREE_MEMORY]])
+; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
+; CHECK: [[AFTER_CORO_FREE]]:
+; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
+; CHECK-NEXT: i32 2, label %[[CORO_RET]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: br label %[[CORO_RET]]
+; CHECK: [[CORO_RET]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define void @bar(
+; CHECK-SAME: i32 [[A:%.*]], i64 [[C:%.*]], double [[D:%.*]], ptr [[E:%.*]]) !dbg [[DBG56:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[__PROMISE:%.*]] = alloca [[PROMISE_TYPE:%.*]], align 8
+; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
+; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
+; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
+; CHECK-NEXT: store i32 [[A]], ptr [[A_ALLOC]], align 4
+; CHECK-NEXT: store i64 [[C]], ptr [[C_ALLOC]], align 4
+; CHECK-NEXT: store double [[D]], ptr [[D_ALLOC]], align 8
+; CHECK-NEXT: store ptr [[E]], ptr [[E_ALLOC]], align 8
+; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
+; CHECK-NEXT: call void @produce(ptr [[STRUCT_DATA]])
+; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
+; CHECK-NEXT: call void @produce_vector(ptr [[UNRESOLVED_DATA]])
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr @bar, ptr @bar.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
+; CHECK-NEXT: br i1 [[ALLOC]], label %[[CORO_ALLOC:.*]], label %[[CORO_INIT_FROM_ENTRY:.*]]
+; CHECK: [[CORO_INIT_FROM_ENTRY]]:
+; CHECK-NEXT: [[DOTCORO_INIT:%.*]] = phi ptr [ null, %[[ENTRY]] ]
+; CHECK-NEXT: br label %[[CORO_INIT:.*]]
+; CHECK: [[CORO_ALLOC]]:
+; CHECK-NEXT: [[MEMORY:%.*]] = call ptr @new(i64 592)
+; CHECK-NEXT: br label %[[CORO_INIT_FROM_CORO_ALLOC:.*]]
+; CHECK: [[CORO_INIT_FROM_CORO_ALLOC]]:
+; CHECK-NEXT: [[MEMORY_CORO_INIT:%.*]] = phi ptr [ [[MEMORY]], %[[CORO_ALLOC]] ]
+; CHECK-NEXT: br label %[[CORO_INIT]]
+; CHECK: [[CORO_INIT]]:
+; CHECK-NEXT: [[PHI_ENTRY_ALLOC:%.*]] = phi ptr [ [[DOTCORO_INIT]], %[[CORO_INIT_FROM_ENTRY]] ], [ [[MEMORY_CORO_INIT]], %[[CORO_INIT_FROM_CORO_ALLOC]] ]
+; CHECK-NEXT: [[BEGIN:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI_ENTRY_ALLOC]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META74:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16), [[META76:![0-9]+]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META58:![0-9]+]], !DIExpression(), [[META77:![0-9]+]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr @bar.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[ALLOC]], ptr @bar.destroy, ptr @bar.cleanup
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 1
+; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ALLOC]], align 4
+; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4
+; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[C_ALLOC]], align 4
+; CHECK-NEXT: store i64 [[TMP4]], ptr [[TMP3]], align 4
+; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[TMP6:%.*]] = load double, ptr [[D_ALLOC]], align 8
+; CHECK-NEXT: store double [[TMP6]], ptr [[TMP5]], align 8
+; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[E_ALLOC]], align 8
+; CHECK-NEXT: store ptr [[TMP8]], ptr [[TMP7]], align 8
+; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[TMP10:%.*]] = load [[STRUCT_BIG_STRUCTURE]], ptr [[STRUCT_DATA]], align 1
+; CHECK-NEXT: store [[STRUCT_BIG_STRUCTURE]] [[TMP10]], ptr [[TMP9]], align 1
+; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[TMP12:%.*]] = load <4 x i32>, ptr [[UNRESOLVED_DATA]], align 16
+; CHECK-NEXT: store <4 x i32> [[TMP12]], ptr [[TMP11]], align 16
+; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
+; CHECK: [[ALLOCASPILLBB]]:
+; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 2
+; CHECK-NEXT: br label %[[POSTSPILL:.*]]
+; CHECK: [[POSTSPILL]]:
+; CHECK-NEXT: [[READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY]], label %[[INIT_READY:.*]], label %[[COROSAVE:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR13]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE:.*]]
+; CHECK: [[AFTERCOROSAVE]]:
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
+; CHECK: [[COROSUSPEND]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET:.*]] [
+; CHECK-NEXT: i8 0, label %[[INIT_READY]]
+; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[INIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP:.*]]
+; CHECK: [[INIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
+; CHECK: [[AFTERCOROSAVE2]]:
+; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
+; CHECK: [[COROSUSPEND3]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
+; CHECK: [[AFTERCOROSUSPEND4]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
+; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AWAIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
+; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
+; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
+; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
+; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @return_void()
+; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
+; CHECK: [[CORO_FINAL]]:
+; CHECK-NEXT: call void @final_suspend()
+; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
+; CHECK: [[COROSAVE5]]:
+; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
+; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
+; CHECK: [[AFTERCOROSAVE6]]:
+; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
+; CHECK: [[COROSUSPEND7]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
+; CHECK: [[RESUME_2_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
+; CHECK: [[AFTERCOROSUSPEND8]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
+; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[FINAL_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[FINAL_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
+; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
+; CHECK-NEXT: [[FREE_MEMORY:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[BEGIN]])
+; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[FREE_MEMORY]], null
+; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
+; CHECK: [[CORO_FREE]]:
+; CHECK-NEXT: call void @delete(ptr [[FREE_MEMORY]])
+; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
+; CHECK: [[AFTER_CORO_FREE]]:
+; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
+; CHECK-NEXT: i32 2, label %[[CORO_RET]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: br label %[[CORO_RET]]
+; CHECK: [[CORO_RET]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG78:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META81:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META83:![0-9]+]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META80:![0-9]+]], !DIExpression(DW_OP_deref), [[META84:![0-9]+]])
+; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
+; CHECK-NEXT: [[UNRESOLVED_DATA3:%.*]] = alloca <9 x i1>, align 2
+; CHECK-NEXT: [[UNRESOLVED_DATA2:%.*]] = alloca <5 x i1>, align 1
+; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
+; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
+; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
+; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
+; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
+; CHECK-NEXT: [[B_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[B_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
+; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[UNRESOLVED_DATA2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
+; CHECK-NEXT: [[UNRESOLVED_DATA3_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 2
+; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
+; CHECK: [[RESUME_ENTRY]]:
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
+; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
+; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
+; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[RESUME_0]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 0, label %[[CORO_RET:.*]] [
+; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
+; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[INIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP:.*]]
+; CHECK: [[INIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
+; CHECK: [[AFTERCOROSAVE2]]:
+; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
+; CHECK: [[COROSUSPEND3]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 0, %[[RESUME_1]] ]
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
+; CHECK: [[AFTERCOROSUSPEND4]]:
+; CHECK-NEXT: switch i8 [[TMP0]], label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
+; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AWAIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
+; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
+; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
+; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
+; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vectori5(ptr [[UNRESOLVED_DATA2_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vectori9(ptr [[UNRESOLVED_DATA3_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[B_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @return_void()
+; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
+; CHECK: [[CORO_FINAL]]:
+; CHECK-NEXT: call void @final_suspend()
+; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
+; CHECK: [[COROSAVE5]]:
+; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
+; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
+; CHECK: [[AFTERCOROSAVE6]]:
+; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
+; CHECK: [[COROSUSPEND7]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
+; CHECK: [[RESUME_2_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
+; CHECK: [[AFTERCOROSUSPEND8]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
+; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[FINAL_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[FINAL_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
+; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
+; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[BEGIN]], null
+; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
+; CHECK: [[CORO_FREE]]:
+; CHECK-NEXT: call void @delete(ptr [[BEGIN]])
+; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
+; CHECK: [[AFTER_CORO_FREE]]:
+; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
+; CHECK-NEXT: i32 2, label %[[CORO_RET]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: br label %[[CORO_RET]]
+; CHECK: [[CORO_RET]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+; CHECK: [[UNREACHABLE12]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG85:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META88:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META90:![0-9]+]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META87:![0-9]+]], !DIExpression(DW_OP_deref), [[META91:![0-9]+]])
+; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
+; CHECK-NEXT: [[UNRESOLVED_DATA3:%.*]] = alloca <9 x i1>, align 2
+; CHECK-NEXT: [[UNRESOLVED_DATA2:%.*]] = alloca <5 x i1>, align 1
+; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
+; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
+; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
+; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
+; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
+; CHECK-NEXT: [[B_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[B_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
+; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[UNRESOLVED_DATA2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
+; CHECK-NEXT: [[UNRESOLVED_DATA3_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 2
+; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
+; CHECK: [[RESUME_ENTRY]]:
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
+; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: [[RESUMEFN_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESUMEFN_ADDR1]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+; CHECK-NEXT: br i1 [[TMP1]], label %[[RESUME_2:.*]], label %[[SWITCH:.*]]
+; CHECK: [[SWITCH]]:
+; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
+; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
+; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[RESUME_0]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 1, label %[[CORO_RET:.*]] [
+; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
+; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[INIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP:.*]]
+; CHECK: [[INIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
+; CHECK: [[AFTERCOROSAVE2]]:
+; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
+; CHECK: [[COROSUSPEND3]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 1, %[[RESUME_1]] ]
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
+; CHECK: [[AFTERCOROSUSPEND4]]:
+; CHECK-NEXT: switch i8 [[TMP2]], label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
+; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AWAIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
+; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
+; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
+; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
+; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vectori5(ptr [[UNRESOLVED_DATA2_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vectori9(ptr [[UNRESOLVED_DATA3_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[B_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @return_void()
+; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
+; CHECK: [[CORO_FINAL]]:
+; CHECK-NEXT: call void @final_suspend()
+; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
+; CHECK: [[COROSAVE5]]:
+; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
+; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
+; CHECK: [[AFTERCOROSAVE6]]:
+; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
+; CHECK: [[COROSUSPEND7]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
+; CHECK: [[RESUME_2]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING]]
+; CHECK: [[RESUME_2_LANDING]]:
+; CHECK-NEXT: [[TMP3:%.*]] = phi i8 [ -1, %[[COROSUSPEND7]] ], [ 1, %[[RESUME_2]] ]
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
+; CHECK: [[AFTERCOROSUSPEND8]]:
+; CHECK-NEXT: switch i8 [[TMP3]], label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
+; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[FINAL_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[FINAL_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
+; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
+; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[BEGIN]], null
+; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
+; CHECK: [[CORO_FREE]]:
+; CHECK-NEXT: call void @delete(ptr [[BEGIN]])
+; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
+; CHECK: [[AFTER_CORO_FREE]]:
+; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
+; CHECK-NEXT: i32 2, label %[[CORO_RET]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: br label %[[CORO_RET]]
+; CHECK: [[CORO_RET]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+; CHECK: [[UNREACHABLE12]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG92:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META95:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META97:![0-9]+]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META94:![0-9]+]], !DIExpression(DW_OP_deref), [[META98:![0-9]+]])
+; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
+; CHECK-NEXT: [[UNRESOLVED_DATA3:%.*]] = alloca <9 x i1>, align 2
+; CHECK-NEXT: [[UNRESOLVED_DATA2:%.*]] = alloca <5 x i1>, align 1
+; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
+; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
+; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
+; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
+; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
+; CHECK-NEXT: [[B_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[B_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
+; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[UNRESOLVED_DATA2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
+; CHECK-NEXT: [[UNRESOLVED_DATA3_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 2
+; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
+; CHECK: [[RESUME_ENTRY]]:
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
+; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: [[RESUMEFN_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESUMEFN_ADDR1]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+; CHECK-NEXT: br i1 [[TMP1]], label %[[RESUME_2:.*]], label %[[SWITCH:.*]]
+; CHECK: [[SWITCH]]:
+; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
+; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
+; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[RESUME_0]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 1, label %[[CORO_RET:.*]] [
+; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
+; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[INIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP:.*]]
+; CHECK: [[INIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
+; CHECK: [[AFTERCOROSAVE2]]:
+; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
+; CHECK: [[COROSUSPEND3]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 1, %[[RESUME_1]] ]
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
+; CHECK: [[AFTERCOROSUSPEND4]]:
+; CHECK-NEXT: switch i8 [[TMP2]], label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
+; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AWAIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
+; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
+; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
+; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
+; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vectori5(ptr [[UNRESOLVED_DATA2_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vectori9(ptr [[UNRESOLVED_DATA3_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[B_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @return_void()
+; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
+; CHECK: [[CORO_FINAL]]:
+; CHECK-NEXT: call void @final_suspend()
+; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
+; CHECK: [[COROSAVE5]]:
+; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
+; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
+; CHECK: [[AFTERCOROSAVE6]]:
+; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
+; CHECK: [[COROSUSPEND7]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
+; CHECK: [[RESUME_2]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING]]
+; CHECK: [[RESUME_2_LANDING]]:
+; CHECK-NEXT: [[TMP3:%.*]] = phi i8 [ -1, %[[COROSUSPEND7]] ], [ 1, %[[RESUME_2]] ]
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
+; CHECK: [[AFTERCOROSUSPEND8]]:
+; CHECK-NEXT: switch i8 [[TMP3]], label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
+; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[FINAL_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[FINAL_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
+; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
+; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr null, null
+; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
+; CHECK: [[CORO_FREE]]:
+; CHECK-NEXT: call void @delete(ptr null)
+; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
+; CHECK: [[AFTER_CORO_FREE]]:
+; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
+; CHECK-NEXT: i32 2, label %[[CORO_RET]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: br label %[[CORO_RET]]
+; CHECK: [[CORO_RET]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+; CHECK: [[UNREACHABLE12]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @bar.resume(
+; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG99:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META102:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META104:![0-9]+]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META101:![0-9]+]], !DIExpression(DW_OP_deref), [[META105:![0-9]+]])
+; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
+; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
+; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
+; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
+; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
+; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
+; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 2
+; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
+; CHECK: [[RESUME_ENTRY]]:
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
+; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
+; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[RESUME_0]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 0, label %[[CORO_RET:.*]] [
+; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
+; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[INIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP:.*]]
+; CHECK: [[INIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
+; CHECK: [[AFTERCOROSAVE2]]:
+; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
+; CHECK: [[COROSUSPEND3]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 0, %[[RESUME_1]] ]
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
+; CHECK: [[AFTERCOROSUSPEND4]]:
+; CHECK-NEXT: switch i8 [[TMP0]], label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
+; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AWAIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
+; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
+; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
+; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
+; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @return_void()
+; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
+; CHECK: [[CORO_FINAL]]:
+; CHECK-NEXT: call void @final_suspend()
+; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
+; CHECK: [[COROSAVE5]]:
+; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
+; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
+; CHECK: [[AFTERCOROSAVE6]]:
+; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
+; CHECK: [[COROSUSPEND7]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
+; CHECK: [[RESUME_2_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
+; CHECK: [[AFTERCOROSUSPEND8]]:
+; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
+; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[FINAL_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[FINAL_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
+; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
+; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[BEGIN]], null
+; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
+; CHECK: [[CORO_FREE]]:
+; CHECK-NEXT: call void @delete(ptr [[BEGIN]])
+; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
+; CHECK: [[AFTER_CORO_FREE]]:
+; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
+; CHECK-NEXT: i32 2, label %[[CORO_RET]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: br label %[[CORO_RET]]
+; CHECK: [[CORO_RET]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+; CHECK: [[UNREACHABLE12]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @bar.destroy(
+; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG106:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META109:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META111:![0-9]+]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META108:![0-9]+]], !DIExpression(DW_OP_deref), [[META112:![0-9]+]])
+; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
+; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
+; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
+; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
+; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
+; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
+; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 2
+; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
+; CHECK: [[RESUME_ENTRY]]:
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: [[RESUMEFN_ADDR1:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESUMEFN_ADDR1]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+; CHECK-NEXT: br i1 [[TMP1]], label %[[RESUME_2:.*]], label %[[SWITCH:.*]]
+; CHECK: [[SWITCH]]:
+; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
+; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
+; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[RESUME_0]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 1, label %[[CORO_RET:.*]] [
+; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
+; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[INIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP:.*]]
+; CHECK: [[INIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
+; CHECK: [[AFTERCOROSAVE2]]:
+; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
+; CHECK: [[COROSUSPEND3]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 1, %[[RESUME_1]] ]
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
+; CHECK: [[AFTERCOROSUSPEND4]]:
+; CHECK-NEXT: switch i8 [[TMP2]], label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
+; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AWAIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
+; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
+; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
+; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
+; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @return_void()
+; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
+; CHECK: [[CORO_FINAL]]:
+; CHECK-NEXT: call void @final_suspend()
+; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
+; CHECK: [[COROSAVE5]]:
+; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
+; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
+; CHECK: [[AFTERCOROSAVE6]]:
+; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
+; CHECK: [[COROSUSPEND7]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
+; CHECK: [[RESUME_2]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING]]
+; CHECK: [[RESUME_2_LANDING]]:
+; CHECK-NEXT: [[TMP3:%.*]] = phi i8 [ -1, %[[COROSUSPEND7]] ], [ 1, %[[RESUME_2]] ]
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
+; CHECK: [[AFTERCOROSUSPEND8]]:
+; CHECK-NEXT: switch i8 [[TMP3]], label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
+; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[FINAL_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[FINAL_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
+; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
+; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[BEGIN]], null
+; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
+; CHECK: [[CORO_FREE]]:
+; CHECK-NEXT: call void @delete(ptr [[BEGIN]])
+; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
+; CHECK: [[AFTER_CORO_FREE]]:
+; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
+; CHECK-NEXT: i32 2, label %[[CORO_RET]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: br label %[[CORO_RET]]
+; CHECK: [[CORO_RET]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+; CHECK: [[UNREACHABLE12]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @bar.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG113:![0-9]+]] {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META116:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META118:![0-9]+]])
+; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META115:![0-9]+]], !DIExpression(DW_OP_deref), [[META119:![0-9]+]])
+; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
+; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
+; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
+; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
+; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
+; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
+; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
+; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
+; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
+; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
+; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
+; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 2
+; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
+; CHECK: [[RESUME_ENTRY]]:
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: [[RESUMEFN_ADDR1:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESUMEFN_ADDR1]], align 8
+; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
+; CHECK-NEXT: br i1 [[TMP1]], label %[[RESUME_2:.*]], label %[[SWITCH:.*]]
+; CHECK: [[SWITCH]]:
+; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
+; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
+; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[RESUME_0]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: switch i8 1, label %[[CORO_RET:.*]] [
+; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
+; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[INIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP:.*]]
+; CHECK: [[INIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
+; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
+; CHECK: [[COROSAVE1]]:
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
+; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
+; CHECK: [[AFTERCOROSAVE2]]:
+; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
+; CHECK: [[COROSUSPEND3]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
+; CHECK: [[RESUME_1]]:
+; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
+; CHECK: [[RESUME_1_LANDING]]:
+; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 1, %[[RESUME_1]] ]
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
+; CHECK: [[AFTERCOROSUSPEND4]]:
+; CHECK-NEXT: switch i8 [[TMP2]], label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
+; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AWAIT_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
+; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
+; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
+; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
+; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
+; CHECK-NEXT: call void @return_void()
+; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
+; CHECK: [[CORO_FINAL]]:
+; CHECK-NEXT: call void @final_suspend()
+; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
+; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
+; CHECK: [[COROSAVE5]]:
+; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
+; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
+; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
+; CHECK: [[AFTERCOROSAVE6]]:
+; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
+; CHECK-NEXT: call void @await_suspend()
+; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
+; CHECK: [[COROSUSPEND7]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
+; CHECK: [[RESUME_2]]:
+; CHECK-NEXT: br label %[[RESUME_2_LANDING]]
+; CHECK: [[RESUME_2_LANDING]]:
+; CHECK-NEXT: [[TMP3:%.*]] = phi i8 [ -1, %[[COROSUSPEND7]] ], [ 1, %[[RESUME_2]] ]
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
+; CHECK: [[AFTERCOROSUSPEND8]]:
+; CHECK-NEXT: switch i8 [[TMP3]], label %[[CORO_RET]] [
+; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
+; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[FINAL_CLEANUP]]:
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
+; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[FINAL_READY]]:
+; CHECK-NEXT: call void @await_resume()
+; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
+; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
+; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
+; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr null, null
+; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
+; CHECK: [[CORO_FREE]]:
+; CHECK-NEXT: call void @delete(ptr null)
+; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
+; CHECK: [[AFTER_CORO_FREE]]:
+; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
+; CHECK-NEXT: i32 2, label %[[CORO_RET]]
+; CHECK-NEXT: ]
+; CHECK: [[CLEANUP_CONT]]:
+; CHECK-NEXT: br label %[[CORO_RET]]
+; CHECK: [[CORO_RET]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+; CHECK: [[UNREACHABLE12]]:
+; CHECK-NEXT: unreachable
+;
;.
; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: [[META2:![0-9]+]], retainedTypes: [[META2]], splitDebugInlining: false, nameTableKind: None)
; CHECK: [[META1]] = !DIFile(filename: "{{.*}}coro-debug.cpp", directory: {{.*}})
@@ -807,4 +1717,46 @@ declare void @final_suspend()
; CHECK: [[META75]] = distinct !DILexicalBlock(scope: [[DBG56]], file: [[META1]], line: 23, column: 12)
; CHECK: [[META76]] = !DILocation(line: 10, scope: [[META75]])
; CHECK: [[META77]] = !DILocation(line: 54, column: 1, scope: [[DBG56]])
+; CHECK: [[DBG78]] = distinct !DISubprogram(name: "foo", linkageName: "f.resume", scope: [[DBG78]], file: [[META1]], line: 23, type: [[META7]], scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META79:![0-9]+]])
+; CHECK: [[META79]] = !{[[META80]]}
+; CHECK: [[META80]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG78]], file: [[META1]], line: 23, type: [[META10]], flags: DIFlagArtificial)
+; CHECK: [[META81]] = !DILocalVariable(name: "__promise", scope: [[META82:![0-9]+]], file: [[META1]], line: 24, type: [[META16]])
+; CHECK: [[META82]] = distinct !DILexicalBlock(scope: [[DBG78]], file: [[META1]], line: 23, column: 12)
+; CHECK: [[META83]] = !DILocation(line: 8, scope: [[META82]])
+; CHECK: [[META84]] = !DILocation(line: 23, column: 1, scope: [[DBG78]])
+; CHECK: [[DBG85]] = distinct !DISubprogram(name: "foo", linkageName: "f.destroy", scope: [[DBG85]], file: [[META1]], line: 23, type: [[META7]], scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META86:![0-9]+]])
+; CHECK: [[META86]] = !{[[META87]]}
+; CHECK: [[META87]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG85]], file: [[META1]], line: 23, type: [[META10]], flags: DIFlagArtificial)
+; CHECK: [[META88]] = !DILocalVariable(name: "__promise", scope: [[META89:![0-9]+]], file: [[META1]], line: 24, type: [[META16]])
+; CHECK: [[META89]] = distinct !DILexicalBlock(scope: [[DBG85]], file: [[META1]], line: 23, column: 12)
+; CHECK: [[META90]] = !DILocation(line: 8, scope: [[META89]])
+; CHECK: [[META91]] = !DILocation(line: 23, column: 1, scope: [[DBG85]])
+; CHECK: [[DBG92]] = distinct !DISubprogram(name: "foo", linkageName: "f.cleanup", scope: [[DBG92]], file: [[META1]], line: 23, type: [[META7]], scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META93:![0-9]+]])
+; CHECK: [[META93]] = !{[[META94]]}
+; CHECK: [[META94]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG92]], file: [[META1]], line: 23, type: [[META10]], flags: DIFlagArtificial)
+; CHECK: [[META95]] = !DILocalVariable(name: "__promise", scope: [[META96:![0-9]+]], file: [[META1]], line: 24, type: [[META16]])
+; CHECK: [[META96]] = distinct !DILexicalBlock(scope: [[DBG92]], file: [[META1]], line: 23, column: 12)
+; CHECK: [[META97]] = !DILocation(line: 8, scope: [[META96]])
+; CHECK: [[META98]] = !DILocation(line: 23, column: 1, scope: [[DBG92]])
+; CHECK: [[DBG99]] = distinct !DISubprogram(name: "bar", linkageName: "bar.resume", scope: [[DBG99]], file: [[META1]], line: 54, type: [[META7]], scopeLine: 54, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META100:![0-9]+]])
+; CHECK: [[META100]] = !{[[META101]]}
+; CHECK: [[META101]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG99]], file: [[META1]], line: 54, type: [[META59]], flags: DIFlagArtificial)
+; CHECK: [[META102]] = !DILocalVariable(name: "__promise", scope: [[META103:![0-9]+]], file: [[META1]], line: 55, type: [[META16]])
+; CHECK: [[META103]] = distinct !DILexicalBlock(scope: [[DBG99]], file: [[META1]], line: 23, column: 12)
+; CHECK: [[META104]] = !DILocation(line: 10, scope: [[META103]])
+; CHECK: [[META105]] = !DILocation(line: 54, column: 1, scope: [[DBG99]])
+; CHECK: [[DBG106]] = distinct !DISubprogram(name: "bar", linkageName: "bar.destroy", scope: [[DBG106]], file: [[META1]], line: 54, type: [[META7]], scopeLine: 54, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META107:![0-9]+]])
+; CHECK: [[META107]] = !{[[META108]]}
+; CHECK: [[META108]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG106]], file: [[META1]], line: 54, type: [[META59]], flags: DIFlagArtificial)
+; CHECK: [[META109]] = !DILocalVariable(name: "__promise", scope: [[META110:![0-9]+]], file: [[META1]], line: 55, type: [[META16]])
+; CHECK: [[META110]] = distinct !DILexicalBlock(scope: [[DBG106]], file: [[META1]], line: 23, column: 12)
+; CHECK: [[META111]] = !DILocation(line: 10, scope: [[META110]])
+; CHECK: [[META112]] = !DILocation(line: 54, column: 1, scope: [[DBG106]])
+; CHECK: [[DBG113]] = distinct !DISubprogram(name: "bar", linkageName: "bar.cleanup", scope: [[DBG113]], file: [[META1]], line: 54, type: [[META7]], scopeLine: 54, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META114:![0-9]+]])
+; CHECK: [[META114]] = !{[[META115]]}
+; CHECK: [[META115]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG113]], file: [[META1]], line: 54, type: [[META59]], flags: DIFlagArtificial)
+; CHECK: [[META116]] = !DILocalVariable(name: "__promise", scope: [[META117:![0-9]+]], file: [[META1]], line: 55, type: [[META16]])
+; CHECK: [[META117]] = distinct !DILexicalBlock(scope: [[DBG113]], file: [[META1]], line: 23, column: 12)
+; CHECK: [[META118]] = !DILocation(line: 10, scope: [[META117]])
+; CHECK: [[META119]] = !DILocation(line: 54, column: 1, scope: [[DBG113]])
;.
diff --git a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
index 95686acecfd1e..e5fe1417dd19f 100644
--- a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we can handle edge splits leading into a landingpad
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
@@ -6,25 +6,6 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @g(i1 %cond, i32 %x, i32 %y) presplitcoroutine personality i32 0 {
-; CHECK-LABEL: define void @g(
-; CHECK-SAME: i1 [[COND:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) personality i32 0 {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr @g.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 32)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @g.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[G_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @g.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[Y_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i32 [[Y]], ptr [[Y_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[COND_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 5
-; CHECK-NEXT: store i1 [[COND]], ptr [[COND_SPILL_ADDR]], align 1
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[G_FRAME]], ptr [[HDL]], i32 0, i32 4
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret void
-;
entry:
%id = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr null)
%size = tail call i64 @llvm.coro.size.i64()
@@ -93,3 +74,67 @@ declare void @__cxa_end_catch()
declare void @llvm.coro.end(ptr, i1, token)
declare void @free(ptr)
declare ptr @llvm.coro.free(token, ptr nocapture readonly)
+; CHECK-LABEL: define void @g(
+; CHECK-SAME: i1 [[COND:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr @g.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @g.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[G_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @g.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[Y_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i32 [[Y]], ptr [[Y_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[COND_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: store i1 [[COND]], ptr [[COND_SPILL_ADDR]], align 1
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[G_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @g.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[COND_RELOAD_ADDR:%.*]] = getelementptr inbounds [[G_FRAME:%.*]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[COND_RELOAD:%.*]] = load i1, ptr [[COND_RELOAD_ADDR]], align 1
+; CHECK-NEXT: br i1 [[COND_RELOAD]], label %[[INVOKE1:.*]], label %[[INVOKE2:.*]]
+; CHECK: [[INVOKE1]]:
+; CHECK-NEXT: invoke void @may_throw1()
+; CHECK-NEXT: to label %[[UNREACH:.*]] unwind label %[[PAD_WITH_PHI_FROM_INVOKE1:.*]]
+; CHECK: [[INVOKE2]]:
+; CHECK-NEXT: invoke void @may_throw2()
+; CHECK-NEXT: to label %[[UNREACH]] unwind label %[[PAD_WITH_PHI_FROM_INVOKE2:.*]]
+; CHECK: [[PAD_WITH_PHI_FROM_INVOKE2]]:
+; CHECK-NEXT: [[TMP0:%.*]] = cleanuppad within none []
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[Y_RELOAD:%.*]] = load i32, ptr [[Y_RELOAD_ADDR]], align 4
+; CHECK-NEXT: cleanupret from [[TMP0]] unwind label %[[PAD_WITH_PHI:.*]]
+; CHECK: [[PAD_WITH_PHI_FROM_INVOKE1]]:
+; CHECK-NEXT: [[TMP1:%.*]] = cleanuppad within none []
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4
+; CHECK-NEXT: cleanupret from [[TMP1]] unwind label %[[PAD_WITH_PHI]]
+; CHECK: [[PAD_WITH_PHI]]:
+; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ [[X_RELOAD]], %[[PAD_WITH_PHI_FROM_INVOKE1]] ], [ [[Y_RELOAD]], %[[PAD_WITH_PHI_FROM_INVOKE2]] ]
+; CHECK-NEXT: [[TOK:%.*]] = cleanuppad within none []
+; CHECK-NEXT: call void @use_val(i32 [[VAL]])
+; CHECK-NEXT: cleanupret from [[TOK]] unwind to caller
+; CHECK: [[UNREACH]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @g.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @g.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
index 7aa2cf5617d88..344549205369d 100644
--- a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we can handle edge splits leading into a landingpad
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
@@ -6,25 +6,6 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @h(i1 %cond, i32 %x, i32 %y) presplitcoroutine personality i32 0 {
-; CHECK-LABEL: define void @h(
-; CHECK-SAME: i1 [[COND:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) personality i32 0 {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr @h.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 32)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @h.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[H_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @h.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[Y_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i32 [[Y]], ptr [[Y_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[COND_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 5
-; CHECK-NEXT: store i1 [[COND]], ptr [[COND_SPILL_ADDR]], align 1
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[H_FRAME]], ptr [[HDL]], i32 0, i32 4
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret void
-;
entry:
%id = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr null)
%size = tail call i64 @llvm.coro.size.i64()
@@ -92,3 +73,69 @@ declare void @__cxa_end_catch()
declare void @llvm.coro.end(ptr, i1, token)
declare void @free(ptr)
declare ptr @llvm.coro.free(token, ptr nocapture readonly)
+; CHECK-LABEL: define void @h(
+; CHECK-SAME: i1 [[COND:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr null, ptr @h.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @h.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[H_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @h.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[Y_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i32 [[Y]], ptr [[Y_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[COND_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: store i1 [[COND]], ptr [[COND_SPILL_ADDR]], align 1
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[H_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @h.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[COND_RELOAD_ADDR:%.*]] = getelementptr inbounds [[H_FRAME:%.*]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[COND_RELOAD:%.*]] = load i1, ptr [[COND_RELOAD_ADDR]], align 1
+; CHECK-NEXT: br i1 [[COND_RELOAD]], label %[[INVOKE1:.*]], label %[[INVOKE2:.*]]
+; CHECK: [[INVOKE1]]:
+; CHECK-NEXT: invoke void @may_throw1()
+; CHECK-NEXT: to label %[[COROEND:.*]] unwind label %[[PAD_WITH_PHI_FROM_INVOKE1:.*]]
+; CHECK: [[INVOKE2]]:
+; CHECK-NEXT: invoke void @may_throw2()
+; CHECK-NEXT: to label %[[COROEND]] unwind label %[[PAD_WITH_PHI_FROM_INVOKE2:.*]]
+; CHECK: [[PAD_WITH_PHI_FROM_INVOKE2]]:
+; CHECK-NEXT: [[TMP0:%.*]] = cleanuppad within none []
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[Y_RELOAD:%.*]] = load i32, ptr [[Y_RELOAD_ADDR]], align 4
+; CHECK-NEXT: cleanupret from [[TMP0]] unwind label %[[PAD_WITH_PHI:.*]]
+; CHECK: [[PAD_WITH_PHI_FROM_INVOKE1]]:
+; CHECK-NEXT: [[TMP1:%.*]] = cleanuppad within none []
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4
+; CHECK-NEXT: cleanupret from [[TMP1]] unwind label %[[PAD_WITH_PHI]]
+; CHECK: [[PAD_WITH_PHI]]:
+; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ [[X_RELOAD]], %[[PAD_WITH_PHI_FROM_INVOKE1]] ], [ [[Y_RELOAD]], %[[PAD_WITH_PHI_FROM_INVOKE2]] ]
+; CHECK-NEXT: [[SWITCH:%.*]] = catchswitch within none [label %[[CATCH:.*]]] unwind to caller
+; CHECK: [[CATCH]]:
+; CHECK-NEXT: [[PAD:%.*]] = catchpad within [[SWITCH]] [ptr null, i32 64, ptr null]
+; CHECK-NEXT: call void @use_val(i32 [[VAL]])
+; CHECK-NEXT: catchret from [[PAD]] to label %[[COROEND]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @h.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @h.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll b/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
index 566fd1d2d9174..32afbc7faecd0 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
@@ -1,31 +1,12 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we can handle spills of array allocas
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, double, double, [4 x i32], i1 }
declare void @consume.double.ptr(ptr)
declare void @consume.i32.ptr(ptr)
define ptr @f() presplitcoroutine {
-; CHECK-LABEL: define ptr @f() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 56)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[PREFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4, i32 0
-; CHECK-NEXT: [[SUFFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: call void @consume.double.ptr(ptr [[PREFIX_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume.i32.ptr(ptr [[DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume.double.ptr(ptr [[SUFFIX_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%prefix = alloca double
%data = alloca i32, i32 4
@@ -75,3 +56,48 @@ declare void @llvm.coro.end(ptr, i1, token)
declare noalias ptr @malloc(i32)
declare double @print(double)
declare void @free(ptr)
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 56)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[PREFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4, i32 0
+; CHECK-NEXT: [[SUFFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: call void @consume.double.ptr(ptr [[PREFIX_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume.i32.ptr(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume.double.ptr(ptr [[SUFFIX_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(56) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[PREFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4, i32 0
+; CHECK-NEXT: [[SUFFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: call void @consume.double.ptr(ptr [[PREFIX_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume.i32.ptr(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume.double.ptr(ptr [[SUFFIX_RELOAD_ADDR]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(56) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(56) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-frame.ll b/llvm/test/Transforms/Coroutines/coro-frame.ll
index 5f9aaeae334ba..34a1c6c8d3136 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame.ll
@@ -1,30 +1,9 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we can handle spills of the result of the invoke instruction
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, double, i64, i1 }
define ptr @f(i64 %this) presplitcoroutine personality i32 0 {
-; CHECK-LABEL: define ptr @f(
-; CHECK-SAME: i64 [[THIS:%.*]]) personality i32 0 {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca i64, align 8
-; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS_ADDR]], align 4
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[THIS1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS1_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[R:%.*]] = call double @print(double 0.000000e+00)
-; CHECK-NEXT: [[R_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store double [[R]], ptr [[R_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%this.addr = alloca i64
store i64 %this, ptr %this.addr
@@ -77,3 +56,50 @@ declare noalias ptr @malloc(i32)
declare double @print(double)
declare void @print2(i64)
declare void @free(ptr)
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i64 [[THIS:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca i64, align 8
+; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS_ADDR]], align 4
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[THIS1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS1_SPILL_ADDR]], align 4
+; CHECK-NEXT: [[R:%.*]] = call double @print(double 0.000000e+00)
+; CHECK-NEXT: [[R_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store double [[R]], ptr [[R_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(40) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[R_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[R_RELOAD:%.*]] = load double, ptr [[R_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[THIS1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[THIS1_RELOAD:%.*]] = load i64, ptr [[THIS1_RELOAD_ADDR]], align 4
+; CHECK-NEXT: [[TMP0:%.*]] = call double @print(double [[R_RELOAD]])
+; CHECK-NEXT: call void @print2(i64 [[THIS1_RELOAD]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(40) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(40) [[HDL:%.*]]) personality i32 0 {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-padding.ll b/llvm/test/Transforms/Coroutines/coro-padding.ll
index c48b8961168e8..89ad2f49730b8 100644
--- a/llvm/test/Transforms/Coroutines/coro-padding.ll
+++ b/llvm/test/Transforms/Coroutines/coro-padding.ll
@@ -1,29 +1,14 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we will insert the correct padding if natural alignment of the
; spilled data does not match the alignment specified in alloca instruction.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%PackedStruct = type <{ i64 }>
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, i1, [15 x i8], %PackedStruct }
declare void @consume(ptr)
define ptr @f() presplitcoroutine {
-; CHECK-LABEL: define ptr @f() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
-; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%data = alloca %PackedStruct, align 32
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -67,3 +52,40 @@ declare void @llvm.coro.end(ptr, i1, token)
declare noalias ptr @malloc(i32)
declare double @print(double)
declare void @free(ptr)
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 32 dereferenceable(64) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 32 dereferenceable(64) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 32 dereferenceable(64) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
index 4b4805d660344..6e53e167ab220 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
@@ -1,10 +1,9 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we can spills coro.begin from an inlined inner coroutine.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%g.Frame = type { ptr, ptr, i32, i1, i32 }
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, ptr, i1 }
@g.resumers = private constant [3 x ptr] [ptr @g.dummy, ptr @g.dummy, ptr @g.dummy]
@@ -13,22 +12,6 @@ declare void @g.dummy(ptr)
declare ptr @g()
define ptr @f() presplitcoroutine {
-; CHECK-LABEL: define ptr @f() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 32)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INNERID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @g, ptr @g.resumers)
-; CHECK-NEXT: [[INNERHDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[INNERID]], ptr null)
-; CHECK-NEXT: [[INNERHDL_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store ptr [[INNERHDL]], ptr [[INNERHDL_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -74,3 +57,45 @@ declare void @llvm.coro.end(ptr, i1, token)
declare noalias ptr @malloc(i32)
declare void @print.i32(i32)
declare void @free(ptr)
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 32)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INNERID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @g, ptr @g.resumers)
+; CHECK-NEXT: [[INNERHDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[INNERID]], ptr null)
+; CHECK-NEXT: [[INNERHDL_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store ptr [[INNERHDL]], ptr [[INNERHDL_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[INNERHDL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INNERHDL_RELOAD:%.*]] = load ptr, ptr [[INNERHDL_RELOAD_ADDR]], align 8
+; CHECK-NEXT: [[GVAR_ADDR:%.*]] = getelementptr inbounds [[G_FRAME:%.*]], ptr [[INNERHDL_RELOAD]], i32 0, i32 4
+; CHECK-NEXT: [[GVAR:%.*]] = load i32, ptr [[GVAR_ADDR]], align 4
+; CHECK-NEXT: call void @print.i32(i32 [[GVAR]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll b/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
index 946cf6991dc23..248dc9c1f7247 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
@@ -1,34 +1,14 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we would take care of the value written to promise before @llvm.coro.begin.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%"class.task::promise_type" = type { [64 x i8] }
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, i32, i1, [43 x i8], %"class.task::promise_type" }
declare void @consume(ptr)
declare void @consume2(ptr)
define ptr @f() presplitcoroutine {
-; CHECK-LABEL: define ptr @f() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[__PROMISE:%.*]] = alloca %"class.task::promise_type", align 64
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: call void @consume2(ptr [[__PROMISE]])
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 128)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
-; CHECK-NEXT: [[TMP1:%.*]] = load %"class.task::promise_type", ptr [[__PROMISE]], align 1
-; CHECK-NEXT: store %"class.task::promise_type" [[TMP1]], ptr [[TMP0]], align 1
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%data = alloca i32, align 4
%__promise = alloca %"class.task::promise_type", align 64
@@ -72,3 +52,47 @@ declare void @llvm.coro.end(ptr, i1, token)
declare noalias ptr @malloc(i32)
declare double @print(double)
declare void @free(ptr)
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[__PROMISE:%.*]] = alloca %"class.task::promise_type", align 64
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: call void @consume2(ptr [[__PROMISE]])
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 128)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[TMP1:%.*]] = load %"class.task::promise_type", ptr [[__PROMISE]], align 1
+; CHECK-NEXT: store %"class.task::promise_type" [[TMP1]], ptr [[TMP0]], align 1
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 64 dereferenceable(128) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume2(ptr [[__PROMISE_RELOAD_ADDR]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 64 dereferenceable(128) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 64 dereferenceable(128) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-promise.ll b/llvm/test/Transforms/Coroutines/coro-spill-promise.ll
index 861b29098581f..f57b67174eeb5 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-promise.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-promise.ll
@@ -1,29 +1,14 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that promise object is reloaded from the correct index of the coro frame.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%"class.task::promise_type" = type { [64 x i8] }
-; CHECK-LABEL: %f.Frame = type { ptr, ptr, i32, i1, [43 x i8], %"class.task::promise_type" }
declare void @consume(ptr)
declare void @consume2(ptr)
define ptr @f() presplitcoroutine {
-; CHECK-LABEL: define ptr @f() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 128)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%data = alloca i32, align 4
%__promise = alloca %"class.task::promise_type", align 64
@@ -65,3 +50,42 @@ declare void @llvm.coro.end(ptr, i1, token)
declare noalias ptr @malloc(i32)
declare double @print(double)
declare void @free(ptr)
+; CHECK-LABEL: define ptr @f() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 128)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 64 dereferenceable(128) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
+; CHECK-NEXT: call void @consume2(ptr [[__PROMISE_RELOAD_ADDR]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 64 dereferenceable(128) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 64 dereferenceable(128) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll b/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
index ba6a2a7d6bb3b..c7fcf0061b51d 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that the return value of @llvm.coro.suspend gets spilled to the frame
; if it may be used across suspend points.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
@@ -12,24 +12,8 @@
; depends on whether the coroutine was resumed or not.
-; CHECK: %f.Frame = type { ptr, ptr, i1, i8 }
define ptr @f(i32 %n) presplitcoroutine {
-; CHECK-LABEL: define ptr @f(
-; CHECK-SAME: i32 [[N:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
-; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i8 -1, ptr [[SP1_SPILL_ADDR]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -65,3 +49,94 @@ suspend:
declare noalias ptr @malloc(i32)
declare void @print(i8)
declare void @free(ptr)
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: i32 [[N:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
+; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i8 -1, ptr [[SP1_SPILL_ADDR]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*]]:
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX:%.*]] = load i1, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: switch i1 [[INDEX]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i1 false, label %[[AFTERCOROSUSPEND:.*]]
+; CHECK-NEXT: i1 true, label %[[AFTERCOROSUSPEND3:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i8 0, ptr [[SP1_SPILL_ADDR]], align 1
+; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND3]]
+; CHECK: [[AFTERCOROSUSPEND3]]:
+; CHECK-NEXT: [[TMP0:%.*]] = phi i8 [ -1, %[[AFTERCOROSUSPEND]] ], [ 0, %[[ENTRY_RESUME]] ]
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[TMP0]], 0
+; CHECK-NEXT: br i1 [[COND]], label %[[CLEANUP:.*]], label %[[COROEND:.*]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[SP1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[SP1_RELOAD:%.*]] = load i8, ptr [[SP1_RELOAD_ADDR]], align 1
+; CHECK-NEXT: call void @print(i8 [[SP1_RELOAD]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: br label %[[COROEND]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX:%.*]] = load i1, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: switch i1 [[INDEX]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i1 false, label %[[AFTERCOROSUSPEND:.*]]
+; CHECK-NEXT: i1 true, label %[[CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i8 1, ptr [[SP1_SPILL_ADDR]], align 1
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[SP1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[SP1_RELOAD:%.*]] = load i8, ptr [[SP1_RELOAD_ADDR]], align 1
+; CHECK-NEXT: call void @print(i8 [[SP1_RELOAD]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX:%.*]] = load i1, ptr [[INDEX_ADDR]], align 1
+; CHECK-NEXT: switch i1 [[INDEX]], label %[[UNREACHABLE:.*]] [
+; CHECK-NEXT: i1 false, label %[[AFTERCOROSUSPEND:.*]]
+; CHECK-NEXT: i1 true, label %[[CLEANUP:.*]]
+; CHECK-NEXT: ]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i8 1, ptr [[SP1_SPILL_ADDR]], align 1
+; CHECK-NEXT: br label %[[CLEANUP]]
+; CHECK: [[CLEANUP]]:
+; CHECK-NEXT: [[SP1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[SP1_RELOAD:%.*]] = load i8, ptr [[SP1_RELOAD_ADDR]], align 1
+; CHECK-NEXT: call void @print(i8 [[SP1_RELOAD]])
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+; CHECK: [[UNREACHABLE]]:
+; CHECK-NEXT: unreachable
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
index b2a6555373ec1..e2811b02101f6 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Tests that coro-split will optimize the lifetime.start maker of each local variable,
; sink them to the places after the suspend block.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse,simplifycfg' -S | FileCheck %s
@@ -8,28 +8,11 @@
%"struct.std::coroutine_handle.0" = type { %"struct.std::coroutine_handle" }
%"struct.lean_future<int>::Awaiter" = type { i32, %"struct.std::coroutine_handle.0" }
-; CHECK: %a.Frame = type { ptr, ptr, i1 }
-; CHECK: %a_optnone.Frame = type { ptr, ptr, i32, i1 }
declare ptr @malloc(i64)
declare void @print(i32)
define void @a() presplitcoroutine {
-; CHECK-LABEL: define void @a() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
-; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @a.resume, ptr [[VFRAME]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
-; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
-; CHECK-NEXT: ret void
-;
entry:
%ref.tmp7 = alloca %"struct.lean_future<int>::Awaiter", align 8
%testval = alloca i32
@@ -60,48 +43,6 @@ exit:
define void @a_optnone() presplitcoroutine optnone noinline {
-; CHECK-LABEL: define void @a_optnone(
-; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a_optnone.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
-; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 0
-; CHECK-NEXT: store ptr @a_optnone.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 1
-; CHECK-NEXT: store ptr @a_optnone.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
-; CHECK: [[ALLOCASPILLBB]]:
-; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: br label %[[POSTSPILL:.*]]
-; CHECK: [[POSTSPILL]]:
-; CHECK-NEXT: br label %[[COROSAVE:.*]]
-; CHECK: [[COROSAVE]]:
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
-; CHECK: [[COROSUSPEND]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 -1, 0
-; CHECK-NEXT: br i1 [[COND]], label %[[AWAIT_READY:.*]], label %[[EXIT:.*]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: br label %[[EXIT]]
-; CHECK: [[EXIT]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
-; CHECK: [[AFTERCOROEND]]:
-; CHECK-NEXT: ret void
-;
entry:
%ref.tmp7 = alloca %"struct.lean_future<int>::Awaiter", align 8
%testval = alloca i32
@@ -144,3 +85,174 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly) #2
declare void @llvm.coro.end(ptr, i1, token) #3
declare void @llvm.lifetime.start.p0(ptr nocapture) #4
declare void @llvm.lifetime.end.p0(ptr nocapture) #4
+; CHECK-LABEL: define void @a() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
+; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @a.resume, ptr [[VFRAME]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define void @a_optnone(
+; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a_optnone.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
+; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 0
+; CHECK-NEXT: store ptr @a_optnone.resume, ptr [[RESUME_ADDR]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: store ptr @a_optnone.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
+; CHECK: [[ALLOCASPILLBB]]:
+; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: br label %[[POSTSPILL:.*]]
+; CHECK: [[POSTSPILL]]:
+; CHECK-NEXT: br label %[[COROSAVE:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
+; CHECK: [[COROSUSPEND]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 -1, 0
+; CHECK-NEXT: br i1 [[COND]], label %[[AWAIT_READY:.*]], label %[[EXIT:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @a.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TESTVAL]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @a.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @a.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @a_optnone.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_OPTNONE_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
+; CHECK: [[RESUME_ENTRY]]:
+; CHECK-NEXT: br label %[[RESUME_0:.*]]
+; CHECK: [[RESUME_0]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 0, 0
+; CHECK-NEXT: br i1 [[COND]], label %[[AWAIT_READY:.*]], label %[[EXIT:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @a_optnone.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_OPTNONE_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
+; CHECK: [[RESUME_ENTRY]]:
+; CHECK-NEXT: br label %[[RESUME_0:.*]]
+; CHECK: [[RESUME_0]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 1, 0
+; CHECK-NEXT: br i1 [[COND]], label %[[AWAIT_READY:.*]], label %[[EXIT:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @a_optnone.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_OPTNONE_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
+; CHECK: [[RESUME_ENTRY]]:
+; CHECK-NEXT: br label %[[RESUME_0:.*]]
+; CHECK: [[RESUME_0]]:
+; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
+; CHECK: [[RESUME_0_LANDING]]:
+; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
+; CHECK: [[AFTERCOROSUSPEND]]:
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 1, 0
+; CHECK-NEXT: br i1 [[COND]], label %[[AWAIT_READY:.*]], label %[[EXIT:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: br label %[[EXIT]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: br label %[[COROEND:.*]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
index 23e5cb80de012..b3347cb8366d7 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
@@ -1,4 +1,4 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Tests that coro-split will optimize the lifetime.start maker of each local variable,
; sink them to the places after the suspend block.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
@@ -12,35 +12,6 @@ declare ptr @malloc(i64)
declare void @print(i32)
define void @a() presplitcoroutine {
-; CHECK-LABEL: define void @a() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
-; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @a.resume, ptr [[VFRAME]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
-; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: [[TESTCOND:%.*]] = call i1 @getcond()
-; CHECK-NEXT: br i1 [[TESTCOND]], label %[[COROSAVE:.*]], label %[[AFTER_AWAIT:.*]]
-; CHECK: [[COROSAVE]]:
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: br i1 false, label %[[AWAIT_READY:.*]], label %[[AFTERCOROEND:.*]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: br label %[[AFTER_AWAIT]]
-; CHECK: [[AFTER_AWAIT]]:
-; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST1]])
-; CHECK-NEXT: br label %[[AFTERCOROEND]]
-; CHECK: [[AFTERCOROEND]]:
-; CHECK-NEXT: ret void
-;
entry:
%ref.tmp7 = alloca %"struct.lean_future<int>::Awaiter", align 8
%testval = alloca i32
@@ -97,3 +68,86 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly) #2
declare void @llvm.coro.end(ptr, i1, token) #3
declare void @llvm.lifetime.start.p0(ptr nocapture) #4
declare void @llvm.lifetime.end.p0(ptr nocapture) #4
+; CHECK-LABEL: define void @a() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a.resumers)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
+; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
+; CHECK-NEXT: store ptr @a.resume, ptr [[VFRAME]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: [[TESTCOND:%.*]] = call i1 @getcond()
+; CHECK-NEXT: br i1 [[TESTCOND]], label %[[COROSAVE:.*]], label %[[AFTER_AWAIT:.*]]
+; CHECK: [[COROSAVE]]:
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: br i1 false, label %[[AWAIT_READY:.*]], label %[[AFTERCOROEND:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: br label %[[AFTER_AWAIT]]
+; CHECK: [[AFTER_AWAIT]]:
+; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST1]])
+; CHECK-NEXT: br label %[[AFTERCOROEND]]
+; CHECK: [[AFTERCOROEND]]:
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @a.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: br i1 true, label %[[AWAIT_READY:.*]], label %[[COROEND:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST1]])
+; CHECK-NEXT: br label %[[COROEND]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @a.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: br i1 false, label %[[AWAIT_READY:.*]], label %[[COROEND:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST1]])
+; CHECK-NEXT: br label %[[COROEND]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @a.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
+; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: br i1 false, label %[[AWAIT_READY:.*]], label %[[COROEND:.*]]
+; CHECK: [[AWAIT_READY]]:
+; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
+; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST]])
+; CHECK-NEXT: call void @print(i32 [[VAL]])
+; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[TEST1]])
+; CHECK-NEXT: br label %[[COROEND]]
+; CHECK: [[COROEND]]:
+; CHECK-NEXT: ret void
+;
diff --git a/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll b/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
index a61e877bf8040..196c82ea81ee3 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
@@ -1,32 +1,8 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Tests that coro-split pass generates TBAA metadata on coroutine frame slot reloads.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
define ptr @f(ptr %p) presplitcoroutine {
-; CHECK-LABEL: define ptr @f(
-; CHECK-SAME: ptr [[P:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*]]:
-; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4, !tbaa [[INT_TBAA0:![0-9]+]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[NEED_ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
-; CHECK-NEXT: br i1 [[NEED_ALLOC]], label %[[DYN_ALLOC:.*]], label %[[BEGIN:.*]]
-; CHECK: [[DYN_ALLOC]]:
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
-; CHECK-NEXT: br label %[[BEGIN]]
-; CHECK: [[BEGIN]]:
-; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOC]], %[[DYN_ALLOC]] ], [ null, %[[ENTRY]] ]
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[NEED_ALLOC]], ptr @f.destroy, ptr @f.cleanup
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 0)
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%x = load i32, ptr %p, !tbaa !3
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -78,6 +54,53 @@ declare void @llvm.coro.end(ptr, i1, token)
declare noalias ptr @malloc(i32) allockind("alloc,uninitialized") "alloc-family"="malloc"
declare void @print(i32)
declare void @free(ptr) willreturn allockind("free") "alloc-family"="malloc"
+; CHECK-LABEL: define ptr @f(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4, !tbaa [[INT_TBAA0:![0-9]+]]
+; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
+; CHECK-NEXT: [[NEED_ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
+; CHECK-NEXT: br i1 [[NEED_ALLOC]], label %[[DYN_ALLOC:.*]], label %[[BEGIN:.*]]
+; CHECK: [[DYN_ALLOC]]:
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
+; CHECK-NEXT: br label %[[BEGIN]]
+; CHECK: [[BEGIN]]:
+; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOC]], %[[DYN_ALLOC]] ], [ null, %[[ENTRY]] ]
+; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI]])
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[NEED_ALLOC]], ptr @f.destroy, ptr @f.cleanup
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 0)
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret ptr [[HDL]]
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4
+; CHECK-NEXT: call void @print(i32 [[X_RELOAD]])
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[HDL]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @f.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: ret void
+;
;.
; CHECK: [[INT_TBAA0]] = !{[[META1:![0-9]+]], [[META1]], i64 0}
; CHECK: [[META1]] = !{!"int", [[META2:![0-9]+]], i64 0}
diff --git a/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll b/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll
index 2b4a6c85998b3..973015fd13aff 100644
--- a/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll
+++ b/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll
@@ -1,7 +1,6 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %foo.Frame = type { ptr, ptr, i32, i16, i1 }
declare ptr @malloc(i64)
declare void @free(ptr)
@@ -17,18 +16,6 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly)
declare token @llvm.coro.save(ptr)
define void @foo() presplitcoroutine {
-; CHECK-LABEL: define void @foo() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[CORO_ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @foo.resumers)
-; CHECK-NEXT: [[CORO_ALLOC:%.*]] = call ptr @malloc(i64 24)
-; CHECK-NEXT: [[CORO_STATE:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[CORO_ID]], ptr [[CORO_ALLOC]])
-; CHECK-NEXT: store ptr @foo.resume, ptr [[CORO_STATE]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[FOO_FRAME:%.*]], ptr [[CORO_STATE]], i32 0, i32 1
-; CHECK-NEXT: store ptr @foo.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[FOO_FRAME]], ptr [[CORO_STATE]], i32 0, i32 4
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: ret void
-;
entry:
%a0 = alloca [0 x i8]
%a1 = alloca i32
@@ -67,3 +54,44 @@ cleanup: ; preds = %wakeup, %entry
}
+; CHECK-LABEL: define void @foo() {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[CORO_ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @foo.resumers)
+; CHECK-NEXT: [[CORO_ALLOC:%.*]] = call ptr @malloc(i64 24)
+; CHECK-NEXT: [[CORO_STATE:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[CORO_ID]], ptr [[CORO_ALLOC]])
+; CHECK-NEXT: store ptr @foo.resume, ptr [[CORO_STATE]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[FOO_FRAME:%.*]], ptr [[CORO_STATE]], i32 0, i32 1
+; CHECK-NEXT: store ptr @foo.destroy, ptr [[DESTROY_ADDR]], align 8
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[FOO_FRAME]], ptr [[CORO_STATE]], i32 0, i32 4
+; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @foo.resume(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[CORO_STATE:%.*]]) {
+; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
+; CHECK-NEXT: [[A1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME:%.*]], ptr [[CORO_STATE]], i32 0, i32 2
+; CHECK-NEXT: [[A4_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[CORO_STATE]], i32 0, i32 3
+; CHECK-NEXT: call void @usePointer(ptr [[CORO_STATE]])
+; CHECK-NEXT: call void @usePointer(ptr [[A1_RELOAD_ADDR]])
+; CHECK-NEXT: call void @usePointer(ptr [[CORO_STATE]])
+; CHECK-NEXT: call void @usePointer(ptr [[CORO_STATE]])
+; CHECK-NEXT: call void @usePointer(ptr [[A4_RELOAD_ADDR]])
+; CHECK-NEXT: call void @usePointer2(ptr [[CORO_STATE]])
+; CHECK-NEXT: call void @free(ptr [[CORO_STATE]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @foo.destroy(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[CORO_STATE:%.*]]) {
+; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
+; CHECK-NEXT: call void @free(ptr [[CORO_STATE]])
+; CHECK-NEXT: ret void
+;
+;
+; CHECK-LABEL: define internal fastcc void @foo.cleanup(
+; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[CORO_STATE:%.*]]) {
+; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
+; CHECK-NEXT: call void @free(ptr null)
+; CHECK-NEXT: ret void
+;
>From 19422018fdb98338d6371add4abeab588564f2b1 Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash at gmail.com>
Date: Wed, 28 Jan 2026 15:59:31 +0000
Subject: [PATCH 3/7] move orphaned comments either to top of file or function
---
llvm/test/Transforms/Coroutines/coro-align16.ll | 1 +
llvm/test/Transforms/Coroutines/coro-align32.ll | 1 +
llvm/test/Transforms/Coroutines/coro-align64-02.ll | 1 +
llvm/test/Transforms/Coroutines/coro-align64.ll | 1 +
llvm/test/Transforms/Coroutines/coro-align8.ll | 1 +
.../Transforms/Coroutines/coro-alloc-with-param-O0.ll | 8 +-------
.../Transforms/Coroutines/coro-alloc-with-param-O2.ll | 8 +-------
llvm/test/Transforms/Coroutines/coro-alloca-07.ll | 3 +--
llvm/test/Transforms/Coroutines/coro-async.ll | 7 ++-----
.../Coroutines/coro-eh-aware-edge-split-01.ll | 8 ++------
.../Coroutines/coro-eh-aware-edge-split-02.ll | 7 ++-----
.../Transforms/Coroutines/coro-frame-arrayalloca.ll | 10 +++-------
llvm/test/Transforms/Coroutines/coro-frame.ll | 9 ++-------
llvm/test/Transforms/Coroutines/coro-padding.ll | 6 ------
.../test/Transforms/Coroutines/coro-spill-corobegin.ll | 9 ++-------
15 files changed, 21 insertions(+), 59 deletions(-)
diff --git a/llvm/test/Transforms/Coroutines/coro-align16.ll b/llvm/test/Transforms/Coroutines/coro-align16.ll
index bfc16e033c0bb..6d482064c0d3e 100644
--- a/llvm/test/Transforms/Coroutines/coro-align16.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align16.ll
@@ -18,6 +18,7 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: ret ptr [[HDL]]
;
entry:
+ ; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
%x = alloca i64, align 16
%y = alloca i64
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
diff --git a/llvm/test/Transforms/Coroutines/coro-align32.ll b/llvm/test/Transforms/Coroutines/coro-align32.ll
index 7cdaef8b0d813..673bf1f7bad6f 100644
--- a/llvm/test/Transforms/Coroutines/coro-align32.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align32.ll
@@ -18,6 +18,7 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: ret ptr [[HDL]]
;
entry:
+ ; All allocas need to go to the frame since they're escaped.
%x = alloca i64, align 16
%y = alloca i32, align 32
%z = alloca i32, align 16
diff --git a/llvm/test/Transforms/Coroutines/coro-align64-02.ll b/llvm/test/Transforms/Coroutines/coro-align64-02.ll
index 80a8cdf827e23..6e45fc8462f3d 100644
--- a/llvm/test/Transforms/Coroutines/coro-align64-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align64-02.ll
@@ -18,6 +18,7 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: ret ptr [[HDL]]
;
entry:
+ ; Both %x and %y need to go to the frame since they're escaped.
%x = alloca i1, align 64
%y = alloca i64, align 32
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
diff --git a/llvm/test/Transforms/Coroutines/coro-align64.ll b/llvm/test/Transforms/Coroutines/coro-align64.ll
index 6717093780f68..bbae259c42102 100644
--- a/llvm/test/Transforms/Coroutines/coro-align64.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align64.ll
@@ -18,6 +18,7 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: ret ptr [[HDL]]
;
entry:
+ ; Both %x and %y need to go to the frame since they're escaped.
%x = alloca i1, align 64
%y = alloca i64
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
diff --git a/llvm/test/Transforms/Coroutines/coro-align8.ll b/llvm/test/Transforms/Coroutines/coro-align8.ll
index 045b3ed2f774e..2f9c7527187aa 100644
--- a/llvm/test/Transforms/Coroutines/coro-align8.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align8.ll
@@ -18,6 +18,7 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: ret ptr [[HDL]]
;
entry:
+ ; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
%x = alloca i64
%y = alloca i64
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
index eea25cef71dea..ae6f8c78cad6d 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
@@ -1,9 +1,9 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we can handle the case when both alloc function and
; the user body consume the same argument.
+; Verify that %this is added to the frame, spilled into the frame, and loaded from the frame.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-
; using copy of this (as it would happen under -O0)
define ptr @f_copy(i64 %this_arg) presplitcoroutine {
entry:
@@ -30,12 +30,6 @@ suspend:
ret ptr %hdl
}
-; See if %this was added to the frame
-
-; See that %this is spilled into the frame
-
-; See that %this was loaded from the frame
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
index 6ffaaba189fdb..6ba13750ce943 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
@@ -1,9 +1,9 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Check that we can handle the case when both alloc function and
; the user body consume the same argument.
+; Verify that %this is added to the frame, spilled into the frame, and loaded from the frame.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-
; using this directly (as it would happen under -O2)
define ptr @f_direct(i64 %this) presplitcoroutine {
entry:
@@ -27,12 +27,6 @@ suspend:
ret ptr %hdl
}
-; See if %this was added to the frame
-
-; See that %this is spilled into the frame
-
-; See that %this was loaded from the frame
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-07.ll b/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
index a23966457c0ec..586076321565c 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
@@ -1,6 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Tests that CoroSplit can succesfully determine allocas should live on the frame
; if their aliases are used across suspension points through PHINode.
+; Verify that both x and y are put in the frame.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
@@ -59,8 +60,6 @@ declare void @print(ptr)
declare noalias ptr @malloc(i32)
declare void @free(ptr)
-; Verify that both x and y are put in the frame.
-
; CHECK-LABEL: define ptr @f(
; CHECK-SAME: i1 [[N:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*]]:
diff --git a/llvm/test/Transforms/Coroutines/coro-async.ll b/llvm/test/Transforms/Coroutines/coro-async.ll
index 86b631604a2e5..0c3289b2bfc10 100644
--- a/llvm/test/Transforms/Coroutines/coro-async.ll
+++ b/llvm/test/Transforms/Coroutines/coro-async.ll
@@ -87,6 +87,7 @@ entry:
; store caller context into callee context
store ptr %async.ctxt, ptr %callee_context
+ ; Make sure the spill is underaligned to the max context alignment (16).
%vector_spill = load <4 x double>, ptr %vector, align 16
%res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
ptr %resume.func_ptr,
@@ -106,17 +107,13 @@ entry:
unreachable
}
+; Make sure we update the async function pointer
define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) {
call void @llvm.coro.async.size.replace(ptr @my_async_function_pa_fp, ptr @my_async_function_fp)
call swiftcc void @my_async_function(ptr %ctxt, ptr %task, ptr %actor)
ret void
}
-; Make sure we update the async function pointer
-
-; Make sure the spill is underaligned to the max context alignment (16).
-
-
@my_async_function2_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
i64 sub (
diff --git a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
index e5fe1417dd19f..4983ab4b47922 100644
--- a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
-; Check that we can handle edge splits leading into a landingpad
+; Check that we can handle edge splits leading into a landingpad.
+; Verify that we create cleanuppads on every edge and insert a reload of the spilled value.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
@@ -27,11 +28,6 @@ invoke2:
invoke void @may_throw2()
to label %unreach unwind label %pad.with.phi
-; Verify that we created cleanuppads on every edge and inserted a reload of the spilled value
-
-
-
-
pad.with.phi:
%val = phi i32 [ %x, %invoke1 ], [ %y, %invoke2 ]
%tok = cleanuppad within none []
diff --git a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
index 344549205369d..a005a9c8e6167 100644
--- a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
-; Check that we can handle edge splits leading into a landingpad
+; Check that we can handle edge splits leading into a landingpad.
+; Verify that we create cleanuppads on every edge and insert a reload of the spilled value.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
@@ -27,10 +28,6 @@ invoke2:
invoke void @may_throw2()
to label %coro.ret unwind label %pad.with.phi
-; Verify that we created cleanuppads on every edge and inserted a reload of the spilled value
-
-
-
pad.with.phi:
%val = phi i32 [ %x, %invoke1 ], [ %y, %invoke2 ]
%switch = catchswitch within none [label %catch] unwind to caller
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll b/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
index 32afbc7faecd0..99adb44349aa7 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
@@ -1,5 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
-; Check that we can handle spills of array allocas
+; Check that we can handle spills of array allocas.
+; Verify that the array alloca is stored as an array field,
+; and we use the correct index to access prefix, data, and suffix.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
@@ -36,12 +38,6 @@ suspend:
ret ptr %hdl
}
-; See if the array alloca was stored as an array field.
-
-; See if we used correct index to access prefix, data, suffix (@f)
-
-; See if we used correct index to access prefix, data, suffix (@f.resume)
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
diff --git a/llvm/test/Transforms/Coroutines/coro-frame.ll b/llvm/test/Transforms/Coroutines/coro-frame.ll
index 34a1c6c8d3136..7f12362cd48ae 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
-; Check that we can handle spills of the result of the invoke instruction
+; Check that we can handle spills of the result of the invoke instruction.
+; Verify that the float result is added to the frame, spilled, and loaded correctly.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
@@ -35,12 +36,6 @@ pad:
cleanupret from %tok unwind to caller
}
-; See if the float was added to the frame
-
-; See if the float was spilled into the frame
-
-; See if the float was loaded from the frame
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
diff --git a/llvm/test/Transforms/Coroutines/coro-padding.ll b/llvm/test/Transforms/Coroutines/coro-padding.ll
index 89ad2f49730b8..9e4d5d95209ad 100644
--- a/llvm/test/Transforms/Coroutines/coro-padding.ll
+++ b/llvm/test/Transforms/Coroutines/coro-padding.ll
@@ -32,12 +32,6 @@ suspend:
ret ptr %hdl
}
-; See if the padding was inserted before PackedStruct
-
-; See if we used correct index to access packed struct (padding is field 3)
-
-; See if we used correct index to access packed struct (padding is field 3)
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
index 6e53e167ab220..1ef841faeab11 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
-; Check that we can spills coro.begin from an inlined inner coroutine.
+; Check that we can spill coro.begin from an inlined inner coroutine.
+; Verify that the inner coro.begin pointer is added to f.Frame, spilled, and loaded correctly.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
%g.Frame = type { ptr, ptr, i32, i1, i32 }
@@ -39,12 +40,6 @@ suspend:
ret ptr %hdl
}
-; See if the ptr for coro.begin was added to f.Frame
-
-; See if the g's coro.begin was spilled into the frame
-
-; See if the coro.begin was loaded from the frame
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
>From 358136f91852299ca08b75b9d22e9fe2ed70875a Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash at gmail.com>
Date: Tue, 3 Feb 2026 16:36:58 +0000
Subject: [PATCH 4/7] finish moving (and fixing) comments and remove some tests
from change that became much more verbose
---
.../Transforms/Coroutines/coro-align16.ll | 2 -
.../Transforms/Coroutines/coro-align32.ll | 2 -
.../Transforms/Coroutines/coro-align64-02.ll | 2 -
.../Transforms/Coroutines/coro-align64.ll | 2 -
.../Transforms/Coroutines/coro-align8-02.ll | 2 -
.../test/Transforms/Coroutines/coro-align8.ll | 2 -
.../Transforms/Coroutines/coro-alloca-01.ll | 3 +-
.../Transforms/Coroutines/coro-alloca-03.ll | 3 +-
.../Transforms/Coroutines/coro-alloca-04.ll | 3 +-
.../Transforms/Coroutines/coro-alloca-06.ll | 2 -
.../Transforms/Coroutines/coro-alloca-07.ll | 2 +-
.../Transforms/Coroutines/coro-alloca-08.ll | 3 +-
.../Coroutines/coro-alloca-outside-frame.ll | 8 +-
.../Coroutines/coro-alloca-with-addrspace.ll | 57 +-
llvm/test/Transforms/Coroutines/coro-async.ll | 1025 ++-------
.../coro-await-suspend-lower-invoke.ll | 2 -
.../Coroutines/coro-await-suspend-lower.ll | 2 -
.../Coroutines/coro-debug-coro-frame.ll | 1850 +++--------------
.../Transforms/Coroutines/coro-materialize.ll | 177 +-
.../Coroutines/coro-spill-suspend.ll | 8 +-
.../coro-split-dbg-nested-struct.ll | 7 -
.../Coroutines/coro-split-sink-lifetime-01.ll | 192 +-
.../Coroutines/coro-split-sink-lifetime-02.ll | 92 +-
23 files changed, 514 insertions(+), 2934 deletions(-)
diff --git a/llvm/test/Transforms/Coroutines/coro-align16.ll b/llvm/test/Transforms/Coroutines/coro-align16.ll
index 6d482064c0d3e..6ff6576a4bc8e 100644
--- a/llvm/test/Transforms/Coroutines/coro-align16.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align16.ll
@@ -44,8 +44,6 @@ suspend:
ret ptr %hdl
}
-; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i32 @llvm.coro.align.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-align32.ll b/llvm/test/Transforms/Coroutines/coro-align32.ll
index 673bf1f7bad6f..f95bf690e4f75 100644
--- a/llvm/test/Transforms/Coroutines/coro-align32.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align32.ll
@@ -48,8 +48,6 @@ suspend:
ret ptr %hdl
}
-; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i32 @llvm.coro.align.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-align64-02.ll b/llvm/test/Transforms/Coroutines/coro-align64-02.ll
index 6e45fc8462f3d..1be0c0bb7e292 100644
--- a/llvm/test/Transforms/Coroutines/coro-align64-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align64-02.ll
@@ -44,8 +44,6 @@ suspend:
ret ptr %hdl
}
-; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i32 @llvm.coro.align.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-align64.ll b/llvm/test/Transforms/Coroutines/coro-align64.ll
index bbae259c42102..a264d614a4a99 100644
--- a/llvm/test/Transforms/Coroutines/coro-align64.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align64.ll
@@ -44,8 +44,6 @@ suspend:
ret ptr %hdl
}
-; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i32 @llvm.coro.align.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-align8-02.ll b/llvm/test/Transforms/Coroutines/coro-align8-02.ll
index bfdf36de31ee8..b4c199d5c5173 100644
--- a/llvm/test/Transforms/Coroutines/coro-align8-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align8-02.ll
@@ -39,8 +39,6 @@ suspend:
ret ptr %hdl
}
-; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i32 @llvm.coro.align.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-align8.ll b/llvm/test/Transforms/Coroutines/coro-align8.ll
index 2f9c7527187aa..6c2e7afe58ac6 100644
--- a/llvm/test/Transforms/Coroutines/coro-align8.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align8.ll
@@ -44,8 +44,6 @@ suspend:
ret ptr %hdl
}
-; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i32 @llvm.coro.align.i32()
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-01.ll b/llvm/test/Transforms/Coroutines/coro-alloca-01.ll
index c7350277d2947..51d72bfaa2d29 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-01.ll
@@ -29,6 +29,7 @@ define ptr @f(i1 %n) presplitcoroutine {
; CHECK-NEXT: ret ptr [[HDL]]
;
entry:
+ ; both %x and %y, as well as %alias_phi would all go to the frame.
%x = alloca i64
%y = alloca i64
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -62,8 +63,6 @@ suspend:
ret ptr %hdl
}
-; both %x and %y, as well as %alias_phi would all go to the frame.
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-03.ll b/llvm/test/Transforms/Coroutines/coro-alloca-03.ll
index 69b9abfbb0d0f..4609cf8403dd4 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-03.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-03.ll
@@ -22,6 +22,7 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: ret ptr [[HDL]]
;
entry:
+ ; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
%x = alloca i64
%y = alloca i64
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
@@ -46,8 +47,6 @@ suspend:
ret ptr %hdl
}
-; %x needs to go to the frame since it's escaped; %y will stay as local since it doesn't escape.
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-04.ll b/llvm/test/Transforms/Coroutines/coro-alloca-04.ll
index 12b104c9a9ad5..2839e9c7e5581 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-04.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-04.ll
@@ -23,6 +23,7 @@ define ptr @f(i1 %n) presplitcoroutine {
; CHECK-NEXT: ret ptr [[HDL]]
;
entry:
+ ; both %x and %alias_phi would go to the frame.
%x = alloca i64
br i1 %n, label %flag_true, label %flag_false
@@ -55,8 +56,6 @@ suspend:
ret ptr %hdl
}
-; both %x and %alias_phi would go to the frame.
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-06.ll b/llvm/test/Transforms/Coroutines/coro-alloca-06.ll
index ffca0534b5ec0..bf338b1aedbe2 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-06.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-06.ll
@@ -64,8 +64,6 @@ suspend:
}
-;
-
declare ptr @llvm.coro.free(token, ptr)
declare i32 @llvm.coro.size.i32()
declare i8 @llvm.coro.suspend(token, i1)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-07.ll b/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
index 586076321565c..5a37387ed4492 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
@@ -1,12 +1,12 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Tests that CoroSplit can succesfully determine allocas should live on the frame
; if their aliases are used across suspension points through PHINode.
-; Verify that both x and y are put in the frame.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
define ptr @f(i1 %n) presplitcoroutine {
entry:
+ ; Verify that both x and y are put in the frame.
%x = alloca i64
%y = alloca i64
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-08.ll b/llvm/test/Transforms/Coroutines/coro-alloca-08.ll
index 929b63b18d18f..d267e49acc056 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-08.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-08.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; Verify that for both foo and bar, testval isn't put on the frame.
%"struct.std::coroutine_handle" = type { ptr }
%"struct.std::coroutine_handle.0" = type { %"struct.std::coroutine_handle" }
@@ -103,8 +104,6 @@ exit:
ret void
}
-; Verify that for both foo and bar, testval isn't put on the frame.
-
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
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll b/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll
index 2207e00439509..e93e97fb06643 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll
@@ -1,10 +1,7 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that CoroSplit can succesfully skip allocas that shall not live on the frame
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S -o %t.ll
; RUN: FileCheck --input-file=%t.ll %s
-; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
-
define ptr @f(i1 %n) presplitcoroutine {
entry:
%x = alloca i64, !coro.outside.frame !{}
@@ -25,7 +22,7 @@ merge:
%alias_phi = phi ptr [ %x, %flag_true ], [ %y, %flag_false ]
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume:
call void @print(ptr %alias_phi)
br label %cleanup
@@ -41,6 +38,7 @@ suspend:
}
; %y and %alias_phi would all go to the frame, but not %x
+; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
; CHECK-LABEL: @f(
; CHECK: %x = alloca i64, align 8, !coro.outside.frame !0
; CHECK-NOT: %x.reload.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
@@ -60,4 +58,4 @@ declare void @llvm.coro.end(ptr, i1, token)
declare void @print(ptr)
declare noalias ptr @malloc(i32)
-declare void @free(ptr)
+declare void @free(ptr)
\ No newline at end of file
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll b/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll
index 007af29f1fad8..8c23147ee6072 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll
@@ -1,70 +1,31 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
-; RUN: opt < %s -passes='cgscc(coro-split)' -S | FileCheck %s
+; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+
+; Test that reloaded addresses are correctly addrspacecast to the original addrspace.
define ptr @f(i1 %n) presplitcoroutine {
; CHECK-LABEL: define ptr @f(
; CHECK-SAME: i1 [[N:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[X:%.*]] = alloca i64, align 8, addrspace(5)
-; CHECK-NEXT: [[Y:%.*]] = alloca i64, align 8, addrspace(5)
+; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 48)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
-; CHECK: [[ALLOCASPILLBB]]:
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = addrspacecast ptr [[TMP0]] to ptr addrspace(5)
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = addrspacecast ptr [[TMP1]] to ptr addrspace(5)
-; CHECK-NEXT: br label %[[POSTSPILL:.*]]
-; CHECK: [[POSTSPILL]]:
; CHECK-NEXT: br i1 [[N]], label %[[FLAG_TRUE:.*]], label %[[FLAG_FALSE:.*]]
-; CHECK: [[FLAG_TRUE]]:
-; CHECK-NEXT: br label %[[MERGE_FROM_FLAG_TRUE:.*]]
-; CHECK: [[MERGE_FROM_FLAG_TRUE]]:
-; CHECK-NEXT: [[X_MERGE:%.*]] = phi ptr addrspace(5) [ [[X_RELOAD_ADDR]], %[[FLAG_TRUE]] ]
-; CHECK-NEXT: br label %[[MERGE:.*]]
; CHECK: [[FLAG_FALSE]]:
-; CHECK-NEXT: br label %[[MERGE_FROM_FLAG_FALSE:.*]]
-; CHECK: [[MERGE_FROM_FLAG_FALSE]]:
-; CHECK-NEXT: [[Y_MERGE:%.*]] = phi ptr addrspace(5) [ [[Y_RELOAD_ADDR]], %[[FLAG_FALSE]] ]
-; CHECK-NEXT: br label %[[MERGE]]
-; CHECK: [[MERGE]]:
-; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr addrspace(5) [ [[X_MERGE]], %[[MERGE_FROM_FLAG_TRUE]] ], [ [[Y_MERGE]], %[[MERGE_FROM_FLAG_FALSE]] ]
+; CHECK-NEXT: br label %[[FLAG_TRUE]]
+; CHECK: [[FLAG_TRUE]]:
+; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr addrspace(5) [ [[Y_RELOAD_ADDR]], %[[FLAG_FALSE]] ], [ [[X_RELOAD_ADDR]], %[[ENTRY]] ]
; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
; CHECK-NEXT: store ptr addrspace(5) [[ALIAS_PHI]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
-; CHECK-NEXT: br label %[[COROSAVE:.*]]
-; CHECK: [[COROSAVE]]:
; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
-; CHECK: [[COROSUSPEND]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 -1, label %[[SUSPEND:.*]] [
-; CHECK-NEXT: i8 0, label %[[RESUME:.*]]
-; CHECK-NEXT: i8 1, label %[[CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[RESUME]]:
-; CHECK-NEXT: [[ALIAS_PHI_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
-; CHECK-NEXT: [[ALIAS_PHI_RELOAD:%.*]] = load ptr addrspace(5), ptr [[ALIAS_PHI_RELOAD_ADDR]], align 8
-; CHECK-NEXT: call void @print(ptr addrspace(5) [[ALIAS_PHI_RELOAD]])
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[MEM:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[HDL]])
-; CHECK-NEXT: call void @free(ptr [[MEM]])
-; CHECK-NEXT: br label %[[SUSPEND]]
-; CHECK: [[SUSPEND]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
-; CHECK: [[AFTERCOROEND]]:
; CHECK-NEXT: ret ptr [[HDL]]
;
entry:
diff --git a/llvm/test/Transforms/Coroutines/coro-async.ll b/llvm/test/Transforms/Coroutines/coro-async.ll
index 0c3289b2bfc10..f94c6c11aa8b1 100644
--- a/llvm/test/Transforms/Coroutines/coro-async.ll
+++ b/llvm/test/Transforms/Coroutines/coro-async.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; RUN: opt < %s -passes='default<O2>' -S | FileCheck --check-prefixes=CHECK %s
; RUN: opt < %s -O0 -S | FileCheck --check-prefixes=CHECK-O0 %s
target datalayout = "p:64:64:64"
@@ -20,21 +19,21 @@ declare void @my_other_async_function(ptr %async.ctxt)
@my_async_function_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @my_async_function to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @my_async_function to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
@my_async_function_pa_fp = constant <{ i32, i32 }>
<{ i32 trunc (
- i64 sub (
- i64 ptrtoint (ptr @my_async_function_pa to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_pa_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 8
+ i64 sub (
+ i64 ptrtoint (ptr @my_async_function_pa to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_pa_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 8
}>
; Function that implements the dispatch to the callee function.
@@ -67,13 +66,13 @@ entry:
%proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @my_async_function_fp)
+ ptr @my_async_function_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
store i64 0, ptr %proj.1, align 8
store i64 1, ptr %proj.2, align 8
call void @some_may_write(ptr %proj.1)
- ; Begin lowering: apply %my_other_async_function(%args...)
+ ; Begin lowering: apply %my_other_async_function(%args...)
; setup callee context
%callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
@@ -87,13 +86,12 @@ entry:
; store caller context into callee context
store ptr %async.ctxt, ptr %callee_context
- ; Make sure the spill is underaligned to the max context alignment (16).
%vector_spill = load <4 x double>, ptr %vector, align 16
%res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
- ptr %resume.func_ptr,
- ptr @__swift_async_resume_project_context,
- ptr @my_async_function.my_other_async_function_fp.apply,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !5
+ ptr %resume.func_ptr,
+ ptr @__swift_async_resume_project_context,
+ ptr @my_async_function.my_other_async_function_fp.apply,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !5
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
%continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1
@@ -107,21 +105,76 @@ entry:
unreachable
}
-; Make sure we update the async function pointer
define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) {
call void @llvm.coro.async.size.replace(ptr @my_async_function_pa_fp, ptr @my_async_function_fp)
call swiftcc void @my_async_function(ptr %ctxt, ptr %task, ptr %actor)
ret void
}
+; Make sure we update the async function pointer
+; CHECK: @my_async_function_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }
+; CHECK: @my_async_function_pa_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }
+; CHECK: @my_async_function2_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 }
+
+; CHECK-LABEL: define swiftcc void @my_async_function(ptr swiftasync initializes((152, 160)) %async.ctxt, ptr %task, ptr %actor)
+; CHECK-O0-LABEL: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor)
+; CHECK-SAME: !dbg ![[SP1:[0-9]+]] {
+; CHECK: coro.return:
+; CHECK: [[FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 128
+; CHECK: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 152
+; CHECK: store ptr %actor, ptr [[ACTOR_SPILL_ADDR]]
+; CHECK: [[ADDR1:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 144
+; CHECK: store ptr %async.ctxt, ptr [[ADDR1]]
+; CHECK: [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 136
+; CHECK: store i64 0, ptr [[FRAMEPTR]]
+; CHECK: store i64 1, ptr [[ALLOCA_PRJ2]]
+; CHECK: tail call void @some_may_write(ptr nonnull [[FRAMEPTR]])
+; CHECK: [[CALLEE_CTXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr %task, ptr nonnull @my_other_async_function_fp)
+; CHECK: [[CALLEE_CTXT_SPILL:%.*]] = getelementptr inbounds nuw i8, ptr %async.ctxt, i64 160
+; CHECK: store ptr [[CALLEE_CTXT]], ptr [[CALLEE_CTXT_SPILL]]
+; CHECK: [[TYPED_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CTXT]], i64 8
+; CHECK: store ptr @my_async_functionTQ0_, ptr [[TYPED_RETURN_TO_CALLER_ADDR]]
+; CHECK: store ptr %async.ctxt, ptr [[CALLEE_CTXT]]
+; Make sure the spill is underaligned to the max context alignment (16).
+; CHECK-O0: [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr {{.*}}
+; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1
+; CHECK-O0: store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_ADDR]], align 16
+; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor)
+; CHECK: ret void
+; CHECK: }
+
+; CHECK-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr readonly swiftasync captures(none) %0, ptr %1, ptr readnone captures(none) %2)
+; CHECK-O0-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr swiftasync %0, ptr %1, ptr %2)
+; CHECK-SAME: !dbg ![[SP2:[0-9]+]] {
+; CHECK: entryresume.0:
+; CHECK: [[CALLER_CONTEXT:%.*]] = load ptr, ptr %0
+; CHECK: [[FRAME_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 128
+; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1
+; CHECK-O0: load <4 x double>, ptr [[VECTOR_SPILL_ADDR]], align 16
+; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 160
+; CHECK: [[CALLEE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]]
+; CHECK: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 152
+; CHECK: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]]
+; CHECK: [[ADDR1:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 144
+; CHECK: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ADDR1]]
+; CHECK: [[ALLOCA_PRJ2:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 136
+; CHECK: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CTXT_RELOAD]])
+; CHECK: [[VAL1:%.*]] = load i64, ptr [[FRAME_PTR]]
+; CHECK: tail call void @some_user(i64 [[VAL1]])
+; CHECK: [[VAL2:%.*]] = load i64, ptr [[ALLOCA_PRJ2]]
+; CHECK: tail call void @some_user(i64 [[VAL2]])
+; CHECK: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr %1, ptr [[ACTOR_RELOAD]])
+; CHECK: ret void
+; CHECK: }
+
@my_async_function2_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @my_async_function2 to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function2_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @my_async_function2 to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function2_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) presplitcoroutine "frame-pointer"="all" !dbg !6 {
@@ -137,10 +190,10 @@ entry:
store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
store ptr %async.ctxt, ptr %callee_context
%res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 2,
- ptr %resume.func_ptr,
- ptr @resume_context_projection,
- ptr @my_async_function.my_other_async_function_fp.apply,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !9
+ ptr %resume.func_ptr,
+ ptr @resume_context_projection,
+ ptr @my_async_function.my_other_async_function_fp.apply,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor), !dbg !9
%continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 0
@@ -149,10 +202,10 @@ entry:
store ptr %resume.func_ptr.1, ptr %callee_context.return_to_caller.addr.1
store ptr %async.ctxt, ptr %callee_context
%res.2 = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
- ptr %resume.func_ptr.1,
- ptr @resume_context_projection,
- ptr @my_async_function.my_other_async_function_fp.apply,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
+ ptr %resume.func_ptr.1,
+ ptr @resume_context_projection,
+ ptr @my_async_function.my_other_async_function_fp.apply,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
%continuation_actor_arg = extractvalue {ptr, ptr, ptr} %res.2, 1
@@ -162,8 +215,33 @@ entry:
unreachable
}
-
-
+; CHECK-LABEL: define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt)
+; CHECK-SAME: #[[FRAMEPOINTER:[0-9]+]]
+; CHECK-SAME: !dbg ![[SP3:[0-9]+]]
+; CHECK: store ptr %async.ctxt,
+; CHECK: store ptr %actor,
+; CHECK: store ptr %task,
+; CHECK: [[CALLEE_CTXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(
+; CHECK: store ptr [[CALLEE_CTXT]],
+; CHECK: store ptr @my_async_function2.resume.0,
+; CHECK: store ptr %async.ctxt,
+; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor)
+; CHECK: ret void
+
+; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.0(ptr %0, ptr readnone captures(none) %1, ptr readonly captures(none) %2)
+; CHECK-SAME: #[[FRAMEPOINTER]]
+; CHECK-SAME: !dbg ![[SP4:[0-9]+]]
+; CHECK: [[CALLEE_CTXT:%.*]] = load ptr, ptr %2
+; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CTXT]], i64 152
+; CHECK: store ptr @my_async_function2.resume.1,
+; CHECK: [[CALLLE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]]
+; CHECK: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CTXT_RELOAD]]
+; CHECK: ret void
+
+; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.1(ptr readonly captures(none) %0, ptr %1, ptr readnone captures(none) %2)
+; CHECK-SAME: #[[FRAMEPOINTER]]
+; CHECK: tail call swiftcc void @asyncReturn({{.*}}%1)
+; CHECK: ret void
define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) {
%prepare = call ptr @llvm.coro.prepare.async(ptr @my_async_function)
@@ -171,15 +249,20 @@ define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) {
ret void
}
+; CHECK-LABEL: define swiftcc void @top_level_caller(ptr initializes((152, 160)) %ctxt, ptr %task, ptr %actor)
+; CHECK: store ptr @my_async_functionTQ0_
+; CHECK: store ptr %ctxt
+; CHECK: tail call swiftcc void @asyncSuspend
+; CHECK: ret void
@dont_crash_on_cf_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @my_async_function to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @my_async_function to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @my_async_function_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
@@ -198,7 +281,7 @@ is_not_null:
define swiftcc void @dont_crash_on_cf(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
entry:
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @dont_crash_on_cf_fp)
+ ptr @dont_crash_on_cf_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
%callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
%callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
@@ -206,10 +289,10 @@ entry:
store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
store ptr %async.ctxt, ptr %callee_context
%res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
- ptr %resume.func_ptr,
- ptr @resume_context_projection,
- ptr @dont_crash_on_cf_dispatch,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
+ ptr %resume.func_ptr,
+ ptr @resume_context_projection,
+ ptr @dont_crash_on_cf_dispatch,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
%continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1
@@ -220,12 +303,12 @@ entry:
@multiple_coro_end_async_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @multiple_coro_end_async to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @multiple_coro_end_async_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @multiple_coro_end_async to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @multiple_coro_end_async_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
define swiftcc void @must_tail_call_return(ptr %async.ctxt, ptr %task, ptr %actor) {
@@ -236,7 +319,7 @@ define swiftcc void @must_tail_call_return(ptr %async.ctxt, ptr %task, ptr %acto
define swiftcc void @multiple_coro_end_async(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
entry:
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @dont_crash_on_cf_fp)
+ ptr @dont_crash_on_cf_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
%callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
%callee_context.return_to_caller.addr = getelementptr inbounds %async.ctxt, ptr %callee_context, i32 0, i32 1
@@ -244,10 +327,10 @@ entry:
store ptr %resume.func_ptr, ptr %callee_context.return_to_caller.addr
store ptr %async.ctxt, ptr %callee_context
%res = call {ptr, ptr, ptr} (i32, ptr, ptr, ...) @llvm.coro.suspend.async(i32 0,
- ptr %resume.func_ptr,
- ptr @resume_context_projection,
- ptr @dont_crash_on_cf_dispatch,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
+ ptr %resume.func_ptr,
+ ptr @resume_context_projection,
+ ptr @dont_crash_on_cf_dispatch,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
%continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1
@@ -261,21 +344,24 @@ is_equal:
is_not_equal:
call void (ptr, i1, ...) @llvm.coro.end.async(
- ptr %hdl, i1 0,
- ptr @must_tail_call_return,
- ptr %async.ctxt, ptr %continuation_task_arg, ptr null)
+ ptr %hdl, i1 0,
+ ptr @must_tail_call_return,
+ ptr %async.ctxt, ptr %continuation_task_arg, ptr null)
unreachable
}
+; CHECK-LABEL: define internal swiftcc void @multiple_coro_end_async.resume.0(
+; CHECK: musttail call swiftcc void @asyncReturn(
+; CHECK: ret void
@polymorphic_suspend_return_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @polymorphic_suspend_return to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @polymorphic_suspend_return_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 64 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @polymorphic_suspend_return to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @polymorphic_suspend_return_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 64 ; Initial async context size without space for frame
}>
define swiftcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine {
@@ -285,13 +371,13 @@ entry:
%proj.2 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 1
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @polymorphic_suspend_return_fp)
+ ptr @polymorphic_suspend_return_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
store i64 0, ptr %proj.1, align 8
store i64 1, ptr %proj.2, align 8
call void @some_may_write(ptr %proj.1)
- ; Begin lowering: apply %my_other_async_function(%args...)
+ ; Begin lowering: apply %my_other_async_function(%args...)
; setup callee context
%callee_context = call ptr @llvm.coro.async.context.alloc(ptr %task, ptr @my_other_async_function_fp)
@@ -306,11 +392,11 @@ entry:
; store caller context into callee context
store ptr %async.ctxt, ptr %callee_context
%res = call {ptr, ptr, ptr, ptr} (i32, ptr, ptr, ...)
- @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32 256, ;; swiftasync at 0 and swiftself at 1 in resume function
- ptr %resume.func_ptr,
- ptr @resume_context_projection,
- ptr @my_async_function.my_other_async_function_fp.apply,
- ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
+ @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i32 256, ;; swiftasync at 0 and swiftself at 1 in resume function
+ ptr %resume.func_ptr,
+ ptr @resume_context_projection,
+ ptr @my_async_function.my_other_async_function_fp.apply,
+ ptr @asyncSuspend, ptr %callee_context, ptr %task, ptr %actor)
call void @llvm.coro.async.context.dealloc(ptr %callee_context)
%continuation_task_arg = extractvalue {ptr, ptr, ptr, ptr} %res, 3
@@ -324,37 +410,43 @@ entry:
unreachable
}
+; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(ptr swiftasync initializes((152, 160)) %async.ctxt, ptr %task, ptr %actor)
+; CHECK-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(ptr {{.*}}swiftasync{{.*}} %0, ptr {{.*}}swiftself{{.*}} %1, ptr {{.*}}%2, ptr {{.*}}%3)
+; CHECK: }
@no_coro_suspend_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @no_coro_suspend to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @no_coro_suspend to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
define swiftcc void @no_coro_suspend(ptr %async.ctx) presplitcoroutine {
entry:
%some_alloca = alloca i64
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @no_coro_suspend_fp)
+ ptr @no_coro_suspend_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
call void @some_may_write(ptr %some_alloca)
call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0)
unreachable
}
+; CHECK-LABEL: define swiftcc void @no_coro_suspend
+; CHECK: [[ALLOCA:%.*]] = alloca i64
+; CHECK: call void @some_may_write(ptr {{.*}}[[ALLOCA]])
@no_coro_suspend_swifterror_fp = constant <{ i32, i32 }>
<{ i32 trunc ( ; Relative pointer to async function
- i64 sub (
- i64 ptrtoint (ptr @no_coro_suspend_swifterror to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_swifterror_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 128 ; Initial async context size without space for frame
+ i64 sub (
+ i64 ptrtoint (ptr @no_coro_suspend_swifterror to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @no_coro_suspend_swifterror_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 128 ; Initial async context size without space for frame
}>
declare void @do_with_swifterror(ptr swifterror)
@@ -363,7 +455,7 @@ define swiftcc void @no_coro_suspend_swifterror(ptr %async.ctx) presplitcoroutin
entry:
%some_alloca = alloca swifterror ptr
%id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
- ptr @no_coro_suspend_swifterror_fp)
+ ptr @no_coro_suspend_swifterror_fp)
%hdl = call ptr @llvm.coro.begin(token %id, ptr null)
store ptr null, ptr %some_alloca, align 8
call void @do_with_swifterror(ptr swifterror %some_alloca)
@@ -371,15 +463,19 @@ entry:
unreachable
}
+ ; CHECK-LABEL: define swiftcc void @no_coro_suspend_swifterror
+ ; CHECK: [[ALLOCA:%.*]] = alloca swifterror ptr
+ ; CHECK: store ptr null, ptr [[ALLOCA]]
+ ; CHECK: call void @do_with_swifterror(ptr {{.*}}swifterror{{.*}} [[ALLOCA]])
@undefined_coro_async_resume_fp = constant <{ i32, i32 }>
<{ i32 trunc (
- i64 sub (
- i64 ptrtoint (ptr @undefined_coro_async_resume to i64),
- i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @undefined_coro_async_resume_fp, i32 0, i32 1) to i64)
- )
- to i32),
- i32 24
+ i64 sub (
+ i64 ptrtoint (ptr @undefined_coro_async_resume to i64),
+ i64 ptrtoint (ptr getelementptr inbounds (<{ i32, i32 }>, ptr @undefined_coro_async_resume_fp, i32 0, i32 1) to i64)
+ )
+ to i32),
+ i32 24
}>
declare void @crash()
@@ -395,10 +491,14 @@ entry:
call void (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 false)
unreachable
}
+; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume
+; CHECK-NOT: @llvm.coro.async.resume
+; CHECK: call void @use(ptr null)
+; CHECK: ret
@simpleFuncTu = global <{i32, i32}> <{
i32 trunc (i64 sub (i64 ptrtoint (ptr @simpleFunc to i64),
- i64 ptrtoint (ptr @simpleFuncTu to i64)) to i32), i32 16 }>
+ i64 ptrtoint (ptr @simpleFuncTu to i64)) to i32), i32 16 }>
define swifttailcc void @simpleFunc(ptr swiftasync %0) presplitcoroutine {
entry:
@@ -414,6 +514,10 @@ entry:
unreachable
}
+; CHECK-LABEL: define swifttailcc void @simpleFunc(ptr swiftasync %0) {
+; CHECK-NOT: define
+; CHECK: [[RESUME:%.*]] = load ptr
+; CHECK: musttail call swifttailcc void [[RESUME]]
define internal swifttailcc void @simpleFunc.0(ptr %0, ptr %1) alwaysinline {
entry:
@@ -440,724 +544,31 @@ declare ptr @hide(ptr)
!llvm.module.flags = !{!0}
!0 = !{i32 2, !"Debug Info Version", i32 3}
+; CHECK: ![[SP1]] = distinct !DISubprogram(name: "my_async_function",
+; CHECK-SAME: linkageName: "my_async_function",
+; CHECK-SAME: scopeLine: 1
!1 = distinct !DISubprogram(name: "my_async_function",
- linkageName: "my_async_function",
- scope: !2, file: !3, line: 1, type: !4,
- scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
+ linkageName: "my_async_function",
+ scope: !2, file: !3, line: 1, type: !4,
+ scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
+; CHECK: ![[SP2]] = distinct !DISubprogram(name: "my_async_function",
+; CHECK-SAME: linkageName: "my_async_functionTQ0_",
+; CHECK-SAME: scopeLine: 2
!2 = distinct !DICompileUnit(language: DW_LANG_Swift, file: !3, emissionKind: FullDebug)
!3 = !DIFile(filename: "/tmp/1.swift", directory: "/")
!4 = !DISubroutineType(types: !{})
!5 = !DILocation(line: 2, column: 0, scope: !1)
+; CHECK: ![[SP3]] = distinct !DISubprogram(name: "my_async_function2",
+; CHECK-SAME: linkageName: "my_async_function2",
+; CHECK-SAME: scopeLine: 1
!6 = distinct !DISubprogram(name: "my_async_function2",
- linkageName: "my_async_function2",
- scope: !2, file: !3, line: 1, type: !4,
- scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
+ linkageName: "my_async_function2",
+ scope: !2, file: !3, line: 1, type: !4,
+ scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
+; CHECK: ![[SP4]] = distinct !DISubprogram(name: "my_async_function2",
+; CHECK-SAME: linkageName: "my_async_function2.resume.0",
+; CHECK-SAME: scopeLine: 1
!7 = !DILexicalBlockFile(scope: !6, file: !8, discriminator: 0)
!8 = !DIFile(filename: "/tmp/fake.cpp", directory: "/")
!9 = !DILocation(line: 2, column: 0, scope: !7)
-; CHECK-LABEL: define swiftcc void @my_async_function.my_other_async_function_fp.apply(
-; CHECK-SAME: ptr readonly captures(none) [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define ptr @__swift_async_resume_project_context(
-; CHECK-SAME: ptr readonly captures(none) [[CTXT:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
-; CHECK-NEXT: ret ptr [[RESUME_CTXT]]
-;
-;
-; CHECK-LABEL: define ptr @resume_context_projection(
-; CHECK-SAME: ptr readonly captures(none) [[CTXT:%.*]]) local_unnamed_addr #[[ATTR0]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
-; CHECK-NEXT: ret ptr [[RESUME_CTXT]]
-;
-;
-; CHECK-LABEL: define swiftcc void @my_async_function(
-; CHECK-SAME: ptr swiftasync initializes((152, 160)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) !dbg [[DBG3:![0-9]+]] {
-; CHECK-NEXT: [[CORO_RETURN:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
-; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: store i64 1, ptr [[PROJ_2]], align 8
-; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR]])
-; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 160
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
-; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6:![0-9]+]]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal swiftcc void @my_async_functionTQ0_(
-; CHECK-SAME: ptr readonly swiftasync captures(none) [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr readnone captures(none) [[TMP2:%.*]]) !dbg [[DBG7:![0-9]+]] {
-; CHECK-NEXT: [[ENTRYRESUME_0:.*:]]
-; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8, !dbg [[DBG8:![0-9]+]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 128
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 160
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 152
-; CHECK-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[PROJ_21:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 136
-; CHECK-NEXT: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CONTEXT_RELOAD]])
-; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: tail call void @some_user(i64 [[VAL]])
-; CHECK-NEXT: [[VAL_2:%.*]] = load i64, ptr [[PROJ_21]], align 8
-; CHECK-NEXT: tail call void @some_user(i64 [[VAL_2]])
-; CHECK-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP1]], ptr [[ACTOR_RELOAD]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define void @my_async_function_pa(
-; CHECK-SAME: ptr initializes((152, 160)) [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 152
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 144
-; CHECK-NEXT: store ptr [[CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[PROJ_2_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 136
-; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR_I]], align 8
-; CHECK-NEXT: store i64 1, ptr [[PROJ_2_I]], align 8
-; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR_I]])
-; CHECK-NEXT: [[CALLEE_CONTEXT_I:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 160
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT_I]], ptr [[CALLEE_CONTEXT_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT_I]], i64 8
-; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I]], align 8
-; CHECK-NEXT: store ptr [[CTXT]], ptr [[CALLEE_CONTEXT_I]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT_I]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define swiftcc void @my_async_function2(
-; CHECK-SAME: ptr [[TASK:%.*]], ptr [[ACTOR:%.*]], ptr [[ASYNC_CTXT:%.*]]) #[[ATTR1:[0-9]+]] !dbg [[DBG9:![0-9]+]] {
-; CHECK-NEXT: [[CORO_RETURN:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-NEXT: store ptr [[TASK]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
-; CHECK-NEXT: store ptr @my_async_function2.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG10:![0-9]+]]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.0(
-; CHECK-SAME: ptr [[TMP0:%.*]], ptr readnone captures(none) [[TMP1:%.*]], ptr readonly captures(none) [[TMP2:%.*]]) #[[ATTR1]] !dbg [[DBG13:![0-9]+]] {
-; CHECK-NEXT: [[ENTRYRESUME_0:.*:]]
-; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP2]], align 8, !dbg [[DBG14:![0-9]+]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 128
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR10:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 152
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD11:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR10]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD_ADDR4:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD5:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR4]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR3:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT_RELOAD11]], i64 8
-; CHECK-NEXT: [[CONTINUATION_TASK_ARG_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 160
-; CHECK-NEXT: store ptr [[TMP0]], ptr [[CONTINUATION_TASK_ARG_SPILL_ADDR]], align 8
-; CHECK-NEXT: store ptr @my_async_function2.resume.1, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR3]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT_RELOAD5]], ptr [[CALLEE_CONTEXT_RELOAD11]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD9:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR10]], align 8
-; CHECK-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 136
-; CHECK-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[TASK_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT_RELOAD9]], ptr [[TASK_RELOAD]], ptr [[ACTOR_RELOAD]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.1(
-; CHECK-SAME: ptr readonly captures(none) [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr readnone captures(none) [[TMP2:%.*]]) #[[ATTR1]] !dbg [[DBG16:![0-9]+]] {
-; CHECK-NEXT: [[ENTRYRESUME_1:.*:]]
-; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
-; CHECK-NEXT: [[CONTINUATION_TASK_ARG_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 160
-; CHECK-NEXT: [[CONTINUATION_TASK_ARG_RELOAD:%.*]] = load ptr, ptr [[CONTINUATION_TASK_ARG_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR6:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 152
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD7:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR6]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
-; CHECK-NEXT: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CONTEXT_RELOAD7]])
-; CHECK-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[CONTINUATION_TASK_ARG_RELOAD]], ptr [[TMP1]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define swiftcc void @top_level_caller(
-; CHECK-SAME: ptr initializes((152, 160)) [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 152
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 144
-; CHECK-NEXT: store ptr [[CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[PROJ_2_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 136
-; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR_I]], align 8
-; CHECK-NEXT: store i64 1, ptr [[PROJ_2_I]], align 8
-; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR_I]])
-; CHECK-NEXT: [[CALLEE_CONTEXT_I:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CTXT]], i64 160
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT_I]], ptr [[CALLEE_CONTEXT_SPILL_ADDR_I]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT_I]], i64 8
-; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_I]], align 8
-; CHECK-NEXT: store ptr [[CTXT]], ptr [[CALLEE_CONTEXT_I]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT_I]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define swiftcc void @dont_crash_on_cf_dispatch(
-; CHECK-SAME: ptr readonly captures(none) [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-NEXT: br i1 [[ISNULL]], label %[[COMMON_RET:.*]], label %[[IS_NOT_NULL:.*]]
-; CHECK: [[COMMON_RET]]:
-; CHECK-NEXT: ret void
-; CHECK: [[IS_NOT_NULL]]:
-; CHECK-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: br label %[[COMMON_RET]]
-;
-;
-; CHECK-LABEL: define swiftcc void @dont_crash_on_cf(
-; CHECK-SAME: ptr initializes((136, 144)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: [[CORO_RETURN:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
-; CHECK-NEXT: store ptr @dont_crash_on_cf.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
-; CHECK: [[IS_NOT_NULL_I]]:
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
-; CHECK: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal swiftcc void @dont_crash_on_cf.resume.0(
-; CHECK-SAME: ptr readonly captures(none) [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr readnone captures(none) [[TMP2:%.*]]) {
-; CHECK-NEXT: [[ENTRYRESUME_0:.*:]]
-; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 128
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 136
-; CHECK-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CONTEXT_RELOAD]])
-; CHECK-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP1]], ptr [[ACTOR_RELOAD]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define swiftcc void @must_tail_call_return(
-; CHECK-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) local_unnamed_addr {
-; CHECK-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define swiftcc void @multiple_coro_end_async(
-; CHECK-SAME: ptr initializes((136, 144)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-NEXT: [[CORO_RETURN:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
-; CHECK-NEXT: store ptr @multiple_coro_end_async.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
-; CHECK: [[IS_NOT_NULL_I]]:
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr nonnull [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
-; CHECK: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal swiftcc void @multiple_coro_end_async.resume.0(
-; CHECK-SAME: ptr readonly captures(none) [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr readnone captures(none) [[TMP2:%.*]]) {
-; CHECK-NEXT: [[ENTRYRESUME_0:.*:]]
-; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 128
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
-; CHECK-NEXT: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CONTEXT_RELOAD]])
-; CHECK-NEXT: [[EQ:%.*]] = icmp eq ptr [[TMP1]], null
-; CHECK-NEXT: br i1 [[EQ]], label %[[COROEND:.*]], label %[[AFTERMUSTTAILCALL_BEFORE_COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 136
-; CHECK-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD4:%.*]] = load ptr, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD4]], ptr null, ptr [[ACTOR_RELOAD]])
-; CHECK-NEXT: ret void
-; CHECK: [[AFTERMUSTTAILCALL_BEFORE_COROEND]]:
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr nonnull [[TMP1]], ptr null)
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(
-; CHECK-SAME: ptr swiftasync initializes((152, 160)) [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-NEXT: [[CORO_RETURN:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 128
-; CHECK-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 152
-; CHECK-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 144
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 136
-; CHECK-NEXT: store i64 0, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: store i64 1, ptr [[PROJ_2]], align 8
-; CHECK-NEXT: tail call void @some_may_write(ptr nonnull [[ASYNC_CTX_FRAMEPTR]])
-; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = tail call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr nonnull @my_other_async_function_fp)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[ASYNC_CTXT]], i64 160
-; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLEE_CONTEXT]], i64 8
-; CHECK-NEXT: store ptr @polymorphic_suspend_return.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-NEXT: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(
-; CHECK-SAME: ptr readonly swiftasync captures(none) [[TMP0:%.*]], ptr readnone swiftself captures(none) [[TMP1:%.*]], ptr readnone captures(none) [[TMP2:%.*]], ptr [[TMP3:%.*]]) {
-; CHECK-NEXT: [[ENTRYRESUME_0:.*:]]
-; CHECK-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 128
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 160
-; CHECK-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 152
-; CHECK-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 144
-; CHECK-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[PROJ_21:%.*]] = getelementptr inbounds nuw i8, ptr [[RESUME_CTXT_I]], i64 136
-; CHECK-NEXT: tail call void @llvm.coro.async.context.dealloc(ptr nonnull [[CALLEE_CONTEXT_RELOAD]])
-; CHECK-NEXT: [[VAL:%.*]] = load i64, ptr [[ASYNC_CTX_FRAMEPTR]], align 8
-; CHECK-NEXT: tail call void @some_user(i64 [[VAL]])
-; CHECK-NEXT: [[VAL_2:%.*]] = load i64, ptr [[PROJ_21]], align 8
-; CHECK-NEXT: tail call void @some_user(i64 [[VAL_2]])
-; CHECK-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP3]], ptr [[ACTOR_RELOAD]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define swiftcc void @no_coro_suspend(
-; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
-; CHECK-NEXT: [[COROEND:.*:]]
-; CHECK-NEXT: [[SOME_ALLOCA:%.*]] = alloca i64, align 8
-; CHECK-NEXT: call void @some_may_write(ptr nonnull [[SOME_ALLOCA]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define swiftcc void @no_coro_suspend_swifterror(
-; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
-; CHECK-NEXT: [[COROEND:.*:]]
-; CHECK-NEXT: [[SOME_ALLOCA:%.*]] = alloca swifterror ptr, align 8
-; CHECK-NEXT: store ptr null, ptr [[SOME_ALLOCA]], align 8
-; CHECK-NEXT: call void @do_with_swifterror(ptr nonnull swifterror [[SOME_ALLOCA]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume(
-; CHECK-SAME: ptr readnone captures(none) [[ASYNC_CTX:%.*]]) {
-; CHECK-NEXT: [[COROEND:.*:]]
-; CHECK-NEXT: tail call void @use(ptr null)
-; CHECK-NEXT: tail call void @crash()
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define swifttailcc void @simpleFunc(
-; CHECK-SAME: ptr swiftasync [[TMP0:%.*]]) {
-; CHECK-NEXT: [[AFTERMUSTTAILCALL_BEFORE_COROEND:.*:]]
-; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 8
-; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
-; CHECK-NEXT: musttail call swifttailcc void [[TMP2]](ptr swiftasync [[TMP0]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @my_async_function.my_other_async_function_fp.apply(
-; CHECK-O0-SAME: ptr [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define ptr @__swift_async_resume_project_context(
-; CHECK-O0-SAME: ptr [[CTXT:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
-; CHECK-O0-NEXT: ret ptr [[RESUME_CTXT]]
-;
-;
-; CHECK-O0-LABEL: define ptr @resume_context_projection(
-; CHECK-O0-SAME: ptr [[CTXT:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[RESUME_CTXT:%.*]] = load ptr, ptr [[CTXT]], align 8
-; CHECK-O0-NEXT: ret ptr [[RESUME_CTXT]]
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @my_async_function(
-; CHECK-O0-SAME: ptr swiftasync [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) !dbg [[DBG3:![0-9]+]] {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
-; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: [[VECTOR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 4
-; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[PROJ_1:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
-; CHECK-O0-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
-; CHECK-O0-NEXT: store i64 0, ptr [[PROJ_1]], align 8
-; CHECK-O0-NEXT: store i64 1, ptr [[PROJ_2]], align 8
-; CHECK-O0-NEXT: call void @some_may_write(ptr [[PROJ_1]])
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 5
-; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-O0-NEXT: [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr [[VECTOR]], align 16
-; CHECK-O0-NEXT: [[VECTOR_SPILL_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1, !dbg [[DBG6:![0-9]+]]
-; CHECK-O0-NEXT: store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_SPILL_ADDR]], align 16, !dbg [[DBG6]]
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG6]]
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define internal swiftcc void @my_async_functionTQ0_(
-; CHECK-O0-SAME: ptr swiftasync [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) !dbg [[DBG7:![0-9]+]] {
-; CHECK-O0-NEXT: [[ENTRYRESUME_0:.*:]]
-; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8, !dbg [[DBG8:![0-9]+]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
-; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: [[VECTOR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: [[VECTOR_SPILL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: [[VECTOR_SPILL_RELOAD:%.*]] = load <4 x double>, ptr [[VECTOR_SPILL_RELOAD_ADDR]], align 16
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 5
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 4
-; CHECK-O0-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[PROJ_22:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
-; CHECK-O0-NEXT: [[PROJ_11:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
-; CHECK-O0-NEXT: call void @llvm.coro.async.context.dealloc(ptr [[CALLEE_CONTEXT_RELOAD]])
-; CHECK-O0-NEXT: [[VAL:%.*]] = load i64, ptr [[PROJ_11]], align 4
-; CHECK-O0-NEXT: call void @some_user(i64 [[VAL]])
-; CHECK-O0-NEXT: [[VAL_2:%.*]] = load i64, ptr [[PROJ_22]], align 4
-; CHECK-O0-NEXT: call void @some_user(i64 [[VAL_2]])
-; CHECK-O0-NEXT: store <4 x double> [[VECTOR_SPILL_RELOAD]], ptr [[VECTOR]], align 16
-; CHECK-O0-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP1]], ptr [[ACTOR_RELOAD]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define void @my_async_function_pa(
-; CHECK-O0-SAME: ptr [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: call swiftcc void @my_async_function(ptr [[CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @my_async_function2(
-; CHECK-O0-SAME: ptr [[TASK:%.*]], ptr [[ACTOR:%.*]], ptr [[ASYNC_CTXT:%.*]]) #[[ATTR0:[0-9]+]] !dbg [[DBG9:![0-9]+]] {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
-; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[TASK_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: store ptr [[TASK]], ptr [[TASK_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @my_async_function2.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]]), !dbg [[DBG10:![0-9]+]]
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define internal swiftcc void @my_async_function2.resume.0(
-; CHECK-O0-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) #[[ATTR0]] !dbg [[DBG13:![0-9]+]] {
-; CHECK-O0-NEXT: [[ENTRYRESUME_0:.*:]]
-; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP2]], align 8, !dbg [[DBG14:![0-9]+]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR7:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD8:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR7]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR3:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD4:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR3]], align 8
-; CHECK-O0-NEXT: [[CONTINUATION_TASK_ARG_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 4
-; CHECK-O0-NEXT: store ptr [[TMP0]], ptr [[CONTINUATION_TASK_ARG_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_1:%.*]] = getelementptr inbounds [[ASYNC_CTXT:%.*]], ptr [[CALLEE_CONTEXT_RELOAD8]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @my_async_function2.resume.1, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR_1]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT_RELOAD4]], ptr [[CALLEE_CONTEXT_RELOAD8]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR5:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD6:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR5]], align 8
-; CHECK-O0-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[TASK_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: [[TASK_RELOAD:%.*]] = load ptr, ptr [[TASK_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT_RELOAD6]], ptr [[TASK_RELOAD]], ptr [[ACTOR_RELOAD]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define internal swiftcc void @my_async_function2.resume.1(
-; CHECK-O0-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) #[[ATTR0]] !dbg [[DBG16:![0-9]+]] {
-; CHECK-O0-NEXT: [[ENTRYRESUME_1:.*:]]
-; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
-; CHECK-O0-NEXT: [[CONTINUATION_TASK_ARG_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 4
-; CHECK-O0-NEXT: [[CONTINUATION_TASK_ARG_RELOAD:%.*]] = load ptr, ptr [[CONTINUATION_TASK_ARG_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION2_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: call void @llvm.coro.async.context.dealloc(ptr [[CALLEE_CONTEXT_RELOAD]])
-; CHECK-O0-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[CONTINUATION_TASK_ARG_RELOAD]], ptr [[TMP1]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @top_level_caller(
-; CHECK-O0-SAME: ptr [[CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: call swiftcc void @my_async_function(ptr [[CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @dont_crash_on_cf_dispatch(
-; CHECK-O0-SAME: ptr [[FNPTR:%.*]], ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: [[ISNULL:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-O0-NEXT: br i1 [[ISNULL]], label %[[IS_NULL:.*]], label %[[IS_NOT_NULL:.*]]
-; CHECK-O0: [[IS_NULL]]:
-; CHECK-O0-NEXT: ret void
-; CHECK-O0: [[IS_NOT_NULL]]:
-; CHECK-O0-NEXT: tail call swiftcc void [[FNPTR]](ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @dont_crash_on_cf(
-; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
-; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @dont_crash_on_cf.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-O0-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-O0-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
-; CHECK-O0: [[IS_NOT_NULL_I]]:
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
-; CHECK-O0: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define internal swiftcc void @dont_crash_on_cf.resume.0(
-; CHECK-O0-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRYRESUME_0:.*:]]
-; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[DONT_CRASH_ON_CF_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: call void @llvm.coro.async.context.dealloc(ptr [[CALLEE_CONTEXT_RELOAD]])
-; CHECK-O0-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP1]], ptr [[ACTOR_RELOAD]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @must_tail_call_return(
-; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @multiple_coro_end_async(
-; CHECK-O0-SAME: ptr [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
-; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @multiple_coro_end_async.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-O0-NEXT: [[ISNULL_I:%.*]] = icmp eq ptr [[TASK]], null
-; CHECK-O0-NEXT: br i1 [[ISNULL_I]], label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT:.*]], label %[[IS_NOT_NULL_I:.*]]
-; CHECK-O0: [[IS_NOT_NULL_I]]:
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: br label %[[DONT_CRASH_ON_CF_DISPATCH_EXIT]]
-; CHECK-O0: [[DONT_CRASH_ON_CF_DISPATCH_EXIT]]:
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define internal swiftcc void @multiple_coro_end_async.resume.0(
-; CHECK-O0-SAME: ptr [[TMP0:%.*]], ptr [[TMP1:%.*]], ptr [[TMP2:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRYRESUME_0:.*:]]
-; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: call void @llvm.coro.async.context.dealloc(ptr [[CALLEE_CONTEXT_RELOAD]])
-; CHECK-O0-NEXT: [[EQ:%.*]] = icmp eq ptr [[TMP1]], null
-; CHECK-O0-NEXT: br i1 [[EQ]], label %[[IS_EQUAL:.*]], label %[[MUSTTAILCALL_BEFORE_COROEND:.*]]
-; CHECK-O0: [[IS_EQUAL]]:
-; CHECK-O0-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR3:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD4:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR3]], align 8
-; CHECK-O0-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD4]], ptr [[TMP1]], ptr [[ACTOR_RELOAD]])
-; CHECK-O0-NEXT: ret void
-; CHECK-O0: [[MUSTTAILCALL_BEFORE_COROEND]]:
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[MULTIPLE_CORO_END_ASYNC_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: musttail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP1]], ptr null)
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @polymorphic_suspend_return(
-; CHECK-O0-SAME: ptr swiftasync [[ASYNC_CTXT:%.*]], ptr [[TASK:%.*]], ptr [[ACTOR:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 128
-; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: [[ACTOR_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: store ptr [[ACTOR]], ptr [[ACTOR_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[PROJ_1:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
-; CHECK-O0-NEXT: [[PROJ_2:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
-; CHECK-O0-NEXT: store i64 0, ptr [[PROJ_1]], align 8
-; CHECK-O0-NEXT: store i64 1, ptr [[PROJ_2]], align 8
-; CHECK-O0-NEXT: call void @some_may_write(ptr [[PROJ_1]])
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr [[TASK]], ptr @my_other_async_function_fp)
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
-; CHECK-O0-NEXT: store ptr @polymorphic_suspend_return.resume.0, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
-; CHECK-O0-NEXT: store ptr [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], align 8
-; CHECK-O0-NEXT: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CONTEXT]], ptr [[TASK]], ptr [[ACTOR]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(
-; CHECK-O0-SAME: ptr swiftasync [[TMP0:%.*]], ptr swiftself [[TMP1:%.*]], ptr [[TMP2:%.*]], ptr [[TMP3:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRYRESUME_0:.*:]]
-; CHECK-O0-NEXT: [[RESUME_CTXT_I:%.*]] = load ptr, ptr [[TMP0]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[RESUME_CTXT_I]], i32 128
-; CHECK-O0-NEXT: [[TMP:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
-; CHECK-O0-NEXT: [[CALLEE_CONTEXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CONTEXT_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[ACTOR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-O0-NEXT: [[ACTOR_RELOAD:%.*]] = load ptr, ptr [[ACTOR_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD_ADDR:%.*]] = getelementptr inbounds [[POLYMORPHIC_SUSPEND_RETURN_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 1
-; CHECK-O0-NEXT: [[ASYNC_CTXT_RELOAD:%.*]] = load ptr, ptr [[ASYNC_CTXT_RELOAD_ADDR]], align 8
-; CHECK-O0-NEXT: [[PROJ_22:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 1
-; CHECK-O0-NEXT: [[PROJ_11:%.*]] = getelementptr inbounds { i64, i64 }, ptr [[TMP]], i64 0, i32 0
-; CHECK-O0-NEXT: call void @llvm.coro.async.context.dealloc(ptr [[CALLEE_CONTEXT_RELOAD]])
-; CHECK-O0-NEXT: [[VAL:%.*]] = load i64, ptr [[PROJ_11]], align 4
-; CHECK-O0-NEXT: call void @some_user(i64 [[VAL]])
-; CHECK-O0-NEXT: [[VAL_2:%.*]] = load i64, ptr [[PROJ_22]], align 4
-; CHECK-O0-NEXT: call void @some_user(i64 [[VAL_2]])
-; CHECK-O0-NEXT: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr [[TMP3]], ptr [[ACTOR_RELOAD]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @no_coro_suspend(
-; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[SOME_ALLOCA:%.*]] = alloca i64, align 8
-; CHECK-O0-NEXT: call void @some_may_write(ptr [[SOME_ALLOCA]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @no_coro_suspend_swifterror(
-; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[SOME_ALLOCA:%.*]] = alloca swifterror ptr, align 8
-; CHECK-O0-NEXT: store ptr null, ptr [[SOME_ALLOCA]], align 8
-; CHECK-O0-NEXT: call void @do_with_swifterror(ptr swifterror [[SOME_ALLOCA]])
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swiftcc void @undefined_coro_async_resume(
-; CHECK-O0-SAME: ptr [[ASYNC_CTX:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: call void @use(ptr null)
-; CHECK-O0-NEXT: call void @crash()
-; CHECK-O0-NEXT: ret void
-;
-;
-; CHECK-O0-LABEL: define swifttailcc void @simpleFunc(
-; CHECK-O0-SAME: ptr swiftasync [[TMP0:%.*]]) {
-; CHECK-O0-NEXT: [[ENTRY:.*:]]
-; CHECK-O0-NEXT: [[TMP1:%.*]] = alloca ptr, align 8
-; CHECK-O0-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8
-; CHECK-O0-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP1]], align 8
-; CHECK-O0-NEXT: [[TMP3:%.*]] = getelementptr inbounds <{ ptr, ptr }>, ptr [[TMP2]], i32 0, i32 1
-; CHECK-O0-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP3]], align 8
-; CHECK-O0-NEXT: [[TMP5:%.*]] = load ptr, ptr [[TMP1]], align 8
-; CHECK-O0-NEXT: musttail call swifttailcc void [[TMP4]](ptr swiftasync [[TMP5]])
-; CHECK-O0-NEXT: ret void
-;
-;.
-; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_Swift, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
-; CHECK: [[META1]] = !DIFile(filename: "{{.*}}1.swift", directory: {{.*}})
-; CHECK: [[DBG3]] = distinct !DISubprogram(name: "my_async_function", linkageName: "my_async_function", scope: [[META0]], file: [[META1]], line: 1, type: [[META4:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
-; CHECK: [[META4]] = !DISubroutineType(types: [[META5:![0-9]+]])
-; CHECK: [[META5]] = !{}
-; CHECK: [[DBG6]] = !DILocation(line: 2, scope: [[DBG3]])
-; CHECK: [[DBG7]] = distinct !DISubprogram(name: "my_async_function", linkageName: "my_async_functionTQ0_", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 2, spFlags: DISPFlagDefinition, unit: [[META0]])
-; CHECK: [[DBG8]] = !DILocation(line: 2, scope: [[DBG7]])
-; CHECK: [[DBG9]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
-; CHECK: [[DBG10]] = !DILocation(line: 2, scope: [[META11:![0-9]+]])
-; CHECK: [[META11]] = !DILexicalBlockFile(scope: [[DBG9]], file: [[META12:![0-9]+]], discriminator: 0)
-; CHECK: [[META12]] = !DIFile(filename: "{{.*}}fake.cpp", directory: {{.*}})
-; CHECK: [[DBG13]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2.resume.0", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
-; CHECK: [[DBG14]] = !DILocation(line: 2, scope: [[META15:![0-9]+]])
-; CHECK: [[META15]] = !DILexicalBlockFile(scope: [[DBG13]], file: [[META12]], discriminator: 0)
-; CHECK: [[DBG16]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2.resume.1", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
-;.
-; CHECK-O0: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_Swift, file: [[META1:![0-9]+]], isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
-; CHECK-O0: [[META1]] = !DIFile(filename: "{{.*}}1.swift", directory: {{.*}})
-; CHECK-O0: [[DBG3]] = distinct !DISubprogram(name: "my_async_function", linkageName: "my_async_function", scope: [[META0]], file: [[META1]], line: 1, type: [[META4:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
-; CHECK-O0: [[META4]] = !DISubroutineType(types: [[META5:![0-9]+]])
-; CHECK-O0: [[META5]] = !{}
-; CHECK-O0: [[DBG6]] = !DILocation(line: 2, scope: [[DBG3]])
-; CHECK-O0: [[DBG7]] = distinct !DISubprogram(name: "my_async_function", linkageName: "my_async_functionTQ0_", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 2, spFlags: DISPFlagDefinition, unit: [[META0]])
-; CHECK-O0: [[DBG8]] = !DILocation(line: 2, scope: [[DBG7]])
-; CHECK-O0: [[DBG9]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
-; CHECK-O0: [[DBG10]] = !DILocation(line: 2, scope: [[META11:![0-9]+]])
-; CHECK-O0: [[META11]] = !DILexicalBlockFile(scope: [[DBG9]], file: [[META12:![0-9]+]], discriminator: 0)
-; CHECK-O0: [[META12]] = !DIFile(filename: "{{.*}}fake.cpp", directory: {{.*}})
-; CHECK-O0: [[DBG13]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2.resume.0", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
-; CHECK-O0: [[DBG14]] = !DILocation(line: 2, scope: [[META15:![0-9]+]])
-; CHECK-O0: [[META15]] = !DILexicalBlockFile(scope: [[DBG13]], file: [[META12]], discriminator: 0)
-; CHECK-O0: [[DBG16]] = distinct !DISubprogram(name: "my_async_function2", linkageName: "my_async_function2.resume.1", scope: [[META0]], file: [[META1]], line: 1, type: [[META4]], scopeLine: 1, spFlags: DISPFlagDefinition, unit: [[META0]])
-;.
diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
index 6db68c3b32edb..0639c710cd420 100644
--- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
+++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
@@ -79,8 +79,6 @@ ret:
ret void
}
-; check that we were haven't accidentally went out of @f.resume body
-
declare void @await_suspend_wrapper_void(ptr, ptr)
declare i1 @await_suspend_wrapper_bool(ptr, ptr)
declare ptr @await_suspend_wrapper_handle(ptr, ptr)
diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
index bc7064e787fac..01d3c90ef466c 100644
--- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
+++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
@@ -60,8 +60,6 @@ ret:
ret void
}
-; check that we were haven't accidentally went out of @f.resume body
-
declare void @await_suspend_wrapper_void(ptr, ptr)
declare i1 @await_suspend_wrapper_bool(ptr, ptr)
declare ptr @await_suspend_wrapper_handle(ptr, ptr)
diff --git a/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll b/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
index b4a4506a9da6b..f2aedefcfd381 100644
--- a/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
@@ -1,8 +1,64 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; RUN: opt < %s -passes='module(coro-early),cgscc(coro-split,coro-split)' -S | FileCheck %s
; Checks whether the dbg.declare for `__coro_frame` are created.
+; CHECK-LABEL: define void @f(
+; CHECK: coro.init:
+; CHECK: %[[begin:.*]] = call noalias nonnull ptr @llvm.coro.begin(
+; CHECK: #dbg_declare(ptr %[[begin]], ![[CORO_FRAME:[0-9]+]], !DIExpression(),
+;
+; CHECK: define internal fastcc void @f.resume(
+; CHECK: entry.resume:
+; CHECK: %[[FramePtr_RESUME:.*]] = alloca ptr
+; CHECK: #dbg_declare(ptr %[[FramePtr_RESUME]], ![[CORO_FRAME_IN_RESUME:[0-9]+]], !DIExpression(DW_OP_deref)
+;
+; CHECK-DAG: ![[FILE:[0-9]+]] = !DIFile(filename: "coro-debug.cpp"
+; CHECK-DAG: ![[RAMP:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov",
+; CHECK-DAG: ![[CORO_FRAME]] = !DILocalVariable(name: "__coro_frame", scope: ![[RAMP]], file: ![[FILE]], line: [[CORO_FRAME_LINE:[0-9]+]], type: ![[FRAME_TYPE:[0-9]+]], flags: DIFlagArtificial)
+; CHECK-DAG: ![[FRAME_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "f.coro_frame_ty", {{.*}}elements: ![[ELEMENTS:[0-9]+]]
+; CHECK-DAG: ![[ELEMENTS]] = !{![[RESUME_FN:[0-9]+]], ![[DESTROY_FN:[0-9]+]], ![[PROMISE:[0-9]+]], ![[VECTOR_TYPE:[0-9]+]], ![[INT64_0:[0-9]+]], ![[DOUBLE_1:[0-9]+]], ![[INT64_PTR:[0-9]+]], ![[INT32_2:[0-9]+]], ![[INT32_3:[0-9]+]], ![[UNALIGNED_UNKNOWN:[0-9]+]], ![[STRUCT:[0-9]+]], ![[CORO_INDEX:[0-9]+]], ![[SMALL_UNKNOWN:[0-9]+]]
+; CHECK-DAG: ![[RESUME_FN]] = !DIDerivedType(tag: DW_TAG_member, name: "__resume_fn"{{.*}}, baseType: ![[RESUME_FN_TYPE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
+; CHECK-DAG: ![[RESUME_FN_TYPE]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+; CHECK-DAG: ![[DESTROY_FN]] = !DIDerivedType(tag: DW_TAG_member, name: "__destroy_fn"{{.*}}, baseType: ![[RESUME_FN_TYPE]]{{.*}}, flags: DIFlagArtificial
+; CHECK-DAG: ![[PROMISE]] = !DIDerivedType(tag: DW_TAG_member, name: "__promise",{{.*}}baseType: ![[PROMISE_BASE:[0-9]+]]
+; CHECK-DAG: ![[PROMISE_BASE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "promise_type"
+; CHECK-DAG: ![[VECTOR_TYPE]] = !DIDerivedType(tag: DW_TAG_member, name: "_0",{{.*}}baseType: ![[VECTOR_TYPE_BASE:[0-9]+]], size: 128
+; CHECK-DAG: ![[VECTOR_TYPE_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE:[0-9]+]], size: 128, align: 16, elements: ![[VECTOR_TYPE_BASE_ELEMENTS:[0-9]+]])
+; CHECK-DAG: ![[UNKNOWN_TYPE_BASE]] = !DIBasicType(name: "UnknownType", size: 8, encoding: DW_ATE_unsigned_char, flags: DIFlagArtificial)
+; CHECK-DAG: ![[VECTOR_TYPE_BASE_ELEMENTS]] = !{![[VECTOR_TYPE_BASE_SUBRANGE:[0-9]+]]}
+; CHECK-DAG: ![[VECTOR_TYPE_BASE_SUBRANGE]] = !DISubrange(count: 16, lowerBound: 0)
+; CHECK-DAG: ![[INT64_0]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I64_BASE:[0-9]+]],{{.*}}, flags: DIFlagArtificial
+; CHECK-DAG: ![[I64_BASE]] = !DIBasicType(name: "__int_64", size: 64, encoding: DW_ATE_signed, flags: DIFlagArtificial)
+; CHECK-DAG: ![[DOUBLE_1]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[DOUBLE_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
+; CHECK-DAG: ![[DOUBLE_BASE]] = !DIBasicType(name: "__double_", size: 64, encoding: DW_ATE_float, flags: DIFlagArtificial)
+; CHECK-DAG: ![[INT32_2]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I32_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
+; CHECK-DAG: ![[I32_BASE]] = !DIBasicType(name: "__int_32", size: 32, encoding: DW_ATE_signed, flags: DIFlagArtificial)
+; CHECK-DAG: ![[INT32_3]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_5", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I32_BASE]]
+; CHECK-DAG: ![[UNALIGNED_UNKNOWN]] = !DIDerivedType(tag: DW_TAG_member, name: "_6",{{.*}}baseType: ![[UNALIGNED_UNKNOWN_BASE:[0-9]+]], size: 9
+; CHECK-DAG: ![[UNALIGNED_UNKNOWN_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE]], size: 16,{{.*}} elements: ![[UNALIGNED_UNKNOWN_ELEMENTS:[0-9]+]])
+; CHECK-DAG: ![[UNALIGNED_UNKNOWN_ELEMENTS]] = !{![[UNALIGNED_UNKNOWN_SUBRANGE:[0-9]+]]}
+; CHECK-DAG: ![[UNALIGNED_UNKNOWN_SUBRANGE]] = !DISubrange(count: 2, lowerBound: 0)
+; CHECK-DAG: ![[STRUCT]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_7", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[STRUCT_BASE:[0-9]+]]
+; CHECK-DAG: ![[STRUCT_BASE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure"{{.*}}, align: 64, flags: DIFlagArtificial, elements: ![[STRUCT_ELEMENTS:[0-9]+]]
+; CHECK-DAG: ![[STRUCT_ELEMENTS]] = !{![[MEM_TYPE:[0-9]+]]}
+; CHECK-DAG: ![[MEM_TYPE]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[MEM_TYPE_BASE:[0-9]+]], size: 4000
+; CHECK-DAG: ![[MEM_TYPE_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE]], size: 4000,
+; CHECK-DAG: ![[CORO_INDEX]] = !DIDerivedType(tag: DW_TAG_member, name: "__coro_index"
+; CHECK-DAG: ![[SMALL_UNKNOWN]] = !DIDerivedType(tag: DW_TAG_member, name: "UnknownType_8",{{.*}} baseType: ![[UNKNOWN_TYPE_BASE]], size: 5
+; CHECK-DAG: ![[PROMISE_VAR:[0-9]+]] = !DILocalVariable(name: "__promise", scope: ![[RAMP_SCOPE:[0-9]+]], file: ![[FILE]]
+; CHECK-DAG: ![[RAMP_SCOPE]] = distinct !DILexicalBlock(scope: ![[RAMP]], file: ![[FILE]], line: 23
+; CHECK-DAG: ![[BAR_FUNC:[0-9]+]] = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv",
+; CHECK-DAG: ![[BAR_SCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[BAR_FUNC]], file: !1
+; CHECK-DAG: ![[FRAME_TYPE_IN_BAR:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar.coro_frame_ty", file: ![[FILE]], line: [[BAR_LINE:[0-9]+]]{{.*}}elements: ![[ELEMENTS_IN_BAR:[0-9]+]]
+; CHECK-DAG: ![[ELEMENTS_IN_BAR]] = !{![[RESUME_FN_IN_BAR:[0-9]+]], ![[DESTROY_FN_IN_BAR:[0-9]+]], ![[PROMISE_IN_BAR:[0-9]+]], ![[VECTOR_TYPE_IN_BAR:[0-9]+]], ![[INT64_IN_BAR:[0-9]+]], ![[DOUBLE_IN_BAR:[0-9]+]], ![[INT64_PTR_IN_BAR:[0-9]+]], ![[INT32_IN_BAR:[0-9]+]], ![[STRUCT_IN_BAR:[0-9]+]], ![[CORO_INDEX_IN_BAR:[0-9]+]]
+; CHECK-DAG: ![[PROMISE_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__promise",{{.*}}baseType: ![[PROMISE_BASE]]
+; CHECK-DAG: ![[VECTOR_TYPE_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "_0", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[VECTOR_TYPE_BASE]]
+; CHECK-DAG: ![[INT64_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[I64_BASE]]
+; CHECK-DAG: ![[DOUBLE_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[DOUBLE_BASE]]
+; CHECK-DAG: ![[INT32_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[I32_BASE]]
+; CHECK-DAG: ![[STRUCT_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_5", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[STRUCT_BASE_IN_BAR:[0-9]+]]
+; CHECK-DAG: ![[STRUCT_BASE_IN_BAR]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]],{{.*}}, align: 64
+; CHECK-DAG: ![[CORO_FRAME_IN_RESUME]] = !DILocalVariable(name: "__coro_frame",{{.*}}type: ![[FRAME_TYPE]]
%promise_type = type { i32, i32, double }
@@ -22,267 +78,267 @@ declare void @pi64p(ptr)
define void @f(i32 %a, i32 %b, i64 %c, double %d, ptr %e) presplitcoroutine !dbg !8 {
entry:
- %__promise = alloca %promise_type, align 8
- %a.alloc = alloca i32, align 4
- %b.alloc = alloca i32, align 4
- %c.alloc = alloca i64, align 4
- %d.alloc = alloca double, align 4
- %e.alloc = alloca ptr, align 4
- store i32 %a, ptr %a.alloc
- store i32 %b, ptr %b.alloc
- store i64 %c, ptr %c.alloc
- store double %d, ptr %d.alloc
- store ptr %e, ptr %e.alloc
- %struct.data = alloca %struct.big_structure, align 1
- call void @produce(ptr %struct.data)
- ; We treat vector type as unresolved type now for test coverage.
- %unresolved_data = alloca <4 x i32>
- call void @produce_vector(ptr %unresolved_data)
- %unresolved_data2 = alloca <5 x i1>
- call void @produce_vectori5(ptr %unresolved_data2)
- %unresolved_data3 = alloca <9 x i1>
- call void @produce_vectori9(ptr %unresolved_data3)
- %id = call token @llvm.coro.id(i32 16, ptr %__promise, ptr null, ptr null)
- %alloc = call i1 @llvm.coro.alloc(token %id)
- br i1 %alloc, label %coro.alloc, label %coro.init
+ %__promise = alloca %promise_type, align 8
+ %a.alloc = alloca i32, align 4
+ %b.alloc = alloca i32, align 4
+ %c.alloc = alloca i64, align 4
+ %d.alloc = alloca double, align 4
+ %e.alloc = alloca ptr, align 4
+ store i32 %a, ptr %a.alloc
+ store i32 %b, ptr %b.alloc
+ store i64 %c, ptr %c.alloc
+ store double %d, ptr %d.alloc
+ store ptr %e, ptr %e.alloc
+ %struct.data = alloca %struct.big_structure, align 1
+ call void @produce(ptr %struct.data)
+ ; We treat vector type as unresolved type now for test coverage.
+ %unresolved_data = alloca <4 x i32>
+ call void @produce_vector(ptr %unresolved_data)
+ %unresolved_data2 = alloca <5 x i1>
+ call void @produce_vectori5(ptr %unresolved_data2)
+ %unresolved_data3 = alloca <9 x i1>
+ call void @produce_vectori9(ptr %unresolved_data3)
+ %id = call token @llvm.coro.id(i32 16, ptr %__promise, ptr null, ptr null)
+ %alloc = call i1 @llvm.coro.alloc(token %id)
+ br i1 %alloc, label %coro.alloc, label %coro.init
coro.alloc: ; preds = %entry
- %size = call i64 @llvm.coro.size.i64()
- %memory = call ptr @new(i64 %size)
- br label %coro.init
+ %size = call i64 @llvm.coro.size.i64()
+ %memory = call ptr @new(i64 %size)
+ br label %coro.init
coro.init: ; preds = %coro.alloc, %entry
- %phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ]
- %begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc)
- call void @llvm.dbg.declare(metadata ptr %__promise, metadata !6, metadata !DIExpression()), !dbg !18
- %ready = call i1 @await_ready()
- br i1 %ready, label %init.ready, label %init.suspend
+ %phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ]
+ %begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc)
+ call void @llvm.dbg.declare(metadata ptr %__promise, metadata !6, metadata !DIExpression()), !dbg !18
+ %ready = call i1 @await_ready()
+ br i1 %ready, label %init.ready, label %init.suspend
init.suspend: ; preds = %coro.init
- %save = call token @llvm.coro.save(ptr null)
- call void @await_suspend()
- %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
- switch i8 %suspend, label %coro.ret [
- i8 0, label %init.ready
- i8 1, label %init.cleanup
- ]
+ %save = call token @llvm.coro.save(ptr null)
+ call void @await_suspend()
+ %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
+ switch i8 %suspend, label %coro.ret [
+ i8 0, label %init.ready
+ i8 1, label %init.cleanup
+ ]
init.cleanup: ; preds = %init.suspend
- br label %cleanup
+ br label %cleanup
init.ready: ; preds = %init.suspend, %coro.init
- call void @await_resume()
- %ready.again = call zeroext i1 @await_ready()
- br i1 %ready.again, label %await.ready, label %await.suspend
+ call void @await_resume()
+ %ready.again = call zeroext i1 @await_ready()
+ br i1 %ready.again, label %await.ready, label %await.suspend
await.suspend: ; preds = %init.ready
- %save.again = call token @llvm.coro.save(ptr null)
- %from.address = call ptr @from_address(ptr %begin)
- call void @await_suspend()
- %suspend.again = call i8 @llvm.coro.suspend(token %save.again, i1 false)
- switch i8 %suspend.again, label %coro.ret [
- i8 0, label %await.ready
- i8 1, label %await.cleanup
- ]
+ %save.again = call token @llvm.coro.save(ptr null)
+ %from.address = call ptr @from_address(ptr %begin)
+ call void @await_suspend()
+ %suspend.again = call i8 @llvm.coro.suspend(token %save.again, i1 false)
+ switch i8 %suspend.again, label %coro.ret [
+ i8 0, label %await.ready
+ i8 1, label %await.cleanup
+ ]
await.cleanup: ; preds = %await.suspend
- br label %cleanup
+ br label %cleanup
await.ready: ; preds = %await.suspend, %init.ready
- call void @await_resume()
- store i32 1, ptr %__promise, align 8
- %j.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 1
- store i32 2, ptr %j.i, align 4
- %k.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 2
- store double 3.000000e+00, ptr %k.i, align 8
- call void @consume(ptr %struct.data)
- call void @consume_vector(ptr %unresolved_data)
- call void @consume_vectori5(ptr %unresolved_data2)
- call void @consume_vectori9(ptr %unresolved_data3)
- call void @pi32(ptr %a.alloc)
- call void @pi32(ptr %b.alloc)
- call void @pi64(ptr %c.alloc)
- call void @pdouble(ptr %d.alloc)
- call void @pi64p(ptr %e.alloc)
- call void @return_void()
- br label %coro.final
+ call void @await_resume()
+ store i32 1, ptr %__promise, align 8
+ %j.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 1
+ store i32 2, ptr %j.i, align 4
+ %k.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 2
+ store double 3.000000e+00, ptr %k.i, align 8
+ call void @consume(ptr %struct.data)
+ call void @consume_vector(ptr %unresolved_data)
+ call void @consume_vectori5(ptr %unresolved_data2)
+ call void @consume_vectori9(ptr %unresolved_data3)
+ call void @pi32(ptr %a.alloc)
+ call void @pi32(ptr %b.alloc)
+ call void @pi64(ptr %c.alloc)
+ call void @pdouble(ptr %d.alloc)
+ call void @pi64p(ptr %e.alloc)
+ call void @return_void()
+ br label %coro.final
coro.final: ; preds = %await.ready
- call void @final_suspend()
- %coro.final.await_ready = call i1 @await_ready()
- br i1 %coro.final.await_ready, label %final.ready, label %final.suspend
+ call void @final_suspend()
+ %coro.final.await_ready = call i1 @await_ready()
+ br i1 %coro.final.await_ready, label %final.ready, label %final.suspend
final.suspend: ; preds = %coro.final
- %final.suspend.coro.save = call token @llvm.coro.save(ptr null)
- %final.suspend.from_address = call ptr @from_address(ptr %begin)
- call void @await_suspend()
- %final.suspend.coro.suspend = call i8 @llvm.coro.suspend(token %final.suspend.coro.save, i1 true)
- switch i8 %final.suspend.coro.suspend, label %coro.ret [
- i8 0, label %final.ready
- i8 1, label %final.cleanup
- ]
+ %final.suspend.coro.save = call token @llvm.coro.save(ptr null)
+ %final.suspend.from_address = call ptr @from_address(ptr %begin)
+ call void @await_suspend()
+ %final.suspend.coro.suspend = call i8 @llvm.coro.suspend(token %final.suspend.coro.save, i1 true)
+ switch i8 %final.suspend.coro.suspend, label %coro.ret [
+ i8 0, label %final.ready
+ i8 1, label %final.cleanup
+ ]
final.cleanup: ; preds = %final.suspend
- br label %cleanup
+ br label %cleanup
final.ready: ; preds = %final.suspend, %coro.final
- call void @await_resume()
- br label %cleanup
+ call void @await_resume()
+ br label %cleanup
cleanup: ; preds = %final.ready, %final.cleanup, %await.cleanup, %init.cleanup
- %cleanup.dest.slot.0 = phi i32 [ 0, %final.ready ], [ 2, %final.cleanup ], [ 2, %await.cleanup ], [ 2, %init.cleanup ]
- %free.memory = call ptr @llvm.coro.free(token %id, ptr %begin)
- %free = icmp ne ptr %free.memory, null
- br i1 %free, label %coro.free, label %after.coro.free
+ %cleanup.dest.slot.0 = phi i32 [ 0, %final.ready ], [ 2, %final.cleanup ], [ 2, %await.cleanup ], [ 2, %init.cleanup ]
+ %free.memory = call ptr @llvm.coro.free(token %id, ptr %begin)
+ %free = icmp ne ptr %free.memory, null
+ br i1 %free, label %coro.free, label %after.coro.free
coro.free: ; preds = %cleanup
- call void @delete(ptr %free.memory)
- br label %after.coro.free
+ call void @delete(ptr %free.memory)
+ br label %after.coro.free
after.coro.free: ; preds = %coro.free, %cleanup
- switch i32 %cleanup.dest.slot.0, label %unreachable [
- i32 0, label %cleanup.cont
- i32 2, label %coro.ret
- ]
+ switch i32 %cleanup.dest.slot.0, label %unreachable [
+ i32 0, label %cleanup.cont
+ i32 2, label %coro.ret
+ ]
cleanup.cont: ; preds = %after.coro.free
- br label %coro.ret
+ br label %coro.ret
coro.ret: ; preds = %cleanup.cont, %after.coro.free, %final.suspend, %await.suspend, %init.suspend
- call void @llvm.coro.end(ptr null, i1 false, token none)
- ret void
+ call void @llvm.coro.end(ptr null, i1 false, token none)
+ ret void
unreachable: ; preds = %after.coro.free
- unreachable
+ unreachable
}
; bar is used to check that we wouldn't create duplicate DIType
define void @bar(i32 %a, i64 %c, double %d, ptr %e) presplitcoroutine !dbg !19 {
entry:
- %__promise = alloca %promise_type, align 8
- %a.alloc = alloca i32, align 4
- %c.alloc = alloca i64, align 4
- %d.alloc = alloca double, align 4
- %e.alloc = alloca ptr, align 4
- store i32 %a, ptr %a.alloc
- store i64 %c, ptr %c.alloc
- store double %d, ptr %d.alloc
- store ptr %e, ptr %e.alloc
- %struct.data = alloca %struct.big_structure, align 1
- call void @produce(ptr %struct.data)
- ; We treat vector type as unresolved type now for test coverage.
- %unresolved_data = alloca <4 x i32>
- call void @produce_vector(ptr %unresolved_data)
- %id = call token @llvm.coro.id(i32 16, ptr %__promise, ptr null, ptr null)
- %alloc = call i1 @llvm.coro.alloc(token %id)
- br i1 %alloc, label %coro.alloc, label %coro.init
+ %__promise = alloca %promise_type, align 8
+ %a.alloc = alloca i32, align 4
+ %c.alloc = alloca i64, align 4
+ %d.alloc = alloca double, align 4
+ %e.alloc = alloca ptr, align 4
+ store i32 %a, ptr %a.alloc
+ store i64 %c, ptr %c.alloc
+ store double %d, ptr %d.alloc
+ store ptr %e, ptr %e.alloc
+ %struct.data = alloca %struct.big_structure, align 1
+ call void @produce(ptr %struct.data)
+ ; We treat vector type as unresolved type now for test coverage.
+ %unresolved_data = alloca <4 x i32>
+ call void @produce_vector(ptr %unresolved_data)
+ %id = call token @llvm.coro.id(i32 16, ptr %__promise, ptr null, ptr null)
+ %alloc = call i1 @llvm.coro.alloc(token %id)
+ br i1 %alloc, label %coro.alloc, label %coro.init
coro.alloc: ; preds = %entry
- %size = call i64 @llvm.coro.size.i64()
- %memory = call ptr @new(i64 %size)
- br label %coro.init
+ %size = call i64 @llvm.coro.size.i64()
+ %memory = call ptr @new(i64 %size)
+ br label %coro.init
coro.init: ; preds = %coro.alloc, %entry
- %phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ]
- %begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc)
- call void @llvm.dbg.declare(metadata ptr %__promise, metadata !21, metadata !DIExpression()), !dbg !22
- %ready = call i1 @await_ready()
- br i1 %ready, label %init.ready, label %init.suspend
+ %phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ]
+ %begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc)
+ call void @llvm.dbg.declare(metadata ptr %__promise, metadata !21, metadata !DIExpression()), !dbg !22
+ %ready = call i1 @await_ready()
+ br i1 %ready, label %init.ready, label %init.suspend
init.suspend: ; preds = %coro.init
- %save = call token @llvm.coro.save(ptr null)
- call void @await_suspend()
- %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
- switch i8 %suspend, label %coro.ret [
- i8 0, label %init.ready
- i8 1, label %init.cleanup
- ]
+ %save = call token @llvm.coro.save(ptr null)
+ call void @await_suspend()
+ %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
+ switch i8 %suspend, label %coro.ret [
+ i8 0, label %init.ready
+ i8 1, label %init.cleanup
+ ]
init.cleanup: ; preds = %init.suspend
- br label %cleanup
+ br label %cleanup
init.ready: ; preds = %init.suspend, %coro.init
- call void @await_resume()
- %ready.again = call zeroext i1 @await_ready()
- br i1 %ready.again, label %await.ready, label %await.suspend
+ call void @await_resume()
+ %ready.again = call zeroext i1 @await_ready()
+ br i1 %ready.again, label %await.ready, label %await.suspend
await.suspend: ; preds = %init.ready
- %save.again = call token @llvm.coro.save(ptr null)
- %from.address = call ptr @from_address(ptr %begin)
- call void @await_suspend()
- %suspend.again = call i8 @llvm.coro.suspend(token %save.again, i1 false)
- switch i8 %suspend.again, label %coro.ret [
- i8 0, label %await.ready
- i8 1, label %await.cleanup
- ]
+ %save.again = call token @llvm.coro.save(ptr null)
+ %from.address = call ptr @from_address(ptr %begin)
+ call void @await_suspend()
+ %suspend.again = call i8 @llvm.coro.suspend(token %save.again, i1 false)
+ switch i8 %suspend.again, label %coro.ret [
+ i8 0, label %await.ready
+ i8 1, label %await.cleanup
+ ]
await.cleanup: ; preds = %await.suspend
- br label %cleanup
+ br label %cleanup
await.ready: ; preds = %await.suspend, %init.ready
- call void @await_resume()
- store i32 1, ptr %__promise, align 8
- %j.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 1
- store i32 2, ptr %j.i, align 4
- %k.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 2
- store double 3.000000e+00, ptr %k.i, align 8
- call void @consume(ptr %struct.data)
- call void @consume_vector(ptr %unresolved_data)
- call void @pi32(ptr %a.alloc)
- call void @pi64(ptr %c.alloc)
- call void @pdouble(ptr %d.alloc)
- call void @pi64p(ptr %e.alloc)
- call void @return_void()
- br label %coro.final
+ call void @await_resume()
+ store i32 1, ptr %__promise, align 8
+ %j.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 1
+ store i32 2, ptr %j.i, align 4
+ %k.i = getelementptr inbounds %promise_type, ptr %__promise, i64 0, i32 2
+ store double 3.000000e+00, ptr %k.i, align 8
+ call void @consume(ptr %struct.data)
+ call void @consume_vector(ptr %unresolved_data)
+ call void @pi32(ptr %a.alloc)
+ call void @pi64(ptr %c.alloc)
+ call void @pdouble(ptr %d.alloc)
+ call void @pi64p(ptr %e.alloc)
+ call void @return_void()
+ br label %coro.final
coro.final: ; preds = %await.ready
- call void @final_suspend()
- %coro.final.await_ready = call i1 @await_ready()
- br i1 %coro.final.await_ready, label %final.ready, label %final.suspend
+ call void @final_suspend()
+ %coro.final.await_ready = call i1 @await_ready()
+ br i1 %coro.final.await_ready, label %final.ready, label %final.suspend
final.suspend: ; preds = %coro.final
- %final.suspend.coro.save = call token @llvm.coro.save(ptr null)
- %final.suspend.from_address = call ptr @from_address(ptr %begin)
- call void @await_suspend()
- %final.suspend.coro.suspend = call i8 @llvm.coro.suspend(token %final.suspend.coro.save, i1 true)
- switch i8 %final.suspend.coro.suspend, label %coro.ret [
- i8 0, label %final.ready
- i8 1, label %final.cleanup
- ]
+ %final.suspend.coro.save = call token @llvm.coro.save(ptr null)
+ %final.suspend.from_address = call ptr @from_address(ptr %begin)
+ call void @await_suspend()
+ %final.suspend.coro.suspend = call i8 @llvm.coro.suspend(token %final.suspend.coro.save, i1 true)
+ switch i8 %final.suspend.coro.suspend, label %coro.ret [
+ i8 0, label %final.ready
+ i8 1, label %final.cleanup
+ ]
final.cleanup: ; preds = %final.suspend
- br label %cleanup
+ br label %cleanup
final.ready: ; preds = %final.suspend, %coro.final
- call void @await_resume()
- br label %cleanup
+ call void @await_resume()
+ br label %cleanup
cleanup: ; preds = %final.ready, %final.cleanup, %await.cleanup, %init.cleanup
- %cleanup.dest.slot.0 = phi i32 [ 0, %final.ready ], [ 2, %final.cleanup ], [ 2, %await.cleanup ], [ 2, %init.cleanup ]
- %free.memory = call ptr @llvm.coro.free(token %id, ptr %begin)
- %free = icmp ne ptr %free.memory, null
- br i1 %free, label %coro.free, label %after.coro.free
+ %cleanup.dest.slot.0 = phi i32 [ 0, %final.ready ], [ 2, %final.cleanup ], [ 2, %await.cleanup ], [ 2, %init.cleanup ]
+ %free.memory = call ptr @llvm.coro.free(token %id, ptr %begin)
+ %free = icmp ne ptr %free.memory, null
+ br i1 %free, label %coro.free, label %after.coro.free
coro.free: ; preds = %cleanup
- call void @delete(ptr %free.memory)
- br label %after.coro.free
+ call void @delete(ptr %free.memory)
+ br label %after.coro.free
after.coro.free: ; preds = %coro.free, %cleanup
- switch i32 %cleanup.dest.slot.0, label %unreachable [
- i32 0, label %cleanup.cont
- i32 2, label %coro.ret
- ]
+ switch i32 %cleanup.dest.slot.0, label %unreachable [
+ i32 0, label %cleanup.cont
+ i32 2, label %coro.ret
+ ]
cleanup.cont: ; preds = %after.coro.free
- br label %coro.ret
+ br label %coro.ret
coro.ret: ; preds = %cleanup.cont, %after.coro.free, %final.suspend, %await.suspend, %init.suspend
- call void @llvm.coro.end(ptr null, i1 false, token none)
- ret void
+ call void @llvm.coro.end(ptr null, i1 false, token none)
+ ret void
unreachable: ; preds = %after.coro.free
- unreachable
+ unreachable
}
@@ -334,1429 +390,3 @@ declare void @final_suspend()
!20 = distinct !DILexicalBlock(scope: !19, file: !1, line: 23, column: 12)
!21 = !DILocalVariable(name: "__promise", scope: !20, file: !1, line: 55, type: !10)
!22 = !DILocation(line: 10, scope: !20)
-; CHECK-LABEL: define void @f(
-; CHECK-SAME: i32 [[A:%.*]], i32 [[B:%.*]], i64 [[C:%.*]], double [[D:%.*]], ptr [[E:%.*]]) !dbg [[DBG6:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*]]:
-; CHECK-NEXT: [[__PROMISE:%.*]] = alloca [[PROMISE_TYPE:%.*]], align 8
-; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[B_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
-; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: store i32 [[A]], ptr [[A_ALLOC]], align 4
-; CHECK-NEXT: store i32 [[B]], ptr [[B_ALLOC]], align 4
-; CHECK-NEXT: store i64 [[C]], ptr [[C_ALLOC]], align 4
-; CHECK-NEXT: store double [[D]], ptr [[D_ALLOC]], align 8
-; CHECK-NEXT: store ptr [[E]], ptr [[E_ALLOC]], align 8
-; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
-; CHECK-NEXT: call void @produce(ptr [[STRUCT_DATA]])
-; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
-; CHECK-NEXT: call void @produce_vector(ptr [[UNRESOLVED_DATA]])
-; CHECK-NEXT: [[UNRESOLVED_DATA2:%.*]] = alloca <5 x i1>, align 1
-; CHECK-NEXT: call void @produce_vectori5(ptr [[UNRESOLVED_DATA2]])
-; CHECK-NEXT: [[UNRESOLVED_DATA3:%.*]] = alloca <9 x i1>, align 2
-; CHECK-NEXT: call void @produce_vectori9(ptr [[UNRESOLVED_DATA3]])
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr @f, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
-; CHECK-NEXT: br i1 [[ALLOC]], label %[[CORO_ALLOC:.*]], label %[[CORO_INIT_FROM_ENTRY:.*]]
-; CHECK: [[CORO_INIT_FROM_ENTRY]]:
-; CHECK-NEXT: [[DOTCORO_INIT:%.*]] = phi ptr [ null, %[[ENTRY]] ]
-; CHECK-NEXT: br label %[[CORO_INIT:.*]]
-; CHECK: [[CORO_ALLOC]]:
-; CHECK-NEXT: [[MEMORY:%.*]] = call ptr @new(i64 592)
-; CHECK-NEXT: br label %[[CORO_INIT_FROM_CORO_ALLOC:.*]]
-; CHECK: [[CORO_INIT_FROM_CORO_ALLOC]]:
-; CHECK-NEXT: [[MEMORY_CORO_INIT:%.*]] = phi ptr [ [[MEMORY]], %[[CORO_ALLOC]] ]
-; CHECK-NEXT: br label %[[CORO_INIT]]
-; CHECK: [[CORO_INIT]]:
-; CHECK-NEXT: [[PHI_ENTRY_ALLOC:%.*]] = phi ptr [ [[DOTCORO_INIT]], %[[CORO_INIT_FROM_ENTRY]] ], [ [[MEMORY_CORO_INIT]], %[[CORO_INIT_FROM_CORO_ALLOC]] ]
-; CHECK-NEXT: [[BEGIN:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI_ENTRY_ALLOC]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META52:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16), [[META54:![0-9]+]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META9:![0-9]+]], !DIExpression(), [[META55:![0-9]+]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[ALLOC]], ptr @f.destroy, ptr @f.cleanup
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 1
-; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ALLOC]], align 4
-; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4
-; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[TMP4:%.*]] = load i32, ptr [[B_ALLOC]], align 4
-; CHECK-NEXT: store i32 [[TMP4]], ptr [[TMP3]], align 4
-; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[C_ALLOC]], align 4
-; CHECK-NEXT: store i64 [[TMP6]], ptr [[TMP5]], align 4
-; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[TMP8:%.*]] = load double, ptr [[D_ALLOC]], align 8
-; CHECK-NEXT: store double [[TMP8]], ptr [[TMP7]], align 8
-; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[TMP10:%.*]] = load ptr, ptr [[E_ALLOC]], align 8
-; CHECK-NEXT: store ptr [[TMP10]], ptr [[TMP9]], align 8
-; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
-; CHECK-NEXT: [[TMP12:%.*]] = load [[STRUCT_BIG_STRUCTURE]], ptr [[STRUCT_DATA]], align 1
-; CHECK-NEXT: store [[STRUCT_BIG_STRUCTURE]] [[TMP12]], ptr [[TMP11]], align 1
-; CHECK-NEXT: [[TMP13:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[TMP14:%.*]] = load <4 x i32>, ptr [[UNRESOLVED_DATA]], align 16
-; CHECK-NEXT: store <4 x i32> [[TMP14]], ptr [[TMP13]], align 16
-; CHECK-NEXT: [[TMP15:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
-; CHECK-NEXT: [[TMP16:%.*]] = load <5 x i1>, ptr [[UNRESOLVED_DATA2]], align 1
-; CHECK-NEXT: store <5 x i1> [[TMP16]], ptr [[TMP15]], align 1
-; CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: [[TMP18:%.*]] = load <9 x i1>, ptr [[UNRESOLVED_DATA3]], align 2
-; CHECK-NEXT: store <9 x i1> [[TMP18]], ptr [[TMP17]], align 2
-; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
-; CHECK: [[ALLOCASPILLBB]]:
-; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[B_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
-; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[UNRESOLVED_DATA2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
-; CHECK-NEXT: [[UNRESOLVED_DATA3_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 2
-; CHECK-NEXT: br label %[[POSTSPILL:.*]]
-; CHECK: [[POSTSPILL]]:
-; CHECK-NEXT: [[READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY]], label %[[INIT_READY:.*]], label %[[COROSAVE:.*]]
-; CHECK: [[COROSAVE]]:
-; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
-; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR13]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE:.*]]
-; CHECK: [[AFTERCOROSAVE]]:
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
-; CHECK: [[COROSUSPEND]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET:.*]] [
-; CHECK-NEXT: i8 0, label %[[INIT_READY]]
-; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[INIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP:.*]]
-; CHECK: [[INIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
-; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
-; CHECK: [[AFTERCOROSAVE2]]:
-; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
-; CHECK: [[COROSUSPEND3]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
-; CHECK: [[AFTERCOROSUSPEND4]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
-; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[AWAIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
-; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
-; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
-; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
-; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vectori5(ptr [[UNRESOLVED_DATA2_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vectori9(ptr [[UNRESOLVED_DATA3_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[B_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @return_void()
-; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
-; CHECK: [[CORO_FINAL]]:
-; CHECK-NEXT: call void @final_suspend()
-; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
-; CHECK: [[COROSAVE5]]:
-; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
-; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
-; CHECK: [[AFTERCOROSAVE6]]:
-; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
-; CHECK: [[COROSUSPEND7]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
-; CHECK: [[RESUME_2_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
-; CHECK: [[AFTERCOROSUSPEND8]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
-; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[FINAL_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[FINAL_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
-; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
-; CHECK-NEXT: [[FREE_MEMORY:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[BEGIN]])
-; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[FREE_MEMORY]], null
-; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
-; CHECK: [[CORO_FREE]]:
-; CHECK-NEXT: call void @delete(ptr [[FREE_MEMORY]])
-; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
-; CHECK: [[AFTER_CORO_FREE]]:
-; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
-; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
-; CHECK-NEXT: i32 2, label %[[CORO_RET]]
-; CHECK-NEXT: ]
-; CHECK: [[CLEANUP_CONT]]:
-; CHECK-NEXT: br label %[[CORO_RET]]
-; CHECK: [[CORO_RET]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
-; CHECK: [[AFTERCOROEND]]:
-; CHECK-NEXT: ret void
-; CHECK: [[UNREACHABLE]]:
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: define void @bar(
-; CHECK-SAME: i32 [[A:%.*]], i64 [[C:%.*]], double [[D:%.*]], ptr [[E:%.*]]) !dbg [[DBG56:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*]]:
-; CHECK-NEXT: [[__PROMISE:%.*]] = alloca [[PROMISE_TYPE:%.*]], align 8
-; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
-; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: store i32 [[A]], ptr [[A_ALLOC]], align 4
-; CHECK-NEXT: store i64 [[C]], ptr [[C_ALLOC]], align 4
-; CHECK-NEXT: store double [[D]], ptr [[D_ALLOC]], align 8
-; CHECK-NEXT: store ptr [[E]], ptr [[E_ALLOC]], align 8
-; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
-; CHECK-NEXT: call void @produce(ptr [[STRUCT_DATA]])
-; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
-; CHECK-NEXT: call void @produce_vector(ptr [[UNRESOLVED_DATA]])
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 16, ptr null, ptr @bar, ptr @bar.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call i1 @llvm.coro.alloc(token [[ID]])
-; CHECK-NEXT: br i1 [[ALLOC]], label %[[CORO_ALLOC:.*]], label %[[CORO_INIT_FROM_ENTRY:.*]]
-; CHECK: [[CORO_INIT_FROM_ENTRY]]:
-; CHECK-NEXT: [[DOTCORO_INIT:%.*]] = phi ptr [ null, %[[ENTRY]] ]
-; CHECK-NEXT: br label %[[CORO_INIT:.*]]
-; CHECK: [[CORO_ALLOC]]:
-; CHECK-NEXT: [[MEMORY:%.*]] = call ptr @new(i64 592)
-; CHECK-NEXT: br label %[[CORO_INIT_FROM_CORO_ALLOC:.*]]
-; CHECK: [[CORO_INIT_FROM_CORO_ALLOC]]:
-; CHECK-NEXT: [[MEMORY_CORO_INIT:%.*]] = phi ptr [ [[MEMORY]], %[[CORO_ALLOC]] ]
-; CHECK-NEXT: br label %[[CORO_INIT]]
-; CHECK: [[CORO_INIT]]:
-; CHECK-NEXT: [[PHI_ENTRY_ALLOC:%.*]] = phi ptr [ [[DOTCORO_INIT]], %[[CORO_INIT_FROM_ENTRY]] ], [ [[MEMORY_CORO_INIT]], %[[CORO_INIT_FROM_CORO_ALLOC]] ]
-; CHECK-NEXT: [[BEGIN:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI_ENTRY_ALLOC]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META74:![0-9]+]], !DIExpression(DW_OP_plus_uconst, 16), [[META76:![0-9]+]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN]], [[META58:![0-9]+]], !DIExpression(), [[META77:![0-9]+]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr @bar.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[ALLOC]], ptr @bar.destroy, ptr @bar.cleanup
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 1
-; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[A_ALLOC]], align 4
-; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4
-; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[TMP4:%.*]] = load i64, ptr [[C_ALLOC]], align 4
-; CHECK-NEXT: store i64 [[TMP4]], ptr [[TMP3]], align 4
-; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[TMP6:%.*]] = load double, ptr [[D_ALLOC]], align 8
-; CHECK-NEXT: store double [[TMP6]], ptr [[TMP5]], align 8
-; CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[TMP8:%.*]] = load ptr, ptr [[E_ALLOC]], align 8
-; CHECK-NEXT: store ptr [[TMP8]], ptr [[TMP7]], align 8
-; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[TMP10:%.*]] = load [[STRUCT_BIG_STRUCTURE]], ptr [[STRUCT_DATA]], align 1
-; CHECK-NEXT: store [[STRUCT_BIG_STRUCTURE]] [[TMP10]], ptr [[TMP9]], align 1
-; CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[TMP12:%.*]] = load <4 x i32>, ptr [[UNRESOLVED_DATA]], align 16
-; CHECK-NEXT: store <4 x i32> [[TMP12]], ptr [[TMP11]], align 16
-; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
-; CHECK: [[ALLOCASPILLBB]]:
-; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 2
-; CHECK-NEXT: br label %[[POSTSPILL:.*]]
-; CHECK: [[POSTSPILL]]:
-; CHECK-NEXT: [[READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY]], label %[[INIT_READY:.*]], label %[[COROSAVE:.*]]
-; CHECK: [[COROSAVE]]:
-; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR13]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE:.*]]
-; CHECK: [[AFTERCOROSAVE]]:
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
-; CHECK: [[COROSUSPEND]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET:.*]] [
-; CHECK-NEXT: i8 0, label %[[INIT_READY]]
-; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[INIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP:.*]]
-; CHECK: [[INIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
-; CHECK: [[AFTERCOROSAVE2]]:
-; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
-; CHECK: [[COROSUSPEND3]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
-; CHECK: [[AFTERCOROSUSPEND4]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
-; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[AWAIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
-; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
-; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
-; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
-; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @return_void()
-; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
-; CHECK: [[CORO_FINAL]]:
-; CHECK-NEXT: call void @final_suspend()
-; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
-; CHECK: [[COROSAVE5]]:
-; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
-; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
-; CHECK: [[AFTERCOROSAVE6]]:
-; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
-; CHECK: [[COROSUSPEND7]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
-; CHECK: [[RESUME_2_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
-; CHECK: [[AFTERCOROSUSPEND8]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
-; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[FINAL_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[FINAL_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
-; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
-; CHECK-NEXT: [[FREE_MEMORY:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[BEGIN]])
-; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[FREE_MEMORY]], null
-; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
-; CHECK: [[CORO_FREE]]:
-; CHECK-NEXT: call void @delete(ptr [[FREE_MEMORY]])
-; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
-; CHECK: [[AFTER_CORO_FREE]]:
-; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
-; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
-; CHECK-NEXT: i32 2, label %[[CORO_RET]]
-; CHECK-NEXT: ]
-; CHECK: [[CLEANUP_CONT]]:
-; CHECK-NEXT: br label %[[CORO_RET]]
-; CHECK: [[CORO_RET]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
-; CHECK: [[AFTERCOROEND]]:
-; CHECK-NEXT: ret void
-; CHECK: [[UNREACHABLE]]:
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: define internal fastcc void @f.resume(
-; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG78:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META81:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META83:![0-9]+]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META80:![0-9]+]], !DIExpression(DW_OP_deref), [[META84:![0-9]+]])
-; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
-; CHECK-NEXT: [[UNRESOLVED_DATA3:%.*]] = alloca <9 x i1>, align 2
-; CHECK-NEXT: [[UNRESOLVED_DATA2:%.*]] = alloca <5 x i1>, align 1
-; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
-; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
-; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
-; CHECK-NEXT: [[B_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[B_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
-; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[UNRESOLVED_DATA2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
-; CHECK-NEXT: [[UNRESOLVED_DATA3_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 2
-; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
-; CHECK: [[RESUME_ENTRY]]:
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
-; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
-; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
-; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
-; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[RESUME_0]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 0, label %[[CORO_RET:.*]] [
-; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
-; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[INIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP:.*]]
-; CHECK: [[INIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
-; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
-; CHECK: [[AFTERCOROSAVE2]]:
-; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
-; CHECK: [[COROSUSPEND3]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: [[TMP0:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 0, %[[RESUME_1]] ]
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
-; CHECK: [[AFTERCOROSUSPEND4]]:
-; CHECK-NEXT: switch i8 [[TMP0]], label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
-; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[AWAIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
-; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
-; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
-; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
-; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vectori5(ptr [[UNRESOLVED_DATA2_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vectori9(ptr [[UNRESOLVED_DATA3_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[B_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @return_void()
-; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
-; CHECK: [[CORO_FINAL]]:
-; CHECK-NEXT: call void @final_suspend()
-; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
-; CHECK: [[COROSAVE5]]:
-; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
-; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
-; CHECK: [[AFTERCOROSAVE6]]:
-; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
-; CHECK: [[COROSUSPEND7]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
-; CHECK: [[RESUME_2_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
-; CHECK: [[AFTERCOROSUSPEND8]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
-; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[FINAL_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[FINAL_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
-; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
-; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[BEGIN]], null
-; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
-; CHECK: [[CORO_FREE]]:
-; CHECK-NEXT: call void @delete(ptr [[BEGIN]])
-; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
-; CHECK: [[AFTER_CORO_FREE]]:
-; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
-; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
-; CHECK-NEXT: i32 2, label %[[CORO_RET]]
-; CHECK-NEXT: ]
-; CHECK: [[CLEANUP_CONT]]:
-; CHECK-NEXT: br label %[[CORO_RET]]
-; CHECK: [[CORO_RET]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-; CHECK: [[UNREACHABLE]]:
-; CHECK-NEXT: unreachable
-; CHECK: [[UNREACHABLE12]]:
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: define internal fastcc void @f.destroy(
-; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG85:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
-; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META88:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META90:![0-9]+]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META87:![0-9]+]], !DIExpression(DW_OP_deref), [[META91:![0-9]+]])
-; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
-; CHECK-NEXT: [[UNRESOLVED_DATA3:%.*]] = alloca <9 x i1>, align 2
-; CHECK-NEXT: [[UNRESOLVED_DATA2:%.*]] = alloca <5 x i1>, align 1
-; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
-; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
-; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
-; CHECK-NEXT: [[B_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[B_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
-; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[UNRESOLVED_DATA2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
-; CHECK-NEXT: [[UNRESOLVED_DATA3_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 2
-; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
-; CHECK: [[RESUME_ENTRY]]:
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
-; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
-; CHECK-NEXT: [[RESUMEFN_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESUMEFN_ADDR1]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
-; CHECK-NEXT: br i1 [[TMP1]], label %[[RESUME_2:.*]], label %[[SWITCH:.*]]
-; CHECK: [[SWITCH]]:
-; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
-; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
-; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[RESUME_0]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 1, label %[[CORO_RET:.*]] [
-; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
-; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[INIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP:.*]]
-; CHECK: [[INIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
-; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
-; CHECK: [[AFTERCOROSAVE2]]:
-; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
-; CHECK: [[COROSUSPEND3]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 1, %[[RESUME_1]] ]
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
-; CHECK: [[AFTERCOROSUSPEND4]]:
-; CHECK-NEXT: switch i8 [[TMP2]], label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
-; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[AWAIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
-; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
-; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
-; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
-; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vectori5(ptr [[UNRESOLVED_DATA2_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vectori9(ptr [[UNRESOLVED_DATA3_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[B_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @return_void()
-; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
-; CHECK: [[CORO_FINAL]]:
-; CHECK-NEXT: call void @final_suspend()
-; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
-; CHECK: [[COROSAVE5]]:
-; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
-; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
-; CHECK: [[AFTERCOROSAVE6]]:
-; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
-; CHECK: [[COROSUSPEND7]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
-; CHECK: [[RESUME_2]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING]]
-; CHECK: [[RESUME_2_LANDING]]:
-; CHECK-NEXT: [[TMP3:%.*]] = phi i8 [ -1, %[[COROSUSPEND7]] ], [ 1, %[[RESUME_2]] ]
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
-; CHECK: [[AFTERCOROSUSPEND8]]:
-; CHECK-NEXT: switch i8 [[TMP3]], label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
-; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[FINAL_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[FINAL_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
-; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
-; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[BEGIN]], null
-; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
-; CHECK: [[CORO_FREE]]:
-; CHECK-NEXT: call void @delete(ptr [[BEGIN]])
-; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
-; CHECK: [[AFTER_CORO_FREE]]:
-; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
-; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
-; CHECK-NEXT: i32 2, label %[[CORO_RET]]
-; CHECK-NEXT: ]
-; CHECK: [[CLEANUP_CONT]]:
-; CHECK-NEXT: br label %[[CORO_RET]]
-; CHECK: [[CORO_RET]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-; CHECK: [[UNREACHABLE]]:
-; CHECK-NEXT: unreachable
-; CHECK: [[UNREACHABLE12]]:
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: define internal fastcc void @f.cleanup(
-; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG92:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
-; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META95:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META97:![0-9]+]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META94:![0-9]+]], !DIExpression(DW_OP_deref), [[META98:![0-9]+]])
-; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
-; CHECK-NEXT: [[UNRESOLVED_DATA3:%.*]] = alloca <9 x i1>, align 2
-; CHECK-NEXT: [[UNRESOLVED_DATA2:%.*]] = alloca <5 x i1>, align 1
-; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
-; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
-; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
-; CHECK-NEXT: [[B_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[B_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 10
-; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[UNRESOLVED_DATA2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 12
-; CHECK-NEXT: [[UNRESOLVED_DATA3_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 2
-; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
-; CHECK: [[RESUME_ENTRY]]:
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
-; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
-; CHECK-NEXT: [[RESUMEFN_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESUMEFN_ADDR1]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
-; CHECK-NEXT: br i1 [[TMP1]], label %[[RESUME_2:.*]], label %[[SWITCH:.*]]
-; CHECK: [[SWITCH]]:
-; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
-; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
-; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[RESUME_0]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 1, label %[[CORO_RET:.*]] [
-; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
-; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[INIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP:.*]]
-; CHECK: [[INIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 11
-; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
-; CHECK: [[AFTERCOROSAVE2]]:
-; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
-; CHECK: [[COROSUSPEND3]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 1, %[[RESUME_1]] ]
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
-; CHECK: [[AFTERCOROSUSPEND4]]:
-; CHECK-NEXT: switch i8 [[TMP2]], label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
-; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[AWAIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
-; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
-; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
-; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
-; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vectori5(ptr [[UNRESOLVED_DATA2_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vectori9(ptr [[UNRESOLVED_DATA3_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[B_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @return_void()
-; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
-; CHECK: [[CORO_FINAL]]:
-; CHECK-NEXT: call void @final_suspend()
-; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
-; CHECK: [[COROSAVE5]]:
-; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
-; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
-; CHECK: [[AFTERCOROSAVE6]]:
-; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
-; CHECK: [[COROSUSPEND7]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
-; CHECK: [[RESUME_2]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING]]
-; CHECK: [[RESUME_2_LANDING]]:
-; CHECK-NEXT: [[TMP3:%.*]] = phi i8 [ -1, %[[COROSUSPEND7]] ], [ 1, %[[RESUME_2]] ]
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
-; CHECK: [[AFTERCOROSUSPEND8]]:
-; CHECK-NEXT: switch i8 [[TMP3]], label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
-; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[FINAL_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[FINAL_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
-; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
-; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr null, null
-; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
-; CHECK: [[CORO_FREE]]:
-; CHECK-NEXT: call void @delete(ptr null)
-; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
-; CHECK: [[AFTER_CORO_FREE]]:
-; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
-; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
-; CHECK-NEXT: i32 2, label %[[CORO_RET]]
-; CHECK-NEXT: ]
-; CHECK: [[CLEANUP_CONT]]:
-; CHECK-NEXT: br label %[[CORO_RET]]
-; CHECK: [[CORO_RET]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-; CHECK: [[UNREACHABLE]]:
-; CHECK-NEXT: unreachable
-; CHECK: [[UNREACHABLE12]]:
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: define internal fastcc void @bar.resume(
-; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG99:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META102:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META104:![0-9]+]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META101:![0-9]+]], !DIExpression(DW_OP_deref), [[META105:![0-9]+]])
-; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
-; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
-; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
-; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
-; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 2
-; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
-; CHECK: [[RESUME_ENTRY]]:
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
-; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
-; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
-; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[RESUME_0]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 0, label %[[CORO_RET:.*]] [
-; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
-; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[INIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP:.*]]
-; CHECK: [[INIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
-; CHECK: [[AFTERCOROSAVE2]]:
-; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
-; CHECK: [[COROSUSPEND3]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: [[TMP0:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 0, %[[RESUME_1]] ]
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
-; CHECK: [[AFTERCOROSUSPEND4]]:
-; CHECK-NEXT: switch i8 [[TMP0]], label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
-; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[AWAIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
-; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
-; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
-; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
-; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @return_void()
-; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
-; CHECK: [[CORO_FINAL]]:
-; CHECK-NEXT: call void @final_suspend()
-; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
-; CHECK: [[COROSAVE5]]:
-; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
-; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
-; CHECK: [[AFTERCOROSAVE6]]:
-; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
-; CHECK: [[COROSUSPEND7]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
-; CHECK: [[RESUME_2_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
-; CHECK: [[AFTERCOROSUSPEND8]]:
-; CHECK-NEXT: switch i8 -1, label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
-; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[FINAL_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[FINAL_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
-; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
-; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[BEGIN]], null
-; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
-; CHECK: [[CORO_FREE]]:
-; CHECK-NEXT: call void @delete(ptr [[BEGIN]])
-; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
-; CHECK: [[AFTER_CORO_FREE]]:
-; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
-; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
-; CHECK-NEXT: i32 2, label %[[CORO_RET]]
-; CHECK-NEXT: ]
-; CHECK: [[CLEANUP_CONT]]:
-; CHECK-NEXT: br label %[[CORO_RET]]
-; CHECK: [[CORO_RET]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-; CHECK: [[UNREACHABLE]]:
-; CHECK-NEXT: unreachable
-; CHECK: [[UNREACHABLE12]]:
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: define internal fastcc void @bar.destroy(
-; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG106:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
-; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META109:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META111:![0-9]+]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META108:![0-9]+]], !DIExpression(DW_OP_deref), [[META112:![0-9]+]])
-; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
-; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
-; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
-; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
-; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 2
-; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
-; CHECK: [[RESUME_ENTRY]]:
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
-; CHECK-NEXT: [[RESUMEFN_ADDR1:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESUMEFN_ADDR1]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
-; CHECK-NEXT: br i1 [[TMP1]], label %[[RESUME_2:.*]], label %[[SWITCH:.*]]
-; CHECK: [[SWITCH]]:
-; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
-; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
-; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[RESUME_0]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 1, label %[[CORO_RET:.*]] [
-; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
-; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[INIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP:.*]]
-; CHECK: [[INIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
-; CHECK: [[AFTERCOROSAVE2]]:
-; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
-; CHECK: [[COROSUSPEND3]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 1, %[[RESUME_1]] ]
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
-; CHECK: [[AFTERCOROSUSPEND4]]:
-; CHECK-NEXT: switch i8 [[TMP2]], label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
-; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[AWAIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
-; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
-; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
-; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
-; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @return_void()
-; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
-; CHECK: [[CORO_FINAL]]:
-; CHECK-NEXT: call void @final_suspend()
-; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
-; CHECK: [[COROSAVE5]]:
-; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
-; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
-; CHECK: [[AFTERCOROSAVE6]]:
-; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
-; CHECK: [[COROSUSPEND7]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
-; CHECK: [[RESUME_2]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING]]
-; CHECK: [[RESUME_2_LANDING]]:
-; CHECK-NEXT: [[TMP3:%.*]] = phi i8 [ -1, %[[COROSUSPEND7]] ], [ 1, %[[RESUME_2]] ]
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
-; CHECK: [[AFTERCOROSUSPEND8]]:
-; CHECK-NEXT: switch i8 [[TMP3]], label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
-; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[FINAL_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[FINAL_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
-; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
-; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr [[BEGIN]], null
-; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
-; CHECK: [[CORO_FREE]]:
-; CHECK-NEXT: call void @delete(ptr [[BEGIN]])
-; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
-; CHECK: [[AFTER_CORO_FREE]]:
-; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
-; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
-; CHECK-NEXT: i32 2, label %[[CORO_RET]]
-; CHECK-NEXT: ]
-; CHECK: [[CLEANUP_CONT]]:
-; CHECK-NEXT: br label %[[CORO_RET]]
-; CHECK: [[CORO_RET]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-; CHECK: [[UNREACHABLE]]:
-; CHECK-NEXT: unreachable
-; CHECK: [[UNREACHABLE12]]:
-; CHECK-NEXT: unreachable
-;
-;
-; CHECK-LABEL: define internal fastcc void @bar.cleanup(
-; CHECK-SAME: ptr noundef nonnull align 16 dereferenceable(592) [[BEGIN:%.*]]) !dbg [[DBG113:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
-; CHECK-NEXT: [[BEGIN_DEBUG:%.*]] = alloca ptr, align 8
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META116:![0-9]+]], !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 16), [[META118:![0-9]+]])
-; CHECK-NEXT: #dbg_declare(ptr [[BEGIN_DEBUG]], [[META115:![0-9]+]], !DIExpression(DW_OP_deref), [[META119:![0-9]+]])
-; CHECK-NEXT: store ptr [[BEGIN]], ptr [[BEGIN_DEBUG]], align 8
-; CHECK-NEXT: [[UNRESOLVED_DATA:%.*]] = alloca <4 x i32>, align 16
-; CHECK-NEXT: [[STRUCT_DATA:%.*]] = alloca [[STRUCT_BIG_STRUCTURE:%.*]], align 1
-; CHECK-NEXT: [[E_ALLOC:%.*]] = alloca ptr, align 4
-; CHECK-NEXT: [[D_ALLOC:%.*]] = alloca double, align 4
-; CHECK-NEXT: [[C_ALLOC:%.*]] = alloca i64, align 4
-; CHECK-NEXT: [[A_ALLOC:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[A_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME:%.*]], ptr [[BEGIN]], i32 0, i32 7
-; CHECK-NEXT: [[C_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 4
-; CHECK-NEXT: [[D_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 5
-; CHECK-NEXT: [[E_ALLOC_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 6
-; CHECK-NEXT: [[STRUCT_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 8
-; CHECK-NEXT: [[UNRESOLVED_DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 3
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 2
-; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
-; CHECK: [[RESUME_ENTRY]]:
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
-; CHECK-NEXT: [[RESUMEFN_ADDR1:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[RESUMEFN_ADDR1]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = icmp eq ptr [[TMP0]], null
-; CHECK-NEXT: br i1 [[TMP1]], label %[[RESUME_2:.*]], label %[[SWITCH:.*]]
-; CHECK: [[SWITCH]]:
-; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE12:.*]] [
-; CHECK-NEXT: i2 0, label %[[RESUME_0:.*]]
-; CHECK-NEXT: i2 1, label %[[RESUME_1:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[RESUME_0]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 1, label %[[CORO_RET:.*]] [
-; CHECK-NEXT: i8 0, label %[[INIT_READY:.*]]
-; CHECK-NEXT: i8 1, label %[[INIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[INIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_INIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_INIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP11:%.*]] = phi i32 [ 2, %[[INIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP:.*]]
-; CHECK: [[INIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: [[READY_AGAIN:%.*]] = call zeroext i1 @await_ready()
-; CHECK-NEXT: br i1 [[READY_AGAIN]], label %[[AWAIT_READY:.*]], label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 9
-; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR14]], align 1
-; CHECK-NEXT: br label %[[AFTERCOROSAVE2:.*]]
-; CHECK: [[AFTERCOROSAVE2]]:
-; CHECK-NEXT: [[FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND3:.*]]
-; CHECK: [[COROSUSPEND3]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: [[TMP2:%.*]] = phi i8 [ -1, %[[COROSUSPEND3]] ], [ 1, %[[RESUME_1]] ]
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND4:.*]]
-; CHECK: [[AFTERCOROSUSPEND4]]:
-; CHECK-NEXT: switch i8 [[TMP2]], label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[AWAIT_READY]]
-; CHECK-NEXT: i8 1, label %[[AWAIT_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[AWAIT_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_AWAIT_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_AWAIT_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP10:%.*]] = phi i32 [ 2, %[[AWAIT_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: store i32 1, ptr [[__PROMISE_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[J_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE:%.*]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 1
-; CHECK-NEXT: store i32 2, ptr [[J_I]], align 4
-; CHECK-NEXT: [[K_I:%.*]] = getelementptr inbounds [[PROMISE_TYPE]], ptr [[__PROMISE_RELOAD_ADDR]], i64 0, i32 2
-; CHECK-NEXT: store double 3.000000e+00, ptr [[K_I]], align 8
-; CHECK-NEXT: call void @consume(ptr [[STRUCT_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @consume_vector(ptr [[UNRESOLVED_DATA_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi32(ptr [[A_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64(ptr [[C_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pdouble(ptr [[D_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @pi64p(ptr [[E_ALLOC_RELOAD_ADDR]])
-; CHECK-NEXT: call void @return_void()
-; CHECK-NEXT: br label %[[CORO_FINAL:.*]]
-; CHECK: [[CORO_FINAL]]:
-; CHECK-NEXT: call void @final_suspend()
-; CHECK-NEXT: [[CORO_FINAL_AWAIT_READY:%.*]] = call i1 @await_ready()
-; CHECK-NEXT: br i1 [[CORO_FINAL_AWAIT_READY]], label %[[FINAL_READY:.*]], label %[[COROSAVE5:.*]]
-; CHECK: [[COROSAVE5]]:
-; CHECK-NEXT: [[RESUMEFN_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[BEGIN]], i32 0, i32 0
-; CHECK-NEXT: store ptr null, ptr [[RESUMEFN_ADDR]], align 8
-; CHECK-NEXT: br label %[[AFTERCOROSAVE6:.*]]
-; CHECK: [[AFTERCOROSAVE6]]:
-; CHECK-NEXT: [[FINAL_SUSPEND_FROM_ADDRESS:%.*]] = call ptr @from_address(ptr [[BEGIN]])
-; CHECK-NEXT: call void @await_suspend()
-; CHECK-NEXT: br label %[[COROSUSPEND7:.*]]
-; CHECK: [[COROSUSPEND7]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING:.*]]
-; CHECK: [[RESUME_2]]:
-; CHECK-NEXT: br label %[[RESUME_2_LANDING]]
-; CHECK: [[RESUME_2_LANDING]]:
-; CHECK-NEXT: [[TMP3:%.*]] = phi i8 [ -1, %[[COROSUSPEND7]] ], [ 1, %[[RESUME_2]] ]
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND8:.*]]
-; CHECK: [[AFTERCOROSUSPEND8]]:
-; CHECK-NEXT: switch i8 [[TMP3]], label %[[CORO_RET]] [
-; CHECK-NEXT: i8 0, label %[[FINAL_READY]]
-; CHECK-NEXT: i8 1, label %[[FINAL_CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[FINAL_CLEANUP]]:
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_CLEANUP:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_CLEANUP]]:
-; CHECK-NEXT: [[DOTCLEANUP9:%.*]] = phi i32 [ 2, %[[FINAL_CLEANUP]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[FINAL_READY]]:
-; CHECK-NEXT: call void @await_resume()
-; CHECK-NEXT: br label %[[CLEANUP_FROM_FINAL_READY:.*]]
-; CHECK: [[CLEANUP_FROM_FINAL_READY]]:
-; CHECK-NEXT: [[DOTCLEANUP:%.*]] = phi i32 [ 0, %[[FINAL_READY]] ]
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[CLEANUP_DEST_SLOT_0:%.*]] = phi i32 [ [[DOTCLEANUP]], %[[CLEANUP_FROM_FINAL_READY]] ], [ [[DOTCLEANUP9]], %[[CLEANUP_FROM_FINAL_CLEANUP]] ], [ [[DOTCLEANUP10]], %[[CLEANUP_FROM_AWAIT_CLEANUP]] ], [ [[DOTCLEANUP11]], %[[CLEANUP_FROM_INIT_CLEANUP]] ]
-; CHECK-NEXT: [[FREE:%.*]] = icmp ne ptr null, null
-; CHECK-NEXT: br i1 [[FREE]], label %[[CORO_FREE:.*]], label %[[AFTER_CORO_FREE:.*]]
-; CHECK: [[CORO_FREE]]:
-; CHECK-NEXT: call void @delete(ptr null)
-; CHECK-NEXT: br label %[[AFTER_CORO_FREE]]
-; CHECK: [[AFTER_CORO_FREE]]:
-; CHECK-NEXT: switch i32 [[CLEANUP_DEST_SLOT_0]], label %[[UNREACHABLE:.*]] [
-; CHECK-NEXT: i32 0, label %[[CLEANUP_CONT:.*]]
-; CHECK-NEXT: i32 2, label %[[CORO_RET]]
-; CHECK-NEXT: ]
-; CHECK: [[CLEANUP_CONT]]:
-; CHECK-NEXT: br label %[[CORO_RET]]
-; CHECK: [[CORO_RET]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-; CHECK: [[UNREACHABLE]]:
-; CHECK-NEXT: unreachable
-; CHECK: [[UNREACHABLE12]]:
-; CHECK-NEXT: unreachable
-;
-;.
-; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META1:![0-9]+]], producer: "{{.*}}clang version {{.*}}", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: [[META2:![0-9]+]], retainedTypes: [[META2]], splitDebugInlining: false, nameTableKind: None)
-; CHECK: [[META1]] = !DIFile(filename: "{{.*}}coro-debug.cpp", directory: {{.*}})
-; CHECK: [[META2]] = !{}
-; CHECK: [[DBG6]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: [[DBG6]], file: [[META1]], line: 23, type: [[META7:![0-9]+]], scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META8:![0-9]+]])
-; CHECK: [[META7]] = !DISubroutineType(types: [[META2]])
-; CHECK: [[META8]] = !{[[META9]]}
-; CHECK: [[META9]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG6]], file: [[META1]], line: 23, type: [[META10:![0-9]+]], flags: DIFlagArtificial)
-; CHECK: [[META10]] = !DICompositeType(tag: DW_TAG_structure_type, name: "f.coro_frame_ty", file: [[META1]], line: 23, size: 4736, align: 128, flags: DIFlagArtificial, elements: [[META11:![0-9]+]])
-; CHECK: [[META11]] = !{[[META12:![0-9]+]], [[META14:![0-9]+]], [[META15:![0-9]+]], [[META24:![0-9]+]], [[META29:![0-9]+]], [[META31:![0-9]+]], [[META33:![0-9]+]], [[META35:![0-9]+]], [[META37:![0-9]+]], [[META38:![0-9]+]], [[META42:![0-9]+]], [[META49:![0-9]+]], [[META51:![0-9]+]]}
-; CHECK: [[META12]] = !DIDerivedType(tag: DW_TAG_member, name: "__resume_fn", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META13:![0-9]+]], size: 64, align: 64, flags: DIFlagArtificial)
-; CHECK: [[META13]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
-; CHECK: [[META14]] = !DIDerivedType(tag: DW_TAG_member, name: "__destroy_fn", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META13]], size: 64, align: 64, offset: 64, flags: DIFlagArtificial)
-; CHECK: [[META15]] = !DIDerivedType(tag: DW_TAG_member, name: "__promise", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META16:![0-9]+]], size: 128, align: 64, offset: 128, flags: DIFlagArtificial)
-; CHECK: [[META16]] = !DIDerivedType(tag: DW_TAG_typedef, name: "promise_type", scope: [[DBG6]], file: [[META1]], line: 15, baseType: [[META17:![0-9]+]])
-; CHECK: [[META17]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "promise_type", scope: [[DBG6]], file: [[META1]], line: 10, size: 128, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: [[META18:![0-9]+]], identifier: "_ZTSN4coro12promise_typeE")
-; CHECK: [[META18]] = !{[[META19:![0-9]+]], [[META21:![0-9]+]], [[META22:![0-9]+]]}
-; CHECK: [[META19]] = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: [[DBG6]], file: [[META1]], line: 10, baseType: [[META20:![0-9]+]], size: 32)
-; CHECK: [[META20]] = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-; CHECK: [[META21]] = !DIDerivedType(tag: DW_TAG_member, name: "j", scope: [[DBG6]], file: [[META1]], line: 10, baseType: [[META20]], size: 32, offset: 32)
-; CHECK: [[META22]] = !DIDerivedType(tag: DW_TAG_member, name: "k", scope: [[DBG6]], file: [[META1]], line: 10, baseType: [[META23:![0-9]+]], size: 64, offset: 64)
-; CHECK: [[META23]] = !DIBasicType(name: "double", size: 64, encoding: DW_ATE_float)
-; CHECK: [[META24]] = !DIDerivedType(tag: DW_TAG_member, name: "_0", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META25:![0-9]+]], size: 128, align: 128, offset: 256, flags: DIFlagArtificial)
-; CHECK: [[META25]] = !DICompositeType(tag: DW_TAG_array_type, baseType: [[META26:![0-9]+]], size: 128, align: 16, elements: [[META27:![0-9]+]])
-; CHECK: [[META26]] = !DIBasicType(name: "UnknownType", size: 8, encoding: DW_ATE_unsigned_char, flags: DIFlagArtificial)
-; CHECK: [[META27]] = !{[[META28:![0-9]+]]}
-; CHECK: [[META28]] = !DISubrange(count: 16, lowerBound: 0)
-; CHECK: [[META29]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META30:![0-9]+]], size: 64, align: 32, offset: 384, flags: DIFlagArtificial)
-; CHECK: [[META30]] = !DIBasicType(name: "__int_64", size: 64, encoding: DW_ATE_signed, flags: DIFlagArtificial)
-; CHECK: [[META31]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META32:![0-9]+]], size: 64, align: 32, offset: 448, flags: DIFlagArtificial)
-; CHECK: [[META32]] = !DIBasicType(name: "__double_", size: 64, encoding: DW_ATE_float, flags: DIFlagArtificial)
-; CHECK: [[META33]] = !DIDerivedType(tag: DW_TAG_member, name: "PointerType_3", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META34:![0-9]+]], size: 64, align: 32, offset: 512, flags: DIFlagArtificial)
-; CHECK: [[META34]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "PointerType", baseType: null, size: 64, align: 64)
-; CHECK: [[META35]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META36:![0-9]+]], size: 32, align: 32, offset: 576, flags: DIFlagArtificial)
-; CHECK: [[META36]] = !DIBasicType(name: "__int_32", size: 32, encoding: DW_ATE_signed, flags: DIFlagArtificial)
-; CHECK: [[META37]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_5", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META36]], size: 32, align: 32, offset: 608, flags: DIFlagArtificial)
-; CHECK: [[META38]] = !DIDerivedType(tag: DW_TAG_member, name: "_6", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META39:![0-9]+]], size: 9, align: 16, offset: 640, flags: DIFlagArtificial)
-; CHECK: [[META39]] = !DICompositeType(tag: DW_TAG_array_type, baseType: [[META26]], size: 16, align: 2, elements: [[META40:![0-9]+]])
-; CHECK: [[META40]] = !{[[META41:![0-9]+]]}
-; CHECK: [[META41]] = !DISubrange(count: 2, lowerBound: 0)
-; CHECK: [[META42]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_7", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META43:![0-9]+]], size: 4000, align: 8, offset: 656, flags: DIFlagArtificial)
-; CHECK: [[META43]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure", scope: [[META10]], file: [[META1]], line: 23, size: 4000, align: 64, flags: DIFlagArtificial, elements: [[META44:![0-9]+]])
-; CHECK: [[META44]] = !{[[META45:![0-9]+]]}
-; CHECK: [[META45]] = !DIDerivedType(tag: DW_TAG_member, scope: [[META43]], file: [[META1]], line: 23, baseType: [[META46:![0-9]+]], size: 4000, align: 1, flags: DIFlagArtificial)
-; CHECK: [[META46]] = !DICompositeType(tag: DW_TAG_array_type, baseType: [[META26]], size: 4000, align: 1, elements: [[META47:![0-9]+]])
-; CHECK: [[META47]] = !{[[META48:![0-9]+]]}
-; CHECK: [[META48]] = !DISubrange(count: 500, lowerBound: 0)
-; CHECK: [[META49]] = !DIDerivedType(tag: DW_TAG_member, name: "__coro_index", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META50:![0-9]+]], size: 2, align: 8, offset: 4656, flags: DIFlagArtificial)
-; CHECK: [[META50]] = !DIBasicType(name: "__coro_index", size: 8, encoding: DW_ATE_unsigned_char)
-; CHECK: [[META51]] = !DIDerivedType(tag: DW_TAG_member, name: "UnknownType_8", scope: [[META10]], file: [[META1]], line: 23, baseType: [[META26]], size: 5, align: 8, offset: 4664, flags: DIFlagArtificial)
-; CHECK: [[META52]] = !DILocalVariable(name: "__promise", scope: [[META53:![0-9]+]], file: [[META1]], line: 24, type: [[META16]])
-; CHECK: [[META53]] = distinct !DILexicalBlock(scope: [[DBG6]], file: [[META1]], line: 23, column: 12)
-; CHECK: [[META54]] = !DILocation(line: 8, scope: [[META53]])
-; CHECK: [[META55]] = !DILocation(line: 23, column: 1, scope: [[DBG6]])
-; CHECK: [[DBG56]] = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: [[DBG56]], file: [[META1]], line: 54, type: [[META7]], scopeLine: 54, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META57:![0-9]+]])
-; CHECK: [[META57]] = !{[[META58]]}
-; CHECK: [[META58]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG56]], file: [[META1]], line: 54, type: [[META59:![0-9]+]], flags: DIFlagArtificial)
-; CHECK: [[META59]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar.coro_frame_ty", file: [[META1]], line: 54, size: 4736, align: 128, flags: DIFlagArtificial, elements: [[META60:![0-9]+]])
-; CHECK: [[META60]] = !{[[META61:![0-9]+]], [[META62:![0-9]+]], [[META63:![0-9]+]], [[META64:![0-9]+]], [[META65:![0-9]+]], [[META66:![0-9]+]], [[META67:![0-9]+]], [[META68:![0-9]+]], [[META69:![0-9]+]], [[META73:![0-9]+]]}
-; CHECK: [[META61]] = !DIDerivedType(tag: DW_TAG_member, name: "__resume_fn", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META13]], size: 64, align: 64, flags: DIFlagArtificial)
-; CHECK: [[META62]] = !DIDerivedType(tag: DW_TAG_member, name: "__destroy_fn", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META13]], size: 64, align: 64, offset: 64, flags: DIFlagArtificial)
-; CHECK: [[META63]] = !DIDerivedType(tag: DW_TAG_member, name: "__promise", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META16]], size: 128, align: 64, offset: 128, flags: DIFlagArtificial)
-; CHECK: [[META64]] = !DIDerivedType(tag: DW_TAG_member, name: "_0", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META25]], size: 128, align: 128, offset: 256, flags: DIFlagArtificial)
-; CHECK: [[META65]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META30]], size: 64, align: 32, offset: 384, flags: DIFlagArtificial)
-; CHECK: [[META66]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META32]], size: 64, align: 32, offset: 448, flags: DIFlagArtificial)
-; CHECK: [[META67]] = !DIDerivedType(tag: DW_TAG_member, name: "PointerType_3", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META34]], size: 64, align: 32, offset: 512, flags: DIFlagArtificial)
-; CHECK: [[META68]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META36]], size: 32, align: 32, offset: 576, flags: DIFlagArtificial)
-; CHECK: [[META69]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_5", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META70:![0-9]+]], size: 4000, align: 8, offset: 608, flags: DIFlagArtificial)
-; CHECK: [[META70]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure", scope: [[META59]], file: [[META1]], line: 54, size: 4000, align: 64, flags: DIFlagArtificial, elements: [[META71:![0-9]+]])
-; CHECK: [[META71]] = !{[[META72:![0-9]+]]}
-; CHECK: [[META72]] = !DIDerivedType(tag: DW_TAG_member, scope: [[META70]], file: [[META1]], line: 54, baseType: [[META46]], size: 4000, align: 1, flags: DIFlagArtificial)
-; CHECK: [[META73]] = !DIDerivedType(tag: DW_TAG_member, name: "__coro_index", scope: [[META59]], file: [[META1]], line: 54, baseType: [[META50]], size: 2, align: 8, offset: 4608, flags: DIFlagArtificial)
-; CHECK: [[META74]] = !DILocalVariable(name: "__promise", scope: [[META75:![0-9]+]], file: [[META1]], line: 55, type: [[META16]])
-; CHECK: [[META75]] = distinct !DILexicalBlock(scope: [[DBG56]], file: [[META1]], line: 23, column: 12)
-; CHECK: [[META76]] = !DILocation(line: 10, scope: [[META75]])
-; CHECK: [[META77]] = !DILocation(line: 54, column: 1, scope: [[DBG56]])
-; CHECK: [[DBG78]] = distinct !DISubprogram(name: "foo", linkageName: "f.resume", scope: [[DBG78]], file: [[META1]], line: 23, type: [[META7]], scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META79:![0-9]+]])
-; CHECK: [[META79]] = !{[[META80]]}
-; CHECK: [[META80]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG78]], file: [[META1]], line: 23, type: [[META10]], flags: DIFlagArtificial)
-; CHECK: [[META81]] = !DILocalVariable(name: "__promise", scope: [[META82:![0-9]+]], file: [[META1]], line: 24, type: [[META16]])
-; CHECK: [[META82]] = distinct !DILexicalBlock(scope: [[DBG78]], file: [[META1]], line: 23, column: 12)
-; CHECK: [[META83]] = !DILocation(line: 8, scope: [[META82]])
-; CHECK: [[META84]] = !DILocation(line: 23, column: 1, scope: [[DBG78]])
-; CHECK: [[DBG85]] = distinct !DISubprogram(name: "foo", linkageName: "f.destroy", scope: [[DBG85]], file: [[META1]], line: 23, type: [[META7]], scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META86:![0-9]+]])
-; CHECK: [[META86]] = !{[[META87]]}
-; CHECK: [[META87]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG85]], file: [[META1]], line: 23, type: [[META10]], flags: DIFlagArtificial)
-; CHECK: [[META88]] = !DILocalVariable(name: "__promise", scope: [[META89:![0-9]+]], file: [[META1]], line: 24, type: [[META16]])
-; CHECK: [[META89]] = distinct !DILexicalBlock(scope: [[DBG85]], file: [[META1]], line: 23, column: 12)
-; CHECK: [[META90]] = !DILocation(line: 8, scope: [[META89]])
-; CHECK: [[META91]] = !DILocation(line: 23, column: 1, scope: [[DBG85]])
-; CHECK: [[DBG92]] = distinct !DISubprogram(name: "foo", linkageName: "f.cleanup", scope: [[DBG92]], file: [[META1]], line: 23, type: [[META7]], scopeLine: 23, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META93:![0-9]+]])
-; CHECK: [[META93]] = !{[[META94]]}
-; CHECK: [[META94]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG92]], file: [[META1]], line: 23, type: [[META10]], flags: DIFlagArtificial)
-; CHECK: [[META95]] = !DILocalVariable(name: "__promise", scope: [[META96:![0-9]+]], file: [[META1]], line: 24, type: [[META16]])
-; CHECK: [[META96]] = distinct !DILexicalBlock(scope: [[DBG92]], file: [[META1]], line: 23, column: 12)
-; CHECK: [[META97]] = !DILocation(line: 8, scope: [[META96]])
-; CHECK: [[META98]] = !DILocation(line: 23, column: 1, scope: [[DBG92]])
-; CHECK: [[DBG99]] = distinct !DISubprogram(name: "bar", linkageName: "bar.resume", scope: [[DBG99]], file: [[META1]], line: 54, type: [[META7]], scopeLine: 54, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META100:![0-9]+]])
-; CHECK: [[META100]] = !{[[META101]]}
-; CHECK: [[META101]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG99]], file: [[META1]], line: 54, type: [[META59]], flags: DIFlagArtificial)
-; CHECK: [[META102]] = !DILocalVariable(name: "__promise", scope: [[META103:![0-9]+]], file: [[META1]], line: 55, type: [[META16]])
-; CHECK: [[META103]] = distinct !DILexicalBlock(scope: [[DBG99]], file: [[META1]], line: 23, column: 12)
-; CHECK: [[META104]] = !DILocation(line: 10, scope: [[META103]])
-; CHECK: [[META105]] = !DILocation(line: 54, column: 1, scope: [[DBG99]])
-; CHECK: [[DBG106]] = distinct !DISubprogram(name: "bar", linkageName: "bar.destroy", scope: [[DBG106]], file: [[META1]], line: 54, type: [[META7]], scopeLine: 54, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META107:![0-9]+]])
-; CHECK: [[META107]] = !{[[META108]]}
-; CHECK: [[META108]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG106]], file: [[META1]], line: 54, type: [[META59]], flags: DIFlagArtificial)
-; CHECK: [[META109]] = !DILocalVariable(name: "__promise", scope: [[META110:![0-9]+]], file: [[META1]], line: 55, type: [[META16]])
-; CHECK: [[META110]] = distinct !DILexicalBlock(scope: [[DBG106]], file: [[META1]], line: 23, column: 12)
-; CHECK: [[META111]] = !DILocation(line: 10, scope: [[META110]])
-; CHECK: [[META112]] = !DILocation(line: 54, column: 1, scope: [[DBG106]])
-; CHECK: [[DBG113]] = distinct !DISubprogram(name: "bar", linkageName: "bar.cleanup", scope: [[DBG113]], file: [[META1]], line: 54, type: [[META7]], scopeLine: 54, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META114:![0-9]+]])
-; CHECK: [[META114]] = !{[[META115]]}
-; CHECK: [[META115]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG113]], file: [[META1]], line: 54, type: [[META59]], flags: DIFlagArtificial)
-; CHECK: [[META116]] = !DILocalVariable(name: "__promise", scope: [[META117:![0-9]+]], file: [[META1]], line: 55, type: [[META16]])
-; CHECK: [[META117]] = distinct !DILexicalBlock(scope: [[DBG113]], file: [[META1]], line: 23, column: 12)
-; CHECK: [[META118]] = !DILocation(line: 10, scope: [[META117]])
-; CHECK: [[META119]] = !DILocation(line: 54, column: 1, scope: [[DBG113]])
-;.
diff --git a/llvm/test/Transforms/Coroutines/coro-materialize.ll b/llvm/test/Transforms/Coroutines/coro-materialize.ll
index c584664f542a6..f55db35edb3ea 100644
--- a/llvm/test/Transforms/Coroutines/coro-materialize.ll
+++ b/llvm/test/Transforms/Coroutines/coro-materialize.ll
@@ -1,32 +1,20 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Verifies that we materialize instruction across suspend points
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
; See that we only spilled one value for f
-; Check other variants where different levels of materialization are achieved
-
; CHECK: %f.Frame = type { ptr, ptr, i32, i1 }
; CHECK: %f_optnone.Frame = type { ptr, ptr, i32, i32, i1 }
+; Check other variants where different levels of materialization are achieved
; CHECK: %f_multiple_remat.Frame = type { ptr, ptr, i32, i1 }
; CHECK: %f_common_def.Frame = type { ptr, ptr, i32, i1 }
; CHECK: %f_common_def_multi_result.Frame = type { ptr, ptr, i32, i1 }
+; CHECK-LABEL: @f(
+; CHECK-LABEL: @f_optnone
+; CHECK-LABEL: @f_multiple_remat(
+; CHECK-LABEL: @f_common_def(
+; CHECK-LABEL: @f_common_def_multi_result(
define ptr @f(i32 %n) presplitcoroutine {
-; CHECK-LABEL: define ptr @f(
-; CHECK-SAME: i32 [[N:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[N_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i32 [[N]], ptr [[N_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR12]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -36,12 +24,12 @@ entry:
%inc1 = add i32 %n, 1
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%inc2 = add i32 %inc1, 1
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
call void @print(i32 %inc1)
@@ -59,76 +47,6 @@ suspend:
; Checks that we won't transform functions with optnone.
define ptr @f_optnone(i32 %n) presplitcoroutine optnone noinline {
-; CHECK-LABEL: define ptr @f_optnone(
-; CHECK-SAME: i32 [[N:%.*]]) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_optnone.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 32)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_OPTNONE_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: store ptr @f_optnone.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f_optnone.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
-; CHECK: [[ALLOCASPILLBB]]:
-; CHECK-NEXT: br label %[[POSTSPILL:.*]]
-; CHECK: [[POSTSPILL]]:
-; CHECK-NEXT: [[INC1:%.*]] = add i32 [[N]], 1
-; CHECK-NEXT: [[INC1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i32 [[INC1]], ptr [[INC1_SPILL_ADDR]], align 4
-; CHECK-NEXT: br label %[[COROSAVE:.*]]
-; CHECK: [[COROSAVE]]:
-; CHECK-NEXT: [[INDEX_ADDR6:%.*]] = getelementptr inbounds nuw [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 4
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR6]], align 1
-; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
-; CHECK: [[COROSUSPEND]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: switch i8 -1, label %[[SUSPEND:.*]] [
-; CHECK-NEXT: i8 0, label %[[RESUME1:.*]]
-; CHECK-NEXT: i8 1, label %[[CLEANUP:.*]]
-; CHECK-NEXT: ]
-; CHECK: [[RESUME1]]:
-; CHECK-NEXT: [[INC1_RELOAD_ADDR4:%.*]] = getelementptr inbounds [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[INC1_RELOAD5:%.*]] = load i32, ptr [[INC1_RELOAD_ADDR4]], align 4
-; CHECK-NEXT: [[INC2:%.*]] = add i32 [[INC1_RELOAD5]], 1
-; CHECK-NEXT: [[INC2_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i32 [[INC2]], ptr [[INC2_SPILL_ADDR]], align 4
-; CHECK-NEXT: br label %[[COROSAVE1:.*]]
-; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR7:%.*]] = getelementptr inbounds nuw [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 4
-; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR7]], align 1
-; CHECK-NEXT: br label %[[COROSUSPEND2:.*]]
-; CHECK: [[COROSUSPEND2]]:
-; CHECK-NEXT: br label %[[RESUME_1_LANDING:.*]]
-; CHECK: [[RESUME_1_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND3:.*]]
-; CHECK: [[AFTERCOROSUSPEND3]]:
-; CHECK-NEXT: switch i8 -1, label %[[SUSPEND]] [
-; CHECK-NEXT: i8 0, label %[[RESUME2:.*]]
-; CHECK-NEXT: i8 1, label %[[CLEANUP]]
-; CHECK-NEXT: ]
-; CHECK: [[RESUME2]]:
-; CHECK-NEXT: [[INC2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: [[INC2_RELOAD:%.*]] = load i32, ptr [[INC2_RELOAD_ADDR]], align 4
-; CHECK-NEXT: [[INC1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_OPTNONE_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[INC1_RELOAD:%.*]] = load i32, ptr [[INC1_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[INC1_RELOAD]])
-; CHECK-NEXT: call void @print(i32 [[INC2_RELOAD]])
-; CHECK-NEXT: br label %[[CLEANUP]]
-; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[MEM:%.*]] = call ptr @llvm.coro.free(token [[ID]], ptr [[HDL]])
-; CHECK-NEXT: call void @free(ptr [[MEM]])
-; CHECK-NEXT: br label %[[SUSPEND]]
-; CHECK: [[SUSPEND]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
-; CHECK: [[AFTERCOROEND]]:
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -138,12 +56,12 @@ entry:
%inc1 = add i32 %n, 1
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%inc2 = add i32 %inc1, 1
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
call void @print(i32 %inc1)
@@ -160,26 +78,6 @@ suspend:
}
define ptr @f_multiple_remat(i32 %n) presplitcoroutine {
-; CHECK-LABEL: define ptr @f_multiple_remat(
-; CHECK-SAME: i32 [[N:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_multiple_remat.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f_multiple_remat.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_MULTIPLE_REMAT_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f_multiple_remat.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[N_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_MULTIPLE_REMAT_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i32 [[N]], ptr [[N_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[INC1:%.*]] = add i32 [[N]], 1
-; CHECK-NEXT: [[INC2:%.*]] = add i32 [[INC1]], 2
-; CHECK-NEXT: [[INC3:%.*]] = add i32 [[INC2]], 3
-; CHECK-NEXT: [[INC4:%.*]] = add i32 [[INC3]], 4
-; CHECK-NEXT: [[INC5:%.*]] = add i32 [[INC4]], 5
-; CHECK-NEXT: [[INDEX_ADDR22:%.*]] = getelementptr inbounds nuw [[F_MULTIPLE_REMAT_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR22]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -194,12 +92,12 @@ entry:
%inc6 = add i32 %inc5, 5
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%inc7 = add i32 %inc6, 1
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
call void @print(i32 %inc1)
@@ -216,25 +114,6 @@ suspend:
}
define ptr @f_common_def(i32 %n) presplitcoroutine {
-; CHECK-LABEL: define ptr @f_common_def(
-; CHECK-SAME: i32 [[N:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_common_def.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f_common_def.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_COMMON_DEF_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f_common_def.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[N_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_COMMON_DEF_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i32 [[N]], ptr [[N_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[INC1:%.*]] = add i32 [[N]], 1
-; CHECK-NEXT: [[INC3:%.*]] = add i32 [[N]], 3
-; CHECK-NEXT: [[INC4:%.*]] = add i32 [[INC3]], [[INC1]]
-; CHECK-NEXT: [[INC5:%.*]] = add i32 [[INC4]], [[INC1]]
-; CHECK-NEXT: [[INDEX_ADDR20:%.*]] = getelementptr inbounds nuw [[F_COMMON_DEF_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR20]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -249,12 +128,12 @@ entry:
%inc6 = add i32 %inc5, 5
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%inc7 = add i32 %inc6, 1
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
call void @print(i32 %inc1)
@@ -271,30 +150,6 @@ suspend:
}
define ptr @f_common_def_multi_result(i32 %n) presplitcoroutine {
-; CHECK-LABEL: define ptr @f_common_def_multi_result(
-; CHECK-SAME: i32 [[N:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f_common_def_multi_result.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
-; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @f_common_def_multi_result.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_COMMON_DEF_MULTI_RESULT_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
-; CHECK-NEXT: store ptr @f_common_def_multi_result.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[N_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_COMMON_DEF_MULTI_RESULT_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: store i32 [[N]], ptr [[N_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[INC1:%.*]] = add i32 [[N]], 1
-; CHECK-NEXT: [[INC2:%.*]] = add i32 [[INC1]], 2
-; CHECK-NEXT: [[INC3:%.*]] = add i32 [[N]], 3
-; CHECK-NEXT: [[INC4:%.*]] = add i32 [[INC3]], [[INC1]]
-; CHECK-NEXT: [[INC5:%.*]] = add i32 [[INC4]], [[INC1]]
-; CHECK-NEXT: [[INC6:%.*]] = add i32 [[INC5]], 4
-; CHECK-NEXT: [[INC8:%.*]] = add i32 [[INC4]], [[INC2]]
-; CHECK-NEXT: [[INC9:%.*]] = add i32 [[INC8]], 5
-; CHECK-NEXT: [[INC10:%.*]] = add i32 [[INC9]], 6
-; CHECK-NEXT: [[INDEX_ADDR27:%.*]] = getelementptr inbounds nuw [[F_COMMON_DEF_MULTI_RESULT_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR27]], align 1
-; CHECK-NEXT: ret ptr [[HDL]]
-;
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
%size = call i32 @llvm.coro.size.i32()
@@ -314,12 +169,12 @@ entry:
%inc11 = add i32 %inc10, 7
%sp1 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp1, label %suspend [i8 0, label %resume1
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume1:
%inc12 = add i32 %inc7, 1
%sp2 = call i8 @llvm.coro.suspend(token none, i1 false)
switch i8 %sp2, label %suspend [i8 0, label %resume2
- i8 1, label %cleanup]
+ i8 1, label %cleanup]
resume2:
call void @print(i32 %inc11)
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll b/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
index c7fcf0061b51d..8f33724a2d12e 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
@@ -3,16 +3,12 @@
; if it may be used across suspend points.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-
; %sp1 should be part of the frame (the i8 value).
-
+;
; If the coro resumes, %sp1 is set to 0.
-
+;
; In the coro destroy function, %sp1 is reloaded from the frame. Its value
; depends on whether the coroutine was resumed or not.
-
-
-
define ptr @f(i32 %n) presplitcoroutine {
entry:
%id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
diff --git a/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll b/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
index 665be555763fc..45a843008e0e9 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
@@ -33,20 +33,13 @@ entry:
; Check that frame debug info is generated
-
; Key validation: Check that nested structs have the correct scope hierarchy
; 1. Promise should be scoped to the frame
-
; 2. Members of Promise should be scoped to Promise (check this before Outer since it comes first in output)
-
; 3. Outer should be scoped to Promise (not the frame!)
-
; 4. First Outer member should be scoped to Outer
-
; 5. Inner should be scoped to Outer (proper nesting)
-
; 6. Members of Inner should be scoped to Inner
-
; 7. Second Outer member comes after Inner (due to output order)
declare token @llvm.coro.id(i32, ptr readnone, ptr readonly, ptr)
diff --git a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
index e2811b02101f6..848cf8b3e461f 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
@@ -1,14 +1,14 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Tests that coro-split will optimize the lifetime.start maker of each local variable,
; sink them to the places after the suspend block.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse,simplifycfg' -S | FileCheck %s
+; CHECK: %a.Frame = type { ptr, ptr, i1 }
+; CHECK: %a_optnone.Frame = type { ptr, ptr, i32, i1 }
%"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 ptr @malloc(i64)
declare void @print(i32)
@@ -25,8 +25,8 @@ entry:
%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
- i8 1, label %exit
+ i8 0, label %await.ready
+ i8 1, label %exit
]
await.ready:
%StrayCoroSave = call token @llvm.coro.save(ptr null)
@@ -41,6 +41,15 @@ exit:
ret void
}
+; CHECK-LABEL: @a.resume(
+; CHECK: %testval = alloca i32, align 4
+; CHECK: call void @llvm.lifetime.start.p0(ptr %testval)
+; CHECK-NEXT: %val = load i32, ptr %ref.tmp7
+; CHECK-NEXT: %test = load i32, ptr %testval
+; CHECK-NEXT: call void @print(i32 %test)
+; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr %testval)
+; CHECK-NEXT: call void @print(i32 %val)
+; CHECK-NEXT: ret void
define void @a_optnone() presplitcoroutine optnone noinline {
entry:
@@ -55,8 +64,8 @@ entry:
%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
- i8 1, label %exit
+ i8 0, label %await.ready
+ i8 1, label %exit
]
await.ready:
%StrayCoroSave = call token @llvm.coro.save(ptr null)
@@ -85,174 +94,3 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly) #2
declare void @llvm.coro.end(ptr, i1, token) #3
declare void @llvm.lifetime.start.p0(ptr nocapture) #4
declare void @llvm.lifetime.end.p0(ptr nocapture) #4
-; CHECK-LABEL: define void @a() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
-; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @a.resume, ptr [[VFRAME]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
-; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define void @a_optnone(
-; CHECK-SAME: ) #[[ATTR0:[0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a_optnone.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
-; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 0
-; CHECK-NEXT: store ptr @a_optnone.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 1
-; CHECK-NEXT: store ptr @a_optnone.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
-; CHECK: [[ALLOCASPILLBB]]:
-; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: br label %[[POSTSPILL:.*]]
-; CHECK: [[POSTSPILL]]:
-; CHECK-NEXT: br label %[[COROSAVE:.*]]
-; CHECK: [[COROSAVE]]:
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_OPTNONE_FRAME]], ptr [[VFRAME]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: br label %[[COROSUSPEND:.*]]
-; CHECK: [[COROSUSPEND]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 -1, 0
-; CHECK-NEXT: br i1 [[COND]], label %[[AWAIT_READY:.*]], label %[[EXIT:.*]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: br label %[[EXIT]]
-; CHECK: [[EXIT]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
-; CHECK: [[AFTERCOROEND]]:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal fastcc void @a.resume(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
-; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TESTVAL]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal fastcc void @a.destroy(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
-; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
-; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal fastcc void @a.cleanup(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
-; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
-; CHECK-NEXT: [[TESTVAL:%.*]] = alloca i32, align 4
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal fastcc void @a_optnone.resume(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_OPTNONE_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
-; CHECK: [[RESUME_ENTRY]]:
-; CHECK-NEXT: br label %[[RESUME_0:.*]]
-; CHECK: [[RESUME_0]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 0, 0
-; CHECK-NEXT: br i1 [[COND]], label %[[AWAIT_READY:.*]], label %[[EXIT:.*]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: br label %[[EXIT]]
-; CHECK: [[EXIT]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal fastcc void @a_optnone.destroy(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_OPTNONE_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
-; CHECK: [[RESUME_ENTRY]]:
-; CHECK-NEXT: br label %[[RESUME_0:.*]]
-; CHECK: [[RESUME_0]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 1, 0
-; CHECK-NEXT: br i1 [[COND]], label %[[AWAIT_READY:.*]], label %[[EXIT:.*]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: br label %[[EXIT]]
-; CHECK: [[EXIT]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal fastcc void @a_optnone.cleanup(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_OPTNONE_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: br label %[[RESUME_ENTRY:.*]]
-; CHECK: [[RESUME_ENTRY]]:
-; CHECK-NEXT: br label %[[RESUME_0:.*]]
-; CHECK: [[RESUME_0]]:
-; CHECK-NEXT: br label %[[RESUME_0_LANDING:.*]]
-; CHECK: [[RESUME_0_LANDING]]:
-; CHECK-NEXT: br label %[[AFTERCOROSUSPEND:.*]]
-; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 1, 0
-; CHECK-NEXT: br i1 [[COND]], label %[[AWAIT_READY:.*]], label %[[EXIT:.*]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: br label %[[EXIT]]
-; CHECK: [[EXIT]]:
-; CHECK-NEXT: br label %[[COROEND:.*]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-;
diff --git a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
index b3347cb8366d7..26037043a26ed 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 6
; Tests that coro-split will optimize the lifetime.start maker of each local variable,
; sink them to the places after the suspend block.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
@@ -27,8 +26,8 @@ if.suspend:
%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
- i8 1, label %exit
+ i8 0, label %await.ready
+ i8 1, label %exit
]
else.direct:
@@ -53,6 +52,10 @@ exit:
ret void
}
+; CHECK-LABEL: @a.resume(
+; CHECK: %[[VAL:testval.+]] = getelementptr inbounds %a.Frame
+; CHECK-NOT: call void @llvm.lifetime.start.p0(ptr %{{.*}})
+; CHECK: %test = load i32, ptr %[[VAL]]
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
declare i1 @llvm.coro.alloc(token) #3
@@ -68,86 +71,3 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly) #2
declare void @llvm.coro.end(ptr, i1, token) #3
declare void @llvm.lifetime.start.p0(ptr nocapture) #4
declare void @llvm.lifetime.end.p0(ptr nocapture) #4
-; CHECK-LABEL: define void @a() {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @a.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
-; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: store ptr @a.resume, ptr [[VFRAME]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
-; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: [[TESTCOND:%.*]] = call i1 @getcond()
-; CHECK-NEXT: br i1 [[TESTCOND]], label %[[COROSAVE:.*]], label %[[AFTER_AWAIT:.*]]
-; CHECK: [[COROSAVE]]:
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[VFRAME]], i32 0, i32 3
-; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
-; CHECK-NEXT: br i1 false, label %[[AWAIT_READY:.*]], label %[[AFTERCOROEND:.*]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: br label %[[AFTER_AWAIT]]
-; CHECK: [[AFTER_AWAIT]]:
-; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST1]])
-; CHECK-NEXT: br label %[[AFTERCOROEND]]
-; CHECK: [[AFTERCOROEND]]:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal fastcc void @a.resume(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
-; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: br i1 true, label %[[AWAIT_READY:.*]], label %[[COROEND:.*]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST1]])
-; CHECK-NEXT: br label %[[COROEND]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal fastcc void @a.destroy(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
-; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: br i1 false, label %[[AWAIT_READY:.*]], label %[[COROEND:.*]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST1]])
-; CHECK-NEXT: br label %[[COROEND]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-;
-;
-; CHECK-LABEL: define internal fastcc void @a.cleanup(
-; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[VFRAME:%.*]]) {
-; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
-; CHECK-NEXT: [[REF_TMP7:%.*]] = alloca %"struct.lean_future<int>::Awaiter", align 8
-; CHECK-NEXT: [[TESTVAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: br i1 false, label %[[AWAIT_READY:.*]], label %[[COROEND:.*]]
-; CHECK: [[AWAIT_READY]]:
-; CHECK-NEXT: [[VAL:%.*]] = load i32, ptr [[REF_TMP7]], align 4
-; CHECK-NEXT: [[TEST:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST]])
-; CHECK-NEXT: call void @print(i32 [[VAL]])
-; CHECK-NEXT: [[TEST1:%.*]] = load i32, ptr [[TESTVAL_RELOAD_ADDR]], align 4
-; CHECK-NEXT: call void @print(i32 [[TEST1]])
-; CHECK-NEXT: br label %[[COROEND]]
-; CHECK: [[COROEND]]:
-; CHECK-NEXT: ret void
-;
>From 635cb26d2b1c4f6f1d6b5ce294dd6ecebe18ad43 Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash at gmail.com>
Date: Fri, 13 Feb 2026 22:05:05 +0000
Subject: [PATCH 5/7] review
---
.../Transforms/Coroutines/coro-byval-param.ll | 6 +-
.../Coroutines/coro-frame-reuse-alloca-01.ll | 5 +-
.../Transforms/Coroutines/coro-param-copy.ll | 12 ++--
.../coro-split-dbg-nested-struct.ll | 62 +++++--------------
.../Coroutines/coro-split-tbaa-md.ll | 4 +-
5 files changed, 31 insertions(+), 58 deletions(-)
diff --git a/llvm/test/Transforms/Coroutines/coro-byval-param.ll b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
index 4575c0af8ee11..ead86322662e7 100644
--- a/llvm/test/Transforms/Coroutines/coro-byval-param.ll
+++ b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
@@ -3,6 +3,9 @@
%promise_type = type { i8 }
%struct.A = type <{ i64, i64, i32, [4 x i8] }>
+; Check that the frame will contain the entire struct, instead of just the
+; struct pointer, and that the alignment is taken into account.
+
; CHECK: %foo.Frame = type { ptr, ptr, %promise_type, i1, [6 x i8], %struct.A }
; Function Attrs: noinline ssp uwtable mustprogress
@@ -86,9 +89,6 @@ coro.ret: ; preds = %coro.free, %cleanup
ret ptr %call2
}
-; check that the frame contains the entire struct, instead of just the struct pointer,
-; and that the alignment is taken into account.
-
; Function Attrs: argmemonly nounwind readonly
declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll
index 4481a30a32dfa..3bed01bb4a877 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll
@@ -1,6 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; Tests that variables in a Corotuine whose lifetime range is not overlapping each other
-; re-use the same slot in Coroutine frame.
+; re-use the same slot in Coroutine frame:
+; There should be only one %struct.big_structure in the frame.
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1 }
@@ -84,8 +85,6 @@ coro.ret:
ret void
}
-; check that there is only one %struct.big_structure in the frame.
-
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
diff --git a/llvm/test/Transforms/Coroutines/coro-param-copy.ll b/llvm/test/Transforms/Coroutines/coro-param-copy.ll
index 4d8d7f607a34f..4f490befafd1e 100644
--- a/llvm/test/Transforms/Coroutines/coro-param-copy.ll
+++ b/llvm/test/Transforms/Coroutines/coro-param-copy.ll
@@ -1,16 +1,16 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+
; Check that we create copy the data from the alloca into the coroutine
; frame slot if it was written to.
-; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+; 1. See that we added both x and y to the frame.
+; 2. Then see that all of the uses prior to coro-begin stays put.
+; 3. Then see that we only copy the x as y was not modified prior to
+; coro.begin.
; CHECK: %f.Frame = type { ptr, ptr, i64, i64, i64, i64, i1 }
define ptr @f() presplitcoroutine {
-; See that we added both x and y to the frame.
-;
-; Then see that all of the uses prior to coro-begin stays put.
-;
-; Then see that we only copy the x as y was not modified prior to coro.begin.
; CHECK-LABEL: define ptr @f() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
diff --git a/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll b/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
index 45a843008e0e9..12dfa16991326 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
@@ -1,4 +1,3 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='cgscc(coro-split)' -S | FileCheck %s
; Test that nested structs in coroutine frames have correct debug info scoping.
@@ -11,18 +10,6 @@
%"class.Promise" = type { %"struct.Outer" }
define void @test_coro_function() presplitcoroutine !dbg !10 {
-; CHECK-LABEL: define void @test_coro_function(
-; CHECK-SAME: ) !dbg [[DBG3:![0-9]+]] {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[__PROMISE:%.*]] = alloca [[CLASS_PROMISE:%.*]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
-; CHECK-NEXT: br label %[[ALLOCASPILLBB:.*]]
-; CHECK: [[ALLOCASPILLBB]]:
-; CHECK-NEXT: #dbg_declare(ptr null, [[META7:![0-9]+]], !DIExpression(), [[META30:![0-9]+]])
-; CHECK-NEXT: br label %[[POSTSPILL:.*]]
-; CHECK: [[POSTSPILL]]:
-; CHECK-NEXT: ret void
-;
entry:
%__promise = alloca %"class.Promise", align 8
%0 = call token @llvm.coro.id(i32 0, ptr %__promise, ptr null, ptr null)
@@ -31,16 +18,33 @@ entry:
ret void
}
+; CHECK: define void @test_coro_function()
; Check that frame debug info is generated
+; CHECK: ![[FRAME_TYPE:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{{.*}}.coro_frame_ty"
+
; Key validation: Check that nested structs have the correct scope hierarchy
; 1. Promise should be scoped to the frame
+; CHECK: ![[PROMISE:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "class_Promise", scope: ![[FRAME_TYPE]]
+
; 2. Members of Promise should be scoped to Promise (check this before Outer since it comes first in output)
+; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "struct_Outer", scope: ![[PROMISE]]
+
; 3. Outer should be scoped to Promise (not the frame!)
+; CHECK: ![[OUTER:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_Outer", scope: ![[PROMISE]]
+
; 4. First Outer member should be scoped to Outer
+; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "struct_Inner", scope: ![[OUTER]]
+
; 5. Inner should be scoped to Outer (proper nesting)
+; CHECK: ![[INNER:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_Inner", scope: ![[OUTER]]
+
; 6. Members of Inner should be scoped to Inner
+; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__int_32", scope: ![[INNER]]
+; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "PointerType", scope: ![[INNER]]
+
; 7. Second Outer member comes after Inner (due to output order)
+; CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__int_64", scope: ![[OUTER]]
declare token @llvm.coro.id(i32, ptr readnone, ptr readonly, ptr)
declare ptr @llvm.coro.begin(token, ptr writeonly)
@@ -55,35 +59,3 @@ declare token @llvm.coro.save(ptr)
!10 = distinct !DISubprogram(name: "test_coro_function", scope: !1, file: !1, line: 1, type: !11, spFlags: DISPFlagDefinition, unit: !0)
!11 = !DISubroutineType(types: !12)
!12 = !{null}
-;.
-; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: [[META1:![0-9]+]], producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
-; CHECK: [[META1]] = !DIFile(filename: "{{.*}}test.cpp", directory: {{.*}})
-; CHECK: [[DBG3]] = distinct !DISubprogram(name: "test_coro_function", scope: [[META1]], file: [[META1]], line: 1, type: [[META4:![0-9]+]], spFlags: DISPFlagDefinition, unit: [[META0]], retainedNodes: [[META6:![0-9]+]])
-; CHECK: [[META4]] = !DISubroutineType(types: [[META5:![0-9]+]])
-; CHECK: [[META5]] = !{null}
-; CHECK: [[META6]] = !{[[META7]]}
-; CHECK: [[META7]] = !DILocalVariable(name: "__coro_frame", scope: [[DBG3]], file: [[META1]], line: 1, type: [[META8:![0-9]+]], flags: DIFlagArtificial)
-; CHECK: [[META8]] = !DICompositeType(tag: DW_TAG_structure_type, name: "test_coro_function.coro_frame_ty", file: [[META1]], line: 1, size: 384, align: 64, flags: DIFlagArtificial, elements: [[META9:![0-9]+]])
-; CHECK: [[META9]] = !{[[META10:![0-9]+]], [[META12:![0-9]+]], [[META13:![0-9]+]], [[META28:![0-9]+]]}
-; CHECK: [[META10]] = !DIDerivedType(tag: DW_TAG_member, name: "__resume_fn", scope: [[META8]], file: [[META1]], line: 1, baseType: [[META11:![0-9]+]], size: 64, align: 64, flags: DIFlagArtificial)
-; CHECK: [[META11]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
-; CHECK: [[META12]] = !DIDerivedType(tag: DW_TAG_member, name: "__destroy_fn", scope: [[META8]], file: [[META1]], line: 1, baseType: [[META11]], size: 64, align: 64, offset: 64, flags: DIFlagArtificial)
-; CHECK: [[META13]] = !DIDerivedType(tag: DW_TAG_member, name: "class_Promise_0", scope: [[META8]], file: [[META1]], line: 1, baseType: [[META14:![0-9]+]], size: 192, align: 64, offset: 128, flags: DIFlagArtificial)
-; CHECK: [[META14]] = !DICompositeType(tag: DW_TAG_structure_type, name: "class_Promise", scope: [[META8]], file: [[META1]], line: 1, size: 192, align: 64, flags: DIFlagArtificial, elements: [[META15:![0-9]+]])
-; CHECK: [[META15]] = !{[[META16:![0-9]+]]}
-; CHECK: [[META16]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_Outer", scope: [[META14]], file: [[META1]], line: 1, baseType: [[META17:![0-9]+]], size: 192, align: 64, flags: DIFlagArtificial)
-; CHECK: [[META17]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_Outer", scope: [[META14]], file: [[META1]], line: 1, size: 192, align: 64, flags: DIFlagArtificial, elements: [[META18:![0-9]+]])
-; CHECK: [[META18]] = !{[[META19:![0-9]+]], [[META26:![0-9]+]]}
-; CHECK: [[META19]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_Inner", scope: [[META17]], file: [[META1]], line: 1, baseType: [[META20:![0-9]+]], size: 128, align: 64, flags: DIFlagArtificial)
-; CHECK: [[META20]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_Inner", scope: [[META17]], file: [[META1]], line: 1, size: 128, align: 64, flags: DIFlagArtificial, elements: [[META21:![0-9]+]])
-; CHECK: [[META21]] = !{[[META22:![0-9]+]], [[META24:![0-9]+]]}
-; CHECK: [[META22]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32", scope: [[META20]], file: [[META1]], line: 1, baseType: [[META23:![0-9]+]], size: 32, flags: DIFlagArtificial)
-; CHECK: [[META23]] = !DIBasicType(name: "__int_32", size: 32, encoding: DW_ATE_signed, flags: DIFlagArtificial)
-; CHECK: [[META24]] = !DIDerivedType(tag: DW_TAG_member, name: "PointerType", scope: [[META20]], file: [[META1]], line: 1, baseType: [[META25:![0-9]+]], size: 64, align: 64, offset: 64, flags: DIFlagArtificial)
-; CHECK: [[META25]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "PointerType", baseType: null, size: 64, align: 64)
-; CHECK: [[META26]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64", scope: [[META17]], file: [[META1]], line: 1, baseType: [[META27:![0-9]+]], size: 64, offset: 128, flags: DIFlagArtificial)
-; CHECK: [[META27]] = !DIBasicType(name: "__int_64", size: 64, encoding: DW_ATE_signed, flags: DIFlagArtificial)
-; CHECK: [[META28]] = !DIDerivedType(tag: DW_TAG_member, name: "__coro_index", scope: [[META8]], file: [[META1]], line: 1, baseType: [[META29:![0-9]+]], size: 64, align: 32, offset: 320, flags: DIFlagArtificial)
-; CHECK: [[META29]] = !DIBasicType(name: "__coro_index", size: 64, encoding: DW_ATE_unsigned_char)
-; CHECK: [[META30]] = !DILocation(line: 1, column: 1, scope: [[DBG3]])
-;.
diff --git a/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll b/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
index 196c82ea81ee3..010c6b87b3c21 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
@@ -83,7 +83,7 @@ declare void @free(ptr) willreturn allockind("free") "alloc-family"="malloc"
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4
+; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4, !tbaa [[F_FRAME_SLOT_TBAA4:![0-9]+]]
; CHECK-NEXT: call void @print(i32 [[X_RELOAD]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
; CHECK-NEXT: ret void
@@ -106,4 +106,6 @@ declare void @free(ptr) willreturn allockind("free") "alloc-family"="malloc"
; CHECK: [[META1]] = !{!"int", [[META2:![0-9]+]], i64 0}
; CHECK: [[META2]] = !{!"omnipotent char", [[META3:![0-9]+]], i64 0}
; CHECK: [[META3]] = !{!"Simple C++ TBAA"}
+; CHECK: [[F_FRAME_SLOT_TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0}
+; CHECK: [[META5]] = !{!"f.Frame Slot", [[META3]], i64 0}
;.
>From f661cf414686d5588bdac29dc5c27e7dd4c89d3b Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash at gmail.com>
Date: Fri, 13 Feb 2026 22:14:35 +0000
Subject: [PATCH 6/7] [Coroutines] Replace struct alloca frame with byte array
and ptradd
Replace coroutine frame struct type with a simple byte array and use
offset-based ptradd operations instead of struct GEP for all field
access. Alloca types have largely lost all meaning to LLVM (even this
pass merges them and uses a random type to represent all of them), and
so they just makes the code to construct alloca more difficult and less
flexible.
Key changes:
- Remove LayoutFieldIndex from frame field tracking
- Remove StructType usage - frame is now a byte array
- Replace all CreateStructGEP/CreateConstInBoundsGEP with CreatePtrAdd
- Store ResumeOffset/DestroyOffset in SwitchLowering for reuse
- Remove Shape.FrameTy, use Shape.FrameSize directly
Bug fix: Uses pointer size and alignment from data layout for header
pointer offsets in debug info instead of hardcoded 8 byte.
Optimization: Replaces load+store patterns with CreateMemCpy for copying
allocas to the frame more efficiently.
Optimization: Add missing inbounds annotations on existing ptradd calls.
Improvement: Preserve debug info of every alloca, even overlapping ones.
The frame type is now completely opaque at the IR level. All structure
is implicit through computed offsets. Debug info still provides detailed
field information using explicit offsets.
Co-Authored-By: Claude Opus 4.5 <noreply at anthropic.com>
---
.../coro-suspend-cleanups.cpp | 4 +-
.../llvm/Transforms/Coroutines/CoroShape.h | 23 +-
llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 439 ++++++++----------
llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 101 ++--
llvm/test/Transforms/Coroutines/ArgAddr.ll | 11 +-
.../Transforms/Coroutines/coro-align16.ll | 9 +-
.../Transforms/Coroutines/coro-align32.ll | 9 +-
.../Transforms/Coroutines/coro-align64-02.ll | 9 +-
.../Transforms/Coroutines/coro-align64.ll | 9 +-
.../Transforms/Coroutines/coro-align8-02.ll | 7 +-
.../test/Transforms/Coroutines/coro-align8.ll | 7 +-
.../Coroutines/coro-alloc-with-param-O0.ll | 8 +-
.../Coroutines/coro-alloc-with-param-O2.ll | 8 +-
.../Transforms/Coroutines/coro-alloca-01.ll | 13 +-
.../Transforms/Coroutines/coro-alloca-02.ll | 11 +-
.../Transforms/Coroutines/coro-alloca-03.ll | 9 +-
.../Transforms/Coroutines/coro-alloca-04.ll | 11 +-
.../Transforms/Coroutines/coro-alloca-06.ll | 7 +-
.../Transforms/Coroutines/coro-alloca-07.ll | 12 +-
.../Transforms/Coroutines/coro-alloca-08.ll | 12 +-
.../Transforms/Coroutines/coro-alloca-09.ll | 12 +-
.../coro-alloca-loop-carried-address.ll | 8 +-
.../Coroutines/coro-alloca-with-addrspace.ll | 10 +-
.../Coroutines/coro-async-dyn-align.ll | 15 +-
.../coro-await-suspend-lower-invoke.ll | 23 +-
.../Coroutines/coro-await-suspend-lower.ll | 23 +-
.../Transforms/Coroutines/coro-byval-param.ll | 16 +-
.../Transforms/Coroutines/coro-catchswitch.ll | 6 +-
.../Coroutines/coro-eh-aware-edge-split-01.ll | 16 +-
.../Coroutines/coro-eh-aware-edge-split-02.ll | 16 +-
.../Coroutines/coro-frame-arrayalloca.ll | 16 +-
.../Coroutines/coro-frame-reuse-alloca-01.ll | 11 +-
.../Coroutines/coro-frame-reuse-alloca-02.ll | 11 +-
.../Coroutines/coro-frame-reuse-alloca-04.ll | 13 +-
.../Coroutines/coro-frame-reuse-alloca-05.ll | 11 +-
llvm/test/Transforms/Coroutines/coro-frame.ll | 12 +-
.../Coroutines/coro-lifetime-end.ll | 18 +-
llvm/test/Transforms/Coroutines/coro-noop.ll | 1 -
.../Transforms/Coroutines/coro-padding.ll | 10 +-
.../Transforms/Coroutines/coro-param-copy.ll | 19 +-
.../Coroutines/coro-retcon-once-value.ll | 2 +-
.../Coroutines/coro-retcon-once-value2.ll | 22 +-
.../Coroutines/coro-retcon-remat.ll | 6 +-
.../Coroutines/coro-retcon-resume-values2.ll | 18 +-
.../test/Transforms/Coroutines/coro-retcon.ll | 8 +-
.../Coroutines/coro-spill-after-phi.ll | 9 +-
.../Coroutines/coro-spill-corobegin.ll | 8 +-
.../coro-spill-defs-before-corobegin.ll | 11 +-
.../Coroutines/coro-spill-promise-02.ll | 15 +-
.../Coroutines/coro-spill-promise.ll | 10 +-
.../Coroutines/coro-spill-suspend.ll | 26 +-
.../coro-split-dbg-nested-struct.ll | 2 +
.../Coroutines/coro-split-tbaa-md.ll | 12 +-
.../Transforms/Coroutines/coro-zero-alloca.ll | 8 +-
54 files changed, 546 insertions(+), 597 deletions(-)
diff --git a/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp b/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp
index d71c2c558996a..77abc53ce2e71 100644
--- a/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp
+++ b/clang/test/CodeGenCoroutines/coro-suspend-cleanups.cpp
@@ -47,7 +47,7 @@ coroutine ArrayInitCoro() {
// CHECK-NEXT: store ptr %arr.reload.addr, ptr %arrayinit.endOfInit.reload.addr, align 8
// CHECK-NEXT: call void @_ZN6PrintyC1EPKc(ptr noundef nonnull align 8 dereferenceable(8) %arr.reload.addr, ptr noundef @.str)
// CHECK-NEXT: %arrayinit.element = getelementptr inbounds %struct.Printy, ptr %arr.reload.addr, i64 1
- // CHECK-NEXT: %arrayinit.element.spill.addr = getelementptr inbounds %_Z13ArrayInitCorov.Frame, ptr %0, i32 0, i32 10
+ // CHECK-NEXT: %arrayinit.element.spill.addr = getelementptr inbounds i8, ptr %0, i64 48
// CHECK-NEXT: store ptr %arrayinit.element, ptr %arrayinit.element.spill.addr, align 8
// CHECK-NEXT: store ptr %arrayinit.element, ptr %arrayinit.endOfInit.reload.addr, align 8
co_await Awaiter{}
@@ -61,7 +61,7 @@ coroutine ArrayInitCoro() {
// CHECK: br label %cleanup{{.*}}
// CHECK: await.ready:
- // CHECK-NEXT: %arrayinit.element.reload.addr = getelementptr inbounds %_Z13ArrayInitCorov.Frame, ptr %0, i32 0, i32 10
+ // CHECK-NEXT: %arrayinit.element.reload.addr = getelementptr inbounds i8, ptr %0, i64 48
// CHECK-NEXT: %arrayinit.element.reload = load ptr, ptr %arrayinit.element.reload.addr, align 8
// CHECK-NEXT: call void @_ZN7Awaiter12await_resumeEv
// CHECK-NEXT: store i1 false, ptr %cleanup.isactive.reload.addr, align 1
diff --git a/llvm/include/llvm/Transforms/Coroutines/CoroShape.h b/llvm/include/llvm/Transforms/Coroutines/CoroShape.h
index 11b004572957f..88ae4dc306be2 100644
--- a/llvm/include/llvm/Transforms/Coroutines/CoroShape.h
+++ b/llvm/include/llvm/Transforms/Coroutines/CoroShape.h
@@ -75,7 +75,6 @@ struct Shape {
SwiftErrorOps.clear();
- FrameTy = nullptr;
FramePtr = nullptr;
AllocaSpillBlock = nullptr;
}
@@ -113,7 +112,6 @@ struct Shape {
coro::ABI ABI;
- StructType *FrameTy = nullptr;
Align FrameAlign;
uint64_t FrameSize = 0;
Value *FramePtr = nullptr;
@@ -123,7 +121,9 @@ struct Shape {
SwitchInst *ResumeSwitch;
AllocaInst *PromiseAlloca;
BasicBlock *ResumeEntryBlock;
- unsigned IndexField;
+ IntegerType *IndexType;
+ unsigned ResumeOffset;
+ unsigned DestroyOffset;
unsigned IndexAlign;
unsigned IndexOffset;
bool HasFinalSuspend;
@@ -172,15 +172,10 @@ struct Shape {
return cast<CoroIdAsyncInst>(CoroBegin->getId());
}
- unsigned getSwitchIndexField() const {
- assert(ABI == coro::ABI::Switch);
- assert(FrameTy && "frame type not assigned");
- return SwitchLowering.IndexField;
- }
IntegerType *getIndexType() const {
assert(ABI == coro::ABI::Switch);
- assert(FrameTy && "frame type not assigned");
- return cast<IntegerType>(FrameTy->getElementType(getSwitchIndexField()));
+ assert(SwitchLowering.IndexType && "index type not assigned");
+ return SwitchLowering.IndexType;
}
ConstantInt *getIndex(uint64_t Value) const {
return ConstantInt::get(getIndexType(), Value);
@@ -188,15 +183,15 @@ struct Shape {
PointerType *getSwitchResumePointerType() const {
assert(ABI == coro::ABI::Switch);
- assert(FrameTy && "frame type not assigned");
- return cast<PointerType>(FrameTy->getElementType(SwitchFieldIndex::Resume));
+ assert(CoroBegin && "CoroBegin not assigned");
+ return PointerType::getUnqual(CoroBegin->getContext());
}
FunctionType *getResumeFunctionType() const {
switch (ABI) {
case coro::ABI::Switch:
- return FunctionType::get(Type::getVoidTy(FrameTy->getContext()),
- PointerType::getUnqual(FrameTy->getContext()),
+ return FunctionType::get(Type::getVoidTy(CoroBegin->getContext()),
+ PointerType::getUnqual(CoroBegin->getContext()),
/*IsVarArg=*/false);
case coro::ABI::Retcon:
case coro::ABI::RetconOnce:
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
index 2f2ef7f9eee2c..01bf6ac22790e 100644
--- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp
@@ -77,7 +77,7 @@ struct FrameDataInfo {
}
void setFieldIndex(Value *V, uint32_t Index) {
- assert((LayoutIndexUpdateStarted || FieldIndexMap.count(V) == 0) &&
+ assert(FieldIndexMap.count(V) == 0 &&
"Cannot set the index for the same field twice.");
FieldIndexMap[V] = Index;
}
@@ -115,16 +115,11 @@ struct FrameDataInfo {
FieldOffsetMap.insert({V, Offset});
}
- // Remap the index of every field in the frame, using the final layout index.
- void updateLayoutIndex(FrameTypeBuilder &B);
+ // Update field offset and alignment information from FrameTypeBuilder.
+ void updateLayoutInfo(FrameTypeBuilder &B);
private:
- // LayoutIndexUpdateStarted is used to avoid updating the index of any field
- // twice by mistake.
- bool LayoutIndexUpdateStarted = false;
- // Map from values to their slot indexes on the frame. They will be first set
- // with their original insertion field index. After the frame is built, their
- // indexes will be updated into the final layout index.
+ // Map from values to their slot indexes on the frame (insertion order).
DenseMap<Value *, uint32_t> FieldIndexMap;
// Map from values to their alignment on the frame. They would be set after
// the frame is built.
@@ -166,10 +161,7 @@ class FrameTypeBuilder {
struct Field {
uint64_t Size;
uint64_t Offset;
- Type *Ty;
- FieldIDType LayoutFieldIndex;
Align Alignment;
- Align TyAlignment;
uint64_t DynamicAlignBuffer;
};
@@ -184,6 +176,8 @@ class FrameTypeBuilder {
SmallVector<Field, 8> Fields;
DenseMap<Value*, unsigned> FieldIndexByKey;
+ IntegerType *SwitchIndexType = nullptr;
+
public:
FrameTypeBuilder(LLVMContext &Context, const DataLayout &DL,
std::optional<Align> MaxFrameAlignment)
@@ -193,17 +187,11 @@ class FrameTypeBuilder {
/// instruction.
[[nodiscard]] FieldIDType addFieldForAlloca(AllocaInst *AI,
bool IsHeader = false) {
- Type *Ty = AI->getAllocatedType();
-
- // Make an array type if this is a static array allocation.
- if (AI->isArrayAllocation()) {
- if (auto *CI = dyn_cast<ConstantInt>(AI->getArraySize()))
- Ty = ArrayType::get(Ty, CI->getValue().getZExtValue());
- else
- report_fatal_error("Coroutines cannot handle non static allocas yet");
- }
-
- return addField(Ty, AI->getAlign(), IsHeader);
+ auto Size = AI->getAllocationSize(AI->getDataLayout());
+ if (!Size || !Size->isFixed())
+ report_fatal_error(
+ "Coroutines cannot handle non static or vscale allocas yet");
+ return addField(Size->getFixedValue(), AI->getAlign(), IsHeader);
}
/// We want to put the allocas whose lifetime-ranges are not overlapped
@@ -236,31 +224,33 @@ class FrameTypeBuilder {
void addFieldForAllocas(const Function &F, FrameDataInfo &FrameData,
coro::Shape &Shape, bool OptimizeFrame);
- /// Add a field to this structure.
+ /// Add a field to this structure for a spill.
[[nodiscard]] FieldIDType addField(Type *Ty, MaybeAlign MaybeFieldAlignment,
bool IsHeader = false,
bool IsSpillOfValue = false) {
- assert(!IsFinished && "adding fields to a finished builder");
assert(Ty && "must provide a type for a field");
-
- // The field size is always the alloc size of the type.
+ // The field size is the alloc size of the type.
uint64_t FieldSize = DL.getTypeAllocSize(Ty);
-
- // For an alloca with size=0, we don't need to add a field and they
- // can just point to any index in the frame. Use index 0.
- if (FieldSize == 0) {
- return 0;
- }
-
- // The field alignment might not be the type alignment, but we need
- // to remember the type alignment anyway to build the type.
- // If we are spilling values we don't need to worry about ABI alignment
+ // The field alignment is usually the type alignment.
+ // But if we are spilling values we don't need to worry about ABI alignment
// concerns.
Align ABIAlign = DL.getABITypeAlign(Ty);
Align TyAlignment = ABIAlign;
if (IsSpillOfValue && MaxFrameAlignment && *MaxFrameAlignment < ABIAlign)
TyAlignment = *MaxFrameAlignment;
Align FieldAlignment = MaybeFieldAlignment.value_or(TyAlignment);
+ return addField(FieldSize, FieldAlignment, IsHeader);
+ }
+
+ /// Add a field to this structure.
+ [[nodiscard]] FieldIDType addField(uint64_t FieldSize, Align FieldAlignment,
+ bool IsHeader = false) {
+ assert(!IsFinished && "adding fields to a finished builder");
+
+ // For an alloca with size=0, we don't need to add a field and they
+ // can just point to any index in the frame. Use index 0.
+ if (FieldSize == 0)
+ return 0;
// The field alignment could be bigger than the max frame case, in that case
// we request additional storage to be able to dynamically align the
@@ -284,13 +274,12 @@ class FrameTypeBuilder {
Offset = OptimizedStructLayoutField::FlexibleOffset;
}
- Fields.push_back({FieldSize, Offset, Ty, 0, FieldAlignment, TyAlignment,
- DynamicAlignBuffer});
+ Fields.push_back({FieldSize, Offset, FieldAlignment, DynamicAlignBuffer});
return Fields.size() - 1;
}
- /// Finish the layout and create the struct type with the given name.
- StructType *finish(StringRef Name);
+ /// Finish the layout and compute final size and alignment.
+ void finish(StringRef Name);
uint64_t getStructSize() const {
assert(IsFinished && "not yet finished!");
@@ -302,22 +291,21 @@ class FrameTypeBuilder {
return StructAlign;
}
- FieldIDType getLayoutFieldIndex(FieldIDType Id) const {
- assert(IsFinished && "not yet finished!");
- return Fields[Id].LayoutFieldIndex;
- }
-
Field getLayoutField(FieldIDType Id) const {
assert(IsFinished && "not yet finished!");
return Fields[Id];
}
+
+ void setSwitchIndexType(IntegerType *Ty) { SwitchIndexType = Ty; }
+
+ IntegerType *getSwitchIndexType() const { return SwitchIndexType; }
};
} // namespace
-void FrameDataInfo::updateLayoutIndex(FrameTypeBuilder &B) {
+void FrameDataInfo::updateLayoutInfo(FrameTypeBuilder &B) {
auto Updater = [&](Value *I) {
- auto Field = B.getLayoutField(getFieldIndex(I));
- setFieldIndex(I, Field.LayoutFieldIndex);
+ uint32_t FieldIndex = getFieldIndex(I);
+ auto Field = B.getLayoutField(FieldIndex);
setAlign(I, Field.Alignment);
uint64_t dynamicAlign =
Field.DynamicAlignBuffer
@@ -326,12 +314,10 @@ void FrameDataInfo::updateLayoutIndex(FrameTypeBuilder &B) {
setDynamicAlign(I, dynamicAlign);
setOffset(I, Field.Offset);
};
- LayoutIndexUpdateStarted = true;
for (auto &S : Spills)
Updater(S.first);
for (const auto &A : Allocas)
Updater(A.Alloca);
- LayoutIndexUpdateStarted = false;
}
void FrameTypeBuilder::addFieldForAllocas(const Function &F,
@@ -463,7 +449,7 @@ void FrameTypeBuilder::addFieldForAllocas(const Function &F,
});
}
-StructType *FrameTypeBuilder::finish(StringRef Name) {
+void FrameTypeBuilder::finish(StringRef Name) {
assert(!IsFinished && "already finished!");
// Prepare the optimal-layout field array.
@@ -475,7 +461,7 @@ StructType *FrameTypeBuilder::finish(StringRef Name) {
Field.Offset);
}
- // Perform layout.
+ // Perform layout to compute size, alignment, and field offsets.
auto SizeAndAlign = performOptimizedStructLayout(LayoutFields);
StructSize = SizeAndAlign.first;
StructAlign = SizeAndAlign.second;
@@ -484,61 +470,13 @@ StructType *FrameTypeBuilder::finish(StringRef Name) {
return *static_cast<Field *>(const_cast<void*>(LayoutField.Id));
};
- // We need to produce a packed struct type if there's a field whose
- // assigned offset isn't a multiple of its natural type alignment.
- bool Packed = [&] {
- for (auto &LayoutField : LayoutFields) {
- auto &F = getField(LayoutField);
- if (!isAligned(F.TyAlignment, LayoutField.Offset))
- return true;
- }
- return false;
- }();
-
- // Build the struct body.
- SmallVector<Type*, 16> FieldTypes;
- FieldTypes.reserve(LayoutFields.size() * 3 / 2);
- uint64_t LastOffset = 0;
+ // Update field offsets from the computed layout.
for (auto &LayoutField : LayoutFields) {
auto &F = getField(LayoutField);
-
- auto Offset = LayoutField.Offset;
-
- // Add a padding field if there's a padding gap and we're either
- // building a packed struct or the padding gap is more than we'd
- // get from aligning to the field type's natural alignment.
- assert(Offset >= LastOffset);
- if (Offset != LastOffset) {
- if (Packed || alignTo(LastOffset, F.TyAlignment) != Offset)
- FieldTypes.push_back(ArrayType::get(Type::getInt8Ty(Context),
- Offset - LastOffset));
- }
-
- F.Offset = Offset;
- F.LayoutFieldIndex = FieldTypes.size();
-
- FieldTypes.push_back(F.Ty);
- if (F.DynamicAlignBuffer) {
- FieldTypes.push_back(
- ArrayType::get(Type::getInt8Ty(Context), F.DynamicAlignBuffer));
- }
- LastOffset = Offset + F.Size;
- }
-
- StructType *Ty = StructType::create(Context, FieldTypes, Name, Packed);
-
-#ifndef NDEBUG
- // Check that the IR layout matches the offsets we expect.
- auto Layout = DL.getStructLayout(Ty);
- for (auto &F : Fields) {
- assert(Ty->getElementType(F.LayoutFieldIndex) == F.Ty);
- assert(Layout->getElementOffset(F.LayoutFieldIndex) == F.Offset);
+ F.Offset = LayoutField.Offset;
}
-#endif
IsFinished = true;
-
- return Ty;
}
static void cacheDIVar(FrameDataInfo &FrameData,
@@ -710,112 +648,96 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape,
unsigned LineNum = DIS->getLine();
DICompositeType *FrameDITy = DBuilder.createStructType(
- DIS->getUnit(), Twine(F.getName() + ".coro_frame_ty").str(),
- DFile, LineNum, Shape.FrameSize * 8,
- Shape.FrameAlign.value() * 8, llvm::DINode::FlagArtificial, nullptr,
- llvm::DINodeArray());
- StructType *FrameTy = Shape.FrameTy;
+ DIS->getUnit(), Twine(F.getName() + ".coro_frame_ty").str(), DFile,
+ LineNum, Shape.FrameSize * 8, Shape.FrameAlign.value() * 8,
+ llvm::DINode::FlagArtificial, nullptr, llvm::DINodeArray());
SmallVector<Metadata *, 16> Elements;
DataLayout Layout = F.getDataLayout();
DenseMap<Value *, DILocalVariable *> DIVarCache;
cacheDIVar(FrameData, DIVarCache);
- unsigned ResumeIndex = coro::Shape::SwitchFieldIndex::Resume;
- unsigned DestroyIndex = coro::Shape::SwitchFieldIndex::Destroy;
- unsigned IndexIndex = Shape.SwitchLowering.IndexField;
-
- DenseMap<unsigned, StringRef> NameCache;
- NameCache.insert({ResumeIndex, "__resume_fn"});
- NameCache.insert({DestroyIndex, "__destroy_fn"});
- NameCache.insert({IndexIndex, "__coro_index"});
-
- Type *ResumeFnTy = FrameTy->getElementType(ResumeIndex),
- *DestroyFnTy = FrameTy->getElementType(DestroyIndex),
- *IndexTy = FrameTy->getElementType(IndexIndex);
-
- DenseMap<unsigned, DIType *> TyCache;
- TyCache.insert(
- {ResumeIndex, DBuilder.createPointerType(
- nullptr, Layout.getTypeSizeInBits(ResumeFnTy))});
- TyCache.insert(
- {DestroyIndex, DBuilder.createPointerType(
- nullptr, Layout.getTypeSizeInBits(DestroyFnTy))});
-
- /// FIXME: If we fill the field `SizeInBits` with the actual size of
- /// __coro_index in bits, then __coro_index wouldn't show in the debugger.
- TyCache.insert({IndexIndex, DBuilder.createBasicType(
- "__coro_index",
- (Layout.getTypeSizeInBits(IndexTy) < 8)
- ? 8
- : Layout.getTypeSizeInBits(IndexTy),
- dwarf::DW_ATE_unsigned_char)});
-
- for (auto *V : FrameData.getAllDefs()) {
- auto It = DIVarCache.find(V);
- if (It == DIVarCache.end())
- continue;
-
- auto Index = FrameData.getFieldIndex(V);
-
- NameCache.insert({Index, It->second->getName()});
- TyCache.insert({Index, It->second->getType()});
- }
-
- // Cache from index to (Align, Offset Pair)
- DenseMap<unsigned, std::pair<unsigned, unsigned>> OffsetCache;
- // The Align and Offset of Resume function and Destroy function are fixed.
- OffsetCache.insert({ResumeIndex, {8, 0}});
- OffsetCache.insert({DestroyIndex, {8, 8}});
- OffsetCache.insert(
- {IndexIndex,
- {Shape.SwitchLowering.IndexAlign, Shape.SwitchLowering.IndexOffset}});
-
- for (auto *V : FrameData.getAllDefs()) {
- auto Index = FrameData.getFieldIndex(V);
-
- OffsetCache.insert(
- {Index, {FrameData.getAlign(V).value(), FrameData.getOffset(V)}});
- }
-
- DenseMap<Type *, DIType *> DITypeCache;
// This counter is used to avoid same type names. e.g., there would be
// many i32 and i64 types in one coroutine. And we would use i32_0 and
// i32_1 to avoid the same type. Since it makes no sense the name of the
// fields confilicts with each other.
unsigned UnknownTypeNum = 0;
- for (unsigned Index = 0; Index < FrameTy->getNumElements(); Index++) {
- auto OCIt = OffsetCache.find(Index);
- if (OCIt == OffsetCache.end())
- continue;
+ DenseMap<Type *, DIType *> DITypeCache;
+
+ auto addElement = [&](StringRef Name, uint64_t SizeInBits, uint64_t Alignment,
+ uint64_t Offset, DIType *DITy) {
+ Elements.push_back(DBuilder.createMemberType(
+ FrameDITy, Name, DFile, LineNum, SizeInBits, Alignment, Offset * 8,
+ llvm::DINode::FlagArtificial, DITy));
+ };
+
+ auto addDIDef = [&](Value *V) {
+ // Get the offset and alignment for this value.
+ uint64_t Offset = FrameData.getOffset(V);
+ Align Alignment = FrameData.getAlign(V);
std::string Name;
uint64_t SizeInBits;
- uint32_t AlignInBits;
- uint64_t OffsetInBits;
DIType *DITy = nullptr;
- Type *Ty = FrameTy->getElementType(Index);
- assert(Ty->isSized() && "We can't handle type which is not sized.\n");
- SizeInBits = Layout.getTypeSizeInBits(Ty).getFixedValue();
- AlignInBits = OCIt->second.first * 8;
- OffsetInBits = OCIt->second.second * 8;
-
- if (auto It = NameCache.find(Index); It != NameCache.end()) {
- Name = It->second.str();
- DITy = TyCache[Index];
+ auto It = DIVarCache.find(V);
+ if (It != DIVarCache.end()) {
+ // Get the type from the debug variable.
+ Name = It->second->getName().str();
+ DITy = It->second->getType();
} else {
- DITy = solveDIType(DBuilder, Ty, Layout, FrameDITy, LineNum, DITypeCache);
+ if (auto AI = dyn_cast<AllocaInst>(V)) {
+ // Frame alloca
+ DITy = solveDIType(DBuilder, AI->getAllocatedType(), Layout, FrameDITy,
+ LineNum, DITypeCache);
+ } else {
+ // Spill
+ DITy = solveDIType(DBuilder, V->getType(), Layout, FrameDITy, LineNum,
+ DITypeCache);
+ }
assert(DITy && "SolveDIType shouldn't return nullptr.\n");
Name = DITy->getName().str();
Name += "_" + std::to_string(UnknownTypeNum);
UnknownTypeNum++;
}
- Elements.push_back(DBuilder.createMemberType(
- FrameDITy, Name, DFile, LineNum, SizeInBits, AlignInBits, OffsetInBits,
- llvm::DINode::FlagArtificial, DITy));
- }
+ if (auto AI = dyn_cast<AllocaInst>(V)) {
+ // Lookup the total size of this alloca originally
+ auto Size = AI->getAllocationSize(Layout);
+ assert(Size && Size->isFixed() &&
+ "unreachable due to addFieldForAlloca checks");
+ SizeInBits = Size->getFixedValue() * 8;
+ } else {
+ // Compute the size of the active data of this member for this spill
+ SizeInBits = Layout.getTypeSizeInBits(V->getType());
+ }
+
+ addElement(Name, SizeInBits, Alignment.value() * 8, Offset, DITy);
+ };
+
+ // For Switch ABI, add debug info for the added fields (resume, destroy).
+ if (Shape.ABI == coro::ABI::Switch) {
+ auto *FnPtrTy = Shape.getSwitchResumePointerType();
+ uint64_t PtrSize = Layout.getPointerSizeInBits(FnPtrTy->getAddressSpace());
+ uint64_t PtrAlign =
+ Layout.getPointerABIAlignment(FnPtrTy->getAddressSpace()).value() * 8;
+ auto *DIPtr = DBuilder.createPointerType(nullptr, PtrSize,
+ FnPtrTy->getAddressSpace());
+ addElement("__resume_fn", PtrSize, PtrAlign,
+ Shape.SwitchLowering.ResumeOffset, DIPtr);
+ addElement("__destroy_fn", PtrSize, PtrAlign,
+ Shape.SwitchLowering.DestroyOffset, DIPtr);
+ uint64_t IndexSize =
+ Layout.getTypeSizeInBits(Shape.getIndexType()).getFixedValue();
+ addElement("__coro_index", IndexSize, Shape.SwitchLowering.IndexAlign * 8,
+ Shape.SwitchLowering.IndexOffset,
+ DBuilder.createBasicType("__coro_index",
+ (IndexSize < 8) ? 8 : IndexSize,
+ dwarf::DW_ATE_unsigned_char));
+ }
+ auto Defs = FrameData.getAllDefs();
+ for (auto *V : Defs)
+ addDIDef(V);
DBuilder.replaceArrays(FrameDITy, DBuilder.getOrCreateArray(Elements));
@@ -850,17 +772,15 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape,
It->getParent()->insertDbgRecordBefore(NewDVR, It);
}
-// Build a struct that will keep state for an active coroutine.
-// struct f.frame {
-// ResumeFnTy ResumeFnAddr;
-// ResumeFnTy DestroyFnAddr;
-// ... promise (if present) ...
-// int ResumeIndex;
-// ... spills ...
-// };
-static StructType *buildFrameType(Function &F, coro::Shape &Shape,
- FrameDataInfo &FrameData,
- bool OptimizeFrame) {
+// Build the coroutine frame type as a byte array.
+// The frame layout includes:
+// - Resume function pointer at offset 0 (Switch ABI only)
+// - Destroy function pointer at offset ptrsize (Switch ABI only)
+// - Promise alloca (Switch ABI only, only if present)
+// - Suspend/Resume index
+// - Spilled values and allocas
+static void buildFrameLayout(Function &F, coro::Shape &Shape,
+ FrameDataInfo &FrameData, bool OptimizeFrame) {
LLVMContext &C = F.getContext();
const DataLayout &DL = F.getDataLayout();
@@ -874,12 +794,12 @@ static StructType *buildFrameType(Function &F, coro::Shape &Shape,
std::optional<FieldIDType> SwitchIndexFieldId;
if (Shape.ABI == coro::ABI::Switch) {
- auto *FnPtrTy = PointerType::getUnqual(C);
+ auto *FnPtrTy = Shape.getSwitchResumePointerType();
// Add header fields for the resume and destroy functions.
// We can rely on these being perfectly packed.
- (void)B.addField(FnPtrTy, std::nullopt, /*header*/ true);
- (void)B.addField(FnPtrTy, std::nullopt, /*header*/ true);
+ (void)B.addField(FnPtrTy, MaybeAlign(), /*header*/ true);
+ (void)B.addField(FnPtrTy, MaybeAlign(), /*header*/ true);
// PromiseAlloca field needs to be explicitly added here because it's
// a header field with a fixed offset based on its alignment. Hence it
@@ -891,9 +811,10 @@ static StructType *buildFrameType(Function &F, coro::Shape &Shape,
// Add a field to store the suspend index. This doesn't need to
// be in the header.
unsigned IndexBits = std::max(1U, Log2_64_Ceil(Shape.CoroSuspends.size()));
- Type *IndexType = Type::getIntNTy(C, IndexBits);
+ IntegerType *IndexType = Type::getIntNTy(C, IndexBits);
- SwitchIndexFieldId = B.addField(IndexType, std::nullopt);
+ SwitchIndexFieldId = B.addField(IndexType, MaybeAlign());
+ B.setSwitchIndexType(IndexType);
} else {
assert(PromiseAlloca == nullptr && "lowering doesn't support promises");
}
@@ -927,21 +848,26 @@ static StructType *buildFrameType(Function &F, coro::Shape &Shape,
FrameData.setFieldIndex(S.first, Id);
}
- StructType *FrameTy = [&] {
+ {
SmallString<32> Name(F.getName());
Name.append(".Frame");
- return B.finish(Name);
- }();
+ B.finish(Name);
+ }
- FrameData.updateLayoutIndex(B);
+ FrameData.updateLayoutInfo(B);
Shape.FrameAlign = B.getStructAlign();
Shape.FrameSize = B.getStructSize();
switch (Shape.ABI) {
case coro::ABI::Switch: {
- // In the switch ABI, remember the switch-index field.
+ // In the switch ABI, remember the function pointer and index field info.
+ // Resume and Destroy function pointers are in the frame header.
+ const DataLayout &DL = F.getDataLayout();
+ Shape.SwitchLowering.ResumeOffset = 0;
+ Shape.SwitchLowering.DestroyOffset = DL.getPointerSize();
+
auto IndexField = B.getLayoutField(*SwitchIndexFieldId);
- Shape.SwitchLowering.IndexField = IndexField.LayoutFieldIndex;
+ Shape.SwitchLowering.IndexType = B.getSwitchIndexType();
Shape.SwitchLowering.IndexAlign = IndexField.Alignment.value();
Shape.SwitchLowering.IndexOffset = IndexField.Offset;
@@ -976,8 +902,6 @@ static StructType *buildFrameType(Function &F, coro::Shape &Shape,
break;
}
}
-
- return FrameTy;
}
/// If MaybeArgument is a byval Argument, return its byval type. Also removes
@@ -997,64 +921,58 @@ static Type *extractByvalIfArgument(Value *MaybeArgument) {
static void createStoreIntoFrame(IRBuilder<> &Builder, Value *Def,
Type *ByValTy, const coro::Shape &Shape,
const FrameDataInfo &FrameData) {
- auto Index = FrameData.getFieldIndex(Def);
- auto *G = Builder.CreateConstInBoundsGEP2_32(
- Shape.FrameTy, Shape.FramePtr, 0, Index,
- Def->getName() + Twine(".spill.addr"));
+ LLVMContext &Ctx = Shape.CoroBegin->getContext();
+ uint64_t Offset = FrameData.getOffset(Def);
+
+ Value *G = Shape.FramePtr;
+ if (Offset != 0) {
+ auto *OffsetVal = ConstantInt::get(Type::getInt64Ty(Ctx), Offset);
+ G = Builder.CreateInBoundsPtrAdd(G, OffsetVal,
+ Def->getName() + Twine(".spill.addr"));
+ }
auto SpillAlignment = Align(FrameData.getAlign(Def));
- // For byval arguments, store the pointed-to value in the frame.
- if (ByValTy)
- Builder.CreateAlignedStore(Builder.CreateLoad(ByValTy, Def), G,
- SpillAlignment);
- else
+ // For byval arguments, copy the pointed-to value to the frame.
+ if (ByValTy) {
+ auto &DL = Builder.GetInsertBlock()->getDataLayout();
+ auto Size = DL.getTypeStoreSize(ByValTy);
+ // Def is a pointer to the byval argument
+ Builder.CreateMemCpy(G, SpillAlignment, Def, SpillAlignment, Size);
+ } else {
Builder.CreateAlignedStore(Def, G, SpillAlignment);
+ }
}
-/// Returns a GEP into the coroutine frame at the offset where Orig is located.
+/// Returns a pointer into the coroutine frame at the offset where Orig is
+/// located.
static Value *createGEPToFramePointer(const FrameDataInfo &FrameData,
IRBuilder<> &Builder, coro::Shape &Shape,
Value *Orig) {
LLVMContext &Ctx = Shape.CoroBegin->getContext();
- FieldIDType Index = FrameData.getFieldIndex(Orig);
- SmallVector<Value *, 3> Indices = {
- ConstantInt::get(Type::getInt32Ty(Ctx), 0),
- ConstantInt::get(Type::getInt32Ty(Ctx), Index),
- };
+ uint64_t Offset = FrameData.getOffset(Orig);
+ auto *OffsetVal = ConstantInt::get(Type::getInt64Ty(Ctx), Offset);
+ Value *Ptr = Builder.CreateInBoundsPtrAdd(Shape.FramePtr, OffsetVal);
- // If Orig is an array alloca, preserve the original type by adding an extra
- // zero offset.
- if (auto *AI = dyn_cast<AllocaInst>(Orig)) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(AI->getArraySize())) {
- auto Count = CI->getValue().getZExtValue();
- if (Count > 1)
- Indices.push_back(ConstantInt::get(Type::getInt32Ty(Ctx), 0));
- } else {
- report_fatal_error("Coroutines cannot handle non static allocas yet");
- }
- }
-
- auto *GEP = Builder.CreateInBoundsGEP(Shape.FrameTy, Shape.FramePtr, Indices);
if (auto *AI = dyn_cast<AllocaInst>(Orig)) {
if (FrameData.getDynamicAlign(Orig) != 0) {
assert(FrameData.getDynamicAlign(Orig) == AI->getAlign().value());
auto *M = AI->getModule();
auto *IntPtrTy = M->getDataLayout().getIntPtrType(AI->getType());
- auto *PtrValue = Builder.CreatePtrToInt(GEP, IntPtrTy);
+ auto *PtrValue = Builder.CreatePtrToInt(Ptr, IntPtrTy);
auto *AlignMask = ConstantInt::get(IntPtrTy, AI->getAlign().value() - 1);
PtrValue = Builder.CreateAdd(PtrValue, AlignMask);
PtrValue = Builder.CreateAnd(PtrValue, Builder.CreateNot(AlignMask));
return Builder.CreateIntToPtr(PtrValue, AI->getType());
}
- // If the type of GEP is not equal to the type of AllocaInst, it implies
+ // If the type of Ptr is not equal to the type of AllocaInst, it implies
// that the AllocaInst may be reused in the Frame slot of other AllocaInst.
// Note: If the strategy dealing with alignment changes, this cast must be
// refined
- if (GEP->getType() != Orig->getType())
- GEP = Builder.CreateAddrSpaceCast(GEP, Orig->getType(),
+ if (Ptr->getType() != Orig->getType())
+ Ptr = Builder.CreateAddrSpaceCast(Ptr, Orig->getType(),
Orig->getName() + Twine(".cast"));
}
- return GEP;
+ return Ptr;
}
/// Find dbg.declare or dbg.declare_value records referencing `Def`. If none are
@@ -1113,7 +1031,6 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
LLVMContext &C = Shape.CoroBegin->getContext();
Function *F = Shape.CoroBegin->getFunction();
IRBuilder<> Builder(C);
- StructType *FrameTy = Shape.FrameTy;
DominatorTree DT(*F);
SmallDenseMap<Argument *, AllocaInst *, 4> ArgToAllocaMap;
@@ -1155,9 +1072,9 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
CurrentReload = GEP;
} else {
auto SpillAlignment = Align(FrameData.getAlign(Def));
- auto *LI = Builder.CreateAlignedLoad(
- FrameTy->getElementType(FrameData.getFieldIndex(E.first)), GEP,
- SpillAlignment, E.first->getName() + Twine(".reload"));
+ auto *LI =
+ Builder.CreateAlignedLoad(E.first->getType(), GEP, SpillAlignment,
+ E.first->getName() + Twine(".reload"));
if (TBAATag)
LI->setMetadata(LLVMContext::MD_tbaa, TBAATag);
CurrentReload = LI;
@@ -1303,13 +1220,14 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
AllocaInst *Alloca = A.Alloca;
if (A.MayWriteBeforeCoroBegin) {
// isEscaped really means potentially modified before CoroBegin.
- if (Alloca->isArrayAllocation())
- report_fatal_error(
- "Coroutines cannot handle copying of array allocas yet");
-
+ // TODO: use Builder.CreateAllocationSize here once that PR is merged
+ auto Size = Alloca->getAllocationSize(Alloca->getDataLayout());
+ assert(Size &&
+ "Coroutines cannot handle copying of dynamic allocas yet.\n");
+ assert(!Size->isScalable() && "Scalable vectors are not yet supported");
auto *G = createGEPToFramePointer(FrameData, Builder, Shape, Alloca);
- auto *Value = Builder.CreateLoad(Alloca->getAllocatedType(), Alloca);
- Builder.CreateStore(Value, G);
+ Builder.CreateMemCpy(G, FrameData.getAlign(Alloca), Alloca,
+ Alloca->getAlign(), Size->getFixedValue());
}
// For each alias to Alloca created before CoroBegin but used after
// CoroBegin, we recreate them after CoroBegin by applying the offset
@@ -1320,7 +1238,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
auto &Value = *Alias.second;
auto ITy = IntegerType::get(C, Value.getBitWidth());
auto *AliasPtr =
- Builder.CreatePtrAdd(FramePtr, ConstantInt::get(ITy, Value));
+ Builder.CreateInBoundsPtrAdd(FramePtr, ConstantInt::get(ITy, Value));
Alias.first->replaceUsesWithIf(
AliasPtr, [&](Use &U) { return DT.dominates(Shape.CoroBegin, U); });
}
@@ -1361,9 +1279,14 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) {
});
if (HasAccessingPromiseBeforeCB) {
Builder.SetInsertPoint(&*Shape.getInsertPtAfterFramePtr());
+ // TODO: use Builder.CreateAllocationSize here once that PR is merged
+ auto Size = PA->getAllocationSize(PA->getDataLayout());
+ assert(Size &&
+ "Coroutines cannot handle copying of dynamic allocas yet.\n");
+ assert(!Size->isScalable() && "Scalable vectors are not yet supported");
auto *G = createGEPToFramePointer(FrameData, Builder, Shape, PA);
- auto *Value = Builder.CreateLoad(PA->getAllocatedType(), PA);
- Builder.CreateStore(Value, G);
+ Builder.CreateMemCpy(G, FrameData.getAlign(PA), PA, PA->getAlign(),
+ Size->getFixedValue());
}
}
}
@@ -2127,9 +2050,9 @@ void coro::BaseABI::buildCoroutineFrame(bool OptimizeFrame) {
Shape.ABI == coro::ABI::Async)
sinkSpillUsesAfterCoroBegin(DT, Shape.CoroBegin, Spills, Allocas);
- // Build frame
+ // Build frame layout
FrameDataInfo FrameData(Spills, Allocas);
- Shape.FrameTy = buildFrameType(F, Shape, FrameData, OptimizeFrame);
+ buildFrameLayout(F, Shape, FrameData, OptimizeFrame);
Shape.FramePtr = Shape.CoroBegin;
// For now, this works for C++ programs only.
buildFrameDebugInfo(F, Shape, FrameData);
diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
index f83b6a601572d..2d6b893af3051 100644
--- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp
@@ -315,11 +315,14 @@ static void markCoroutineAsDone(IRBuilder<> &Builder, const coro::Shape &Shape,
assert(
Shape.ABI == coro::ABI::Switch &&
"markCoroutineAsDone is only supported for Switch-Resumed ABI for now.");
- auto *GepIndex = Builder.CreateStructGEP(
- Shape.FrameTy, FramePtr, coro::Shape::SwitchFieldIndex::Resume,
- "ResumeFn.addr");
- auto *NullPtr = ConstantPointerNull::get(cast<PointerType>(
- Shape.FrameTy->getTypeAtIndex(coro::Shape::SwitchFieldIndex::Resume)));
+ // Resume function pointer
+ Value *GepIndex = FramePtr;
+ if (Shape.SwitchLowering.ResumeOffset != 0) {
+ GepIndex = Builder.CreateInBoundsPtrAdd(
+ FramePtr, ConstantInt::get(Type::getInt64Ty(FramePtr->getContext()),
+ Shape.SwitchLowering.ResumeOffset));
+ }
+ auto *NullPtr = ConstantPointerNull::get(Shape.getSwitchResumePointerType());
Builder.CreateStore(NullPtr, GepIndex);
// If the coroutine don't have unwind coro end, we could omit the store to
@@ -336,9 +339,10 @@ static void markCoroutineAsDone(IRBuilder<> &Builder, const coro::Shape &Shape,
"The final suspend should only live in the last position of "
"CoroSuspends.");
ConstantInt *IndexVal = Shape.getIndex(Shape.CoroSuspends.size() - 1);
- auto *FinalIndex = Builder.CreateStructGEP(
- Shape.FrameTy, FramePtr, Shape.getSwitchIndexField(), "index.addr");
-
+ auto *Offset = ConstantInt::get(Type::getInt64Ty(FramePtr->getContext()),
+ Shape.SwitchLowering.IndexOffset);
+ Value *FinalIndex =
+ Builder.CreateInBoundsPtrAdd(FramePtr, Offset, "index.addr");
Builder.CreateStore(IndexVal, FinalIndex);
}
}
@@ -420,9 +424,14 @@ void coro::BaseCloner::handleFinalSuspend() {
// to generate code for other cases.
Builder.CreateBr(ResumeBB);
} else {
- auto *GepIndex = Builder.CreateStructGEP(
- Shape.FrameTy, NewFramePtr, coro::Shape::SwitchFieldIndex::Resume,
- "ResumeFn.addr");
+ // Resume function pointer
+ Value *GepIndex = NewFramePtr;
+ if (Shape.SwitchLowering.ResumeOffset != 0) {
+ GepIndex = Builder.CreateInBoundsPtrAdd(
+ NewFramePtr,
+ ConstantInt::get(Type::getInt64Ty(NewFramePtr->getContext()),
+ Shape.SwitchLowering.ResumeOffset));
+ }
auto *Load =
Builder.CreateLoad(Shape.getSwitchResumePointerType(), GepIndex);
auto *Cond = Builder.CreateIsNull(Load);
@@ -766,9 +775,11 @@ Value *coro::BaseCloner::deriveNewFramePointer() {
CallerContext->setDebugLoc(DbgLoc);
// The frame is located after the async_context header.
auto &Context = Builder.getContext();
- auto *FramePtrAddr = Builder.CreateConstInBoundsGEP1_32(
- Type::getInt8Ty(Context), CallerContext,
- Shape.AsyncLowering.FrameOffset, "async.ctx.frameptr");
+ auto *FramePtrAddr = Builder.CreateInBoundsPtrAdd(
+ CallerContext,
+ ConstantInt::get(Type::getInt64Ty(Context),
+ Shape.AsyncLowering.FrameOffset),
+ "async.ctx.frameptr");
// Inline the projection function.
InlineFunctionInfo InlineInfo;
auto InlineRes = InlineFunction(*CallerContext, InlineInfo);
@@ -780,7 +791,7 @@ Value *coro::BaseCloner::deriveNewFramePointer() {
case coro::ABI::Retcon:
case coro::ABI::RetconOnce: {
Argument *NewStorage = &*NewF->arg_begin();
- auto FramePtrTy = PointerType::getUnqual(Shape.FrameTy->getContext());
+ auto FramePtrTy = PointerType::getUnqual(Shape.FramePtr->getContext());
// If the storage is inline, just bitcast to the storage to the frame type.
if (Shape.RetconLowering.IsFrameInlineInStorage)
@@ -1119,11 +1130,7 @@ static void updateAsyncFuncPointerContextSize(coro::Shape &Shape) {
}
static TypeSize getFrameSizeForShape(coro::Shape &Shape) {
- // In the same function all coro.sizes should have the same result type.
- auto *SizeIntrin = Shape.CoroSizes.back();
- Module *M = SizeIntrin->getModule();
- const DataLayout &DL = M->getDataLayout();
- return DL.getTypeAllocSize(Shape.FrameTy);
+ return TypeSize::getFixed(Shape.FrameSize);
}
static void replaceFrameSizeAndAlignment(coro::Shape &Shape) {
@@ -1173,7 +1180,10 @@ static void handleNoSuspendCoroutine(coro::Shape &Shape) {
coro::replaceCoroFree(SwitchId, /*Elide=*/AllocInst != nullptr);
if (AllocInst) {
IRBuilder<> Builder(AllocInst);
- auto *Frame = Builder.CreateAlloca(Shape.FrameTy);
+ // Create an alloca for a byte array of the frame size
+ auto *FrameTy = ArrayType::get(Type::getInt8Ty(Builder.getContext()),
+ Shape.FrameSize);
+ auto *Frame = Builder.CreateAlloca(FrameTy);
Frame->setAlignment(Shape.FrameAlign);
AllocInst->replaceAllUsesWith(Builder.getFalse());
AllocInst->eraseFromParent();
@@ -1420,7 +1430,7 @@ struct SwitchCoroutineSplitter {
SmallVector<Type *> NewParams;
NewParams.reserve(OldParams.size() + 1);
NewParams.append(OldParams.begin(), OldParams.end());
- NewParams.push_back(PointerType::getUnqual(Shape.FrameTy->getContext()));
+ NewParams.push_back(PointerType::getUnqual(Shape.FramePtr->getContext()));
auto *NewFnTy = FunctionType::get(OrigFnTy->getReturnType(), NewParams,
OrigFnTy->isVarArg());
@@ -1502,9 +1512,10 @@ struct SwitchCoroutineSplitter {
IRBuilder<> Builder(NewEntry);
auto *FramePtr = Shape.FramePtr;
- auto *FrameTy = Shape.FrameTy;
- auto *GepIndex = Builder.CreateStructGEP(
- FrameTy, FramePtr, Shape.getSwitchIndexField(), "index.addr");
+ auto *Offset =
+ ConstantInt::get(Type::getInt64Ty(C), Shape.SwitchLowering.IndexOffset);
+ Value *GepIndex =
+ Builder.CreateInBoundsPtrAdd(FramePtr, Offset, "index.addr");
auto *Index = Builder.CreateLoad(Shape.getIndexType(), GepIndex, "index");
auto *Switch =
Builder.CreateSwitch(Index, UnreachBB, Shape.CoroSuspends.size());
@@ -1526,8 +1537,10 @@ struct SwitchCoroutineSplitter {
// point.
markCoroutineAsDone(Builder, Shape, FramePtr);
} else {
- auto *GepIndex = Builder.CreateStructGEP(
- FrameTy, FramePtr, Shape.getSwitchIndexField(), "index.addr");
+ auto *Offset = ConstantInt::get(Type::getInt64Ty(C),
+ Shape.SwitchLowering.IndexOffset);
+ Value *GepIndex =
+ Builder.CreateInBoundsPtrAdd(FramePtr, Offset, "index.addr");
Builder.CreateStore(IndexVal, GepIndex);
}
@@ -1609,10 +1622,17 @@ struct SwitchCoroutineSplitter {
static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn,
Function *DestroyFn, Function *CleanupFn) {
IRBuilder<> Builder(&*Shape.getInsertPtAfterFramePtr());
-
- auto *ResumeAddr = Builder.CreateStructGEP(
- Shape.FrameTy, Shape.FramePtr, coro::Shape::SwitchFieldIndex::Resume,
- "resume.addr");
+ LLVMContext &C = ResumeFn->getContext();
+
+ // Resume function pointer
+ Value *ResumeAddr = Shape.FramePtr;
+ if (Shape.SwitchLowering.ResumeOffset != 0) {
+ ResumeAddr = Builder.CreateInBoundsPtrAdd(
+ Shape.FramePtr,
+ ConstantInt::get(Type::getInt64Ty(C),
+ Shape.SwitchLowering.ResumeOffset),
+ "resume.addr");
+ }
Builder.CreateStore(ResumeFn, ResumeAddr);
Value *DestroyOrCleanupFn = DestroyFn;
@@ -1624,8 +1644,11 @@ struct SwitchCoroutineSplitter {
DestroyOrCleanupFn = Builder.CreateSelect(CA, DestroyFn, CleanupFn);
}
- auto *DestroyAddr = Builder.CreateStructGEP(
- Shape.FrameTy, Shape.FramePtr, coro::Shape::SwitchFieldIndex::Destroy,
+ // Destroy function pointer
+ Value *DestroyAddr = Builder.CreateInBoundsPtrAdd(
+ Shape.FramePtr,
+ ConstantInt::get(Type::getInt64Ty(C),
+ Shape.SwitchLowering.DestroyOffset),
"destroy.addr");
Builder.CreateStore(DestroyOrCleanupFn, DestroyAddr);
}
@@ -1736,8 +1759,10 @@ void coro::AsyncABI::splitCoroutine(Function &F, coro::Shape &Shape,
auto *FramePtr = Id->getStorage();
FramePtr = Builder.CreateBitOrPointerCast(FramePtr, Int8PtrTy);
- FramePtr = Builder.CreateConstInBoundsGEP1_32(
- Type::getInt8Ty(Context), FramePtr, Shape.AsyncLowering.FrameOffset,
+ FramePtr = Builder.CreateInBoundsPtrAdd(
+ FramePtr,
+ ConstantInt::get(Type::getInt64Ty(Context),
+ Shape.AsyncLowering.FrameOffset),
"async.ctx.frameptr");
// Map all uses of llvm.coro.begin to the allocated frame pointer.
@@ -1834,14 +1859,12 @@ void coro::AnyRetconABI::splitCoroutine(Function &F, coro::Shape &Shape,
} else {
IRBuilder<> Builder(Id);
- // Determine the size of the frame.
- const DataLayout &DL = F.getDataLayout();
- auto Size = DL.getTypeAllocSize(Shape.FrameTy);
+ auto FrameSize = Builder.getInt64(Shape.FrameSize);
// Allocate. We don't need to update the call graph node because we're
// going to recompute it from scratch after splitting.
// FIXME: pass the required alignment
- RawFramePtr = Shape.emitAlloc(Builder, Builder.getInt64(Size), nullptr);
+ RawFramePtr = Shape.emitAlloc(Builder, FrameSize, nullptr);
RawFramePtr =
Builder.CreateBitCast(RawFramePtr, Shape.CoroBegin->getType());
diff --git a/llvm/test/Transforms/Coroutines/ArgAddr.ll b/llvm/test/Transforms/Coroutines/ArgAddr.ll
index b8a478c86a767..c6fca4996d86c 100644
--- a/llvm/test/Transforms/Coroutines/ArgAddr.ll
+++ b/llvm/test/Transforms/Coroutines/ArgAddr.ll
@@ -3,6 +3,8 @@
; coro.begin.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
define nonnull ptr @f(i32 %n) presplitcoroutine {
; CHECK-LABEL: define nonnull ptr @f(
; CHECK-SAME: i32 [[N:%.*]]) {
@@ -13,17 +15,16 @@ define nonnull ptr @f(i32 %n) presplitcoroutine {
; CHECK-NEXT: [[CALL:%.*]] = tail call ptr @malloc(i32 24)
; CHECK-NEXT: [[TMP0:%.*]] = tail call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[CALL]])
; CHECK-NEXT: store ptr @f.resume, ptr [[TMP0]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[TMP0]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[TMP0]], i32 0, i32 2
-; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[N_ADDR]], align 4
-; CHECK-NEXT: store i32 [[TMP2]], ptr [[TMP1]], align 4
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 16
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[TMP1]], ptr align 4 [[N_ADDR]], i64 4, i1 false)
; CHECK-NEXT: call void @ctor(ptr [[TMP1]])
; CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[TMP1]], align 4
; CHECK-NEXT: [[DEC:%.*]] = add nsw i32 [[TMP3]], -1
; CHECK-NEXT: store i32 [[DEC]], ptr [[TMP1]], align 4
; CHECK-NEXT: call void @print(i32 [[TMP3]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[TMP0]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 20
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[TMP0]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-align16.ll b/llvm/test/Transforms/Coroutines/coro-align16.ll
index 6ff6576a4bc8e..e74f23e8e531c 100644
--- a/llvm/test/Transforms/Coroutines/coro-align16.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align16.ll
@@ -2,18 +2,19 @@
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i64, i64, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f() presplitcoroutine {
; CHECK-LABEL: define ptr @f() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 16, i32 40)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 16, i32 48)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-align32.ll b/llvm/test/Transforms/Coroutines/coro-align32.ll
index f95bf690e4f75..6f61a32fde95a 100644
--- a/llvm/test/Transforms/Coroutines/coro-align32.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align32.ll
@@ -2,18 +2,19 @@
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i64, i1, i1, [6 x i8], i32, [12 x i8], i32 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f() presplitcoroutine {
; CHECK-LABEL: define ptr @f() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 32, i32 56)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 32, i32 64)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 25
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-align64-02.ll b/llvm/test/Transforms/Coroutines/coro-align64-02.ll
index 1be0c0bb7e292..471e4fc751378 100644
--- a/llvm/test/Transforms/Coroutines/coro-align64-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align64-02.ll
@@ -2,18 +2,19 @@
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i1, [15 x i8], i64, [24 x i8], i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f() presplitcoroutine {
; CHECK-LABEL: define ptr @f() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 64, i32 72)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 64, i32 128)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-align64.ll b/llvm/test/Transforms/Coroutines/coro-align64.ll
index a264d614a4a99..801a7a1d89a9a 100644
--- a/llvm/test/Transforms/Coroutines/coro-align64.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align64.ll
@@ -2,18 +2,19 @@
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i64, i1, [39 x i8], i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f() presplitcoroutine {
; CHECK-LABEL: define ptr @f() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 64, i32 72)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 64, i32 128)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-align8-02.ll b/llvm/test/Transforms/Coroutines/coro-align8-02.ll
index b4c199d5c5173..5a09b211ccfe4 100644
--- a/llvm/test/Transforms/Coroutines/coro-align8-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align8-02.ll
@@ -2,7 +2,8 @@
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f() presplitcoroutine {
; CHECK-LABEL: define ptr @f() {
@@ -11,9 +12,9 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 8, i32 24)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-align8.ll b/llvm/test/Transforms/Coroutines/coro-align8.ll
index 6c2e7afe58ac6..d98fd10a44655 100644
--- a/llvm/test/Transforms/Coroutines/coro-align8.ll
+++ b/llvm/test/Transforms/Coroutines/coro-align8.ll
@@ -2,7 +2,8 @@
; Tests that the coro.align intrinsic could be lowered to correct alignment
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i64, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f() presplitcoroutine {
; CHECK-LABEL: define ptr @f() {
@@ -11,9 +12,9 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @aligned_alloc(i32 8, i32 32)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
index ae6f8c78cad6d..2db096f13136d 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O0.ll
@@ -54,11 +54,11 @@ declare void @free(ptr)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @myAlloc(i64 [[THIS_ARG]], i32 32)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f_copy.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_COPY_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f_copy.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[THIS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_COPY_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[THIS_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i64 [[THIS_ARG]], ptr [[THIS_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_COPY_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -66,7 +66,7 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f_copy.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[THIS_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_COPY_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[THIS_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[THIS_RELOAD:%.*]] = load i64, ptr [[THIS_RELOAD_ADDR]], align 4
; CHECK-NEXT: call void @print2(i64 [[THIS_RELOAD]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
diff --git a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
index 6ba13750ce943..e079d8114cc23 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloc-with-param-O2.ll
@@ -49,11 +49,11 @@ declare void @free(ptr)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @myAlloc(i64 [[THIS]], i32 32)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f_direct.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_DIRECT_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f_direct.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[THIS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_DIRECT_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[THIS_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_DIRECT_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -61,7 +61,7 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f_direct.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[THIS_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_DIRECT_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[THIS_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[THIS_RELOAD:%.*]] = load i64, ptr [[THIS_RELOAD_ADDR]], align 4
; CHECK-NEXT: call void @print2(i64 [[THIS_RELOAD]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-01.ll b/llvm/test/Transforms/Coroutines/coro-alloca-01.ll
index 51d72bfaa2d29..64530553c254a 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-01.ll
@@ -3,7 +3,8 @@
; if their aliases are used across suspension points through PHINode.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i64, i64, ptr, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f(i1 %n) presplitcoroutine {
; CHECK-LABEL: define ptr @f(
@@ -13,18 +14,18 @@ define ptr @f(i1 %n) presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 48)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: br i1 [[N]], label %[[MERGE:.*]], label %[[MERGE_FROM_FLAG_FALSE:.*]]
; CHECK: [[MERGE_FROM_FLAG_FALSE]]:
; CHECK-NEXT: br label %[[MERGE]]
; CHECK: [[MERGE]]:
; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr [ [[Y_RELOAD_ADDR]], %[[MERGE_FROM_FLAG_FALSE]] ], [ [[X_RELOAD_ADDR]], %[[ENTRY]] ]
-; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: store ptr [[ALIAS_PHI]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 40
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-02.ll b/llvm/test/Transforms/Coroutines/coro-alloca-02.ll
index e760bd59a2e4c..5dfa4892c03d3 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-02.ll
@@ -3,7 +3,8 @@
; the alloac will be put on the frame.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f() presplitcoroutine {
; CHECK-LABEL: define ptr @f() {
@@ -12,12 +13,12 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store ptr [[X_RELOAD_ADDR]], ptr [[Y_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-03.ll b/llvm/test/Transforms/Coroutines/coro-alloca-03.ll
index 4609cf8403dd4..4c5e4393dae90 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-03.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-03.ll
@@ -2,7 +2,8 @@
; Tests that allocas escaped through function calls will live on the frame.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i64, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f() presplitcoroutine {
; CHECK-LABEL: define ptr @f() {
@@ -12,12 +13,12 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 32)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: call void @capture_call(ptr [[X_RELOAD_ADDR]])
; CHECK-NEXT: call void @nocapture_call(ptr [[Y]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-04.ll b/llvm/test/Transforms/Coroutines/coro-alloca-04.ll
index 2839e9c7e5581..f31c0fc32defc 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-04.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-04.ll
@@ -3,7 +3,8 @@
; if their aliases are used across suspension points through PHINode.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f(i1 %n) presplitcoroutine {
; CHECK-LABEL: define ptr @f(
@@ -13,12 +14,12 @@ define ptr @f(i1 %n) presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
+; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store ptr [[TMP0]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR2]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-06.ll b/llvm/test/Transforms/Coroutines/coro-alloca-06.ll
index bf338b1aedbe2..e9c54f8c49171 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-06.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-06.ll
@@ -3,9 +3,10 @@
; though their pointers are stored.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
%handle = type { ptr }
-; CHECK: %f.Frame = type { ptr, ptr, i1 }
define ptr @f() presplitcoroutine {
; CHECK-LABEL: define ptr @f() {
@@ -16,14 +17,14 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
; CHECK-NEXT: [[TMP2:%.*]] = call ptr @await_suspend()
; CHECK-NEXT: store ptr [[TMP2]], ptr [[TMP0]], align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TMP1]])
; CHECK-NEXT: store ptr [[TMP0]], ptr [[TMP1]], align 8
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TMP1]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-07.ll b/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
index 5a37387ed4492..76aca567f785b 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-07.ll
@@ -67,19 +67,19 @@ declare void @free(ptr)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 48)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: br i1 [[N]], label %[[MERGE:.*]], label %[[MERGE_FROM_FLAG_FALSE:.*]]
; CHECK: [[MERGE_FROM_FLAG_FALSE]]:
; CHECK-NEXT: br label %[[MERGE]]
; CHECK: [[MERGE]]:
; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr [ [[Y_RELOAD_ADDR]], %[[MERGE_FROM_FLAG_FALSE]] ], [ [[X_RELOAD_ADDR]], %[[ENTRY]] ]
-; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: store ptr [[ALIAS_PHI]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
; CHECK-NEXT: store i8 1, ptr [[ALIAS_PHI]], align 1
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 40
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -87,7 +87,7 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(48) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[ALIAS_PHI_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[ALIAS_PHI_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: [[ALIAS_PHI_RELOAD:%.*]] = load ptr, ptr [[ALIAS_PHI_RELOAD_ADDR]], align 8
; CHECK-NEXT: call void @print(ptr [[ALIAS_PHI_RELOAD]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-08.ll b/llvm/test/Transforms/Coroutines/coro-alloca-08.ll
index d267e49acc056..2c863b4838237 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-08.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-08.ll
@@ -2,12 +2,12 @@
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
; Verify that for both foo and bar, testval isn't put on the frame.
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
%"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" }
-; CHECK: %foo.Frame = type { ptr, ptr, i1 }
-; CHECK: %bar.Frame = type { ptr, ptr, i1 }
declare ptr @malloc(i64)
@@ -24,12 +24,12 @@ define void @foo() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @foo.resume, ptr [[VFRAME]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[FOO_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 8
; CHECK-NEXT: store ptr @foo.destroy, ptr [[DESTROY_ADDR]], align 8
; CHECK-NEXT: call void @llvm.lifetime.start.p0(ptr [[TESTVAL]])
; CHECK-NEXT: call void @consume.i8.array(ptr [[TESTVAL]])
; CHECK-NEXT: call void @llvm.lifetime.end.p0(ptr [[TESTVAL]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 16
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret void
;
@@ -67,9 +67,9 @@ define void @bar() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @bar.resume, ptr [[VFRAME]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[BAR_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 8
; CHECK-NEXT: store ptr @bar.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[BAR_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 16
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: br i1 false, label %[[AWAIT_READY:.*]], label %[[AFTERCOROEND:.*]]
; CHECK: [[AWAIT_READY]]:
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-09.ll b/llvm/test/Transforms/Coroutines/coro-alloca-09.ll
index 4736790dfe324..42b75c18c1a65 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-09.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-09.ll
@@ -11,19 +11,19 @@ define ptr @f(i1 %n) presplitcoroutine {
; CHECK-NEXT: [[MEM:%.*]] = call ptr @malloc(i32 56)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[MEM]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[ALIAS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
+; CHECK-NEXT: [[ALIAS_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i64 0, ptr [[X_RELOAD_ADDR]], align 4
; CHECK-NEXT: store i64 0, ptr [[ALIAS_SPILL_ADDR]], align 4
; CHECK-NEXT: [[X_ALIAS:%.*]] = insertvalue [1 x ptr] poison, ptr [[X_RELOAD_ADDR]], 0
-; CHECK-NEXT: [[X_ALIAS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[X_ALIAS_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: store [1 x ptr] [[X_ALIAS]], ptr [[X_ALIAS_SPILL_ADDR]], align 8
; CHECK-NEXT: [[Y_ALIAS:%.*]] = insertelement <1 x ptr> poison, ptr [[ALIAS_SPILL_ADDR]], i32 0
-; CHECK-NEXT: [[Y_ALIAS_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[Y_ALIAS_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 40
; CHECK-NEXT: store <1 x ptr> [[Y_ALIAS]], ptr [[Y_ALIAS_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 6
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 48
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-loop-carried-address.ll b/llvm/test/Transforms/Coroutines/coro-alloca-loop-carried-address.ll
index baec3f1a0c869..5d100df9424c0 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-loop-carried-address.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-loop-carried-address.ll
@@ -11,10 +11,10 @@ define void @foo() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 40)
; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @foo.resume, ptr [[VFRAME]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[FOO_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 8
; CHECK-NEXT: store ptr @foo.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[STACKVAR0_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 2
-; CHECK-NEXT: [[STACKVAR1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 3
+; CHECK-NEXT: [[STACKVAR0_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 16
+; CHECK-NEXT: [[STACKVAR1_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 24
; CHECK-NEXT: [[STACKVAR0_INT:%.*]] = ptrtoint ptr [[STACKVAR0_RELOAD_ADDR]] to i64
; CHECK-NEXT: store i64 [[STACKVAR0_INT]], ptr @escape_hatch0, align 4
; CHECK-NEXT: [[STACKVAR1_INT:%.*]] = ptrtoint ptr [[STACKVAR1_RELOAD_ADDR]] to i64
@@ -23,7 +23,7 @@ define void @foo() presplitcoroutine {
; CHECK: loop:
; CHECK-NEXT: store i64 1234, ptr [[STACKVAR0_RELOAD_ADDR]], align 4
; CHECK-NEXT: call void @bar()
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[FOO_FRAME]], ptr [[VFRAME]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 32
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[AFTERCOROEND:%.*]]
; CHECK: AfterCoroEnd:
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll b/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll
index 8c23147ee6072..8d568016b7a29 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-with-addrspace.ll
@@ -11,20 +11,20 @@ define ptr @f(i1 %n) presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 48)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = addrspacecast ptr [[TMP0]] to ptr addrspace(5)
-; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = addrspacecast ptr [[TMP1]] to ptr addrspace(5)
; CHECK-NEXT: br i1 [[N]], label %[[FLAG_TRUE:.*]], label %[[FLAG_FALSE:.*]]
; CHECK: [[FLAG_FALSE]]:
; CHECK-NEXT: br label %[[FLAG_TRUE]]
; CHECK: [[FLAG_TRUE]]:
; CHECK-NEXT: [[ALIAS_PHI:%.*]] = phi ptr addrspace(5) [ [[Y_RELOAD_ADDR]], %[[FLAG_FALSE]] ], [ [[X_RELOAD_ADDR]], %[[ENTRY]] ]
-; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[ALIAS_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: store ptr addrspace(5) [[ALIAS_PHI]], ptr [[ALIAS_PHI_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 40
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll b/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll
index 802d1e432bf5c..58104ebc5aebf 100644
--- a/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll
+++ b/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll
@@ -9,7 +9,6 @@ target datalayout = "p:64:64:64"
%async.ctxt = type { ptr, ptr }
-; CHECK: %my_async_function.Frame = type { i64, [48 x i8], i64, i64, [16 x i8], ptr, i64, ptr }
@my_other_async_function_fp = external global <{ i32, i32 }>
declare void @my_other_async_function(ptr %async.ctxt)
@@ -64,27 +63,27 @@ define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) presplitcorou
; CHECK-LABEL: define swiftcc void @my_async_function(
; CHECK-SAME: ptr swiftasync [[ASYNC_CTXT:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i32 32
-; CHECK-NEXT: [[STACK:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME:%.*]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 2
-; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 6
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 3
+; CHECK-NEXT: [[ASYNC_CTX_FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTXT]], i64 32
+; CHECK-NEXT: [[STACK:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTX_FRAMEPTR]], i64 56
+; CHECK-NEXT: [[STACK2:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTX_FRAMEPTR]], i64 96
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTX_FRAMEPTR]], i64 64
; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[TMP0]] to i64
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 31
; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], -32
; CHECK-NEXT: [[STACK3:%.*]] = inttoptr i64 [[TMP3]] to ptr
-; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 0
+; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTX_FRAMEPTR]], i64 0
; CHECK-NEXT: [[TMP5:%.*]] = ptrtoint ptr [[TMP4]] to i64
; CHECK-NEXT: [[TMP6:%.*]] = add i64 [[TMP5]], 63
; CHECK-NEXT: [[TMP7:%.*]] = and i64 [[TMP6]], -64
; CHECK-NEXT: [[STACK4:%.*]] = inttoptr i64 [[TMP7]] to ptr
-; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 5
+; CHECK-NEXT: [[ASYNC_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTX_FRAMEPTR]], i64 88
; CHECK-NEXT: store ptr [[ASYNC_CTXT]], ptr [[ASYNC_CTXT_SPILL_ADDR]], align 8
; CHECK-NEXT: store i64 0, ptr [[STACK]], align 4
; CHECK-NEXT: store i64 1, ptr [[STACK2]], align 4
; CHECK-NEXT: store i64 2, ptr [[STACK3]], align 4
; CHECK-NEXT: store i64 3, ptr [[STACK4]], align 4
; CHECK-NEXT: [[CALLEE_CONTEXT:%.*]] = call ptr @llvm.coro.async.context.alloc(ptr null, ptr null)
-; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds [[MY_ASYNC_FUNCTION_FRAME]], ptr [[ASYNC_CTX_FRAMEPTR]], i32 0, i32 7
+; CHECK-NEXT: [[CALLEE_CONTEXT_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[ASYNC_CTX_FRAMEPTR]], i64 104
; CHECK-NEXT: store ptr [[CALLEE_CONTEXT]], ptr [[CALLEE_CONTEXT_SPILL_ADDR]], align 8
; CHECK-NEXT: [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR:%.*]] = getelementptr inbounds [[ASYNC_CTXT]], ptr [[CALLEE_CONTEXT]], i32 0, i32 1
; CHECK-NEXT: store ptr @my_async_functionTQ0_, ptr [[CALLEE_CONTEXT_RETURN_TO_CALLER_ADDR]], align 8
diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
index 0639c710cd420..72bb8fcf5b610 100644
--- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
+++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower-invoke.ll
@@ -109,12 +109,11 @@ declare void @free(ptr)
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
+; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR12]], align 1
; CHECK-NEXT: ret void
;
@@ -122,8 +121,8 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
; CHECK-NEXT: [[ENTRY_RESUME:.*]]:
-; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE:.*]] [
; CHECK-NEXT: i2 0, label %[[COROSAVE1:.*]]
@@ -132,7 +131,7 @@ declare void @free(ptr)
; CHECK-NEXT: i2 -1, label %[[CLEANUP:.*]]
; CHECK-NEXT: ]
; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR13]], align 1
; CHECK-NEXT: invoke void @await_suspend_wrapper_void(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
; CHECK-NEXT: to label %[[AFTERCOROSUSPEND3]] unwind label %[[PAD:.*]]
@@ -141,7 +140,7 @@ declare void @free(ptr)
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[COND]], label %[[COROSAVE4:.*]], label %[[COROEND:.*]]
; CHECK: [[COROSAVE4]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i2 -2, ptr [[INDEX_ADDR14]], align 1
; CHECK-NEXT: [[TMP1:%.*]] = invoke i1 @await_suspend_wrapper_bool(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
; CHECK-NEXT: to label %[[STEP1_CONTINUE:.*]] unwind label %[[PAD]]
@@ -152,7 +151,7 @@ declare void @free(ptr)
; CHECK-NEXT: [[COND1:%.*]] = icmp eq i8 [[TMP2]], 0
; CHECK-NEXT: br i1 [[COND1]], label %[[COROSAVE8]], label %[[COROEND]]
; CHECK: [[COROSAVE8]]:
-; CHECK-NEXT: [[INDEX_ADDR15:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR15:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i2 -1, ptr [[INDEX_ADDR15]], align 1
; CHECK-NEXT: [[TMP3:%.*]] = invoke ptr @await_suspend_wrapper_handle(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
; CHECK-NEXT: to label %[[STEP2_CONTINUE:.*]] unwind label %[[PAD]]
@@ -179,7 +178,7 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.destroy(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
-; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
; CHECK-NEXT: call void @free(ptr [[HDL]])
; CHECK-NEXT: ret void
;
@@ -187,7 +186,7 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.cleanup(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) personality i32 0 {
; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
-; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
; CHECK-NEXT: call void @free(ptr null)
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
index 01d3c90ef466c..05bac14f26a2d 100644
--- a/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
+++ b/llvm/test/Transforms/Coroutines/coro-await-suspend-lower.ll
@@ -86,12 +86,11 @@ declare void @free(ptr)
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @f, ptr @f.resumers)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
-; CHECK-NEXT: [[RESUME_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: store ptr @f.resume, ptr [[RESUME_ADDR]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
+; CHECK-NEXT: [[INDEX_ADDR12:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i2 0, ptr [[INDEX_ADDR12]], align 1
; CHECK-NEXT: ret void
;
@@ -99,8 +98,8 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*]]:
-; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[INDEX:%.*]] = load i2, ptr [[INDEX_ADDR]], align 1
; CHECK-NEXT: switch i2 [[INDEX]], label %[[UNREACHABLE:.*]] [
; CHECK-NEXT: i2 0, label %[[COROSAVE1:.*]]
@@ -109,7 +108,7 @@ declare void @free(ptr)
; CHECK-NEXT: i2 -1, label %[[CLEANUP:.*]]
; CHECK-NEXT: ]
; CHECK: [[COROSAVE1]]:
-; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR13:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i2 1, ptr [[INDEX_ADDR13]], align 1
; CHECK-NEXT: call void @await_suspend_wrapper_void(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
; CHECK-NEXT: br label %[[AFTERCOROSUSPEND3]]
@@ -118,7 +117,7 @@ declare void @free(ptr)
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[COND]], label %[[COROSAVE4:.*]], label %[[COROEND:.*]]
; CHECK: [[COROSAVE4]]:
-; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR14:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i2 -2, ptr [[INDEX_ADDR14]], align 1
; CHECK-NEXT: [[TMP1:%.*]] = call i1 @await_suspend_wrapper_bool(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
; CHECK-NEXT: br i1 [[TMP1]], label %[[AFTERCOROSUSPEND7]], label %[[COROSAVE8:.*]]
@@ -127,7 +126,7 @@ declare void @free(ptr)
; CHECK-NEXT: [[COND1:%.*]] = icmp eq i8 [[TMP2]], 0
; CHECK-NEXT: br i1 [[COND1]], label %[[COROSAVE8]], label %[[COROEND]]
; CHECK: [[COROSAVE8]]:
-; CHECK-NEXT: [[INDEX_ADDR15:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR15:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i2 -1, ptr [[INDEX_ADDR15]], align 1
; CHECK-NEXT: [[TMP3:%.*]] = call ptr @await_suspend_wrapper_handle(ptr [[AWAITER_RELOAD_ADDR]], ptr [[HDL]])
; CHECK-NEXT: [[TMP4:%.*]] = call ptr @llvm.coro.subfn.addr(ptr [[TMP3]], i8 0)
@@ -145,7 +144,7 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.destroy(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
-; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
; CHECK-NEXT: call void @free(ptr [[HDL]])
; CHECK-NEXT: ret void
;
@@ -153,7 +152,7 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.cleanup(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
-; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 0
+; CHECK-NEXT: [[AWAITER_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 0
; CHECK-NEXT: call void @free(ptr null)
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/Coroutines/coro-byval-param.ll b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
index ead86322662e7..db1f151b59bc5 100644
--- a/llvm/test/Transforms/Coroutines/coro-byval-param.ll
+++ b/llvm/test/Transforms/Coroutines/coro-byval-param.ll
@@ -1,13 +1,14 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
%promise_type = type { i8 }
%struct.A = type <{ i64, i64, i32, [4 x i8] }>
; Check that the frame will contain the entire struct, instead of just the
; struct pointer, and that the alignment is taken into account.
-; CHECK: %foo.Frame = type { ptr, ptr, %promise_type, i1, [6 x i8], %struct.A }
-
; Function Attrs: noinline ssp uwtable mustprogress
define ptr @foo(ptr nocapture readonly byval(%struct.A) align 8 %a1) #0 {
; CHECK-LABEL: define ptr @foo(
@@ -24,15 +25,14 @@ define ptr @foo(ptr nocapture readonly byval(%struct.A) align 8 %a1) #0 {
; CHECK-NEXT: [[TMP3:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr [[TMP2]])
; CHECK-NEXT: store ptr @foo.resume, ptr [[TMP3]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = select i1 [[TMP1]], ptr @foo.destroy, ptr @foo.cleanup
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[FOO_FRAME:%.*]], ptr [[TMP3]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 8
; CHECK-NEXT: store ptr [[TMP4]], ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[TMP3]], i32 0, i32 2
-; CHECK-NEXT: [[A1_SPILL_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[TMP3]], i32 0, i32 5
-; CHECK-NEXT: [[TMP5:%.*]] = load [[STRUCT_A]], ptr [[A1]], align 1
-; CHECK-NEXT: store [[STRUCT_A]] [[TMP5]], ptr [[A1_SPILL_ADDR]], align 8
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 16
+; CHECK-NEXT: [[A1_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 24
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[A1_SPILL_ADDR]], ptr align 8 [[A1]], i64 24, i1 false)
; CHECK-NEXT: [[CALL2:%.*]] = call ptr @_ZN4task12promise_type17get_return_objectEv(ptr nonnull dereferenceable(1) [[__PROMISE_RELOAD_ADDR]])
; CHECK-NEXT: call void @initial_suspend(ptr nonnull dereferenceable(1) [[__PROMISE_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds nuw [[FOO_FRAME]], ptr [[TMP3]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds i8, ptr [[TMP3]], i64 17
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR5]], align 1
; CHECK-NEXT: call fastcc void @_ZNSt12experimental13coroutines_v116coroutine_handleIN4task12promise_typeEE12from_addressEPv(ptr [[TMP3]]) #[[ATTR2:[0-9]+]]
; CHECK-NEXT: ret ptr [[CALL2]]
diff --git a/llvm/test/Transforms/Coroutines/coro-catchswitch.ll b/llvm/test/Transforms/Coroutines/coro-catchswitch.ll
index ec55954cea194..1fcf36f4f7ea9 100644
--- a/llvm/test/Transforms/Coroutines/coro-catchswitch.ll
+++ b/llvm/test/Transforms/Coroutines/coro-catchswitch.ll
@@ -13,7 +13,7 @@ define void @f(i1 %cond) presplitcoroutine personality i32 0 {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 16)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 4
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 4
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 4
; CHECK-NEXT: br i1 [[COND]], label %[[IF_ELSE:.*]], label %[[IF_THEN:.*]]
; CHECK: [[IF_THEN]]:
@@ -25,7 +25,7 @@ define void @f(i1 %cond) presplitcoroutine personality i32 0 {
; CHECK: [[CATCH_DISPATCH]]:
; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ 1, %[[IF_THEN]] ], [ 2, %[[IF_ELSE]] ]
; CHECK-NEXT: [[TMP0:%.*]] = cleanuppad within none []
-; CHECK-NEXT: [[VAL_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[VAL_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store i32 [[VAL]], ptr [[VAL_SPILL_ADDR]], align 4
; CHECK-NEXT: cleanupret from [[TMP0]] unwind label %[[BB1:.*]]
; CHECK: [[BB1]]:
@@ -34,7 +34,7 @@ define void @f(i1 %cond) presplitcoroutine personality i32 0 {
; CHECK-NEXT: [[PAD:%.*]] = catchpad within [[SWITCH]] [ptr null, i32 64, ptr null]
; CHECK-NEXT: catchret from [[PAD]] to label %[[COROSAVE:.*]]
; CHECK: [[COROSAVE]]:
-; CHECK-NEXT: [[INDEX_ADDR3:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR3:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 12
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR3]], align 1
; CHECK-NEXT: br i1 false, label %[[RESUME:.*]], label %[[AFTERCOROEND]]
; CHECK: [[RESUME]]:
diff --git a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
index 4983ab4b47922..713e36c1f8fc9 100644
--- a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-01.ll
@@ -77,15 +77,15 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 32)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @g.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[G_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @g.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[Y_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[Y_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 20
; CHECK-NEXT: store i32 [[Y]], ptr [[Y_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[COND_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[COND_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 25
; CHECK-NEXT: store i1 [[COND]], ptr [[COND_SPILL_ADDR]], align 1
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[G_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret void
;
@@ -93,7 +93,7 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly)
; CHECK-LABEL: define internal fastcc void @g.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) personality i32 0 {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[COND_RELOAD_ADDR:%.*]] = getelementptr inbounds [[G_FRAME:%.*]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[COND_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 25
; CHECK-NEXT: [[COND_RELOAD:%.*]] = load i1, ptr [[COND_RELOAD_ADDR]], align 1
; CHECK-NEXT: br i1 [[COND_RELOAD]], label %[[INVOKE1:.*]], label %[[INVOKE2:.*]]
; CHECK: [[INVOKE1]]:
@@ -104,12 +104,12 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly)
; CHECK-NEXT: to label %[[UNREACH]] unwind label %[[PAD_WITH_PHI_FROM_INVOKE2:.*]]
; CHECK: [[PAD_WITH_PHI_FROM_INVOKE2]]:
; CHECK-NEXT: [[TMP0:%.*]] = cleanuppad within none []
-; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 20
; CHECK-NEXT: [[Y_RELOAD:%.*]] = load i32, ptr [[Y_RELOAD_ADDR]], align 4
; CHECK-NEXT: cleanupret from [[TMP0]] unwind label %[[PAD_WITH_PHI:.*]]
; CHECK: [[PAD_WITH_PHI_FROM_INVOKE1]]:
; CHECK-NEXT: [[TMP1:%.*]] = cleanuppad within none []
-; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4
; CHECK-NEXT: cleanupret from [[TMP1]] unwind label %[[PAD_WITH_PHI]]
; CHECK: [[PAD_WITH_PHI]]:
diff --git a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
index a005a9c8e6167..335b9e5cd7945 100644
--- a/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-eh-aware-edge-split-02.ll
@@ -77,15 +77,15 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 32)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @h.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[H_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @h.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[Y_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[Y_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 20
; CHECK-NEXT: store i32 [[Y]], ptr [[Y_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[COND_SPILL_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[COND_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 25
; CHECK-NEXT: store i1 [[COND]], ptr [[COND_SPILL_ADDR]], align 1
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[H_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret void
;
@@ -93,7 +93,7 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly)
; CHECK-LABEL: define internal fastcc void @h.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) personality i32 0 {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[COND_RELOAD_ADDR:%.*]] = getelementptr inbounds [[H_FRAME:%.*]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[COND_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 25
; CHECK-NEXT: [[COND_RELOAD:%.*]] = load i1, ptr [[COND_RELOAD_ADDR]], align 1
; CHECK-NEXT: br i1 [[COND_RELOAD]], label %[[INVOKE1:.*]], label %[[INVOKE2:.*]]
; CHECK: [[INVOKE1]]:
@@ -104,12 +104,12 @@ declare ptr @llvm.coro.free(token, ptr nocapture readonly)
; CHECK-NEXT: to label %[[COROEND]] unwind label %[[PAD_WITH_PHI_FROM_INVOKE2:.*]]
; CHECK: [[PAD_WITH_PHI_FROM_INVOKE2]]:
; CHECK-NEXT: [[TMP0:%.*]] = cleanuppad within none []
-; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[Y_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 20
; CHECK-NEXT: [[Y_RELOAD:%.*]] = load i32, ptr [[Y_RELOAD_ADDR]], align 4
; CHECK-NEXT: cleanupret from [[TMP0]] unwind label %[[PAD_WITH_PHI:.*]]
; CHECK: [[PAD_WITH_PHI_FROM_INVOKE1]]:
; CHECK-NEXT: [[TMP1:%.*]] = cleanuppad within none []
-; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[H_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4
; CHECK-NEXT: cleanupret from [[TMP1]] unwind label %[[PAD_WITH_PHI]]
; CHECK: [[PAD_WITH_PHI]]:
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll b/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
index 99adb44349aa7..d0e1f32f12af8 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-arrayalloca.ll
@@ -58,15 +58,15 @@ declare void @free(ptr)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 56)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[PREFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4, i32 0
-; CHECK-NEXT: [[SUFFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[PREFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
+; CHECK-NEXT: [[SUFFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: call void @consume.double.ptr(ptr [[PREFIX_RELOAD_ADDR]])
; CHECK-NEXT: call void @consume.i32.ptr(ptr [[DATA_RELOAD_ADDR]])
; CHECK-NEXT: call void @consume.double.ptr(ptr [[SUFFIX_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 48
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -74,9 +74,9 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(56) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[PREFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4, i32 0
-; CHECK-NEXT: [[SUFFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[PREFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
+; CHECK-NEXT: [[SUFFIX_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: call void @consume.double.ptr(ptr [[PREFIX_RELOAD_ADDR]])
; CHECK-NEXT: call void @consume.i32.ptr(ptr [[DATA_RELOAD_ADDR]])
; CHECK-NEXT: call void @consume.double.ptr(ptr [[SUFFIX_RELOAD_ADDR]])
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll
index 3bed01bb4a877..077c01f11c9af 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-01.ll
@@ -4,7 +4,8 @@
; There should be only one %struct.big_structure in the frame.
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
%"struct.task::promise_type" = type { i8 }
%struct.awaitable = type { i8 }
@@ -18,18 +19,18 @@ define void @a(i1 zeroext %cond) presplitcoroutine {
; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @a, ptr @a.resumers)
; CHECK-NEXT: [[TMP1:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr null)
; CHECK-NEXT: store ptr @a.resume, ptr [[TMP1]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[TMP1]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 8
; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[TMP1]], i32 0, i32 3
+; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 17
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
; CHECK: [[IF_THEN]]:
; CHECK-NEXT: call void @consume(ptr nonnull [[A_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 517
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
; CHECK: [[IF_ELSE]]:
; CHECK-NEXT: call void @consume(ptr nonnull [[A_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 517
; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR5]], align 1
; CHECK-NEXT: br label %[[AFTERCOROEND]]
; CHECK: [[AFTERCOROEND]]:
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-02.ll b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-02.ll
index 87fea63ce0b39..b4cc57c24f0d8 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-02.ll
@@ -3,7 +3,8 @@
; re-use the same slot in Coroutine frame.
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
%"struct.task::promise_type" = type { i8 }
%struct.awaitable = type { i8 }
@@ -19,18 +20,18 @@ define void @a(i1 zeroext %cond) presplitcoroutine {
; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @a, ptr @a.resumers)
; CHECK-NEXT: [[TMP1:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr null)
; CHECK-NEXT: store ptr @a.resume, ptr [[TMP1]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[TMP1]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 8
; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[TMP1]], i32 0, i32 3
+; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 17
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
; CHECK: [[IF_THEN]]:
; CHECK-NEXT: call void @consume(ptr nonnull [[A_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 517
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
; CHECK: [[IF_ELSE]]:
; CHECK-NEXT: call void @consume.2(ptr nonnull [[A_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 517
; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR5]], align 1
; CHECK-NEXT: br label %[[AFTERCOROEND]]
; CHECK: [[AFTERCOROEND]]:
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-04.ll b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-04.ll
index db2458c71a731..533525b691350 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-04.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-04.ll
@@ -3,7 +3,8 @@
; range is not overlapping each other should not re-use the same slot in Coroutine frame.
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", %struct.big_structure, i1, [26 x i8], %struct.big_structure.2 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
%"struct.task::promise_type" = type { i8 }
%struct.awaitable = type { i8 }
@@ -19,19 +20,19 @@ define void @a(i1 zeroext %cond) presplitcoroutine {
; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @a, ptr @a.resumers)
; CHECK-NEXT: [[TMP1:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr null)
; CHECK-NEXT: store ptr @a.resume, ptr [[TMP1]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[TMP1]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 8
; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[TMP1]], i32 0, i32 3
-; CHECK-NEXT: [[B_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[TMP1]], i32 0, i32 6
+; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 17
+; CHECK-NEXT: [[B_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 544
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
; CHECK: [[IF_THEN]]:
; CHECK-NEXT: call void @consume(ptr nonnull [[A_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 517
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
; CHECK: [[IF_ELSE]]:
; CHECK-NEXT: call void @consume.2(ptr nonnull [[B_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 517
; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR5]], align 1
; CHECK-NEXT: br label %[[AFTERCOROEND]]
; CHECK: [[AFTERCOROEND]]:
diff --git a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-05.ll b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-05.ll
index 1815df83b227b..b78e448b880d6 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-05.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame-reuse-alloca-05.ll
@@ -3,7 +3,8 @@
; lifetime range is not overlapping each other re-use the same slot in CorotuineFrame.
; RUN: opt < %s -passes='cgscc(coro-split<reuse-storage>),simplifycfg,early-cse' -S | FileCheck %s
-; CHECK: %a.Frame = type { ptr, ptr, %"struct.task::promise_type", i1, [14 x i8], %struct.big_structure }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
%"struct.task::promise_type" = type { i8 }
%struct.awaitable = type { i8 }
@@ -19,18 +20,18 @@ define void @a(i1 zeroext %cond) presplitcoroutine {
; CHECK-NEXT: [[TMP0:%.*]] = call token @llvm.coro.id(i32 16, ptr nonnull null, ptr @a, ptr @a.resumers)
; CHECK-NEXT: [[TMP1:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[TMP0]], ptr null)
; CHECK-NEXT: store ptr @a.resume, ptr [[TMP1]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[A_FRAME:%.*]], ptr [[TMP1]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 8
; CHECK-NEXT: store ptr @a.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds [[A_FRAME]], ptr [[TMP1]], i32 0, i32 5
+; CHECK-NEXT: [[A_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 32
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
; CHECK: [[IF_THEN]]:
; CHECK-NEXT: call void @consume(ptr nonnull [[A_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 17
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
; CHECK-NEXT: br label %[[AFTERCOROEND:.*]]
; CHECK: [[IF_ELSE]]:
; CHECK-NEXT: call void @consume.2(ptr nonnull [[A_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds nuw [[A_FRAME]], ptr [[TMP1]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR5:%.*]] = getelementptr inbounds i8, ptr [[TMP1]], i64 17
; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR5]], align 1
; CHECK-NEXT: br label %[[AFTERCOROEND]]
; CHECK: [[AFTERCOROEND]]:
diff --git a/llvm/test/Transforms/Coroutines/coro-frame.ll b/llvm/test/Transforms/Coroutines/coro-frame.ll
index 7f12362cd48ae..1beccdf5de7b0 100644
--- a/llvm/test/Transforms/Coroutines/coro-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-frame.ll
@@ -60,14 +60,14 @@ declare void @free(ptr)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[THIS1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[THIS1_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i64 [[THIS]], ptr [[THIS1_SPILL_ADDR]], align 4
; CHECK-NEXT: [[R:%.*]] = call double @print(double 0.000000e+00)
-; CHECK-NEXT: [[R_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[R_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store double [[R]], ptr [[R_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -75,9 +75,9 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(40) [[HDL:%.*]]) personality i32 0 {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[R_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[R_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[R_RELOAD:%.*]] = load double, ptr [[R_RELOAD_ADDR]], align 8
-; CHECK-NEXT: [[THIS1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[THIS1_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: [[THIS1_RELOAD:%.*]] = load i64, ptr [[THIS1_RELOAD_ADDR]], align 4
; CHECK-NEXT: [[TMP0:%.*]] = call double @print(double [[R_RELOAD]])
; CHECK-NEXT: call void @print2(i64 [[THIS1_RELOAD]])
diff --git a/llvm/test/Transforms/Coroutines/coro-lifetime-end.ll b/llvm/test/Transforms/Coroutines/coro-lifetime-end.ll
index 503b93ea76a02..83137a15cd16e 100644
--- a/llvm/test/Transforms/Coroutines/coro-lifetime-end.ll
+++ b/llvm/test/Transforms/Coroutines/coro-lifetime-end.ll
@@ -17,11 +17,11 @@ define void @HasNoLifetimeEnd() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @HasNoLifetimeEnd.resume, ptr [[VFRAME]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[HASNOLIFETIMEEND_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 8
; CHECK-NEXT: store ptr @HasNoLifetimeEnd.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds [[HASNOLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 16
; CHECK-NEXT: call void @consume.i8.array(ptr [[INDEX_ADDR1]])
-; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds nuw [[HASNOLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 116
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR2]], align 1
; CHECK-NEXT: ret void
;
@@ -54,11 +54,11 @@ define void @LifetimeEndAfterCoroEnd() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @LifetimeEndAfterCoroEnd.resume, ptr [[VFRAME]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[LIFETIMEENDAFTERCOROEND_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 8
; CHECK-NEXT: store ptr @LifetimeEndAfterCoroEnd.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds [[LIFETIMEENDAFTERCOROEND_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 16
; CHECK-NEXT: call void @consume.i8.array(ptr [[INDEX_ADDR1]])
-; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds nuw [[LIFETIMEENDAFTERCOROEND_FRAME]], ptr [[VFRAME]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 116
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR2]], align 1
; CHECK-NEXT: ret void
;
@@ -92,12 +92,12 @@ define void @BranchWithoutLifetimeEnd() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i64 16)
; CHECK-NEXT: [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @BranchWithoutLifetimeEnd.resume, ptr [[VFRAME]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[BRANCHWITHOUTLIFETIMEEND_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 8
; CHECK-NEXT: store ptr @BranchWithoutLifetimeEnd.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TESTVAL:%.*]] = getelementptr inbounds [[BRANCHWITHOUTLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 2
+; CHECK-NEXT: [[TESTVAL:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 16
; CHECK-NEXT: call void @consume.i8.array(ptr [[TESTVAL]])
; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr @testbool, align 1
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[BRANCHWITHOUTLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[VFRAME]], i64 116
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret void
;
diff --git a/llvm/test/Transforms/Coroutines/coro-noop.ll b/llvm/test/Transforms/Coroutines/coro-noop.ll
index de92df6b9f90b..0f61db42c5dec 100644
--- a/llvm/test/Transforms/Coroutines/coro-noop.ll
+++ b/llvm/test/Transforms/Coroutines/coro-noop.ll
@@ -1,7 +1,6 @@
; Tests that CoroCleanup pass correctly lowers coro.noop
; RUN: opt < %s -S -passes=coro-cleanup | FileCheck %s
-; CHECK: %NoopCoro.Frame = type { ptr, ptr }
; CHECK: @NoopCoro.Frame.Const = private constant %NoopCoro.Frame { ptr @__NoopCoro_ResumeDestroy, ptr @__NoopCoro_ResumeDestroy }
diff --git a/llvm/test/Transforms/Coroutines/coro-padding.ll b/llvm/test/Transforms/Coroutines/coro-padding.ll
index 9e4d5d95209ad..c8749bc43db8e 100644
--- a/llvm/test/Transforms/Coroutines/coro-padding.ll
+++ b/llvm/test/Transforms/Coroutines/coro-padding.ll
@@ -49,14 +49,14 @@ declare void @free(ptr)
; CHECK-LABEL: define ptr @f() {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @f.resumers)
-; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 40)
+; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 64)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -64,7 +64,7 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 32 dereferenceable(64) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
; CHECK-NEXT: ret void
diff --git a/llvm/test/Transforms/Coroutines/coro-param-copy.ll b/llvm/test/Transforms/Coroutines/coro-param-copy.ll
index 4f490befafd1e..10a0ed2deedc4 100644
--- a/llvm/test/Transforms/Coroutines/coro-param-copy.ll
+++ b/llvm/test/Transforms/Coroutines/coro-param-copy.ll
@@ -8,7 +8,8 @@
; 3. Then see that we only copy the x as y was not modified prior to
; coro.begin.
-; CHECK: %f.Frame = type { ptr, ptr, i64, i64, i64, i64, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f() presplitcoroutine {
; CHECK-LABEL: define ptr @f() {
@@ -27,17 +28,15 @@ define ptr @f() presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @myAlloc(i32 56)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
-; CHECK-NEXT: [[TMP1:%.*]] = load i64, ptr [[X_ADDR]], align 4
-; CHECK-NEXT: store i64 [[TMP1]], ptr [[TMP0]], align 4
-; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
-; CHECK-NEXT: [[TMP3:%.*]] = load i64, ptr [[Z_ADDR]], align 4
-; CHECK-NEXT: store i64 [[TMP3]], ptr [[TMP2]], align 4
-; CHECK-NEXT: [[Y_ADDR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP0]], ptr align 8 [[X_ADDR]], i64 8, i1 false)
+; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 40
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[TMP1]], ptr align 8 [[Z_ADDR]], i64 8, i1 false)
+; CHECK-NEXT: [[Y_ADDR_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 32
; CHECK-NEXT: call void @llvm.memset.p0.i32(ptr [[Y_ADDR_RELOAD_ADDR]], i8 1, i32 4, i1 false)
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 6
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 48
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-once-value.ll b/llvm/test/Transforms/Coroutines/coro-retcon-once-value.ll
index 026e23913d647..74a3f8d449d0c 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-once-value.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-once-value.ll
@@ -157,7 +157,7 @@ declare void @print(i32)
;
; CHECK-LABEL: @g(
; CHECK-NEXT: PostSpill:
-; CHECK-NEXT: [[TMP0:%.*]] = tail call ptr @allocate(i32 16)
+; CHECK-NEXT: [[TMP0:%.*]] = tail call ptr @allocate(i32 12)
; CHECK-NEXT: store ptr [[TMP0]], ptr [[BUFFER:%.*]], align 8
; CHECK-NEXT: [[VAL_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[TMP0]], i64 8
; CHECK-NEXT: store i32 [[VAL:%.*]], ptr [[VAL_SPILL_ADDR]], align 4
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-once-value2.ll b/llvm/test/Transforms/Coroutines/coro-retcon-once-value2.ll
index aad762e2c9335..bf95b2a74e6de 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-once-value2.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-once-value2.ll
@@ -84,9 +84,9 @@ declare fastcc void @deallocate(ptr %ptr)
declare void @print(i32)
; CHECK-LABEL: @f(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 16)
+; CHECK-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 12)
; CHECK-NEXT: store ptr [[TMP0]], ptr [[BUFFER:%.*]], align 8
-; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[TMP0]], i32 0, i32 1
+; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
; 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
@@ -97,7 +97,7 @@ declare void @print(i32)
; CHECK-LABEL: @f.resume.0(
; CHECK-NEXT: entryresume.0:
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0:%.*]], align 8
-; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[TMP2]], i32 0, i32 1
+; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 8
; CHECK-NEXT: br i1 [[TMP1:%.*]], label [[COROEND:%.*]], label [[CONT:%.*]]
; CHECK: cont:
; CHECK-NEXT: [[PTR_RELOAD:%.*]] = load ptr, ptr [[TMP2]], align 8
@@ -111,10 +111,10 @@ declare void @print(i32)
;
; CHECK-LABEL: @g(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 16)
+; CHECK-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 13)
; CHECK-NEXT: store ptr [[TMP0]], ptr [[BUFFER:%.*]], align 8
-; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[G_FRAME:%.*]], ptr [[TMP0]], i32 0, i32 1
-; CHECK-NEXT: [[VAL_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[TMP0]], i32 0, i32 2
+; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
+; CHECK-NEXT: [[VAL_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 12
; CHECK-NEXT: store i8 [[VAL:%.*]], ptr [[VAL_SPILL_ADDR]], align 1
; CHECK-NEXT: store ptr [[PTR:%.*]], ptr [[TMP0]], align 8
; CHECK-NEXT: [[OLDVALUE:%.*]] = load i32, ptr [[PTR]], align 4
@@ -126,7 +126,7 @@ declare void @print(i32)
; CHECK-LABEL: @g.resume.0(
; CHECK-NEXT: entryresume.0:
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0:%.*]], align 8
-; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[G_FRAME:%.*]], ptr [[TMP2]], i32 0, i32 1
+; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 8
; CHECK-NEXT: br i1 [[TMP1:%.*]], label [[CLEANUP:%.*]], label [[CONT:%.*]]
; CHECK: cont:
; CHECK-NEXT: [[PTR_RELOAD:%.*]] = load ptr, ptr [[TMP2]], align 8
@@ -134,7 +134,7 @@ declare void @print(i32)
; CHECK-NEXT: store i32 [[NEWVALUE]], ptr [[PTR_RELOAD]], align 4
; CHECK-NEXT: br label [[CLEANUP]]
; CHECK: cleanup:
-; CHECK-NEXT: [[VAL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[TMP2]], i32 0, i32 2
+; CHECK-NEXT: [[VAL_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 12
; CHECK-NEXT: [[VAL_RELOAD:%.*]] = load i8, ptr [[VAL_RELOAD_ADDR]], align 1
; CHECK-NEXT: call fastcc void @deallocate(ptr [[TMP2]])
; CHECK-NEXT: ret i8 [[VAL_RELOAD]]
@@ -142,9 +142,9 @@ declare void @print(i32)
;
; CHECK-LABEL: @h(
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 16)
+; CHECK-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 12)
; CHECK-NEXT: store ptr [[TMP0]], ptr [[BUFFER:%.*]], align 8
-; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[H_FRAME:%.*]], ptr [[TMP0]], i32 0, i32 1
+; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 8
; 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
@@ -155,7 +155,7 @@ declare void @print(i32)
; CHECK-LABEL: @h.resume.0(
; CHECK-NEXT: entryresume.0:
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0:%.*]], align 8
-; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds [[H_FRAME:%.*]], ptr [[TMP2]], i32 0, i32 1
+; CHECK-NEXT: [[TEMP:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 8
; CHECK-NEXT: br i1 [[TMP1:%.*]], label [[COROEND:%.*]], label [[CONT:%.*]]
; CHECK: cont:
; CHECK-NEXT: [[PTR_RELOAD:%.*]] = load ptr, ptr [[TMP2]], align 8
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll b/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll
index eeba55b8f23a4..ed680adb48eef 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-remat.ll
@@ -4,14 +4,14 @@
; RUN: opt < %s -O0 -S | FileCheck %s
-; CHECK: %f.Frame = type { i32 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define { ptr, i32 } @f(ptr %buffer, i32 %n) {
; CHECK-LABEL: define { ptr, i32 } @f(
; CHECK-SAME: ptr [[BUFFER:%.*]], i32 [[N:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[N_VAL_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[BUFFER]], i32 0, i32 0
-; CHECK-NEXT: store i32 [[N]], ptr [[N_VAL_SPILL_ADDR]], align 4
+; CHECK-NEXT: store i32 [[N]], ptr [[BUFFER]], align 4
; CHECK-NEXT: call void @print(i32 [[N]])
; CHECK-NEXT: [[INC1:%.*]] = add i32 [[N]], 1
; CHECK-NEXT: [[INC2:%.*]] = add i32 [[INC1]], 2
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon-resume-values2.ll b/llvm/test/Transforms/Coroutines/coro-retcon-resume-values2.ll
index a19c1ca0e7f3a..b1dfbd1b6d4f6 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon-resume-values2.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon-resume-values2.ll
@@ -44,11 +44,11 @@ declare void @print(i32)
; CHECK-LABEL: @f.resume.0(
; CHECK-NEXT: entryresume.0:
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0:%.*]], align 8
-; CHECK-NEXT: [[VALUE0_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[TMP2]], i32 0, i32 1
+; CHECK-NEXT: [[VALUE0_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 4
; CHECK-NEXT: store i32 [[TMP1:%.*]], ptr [[VALUE0_SPILL_ADDR]], align 4
; CHECK-NEXT: [[N_RELOAD:%.*]] = load i32, ptr [[TMP2]], align 4
; CHECK-NEXT: [[SUM0:%.*]] = call i32 @add(i32 [[N_RELOAD]], i32 [[TMP1]])
-; CHECK-NEXT: [[SUM0_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[TMP2]], i32 0, i32 2
+; CHECK-NEXT: [[SUM0_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 8
; CHECK-NEXT: store i32 [[SUM0]], ptr [[SUM0_SPILL_ADDR]], align 4
; CHECK-NEXT: ret ptr @f.resume.1
;
@@ -56,15 +56,15 @@ declare void @print(i32)
; CHECK-LABEL: @f.resume.1(
; CHECK-NEXT: entryresume.1:
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0:%.*]], align 8
-; CHECK-NEXT: [[VALUE1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[TMP2]], i32 0, i32 3
+; CHECK-NEXT: [[VALUE1_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 12
; CHECK-NEXT: store i32 [[TMP1:%.*]], ptr [[VALUE1_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[SUM0_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[TMP2]], i32 0, i32 2
+; CHECK-NEXT: [[SUM0_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 8
; CHECK-NEXT: [[SUM0_RELOAD:%.*]] = load i32, ptr [[SUM0_RELOAD_ADDR]], align 4
-; CHECK-NEXT: [[VALUE0_RELOAD_ADDR5:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[TMP2]], i32 0, i32 1
+; CHECK-NEXT: [[VALUE0_RELOAD_ADDR5:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 4
; CHECK-NEXT: [[VALUE0_RELOAD6:%.*]] = load i32, ptr [[VALUE0_RELOAD_ADDR5]], align 4
; CHECK-NEXT: [[SUM1:%.*]] = call i32 @add(i32 [[SUM0_RELOAD]], i32 [[VALUE0_RELOAD6]])
; CHECK-NEXT: [[SUM2:%.*]] = call i32 @add(i32 [[SUM1]], i32 [[TMP1]])
-; CHECK-NEXT: [[SUM2_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[TMP2]], i32 0, i32 4
+; CHECK-NEXT: [[SUM2_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 16
; CHECK-NEXT: store i32 [[SUM2]], ptr [[SUM2_SPILL_ADDR]], align 4
; CHECK-NEXT: ret ptr @f.resume.2
;
@@ -72,11 +72,11 @@ declare void @print(i32)
; CHECK-LABEL: @f.resume.2(
; CHECK-NEXT: entryresume.2:
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0:%.*]], align 8
-; CHECK-NEXT: [[SUM2_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[TMP2]], i32 0, i32 4
+; CHECK-NEXT: [[SUM2_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 16
; CHECK-NEXT: [[SUM2_RELOAD:%.*]] = load i32, ptr [[SUM2_RELOAD_ADDR]], align 4
-; CHECK-NEXT: [[VALUE1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[TMP2]], i32 0, i32 3
+; CHECK-NEXT: [[VALUE1_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 12
; CHECK-NEXT: [[VALUE1_RELOAD:%.*]] = load i32, ptr [[VALUE1_RELOAD_ADDR]], align 4
-; CHECK-NEXT: [[VALUE0_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[TMP2]], i32 0, i32 1
+; CHECK-NEXT: [[VALUE0_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP2]], i64 4
; CHECK-NEXT: [[VALUE0_RELOAD:%.*]] = load i32, ptr [[VALUE0_RELOAD_ADDR]], align 4
; CHECK-NEXT: [[SUM3:%.*]] = call i32 @add(i32 [[SUM2_RELOAD]], i32 [[VALUE0_RELOAD]])
; CHECK-NEXT: [[SUM4:%.*]] = call i32 @add(i32 [[SUM3]], i32 [[VALUE1_RELOAD]])
diff --git a/llvm/test/Transforms/Coroutines/coro-retcon.ll b/llvm/test/Transforms/Coroutines/coro-retcon.ll
index 86eba3b5d134f..d36ff5271bc71 100644
--- a/llvm/test/Transforms/Coroutines/coro-retcon.ll
+++ b/llvm/test/Transforms/Coroutines/coro-retcon.ll
@@ -12,8 +12,7 @@ define ptr @f(ptr %buffer, i32 %n) {
;
; CORO-LABEL: @f(
; CORO-NEXT: entry:
-; CORO-NEXT: [[N_VAL_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[BUFFER:%.*]], i32 0, i32 0
-; CORO-NEXT: store i32 [[N:%.*]], ptr [[N_VAL_SPILL_ADDR]], align 4
+; CORO-NEXT: store i32 [[N:%.*]], ptr [[N_VAL_SPILL_ADDR:%.*]], align 4
; CORO-NEXT: call void @print(i32 [[N]])
; CORO-NEXT: ret ptr @f.resume.0
;
@@ -84,9 +83,8 @@ define hidden { ptr, ptr } @g(ptr %buffer, ptr %ptr) {
; CORO-NEXT: entry:
; CORO-NEXT: [[TMP0:%.*]] = call ptr @allocate(i32 8)
; CORO-NEXT: store ptr [[TMP0]], ptr [[BUFFER:%.*]], align 8
-; CORO-NEXT: [[PTR_SPILL_ADDR:%.*]] = getelementptr inbounds [[G_FRAME:%.*]], ptr [[TMP0]], i32 0, i32 0
-; CORO-NEXT: store ptr [[PTR:%.*]], ptr [[PTR_SPILL_ADDR]], align 8
-; CORO-NEXT: [[PTR_RELOAD_ADDR:%.*]] = getelementptr inbounds [[G_FRAME]], ptr [[TMP0]], i32 0, i32 0
+; CORO-NEXT: store ptr [[PTR:%.*]], ptr [[TMP0]], align 8
+; CORO-NEXT: [[PTR_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[TMP0]], i64 0
; CORO-NEXT: [[PTR_RELOAD:%.*]] = load ptr, ptr [[PTR_RELOAD_ADDR]], align 8
; CORO-NEXT: [[TMP1:%.*]] = insertvalue { ptr, ptr } poison, ptr @g.resume.0, 0
; CORO-NEXT: [[TMP2:%.*]] = insertvalue { ptr, ptr } [[TMP1]], ptr [[PTR_RELOAD]], 1
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-after-phi.ll b/llvm/test/Transforms/Coroutines/coro-spill-after-phi.ll
index 6694fa79b8858..c983e063a2965 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-after-phi.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-after-phi.ll
@@ -4,7 +4,6 @@
; Verifies that the both phis are stored correctly in the coroutine frame
-; CHECK: %f.Frame = type { ptr, ptr, i32, i32, i1 }
define ptr @f(i1 %n) presplitcoroutine {
; CHECK-LABEL: @f(
@@ -13,15 +12,15 @@ define ptr @f(i1 %n) presplitcoroutine {
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 32)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[N:%.*]], i32 0, i32 2
; CHECK-NEXT: [[SPEC_SELECT5:%.*]] = select i1 [[N]], i32 1, i32 3
-; CHECK-NEXT: [[PHI2_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[PHI2_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 20
; CHECK-NEXT: store i32 [[SPEC_SELECT5]], ptr [[PHI2_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[PHI1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[PHI1_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i32 [[SPEC_SELECT]], ptr [[PHI1_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
index 1ef841faeab11..7a62885ec37ea 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-corobegin.ll
@@ -58,13 +58,13 @@ declare void @free(ptr)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 32)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
; CHECK-NEXT: [[INNERID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr @g, ptr @g.resumers)
; CHECK-NEXT: [[INNERHDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[INNERID]], ptr null)
-; CHECK-NEXT: [[INNERHDL_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INNERHDL_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store ptr [[INNERHDL]], ptr [[INNERHDL_SPILL_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -72,7 +72,7 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(32) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[INNERHDL_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INNERHDL_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[INNERHDL_RELOAD:%.*]] = load ptr, ptr [[INNERHDL_RELOAD_ADDR]], align 8
; CHECK-NEXT: [[GVAR_ADDR:%.*]] = getelementptr inbounds [[G_FRAME:%.*]], ptr [[INNERHDL_RELOAD]], i32 0, i32 4
; CHECK-NEXT: [[GVAR:%.*]] = load i32, ptr [[GVAR_ADDR]], align 4
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-defs-before-corobegin.ll b/llvm/test/Transforms/Coroutines/coro-spill-defs-before-corobegin.ll
index 7f14693052bd0..0c3b9aa49c919 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-defs-before-corobegin.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-defs-before-corobegin.ll
@@ -2,7 +2,8 @@
; Verifies that phi and invoke definitions before CoroBegin are spilled properly.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse,simplifycfg' -S | FileCheck %s
-; CHECK: %f.Frame = type { ptr, ptr, i32, i32, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
define ptr @f(i1 %n) presplitcoroutine personality i32 0 {
; CHECK-LABEL: define ptr @f(
@@ -15,15 +16,15 @@ define ptr @f(i1 %n) presplitcoroutine personality i32 0 {
; CHECK-NEXT: [[VALUE_INVOKE:%.*]] = call i32 @calc()
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[VALUE_INVOKE_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[VALUE_INVOKE_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 20
; CHECK-NEXT: store i32 [[VALUE_INVOKE]], ptr [[VALUE_INVOKE_SPILL_ADDR]], align 4
-; CHECK-NEXT: [[VALUE_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[VALUE_PHI_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i32 [[SPEC_SELECT]], ptr [[VALUE_PHI_SPILL_ADDR]], align 4
; CHECK-NEXT: [[TMP0:%.*]] = call i32 @print(i32 [[SPEC_SELECT]])
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @print(i32 [[VALUE_INVOKE]])
-; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR2:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 24
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR2]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll b/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
index 248dc9c1f7247..1211873500430 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-promise-02.ll
@@ -60,14 +60,13 @@ declare void @free(ptr)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 128)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
-; CHECK-NEXT: [[TMP1:%.*]] = load %"class.task::promise_type", ptr [[__PROMISE]], align 1
-; CHECK-NEXT: store %"class.task::promise_type" [[TMP1]], ptr [[TMP0]], align 1
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 64
+; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 64 [[TMP0]], ptr align 64 [[__PROMISE]], i64 64, i1 false)
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 20
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -75,8 +74,8 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 64 dereferenceable(128) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 64
; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
; CHECK-NEXT: call void @consume2(ptr [[__PROMISE_RELOAD_ADDR]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-promise.ll b/llvm/test/Transforms/Coroutines/coro-spill-promise.ll
index f57b67174eeb5..530bfa3ec1d48 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-promise.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-promise.ll
@@ -56,11 +56,11 @@ declare void @free(ptr)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 128)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 20
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -68,8 +68,8 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 64 dereferenceable(128) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 5
+; CHECK-NEXT: [[DATA_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
+; CHECK-NEXT: [[__PROMISE_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 64
; CHECK-NEXT: call void @consume(ptr [[DATA_RELOAD_ADDR]])
; CHECK-NEXT: call void @consume2(ptr [[__PROMISE_RELOAD_ADDR]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
diff --git a/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll b/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
index 8f33724a2d12e..35fd078643c89 100644
--- a/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
+++ b/llvm/test/Transforms/Coroutines/coro-spill-suspend.ll
@@ -4,9 +4,7 @@
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
; %sp1 should be part of the frame (the i8 value).
-;
; If the coro resumes, %sp1 is set to 0.
-;
; In the coro destroy function, %sp1 is reloaded from the frame. Its value
; depends on whether the coroutine was resumed or not.
define ptr @f(i32 %n) presplitcoroutine {
@@ -52,11 +50,11 @@ declare void @free(ptr)
; CHECK-NEXT: [[ALLOC:%.*]] = call ptr @malloc(i32 24)
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr @f.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR4:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR4]], align 1
-; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 17
; CHECK-NEXT: store i8 -1, ptr [[SP1_SPILL_ADDR]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -64,14 +62,14 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*]]:
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[INDEX:%.*]] = load i1, ptr [[INDEX_ADDR]], align 1
; CHECK-NEXT: switch i1 [[INDEX]], label %[[UNREACHABLE:.*]] [
; CHECK-NEXT: i1 false, label %[[AFTERCOROSUSPEND:.*]]
; CHECK-NEXT: i1 true, label %[[AFTERCOROSUSPEND3:.*]]
; CHECK-NEXT: ]
; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 17
; CHECK-NEXT: store i8 0, ptr [[SP1_SPILL_ADDR]], align 1
; CHECK-NEXT: store i1 true, ptr [[INDEX_ADDR]], align 1
; CHECK-NEXT: br label %[[AFTERCOROSUSPEND3]]
@@ -80,7 +78,7 @@ declare void @free(ptr)
; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[TMP0]], 0
; CHECK-NEXT: br i1 [[COND]], label %[[CLEANUP:.*]], label %[[COROEND:.*]]
; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[SP1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[SP1_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 17
; CHECK-NEXT: [[SP1_RELOAD:%.*]] = load i8, ptr [[SP1_RELOAD_ADDR]], align 1
; CHECK-NEXT: call void @print(i8 [[SP1_RELOAD]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
@@ -94,18 +92,18 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.destroy(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_DESTROY:.*:]]
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[INDEX:%.*]] = load i1, ptr [[INDEX_ADDR]], align 1
; CHECK-NEXT: switch i1 [[INDEX]], label %[[UNREACHABLE:.*]] [
; CHECK-NEXT: i1 false, label %[[AFTERCOROSUSPEND:.*]]
; CHECK-NEXT: i1 true, label %[[CLEANUP:.*]]
; CHECK-NEXT: ]
; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 17
; CHECK-NEXT: store i8 1, ptr [[SP1_SPILL_ADDR]], align 1
; CHECK-NEXT: br label %[[CLEANUP]]
; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[SP1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[SP1_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 17
; CHECK-NEXT: [[SP1_RELOAD:%.*]] = load i8, ptr [[SP1_RELOAD_ADDR]], align 1
; CHECK-NEXT: call void @print(i8 [[SP1_RELOAD]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
@@ -117,18 +115,18 @@ declare void @free(ptr)
; CHECK-LABEL: define internal fastcc void @f.cleanup(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_CLEANUP:.*:]]
-; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[INDEX_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: [[INDEX:%.*]] = load i1, ptr [[INDEX_ADDR]], align 1
; CHECK-NEXT: switch i1 [[INDEX]], label %[[UNREACHABLE:.*]] [
; CHECK-NEXT: i1 false, label %[[AFTERCOROSUSPEND:.*]]
; CHECK-NEXT: i1 true, label %[[CLEANUP:.*]]
; CHECK-NEXT: ]
; CHECK: [[AFTERCOROSUSPEND]]:
-; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[SP1_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 17
; CHECK-NEXT: store i8 1, ptr [[SP1_SPILL_ADDR]], align 1
; CHECK-NEXT: br label %[[CLEANUP]]
; CHECK: [[CLEANUP]]:
-; CHECK-NEXT: [[SP1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[SP1_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 17
; CHECK-NEXT: [[SP1_RELOAD:%.*]] = load i8, ptr [[SP1_RELOAD_ADDR]], align 1
; CHECK-NEXT: call void @print(i8 [[SP1_RELOAD]])
; CHECK-NEXT: call void @free(ptr null)
diff --git a/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll b/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
index 12dfa16991326..0d0ea4991146d 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
@@ -2,6 +2,8 @@
; Test that nested structs in coroutine frames have correct debug info scoping.
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
; Minimal nested struct types that used to trigger a scoping issue:
; we used to set the wrong `scope` for the `DIDerivedType` member entries of the `DICompositeType`
; as well as the `scope` for `DICompositeType` for the inner struct itself.
diff --git a/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll b/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
index 010c6b87b3c21..54a721b1365d8 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
@@ -69,12 +69,12 @@ declare void @free(ptr) willreturn allockind("free") "alloc-family"="malloc"
; CHECK-NEXT: [[HDL:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[PHI]])
; CHECK-NEXT: store ptr @f.resume, ptr [[HDL]], align 8
; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[NEED_ALLOC]], ptr @f.destroy, ptr @f.cleanup
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 8
; CHECK-NEXT: store ptr [[TMP0]], ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds [[F_FRAME]], ptr [[HDL]], i32 0, i32 2
+; CHECK-NEXT: [[X_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
; CHECK-NEXT: store i32 [[X]], ptr [[X_SPILL_ADDR]], align 4
; CHECK-NEXT: call void @print(i32 0)
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[F_FRAME]], ptr [[HDL]], i32 0, i32 3
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 20
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret ptr [[HDL]]
;
@@ -82,8 +82,8 @@ declare void @free(ptr) willreturn allockind("free") "alloc-family"="malloc"
; CHECK-LABEL: define internal fastcc void @f.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds [[F_FRAME:%.*]], ptr [[HDL]], i32 0, i32 2
-; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4, !tbaa [[F_FRAME_SLOT_TBAA4:![0-9]+]]
+; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
+; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4, !tbaa [[F.FRAME_SLOT_TBAA4:![0-9]+]]
; CHECK-NEXT: call void @print(i32 [[X_RELOAD]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
; CHECK-NEXT: ret void
@@ -106,6 +106,6 @@ declare void @free(ptr) willreturn allockind("free") "alloc-family"="malloc"
; CHECK: [[META1]] = !{!"int", [[META2:![0-9]+]], i64 0}
; CHECK: [[META2]] = !{!"omnipotent char", [[META3:![0-9]+]], i64 0}
; CHECK: [[META3]] = !{!"Simple C++ TBAA"}
-; CHECK: [[F_FRAME_SLOT_TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0}
+; CHECK: [[F.FRAME_SLOT_TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0}
; CHECK: [[META5]] = !{!"f.Frame Slot", [[META3]], i64 0}
;.
diff --git a/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll b/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll
index 973015fd13aff..5a0de393007c0 100644
--- a/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll
+++ b/llvm/test/Transforms/Coroutines/coro-zero-alloca.ll
@@ -60,9 +60,9 @@ cleanup: ; preds = %wakeup, %entry
; CHECK-NEXT: [[CORO_ALLOC:%.*]] = call ptr @malloc(i64 24)
; CHECK-NEXT: [[CORO_STATE:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[CORO_ID]], ptr [[CORO_ALLOC]])
; CHECK-NEXT: store ptr @foo.resume, ptr [[CORO_STATE]], align 8
-; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds nuw [[FOO_FRAME:%.*]], ptr [[CORO_STATE]], i32 0, i32 1
+; CHECK-NEXT: [[DESTROY_ADDR:%.*]] = getelementptr inbounds i8, ptr [[CORO_STATE]], i64 8
; CHECK-NEXT: store ptr @foo.destroy, ptr [[DESTROY_ADDR]], align 8
-; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds nuw [[FOO_FRAME]], ptr [[CORO_STATE]], i32 0, i32 4
+; CHECK-NEXT: [[INDEX_ADDR1:%.*]] = getelementptr inbounds i8, ptr [[CORO_STATE]], i64 22
; CHECK-NEXT: store i1 false, ptr [[INDEX_ADDR1]], align 1
; CHECK-NEXT: ret void
;
@@ -70,8 +70,8 @@ cleanup: ; preds = %wakeup, %entry
; CHECK-LABEL: define internal fastcc void @foo.resume(
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[CORO_STATE:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
-; CHECK-NEXT: [[A1_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME:%.*]], ptr [[CORO_STATE]], i32 0, i32 2
-; CHECK-NEXT: [[A4_RELOAD_ADDR:%.*]] = getelementptr inbounds [[FOO_FRAME]], ptr [[CORO_STATE]], i32 0, i32 3
+; CHECK-NEXT: [[A1_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[CORO_STATE]], i64 16
+; CHECK-NEXT: [[A4_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[CORO_STATE]], i64 20
; CHECK-NEXT: call void @usePointer(ptr [[CORO_STATE]])
; CHECK-NEXT: call void @usePointer(ptr [[A1_RELOAD_ADDR]])
; CHECK-NEXT: call void @usePointer(ptr [[CORO_STATE]])
>From d93b678652da720d3c2d552364e7aff87d27eca4 Mon Sep 17 00:00:00 2001
From: Jameson Nash <vtjnash at gmail.com>
Date: Fri, 13 Feb 2026 18:57:34 +0000
Subject: [PATCH 7/7] update remaining tests by hand
---
.../Coroutines/coro-alloca-outside-frame.ll | 5 ++--
llvm/test/Transforms/Coroutines/coro-async.ll | 4 +--
.../Coroutines/coro-debug-coro-frame.ll | 28 ++++++++++---------
.../Transforms/Coroutines/coro-materialize.ll | 13 +++++----
.../coro-split-dbg-nested-struct.ll | 2 --
.../Coroutines/coro-split-sink-lifetime-01.ll | 4 +--
.../Coroutines/coro-split-sink-lifetime-02.ll | 4 ++-
.../Coroutines/coro-split-tbaa-md.ll | 6 ++--
8 files changed, 36 insertions(+), 30 deletions(-)
diff --git a/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll b/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll
index e93e97fb06643..58d1aea739e3f 100644
--- a/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-alloca-outside-frame.ll
@@ -38,11 +38,10 @@ suspend:
}
; %y and %alias_phi would all go to the frame, but not %x
-; CHECK: %f.Frame = type { ptr, ptr, i64, ptr, i1 }
; CHECK-LABEL: @f(
; CHECK: %x = alloca i64, align 8, !coro.outside.frame !0
-; CHECK-NOT: %x.reload.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
-; CHECK: %y.reload.addr = getelementptr inbounds %f.Frame, ptr %hdl, i32 0, i32 2
+; CHECK-NOT: %x.reload.addr = getelementptr inbounds i8, ptr %hdl, i64 16
+; CHECK: %y.reload.addr = getelementptr inbounds i8, ptr %hdl, i64 16
; CHECK: %alias_phi = phi ptr [ %y.reload.addr, %merge.from.flag_false ], [ %x, %entry ]
declare ptr @llvm.coro.free(token, ptr)
diff --git a/llvm/test/Transforms/Coroutines/coro-async.ll b/llvm/test/Transforms/Coroutines/coro-async.ll
index f94c6c11aa8b1..2c2febde6758f 100644
--- a/llvm/test/Transforms/Coroutines/coro-async.ll
+++ b/llvm/test/Transforms/Coroutines/coro-async.ll
@@ -137,7 +137,7 @@ define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) {
; CHECK: store ptr %async.ctxt, ptr [[CALLEE_CTXT]]
; Make sure the spill is underaligned to the max context alignment (16).
; CHECK-O0: [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr {{.*}}
-; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1
+; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr {{.*}}, i64 32
; CHECK-O0: store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_ADDR]], align 16
; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor)
; CHECK: ret void
@@ -149,7 +149,7 @@ define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) {
; CHECK: entryresume.0:
; CHECK: [[CALLER_CONTEXT:%.*]] = load ptr, ptr %0
; CHECK: [[FRAME_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 128
-; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1
+; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr {{.*}}, i64 32
; CHECK-O0: load <4 x double>, ptr [[VECTOR_SPILL_ADDR]], align 16
; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds nuw i8, ptr [[CALLER_CONTEXT]], i64 160
; CHECK: [[CALLEE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]]
diff --git a/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll b/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
index f2aedefcfd381..28f8beddcdb7b 100644
--- a/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
+++ b/llvm/test/Transforms/Coroutines/coro-debug-coro-frame.ll
@@ -16,51 +16,53 @@
; CHECK-DAG: ![[RAMP:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov",
; CHECK-DAG: ![[CORO_FRAME]] = !DILocalVariable(name: "__coro_frame", scope: ![[RAMP]], file: ![[FILE]], line: [[CORO_FRAME_LINE:[0-9]+]], type: ![[FRAME_TYPE:[0-9]+]], flags: DIFlagArtificial)
; CHECK-DAG: ![[FRAME_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "f.coro_frame_ty", {{.*}}elements: ![[ELEMENTS:[0-9]+]]
-; CHECK-DAG: ![[ELEMENTS]] = !{![[RESUME_FN:[0-9]+]], ![[DESTROY_FN:[0-9]+]], ![[PROMISE:[0-9]+]], ![[VECTOR_TYPE:[0-9]+]], ![[INT64_0:[0-9]+]], ![[DOUBLE_1:[0-9]+]], ![[INT64_PTR:[0-9]+]], ![[INT32_2:[0-9]+]], ![[INT32_3:[0-9]+]], ![[UNALIGNED_UNKNOWN:[0-9]+]], ![[STRUCT:[0-9]+]], ![[CORO_INDEX:[0-9]+]], ![[SMALL_UNKNOWN:[0-9]+]]
+; CHECK-DAG: ![[ELEMENTS]] = !{![[RESUME_FN:[0-9]+]], ![[DESTROY_FN:[0-9]+]], ![[CORO_INDEX:[0-9]+]], ![[INT32_0:[0-9]+]], ![[INT32_1:[0-9]+]], ![[INT64_2:[0-9]+]], ![[DOUBLE_3:[0-9]+]], ![[INT64_PTR_4:[0-9]+]], ![[STRUCT_5:[0-9]+]], ![[VECTOR_TYPE_6:[0-9]+]], ![[SMALL_UNKNOWN_7:[0-9]+]], ![[UNALIGNED_UNKNOWN_8:[0-9]+]], ![[PROMISE:[0-9]+]]
; CHECK-DAG: ![[RESUME_FN]] = !DIDerivedType(tag: DW_TAG_member, name: "__resume_fn"{{.*}}, baseType: ![[RESUME_FN_TYPE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
; CHECK-DAG: ![[RESUME_FN_TYPE]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
; CHECK-DAG: ![[DESTROY_FN]] = !DIDerivedType(tag: DW_TAG_member, name: "__destroy_fn"{{.*}}, baseType: ![[RESUME_FN_TYPE]]{{.*}}, flags: DIFlagArtificial
; CHECK-DAG: ![[PROMISE]] = !DIDerivedType(tag: DW_TAG_member, name: "__promise",{{.*}}baseType: ![[PROMISE_BASE:[0-9]+]]
; CHECK-DAG: ![[PROMISE_BASE]] = !DIDerivedType(tag: DW_TAG_typedef, name: "promise_type"
-; CHECK-DAG: ![[VECTOR_TYPE]] = !DIDerivedType(tag: DW_TAG_member, name: "_0",{{.*}}baseType: ![[VECTOR_TYPE_BASE:[0-9]+]], size: 128
+; CHECK-DAG: ![[VECTOR_TYPE_6]] = !DIDerivedType(tag: DW_TAG_member, name: "_6",{{.*}}baseType: ![[VECTOR_TYPE_BASE:[0-9]+]], size: 128
; CHECK-DAG: ![[VECTOR_TYPE_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE:[0-9]+]], size: 128, align: 16, elements: ![[VECTOR_TYPE_BASE_ELEMENTS:[0-9]+]])
; CHECK-DAG: ![[UNKNOWN_TYPE_BASE]] = !DIBasicType(name: "UnknownType", size: 8, encoding: DW_ATE_unsigned_char, flags: DIFlagArtificial)
; CHECK-DAG: ![[VECTOR_TYPE_BASE_ELEMENTS]] = !{![[VECTOR_TYPE_BASE_SUBRANGE:[0-9]+]]}
; CHECK-DAG: ![[VECTOR_TYPE_BASE_SUBRANGE]] = !DISubrange(count: 16, lowerBound: 0)
-; CHECK-DAG: ![[INT64_0]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I64_BASE:[0-9]+]],{{.*}}, flags: DIFlagArtificial
+; CHECK-DAG: ![[INT64_2]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_2", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I64_BASE:[0-9]+]],{{.*}}, flags: DIFlagArtificial
; CHECK-DAG: ![[I64_BASE]] = !DIBasicType(name: "__int_64", size: 64, encoding: DW_ATE_signed, flags: DIFlagArtificial)
-; CHECK-DAG: ![[DOUBLE_1]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[DOUBLE_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
+; CHECK-DAG: ![[DOUBLE_3]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__3", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[DOUBLE_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
; CHECK-DAG: ![[DOUBLE_BASE]] = !DIBasicType(name: "__double_", size: 64, encoding: DW_ATE_float, flags: DIFlagArtificial)
-; CHECK-DAG: ![[INT32_2]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I32_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
+; CHECK-DAG: ![[INT32_0]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_0", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I32_BASE:[0-9]+]]{{.*}}, flags: DIFlagArtificial
; CHECK-DAG: ![[I32_BASE]] = !DIBasicType(name: "__int_32", size: 32, encoding: DW_ATE_signed, flags: DIFlagArtificial)
-; CHECK-DAG: ![[INT32_3]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_5", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I32_BASE]]
-; CHECK-DAG: ![[UNALIGNED_UNKNOWN]] = !DIDerivedType(tag: DW_TAG_member, name: "_6",{{.*}}baseType: ![[UNALIGNED_UNKNOWN_BASE:[0-9]+]], size: 9
+; CHECK-DAG: ![[INT32_1]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_1", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[I32_BASE]]
+; CHECK-DAG: ![[UNALIGNED_UNKNOWN_8]] = !DIDerivedType(tag: DW_TAG_member, name: "_8",{{.*}}baseType: ![[UNALIGNED_UNKNOWN_BASE:[0-9]+]], size: 16
; CHECK-DAG: ![[UNALIGNED_UNKNOWN_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE]], size: 16,{{.*}} elements: ![[UNALIGNED_UNKNOWN_ELEMENTS:[0-9]+]])
; CHECK-DAG: ![[UNALIGNED_UNKNOWN_ELEMENTS]] = !{![[UNALIGNED_UNKNOWN_SUBRANGE:[0-9]+]]}
; CHECK-DAG: ![[UNALIGNED_UNKNOWN_SUBRANGE]] = !DISubrange(count: 2, lowerBound: 0)
-; CHECK-DAG: ![[STRUCT]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_7", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[STRUCT_BASE:[0-9]+]]
+; CHECK-DAG: ![[STRUCT_5]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_5", scope: ![[FRAME_TYPE]], file: ![[FILE]], line: [[CORO_FRAME_LINE]], baseType: ![[STRUCT_BASE:[0-9]+]]
; CHECK-DAG: ![[STRUCT_BASE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure"{{.*}}, align: 64, flags: DIFlagArtificial, elements: ![[STRUCT_ELEMENTS:[0-9]+]]
; CHECK-DAG: ![[STRUCT_ELEMENTS]] = !{![[MEM_TYPE:[0-9]+]]}
; CHECK-DAG: ![[MEM_TYPE]] = !DIDerivedType(tag: DW_TAG_member,{{.*}} baseType: ![[MEM_TYPE_BASE:[0-9]+]], size: 4000
; CHECK-DAG: ![[MEM_TYPE_BASE]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[UNKNOWN_TYPE_BASE]], size: 4000,
; CHECK-DAG: ![[CORO_INDEX]] = !DIDerivedType(tag: DW_TAG_member, name: "__coro_index"
-; CHECK-DAG: ![[SMALL_UNKNOWN]] = !DIDerivedType(tag: DW_TAG_member, name: "UnknownType_8",{{.*}} baseType: ![[UNKNOWN_TYPE_BASE]], size: 5
+; CHECK-DAG: ![[SMALL_UNKNOWN_7]] = !DIDerivedType(tag: DW_TAG_member, name: "UnknownType_7",{{.*}} baseType: ![[UNKNOWN_TYPE_BASE]], size: 8
; CHECK-DAG: ![[PROMISE_VAR:[0-9]+]] = !DILocalVariable(name: "__promise", scope: ![[RAMP_SCOPE:[0-9]+]], file: ![[FILE]]
; CHECK-DAG: ![[RAMP_SCOPE]] = distinct !DILexicalBlock(scope: ![[RAMP]], file: ![[FILE]], line: 23
; CHECK-DAG: ![[BAR_FUNC:[0-9]+]] = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv",
; CHECK-DAG: ![[BAR_SCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[BAR_FUNC]], file: !1
; CHECK-DAG: ![[FRAME_TYPE_IN_BAR:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "bar.coro_frame_ty", file: ![[FILE]], line: [[BAR_LINE:[0-9]+]]{{.*}}elements: ![[ELEMENTS_IN_BAR:[0-9]+]]
-; CHECK-DAG: ![[ELEMENTS_IN_BAR]] = !{![[RESUME_FN_IN_BAR:[0-9]+]], ![[DESTROY_FN_IN_BAR:[0-9]+]], ![[PROMISE_IN_BAR:[0-9]+]], ![[VECTOR_TYPE_IN_BAR:[0-9]+]], ![[INT64_IN_BAR:[0-9]+]], ![[DOUBLE_IN_BAR:[0-9]+]], ![[INT64_PTR_IN_BAR:[0-9]+]], ![[INT32_IN_BAR:[0-9]+]], ![[STRUCT_IN_BAR:[0-9]+]], ![[CORO_INDEX_IN_BAR:[0-9]+]]
+; CHECK-DAG: ![[ELEMENTS_IN_BAR]] = !{![[RESUME_FN_IN_BAR:[0-9]+]], ![[DESTROY_FN_IN_BAR:[0-9]+]], ![[CORO_INDEX_IN_BAR:[0-9]+]], ![[INT32_IN_BAR:[0-9]+]], ![[INT64_IN_BAR:[0-9]+]], ![[DOUBLE_IN_BAR:[0-9]+]], ![[INT64_PTR_IN_BAR:[0-9]+]], ![[STRUCT_IN_BAR:[0-9]+]], ![[VECTOR_TYPE_IN_BAR:[0-9]+]], ![[PROMISE_IN_BAR:[0-9]+]]
; CHECK-DAG: ![[PROMISE_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__promise",{{.*}}baseType: ![[PROMISE_BASE]]
-; CHECK-DAG: ![[VECTOR_TYPE_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "_0", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[VECTOR_TYPE_BASE]]
+; CHECK-DAG: ![[VECTOR_TYPE_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "_5", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[VECTOR_TYPE_BASE]]
; CHECK-DAG: ![[INT64_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_64_1", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[I64_BASE]]
; CHECK-DAG: ![[DOUBLE_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__double__2", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[DOUBLE_BASE]]
-; CHECK-DAG: ![[INT32_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_4", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[I32_BASE]]
-; CHECK-DAG: ![[STRUCT_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_5", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[STRUCT_BASE_IN_BAR:[0-9]+]]
+; CHECK-DAG: ![[INT32_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "__int_32_0", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[I32_BASE]]
+; CHECK-DAG: ![[STRUCT_IN_BAR]] = !DIDerivedType(tag: DW_TAG_member, name: "struct_big_structure_4", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]], baseType: ![[STRUCT_BASE_IN_BAR:[0-9]+]]
; CHECK-DAG: ![[STRUCT_BASE_IN_BAR]] = !DICompositeType(tag: DW_TAG_structure_type, name: "struct_big_structure", scope: ![[FRAME_TYPE_IN_BAR]], file: ![[FILE]], line: [[BAR_LINE]],{{.*}}, align: 64
; CHECK-DAG: ![[CORO_FRAME_IN_RESUME]] = !DILocalVariable(name: "__coro_frame",{{.*}}type: ![[FRAME_TYPE]]
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
%promise_type = type { i32, i32, double }
%struct.big_structure = type { [500 x i8] }
declare void @produce(ptr)
diff --git a/llvm/test/Transforms/Coroutines/coro-materialize.ll b/llvm/test/Transforms/Coroutines/coro-materialize.ll
index f55db35edb3ea..abe8c61117c6d 100644
--- a/llvm/test/Transforms/Coroutines/coro-materialize.ll
+++ b/llvm/test/Transforms/Coroutines/coro-materialize.ll
@@ -2,17 +2,20 @@
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
; See that we only spilled one value for f
-; CHECK: %f.Frame = type { ptr, ptr, i32, i1 }
-; CHECK: %f_optnone.Frame = type { ptr, ptr, i32, i32, i1 }
; Check other variants where different levels of materialization are achieved
-; CHECK: %f_multiple_remat.Frame = type { ptr, ptr, i32, i1 }
-; CHECK: %f_common_def.Frame = type { ptr, ptr, i32, i1 }
-; CHECK: %f_common_def_multi_result.Frame = type { ptr, ptr, i32, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
; CHECK-LABEL: @f(
+; CHECK: malloc(i32 24)
; CHECK-LABEL: @f_optnone
+; CHECK: malloc(i32 32)
; CHECK-LABEL: @f_multiple_remat(
+; CHECK: malloc(i32 24)
; CHECK-LABEL: @f_common_def(
+; CHECK: malloc(i32 24)
; CHECK-LABEL: @f_common_def_multi_result(
+; CHECK: malloc(i32 24)
define ptr @f(i32 %n) presplitcoroutine {
entry:
diff --git a/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll b/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
index 0d0ea4991146d..12dfa16991326 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-dbg-nested-struct.ll
@@ -2,8 +2,6 @@
; Test that nested structs in coroutine frames have correct debug info scoping.
-target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
-
; Minimal nested struct types that used to trigger a scoping issue:
; we used to set the wrong `scope` for the `DIDerivedType` member entries of the `DICompositeType`
; as well as the `scope` for `DICompositeType` for the inner struct itself.
diff --git a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
index 848cf8b3e461f..8fcfcd49caa7d 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-01.ll
@@ -2,8 +2,8 @@
; sink them to the places after the suspend block.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse,simplifycfg' -S | FileCheck %s
-; CHECK: %a.Frame = type { ptr, ptr, i1 }
-; CHECK: %a_optnone.Frame = type { ptr, ptr, i32, i1 }
+
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
%"struct.std::coroutine_handle" = type { ptr }
%"struct.std::coroutine_handle.0" = type { %"struct.std::coroutine_handle" }
diff --git a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
index 26037043a26ed..c5a69a584d496 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-sink-lifetime-02.ll
@@ -2,6 +2,8 @@
; sink them to the places after the suspend block.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
%"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" }
@@ -53,7 +55,7 @@ exit:
}
; CHECK-LABEL: @a.resume(
-; CHECK: %[[VAL:testval.+]] = getelementptr inbounds %a.Frame
+; CHECK: %[[VAL:testval.+]] = getelementptr inbounds i8
; CHECK-NOT: call void @llvm.lifetime.start.p0(ptr %{{.*}})
; CHECK: %test = load i32, ptr %[[VAL]]
diff --git a/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll b/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
index 54a721b1365d8..ec4c4c42769b0 100644
--- a/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
+++ b/llvm/test/Transforms/Coroutines/coro-split-tbaa-md.ll
@@ -2,6 +2,8 @@
; Tests that coro-split pass generates TBAA metadata on coroutine frame slot reloads.
; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
+target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
define ptr @f(ptr %p) presplitcoroutine {
entry:
%x = load i32, ptr %p, !tbaa !3
@@ -83,7 +85,7 @@ declare void @free(ptr) willreturn allockind("free") "alloc-family"="malloc"
; CHECK-SAME: ptr noundef nonnull align 8 dereferenceable(24) [[HDL:%.*]]) {
; CHECK-NEXT: [[ENTRY_RESUME:.*:]]
; CHECK-NEXT: [[X_RELOAD_ADDR:%.*]] = getelementptr inbounds i8, ptr [[HDL]], i64 16
-; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4, !tbaa [[F.FRAME_SLOT_TBAA4:![0-9]+]]
+; CHECK-NEXT: [[X_RELOAD:%.*]] = load i32, ptr [[X_RELOAD_ADDR]], align 4, !tbaa [[F_FRAME_SLOT_TBAA4:![0-9]+]]
; CHECK-NEXT: call void @print(i32 [[X_RELOAD]])
; CHECK-NEXT: call void @free(ptr [[HDL]])
; CHECK-NEXT: ret void
@@ -106,6 +108,6 @@ declare void @free(ptr) willreturn allockind("free") "alloc-family"="malloc"
; CHECK: [[META1]] = !{!"int", [[META2:![0-9]+]], i64 0}
; CHECK: [[META2]] = !{!"omnipotent char", [[META3:![0-9]+]], i64 0}
; CHECK: [[META3]] = !{!"Simple C++ TBAA"}
-; CHECK: [[F.FRAME_SLOT_TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0}
+; CHECK: [[F_FRAME_SLOT_TBAA4]] = !{[[META5:![0-9]+]], [[META5]], i64 0}
; CHECK: [[META5]] = !{!"f.Frame Slot", [[META3]], i64 0}
;.
More information about the cfe-commits
mailing list