Home | History | Annotate | Download | only in Inline
      1 ; RUN: opt < %s -inline -S | FileCheck %s
      2 
      3 ; Test that the inliner correctly handles inlining into invoke sites
      4 ; by appending selectors and forwarding _Unwind_Resume directly to the
      5 ; enclosing landing pad.
      6 
      7 ;; Test 0 - basic functionality.
      8 
      9 %struct.A = type { i8 }
     10 
     11 @_ZTIi = external constant i8*
     12 
     13 declare void @_ZN1AC1Ev(%struct.A*)
     14 
     15 declare void @_ZN1AD1Ev(%struct.A*)
     16 
     17 declare void @use(i32) nounwind
     18 
     19 declare void @opaque()
     20 
     21 declare i32 @llvm.eh.typeid.for(i8*) nounwind
     22 
     23 declare i32 @__gxx_personality_v0(...)
     24 
     25 declare i8* @__cxa_begin_catch(i8*)
     26 
     27 declare void @__cxa_end_catch()
     28 
     29 declare void @_ZSt9terminatev()
     30 
     31 define internal void @test0_in() alwaysinline uwtable ssp {
     32 entry:
     33   %a = alloca %struct.A, align 1
     34   %b = alloca %struct.A, align 1
     35   call void @_ZN1AC1Ev(%struct.A* %a)
     36   invoke void @_ZN1AC1Ev(%struct.A* %b)
     37           to label %invoke.cont unwind label %lpad
     38 
     39 invoke.cont:
     40   invoke void @_ZN1AD1Ev(%struct.A* %b)
     41           to label %invoke.cont1 unwind label %lpad
     42 
     43 invoke.cont1:
     44   call void @_ZN1AD1Ev(%struct.A* %a)
     45   ret void
     46 
     47 lpad:
     48   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
     49             cleanup
     50   invoke void @_ZN1AD1Ev(%struct.A* %a)
     51           to label %invoke.cont2 unwind label %terminate.lpad
     52 
     53 invoke.cont2:
     54   resume { i8*, i32 } %exn
     55 
     56 terminate.lpad:
     57   %exn1 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
     58             catch i8* null
     59   call void @_ZSt9terminatev() noreturn nounwind
     60   unreachable
     61 }
     62 
     63 define void @test0_out() uwtable ssp {
     64 entry:
     65   invoke void @test0_in()
     66           to label %ret unwind label %lpad
     67 
     68 ret:
     69   ret void
     70 
     71 lpad:                                             ; preds = %entry
     72   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
     73             catch i8* bitcast (i8** @_ZTIi to i8*)
     74   %eh.exc = extractvalue { i8*, i32 } %exn, 0
     75   %eh.selector = extractvalue { i8*, i32 } %exn, 1
     76   %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind
     77   %1 = icmp eq i32 %eh.selector, %0
     78   br i1 %1, label %catch, label %eh.resume
     79 
     80 catch:
     81   %ignored = call i8* @__cxa_begin_catch(i8* %eh.exc) nounwind
     82   call void @__cxa_end_catch() nounwind
     83   br label %ret
     84 
     85 eh.resume:
     86   resume { i8*, i32 } %exn
     87 }
     88 
     89 ; CHECK:    define void @test0_out()
     90 ; CHECK:      [[A:%.*]] = alloca %struct.A,
     91 ; CHECK:      [[B:%.*]] = alloca %struct.A,
     92 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A]])
     93 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B]])
     94 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B]])
     95 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A]])
     96 ; CHECK:      landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
     97 ; CHECK-NEXT:    cleanup
     98 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
     99 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    100 ; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A]])
    101 ; CHECK-NEXT:   to label %[[LBL:[^\s]+]] unwind
    102 ; CHECK: [[LBL]]:
    103 ; CHECK-NEXT: br label %[[LPAD:[^\s]+]]
    104 ; CHECK:      ret void
    105 ; CHECK:      landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    106 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    107 ; CHECK-NEXT: br label %[[LPAD]]
    108 ; CHECK: [[LPAD]]:
    109 ; CHECK-NEXT: phi { i8*, i32 } [
    110 ; CHECK-NEXT: extractvalue { i8*, i32 }
    111 ; CHECK-NEXT: extractvalue { i8*, i32 }
    112 ; CHECK-NEXT: call i32 @llvm.eh.typeid.for(
    113 
    114 
    115 ;; Test 1 - Correctly handle phis in outer landing pads.
    116 
    117 define void @test1_out() uwtable ssp {
    118 entry:
    119   invoke void @test0_in()
    120           to label %cont unwind label %lpad
    121 
    122 cont:
    123   invoke void @test0_in()
    124           to label %ret unwind label %lpad
    125 
    126 ret:
    127   ret void
    128 
    129 lpad:
    130   %x = phi i32 [ 0, %entry ], [ 1, %cont ]
    131   %y = phi i32 [ 1, %entry ], [ 4, %cont ]
    132   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
    133             catch i8* bitcast (i8** @_ZTIi to i8*)
    134   %eh.exc = extractvalue { i8*, i32 } %exn, 0
    135   %eh.selector = extractvalue { i8*, i32 } %exn, 1
    136   %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind
    137   %1 = icmp eq i32 %eh.selector, %0
    138   br i1 %1, label %catch, label %eh.resume
    139 
    140 catch:
    141   %ignored = call i8* @__cxa_begin_catch(i8* %eh.exc) nounwind
    142   call void @use(i32 %x)
    143   call void @use(i32 %y)
    144   call void @__cxa_end_catch() nounwind
    145   br label %ret
    146 
    147 eh.resume:
    148   resume { i8*, i32 } %exn
    149 }
    150 
    151 ; CHECK:    define void @test1_out()
    152 ; CHECK:      [[A2:%.*]] = alloca %struct.A,
    153 ; CHECK:      [[B2:%.*]] = alloca %struct.A,
    154 ; CHECK:      [[A1:%.*]] = alloca %struct.A,
    155 ; CHECK:      [[B1:%.*]] = alloca %struct.A,
    156 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A1]])
    157 ; CHECK-NEXT:   unwind label %[[LPAD:[^\s]+]]
    158 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B1]])
    159 ; CHECK-NEXT:   unwind label %[[LPAD1:[^\s]+]]
    160 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B1]])
    161 ; CHECK-NEXT:   unwind label %[[LPAD1]]
    162 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A1]])
    163 ; CHECK-NEXT:   unwind label %[[LPAD]]
    164 
    165 ; Inner landing pad from first inlining.
    166 ; CHECK:    [[LPAD1]]:
    167 ; CHECK-NEXT: [[LPADVAL1:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    168 ; CHECK-NEXT:    cleanup
    169 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    170 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    171 ; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A1]])
    172 ; CHECK-NEXT:   to label %[[RESUME1:[^\s]+]] unwind
    173 ; CHECK: [[RESUME1]]:
    174 ; CHECK-NEXT: br label %[[LPAD_JOIN1:[^\s]+]]
    175 
    176 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A2]])
    177 ; CHECK-NEXT:   unwind label %[[LPAD]]
    178 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B2]])
    179 ; CHECK-NEXT:   unwind label %[[LPAD2:[^\s]+]]
    180 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B2]])
    181 ; CHECK-NEXT:   unwind label %[[LPAD2]]
    182 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A2]])
    183 ; CHECK-NEXT:   unwind label %[[LPAD]]
    184 
    185 ; Inner landing pad from second inlining.
    186 ; CHECK:    [[LPAD2]]:
    187 ; CHECK-NEXT: [[LPADVAL2:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    188 ; CHECK-NEXT:   cleanup
    189 ; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
    190 ; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
    191 ; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A2]])
    192 ; CHECK-NEXT:   to label %[[RESUME2:[^\s]+]] unwind
    193 ; CHECK: [[RESUME2]]:
    194 ; CHECK-NEXT: br label %[[LPAD_JOIN2:[^\s]+]]
    195 
    196 ; CHECK:      ret void
    197 
    198 ; CHECK:    [[LPAD]]:
    199 ; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, %entry ], [ 0, {{%.*}} ], [ 1, %cont ], [ 1, {{%.*}} ]
    200 ; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 1, %entry ], [ 1, {{%.*}} ], [ 4, %cont ], [ 4, {{%.*}} ]
    201 ; CHECK-NEXT: [[LPADVAL:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    202 ; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
    203 ; CHECK-NEXT: br label %[[LPAD_JOIN2]]
    204 
    205 ; CHECK: [[LPAD_JOIN2]]:
    206 ; CHECK-NEXT: [[XJ2:%.*]] = phi i32 [ [[X]], %[[LPAD]] ], [ 1, %[[RESUME2]] ]
    207 ; CHECK-NEXT: [[YJ2:%.*]] = phi i32 [ [[Y]], %[[LPAD]] ], [ 4, %[[RESUME2]] ]
    208 ; CHECK-NEXT: [[EXNJ2:%.*]] = phi { i8*, i32 } [ [[LPADVAL]], %[[LPAD]] ], [ [[LPADVAL2]], %[[RESUME2]] ]
    209 ; CHECK-NEXT: br label %[[LPAD_JOIN1]]
    210 
    211 ; CHECK: [[LPAD_JOIN1]]:
    212 ; CHECK-NEXT: [[XJ1:%.*]] = phi i32 [ [[XJ2]], %[[LPAD_JOIN2]] ], [ 0, %[[RESUME1]] ]
    213 ; CHECK-NEXT: [[YJ1:%.*]] = phi i32 [ [[YJ2]], %[[LPAD_JOIN2]] ], [ 1, %[[RESUME1]] ]
    214 ; CHECK-NEXT: [[EXNJ1:%.*]] = phi { i8*, i32 } [ [[EXNJ2]], %[[LPAD_JOIN2]] ], [ [[LPADVAL1]], %[[RESUME1]] ]
    215 ; CHECK-NEXT: extractvalue { i8*, i32 } [[EXNJ1]], 0
    216 ; CHECK-NEXT: [[SELJ1:%.*]] = extractvalue { i8*, i32 } [[EXNJ1]], 1
    217 ; CHECK-NEXT: [[T:%.*]] = call i32 @llvm.eh.typeid.for(
    218 ; CHECK-NEXT: icmp eq i32 [[SELJ1]], [[T]]
    219 
    220 ; CHECK:      call void @use(i32 [[XJ1]])
    221 ; CHECK:      call void @use(i32 [[YJ1]])
    222 
    223 ; CHECK:      resume { i8*, i32 }
    224 
    225 
    226 ;; Test 2 - Don't make invalid IR for inlines into landing pads without eh.exception calls
    227 define void @test2_out() uwtable ssp {
    228 entry:
    229   invoke void @test0_in()
    230           to label %ret unwind label %lpad
    231 
    232 ret:
    233   ret void
    234 
    235 lpad:
    236   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
    237             cleanup
    238   call void @_ZSt9terminatev()
    239   unreachable
    240 }
    241 
    242 ; CHECK: define void @test2_out()
    243 ; CHECK:      [[A:%.*]] = alloca %struct.A,
    244 ; CHECK:      [[B:%.*]] = alloca %struct.A,
    245 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A]])
    246 ; CHECK-NEXT:   unwind label %[[LPAD:[^\s]+]]
    247 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B]])
    248 ; CHECK-NEXT:   unwind label %[[LPAD2:[^\s]+]]
    249 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B]])
    250 ; CHECK-NEXT:   unwind label %[[LPAD2]]
    251 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A]])
    252 ; CHECK-NEXT:   unwind label %[[LPAD]]
    253 
    254 
    255 ;; Test 3 - Deal correctly with split unwind edges.
    256 define void @test3_out() uwtable ssp {
    257 entry:
    258   invoke void @test0_in()
    259           to label %ret unwind label %lpad
    260 
    261 ret:
    262   ret void
    263 
    264 lpad:
    265   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
    266             catch i8* bitcast (i8** @_ZTIi to i8*)
    267   br label %lpad.cont
    268 
    269 lpad.cont:
    270   call void @_ZSt9terminatev()
    271   unreachable
    272 }
    273 
    274 ; CHECK: define void @test3_out()
    275 ; CHECK:      landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    276 ; CHECK-NEXT:    cleanup
    277 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    278 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    279 ; CHECK-NEXT: invoke void @_ZN1AD1Ev(
    280 ; CHECK-NEXT:   to label %[[L:[^\s]+]] unwind
    281 ; CHECK:    [[L]]:
    282 ; CHECK-NEXT: br label %[[JOIN:[^\s]+]]
    283 ; CHECK:    [[JOIN]]:
    284 ; CHECK-NEXT: phi { i8*, i32 }
    285 ; CHECK-NEXT: br label %lpad.cont
    286 ; CHECK:    lpad.cont:
    287 ; CHECK-NEXT: call void @_ZSt9terminatev()
    288 
    289 
    290 ;; Test 4 - Split unwind edges with a dominance problem
    291 define void @test4_out() uwtable ssp {
    292 entry:
    293   invoke void @test0_in()
    294           to label %cont unwind label %lpad.crit
    295 
    296 cont:
    297   invoke void @opaque()
    298           to label %ret unwind label %lpad
    299 
    300 ret:
    301   ret void
    302 
    303 lpad.crit:
    304   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
    305             catch i8* bitcast (i8** @_ZTIi to i8*)
    306   call void @opaque() nounwind
    307   br label %terminate
    308 
    309 lpad:
    310   %exn2 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
    311             catch i8* bitcast (i8** @_ZTIi to i8*)
    312   br label %terminate
    313 
    314 terminate:
    315   %phi = phi i32 [ 0, %lpad.crit ], [ 1, %lpad ]
    316   call void @use(i32 %phi)
    317   call void @_ZSt9terminatev()
    318   unreachable
    319 }
    320 
    321 ; CHECK: define void @test4_out()
    322 ; CHECK:      landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    323 ; CHECK-NEXT:    cleanup
    324 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    325 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    326 ; CHECK-NEXT: invoke void @_ZN1AD1Ev(
    327 ; CHECK-NEXT:   to label %[[L:[^\s]+]] unwind
    328 ; CHECK:    [[L]]:
    329 ; CHECK-NEXT: br label %[[JOIN:[^\s]+]]
    330 ; CHECK:      invoke void @opaque()
    331 ; CHECK-NEXT:                  unwind label %lpad
    332 ; CHECK:    lpad.crit:
    333 ; CHECK-NEXT: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    334 ; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
    335 ; CHECK-NEXT: br label %[[JOIN]]
    336 ; CHECK:    [[JOIN]]:
    337 ; CHECK-NEXT: phi { i8*, i32 }
    338 ; CHECK-NEXT: call void @opaque() [[NUW:#[0-9]+]]
    339 ; CHECK-NEXT: br label %[[FIX:[^\s]+]]
    340 ; CHECK:    lpad:
    341 ; CHECK-NEXT: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    342 ; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
    343 ; CHECK-NEXT: br label %[[FIX]]
    344 ; CHECK:    [[FIX]]:
    345 ; CHECK-NEXT: [[T1:%.*]] = phi i32 [ 0, %[[JOIN]] ], [ 1, %lpad ]
    346 ; CHECK-NEXT: call void @use(i32 [[T1]])
    347 ; CHECK-NEXT: call void @_ZSt9terminatev()
    348 
    349 ; CHECK: attributes [[NUW]] = { nounwind }
    350 ; CHECK: attributes #1 = { nounwind readnone }
    351 ; CHECK: attributes #2 = { ssp uwtable }
    352 ; CHECK: attributes #3 = { noreturn nounwind }
    353