1 ; RUN: opt -mtriple=x86_64-pc-windows-msvc -S -winehprepare < %s | FileCheck %s 2 3 declare i32 @__CxxFrameHandler3(...) 4 declare i32 @__C_specific_handler(...) 5 declare void @ProcessCLRException(...) 6 7 declare void @f() 8 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 13 14 define void @test1() personality i32 (...)* @__CxxFrameHandler3 { 15 entry: 16 ; %x def colors: {entry} subset of use colors; must spill 17 %x = call i32 @llvm.qux() 18 invoke void @f() 19 to label %noreturn unwind label %catch.switch 20 catch.switch: 21 %cs = catchswitch within none [label %catch] unwind to caller 22 catch: 23 %cp = catchpad within %cs [] 24 br label %noreturn 25 noreturn: 26 ; %x use colors: {entry, cleanup} 27 call void @llvm.foo(i32 %x) 28 unreachable 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. 33 ; CHECK-LABEL: define void @test1( 34 ; CHECK: entry: 35 ; CHECK: %x = call i32 @llvm.qux() 36 ; CHECK: invoke void @f() 37 ; CHECK: to label %[[EntryCopy:[^ ]+]] unwind label %catch 38 ; CHECK: catch.switch: 39 ; CHECK: %cs = catchswitch within none [label %catch] unwind to caller 40 ; CHECK: catch: 41 ; CHECK: catchpad within %cs [] 42 ; CHECK-NEXT: call void @llvm.foo(i32 %x) 43 ; CHECK: [[EntryCopy]]: 44 ; CHECK: call void @llvm.foo(i32 %x) 45 46 47 define void @test2() personality i32 (...)* @__CxxFrameHandler3 { 48 entry: 49 invoke void @f() 50 to label %exit unwind label %cleanup 51 cleanup: 52 cleanuppad within none [] 53 br label %exit 54 exit: 55 call void @llvm.bar() 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. 61 ; CHECK-LABEL: define void @test2( 62 ; CHECK: entry: 63 ; CHECK: invoke void @f() 64 ; CHECK: to label %[[exit:[^ ]+]] unwind label %cleanup 65 ; CHECK: cleanup: 66 ; CHECK: cleanuppad within none [] 67 ; CHECK: call void @llvm.bar() 68 ; CHECK-NEXT: unreachable 69 ; CHECK: [[exit]]: 70 ; CHECK: call void @llvm.bar() 71 ; CHECK-NEXT: ret void 72 73 74 define void @test3() personality i32 (...)* @__CxxFrameHandler3 { 75 entry: 76 invoke void @f() 77 to label %invoke.cont unwind label %catch.switch 78 invoke.cont: 79 invoke void @f() 80 to label %exit unwind label %cleanup 81 catch.switch: 82 %cs = catchswitch within none [label %catch] unwind to caller 83 catch: 84 catchpad within %cs [] 85 br label %shared 86 cleanup: 87 cleanuppad within none [] 88 br label %shared 89 shared: 90 call void @llvm.bar() 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). 97 ; CHECK-LABEL: define void @test3( 98 ; CHECK: invoke void @f() 99 ; CHECK: invoke void @f() 100 ; CHECK: to label %[[exit:[^ ]+]] unwind 101 ; CHECK: catch: 102 ; CHECK: catchpad within %cs [] 103 ; CHECK-NEXT: call void @llvm.bar() 104 ; CHECK-NEXT: unreachable 105 ; CHECK: cleanup: 106 ; CHECK: cleanuppad within none [] 107 ; CHECK: call void @llvm.bar() 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() 116 to label %shared unwind label %catch.switch 117 catch.switch: 118 %cs = catchswitch within none [label %catch] unwind to caller 119 catch: 120 catchpad within %cs [] 121 br label %shared 122 shared: 123 %x = call i32 @llvm.qux() 124 %i = call i32 @llvm.qux() 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 ] 129 %b = call i1 @llvm.baz() 130 br i1 %b, label %left, label %right 131 left: 132 %y = call i32 @llvm.qux() 133 br label %loop.tail 134 right: 135 call void @llvm.foo(i32 %x) 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: 142 call void @llvm.foo(i32 %x) 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. 148 ; CHECK-LABEL: define void @test4( 149 ; CHECK: entry: 150 ; CHECK: to label %[[shared_E:[^ ]+]] unwind label %catch.switch 151 ; CHECK: catch: 152 ; CHECK: catchpad within %cs [] 153 ; CHECK: [[x_C:%[^ ]+]] = call i32 @llvm.qux() 154 ; CHECK: [[i_C:%[^ ]+]] = call i32 @llvm.qux() 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]]: 158 ; CHECK: [[x_E:%[^ ]+]] = call i32 @llvm.qux() 159 ; CHECK: [[i_E:%[^ ]+]] = call i32 @llvm.qux() 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]]: 163 ; CHECK: [[iloop_C:%[^ ]+]] = phi i32 [ [[i_C]], %catch ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ] 164 ; CHECK: [[b_C:%[^ ]+]] = call i1 @llvm.baz() 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:[^ ]+]] ] 168 ; CHECK: [[b_E:%[^ ]+]] = call i1 @llvm.baz() 169 ; CHECK: br i1 [[b_E]], label %[[left_E:[^ ]+]], label %[[right_E:[^ ]+]] 170 ; CHECK: [[left_C]]: 171 ; CHECK: [[y_C:%[^ ]+]] = call i32 @llvm.qux() 172 ; CHECK: br label %[[looptail_C]] 173 ; CHECK: [[left_E]]: 174 ; CHECK: [[y_E:%[^ ]+]] = call i32 @llvm.qux() 175 ; CHECK: br label %[[looptail_E]] 176 ; CHECK: [[right_C]]: 177 ; CHECK: call void @llvm.foo(i32 [[x_C]]) 178 ; CHECK: br label %[[looptail_C]] 179 ; CHECK: [[right_E]]: 180 ; CHECK: call void @llvm.foo(i32 [[x_E]]) 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]]: 191 ; CHECK: call void @llvm.foo(i32 [[x_C]]) 192 ; CHECK: unreachable 193 ; CHECK: [[exit_E]]: 194 ; CHECK: call void @llvm.foo(i32 [[x_E]]) 195 ; CHECK: unreachable 196 197 198 define void @test5() personality i32 (...)* @__C_specific_handler { 199 entry: 200 invoke void @f() 201 to label %exit unwind label %outer 202 outer: 203 %o = cleanuppad within none [] 204 %x = call i32 @llvm.qux() 205 invoke void @f() [ "funclet"(token %o) ] 206 to label %outer.ret unwind label %catch.switch 207 catch.switch: 208 %cs = catchswitch within %o [label %inner] unwind to caller 209 inner: 210 %i = catchpad within %cs [] 211 catchret from %i to label %outer.post-inner 212 outer.post-inner: 213 call void @llvm.foo(i32 %x) 214 br label %outer.ret 215 outer.ret: 216 cleanupret from %o unwind to caller 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. 223 ; CHECK-LABEL: define void @test5( 224 ; CHECK: outer: 225 ; CHECK: %x = call i32 @llvm.qux() 226 ; CHECK-NEXT: invoke void @f() 227 ; CHECK-NEXT: to label %outer.ret unwind label %catch.switch 228 ; CHECK: inner: 229 ; CHECK-NEXT: %i = catchpad within %cs [] 230 ; CHECK-NEXT: catchret from %i to label %outer.post-inner 231 ; CHECK: outer.post-inner: 232 ; CHECK-NEXT: call void @llvm.foo(i32 %x) 233 ; CHECK-NEXT: br label %outer.ret 234 235 236 define void @test10() personality i32 (...)* @__CxxFrameHandler3 { 237 entry: 238 invoke void @f() 239 to label %unreachable unwind label %inner 240 inner: 241 %cleanup = cleanuppad within none [] 242 ; make sure we don't overlook this cleanupret and try to process 243 ; successor %outer as a child of inner. 244 cleanupret from %cleanup unwind label %outer 245 outer: 246 %cs = catchswitch within none [label %catch.body] unwind to caller 247 248 catch.body: 249 %catch = catchpad within %cs [] 250 catchret from %catch to label %exit 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: 261 ; CHECK-NEXT: %cleanup = cleanuppad within none [] 262 ; CHECK-NEXT: cleanupret from %cleanup unwind label %outer 263 ; CHECK: outer: 264 ; CHECK-NEXT: %cs = catchswitch within none [label %catch.body] unwind to caller 265 ; CHECK: catch.body: 266 ; CHECK-NEXT: %catch = catchpad within %cs [] 267 ; CHECK-NEXT: catchret from %catch to label %exit 268 ; CHECK: exit: 269 ; CHECK-NEXT: ret void 270 271 define void @test11() personality i32 (...)* @__C_specific_handler { 272 entry: 273 invoke void @f() 274 to label %exit unwind label %cleanup.outer 275 cleanup.outer: 276 %outer = cleanuppad within none [] 277 invoke void @f() [ "funclet"(token %outer) ] 278 to label %outer.cont unwind label %cleanup.inner 279 outer.cont: 280 br label %merge 281 cleanup.inner: 282 %inner = cleanuppad within %outer [] 283 br label %merge 284 merge: 285 call void @llvm.bar() 286 unreachable 287 exit: 288 ret void 289 } 290 ; merge.end will get cloned for outer and inner, but is implausible 291 ; from inner, so the call @f() in inner's copy of merge should be 292 ; rewritten to call @f() 293 ; CHECK-LABEL: define void @test11() 294 ; CHECK: %inner = cleanuppad within %outer [] 295 ; CHECK-NEXT: call void @llvm.bar() 296 ; CHECK-NEXT: unreachable 297 298 define void @test12() personality i32 (...)* @__CxxFrameHandler3 !dbg !5 { 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: 306 cleanuppad within none [] 307 br label %join 308 right: 309 cleanuppad within none [] 310 br label %join 311 join: 312 ; This call will get cloned; make sure we can handle cloning 313 ; instructions with debug metadata attached. 314 call void @llvm.bar(), !dbg !9 315 unreachable 316 exit: 317 ret void 318 } 319 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: 327 cleanuppad within none [] 328 unreachable 329 } 330 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 375 ;; Debug info (from test12) 376 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} 386 !1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !2, producer: "compiler", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !3) 387 !2 = !DIFile(filename: "test.cpp", directory: ".") 388 !3 = !{} 389 !5 = distinct !DISubprogram(name: "test12", scope: !2, file: !2, type: !6, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !1, retainedNodes: !3) 390 !6 = !DISubroutineType(types: !7) 391 !7 = !{null} 392 !8 = !DILocation(line: 1, scope: !5) 393 !9 = !DILocation(line: 2, scope: !5) 394