1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s 3 4; int foo1_with_default(int a) { 5; switch(a) { 6; case 10: 7; return 10; 8; case 20: 9; return 2; 10; } 11; return 4; 12; } 13 14define i32 @foo1_with_default(i32 %a) { 15; CHECK-LABEL: @foo1_with_default( 16; CHECK-NEXT: entry: 17; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[A:%.*]], 20 18; CHECK-NEXT: [[SWITCH_SELECT:%.*]] = select i1 [[SWITCH_SELECTCMP]], i32 2, i32 4 19; CHECK-NEXT: [[SWITCH_SELECTCMP1:%.*]] = icmp eq i32 [[A]], 10 20; CHECK-NEXT: [[SWITCH_SELECT2:%.*]] = select i1 [[SWITCH_SELECTCMP1]], i32 10, i32 [[SWITCH_SELECT]] 21; CHECK-NEXT: ret i32 [[SWITCH_SELECT2]] 22; 23entry: 24 switch i32 %a, label %sw.epilog [ 25 i32 10, label %sw.bb 26 i32 20, label %sw.bb1 27 ] 28 29sw.bb: 30 br label %return 31 32sw.bb1: 33 br label %return 34 35sw.epilog: 36 br label %return 37 38return: 39 %retval.0 = phi i32 [ 4, %sw.epilog ], [ 2, %sw.bb1 ], [ 10, %sw.bb ] 40 ret i32 %retval.0 41} 42 43; Same as above, but both cases have the same value. 44define i32 @same_value(i32 %a) { 45; CHECK-LABEL: @same_value( 46; CHECK-NEXT: entry: 47; CHECK-NEXT: [[SWITCH_SELECTCMP_CASE1:%.*]] = icmp eq i32 [[A:%.*]], 10 48; CHECK-NEXT: [[SWITCH_SELECTCMP_CASE2:%.*]] = icmp eq i32 [[A]], 20 49; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = or i1 [[SWITCH_SELECTCMP_CASE1]], [[SWITCH_SELECTCMP_CASE2]] 50; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[SWITCH_SELECTCMP]], i32 10, i32 4 51; CHECK-NEXT: ret i32 [[TMP0]] 52; 53entry: 54 switch i32 %a, label %sw.epilog [ 55 i32 10, label %sw.bb 56 i32 20, label %sw.bb 57 ] 58 59sw.bb: 60 br label %return 61 62sw.epilog: 63 br label %return 64 65return: 66 %retval.0 = phi i32 [ 4, %sw.epilog ], [ 10, %sw.bb ] 67 ret i32 %retval.0 68} 69 70define i1 @switch_to_select_same2_case_results_different_default(i8 %0) { 71; CHECK-LABEL: @switch_to_select_same2_case_results_different_default( 72; CHECK-NEXT: [[SWITCH_AND:%.*]] = and i8 [[TMP0:%.*]], -5 73; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i8 [[SWITCH_AND]], 0 74; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[SWITCH_SELECTCMP]], i1 true, i1 false 75; CHECK-NEXT: ret i1 [[TMP2]] 76; 77 switch i8 %0, label %2 [ 78 i8 4, label %3 79 i8 0, label %3 80 ] 81 822: 83 br label %3 84 853: 86 %4 = phi i1 [ false, %2 ], [ true, %1 ], [ true, %1 ] 87 ret i1 %4 88} 89 90define i1 @switch_to_select_same2_case_results_different_default_and_positive_offset_for_case(i8 %0) { 91; CHECK-LABEL: @switch_to_select_same2_case_results_different_default_and_positive_offset_for_case( 92; CHECK-NEXT: [[TMP2:%.*]] = sub i8 [[TMP0:%.*]], 43 93; CHECK-NEXT: [[SWITCH_AND:%.*]] = and i8 [[TMP2]], -3 94; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i8 [[SWITCH_AND]], 0 95; CHECK-NEXT: [[TMP3:%.*]] = select i1 [[SWITCH_SELECTCMP]], i1 true, i1 false 96; CHECK-NEXT: ret i1 [[TMP3]] 97; 98 switch i8 %0, label %2 [ 99 i8 43, label %3 100 i8 45, label %3 101 ] 102 1032: 104 br label %3 105 1063: 107 %4 = phi i1 [ false, %2 ], [ true, %1 ], [ true, %1 ] 108 ret i1 %4 109} 110 111define i8 @switch_to_select_same2_case_results_different_default_and_negative_offset_for_case(i32 %i) { 112; CHECK-LABEL: @switch_to_select_same2_case_results_different_default_and_negative_offset_for_case( 113; CHECK-NEXT: entry: 114; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[I:%.*]], -5 115; CHECK-NEXT: [[SWITCH_AND:%.*]] = and i32 [[TMP0]], -3 116; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[SWITCH_AND]], 0 117; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[SWITCH_SELECTCMP]], i8 3, i8 42 118; CHECK-NEXT: ret i8 [[TMP1]] 119; 120entry: 121 switch i32 %i, label %default [ 122 i32 -3, label %end 123 i32 -5, label %end 124 ] 125 126default: 127 br label %end 128 129end: 130 %t0 = phi i8 [ 42, %default ], [ 3, %entry ], [ 3, %entry ] 131 ret i8 %t0 132} 133 134define i1 @switch_to_select_same4_case_results_different_default(i32 %i) { 135; CHECK-LABEL: @switch_to_select_same4_case_results_different_default( 136; CHECK-NEXT: entry: 137; CHECK-NEXT: [[SWITCH_AND:%.*]] = and i32 [[I:%.*]], -7 138; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[SWITCH_AND]], 0 139; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[SWITCH_SELECTCMP]], i1 true, i1 false 140; CHECK-NEXT: ret i1 [[TMP0]] 141; 142entry: 143 switch i32 %i, label %lor.rhs [ 144 i32 0, label %lor.end 145 i32 2, label %lor.end 146 i32 4, label %lor.end 147 i32 6, label %lor.end 148 ] 149 150lor.rhs: 151 br label %lor.end 152 153lor.end: 154 %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ], [ true, %entry ] 155 ret i1 %0 156} 157 158define i1 @switch_to_select_same4_case_results_different_default_alt_bitmask(i32 %i) { 159; CHECK-LABEL: @switch_to_select_same4_case_results_different_default_alt_bitmask( 160; CHECK-NEXT: entry: 161; CHECK-NEXT: [[SWITCH_AND:%.*]] = and i32 [[I:%.*]], -11 162; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[SWITCH_AND]], 0 163; CHECK-NEXT: [[TMP0:%.*]] = select i1 [[SWITCH_SELECTCMP]], i1 true, i1 false 164; CHECK-NEXT: ret i1 [[TMP0]] 165; 166entry: 167 switch i32 %i, label %lor.rhs [ 168 i32 0, label %lor.end 169 i32 2, label %lor.end 170 i32 8, label %lor.end 171 i32 10, label %lor.end 172 ] 173 174lor.rhs: 175 br label %lor.end 176 177lor.end: 178 %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ], [ true, %entry ] 179 ret i1 %0 180} 181 182define i1 @switch_to_select_same4_case_results_different_default_positive_offset(i32 %i) { 183; CHECK-LABEL: @switch_to_select_same4_case_results_different_default_positive_offset( 184; CHECK-NEXT: entry: 185; CHECK-NEXT: [[TMP0:%.*]] = sub i32 [[I:%.*]], 2 186; CHECK-NEXT: [[SWITCH_AND:%.*]] = and i32 [[TMP0]], -11 187; CHECK-NEXT: [[SWITCH_SELECTCMP:%.*]] = icmp eq i32 [[SWITCH_AND]], 0 188; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[SWITCH_SELECTCMP]], i1 true, i1 false 189; CHECK-NEXT: ret i1 [[TMP1]] 190; 191entry: 192 switch i32 %i, label %lor.rhs [ 193 i32 2, label %lor.end 194 i32 4, label %lor.end 195 i32 10, label %lor.end 196 i32 12, label %lor.end 197 ] 198 199lor.rhs: 200 br label %lor.end 201 202lor.end: 203 %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ], [ true, %entry ] 204 ret i1 %0 205} 206 207define i1 @switch_to_select_invalid_mask(i32 %i) { 208; CHECK-LABEL: @switch_to_select_invalid_mask( 209; CHECK-NEXT: entry: 210; CHECK-NEXT: switch i32 [[I:%.*]], label [[LOR_RHS:%.*]] [ 211; CHECK-NEXT: i32 1, label [[LOR_END:%.*]] 212; CHECK-NEXT: i32 4, label [[LOR_END]] 213; CHECK-NEXT: i32 10, label [[LOR_END]] 214; CHECK-NEXT: i32 12, label [[LOR_END]] 215; CHECK-NEXT: ] 216; CHECK: lor.rhs: 217; CHECK-NEXT: br label [[LOR_END]] 218; CHECK: lor.end: 219; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ] 220; CHECK-NEXT: ret i1 [[TMP0]] 221; 222entry: 223 switch i32 %i, label %lor.rhs [ 224 i32 1, label %lor.end 225 i32 4, label %lor.end 226 i32 10, label %lor.end 227 i32 12, label %lor.end 228 ] 229 230lor.rhs: 231 br label %lor.end 232 233lor.end: 234 %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ], [ true, %entry ] 235 ret i1 %0 236} 237 238define i1 @switch_to_select_nonpow2_cases(i32 %i) { 239; CHECK-LABEL: @switch_to_select_nonpow2_cases( 240; CHECK-NEXT: entry: 241; CHECK-NEXT: switch i32 [[I:%.*]], label [[LOR_RHS:%.*]] [ 242; CHECK-NEXT: i32 0, label [[LOR_END:%.*]] 243; CHECK-NEXT: i32 2, label [[LOR_END]] 244; CHECK-NEXT: i32 4, label [[LOR_END]] 245; CHECK-NEXT: ] 246; CHECK: lor.rhs: 247; CHECK-NEXT: br label [[LOR_END]] 248; CHECK: lor.end: 249; CHECK-NEXT: [[TMP0:%.*]] = phi i1 [ true, [[ENTRY:%.*]] ], [ false, [[LOR_RHS]] ], [ true, [[ENTRY]] ], [ true, [[ENTRY]] ] 250; CHECK-NEXT: ret i1 [[TMP0]] 251; 252entry: 253 switch i32 %i, label %lor.rhs [ 254 i32 0, label %lor.end 255 i32 2, label %lor.end 256 i32 4, label %lor.end 257 ] 258 259lor.rhs: 260 br label %lor.end 261 262lor.end: 263 %0 = phi i1 [ true, %entry ], [ false, %lor.rhs ], [ true, %entry ], [ true, %entry ] 264 ret i1 %0 265} 266 267; TODO: we can produce the optimal code when there is no default also 268define i8 @switch_to_select_two_case_results_no_default(i32 %i) { 269; CHECK-LABEL: @switch_to_select_two_case_results_no_default( 270; CHECK-NEXT: entry: 271; CHECK-NEXT: switch i32 [[I:%.*]], label [[DEFAULT:%.*]] [ 272; CHECK-NEXT: i32 0, label [[END:%.*]] 273; CHECK-NEXT: i32 2, label [[END]] 274; CHECK-NEXT: i32 4, label [[CASE3:%.*]] 275; CHECK-NEXT: i32 6, label [[CASE3]] 276; CHECK-NEXT: ] 277; CHECK: case3: 278; CHECK-NEXT: br label [[END]] 279; CHECK: default: 280; CHECK-NEXT: unreachable 281; CHECK: end: 282; CHECK-NEXT: [[T0:%.*]] = phi i8 [ 44, [[CASE3]] ], [ 42, [[ENTRY:%.*]] ], [ 42, [[ENTRY]] ] 283; CHECK-NEXT: ret i8 [[T0]] 284; 285entry: 286 switch i32 %i, label %default [ 287 i32 0, label %case1 288 i32 2, label %case2 289 i32 4, label %case3 290 i32 6, label %case4 291 ] 292 293case1: 294 br label %end 295 296case2: 297 br label %end 298 299case3: 300 br label %end 301 302case4: 303 br label %end 304 305default: 306 unreachable 307 308end: 309 %t0 = phi i8 [ 42, %case1 ], [ 42, %case2 ], [ 44, %case3 ], [ 44, %case4 ] 310 ret i8 %t0 311} 312