1; Verifies that we materialize instruction across suspend points 2; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s 3 4; See that we only spilled one value for f 5; CHECK: %f.Frame = type { ptr, ptr, i32, i1 } 6; CHECK: %f_optnone.Frame = type { ptr, ptr, i32, i32, i1 } 7; Check other variants where different levels of materialization are achieved 8; CHECK: %f_multiple_remat.Frame = type { ptr, ptr, i32, i1 } 9; CHECK: %f_common_def.Frame = type { ptr, ptr, i32, i1 } 10; CHECK: %f_common_def_multi_result.Frame = type { ptr, ptr, i32, i1 } 11; CHECK-LABEL: @f( 12; CHECK-LABEL: @f_optnone 13; CHECK-LABEL: @f_multiple_remat( 14; CHECK-LABEL: @f_common_def( 15; CHECK-LABEL: @f_common_def_multi_result( 16 17define ptr @f(i32 %n) presplitcoroutine { 18entry: 19 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) 20 %size = call i32 @llvm.coro.size.i32() 21 %alloc = call ptr @malloc(i32 %size) 22 %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc) 23 24 %inc1 = add i32 %n, 1 25 %sp1 = call i8 @llvm.coro.suspend(token none, i1 false) 26 switch i8 %sp1, label %suspend [i8 0, label %resume1 27 i8 1, label %cleanup] 28resume1: 29 %inc2 = add i32 %inc1, 1 30 %sp2 = call i8 @llvm.coro.suspend(token none, i1 false) 31 switch i8 %sp1, label %suspend [i8 0, label %resume2 32 i8 1, label %cleanup] 33 34resume2: 35 call void @print(i32 %inc1) 36 call void @print(i32 %inc2) 37 br label %cleanup 38 39cleanup: 40 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl) 41 call void @free(ptr %mem) 42 br label %suspend 43suspend: 44 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) 45 ret ptr %hdl 46} 47 48; Checks that we won't transform functions with optnone. 49define ptr @f_optnone(i32 %n) presplitcoroutine optnone noinline { 50entry: 51 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) 52 %size = call i32 @llvm.coro.size.i32() 53 %alloc = call ptr @malloc(i32 %size) 54 %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc) 55 56 %inc1 = add i32 %n, 1 57 %sp1 = call i8 @llvm.coro.suspend(token none, i1 false) 58 switch i8 %sp1, label %suspend [i8 0, label %resume1 59 i8 1, label %cleanup] 60resume1: 61 %inc2 = add i32 %inc1, 1 62 %sp2 = call i8 @llvm.coro.suspend(token none, i1 false) 63 switch i8 %sp1, label %suspend [i8 0, label %resume2 64 i8 1, label %cleanup] 65 66resume2: 67 call void @print(i32 %inc1) 68 call void @print(i32 %inc2) 69 br label %cleanup 70 71cleanup: 72 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl) 73 call void @free(ptr %mem) 74 br label %suspend 75suspend: 76 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) 77 ret ptr %hdl 78} 79 80define ptr @f_multiple_remat(i32 %n) presplitcoroutine { 81entry: 82 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) 83 %size = call i32 @llvm.coro.size.i32() 84 %alloc = call ptr @malloc(i32 %size) 85 %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc) 86 87 %inc1 = add i32 %n, 1 88 %inc2 = add i32 %inc1, 2 89 %inc3 = add i32 %inc2, 3 90 %inc4 = add i32 %inc3, 4 91 %inc5 = add i32 %inc4, 5 92 %inc6 = add i32 %inc5, 5 93 %sp1 = call i8 @llvm.coro.suspend(token none, i1 false) 94 switch i8 %sp1, label %suspend [i8 0, label %resume1 95 i8 1, label %cleanup] 96resume1: 97 %inc7 = add i32 %inc6, 1 98 %sp2 = call i8 @llvm.coro.suspend(token none, i1 false) 99 switch i8 %sp1, label %suspend [i8 0, label %resume2 100 i8 1, label %cleanup] 101 102resume2: 103 call void @print(i32 %inc1) 104 call void @print(i32 %inc7) 105 br label %cleanup 106 107cleanup: 108 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl) 109 call void @free(ptr %mem) 110 br label %suspend 111suspend: 112 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) 113 ret ptr %hdl 114} 115 116define ptr @f_common_def(i32 %n) presplitcoroutine { 117entry: 118 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) 119 %size = call i32 @llvm.coro.size.i32() 120 %alloc = call ptr @malloc(i32 %size) 121 %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc) 122 123 %inc1 = add i32 %n, 1 124 %inc2 = add i32 %inc1, 2 125 %inc3 = add i32 %n, 3 126 %inc4 = add i32 %inc3, %inc1 127 %inc5 = add i32 %inc4, %inc1 128 %inc6 = add i32 %inc5, 5 129 %sp1 = call i8 @llvm.coro.suspend(token none, i1 false) 130 switch i8 %sp1, label %suspend [i8 0, label %resume1 131 i8 1, label %cleanup] 132resume1: 133 %inc7 = add i32 %inc6, 1 134 %sp2 = call i8 @llvm.coro.suspend(token none, i1 false) 135 switch i8 %sp1, label %suspend [i8 0, label %resume2 136 i8 1, label %cleanup] 137 138resume2: 139 call void @print(i32 %inc1) 140 call void @print(i32 %inc7) 141 br label %cleanup 142 143cleanup: 144 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl) 145 call void @free(ptr %mem) 146 br label %suspend 147suspend: 148 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) 149 ret ptr %hdl 150} 151 152define ptr @f_common_def_multi_result(i32 %n) presplitcoroutine { 153entry: 154 %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) 155 %size = call i32 @llvm.coro.size.i32() 156 %alloc = call ptr @malloc(i32 %size) 157 %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc) 158 159 %inc1 = add i32 %n, 1 160 %inc2 = add i32 %inc1, 2 161 %inc3 = add i32 %n, 3 162 %inc4 = add i32 %inc3, %inc1 163 %inc5 = add i32 %inc4, %inc1 164 %inc6 = add i32 %inc5, 4 165 %inc7 = add i32 %inc6, 5 166 %inc8 = add i32 %inc4, %inc2 167 %inc9 = add i32 %inc8, 5 168 %inc10 = add i32 %inc9, 6 169 %inc11 = add i32 %inc10, 7 170 %sp1 = call i8 @llvm.coro.suspend(token none, i1 false) 171 switch i8 %sp1, label %suspend [i8 0, label %resume1 172 i8 1, label %cleanup] 173resume1: 174 %inc12 = add i32 %inc7, 1 175 %sp2 = call i8 @llvm.coro.suspend(token none, i1 false) 176 switch i8 %sp1, label %suspend [i8 0, label %resume2 177 i8 1, label %cleanup] 178 179resume2: 180 call void @print(i32 %inc11) 181 call void @print(i32 %inc12) 182 br label %cleanup 183 184cleanup: 185 %mem = call ptr @llvm.coro.free(token %id, ptr %hdl) 186 call void @free(ptr %mem) 187 br label %suspend 188suspend: 189 call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) 190 ret ptr %hdl 191} 192 193 194declare ptr @llvm.coro.free(token, ptr) 195declare i32 @llvm.coro.size.i32() 196declare i8 @llvm.coro.suspend(token, i1) 197declare void @llvm.coro.resume(ptr) 198declare void @llvm.coro.destroy(ptr) 199 200declare token @llvm.coro.id(i32, ptr, ptr, ptr) 201declare i1 @llvm.coro.alloc(token) 202declare ptr @llvm.coro.begin(token, ptr) 203declare i1 @llvm.coro.end(ptr, i1, token) 204 205declare noalias ptr @malloc(i32) 206declare void @print(i32) 207declare void @free(ptr) 208