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