David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 1 | ; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 2 | |
| 3 | declare i32 @__CxxFrameHandler3(...) |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 4 | declare i32 @__C_specific_handler(...) |
Joseph Tremoulet | 71e5676 | 2016-01-02 15:22:36 +0000 | [diff] [blame] | 5 | declare void @ProcessCLRException(...) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 6 | |
| 7 | declare void @f() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 8 | |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 9 | declare void @llvm.foo(i32) nounwind |
| 10 | declare void @llvm.bar() nounwind |
| 11 | declare i32 @llvm.qux() nounwind |
| 12 | declare i1 @llvm.baz() nounwind |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 13 | |
| 14 | define void @test1() personality i32 (...)* @__CxxFrameHandler3 { |
| 15 | entry: |
| 16 | ; %x def colors: {entry} subset of use colors; must spill |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 17 | %x = call i32 @llvm.qux() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 18 | invoke void @f() |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 19 | to label %noreturn unwind label %catch.switch |
| 20 | catch.switch: |
| 21 | %cs = catchswitch within none [label %catch] unwind to caller |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 22 | catch: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 23 | %cp = catchpad within %cs [] |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 24 | br label %noreturn |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 25 | noreturn: |
| 26 | ; %x use colors: {entry, cleanup} |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 27 | call void @llvm.foo(i32 %x) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 28 | unreachable |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 29 | } |
| 30 | ; Need two copies of the call to @h, one under entry and one under catch. |
| 31 | ; Currently we generate a load for each, though we shouldn't need one |
| 32 | ; for the use in entry's copy. |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 33 | ; CHECK-LABEL: define void @test1( |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 34 | ; CHECK: entry: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 35 | ; CHECK: %x = call i32 @llvm.qux() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 36 | ; CHECK: invoke void @f() |
| 37 | ; CHECK: to label %[[EntryCopy:[^ ]+]] unwind label %catch |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 38 | ; CHECK: catch.switch: |
| 39 | ; CHECK: %cs = catchswitch within none [label %catch] unwind to caller |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 40 | ; CHECK: catch: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 41 | ; CHECK: catchpad within %cs [] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 42 | ; CHECK-NEXT: call void @llvm.foo(i32 %x) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 43 | ; CHECK: [[EntryCopy]]: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 44 | ; CHECK: call void @llvm.foo(i32 %x) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 45 | |
| 46 | |
David Majnemer | 784d4a4 | 2016-02-01 03:29:38 +0000 | [diff] [blame] | 47 | define void @test2() personality i32 (...)* @__CxxFrameHandler3 { |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 48 | entry: |
| 49 | invoke void @f() |
| 50 | to label %exit unwind label %cleanup |
| 51 | cleanup: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 52 | cleanuppad within none [] |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 53 | br label %exit |
| 54 | exit: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 55 | call void @llvm.bar() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 56 | ret void |
| 57 | } |
| 58 | ; Need two copies of %exit's call to @f -- the subsequent ret is only |
| 59 | ; valid when coming from %entry, but on the path from %cleanup, this |
| 60 | ; might be a valid call to @f which might dynamically not return. |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 61 | ; CHECK-LABEL: define void @test2( |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 62 | ; CHECK: entry: |
| 63 | ; CHECK: invoke void @f() |
| 64 | ; CHECK: to label %[[exit:[^ ]+]] unwind label %cleanup |
| 65 | ; CHECK: cleanup: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 66 | ; CHECK: cleanuppad within none [] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 67 | ; CHECK: call void @llvm.bar() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 68 | ; CHECK-NEXT: unreachable |
| 69 | ; CHECK: [[exit]]: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 70 | ; CHECK: call void @llvm.bar() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 71 | ; CHECK-NEXT: ret void |
| 72 | |
| 73 | |
David Majnemer | 784d4a4 | 2016-02-01 03:29:38 +0000 | [diff] [blame] | 74 | define void @test3() personality i32 (...)* @__CxxFrameHandler3 { |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 75 | entry: |
| 76 | invoke void @f() |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 77 | to label %invoke.cont unwind label %catch.switch |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 78 | invoke.cont: |
| 79 | invoke void @f() |
| 80 | to label %exit unwind label %cleanup |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 81 | catch.switch: |
| 82 | %cs = catchswitch within none [label %catch] unwind to caller |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 83 | catch: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 84 | catchpad within %cs [] |
| 85 | br label %shared |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 86 | cleanup: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 87 | cleanuppad within none [] |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 88 | br label %shared |
| 89 | shared: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 90 | call void @llvm.bar() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 91 | br label %exit |
| 92 | exit: |
| 93 | ret void |
| 94 | } |
| 95 | ; Need two copies of %shared's call to @f (similar to @test2 but |
| 96 | ; the two regions here are siblings, not parent-child). |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 97 | ; CHECK-LABEL: define void @test3( |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 98 | ; CHECK: invoke void @f() |
| 99 | ; CHECK: invoke void @f() |
| 100 | ; CHECK: to label %[[exit:[^ ]+]] unwind |
| 101 | ; CHECK: catch: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 102 | ; CHECK: catchpad within %cs [] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 103 | ; CHECK-NEXT: call void @llvm.bar() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 104 | ; CHECK-NEXT: unreachable |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 105 | ; CHECK: cleanup: |
| 106 | ; CHECK: cleanuppad within none [] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 107 | ; CHECK: call void @llvm.bar() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 108 | ; CHECK-NEXT: unreachable |
| 109 | ; CHECK: [[exit]]: |
| 110 | ; CHECK: ret void |
| 111 | |
| 112 | |
| 113 | define void @test4() personality i32 (...)* @__CxxFrameHandler3 { |
| 114 | entry: |
| 115 | invoke void @f() |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 116 | to label %shared unwind label %catch.switch |
| 117 | catch.switch: |
| 118 | %cs = catchswitch within none [label %catch] unwind to caller |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 119 | catch: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 120 | catchpad within %cs [] |
| 121 | br label %shared |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 122 | shared: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 123 | %x = call i32 @llvm.qux() |
| 124 | %i = call i32 @llvm.qux() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 125 | %zero.trip = icmp eq i32 %i, 0 |
| 126 | br i1 %zero.trip, label %exit, label %loop |
| 127 | loop: |
| 128 | %i.loop = phi i32 [ %i, %shared ], [ %i.dec, %loop.tail ] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 129 | %b = call i1 @llvm.baz() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 130 | br i1 %b, label %left, label %right |
| 131 | left: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 132 | %y = call i32 @llvm.qux() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 133 | br label %loop.tail |
| 134 | right: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 135 | call void @llvm.foo(i32 %x) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 136 | br label %loop.tail |
| 137 | loop.tail: |
| 138 | %i.dec = sub i32 %i.loop, 1 |
| 139 | %done = icmp eq i32 %i.dec, 0 |
| 140 | br i1 %done, label %exit, label %loop |
| 141 | exit: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 142 | call void @llvm.foo(i32 %x) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 143 | unreachable |
| 144 | } |
| 145 | ; Make sure we can clone regions that have internal control |
| 146 | ; flow and SSA values. Here we need two copies of everything |
| 147 | ; from %shared to %exit. |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 148 | ; CHECK-LABEL: define void @test4( |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 149 | ; CHECK: entry: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 150 | ; CHECK: to label %[[shared_E:[^ ]+]] unwind label %catch.switch |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 151 | ; CHECK: catch: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 152 | ; CHECK: catchpad within %cs [] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 153 | ; CHECK: [[x_C:%[^ ]+]] = call i32 @llvm.qux() |
| 154 | ; CHECK: [[i_C:%[^ ]+]] = call i32 @llvm.qux() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 155 | ; CHECK: [[zt_C:%[^ ]+]] = icmp eq i32 [[i_C]], 0 |
| 156 | ; CHECK: br i1 [[zt_C]], label %[[exit_C:[^ ]+]], label %[[loop_C:[^ ]+]] |
| 157 | ; CHECK: [[shared_E]]: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 158 | ; CHECK: [[x_E:%[^ ]+]] = call i32 @llvm.qux() |
| 159 | ; CHECK: [[i_E:%[^ ]+]] = call i32 @llvm.qux() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 160 | ; CHECK: [[zt_E:%[^ ]+]] = icmp eq i32 [[i_E]], 0 |
| 161 | ; CHECK: br i1 [[zt_E]], label %[[exit_E:[^ ]+]], label %[[loop_E:[^ ]+]] |
| 162 | ; CHECK: [[loop_C]]: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 163 | ; CHECK: [[iloop_C:%[^ ]+]] = phi i32 [ [[i_C]], %catch ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 164 | ; CHECK: [[b_C:%[^ ]+]] = call i1 @llvm.baz() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 165 | ; CHECK: br i1 [[b_C]], label %[[left_C:[^ ]+]], label %[[right_C:[^ ]+]] |
| 166 | ; CHECK: [[loop_E]]: |
| 167 | ; CHECK: [[iloop_E:%[^ ]+]] = phi i32 [ [[i_E]], %[[shared_E]] ], [ [[idec_E:%[^ ]+]], %[[looptail_E:[^ ]+]] ] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 168 | ; CHECK: [[b_E:%[^ ]+]] = call i1 @llvm.baz() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 169 | ; CHECK: br i1 [[b_E]], label %[[left_E:[^ ]+]], label %[[right_E:[^ ]+]] |
| 170 | ; CHECK: [[left_C]]: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 171 | ; CHECK: [[y_C:%[^ ]+]] = call i32 @llvm.qux() |
Hans Wennborg | 4a61370 | 2015-08-31 21:10:35 +0000 | [diff] [blame] | 172 | ; CHECK: br label %[[looptail_C]] |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 173 | ; CHECK: [[left_E]]: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 174 | ; CHECK: [[y_E:%[^ ]+]] = call i32 @llvm.qux() |
Hans Wennborg | 4a61370 | 2015-08-31 21:10:35 +0000 | [diff] [blame] | 175 | ; CHECK: br label %[[looptail_E]] |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 176 | ; CHECK: [[right_C]]: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 177 | ; CHECK: call void @llvm.foo(i32 [[x_C]]) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 178 | ; CHECK: br label %[[looptail_C]] |
| 179 | ; CHECK: [[right_E]]: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 180 | ; CHECK: call void @llvm.foo(i32 [[x_E]]) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 181 | ; CHECK: br label %[[looptail_E]] |
| 182 | ; CHECK: [[looptail_C]]: |
| 183 | ; CHECK: [[idec_C]] = sub i32 [[iloop_C]], 1 |
| 184 | ; CHECK: [[done_C:%[^ ]+]] = icmp eq i32 [[idec_C]], 0 |
| 185 | ; CHECK: br i1 [[done_C]], label %[[exit_C]], label %[[loop_C]] |
| 186 | ; CHECK: [[looptail_E]]: |
| 187 | ; CHECK: [[idec_E]] = sub i32 [[iloop_E]], 1 |
| 188 | ; CHECK: [[done_E:%[^ ]+]] = icmp eq i32 [[idec_E]], 0 |
| 189 | ; CHECK: br i1 [[done_E]], label %[[exit_E]], label %[[loop_E]] |
| 190 | ; CHECK: [[exit_C]]: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 191 | ; CHECK: call void @llvm.foo(i32 [[x_C]]) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 192 | ; CHECK: unreachable |
| 193 | ; CHECK: [[exit_E]]: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 194 | ; CHECK: call void @llvm.foo(i32 [[x_E]]) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 195 | ; CHECK: unreachable |
| 196 | |
| 197 | |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 198 | define void @test5() personality i32 (...)* @__C_specific_handler { |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 199 | entry: |
| 200 | invoke void @f() |
| 201 | to label %exit unwind label %outer |
| 202 | outer: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 203 | %o = cleanuppad within none [] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 204 | %x = call i32 @llvm.qux() |
| 205 | invoke void @f() [ "funclet"(token %o) ] |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 206 | to label %outer.ret unwind label %catch.switch |
| 207 | catch.switch: |
| 208 | %cs = catchswitch within %o [label %inner] unwind to caller |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 209 | inner: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 210 | %i = catchpad within %cs [] |
| 211 | catchret from %i to label %outer.post-inner |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 212 | outer.post-inner: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 213 | call void @llvm.foo(i32 %x) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 214 | br label %outer.ret |
| 215 | outer.ret: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 216 | cleanupret from %o unwind to caller |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 217 | exit: |
| 218 | ret void |
| 219 | } |
| 220 | ; Simple nested case (catch-inside-cleanup). Nothing needs |
| 221 | ; to be cloned. The def and use of %x are both in %outer |
| 222 | ; and so don't need to be spilled. |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 223 | ; CHECK-LABEL: define void @test5( |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 224 | ; CHECK: outer: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 225 | ; CHECK: %x = call i32 @llvm.qux() |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 226 | ; CHECK-NEXT: invoke void @f() |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 227 | ; CHECK-NEXT: to label %outer.ret unwind label %catch.switch |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 228 | ; CHECK: inner: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 229 | ; CHECK-NEXT: %i = catchpad within %cs [] |
| 230 | ; CHECK-NEXT: catchret from %i to label %outer.post-inner |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 231 | ; CHECK: outer.post-inner: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 232 | ; CHECK-NEXT: call void @llvm.foo(i32 %x) |
Joseph Tremoulet | ec18285 | 2015-08-28 01:12:35 +0000 | [diff] [blame] | 233 | ; CHECK-NEXT: br label %outer.ret |
| 234 | |
| 235 | |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 236 | define void @test10() personality i32 (...)* @__CxxFrameHandler3 { |
| 237 | entry: |
| 238 | invoke void @f() |
| 239 | to label %unreachable unwind label %inner |
| 240 | inner: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 241 | %cleanup = cleanuppad within none [] |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 242 | ; make sure we don't overlook this cleanupret and try to process |
| 243 | ; successor %outer as a child of inner. |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 244 | cleanupret from %cleanup unwind label %outer |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 245 | outer: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 246 | %cs = catchswitch within none [label %catch.body] unwind to caller |
| 247 | |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 248 | catch.body: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 249 | %catch = catchpad within %cs [] |
| 250 | catchret from %catch to label %exit |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 251 | exit: |
| 252 | ret void |
| 253 | unreachable: |
| 254 | unreachable |
| 255 | } |
| 256 | ; CHECK-LABEL: define void @test10( |
| 257 | ; CHECK-NEXT: entry: |
| 258 | ; CHECK-NEXT: invoke |
| 259 | ; CHECK-NEXT: to label %unreachable unwind label %inner |
| 260 | ; CHECK: inner: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 261 | ; CHECK-NEXT: %cleanup = cleanuppad within none [] |
| 262 | ; CHECK-NEXT: cleanupret from %cleanup unwind label %outer |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 263 | ; CHECK: outer: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 264 | ; CHECK-NEXT: %cs = catchswitch within none [label %catch.body] unwind to caller |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 265 | ; CHECK: catch.body: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 266 | ; CHECK-NEXT: %catch = catchpad within %cs [] |
| 267 | ; CHECK-NEXT: catchret from %catch to label %exit |
Joseph Tremoulet | f3aff31 | 2015-09-10 16:51:25 +0000 | [diff] [blame] | 268 | ; CHECK: exit: |
| 269 | ; CHECK-NEXT: ret void |
Joseph Tremoulet | 09af67a | 2015-09-27 01:47:46 +0000 | [diff] [blame] | 270 | |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 271 | define void @test11() personality i32 (...)* @__C_specific_handler { |
Joseph Tremoulet | 09af67a | 2015-09-27 01:47:46 +0000 | [diff] [blame] | 272 | entry: |
| 273 | invoke void @f() |
| 274 | to label %exit unwind label %cleanup.outer |
| 275 | cleanup.outer: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 276 | %outer = cleanuppad within none [] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 277 | invoke void @f() [ "funclet"(token %outer) ] |
Joseph Tremoulet | 09af67a | 2015-09-27 01:47:46 +0000 | [diff] [blame] | 278 | to label %outer.cont unwind label %cleanup.inner |
| 279 | outer.cont: |
| 280 | br label %merge |
| 281 | cleanup.inner: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 282 | %inner = cleanuppad within %outer [] |
Joseph Tremoulet | 09af67a | 2015-09-27 01:47:46 +0000 | [diff] [blame] | 283 | br label %merge |
| 284 | merge: |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 285 | call void @llvm.bar() |
Joseph Tremoulet | 09af67a | 2015-09-27 01:47:46 +0000 | [diff] [blame] | 286 | unreachable |
Joseph Tremoulet | 09af67a | 2015-09-27 01:47:46 +0000 | [diff] [blame] | 287 | exit: |
| 288 | ret void |
| 289 | } |
| 290 | ; merge.end will get cloned for outer and inner, but is implausible |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 291 | ; from inner, so the call @f() in inner's copy of merge should be |
Joseph Tremoulet | 09af67a | 2015-09-27 01:47:46 +0000 | [diff] [blame] | 292 | ; rewritten to call @f() |
| 293 | ; CHECK-LABEL: define void @test11() |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 294 | ; CHECK: %inner = cleanuppad within %outer [] |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 295 | ; CHECK-NEXT: call void @llvm.bar() |
Joseph Tremoulet | 09af67a | 2015-09-27 01:47:46 +0000 | [diff] [blame] | 296 | ; CHECK-NEXT: unreachable |
Joseph Tremoulet | 39234fc | 2015-10-07 19:29:56 +0000 | [diff] [blame] | 297 | |
Peter Collingbourne | d4bff30 | 2015-11-05 22:03:56 +0000 | [diff] [blame] | 298 | define void @test12() personality i32 (...)* @__CxxFrameHandler3 !dbg !5 { |
Joseph Tremoulet | 39234fc | 2015-10-07 19:29:56 +0000 | [diff] [blame] | 299 | entry: |
| 300 | invoke void @f() |
| 301 | to label %cont unwind label %left, !dbg !8 |
| 302 | cont: |
| 303 | invoke void @f() |
| 304 | to label %exit unwind label %right |
| 305 | left: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 306 | cleanuppad within none [] |
Joseph Tremoulet | 39234fc | 2015-10-07 19:29:56 +0000 | [diff] [blame] | 307 | br label %join |
| 308 | right: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 309 | cleanuppad within none [] |
Joseph Tremoulet | 39234fc | 2015-10-07 19:29:56 +0000 | [diff] [blame] | 310 | br label %join |
| 311 | join: |
| 312 | ; This call will get cloned; make sure we can handle cloning |
| 313 | ; instructions with debug metadata attached. |
David Majnemer | 3bb88c0 | 2015-12-15 21:27:27 +0000 | [diff] [blame] | 314 | call void @llvm.bar(), !dbg !9 |
Joseph Tremoulet | 39234fc | 2015-10-07 19:29:56 +0000 | [diff] [blame] | 315 | unreachable |
| 316 | exit: |
| 317 | ret void |
| 318 | } |
| 319 | |
David Majnemer | c289c9f | 2015-10-07 21:08:25 +0000 | [diff] [blame] | 320 | ; CHECK-LABEL: define void @test13() |
| 321 | ; CHECK: ret void |
| 322 | define void @test13() personality i32 (...)* @__CxxFrameHandler3 { |
| 323 | entry: |
| 324 | ret void |
| 325 | |
| 326 | unreachable: |
David Majnemer | 8a1c45d | 2015-12-12 05:38:55 +0000 | [diff] [blame] | 327 | cleanuppad within none [] |
David Majnemer | c289c9f | 2015-10-07 21:08:25 +0000 | [diff] [blame] | 328 | unreachable |
| 329 | } |
| 330 | |
Joseph Tremoulet | 71e5676 | 2016-01-02 15:22:36 +0000 | [diff] [blame] | 331 | define void @test14() personality void (...)* @ProcessCLRException { |
| 332 | entry: |
| 333 | invoke void @f() |
| 334 | to label %cont unwind label %cleanup |
| 335 | cont: |
| 336 | invoke void @f() |
| 337 | to label %exit unwind label %switch.outer |
| 338 | cleanup: |
| 339 | %cleanpad = cleanuppad within none [] |
| 340 | invoke void @f() [ "funclet" (token %cleanpad) ] |
| 341 | to label %cleanret unwind label %switch.inner |
| 342 | switch.inner: |
| 343 | %cs.inner = catchswitch within %cleanpad [label %pad.inner] unwind to caller |
| 344 | pad.inner: |
| 345 | %cp.inner = catchpad within %cs.inner [i32 1] |
| 346 | catchret from %cp.inner to label %join |
| 347 | cleanret: |
| 348 | cleanupret from %cleanpad unwind to caller |
| 349 | switch.outer: |
| 350 | %cs.outer = catchswitch within none [label %pad.outer] unwind to caller |
| 351 | pad.outer: |
| 352 | %cp.outer = catchpad within %cs.outer [i32 2] |
| 353 | catchret from %cp.outer to label %join |
| 354 | join: |
| 355 | %phi = phi i32 [ 1, %pad.inner ], [ 2, %pad.outer ] |
| 356 | call void @llvm.foo(i32 %phi) |
| 357 | unreachable |
| 358 | exit: |
| 359 | ret void |
| 360 | } |
| 361 | ; Both catchrets target %join, but the catchret from %cp.inner |
| 362 | ; returns to %cleanpad and the catchret from %cp.outer returns to the |
| 363 | ; main function, so %join needs to get cloned and one of the cleanuprets |
| 364 | ; needs to be updated to target the clone |
| 365 | ; CHECK-LABEL: define void @test14() |
| 366 | ; CHECK: catchret from %cp.inner to label %[[Clone1:.+]] |
| 367 | ; CHECK: catchret from %cp.outer to label %[[Clone2:.+]] |
| 368 | ; CHECK: [[Clone1]]: |
| 369 | ; CHECK-NEXT: call void @llvm.foo(i32 1) |
| 370 | ; CHECK-NEXT: unreachable |
| 371 | ; CHECK: [[Clone2]]: |
| 372 | ; CHECK-NEXT: call void @llvm.foo(i32 2) |
| 373 | ; CHECK-NEXT: unreachable |
| 374 | |
Joseph Tremoulet | 53e9cbd | 2015-10-16 18:08:16 +0000 | [diff] [blame] | 375 | ;; Debug info (from test12) |
| 376 | |
Joseph Tremoulet | 39234fc | 2015-10-07 19:29:56 +0000 | [diff] [blame] | 377 | ; Make sure the DISubprogram doesn't get cloned |
| 378 | ; CHECK-LABEL: !llvm.module.flags |
| 379 | ; CHECK-NOT: !DISubprogram |
| 380 | ; CHECK: !{{[0-9]+}} = distinct !DISubprogram(name: "test12" |
| 381 | ; CHECK-NOT: !DISubprogram |
| 382 | !llvm.module.flags = !{!0} |
| 383 | !llvm.dbg.cu = !{!1} |
| 384 | |
| 385 | !0 = !{i32 2, !"Debug Info Version", i32 3} |
Adrian Prantl | 75819ae | 2016-04-15 15:57:41 +0000 | [diff] [blame] | 386 | !1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "compiler", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3) |
Joseph Tremoulet | 39234fc | 2015-10-07 19:29:56 +0000 | [diff] [blame] | 387 | !2 = !DIFile(filename: "test.cpp", directory: ".") |
| 388 | !3 = !{} |
Adrian Prantl | 75819ae | 2016-04-15 15:57:41 +0000 | [diff] [blame] | 389 | !5 = distinct !DISubprogram(name: "test12", scope: !2, file: !2, type: !6, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !1, variables: !3) |
Joseph Tremoulet | 39234fc | 2015-10-07 19:29:56 +0000 | [diff] [blame] | 390 | !6 = !DISubroutineType(types: !7) |
| 391 | !7 = !{null} |
| 392 | !8 = !DILocation(line: 1, scope: !5) |
| 393 | !9 = !DILocation(line: 2, scope: !5) |