1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=instcombine < %s | FileCheck %s 3 4declare void @use(i8) 5declare void @use.i1(i1) 6declare i8 @llvm.umin.i8(i8, i8) 7 8define i1 @icmp_select_const(i8 %x, i8 %y) { 9; CHECK-LABEL: @icmp_select_const( 10; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 11; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], 0 12; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 13; CHECK-NEXT: ret i1 [[CMP2]] 14; 15 %cmp1 = icmp eq i8 %x, 0 16 %sel = select i1 %cmp1, i8 0, i8 %y 17 %cmp2 = icmp eq i8 %sel, 0 18 ret i1 %cmp2 19} 20 21define i1 @icmp_select_var(i8 %x, i8 %y, i8 %z) { 22; CHECK-LABEL: @icmp_select_var( 23; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 24; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[Z:%.*]] 25; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 26; CHECK-NEXT: ret i1 [[CMP2]] 27; 28 %cmp1 = icmp eq i8 %x, 0 29 %sel = select i1 %cmp1, i8 %z, i8 %y 30 %cmp2 = icmp eq i8 %sel, %z 31 ret i1 %cmp2 32} 33 34define i1 @icmp_select_var_commuted(i8 %x, i8 %y, i8 %_z) { 35; CHECK-LABEL: @icmp_select_var_commuted( 36; CHECK-NEXT: [[Z:%.*]] = udiv i8 42, [[_Z:%.*]] 37; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 38; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[Z]] 39; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 40; CHECK-NEXT: ret i1 [[CMP2]] 41; 42 %z = udiv i8 42, %_z ; thwart complexity-based canonicalization 43 %cmp1 = icmp eq i8 %x, 0 44 %sel = select i1 %cmp1, i8 %z, i8 %y 45 %cmp2 = icmp eq i8 %z, %sel 46 ret i1 %cmp2 47} 48 49define i1 @icmp_select_var_select(i8 %x, i8 %y, i1 %c) { 50; CHECK-LABEL: @icmp_select_var_select( 51; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 52; CHECK-NEXT: [[CMP212:%.*]] = icmp eq i8 [[X]], [[Y:%.*]] 53; CHECK-NEXT: [[NOT_C:%.*]] = xor i1 [[C:%.*]], true 54; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[CMP1]], i1 true, i1 [[NOT_C]] 55; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[TMP1]], i1 true, i1 [[CMP212]] 56; CHECK-NEXT: ret i1 [[CMP2]] 57; 58 %z = select i1 %c, i8 %x, i8 %y 59 %cmp1 = icmp eq i8 %x, 0 60 %sel = select i1 %cmp1, i8 %z, i8 %y 61 %cmp2 = icmp eq i8 %z, %sel 62 ret i1 %cmp2 63} 64 65define i1 @icmp_select_var_both_fold(i8 %x, i8 %y, i8 %_z) { 66; CHECK-LABEL: @icmp_select_var_both_fold( 67; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 68; CHECK-NEXT: ret i1 [[CMP1]] 69; 70 %z = or i8 %_z, 1 71 %cmp1 = icmp eq i8 %x, 0 72 %sel = select i1 %cmp1, i8 %z, i8 2 73 %cmp2 = icmp eq i8 %sel, %z 74 ret i1 %cmp2 75} 76 77define i1 @icmp_select_var_extra_use(i8 %x, i8 %y, i8 %z) { 78; CHECK-LABEL: @icmp_select_var_extra_use( 79; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 80; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 [[Z:%.*]], i8 [[Y:%.*]] 81; CHECK-NEXT: call void @use(i8 [[SEL]]) 82; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i8 [[SEL]], [[Z]] 83; CHECK-NEXT: ret i1 [[CMP2]] 84; 85 %cmp1 = icmp eq i8 %x, 0 86 %sel = select i1 %cmp1, i8 %z, i8 %y 87 call void @use(i8 %sel) 88 %cmp2 = icmp eq i8 %sel, %z 89 ret i1 %cmp2 90} 91 92define i1 @icmp_select_var_both_fold_extra_use(i8 %x, i8 %y, i8 %_z) { 93; CHECK-LABEL: @icmp_select_var_both_fold_extra_use( 94; CHECK-NEXT: [[Z:%.*]] = or i8 [[_Z:%.*]], 1 95; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 96; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 [[Z]], i8 2 97; CHECK-NEXT: call void @use(i8 [[SEL]]) 98; CHECK-NEXT: ret i1 [[CMP1]] 99; 100 %z = or i8 %_z, 1 101 %cmp1 = icmp eq i8 %x, 0 102 %sel = select i1 %cmp1, i8 %z, i8 2 103 call void @use(i8 %sel) 104 %cmp2 = icmp eq i8 %sel, %z 105 ret i1 %cmp2 106} 107 108define i1 @icmp_select_var_pred_ne(i8 %x, i8 %y, i8 %z) { 109; CHECK-LABEL: @icmp_select_var_pred_ne( 110; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0 111; CHECK-NEXT: [[CMP21:%.*]] = icmp ne i8 [[Y:%.*]], [[Z:%.*]] 112; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false 113; CHECK-NEXT: ret i1 [[CMP2]] 114; 115 %cmp1 = icmp eq i8 %x, 0 116 %sel = select i1 %cmp1, i8 %z, i8 %y 117 %cmp2 = icmp ne i8 %sel, %z 118 ret i1 %cmp2 119} 120 121define i1 @icmp_select_var_pred_ult(i8 %x, i8 %y, i8 %z) { 122; CHECK-LABEL: @icmp_select_var_pred_ult( 123; CHECK-NEXT: [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2 124; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 125; CHECK-NEXT: [[CMP21:%.*]] = icmp ult i8 [[Y:%.*]], [[Z1]] 126; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 127; CHECK-NEXT: ret i1 [[CMP2]] 128; 129 %z1 = add nuw i8 %z, 2 130 %cmp1 = icmp eq i8 %x, 0 131 %sel = select i1 %cmp1, i8 %z, i8 %y 132 %cmp2 = icmp ult i8 %sel, %z1 133 ret i1 %cmp2 134} 135 136define i1 @icmp_select_var_pred_uge(i8 %x, i8 %y, i8 %z) { 137; CHECK-LABEL: @icmp_select_var_pred_uge( 138; CHECK-NEXT: [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2 139; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0 140; CHECK-NEXT: [[CMP21:%.*]] = icmp uge i8 [[Y:%.*]], [[Z1]] 141; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false 142; CHECK-NEXT: ret i1 [[CMP2]] 143; 144 %z1 = add nuw i8 %z, 2 145 %cmp1 = icmp eq i8 %x, 0 146 %sel = select i1 %cmp1, i8 %z, i8 %y 147 %cmp2 = icmp uge i8 %sel, %z1 148 ret i1 %cmp2 149} 150 151define i1 @icmp_select_var_pred_uge_commuted(i8 %x, i8 %y, i8 %z) { 152; CHECK-LABEL: @icmp_select_var_pred_uge_commuted( 153; CHECK-NEXT: [[Z1:%.*]] = add nuw i8 [[Z:%.*]], 2 154; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 155; CHECK-NEXT: [[CMP21:%.*]] = icmp ule i8 [[Y:%.*]], [[Z1]] 156; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 157; CHECK-NEXT: ret i1 [[CMP2]] 158; 159 %z1 = add nuw i8 %z, 2 160 %cmp1 = icmp eq i8 %x, 0 161 %sel = select i1 %cmp1, i8 %z, i8 %y 162 %cmp2 = icmp uge i8 %z1, %sel 163 ret i1 %cmp2 164} 165 166define i1 @icmp_select_implied_cond(i8 %x, i8 %y) { 167; CHECK-LABEL: @icmp_select_implied_cond( 168; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 169; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]] 170; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 171; CHECK-NEXT: ret i1 [[CMP2]] 172; 173 %cmp1 = icmp eq i8 %x, 0 174 %sel = select i1 %cmp1, i8 0, i8 %y 175 %cmp2 = icmp eq i8 %sel, %x 176 ret i1 %cmp2 177} 178 179define i1 @icmp_select_implied_cond_ne(i8 %x, i8 %y) { 180; CHECK-LABEL: @icmp_select_implied_cond_ne( 181; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0 182; CHECK-NEXT: [[CMP21:%.*]] = icmp ne i8 [[Y:%.*]], [[X]] 183; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[CMP21]], i1 false 184; CHECK-NEXT: ret i1 [[CMP2]] 185; 186 %cmp1 = icmp eq i8 %x, 0 187 %sel = select i1 %cmp1, i8 0, i8 %y 188 %cmp2 = icmp ne i8 %sel, %x 189 ret i1 %cmp2 190} 191 192define i1 @icmp_select_implied_cond_swapped_select(i8 %x, i8 %y) { 193; CHECK-LABEL: @icmp_select_implied_cond_swapped_select( 194; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 195; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8 [[Y:%.*]], 0 196; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 [[TMP1]], i1 false 197; CHECK-NEXT: ret i1 [[CMP2]] 198; 199 %cmp1 = icmp eq i8 %x, 0 200 %sel = select i1 %cmp1, i8 %y, i8 0 201 %cmp2 = icmp eq i8 %sel, %x 202 ret i1 %cmp2 203} 204 205define i1 @icmp_select_implied_cond_swapped_select_with_inv_cond(i8 %x, i8 %y) { 206; CHECK-LABEL: @icmp_select_implied_cond_swapped_select_with_inv_cond( 207; CHECK-NEXT: [[CMP1:%.*]] = icmp ne i8 [[X:%.*]], 0 208; CHECK-NEXT: call void @use.i1(i1 [[CMP1]]) 209; CHECK-NEXT: [[CMP21:%.*]] = icmp eq i8 [[Y:%.*]], [[X]] 210; CHECK-NEXT: [[NOT_CMP1:%.*]] = xor i1 [[CMP1]], true 211; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[NOT_CMP1]], i1 true, i1 [[CMP21]] 212; CHECK-NEXT: ret i1 [[CMP2]] 213; 214 %cmp1 = icmp ne i8 %x, 0 215 call void @use.i1(i1 %cmp1) 216 %sel = select i1 %cmp1, i8 %y, i8 0 217 %cmp2 = icmp eq i8 %sel, %x 218 ret i1 %cmp2 219} 220 221define i1 @icmp_select_implied_cond_relational(i8 %x, i8 %y) { 222; CHECK-LABEL: @icmp_select_implied_cond_relational( 223; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[X:%.*]], 10 224; CHECK-NEXT: [[CMP21:%.*]] = icmp ult i8 [[Y:%.*]], [[X]] 225; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 226; CHECK-NEXT: ret i1 [[CMP2]] 227; 228 %cmp1 = icmp ugt i8 %x, 10 229 %sel = select i1 %cmp1, i8 10, i8 %y 230 %cmp2 = icmp ult i8 %sel, %x 231 ret i1 %cmp2 232} 233 234define i1 @icmp_select_implied_cond_relational_off_by_one(i8 %x, i8 %y) { 235; CHECK-LABEL: @icmp_select_implied_cond_relational_off_by_one( 236; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 [[X:%.*]], 10 237; CHECK-NEXT: call void @use.i1(i1 [[CMP1]]) 238; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], i8 11, i8 [[Y:%.*]] 239; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 [[SEL]], [[X]] 240; CHECK-NEXT: ret i1 [[CMP2]] 241; 242 %cmp1 = icmp ugt i8 %x, 10 243 call void @use.i1(i1 %cmp1) 244 %sel = select i1 %cmp1, i8 11, i8 %y 245 %cmp2 = icmp ult i8 %sel, %x 246 ret i1 %cmp2 247} 248 249define i1 @umin_seq_comparison(i8 %x, i8 %y) { 250; CHECK-LABEL: @umin_seq_comparison( 251; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[X:%.*]], 0 252; CHECK-NEXT: [[CMP21:%.*]] = icmp ule i8 [[X]], [[Y:%.*]] 253; CHECK-NEXT: [[CMP2:%.*]] = select i1 [[CMP1]], i1 true, i1 [[CMP21]] 254; CHECK-NEXT: ret i1 [[CMP2]] 255; 256 %min = call i8 @llvm.umin.i8(i8 %x, i8 %y) 257 %cmp1 = icmp eq i8 %x, 0 258 %sel = select i1 %cmp1, i8 0, i8 %min 259 %cmp2 = icmp eq i8 %sel, %x 260 ret i1 %cmp2 261} 262 263; ((A ? TC : FC) & (B ? TC : FC)) == 0 --> xor A, B 264 265define i1 @select_constants_and_icmp_eq0(i1 %x, i1 %y) { 266; CHECK-LABEL: @select_constants_and_icmp_eq0( 267; CHECK-NEXT: [[CMP:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]] 268; CHECK-NEXT: ret i1 [[CMP]] 269; 270 %s1 = select i1 %x, i8 2, i8 1 271 %s2 = select i1 %y, i8 2, i8 1 272 %and = and i8 %s1, %s2 273 %cmp = icmp eq i8 %and, 0 274 ret i1 %cmp 275} 276 277; extra uses on all intermediates are ok 278 279define i1 @select_constants_and_icmp_eq0_uses(i1 %x, i1 %y) { 280; CHECK-LABEL: @select_constants_and_icmp_eq0_uses( 281; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 2, i8 1 282; CHECK-NEXT: call void @use(i8 [[S1]]) 283; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 2, i8 1 284; CHECK-NEXT: call void @use(i8 [[S2]]) 285; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] 286; CHECK-NEXT: call void @use(i8 [[AND]]) 287; CHECK-NEXT: [[CMP:%.*]] = xor i1 [[X]], [[Y]] 288; CHECK-NEXT: ret i1 [[CMP]] 289; 290 %s1 = select i1 %x, i8 2, i8 1 291 call void @use(i8 %s1) 292 %s2 = select i1 %y, i8 2, i8 1 293 call void @use(i8 %s2) 294 %and = and i8 %s1, %s2 295 call void @use(i8 %and) 296 %cmp = icmp eq i8 %and, 0 297 ret i1 %cmp 298} 299 300; vector splat constants are ok 301 302define <2 x i1> @select_constants_and_icmp_eq0_vec_splat(<2 x i1> %x, <2 x i1> %y) { 303; CHECK-LABEL: @select_constants_and_icmp_eq0_vec_splat( 304; CHECK-NEXT: [[CMP:%.*]] = xor <2 x i1> [[X:%.*]], [[Y:%.*]] 305; CHECK-NEXT: ret <2 x i1> [[CMP]] 306; 307 %s1 = select <2 x i1> %x, <2 x i9> <i9 3, i9 3>, <2 x i9> <i9 48, i9 48> 308 %s2 = select <2 x i1> %y, <2 x i9> <i9 3, i9 3>, <2 x i9> <i9 48, i9 48> 309 %and = and <2 x i9> %s1, %s2 310 %cmp = icmp eq <2 x i9> %and, zeroinitializer 311 ret <2 x i1> %cmp 312} 313 314; common bit set - simplified via known bits 315 316define i1 @select_constants_and_icmp_eq0_common_bit(i1 %x, i1 %y) { 317; CHECK-LABEL: @select_constants_and_icmp_eq0_common_bit( 318; CHECK-NEXT: ret i1 false 319; 320 %s1 = select i1 %x, i8 2, i8 3 321 %s2 = select i1 %y, i8 2, i8 3 322 %and = and i8 %s1, %s2 323 %cmp = icmp eq i8 %and, 0 324 ret i1 %cmp 325} 326 327; negative test - need matching constants 328 329define i1 @select_constants_and_icmp_eq0_no_common_op1(i1 %x, i1 %y) { 330; CHECK-LABEL: @select_constants_and_icmp_eq0_no_common_op1( 331; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3 332; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 24, i8 3 333; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] 334; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], 0 335; CHECK-NEXT: ret i1 [[CMP]] 336; 337 %s1 = select i1 %x, i8 16, i8 3 338 %s2 = select i1 %y, i8 24, i8 3 339 %and = and i8 %s1, %s2 340 %cmp = icmp eq i8 %and, 0 341 ret i1 %cmp 342} 343 344; negative test - need matching constants 345 346define i1 @select_constants_and_icmp_eq0_no_common_op2(i1 %x, i1 %y) { 347; CHECK-LABEL: @select_constants_and_icmp_eq0_no_common_op2( 348; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3 349; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 16, i8 7 350; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] 351; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], 0 352; CHECK-NEXT: ret i1 [[CMP]] 353; 354 %s1 = select i1 %x, i8 16, i8 3 355 %s2 = select i1 %y, i8 16, i8 7 356 %and = and i8 %s1, %s2 357 %cmp = icmp eq i8 %and, 0 358 ret i1 %cmp 359} 360 361; reduces via FoldOpInstSelect, but this could be a simple 'or' 362 363define i1 @select_constants_and_icmp_eq0_zero_tval(i1 %x, i1 %y) { 364; CHECK-LABEL: @select_constants_and_icmp_eq0_zero_tval( 365; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]] 366; CHECK-NEXT: ret i1 [[TMP1]] 367; 368 %s1 = select i1 %x, i8 0, i8 12 369 %s2 = select i1 %y, i8 0, i8 12 370 %and = and i8 %s1, %s2 371 %cmp = icmp eq i8 %and, 0 372 ret i1 %cmp 373} 374 375; reduces via FoldOpInstSelect, but this could be a simple 'not-of-and' 376 377define i1 @select_constants_and_icmp_eq0_zero_fval(i1 %x, i1 %y) { 378; CHECK-LABEL: @select_constants_and_icmp_eq0_zero_fval( 379; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false 380; CHECK-NEXT: [[NOT_:%.*]] = xor i1 [[TMP1]], true 381; CHECK-NEXT: ret i1 [[NOT_]] 382; 383 %s1 = select i1 %x, i8 12, i8 0 384 %s2 = select i1 %y, i8 12, i8 0 385 %and = and i8 %s1, %s2 386 %cmp = icmp eq i8 %and, 0 387 ret i1 %cmp 388} 389 390; TODO: x & y 391 392define i1 @select_constants_and_icmp_eq_tval(i1 %x, i1 %y) { 393; CHECK-LABEL: @select_constants_and_icmp_eq_tval( 394; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 6, i8 1 395; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 6, i8 1 396; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] 397; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], 6 398; CHECK-NEXT: ret i1 [[CMP]] 399; 400 %s1 = select i1 %x, i8 6, i8 1 401 %s2 = select i1 %y, i8 6, i8 1 402 %and = and i8 %s1, %s2 403 %cmp = icmp eq i8 %and, 6 404 ret i1 %cmp 405} 406 407; TODO: ~(x | y) 408 409define i1 @select_constants_and_icmp_eq_fval(i1 %x, i1 %y) { 410; CHECK-LABEL: @select_constants_and_icmp_eq_fval( 411; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 12, i8 3 412; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 12, i8 3 413; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] 414; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[AND]], 3 415; CHECK-NEXT: ret i1 [[CMP]] 416; 417 %s1 = select i1 %x, i8 12, i8 3 418 %s2 = select i1 %y, i8 12, i8 3 419 %and = and i8 %s1, %s2 420 %cmp = icmp eq i8 %and, 3 421 ret i1 %cmp 422} 423 424; ((A ? TC : FC) & (B ? TC : FC)) != 0 --> not(xor A, B) 425 426define i1 @select_constants_and_icmp_ne0(i1 %x, i1 %y) { 427; CHECK-LABEL: @select_constants_and_icmp_ne0( 428; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[X:%.*]], [[Y:%.*]] 429; CHECK-NEXT: [[CMP:%.*]] = xor i1 [[TMP1]], true 430; CHECK-NEXT: ret i1 [[CMP]] 431; 432 %s1 = select i1 %x, i8 2, i8 1 433 %s2 = select i1 %y, i8 2, i8 1 434 %and = and i8 %s1, %s2 435 %cmp = icmp ne i8 %and, 0 436 ret i1 %cmp 437} 438 439; extra uses on select intermediates are ok 440 441define i1 @select_constants_and_icmp_ne0_uses(i1 %x, i1 %y) { 442; CHECK-LABEL: @select_constants_and_icmp_ne0_uses( 443; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 2, i8 1 444; CHECK-NEXT: call void @use(i8 [[S1]]) 445; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 2, i8 1 446; CHECK-NEXT: call void @use(i8 [[S2]]) 447; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[X]], [[Y]] 448; CHECK-NEXT: [[CMP:%.*]] = xor i1 [[TMP1]], true 449; CHECK-NEXT: ret i1 [[CMP]] 450; 451 %s1 = select i1 %x, i8 2, i8 1 452 call void @use(i8 %s1) 453 %s2 = select i1 %y, i8 2, i8 1 454 call void @use(i8 %s2) 455 %and = and i8 %s1, %s2 456 %cmp = icmp ne i8 %and, 0 457 ret i1 %cmp 458} 459 460; negative test - don't create extra instructions 461 462define i1 @select_constants_and_icmp_ne0_all_uses(i1 %x, i1 %y) { 463; CHECK-LABEL: @select_constants_and_icmp_ne0_all_uses( 464; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 2, i8 1 465; CHECK-NEXT: call void @use(i8 [[S1]]) 466; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 2, i8 1 467; CHECK-NEXT: call void @use(i8 [[S2]]) 468; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] 469; CHECK-NEXT: call void @use(i8 [[AND]]) 470; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[AND]], 0 471; CHECK-NEXT: ret i1 [[CMP]] 472; 473 %s1 = select i1 %x, i8 2, i8 1 474 call void @use(i8 %s1) 475 %s2 = select i1 %y, i8 2, i8 1 476 call void @use(i8 %s2) 477 %and = and i8 %s1, %s2 478 call void @use(i8 %and) 479 %cmp = icmp ne i8 %and, 0 480 ret i1 %cmp 481} 482 483; vector splat constants are ok 484 485define <2 x i1> @select_constants_and_icmp_ne0_vec_splat(<2 x i1> %x, <2 x i1> %y) { 486; CHECK-LABEL: @select_constants_and_icmp_ne0_vec_splat( 487; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i1> [[X:%.*]], [[Y:%.*]] 488; CHECK-NEXT: [[CMP:%.*]] = xor <2 x i1> [[TMP1]], splat (i1 true) 489; CHECK-NEXT: ret <2 x i1> [[CMP]] 490; 491 %s1 = select <2 x i1> %x, <2 x i9> <i9 3, i9 3>, <2 x i9> <i9 48, i9 48> 492 %s2 = select <2 x i1> %y, <2 x i9> <i9 3, i9 3>, <2 x i9> <i9 48, i9 48> 493 %and = and <2 x i9> %s1, %s2 494 %cmp = icmp ne <2 x i9> %and, zeroinitializer 495 ret <2 x i1> %cmp 496} 497 498; common bit set - simplified via known bits 499 500define i1 @select_constants_and_icmp_ne0_common_bit(i1 %x, i1 %y) { 501; CHECK-LABEL: @select_constants_and_icmp_ne0_common_bit( 502; CHECK-NEXT: ret i1 true 503; 504 %s1 = select i1 %x, i8 2, i8 3 505 %s2 = select i1 %y, i8 2, i8 3 506 %and = and i8 %s1, %s2 507 %cmp = icmp ne i8 %and, 0 508 ret i1 %cmp 509} 510 511; negative test - need matching constants 512 513define i1 @select_constants_and_icmp_ne0_no_common_op1(i1 %x, i1 %y) { 514; CHECK-LABEL: @select_constants_and_icmp_ne0_no_common_op1( 515; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3 516; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 24, i8 3 517; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] 518; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[AND]], 0 519; CHECK-NEXT: ret i1 [[CMP]] 520; 521 %s1 = select i1 %x, i8 16, i8 3 522 %s2 = select i1 %y, i8 24, i8 3 523 %and = and i8 %s1, %s2 524 %cmp = icmp ne i8 %and, 0 525 ret i1 %cmp 526} 527 528; negative test - need matching constants 529 530define i1 @select_constants_and_icmp_ne0_no_common_op2(i1 %x, i1 %y) { 531; CHECK-LABEL: @select_constants_and_icmp_ne0_no_common_op2( 532; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 16, i8 3 533; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 16, i8 7 534; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] 535; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[AND]], 0 536; CHECK-NEXT: ret i1 [[CMP]] 537; 538 %s1 = select i1 %x, i8 16, i8 3 539 %s2 = select i1 %y, i8 16, i8 7 540 %and = and i8 %s1, %s2 541 %cmp = icmp ne i8 %and, 0 542 ret i1 %cmp 543} 544 545; reduces via FoldOpInstSelect, but this could be a simple 'nor' 546 547define i1 @select_constants_and_icmp_ne0_zero_tval(i1 %x, i1 %y) { 548; CHECK-LABEL: @select_constants_and_icmp_ne0_zero_tval( 549; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 true, i1 [[Y:%.*]] 550; CHECK-NEXT: [[NOT_:%.*]] = xor i1 [[TMP1]], true 551; CHECK-NEXT: ret i1 [[NOT_]] 552; 553 %s1 = select i1 %x, i8 0, i8 12 554 %s2 = select i1 %y, i8 0, i8 12 555 %and = and i8 %s1, %s2 556 %cmp = icmp ne i8 %and, 0 557 ret i1 %cmp 558} 559 560; reduces via FoldOpInstSelect, but this could be a simple 'and' 561 562define i1 @select_constants_and_icmp_ne0_zero_fval(i1 %x, i1 %y) { 563; CHECK-LABEL: @select_constants_and_icmp_ne0_zero_fval( 564; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[X:%.*]], i1 [[Y:%.*]], i1 false 565; CHECK-NEXT: ret i1 [[TMP1]] 566; 567 %s1 = select i1 %x, i8 12, i8 0 568 %s2 = select i1 %y, i8 12, i8 0 569 %and = and i8 %s1, %s2 570 %cmp = icmp ne i8 %and, 0 571 ret i1 %cmp 572} 573 574; TODO: ~(x & y) 575 576define i1 @select_constants_and_icmp_ne_tval(i1 %x, i1 %y) { 577; CHECK-LABEL: @select_constants_and_icmp_ne_tval( 578; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 6, i8 1 579; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 6, i8 1 580; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] 581; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[AND]], 6 582; CHECK-NEXT: ret i1 [[CMP]] 583; 584 %s1 = select i1 %x, i8 6, i8 1 585 %s2 = select i1 %y, i8 6, i8 1 586 %and = and i8 %s1, %s2 587 %cmp = icmp ne i8 %and, 6 588 ret i1 %cmp 589} 590 591; TODO: (x | y) 592 593define i1 @select_constants_and_icmp_ne_fval(i1 %x, i1 %y) { 594; CHECK-LABEL: @select_constants_and_icmp_ne_fval( 595; CHECK-NEXT: [[S1:%.*]] = select i1 [[X:%.*]], i8 12, i8 3 596; CHECK-NEXT: [[S2:%.*]] = select i1 [[Y:%.*]], i8 12, i8 3 597; CHECK-NEXT: [[AND:%.*]] = and i8 [[S1]], [[S2]] 598; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[AND]], 3 599; CHECK-NEXT: ret i1 [[CMP]] 600; 601 %s1 = select i1 %x, i8 12, i8 3 602 %s2 = select i1 %y, i8 12, i8 3 603 %and = and i8 %s1, %s2 604 %cmp = icmp ne i8 %and, 3 605 ret i1 %cmp 606} 607 608define i1 @icmp_eq_select(i1 %cond, i32 %a, i32 %b) { 609; CHECK-LABEL: @icmp_eq_select( 610; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 [[A:%.*]], [[B:%.*]] 611; CHECK-NEXT: ret i1 [[RES]] 612; 613 %lhs = select i1 %cond, i32 %a, i32 %b 614 %rhs = select i1 %cond, i32 %b, i32 %a 615 %res = icmp eq i32 %lhs, %rhs 616 ret i1 %res 617} 618 619define i1 @icmp_slt_select(i1 %cond, i32 %a, i32 %b) { 620; CHECK-LABEL: @icmp_slt_select( 621; CHECK-NEXT: [[LHS:%.*]] = select i1 [[COND:%.*]], i32 [[A:%.*]], i32 [[B:%.*]] 622; CHECK-NEXT: [[RHS:%.*]] = select i1 [[COND]], i32 [[B]], i32 [[A]] 623; CHECK-NEXT: [[RES:%.*]] = icmp slt i32 [[LHS]], [[RHS]] 624; CHECK-NEXT: ret i1 [[RES]] 625; 626 %lhs = select i1 %cond, i32 %a, i32 %b 627 %rhs = select i1 %cond, i32 %b, i32 %a 628 %res = icmp slt i32 %lhs, %rhs 629 ret i1 %res 630} 631