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: invoke void @_ZN1AD1Ev(%struct.A* [[A]])
    100 ; CHECK-NEXT:   to label %[[LBL:[^\s]+]] unwind
    101 ; CHECK: [[LBL]]:
    102 ; CHECK-NEXT: br label %[[LPAD:[^\s]+]]
    103 ; CHECK:      ret void
    104 ; CHECK:      landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    105 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    106 ; CHECK-NEXT: br label %[[LPAD]]
    107 ; CHECK: [[LPAD]]:
    108 ; CHECK-NEXT: phi { i8*, i32 } [
    109 ; CHECK-NEXT: extractvalue { i8*, i32 }
    110 ; CHECK-NEXT: extractvalue { i8*, i32 }
    111 ; CHECK-NEXT: call i32 @llvm.eh.typeid.for(
    112 
    113 
    114 ;; Test 1 - Correctly handle phis in outer landing pads.
    115 
    116 define void @test1_out() uwtable ssp {
    117 entry:
    118   invoke void @test0_in()
    119           to label %cont unwind label %lpad
    120 
    121 cont:
    122   invoke void @test0_in()
    123           to label %ret unwind label %lpad
    124 
    125 ret:
    126   ret void
    127 
    128 lpad:
    129   %x = phi i32 [ 0, %entry ], [ 1, %cont ]
    130   %y = phi i32 [ 1, %entry ], [ 4, %cont ]
    131   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
    132             catch i8* bitcast (i8** @_ZTIi to i8*)
    133   %eh.exc = extractvalue { i8*, i32 } %exn, 0
    134   %eh.selector = extractvalue { i8*, i32 } %exn, 1
    135   %0 = call i32 @llvm.eh.typeid.for(i8* bitcast (i8** @_ZTIi to i8*)) nounwind
    136   %1 = icmp eq i32 %eh.selector, %0
    137   br i1 %1, label %catch, label %eh.resume
    138 
    139 catch:
    140   %ignored = call i8* @__cxa_begin_catch(i8* %eh.exc) nounwind
    141   call void @use(i32 %x)
    142   call void @use(i32 %y)
    143   call void @__cxa_end_catch() nounwind
    144   br label %ret
    145 
    146 eh.resume:
    147   resume { i8*, i32 } %exn
    148 }
    149 
    150 ; CHECK:    define void @test1_out()
    151 ; CHECK:      [[A2:%.*]] = alloca %struct.A,
    152 ; CHECK:      [[B2:%.*]] = alloca %struct.A,
    153 ; CHECK:      [[A1:%.*]] = alloca %struct.A,
    154 ; CHECK:      [[B1:%.*]] = alloca %struct.A,
    155 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A1]])
    156 ; CHECK-NEXT:   unwind label %[[LPAD:[^\s]+]]
    157 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B1]])
    158 ; CHECK-NEXT:   unwind label %[[LPAD1:[^\s]+]]
    159 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B1]])
    160 ; CHECK-NEXT:   unwind label %[[LPAD1]]
    161 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A1]])
    162 ; CHECK-NEXT:   unwind label %[[LPAD]]
    163 
    164 ; Inner landing pad from first inlining.
    165 ; CHECK:    [[LPAD1]]:
    166 ; CHECK-NEXT: [[LPADVAL1:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    167 ; CHECK-NEXT:    cleanup
    168 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    169 ; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A1]])
    170 ; CHECK-NEXT:   to label %[[RESUME1:[^\s]+]] unwind
    171 ; CHECK: [[RESUME1]]:
    172 ; CHECK-NEXT: br label %[[LPAD_JOIN1:[^\s]+]]
    173 
    174 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A2]])
    175 ; CHECK-NEXT:   unwind label %[[LPAD]]
    176 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B2]])
    177 ; CHECK-NEXT:   unwind label %[[LPAD2:[^\s]+]]
    178 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B2]])
    179 ; CHECK-NEXT:   unwind label %[[LPAD2]]
    180 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A2]])
    181 ; CHECK-NEXT:   unwind label %[[LPAD]]
    182 
    183 ; Inner landing pad from second inlining.
    184 ; CHECK:    [[LPAD2]]:
    185 ; CHECK-NEXT: [[LPADVAL2:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    186 ; CHECK-NEXT:   cleanup
    187 ; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
    188 ; CHECK-NEXT: invoke void @_ZN1AD1Ev(%struct.A* [[A2]])
    189 ; CHECK-NEXT:   to label %[[RESUME2:[^\s]+]] unwind
    190 ; CHECK: [[RESUME2]]:
    191 ; CHECK-NEXT: br label %[[LPAD_JOIN2:[^\s]+]]
    192 
    193 ; CHECK:      ret void
    194 
    195 ; CHECK:    [[LPAD]]:
    196 ; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, %entry ], [ 0, {{%.*}} ], [ 1, %cont ], [ 1, {{%.*}} ]
    197 ; CHECK-NEXT: [[Y:%.*]] = phi i32 [ 1, %entry ], [ 1, {{%.*}} ], [ 4, %cont ], [ 4, {{%.*}} ]
    198 ; CHECK-NEXT: [[LPADVAL:%.*]] = landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    199 ; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
    200 ; CHECK-NEXT: br label %[[LPAD_JOIN2]]
    201 
    202 ; CHECK: [[LPAD_JOIN2]]:
    203 ; CHECK-NEXT: [[XJ2:%.*]] = phi i32 [ [[X]], %[[LPAD]] ], [ 1, %[[RESUME2]] ]
    204 ; CHECK-NEXT: [[YJ2:%.*]] = phi i32 [ [[Y]], %[[LPAD]] ], [ 4, %[[RESUME2]] ]
    205 ; CHECK-NEXT: [[EXNJ2:%.*]] = phi { i8*, i32 } [ [[LPADVAL]], %[[LPAD]] ], [ [[LPADVAL2]], %[[RESUME2]] ]
    206 ; CHECK-NEXT: br label %[[LPAD_JOIN1]]
    207 
    208 ; CHECK: [[LPAD_JOIN1]]:
    209 ; CHECK-NEXT: [[XJ1:%.*]] = phi i32 [ [[XJ2]], %[[LPAD_JOIN2]] ], [ 0, %[[RESUME1]] ]
    210 ; CHECK-NEXT: [[YJ1:%.*]] = phi i32 [ [[YJ2]], %[[LPAD_JOIN2]] ], [ 1, %[[RESUME1]] ]
    211 ; CHECK-NEXT: [[EXNJ1:%.*]] = phi { i8*, i32 } [ [[EXNJ2]], %[[LPAD_JOIN2]] ], [ [[LPADVAL1]], %[[RESUME1]] ]
    212 ; CHECK-NEXT: extractvalue { i8*, i32 } [[EXNJ1]], 0
    213 ; CHECK-NEXT: [[SELJ1:%.*]] = extractvalue { i8*, i32 } [[EXNJ1]], 1
    214 ; CHECK-NEXT: [[T:%.*]] = call i32 @llvm.eh.typeid.for(
    215 ; CHECK-NEXT: icmp eq i32 [[SELJ1]], [[T]]
    216 
    217 ; CHECK:      call void @use(i32 [[XJ1]])
    218 ; CHECK:      call void @use(i32 [[YJ1]])
    219 
    220 ; CHECK:      resume { i8*, i32 }
    221 
    222 
    223 ;; Test 2 - Don't make invalid IR for inlines into landing pads without eh.exception calls
    224 define void @test2_out() uwtable ssp {
    225 entry:
    226   invoke void @test0_in()
    227           to label %ret unwind label %lpad
    228 
    229 ret:
    230   ret void
    231 
    232 lpad:
    233   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
    234             cleanup
    235   call void @_ZSt9terminatev()
    236   unreachable
    237 }
    238 
    239 ; CHECK: define void @test2_out()
    240 ; CHECK:      [[A:%.*]] = alloca %struct.A,
    241 ; CHECK:      [[B:%.*]] = alloca %struct.A,
    242 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[A]])
    243 ; CHECK-NEXT:   unwind label %[[LPAD:[^\s]+]]
    244 ; CHECK:      invoke void @_ZN1AC1Ev(%struct.A* [[B]])
    245 ; CHECK-NEXT:   unwind label %[[LPAD2:[^\s]+]]
    246 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[B]])
    247 ; CHECK-NEXT:   unwind label %[[LPAD2]]
    248 ; CHECK:      invoke void @_ZN1AD1Ev(%struct.A* [[A]])
    249 ; CHECK-NEXT:   unwind label %[[LPAD]]
    250 
    251 
    252 ;; Test 3 - Deal correctly with split unwind edges.
    253 define void @test3_out() uwtable ssp {
    254 entry:
    255   invoke void @test0_in()
    256           to label %ret unwind label %lpad
    257 
    258 ret:
    259   ret void
    260 
    261 lpad:
    262   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
    263             catch i8* bitcast (i8** @_ZTIi to i8*)
    264   br label %lpad.cont
    265 
    266 lpad.cont:
    267   call void @_ZSt9terminatev()
    268   unreachable
    269 }
    270 
    271 ; CHECK: define void @test3_out()
    272 ; CHECK:      landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    273 ; CHECK-NEXT:    cleanup
    274 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    275 ; CHECK-NEXT: invoke void @_ZN1AD1Ev(
    276 ; CHECK-NEXT:   to label %[[L:[^\s]+]] unwind
    277 ; CHECK:    [[L]]:
    278 ; CHECK-NEXT: br label %[[JOIN:[^\s]+]]
    279 ; CHECK:    [[JOIN]]:
    280 ; CHECK-NEXT: phi { i8*, i32 }
    281 ; CHECK-NEXT: br label %lpad.cont
    282 ; CHECK:    lpad.cont:
    283 ; CHECK-NEXT: call void @_ZSt9terminatev()
    284 
    285 
    286 ;; Test 4 - Split unwind edges with a dominance problem
    287 define void @test4_out() uwtable ssp {
    288 entry:
    289   invoke void @test0_in()
    290           to label %cont unwind label %lpad.crit
    291 
    292 cont:
    293   invoke void @opaque()
    294           to label %ret unwind label %lpad
    295 
    296 ret:
    297   ret void
    298 
    299 lpad.crit:
    300   %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
    301             catch i8* bitcast (i8** @_ZTIi to i8*)
    302   call void @opaque() nounwind
    303   br label %terminate
    304 
    305 lpad:
    306   %exn2 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0
    307             catch i8* bitcast (i8** @_ZTIi to i8*)
    308   br label %terminate
    309 
    310 terminate:
    311   %phi = phi i32 [ 0, %lpad.crit ], [ 1, %lpad ]
    312   call void @use(i32 %phi)
    313   call void @_ZSt9terminatev()
    314   unreachable
    315 }
    316 
    317 ; CHECK: define void @test4_out()
    318 ; CHECK:      landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    319 ; CHECK-NEXT:    cleanup
    320 ; CHECK-NEXT:    catch i8* bitcast (i8** @_ZTIi to i8*)
    321 ; CHECK-NEXT: invoke void @_ZN1AD1Ev(
    322 ; CHECK-NEXT:   to label %[[L:[^\s]+]] unwind
    323 ; CHECK:    [[L]]:
    324 ; CHECK-NEXT: br label %[[JOIN:[^\s]+]]
    325 ; CHECK:      invoke void @opaque()
    326 ; CHECK-NEXT:                  unwind label %lpad
    327 ; CHECK:    lpad.crit:
    328 ; CHECK-NEXT: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    329 ; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
    330 ; CHECK-NEXT: br label %[[JOIN]]
    331 ; CHECK:    [[JOIN]]:
    332 ; CHECK-NEXT: phi { i8*, i32 }
    333 ; CHECK-NEXT: call void @opaque() nounwind
    334 ; CHECK-NEXT: br label %[[FIX:[^\s]+]]
    335 ; CHECK:    lpad:
    336 ; CHECK-NEXT: landingpad { i8*, i32 } personality i32 (...)* @__gxx_personality_v0
    337 ; CHECK-NEXT:   catch i8* bitcast (i8** @_ZTIi to i8*)
    338 ; CHECK-NEXT: br label %[[FIX]]
    339 ; CHECK:    [[FIX]]:
    340 ; CHECK-NEXT: [[T1:%.*]] = phi i32 [ 0, %[[JOIN]] ], [ 1, %lpad ]
    341 ; CHECK-NEXT: call void @use(i32 [[T1]])
    342 ; CHECK-NEXT: call void @_ZSt9terminatev()
    343