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 13declare void @_ZN1AC1Ev(%struct.A*) 14 15declare void @_ZN1AD1Ev(%struct.A*) 16 17declare void @use(i32) nounwind 18 19declare void @opaque() 20 21declare i32 @llvm.eh.typeid.for(i8*) nounwind 22 23declare i32 @__gxx_personality_v0(...) 24 25declare i8* @__cxa_begin_catch(i8*) 26 27declare void @__cxa_end_catch() 28 29declare void @_ZSt9terminatev() 30 31define internal void @test0_in() alwaysinline uwtable ssp { 32entry: 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 39invoke.cont: 40 invoke void @_ZN1AD1Ev(%struct.A* %b) 41 to label %invoke.cont1 unwind label %lpad 42 43invoke.cont1: 44 call void @_ZN1AD1Ev(%struct.A* %a) 45 ret void 46 47lpad: 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 53invoke.cont2: 54 resume { i8*, i32 } %exn 55 56terminate.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 63define void @test0_out() uwtable ssp { 64entry: 65 invoke void @test0_in() 66 to label %ret unwind label %lpad 67 68ret: 69 ret void 70 71lpad: ; 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 80catch: 81 %ignored = call i8* @__cxa_begin_catch(i8* %eh.exc) nounwind 82 call void @__cxa_end_catch() nounwind 83 br label %ret 84 85eh.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 117define void @test1_out() uwtable ssp { 118entry: 119 invoke void @test0_in() 120 to label %cont unwind label %lpad 121 122cont: 123 invoke void @test0_in() 124 to label %ret unwind label %lpad 125 126ret: 127 ret void 128 129lpad: 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 140catch: 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 147eh.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 227define void @test2_out() uwtable ssp { 228entry: 229 invoke void @test0_in() 230 to label %ret unwind label %lpad 231 232ret: 233 ret void 234 235lpad: 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. 256define void @test3_out() uwtable ssp { 257entry: 258 invoke void @test0_in() 259 to label %ret unwind label %lpad 260 261ret: 262 ret void 263 264lpad: 265 %exn = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 266 catch i8* bitcast (i8** @_ZTIi to i8*) 267 br label %lpad.cont 268 269lpad.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 291define void @test4_out() uwtable ssp { 292entry: 293 invoke void @test0_in() 294 to label %cont unwind label %lpad.crit 295 296cont: 297 invoke void @opaque() 298 to label %ret unwind label %lpad 299 300ret: 301 ret void 302 303lpad.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 309lpad: 310 %exn2 = landingpad {i8*, i32} personality i32 (...)* @__gxx_personality_v0 311 catch i8* bitcast (i8** @_ZTIi to i8*) 312 br label %terminate 313 314terminate: 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