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