1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -S -passes=ipsccp < %s | FileCheck %s 3 4; Make sure we always consider the default edge executable for a switch 5; with no cases. 6declare void @foo() 7declare i32 @g(i32) 8 9define void @test1() { 10; CHECK-LABEL: define void @test1() { 11; CHECK-NEXT: switch i32 undef, label [[D:%.*]] [ 12; CHECK-NEXT: ] 13; CHECK: d: 14; CHECK-NEXT: call void @foo() 15; CHECK-NEXT: ret void 16; 17 switch i32 undef, label %d [] 18d: 19 call void @foo() 20 ret void 21} 22 23define i32 @test_duplicate_successors_phi(i1 %c, i32 %x) { 24; CHECK-LABEL: define i32 @test_duplicate_successors_phi( 25; CHECK-SAME: i1 [[C:%.*]], i32 [[X:%.*]]) { 26; CHECK-NEXT: entry: 27; CHECK-NEXT: br i1 [[C]], label [[SWITCH:%.*]], label [[END:%.*]] 28; CHECK: switch: 29; CHECK-NEXT: br label [[SWITCH_DEFAULT:%.*]] 30; CHECK: switch.default: 31; CHECK-NEXT: ret i32 -1 32; CHECK: end: 33; CHECK-NEXT: ret i32 [[X]] 34; 35entry: 36 br i1 %c, label %switch, label %end 37 38switch: 39 switch i32 -1, label %switch.default [ 40 i32 0, label %end 41 i32 1, label %end 42 ] 43 44switch.default: 45 ret i32 -1 46 47end: 48 %phi = phi i32 [ %x, %entry ], [ 1, %switch ], [ 1, %switch ] 49 ret i32 %phi 50} 51 52define i32 @test_duplicate_successors_phi_2(i1 %c, i32 %x) { 53; CHECK-LABEL: define i32 @test_duplicate_successors_phi_2( 54; CHECK-SAME: i1 [[C:%.*]], i32 [[X:%.*]]) { 55; CHECK-NEXT: entry: 56; CHECK-NEXT: br i1 [[C]], label [[SWITCH:%.*]], label [[END:%.*]] 57; CHECK: switch: 58; CHECK-NEXT: br label [[END]] 59; CHECK: end: 60; CHECK-NEXT: [[PHI:%.*]] = phi i32 [ [[X]], [[ENTRY:%.*]] ], [ 1, [[SWITCH]] ] 61; CHECK-NEXT: ret i32 [[PHI]] 62; 63entry: 64 br i1 %c, label %switch, label %end 65 66switch: 67 switch i32 0, label %switch.default [ 68 i32 0, label %end 69 i32 1, label %end 70 ] 71 72switch.default: 73 ret i32 -1 74 75end: 76 %phi = phi i32 [ %x, %entry ], [ 1, %switch ], [ 1, %switch ] 77 ret i32 %phi 78} 79 80define i32 @test_duplicate_successors_phi_3(i1 %c1, ptr %p, i32 %y) { 81; CHECK-LABEL: define i32 @test_duplicate_successors_phi_3( 82; CHECK-SAME: i1 [[C1:%.*]], ptr [[P:%.*]], i32 [[Y:%.*]]) { 83; CHECK-NEXT: entry: 84; CHECK-NEXT: br i1 [[C1]], label [[SWITCH:%.*]], label [[SWITCH_1:%.*]] 85; CHECK: switch: 86; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0:![0-9]+]] 87; CHECK-NEXT: switch i32 [[X]], label [[SWITCH_DEFAULT:%.*]] [ 88; CHECK-NEXT: i32 0, label [[SWITCH_DEFAULT]] 89; CHECK-NEXT: i32 1, label [[SWITCH_0:%.*]] 90; CHECK-NEXT: i32 2, label [[SWITCH_0]] 91; CHECK-NEXT: ] 92; CHECK: switch.default: 93; CHECK-NEXT: ret i32 -1 94; CHECK: switch.0: 95; CHECK-NEXT: ret i32 0 96; CHECK: switch.1: 97; CHECK-NEXT: ret i32 [[Y]] 98; 99entry: 100 br i1 %c1, label %switch, label %switch.1 101 102switch: 103 %x = load i32, ptr %p, !range !{i32 0, i32 3} 104 switch i32 %x, label %switch.default [ 105 i32 0, label %switch.default 106 i32 1, label %switch.0 107 i32 2, label %switch.0 108 i32 3, label %switch.1 109 i32 4, label %switch.1 110 ] 111 112switch.default: 113 ret i32 -1 114 115switch.0: 116 ret i32 0 117 118switch.1: 119 %phi = phi i32 [ %y, %entry ], [ 0, %switch ], [ 0, %switch ] 120 ret i32 %phi 121} 122 123define i32 @test_local_range(ptr %p) { 124; CHECK-LABEL: define range(i32 0, 3) i32 @test_local_range( 125; CHECK-SAME: ptr [[P:%.*]]) { 126; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0]] 127; CHECK-NEXT: switch i32 [[X]], label [[DEFAULT_UNREACHABLE:%.*]] [ 128; CHECK-NEXT: i32 0, label [[SWITCH_0:%.*]] 129; CHECK-NEXT: i32 1, label [[SWITCH_1:%.*]] 130; CHECK-NEXT: i32 2, label [[SWITCH_2:%.*]] 131; CHECK-NEXT: ] 132; CHECK: default.unreachable: 133; CHECK-NEXT: unreachable 134; CHECK: switch.0: 135; CHECK-NEXT: ret i32 0 136; CHECK: switch.1: 137; CHECK-NEXT: ret i32 1 138; CHECK: switch.2: 139; CHECK-NEXT: ret i32 2 140; 141 %x = load i32, ptr %p, !range !{i32 0, i32 3} 142 switch i32 %x, label %switch.default [ 143 i32 0, label %switch.0 144 i32 1, label %switch.1 145 i32 2, label %switch.2 146 i32 3, label %switch.3 147 ] 148 149switch.default: 150 ret i32 -1 151 152switch.0: 153 ret i32 0 154 155switch.1: 156 ret i32 1 157 158switch.2: 159 ret i32 2 160 161switch.3: 162 ret i32 3 163} 164 165; TODO: Determine that case i3 is dead, even though the edge is shared? 166define i32 @test_duplicate_successors(ptr %p) { 167; CHECK-LABEL: define range(i32 0, 2) i32 @test_duplicate_successors( 168; CHECK-SAME: ptr [[P:%.*]]) { 169; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 4, !range [[RNG0]] 170; CHECK-NEXT: switch i32 [[X]], label [[DEFAULT_UNREACHABLE:%.*]] [ 171; CHECK-NEXT: i32 0, label [[SWITCH_0:%.*]] 172; CHECK-NEXT: i32 1, label [[SWITCH_0]] 173; CHECK-NEXT: i32 2, label [[SWITCH_1:%.*]] 174; CHECK-NEXT: i32 3, label [[SWITCH_1]] 175; CHECK-NEXT: ] 176; CHECK: default.unreachable: 177; CHECK-NEXT: unreachable 178; CHECK: switch.0: 179; CHECK-NEXT: ret i32 0 180; CHECK: switch.1: 181; CHECK-NEXT: ret i32 1 182; 183 %x = load i32, ptr %p, !range !{i32 0, i32 3} 184 switch i32 %x, label %switch.default [ 185 i32 0, label %switch.0 186 i32 1, label %switch.0 187 i32 2, label %switch.1 188 i32 3, label %switch.1 189 i32 4, label %switch.2 190 i32 5, label %switch.2 191 ] 192 193switch.default: 194 ret i32 -1 195 196switch.0: 197 ret i32 0 198 199switch.1: 200 ret i32 1 201 202switch.2: 203 ret i32 2 204} 205 206; Case i32 2 is dead as well, but this cannot be determined based on 207; range information. 208define internal i32 @test_ip_range(i32 %x) { 209; CHECK-LABEL: define internal range(i32 1, 4) i32 @test_ip_range( 210; CHECK-SAME: i32 range(i32 1, 4) [[X:%.*]]) { 211; CHECK-NEXT: switch i32 [[X]], label [[DEFAULT_UNREACHABLE:%.*]] [ 212; CHECK-NEXT: i32 3, label [[SWITCH_3:%.*]] 213; CHECK-NEXT: i32 1, label [[SWITCH_1:%.*]] 214; CHECK-NEXT: i32 2, label [[SWITCH_2:%.*]] 215; CHECK-NEXT: ], !prof [[PROF1:![0-9]+]] 216; CHECK: default.unreachable: 217; CHECK-NEXT: unreachable 218; CHECK: switch.1: 219; CHECK-NEXT: ret i32 1 220; CHECK: switch.2: 221; CHECK-NEXT: ret i32 2 222; CHECK: switch.3: 223; CHECK-NEXT: ret i32 3 224; 225 switch i32 %x, label %switch.default [ 226 i32 0, label %switch.0 227 i32 1, label %switch.1 228 i32 2, label %switch.2 229 i32 3, label %switch.3 230 ], !prof !{!"branch_weights", i32 1, i32 2, i32 3, i32 4, i32 5} 231 232switch.default: 233 ret i32 -1 234 235switch.0: 236 ret i32 0 237 238switch.1: 239 ret i32 1 240 241switch.2: 242 ret i32 2 243 244switch.3: 245 ret i32 3 246} 247 248define void @call_test_ip_range() { 249; CHECK-LABEL: define void @call_test_ip_range() { 250; CHECK-NEXT: [[TMP1:%.*]] = call i32 @test_ip_range(i32 1) 251; CHECK-NEXT: [[TMP2:%.*]] = call i32 @test_ip_range(i32 3) 252; CHECK-NEXT: ret void 253; 254 call i32 @test_ip_range(i32 1) 255 call i32 @test_ip_range(i32 3) 256 ret void 257} 258 259define i32 @test_switch_range_may_include_undef(i1 %c.1, i1 %c.2, i32 %x) { 260; CHECK-LABEL: define range(i32 -1, 21) i32 @test_switch_range_may_include_undef( 261; CHECK-SAME: i1 [[C_1:%.*]], i1 [[C_2:%.*]], i32 [[X:%.*]]) { 262; CHECK-NEXT: entry: 263; CHECK-NEXT: br i1 [[C_1]], label [[THEN_1:%.*]], label [[ELSE_1:%.*]] 264; CHECK: then.1: 265; CHECK-NEXT: br i1 [[C_2]], label [[SWITCH:%.*]], label [[ELSE_2:%.*]] 266; CHECK: else.1: 267; CHECK-NEXT: br label [[SWITCH]] 268; CHECK: else.2: 269; CHECK-NEXT: br label [[SWITCH]] 270; CHECK: switch: 271; CHECK-NEXT: [[P:%.*]] = phi i32 [ 0, [[THEN_1]] ], [ 2, [[ELSE_1]] ], [ undef, [[ELSE_2]] ] 272; CHECK-NEXT: switch i32 [[P]], label [[SWITCH_DEFAULT:%.*]] [ 273; CHECK-NEXT: i32 0, label [[END_1:%.*]] 274; CHECK-NEXT: i32 3, label [[END_2:%.*]] 275; CHECK-NEXT: ] 276; CHECK: switch.default: 277; CHECK-NEXT: ret i32 -1 278; CHECK: end.1: 279; CHECK-NEXT: ret i32 10 280; CHECK: end.2: 281; CHECK-NEXT: ret i32 20 282; 283entry: 284 br i1 %c.1, label %then.1, label %else.1 285 286then.1: 287 br i1 %c.2, label %switch, label %else.2 288 289else.1: 290 br label %switch 291 292else.2: 293 br label %switch 294 295switch: 296 %p = phi i32 [ 0, %then.1 ], [ 2, %else.1 ], [ undef, %else.2 ] 297 switch i32 %p, label %switch.default [ 298 i32 0, label %end.1 299 i32 3, label %end.2 300 ] 301 302switch.default: 303 ret i32 -1 304 305end.1: 306 ret i32 10 307 308end.2: 309 ret i32 20 310} 311 312define i32 @test_default_unreachable_by_dom_cond(i32 %x) { 313; CHECK-LABEL: define i32 @test_default_unreachable_by_dom_cond( 314; CHECK-SAME: i32 [[X:%.*]]) { 315; CHECK-NEXT: entry: 316; CHECK-NEXT: [[OR_COND:%.*]] = icmp ult i32 [[X]], 4 317; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] 318; CHECK: if.then: 319; CHECK-NEXT: switch i32 [[X]], label [[DEFAULT_UNREACHABLE:%.*]] [ 320; CHECK-NEXT: i32 0, label [[SW_BB:%.*]] 321; CHECK-NEXT: i32 1, label [[SW_BB2:%.*]] 322; CHECK-NEXT: i32 2, label [[SW_BB4:%.*]] 323; CHECK-NEXT: i32 3, label [[SW_BB6:%.*]] 324; CHECK-NEXT: ] 325; CHECK: sw.bb: 326; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @g(i32 2) 327; CHECK-NEXT: br label [[RETURN]] 328; CHECK: sw.bb2: 329; CHECK-NEXT: [[CALL3:%.*]] = tail call i32 @g(i32 3) 330; CHECK-NEXT: br label [[RETURN]] 331; CHECK: sw.bb4: 332; CHECK-NEXT: [[CALL5:%.*]] = tail call i32 @g(i32 4) 333; CHECK-NEXT: br label [[RETURN]] 334; CHECK: sw.bb6: 335; CHECK-NEXT: [[CALL7:%.*]] = tail call i32 @g(i32 5) 336; CHECK-NEXT: br label [[RETURN]] 337; CHECK: default.unreachable: 338; CHECK-NEXT: unreachable 339; CHECK: return: 340; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL7]], [[SW_BB6]] ], [ [[CALL5]], [[SW_BB4]] ], [ [[CALL3]], [[SW_BB2]] ], [ [[CALL]], [[SW_BB]] ], [ -23, [[ENTRY:%.*]] ] 341; CHECK-NEXT: ret i32 [[RETVAL_0]] 342; 343entry: 344 %or.cond = icmp ult i32 %x, 4 345 br i1 %or.cond, label %if.then, label %return 346 347if.then: 348 switch i32 %x, label %sw.epilog [ 349 i32 0, label %sw.bb 350 i32 1, label %sw.bb2 351 i32 2, label %sw.bb4 352 i32 3, label %sw.bb6 353 ] 354 355sw.bb: 356 %call = tail call i32 @g(i32 2) 357 br label %return 358 359sw.bb2: 360 %call3 = tail call i32 @g(i32 3) 361 br label %return 362 363sw.bb4: 364 %call5 = tail call i32 @g(i32 4) 365 br label %return 366 367sw.bb6: 368 %call7 = tail call i32 @g(i32 5) 369 br label %return 370 371sw.epilog: 372 call void @foo() 373 br label %return 374 375return: 376 %retval.0 = phi i32 [ %call7, %sw.bb6 ], [ %call5, %sw.bb4 ], [ %call3, %sw.bb2 ], [ %call, %sw.bb ], [ -23, %sw.epilog ], [ -23, %entry ] 377 ret i32 %retval.0 378} 379 380declare void @llvm.assume(i1) 381 382;. 383; CHECK: [[RNG0]] = !{i32 0, i32 3} 384; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 5, i32 3, i32 4} 385;. 386