1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3 2; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s 3 4; Test a bunch of cases where the combination of phis in switch should be merged into one phi 5 6declare void @use(i8) 7 8define i8 @phis_of_switch_minimal(i8 noundef %arg) { 9; CHECK-LABEL: define i8 @phis_of_switch_minimal( 10; CHECK-SAME: i8 noundef [[ARG:%.*]]) { 11; CHECK-NEXT: start: 12; CHECK-NEXT: switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [ 13; CHECK-NEXT: i8 0, label [[CASE01:%.*]] 14; CHECK-NEXT: i8 1, label [[CASE1:%.*]] 15; CHECK-NEXT: i8 2, label [[END:%.*]] 16; CHECK-NEXT: ] 17; CHECK: unreachable: 18; CHECK-NEXT: unreachable 19; CHECK: case1: 20; CHECK-NEXT: br label [[END]] 21; CHECK: case01: 22; CHECK-NEXT: br label [[END]] 23; CHECK: end: 24; CHECK-NEXT: [[PHI2:%.*]] = phi i8 [ 3, [[START:%.*]] ], [ 2, [[CASE1]] ], [ 1, [[CASE01]] ] 25; CHECK-NEXT: ret i8 [[PHI2]] 26; 27start: 28 switch i8 %arg, label %unreachable [ 29 i8 0, label %case01 30 i8 1, label %case1 31 i8 2, label %end 32 ] 33unreachable: 34 unreachable 35case1: 36 br label %case01 37 38case01: 39 %phi1 = phi i8 [ 2, %case1 ], [1, %start] 40 br label %end 41 42end: 43 %phi2 = phi i8 [ %phi1, %case01 ], [ 3, %start ] 44 ret i8 %phi2 45} 46 47define i8 @phis_of_switch(i8 noundef %arg) { 48; CHECK-LABEL: define i8 @phis_of_switch( 49; CHECK-SAME: i8 noundef [[ARG:%.*]]) { 50; CHECK-NEXT: start: 51; CHECK-NEXT: switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [ 52; CHECK-NEXT: i8 0, label [[CASE012:%.*]] 53; CHECK-NEXT: i8 1, label [[CASE1:%.*]] 54; CHECK-NEXT: i8 2, label [[CASE2:%.*]] 55; CHECK-NEXT: i8 3, label [[END:%.*]] 56; CHECK-NEXT: ] 57; CHECK: unreachable: 58; CHECK-NEXT: unreachable 59; CHECK: case1: 60; CHECK-NEXT: br label [[END]] 61; CHECK: case2: 62; CHECK-NEXT: br label [[END]] 63; CHECK: case012: 64; CHECK-NEXT: br label [[END]] 65; CHECK: end: 66; CHECK-NEXT: [[PHI2:%.*]] = phi i8 [ 4, [[START:%.*]] ], [ 3, [[CASE2]] ], [ 2, [[CASE1]] ], [ 1, [[CASE012]] ] 67; CHECK-NEXT: ret i8 [[PHI2]] 68; 69start: 70 switch i8 %arg, label %unreachable [ 71 i8 0, label %case012 72 i8 1, label %case1 73 i8 2, label %case2 74 i8 3, label %end 75 ] 76unreachable: 77 unreachable 78case1: 79 br label %case012 80 81case2: 82 br label %case012 83 84case012: 85 %phi1 = phi i8 [ 3, %case2 ], [ 2, %case1 ], [1, %start] 86 br label %end 87 88end: 89 %phi2 = phi i8 [ %phi1, %case012 ], [ 4, %start ] 90 ret i8 %phi2 91} 92 93define i8 @multiple_phis_of_switch(i8 noundef %arg) { 94; CHECK-LABEL: define i8 @multiple_phis_of_switch( 95; CHECK-SAME: i8 noundef [[ARG:%.*]]) { 96; CHECK-NEXT: start: 97; CHECK-NEXT: switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [ 98; CHECK-NEXT: i8 0, label [[CASE012:%.*]] 99; CHECK-NEXT: i8 1, label [[CASE1:%.*]] 100; CHECK-NEXT: i8 2, label [[CASE2:%.*]] 101; CHECK-NEXT: i8 3, label [[END:%.*]] 102; CHECK-NEXT: ] 103; CHECK: unreachable: 104; CHECK-NEXT: unreachable 105; CHECK: case1: 106; CHECK-NEXT: br label [[END]] 107; CHECK: case2: 108; CHECK-NEXT: br label [[END]] 109; CHECK: case012: 110; CHECK-NEXT: br label [[END]] 111; CHECK: end: 112; CHECK-NEXT: [[PHI2_1:%.*]] = phi i8 [ 4, [[START:%.*]] ], [ 3, [[CASE2]] ], [ 2, [[CASE1]] ], [ 1, [[CASE012]] ] 113; CHECK-NEXT: [[PHI2_2:%.*]] = phi i8 [ 5, [[START]] ], [ 3, [[CASE2]] ], [ 2, [[CASE1]] ], [ 1, [[CASE012]] ] 114; CHECK-NEXT: [[PHI2_3:%.*]] = phi i8 [ 3, [[START]] ], [ 6, [[CASE2]] ], [ 5, [[CASE1]] ], [ 4, [[CASE012]] ] 115; CHECK-NEXT: call void @use(i8 [[PHI2_1]]) 116; CHECK-NEXT: call void @use(i8 [[PHI2_2]]) 117; CHECK-NEXT: call void @use(i8 [[PHI2_3]]) 118; CHECK-NEXT: ret i8 [[PHI2_1]] 119; 120start: 121 switch i8 %arg, label %unreachable [ 122 i8 0, label %case012 123 i8 1, label %case1 124 i8 2, label %case2 125 i8 3, label %end 126 ] 127unreachable: 128 unreachable 129case1: 130 br label %case012 131 132case2: 133 br label %case012 134 135case012: 136 %phi1_1 = phi i8 [ 3, %case2 ], [ 2, %case1 ], [1, %start] 137 %phi1_2 = phi i8 [ 6, %case2 ], [ 5, %case1 ], [4, %start] 138 br label %end 139 140end: 141 %phi2_1 = phi i8 [ %phi1_1, %case012 ], [ 4, %start ] 142 %phi2_2 = phi i8 [ %phi1_1, %case012 ], [ 5, %start ] 143 %phi2_3 = phi i8 [ %phi1_2, %case012 ], [ 3, %start ] 144 call void @use(i8 %phi2_1) 145 call void @use(i8 %phi2_2) 146 call void @use(i8 %phi2_3) 147 ret i8 %phi2_1 148} 149 150define i8 @phis_of_switch_multiple_stage0(i8 noundef %arg) { 151; CHECK-LABEL: define i8 @phis_of_switch_multiple_stage0( 152; CHECK-SAME: i8 noundef [[ARG:%.*]]) { 153; CHECK-NEXT: start: 154; CHECK-NEXT: switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [ 155; CHECK-NEXT: i8 0, label [[CASE0:%.*]] 156; CHECK-NEXT: i8 1, label [[CASE1:%.*]] 157; CHECK-NEXT: i8 2, label [[CASE2:%.*]] 158; CHECK-NEXT: i8 3, label [[CASE0123:%.*]] 159; CHECK-NEXT: i8 4, label [[CASE01234:%.*]] 160; CHECK-NEXT: i8 5, label [[END:%.*]] 161; CHECK-NEXT: ] 162; CHECK: unreachable: 163; CHECK-NEXT: unreachable 164; CHECK: case0: 165; CHECK-NEXT: br label [[END]] 166; CHECK: case1: 167; CHECK-NEXT: br label [[END]] 168; CHECK: case2: 169; CHECK-NEXT: br label [[END]] 170; CHECK: case0123: 171; CHECK-NEXT: br label [[END]] 172; CHECK: case01234: 173; CHECK-NEXT: br label [[END]] 174; CHECK: end: 175; CHECK-NEXT: [[PHI3:%.*]] = phi i8 [ 6, [[START:%.*]] ], [ 3, [[CASE2]] ], [ 2, [[CASE1]] ], [ 1, [[CASE0]] ], [ 4, [[CASE0123]] ], [ 5, [[CASE01234]] ] 176; CHECK-NEXT: ret i8 [[PHI3]] 177; 178start: 179 switch i8 %arg, label %unreachable [ 180 i8 0, label %case0 181 i8 1, label %case1 182 i8 2, label %case2 183 i8 3, label %case0123 184 i8 4, label %case01234 185 i8 5, label %end 186 ] 187unreachable: 188 unreachable 189 190case0: 191 br label %case0123 192 193case1: 194 br label %case0123 195 196case2: 197 br label %case0123 198 199case0123: 200 %phi1 = phi i8 [4, %start], [ 3, %case2 ], [ 2, %case1 ], [ 1, %case0 ] 201 br label %case01234 202 203case01234: 204 %phi2 = phi i8 [ %phi1, %case0123 ], [ 5, %start ] 205 br label %end 206 207end: 208 %phi3 = phi i8 [ %phi2, %case01234 ], [6, %start] 209 ret i8 %phi3 210} 211 212define i8 @phis_of_switch_multiple_stage1(i8 noundef %arg) { 213; CHECK-LABEL: define i8 @phis_of_switch_multiple_stage1( 214; CHECK-SAME: i8 noundef [[ARG:%.*]]) { 215; CHECK-NEXT: start: 216; CHECK-NEXT: switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [ 217; CHECK-NEXT: i8 0, label [[CASE0:%.*]] 218; CHECK-NEXT: i8 1, label [[CASE1:%.*]] 219; CHECK-NEXT: i8 2, label [[CASE012:%.*]] 220; CHECK-NEXT: i8 3, label [[CASE3:%.*]] 221; CHECK-NEXT: i8 4, label [[CASE4:%.*]] 222; CHECK-NEXT: i8 5, label [[CASE345:%.*]] 223; CHECK-NEXT: i8 6, label [[CASE0123456:%.*]] 224; CHECK-NEXT: ] 225; CHECK: unreachable: 226; CHECK-NEXT: unreachable 227; CHECK: case0: 228; CHECK-NEXT: br label [[CASE0123456]] 229; CHECK: case1: 230; CHECK-NEXT: br label [[CASE0123456]] 231; CHECK: case012: 232; CHECK-NEXT: br label [[CASE0123456]] 233; CHECK: case3: 234; CHECK-NEXT: br label [[CASE0123456]] 235; CHECK: case4: 236; CHECK-NEXT: br label [[CASE0123456]] 237; CHECK: case345: 238; CHECK-NEXT: br label [[CASE0123456]] 239; CHECK: case0123456: 240; CHECK-NEXT: [[PHI1234567:%.*]] = phi i8 [ 7, [[START:%.*]] ], [ 2, [[CASE1]] ], [ 1, [[CASE0]] ], [ 3, [[CASE012]] ], [ 5, [[CASE4]] ], [ 4, [[CASE3]] ], [ 6, [[CASE345]] ] 241; CHECK-NEXT: ret i8 [[PHI1234567]] 242; 243start: 244 switch i8 %arg, label %unreachable [ 245 i8 0, label %case0 246 i8 1, label %case1 247 i8 2, label %case012 248 i8 3, label %case3 249 i8 4, label %case4 250 i8 5, label %case345 251 i8 6, label %case0123456 252 ] 253unreachable: 254 unreachable 255case0: 256 br label %case012 257 258case1: 259 br label %case012 260 261case012: 262 %phi123 = phi i8 [3, %start], [ 2, %case1 ], [ 1, %case0 ] 263 br label %case0123456 264 265case3: 266 br label %case345 267 268case4: 269 br label %case345 270 271case345: 272 %phi456 = phi i8 [6, %start], [ 5, %case4 ], [ 4, %case3 ] 273 br label %case0123456 274 275case0123456: 276 %phi1234567 = phi i8 [7, %start], [ %phi456, %case345 ], [ %phi123, %case012 ] 277 ret i8 %phi1234567 278 279} 280 281define i8 @phis_of_switch_extra_use_fail(i8 noundef %arg) { 282; CHECK-LABEL: define i8 @phis_of_switch_extra_use_fail( 283; CHECK-SAME: i8 noundef [[ARG:%.*]]) { 284; CHECK-NEXT: start: 285; CHECK-NEXT: switch i8 [[ARG]], label [[UNREACHABLE:%.*]] [ 286; CHECK-NEXT: i8 0, label [[CASE012:%.*]] 287; CHECK-NEXT: i8 1, label [[CASE1:%.*]] 288; CHECK-NEXT: i8 2, label [[CASE2:%.*]] 289; CHECK-NEXT: i8 3, label [[END:%.*]] 290; CHECK-NEXT: ] 291; CHECK: unreachable: 292; CHECK-NEXT: unreachable 293; CHECK: case1: 294; CHECK-NEXT: br label [[CASE012]] 295; CHECK: case2: 296; CHECK-NEXT: br label [[CASE012]] 297; CHECK: case012: 298; CHECK-NEXT: [[PHI1:%.*]] = phi i8 [ 3, [[CASE2]] ], [ 2, [[CASE1]] ], [ 1, [[START:%.*]] ] 299; CHECK-NEXT: call void @use(i8 [[PHI1]]) 300; CHECK-NEXT: br label [[END]] 301; CHECK: end: 302; CHECK-NEXT: [[PHI2:%.*]] = phi i8 [ [[PHI1]], [[CASE012]] ], [ 4, [[START]] ] 303; CHECK-NEXT: ret i8 [[PHI2]] 304; 305start: 306 switch i8 %arg, label %unreachable [ 307 i8 0, label %case012 308 i8 1, label %case1 309 i8 2, label %case2 i8 3, label %end 310 ] 311unreachable: 312 unreachable 313case1: 314 br label %case012 315 316case2: 317 br label %case012 318 319case012: 320 %phi1 = phi i8 [ 3, %case2 ], [ 2, %case1 ], [1, %start] 321 call void @use(i8 %phi1) 322 br label %end 323 324end: 325 %phi2 = phi i8 [ %phi1, %case012 ], [ 4, %start ] 326 ret i8 %phi2 327} 328