1; RUN: opt -disable-output -passes=print-lcg %s 2>&1 | FileCheck %s 2; 3; Basic validation of the call graph analysis used in the new pass manager. 4 5define void @f() { 6; CHECK-LABEL: Edges in function: f 7; CHECK-NOT: -> 8 9entry: 10 ret void 11} 12 13; A bunch more functions just to make it easier to test several call edges at once. 14define void @f1() { 15 ret void 16} 17define void @f2() { 18 ret void 19} 20define void @f3() { 21 ret void 22} 23define void @f4() { 24 ret void 25} 26define void @f5() { 27 ret void 28} 29define void @f6() { 30 ret void 31} 32define void @f7() { 33 ret void 34} 35define void @f8() { 36 ret void 37} 38define void @f9() { 39 ret void 40} 41define void @f10() { 42 ret void 43} 44define void @f11() { 45 ret void 46} 47define void @f12() { 48 ret void 49} 50 51declare i32 @__gxx_personality_v0(...) 52 53define void @test0() { 54; CHECK-LABEL: Edges in function: test0 55; CHECK-NEXT: call -> f 56; CHECK-NOT: -> 57 58entry: 59 call void @f() 60 call void @f() 61 call void @f() 62 call void @f() 63 ret void 64} 65 66define void ()* @test1(void ()** %x) personality i32 (...)* @__gxx_personality_v0 { 67; CHECK-LABEL: Edges in function: test1 68; CHECK-NEXT: call -> f6 69; CHECK-NEXT: call -> f10 70; CHECK-NEXT: ref -> f12 71; CHECK-NEXT: ref -> f11 72; CHECK-NEXT: ref -> f7 73; CHECK-NEXT: ref -> f9 74; CHECK-NEXT: ref -> f8 75; CHECK-NEXT: ref -> f5 76; CHECK-NEXT: ref -> f4 77; CHECK-NEXT: ref -> f3 78; CHECK-NEXT: ref -> f2 79; CHECK-NEXT: ref -> f1 80; CHECK-NOT: -> 81 82entry: 83 br label %next 84 85dead: 86 br label %next 87 88next: 89 phi void ()* [ @f1, %entry ], [ @f2, %dead ] 90 select i1 true, void ()* @f3, void ()* @f4 91 store void ()* @f5, void ()** %x 92 call void @f6() 93 call void (void ()*, void ()*) bitcast (void ()* @f7 to void (void ()*, void ()*)*)(void ()* @f8, void ()* @f9) 94 invoke void @f10() to label %exit unwind label %unwind 95 96exit: 97 ret void ()* @f11 98 99unwind: 100 %res = landingpad { i8*, i32 } 101 cleanup 102 resume { i8*, i32 } { i8* bitcast (void ()* @f12 to i8*), i32 42 } 103} 104 105@g = global void ()* @f1 106@g1 = global [4 x void ()*] [void ()* @f2, void ()* @f3, void ()* @f4, void ()* @f5] 107@g2 = global {i8, void ()*, i8} {i8 1, void ()* @f6, i8 2} 108@h = constant void ()* @f7 109 110define void @test2() { 111; CHECK-LABEL: Edges in function: test2 112; CHECK-NEXT: ref -> f7 113; CHECK-NEXT: ref -> f6 114; CHECK-NEXT: ref -> f5 115; CHECK-NEXT: ref -> f4 116; CHECK-NEXT: ref -> f3 117; CHECK-NEXT: ref -> f2 118; CHECK-NEXT: ref -> f1 119; CHECK-NOT: -> 120 121 load i8*, i8** bitcast (void ()** @g to i8**) 122 load i8*, i8** bitcast (void ()** getelementptr ([4 x void ()*], [4 x void ()*]* @g1, i32 0, i32 2) to i8**) 123 load i8*, i8** bitcast (void ()** getelementptr ({i8, void ()*, i8}, {i8, void ()*, i8}* @g2, i32 0, i32 1) to i8**) 124 load i8*, i8** bitcast (void ()** @h to i8**) 125 ret void 126} 127 128@test3_ptr = external global void ()* 129 130define void @test3_aa1() { 131; CHECK-LABEL: Edges in function: test3_aa1 132; CHECK-NEXT: call -> test3_aa2 133; CHECK-NEXT: ref -> test3_ab1 134; CHECK-NOT: -> 135 136entry: 137 call void @test3_aa2() 138 store void ()* @test3_ab1, void ()** @test3_ptr 139 ret void 140} 141 142define void @test3_aa2() { 143; CHECK-LABEL: Edges in function: test3_aa2 144; CHECK-NEXT: call -> test3_aa1 145; CHECK-NEXT: call -> test3_ab2 146; CHECK-NOT: -> 147 148entry: 149 call void @test3_aa1() 150 call void @test3_ab2() 151 ret void 152} 153 154define void @test3_ab1() { 155; CHECK-LABEL: Edges in function: test3_ab1 156; CHECK-NEXT: call -> test3_ab2 157; CHECK-NEXT: call -> test3_ac1 158; CHECK-NOT: -> 159 160entry: 161 call void @test3_ab2() 162 call void @test3_ac1() 163 ret void 164} 165 166define void @test3_ab2() { 167; CHECK-LABEL: Edges in function: test3_ab2 168; CHECK-NEXT: call -> test3_ab1 169; CHECK-NEXT: call -> test3_ba1 170; CHECK-NOT: -> 171 172entry: 173 call void @test3_ab1() 174 call void @test3_ba1() 175 ret void 176} 177 178define void @test3_ac1() { 179; CHECK-LABEL: Edges in function: test3_ac1 180; CHECK-NEXT: call -> test3_ac2 181; CHECK-NEXT: ref -> test3_aa2 182; CHECK-NOT: -> 183 184entry: 185 call void @test3_ac2() 186 store void ()* @test3_aa2, void ()** @test3_ptr 187 ret void 188} 189 190define void @test3_ac2() { 191; CHECK-LABEL: Edges in function: test3_ac2 192; CHECK-NEXT: call -> test3_ac1 193; CHECK-NEXT: ref -> test3_ba1 194; CHECK-NOT: -> 195 196entry: 197 call void @test3_ac1() 198 store void ()* @test3_ba1, void ()** @test3_ptr 199 ret void 200} 201 202define void @test3_ba1() { 203; CHECK-LABEL: Edges in function: test3_ba1 204; CHECK-NEXT: call -> test3_bb1 205; CHECK-NEXT: ref -> test3_ca1 206; CHECK-NOT: -> 207 208entry: 209 call void @test3_bb1() 210 store void ()* @test3_ca1, void ()** @test3_ptr 211 ret void 212} 213 214define void @test3_bb1() { 215; CHECK-LABEL: Edges in function: test3_bb1 216; CHECK-NEXT: call -> test3_ca2 217; CHECK-NEXT: ref -> test3_ba1 218; CHECK-NOT: -> 219 220entry: 221 call void @test3_ca2() 222 store void ()* @test3_ba1, void ()** @test3_ptr 223 ret void 224} 225 226define void @test3_ca1() { 227; CHECK-LABEL: Edges in function: test3_ca1 228; CHECK-NEXT: call -> test3_ca2 229; CHECK-NOT: -> 230 231entry: 232 call void @test3_ca2() 233 ret void 234} 235 236define void @test3_ca2() { 237; CHECK-LABEL: Edges in function: test3_ca2 238; CHECK-NEXT: call -> test3_ca3 239; CHECK-NOT: -> 240 241entry: 242 call void @test3_ca3() 243 ret void 244} 245 246define void @test3_ca3() { 247; CHECK-LABEL: Edges in function: test3_ca3 248; CHECK-NEXT: call -> test3_ca1 249; CHECK-NOT: -> 250 251entry: 252 call void @test3_ca1() 253 ret void 254} 255 256; Verify the SCCs formed. 257; 258; CHECK-LABEL: RefSCC with 1 call SCCs: 259; CHECK-NEXT: SCC with 3 functions: 260; CHECK-NEXT: test3_ca3 261; CHECK-NEXT: test3_ca1 262; CHECK-NEXT: test3_ca2 263; 264; CHECK-LABEL: RefSCC with 2 call SCCs: 265; CHECK-NEXT: SCC with 1 functions: 266; CHECK-NEXT: test3_bb1 267; CHECK-NEXT: SCC with 1 functions: 268; CHECK-NEXT: test3_ba1 269; 270; CHECK-LABEL: RefSCC with 3 call SCCs: 271; CHECK-NEXT: SCC with 2 functions: 272; CHECK-NEXT: test3_ac2 273; CHECK-NEXT: test3_ac1 274; CHECK-NEXT: SCC with 2 functions: 275; CHECK-NEXT: test3_ab2 276; CHECK-NEXT: test3_ab1 277; CHECK-NEXT: SCC with 2 functions: 278; CHECK-NEXT: test3_aa2 279; CHECK-NEXT: test3_aa1 280; 281; CHECK-LABEL: RefSCC with 1 call SCCs: 282; CHECK-NEXT: SCC with 1 functions: 283; CHECK-NEXT: f7 284; 285; CHECK-LABEL: RefSCC with 1 call SCCs: 286; CHECK-NEXT: SCC with 1 functions: 287; CHECK-NEXT: f6 288; 289; CHECK-LABEL: RefSCC with 1 call SCCs: 290; CHECK-NEXT: SCC with 1 functions: 291; CHECK-NEXT: f5 292; 293; CHECK-LABEL: RefSCC with 1 call SCCs: 294; CHECK-NEXT: SCC with 1 functions: 295; CHECK-NEXT: f4 296; 297; CHECK-LABEL: RefSCC with 1 call SCCs: 298; CHECK-NEXT: SCC with 1 functions: 299; CHECK-NEXT: f3 300; 301; CHECK-LABEL: RefSCC with 1 call SCCs: 302; CHECK-NEXT: SCC with 1 functions: 303; CHECK-NEXT: f2 304; 305; CHECK-LABEL: RefSCC with 1 call SCCs: 306; CHECK-NEXT: SCC with 1 functions: 307; CHECK-NEXT: f1 308; 309; CHECK-LABEL: RefSCC with 1 call SCCs: 310; CHECK-NEXT: SCC with 1 functions: 311; CHECK-NEXT: test2 312; 313; CHECK-LABEL: RefSCC with 1 call SCCs: 314; CHECK-NEXT: SCC with 1 functions: 315; CHECK-NEXT: f10 316; 317; CHECK-LABEL: RefSCC with 1 call SCCs: 318; CHECK-NEXT: SCC with 1 functions: 319; CHECK-NEXT: f12 320; 321; CHECK-LABEL: RefSCC with 1 call SCCs: 322; CHECK-NEXT: SCC with 1 functions: 323; CHECK-NEXT: f11 324; 325; CHECK-LABEL: RefSCC with 1 call SCCs: 326; CHECK-NEXT: SCC with 1 functions: 327; CHECK-NEXT: f9 328; 329; CHECK-LABEL: RefSCC with 1 call SCCs: 330; CHECK-NEXT: SCC with 1 functions: 331; CHECK-NEXT: f8 332; 333; CHECK-LABEL: RefSCC with 1 call SCCs: 334; CHECK-NEXT: SCC with 1 functions: 335; CHECK-NEXT: test1 336; 337; CHECK-LABEL: RefSCC with 1 call SCCs: 338; CHECK-NEXT: SCC with 1 functions: 339; CHECK-NEXT: f 340; 341; CHECK-LABEL: RefSCC with 1 call SCCs: 342; CHECK-NEXT: SCC with 1 functions: 343; CHECK-NEXT: test0 344