1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4declare void @use8(i8) 5declare void @use32(i32) 6 7; There should be no 'and' instructions left in any test. 8 9define i32 @test1(i32 %A) { 10; CHECK-LABEL: @test1( 11; CHECK-NEXT: ret i32 0 12; 13 %B = and i32 %A, 0 14 ret i32 %B 15} 16 17define i32 @test2(i32 %A) { 18; CHECK-LABEL: @test2( 19; CHECK-NEXT: ret i32 [[A:%.*]] 20; 21 %B = and i32 %A, -1 22 ret i32 %B 23} 24 25define i1 @test3(i1 %A) { 26; CHECK-LABEL: @test3( 27; CHECK-NEXT: ret i1 false 28; 29 %B = and i1 %A, false 30 ret i1 %B 31} 32 33define i1 @test4(i1 %A) { 34; CHECK-LABEL: @test4( 35; CHECK-NEXT: ret i1 [[A:%.*]] 36; 37 %B = and i1 %A, true 38 ret i1 %B 39} 40 41define i32 @test5(i32 %A) { 42; CHECK-LABEL: @test5( 43; CHECK-NEXT: ret i32 [[A:%.*]] 44; 45 %B = and i32 %A, %A 46 ret i32 %B 47} 48 49define i1 @test6(i1 %A) { 50; CHECK-LABEL: @test6( 51; CHECK-NEXT: ret i1 [[A:%.*]] 52; 53 %B = and i1 %A, %A 54 ret i1 %B 55} 56 57; A & ~A == 0 58define i32 @test7(i32 %A) { 59; CHECK-LABEL: @test7( 60; CHECK-NEXT: ret i32 0 61; 62 %NotA = xor i32 %A, -1 63 %B = and i32 %A, %NotA 64 ret i32 %B 65} 66 67; AND associates 68define i8 @test8(i8 %A) { 69; CHECK-LABEL: @test8( 70; CHECK-NEXT: ret i8 0 71; 72 %B = and i8 %A, 3 73 %C = and i8 %B, 4 74 ret i8 %C 75} 76 77; Test of sign bit, convert to setle %A, 0 78define i1 @test9(i32 %A) { 79; CHECK-LABEL: @test9( 80; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[A:%.*]], 0 81; CHECK-NEXT: ret i1 [[C]] 82; 83 %B = and i32 %A, -2147483648 84 %C = icmp ne i32 %B, 0 85 ret i1 %C 86} 87 88; Test of sign bit, convert to setle %A, 0 89define i1 @test9a(i32 %A) { 90; CHECK-LABEL: @test9a( 91; CHECK-NEXT: [[C:%.*]] = icmp slt i32 [[A:%.*]], 0 92; CHECK-NEXT: ret i1 [[C]] 93; 94 %B = and i32 %A, -2147483648 95 %C = icmp ne i32 %B, 0 96 ret i1 %C 97} 98 99define i32 @test10(i32 %A) { 100; CHECK-LABEL: @test10( 101; CHECK-NEXT: ret i32 1 102; 103 %B = and i32 %A, 12 104 %C = xor i32 %B, 15 105 ; (X ^ C1) & C2 --> (X & C2) ^ (C1&C2) 106 %D = and i32 %C, 1 107 ret i32 %D 108} 109 110define i32 @test11(i32 %A, i32* %P) { 111; CHECK-LABEL: @test11( 112; CHECK-NEXT: [[B:%.*]] = or i32 [[A:%.*]], 3 113; CHECK-NEXT: [[C:%.*]] = xor i32 [[B]], 12 114; CHECK-NEXT: store i32 [[C]], i32* [[P:%.*]], align 4 115; CHECK-NEXT: ret i32 3 116; 117 %B = or i32 %A, 3 118 %C = xor i32 %B, 12 119 ; additional use of C 120 store i32 %C, i32* %P 121 ; %C = and uint %B, 3 --> 3 122 %D = and i32 %C, 3 123 ret i32 %D 124} 125 126define i1 @test12(i32 %A, i32 %B) { 127; CHECK-LABEL: @test12( 128; CHECK-NEXT: [[C1:%.*]] = icmp ult i32 [[A:%.*]], [[B:%.*]] 129; CHECK-NEXT: ret i1 [[C1]] 130; 131 %C1 = icmp ult i32 %A, %B 132 %C2 = icmp ule i32 %A, %B 133 ; (A < B) & (A <= B) === (A < B) 134 %D = and i1 %C1, %C2 135 ret i1 %D 136} 137 138define i1 @test13(i32 %A, i32 %B) { 139; CHECK-LABEL: @test13( 140; CHECK-NEXT: ret i1 false 141; 142 %C1 = icmp ult i32 %A, %B 143 %C2 = icmp ugt i32 %A, %B 144 ; (A < B) & (A > B) === false 145 %D = and i1 %C1, %C2 146 ret i1 %D 147} 148 149define i1 @test14(i8 %A) { 150; CHECK-LABEL: @test14( 151; CHECK-NEXT: [[C:%.*]] = icmp slt i8 [[A:%.*]], 0 152; CHECK-NEXT: ret i1 [[C]] 153; 154 %B = and i8 %A, -128 155 %C = icmp ne i8 %B, 0 156 ret i1 %C 157} 158 159define i8 @test15(i8 %A) { 160; CHECK-LABEL: @test15( 161; CHECK-NEXT: ret i8 0 162; 163 %B = lshr i8 %A, 7 164 ; Always equals zero 165 %C = and i8 %B, 2 166 ret i8 %C 167} 168 169define i8 @test16(i8 %A) { 170; CHECK-LABEL: @test16( 171; CHECK-NEXT: ret i8 0 172; 173 %B = shl i8 %A, 2 174 %C = and i8 %B, 3 175 ret i8 %C 176} 177 178define i1 @test18(i32 %A) { 179; CHECK-LABEL: @test18( 180; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A:%.*]], 127 181; CHECK-NEXT: ret i1 [[C]] 182; 183 %B = and i32 %A, -128 184 ;; C >= 128 185 %C = icmp ne i32 %B, 0 186 ret i1 %C 187} 188 189define <2 x i1> @test18_vec(<2 x i32> %A) { 190; CHECK-LABEL: @test18_vec( 191; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i32> [[A:%.*]], <i32 127, i32 127> 192; CHECK-NEXT: ret <2 x i1> [[C]] 193; 194 %B = and <2 x i32> %A, <i32 -128, i32 -128> 195 %C = icmp ne <2 x i32> %B, zeroinitializer 196 ret <2 x i1> %C 197} 198 199define i1 @test18a(i8 %A) { 200; CHECK-LABEL: @test18a( 201; CHECK-NEXT: [[C:%.*]] = icmp ult i8 [[A:%.*]], 2 202; CHECK-NEXT: ret i1 [[C]] 203; 204 %B = and i8 %A, -2 205 %C = icmp eq i8 %B, 0 206 ret i1 %C 207} 208 209define <2 x i1> @test18a_vec(<2 x i8> %A) { 210; CHECK-LABEL: @test18a_vec( 211; CHECK-NEXT: [[C:%.*]] = icmp ult <2 x i8> [[A:%.*]], <i8 2, i8 2> 212; CHECK-NEXT: ret <2 x i1> [[C]] 213; 214 %B = and <2 x i8> %A, <i8 -2, i8 -2> 215 %C = icmp eq <2 x i8> %B, zeroinitializer 216 ret <2 x i1> %C 217} 218 219define i32 @test19(i32 %A) { 220; CHECK-LABEL: @test19( 221; CHECK-NEXT: [[B:%.*]] = shl i32 [[A:%.*]], 3 222; CHECK-NEXT: ret i32 [[B]] 223; 224 %B = shl i32 %A, 3 225 ;; Clearing a zero bit 226 %C = and i32 %B, -2 227 ret i32 %C 228} 229 230define i8 @test20(i8 %A) { 231; CHECK-LABEL: @test20( 232; CHECK-NEXT: [[C:%.*]] = lshr i8 [[A:%.*]], 7 233; CHECK-NEXT: ret i8 [[C]] 234; 235 %C = lshr i8 %A, 7 236 ;; Unneeded 237 %D = and i8 %C, 1 238 ret i8 %D 239} 240 241define i1 @test23(i32 %A) { 242; CHECK-LABEL: @test23( 243; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[A:%.*]], 2 244; CHECK-NEXT: ret i1 [[TMP1]] 245; 246 %B = icmp sgt i32 %A, 1 247 %C = icmp sle i32 %A, 2 248 %D = and i1 %B, %C 249 ret i1 %D 250} 251 252; FIXME: Vectors should fold too. 253define <2 x i1> @test23vec(<2 x i32> %A) { 254; CHECK-LABEL: @test23vec( 255; CHECK-NEXT: [[B:%.*]] = icmp sgt <2 x i32> [[A:%.*]], <i32 1, i32 1> 256; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i32> [[A]], <i32 3, i32 3> 257; CHECK-NEXT: [[D:%.*]] = and <2 x i1> [[B]], [[C]] 258; CHECK-NEXT: ret <2 x i1> [[D]] 259; 260 %B = icmp sgt <2 x i32> %A, <i32 1, i32 1> 261 %C = icmp sle <2 x i32> %A, <i32 2, i32 2> 262 %D = and <2 x i1> %B, %C 263 ret <2 x i1> %D 264} 265 266define i1 @test24(i32 %A) { 267; CHECK-LABEL: @test24( 268; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A:%.*]], 2 269; CHECK-NEXT: ret i1 [[TMP1]] 270; 271 %B = icmp sgt i32 %A, 1 272 %C = icmp ne i32 %A, 2 273 ;; A > 2 274 %D = and i1 %B, %C 275 ret i1 %D 276} 277 278define i1 @test25(i32 %A) { 279; CHECK-LABEL: @test25( 280; CHECK-NEXT: [[A_OFF:%.*]] = add i32 [[A:%.*]], -50 281; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[A_OFF]], 50 282; CHECK-NEXT: ret i1 [[TMP1]] 283; 284 %B = icmp sge i32 %A, 50 285 %C = icmp slt i32 %A, 100 286 %D = and i1 %B, %C 287 ret i1 %D 288} 289 290; FIXME: Vectors should fold too. 291define <2 x i1> @test25vec(<2 x i32> %A) { 292; CHECK-LABEL: @test25vec( 293; CHECK-NEXT: [[B:%.*]] = icmp sgt <2 x i32> [[A:%.*]], <i32 49, i32 49> 294; CHECK-NEXT: [[C:%.*]] = icmp slt <2 x i32> [[A]], <i32 100, i32 100> 295; CHECK-NEXT: [[D:%.*]] = and <2 x i1> [[B]], [[C]] 296; CHECK-NEXT: ret <2 x i1> [[D]] 297; 298 %B = icmp sge <2 x i32> %A, <i32 50, i32 50> 299 %C = icmp slt <2 x i32> %A, <i32 100, i32 100> 300 %D = and <2 x i1> %B, %C 301 ret <2 x i1> %D 302} 303 304define i8 @test27(i8 %A) { 305; CHECK-LABEL: @test27( 306; CHECK-NEXT: ret i8 0 307; 308 %B = and i8 %A, 4 309 %C = sub i8 %B, 16 310 ;; 0xF0 311 %D = and i8 %C, -16 312 %E = add i8 %D, 16 313 ret i8 %E 314} 315 316;; This is just a zero-extending shr. 317define i32 @test28(i32 %X) { 318; CHECK-LABEL: @test28( 319; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 24 320; CHECK-NEXT: ret i32 [[TMP1]] 321; 322 ;; Sign extend 323 %Y = ashr i32 %X, 24 324 ;; Mask out sign bits 325 %Z = and i32 %Y, 255 326 ret i32 %Z 327} 328 329define i32 @test29(i8 %X) { 330; CHECK-LABEL: @test29( 331; CHECK-NEXT: [[Y:%.*]] = zext i8 [[X:%.*]] to i32 332; CHECK-NEXT: ret i32 [[Y]] 333; 334 %Y = zext i8 %X to i32 335 ;; Zero extend makes this unneeded. 336 %Z = and i32 %Y, 255 337 ret i32 %Z 338} 339 340define i32 @test30(i1 %X) { 341; CHECK-LABEL: @test30( 342; CHECK-NEXT: [[Y:%.*]] = zext i1 [[X:%.*]] to i32 343; CHECK-NEXT: ret i32 [[Y]] 344; 345 %Y = zext i1 %X to i32 346 %Z = and i32 %Y, 1 347 ret i32 %Z 348} 349 350define i32 @test31(i1 %X) { 351; CHECK-LABEL: @test31( 352; CHECK-NEXT: [[Z:%.*]] = select i1 [[X:%.*]], i32 16, i32 0 353; CHECK-NEXT: ret i32 [[Z]] 354; 355 %Y = zext i1 %X to i32 356 %Z = shl i32 %Y, 4 357 %A = and i32 %Z, 16 358 ret i32 %A 359} 360 361; Demanded bit analysis allows us to eliminate the add. 362 363define <2 x i32> @and_demanded_bits_splat_vec(<2 x i32> %x) { 364; CHECK-LABEL: @and_demanded_bits_splat_vec( 365; CHECK-NEXT: [[Z:%.*]] = and <2 x i32> [[X:%.*]], <i32 7, i32 7> 366; CHECK-NEXT: ret <2 x i32> [[Z]] 367; 368 %y = add <2 x i32> %x, <i32 8, i32 8> 369 %z = and <2 x i32> %y, <i32 7, i32 7> 370 ret <2 x i32> %z 371} 372 373; zext (x >> 8) has all zeros in the high 24-bits: 0x000000xx 374; (y | 255) has all ones in the low 8-bits: 0xyyyyyyff 375; 'and' of those is all known bits - it's just 'z'. 376 377define i32 @and_zext_demanded(i16 %x, i32 %y) { 378; CHECK-LABEL: @and_zext_demanded( 379; CHECK-NEXT: [[S:%.*]] = lshr i16 [[X:%.*]], 8 380; CHECK-NEXT: [[Z:%.*]] = zext i16 [[S]] to i32 381; CHECK-NEXT: ret i32 [[Z]] 382; 383 %s = lshr i16 %x, 8 384 %z = zext i16 %s to i32 385 %o = or i32 %y, 255 386 %a = and i32 %o, %z 387 ret i32 %a 388} 389 390define i32 @test32(i32 %In) { 391; CHECK-LABEL: @test32( 392; CHECK-NEXT: ret i32 0 393; 394 %Y = and i32 %In, 16 395 %Z = lshr i32 %Y, 2 396 %A = and i32 %Z, 1 397 ret i32 %A 398} 399 400;; Code corresponding to one-bit bitfield ^1. 401define i32 @test33(i32 %b) { 402; CHECK-LABEL: @test33( 403; CHECK-NEXT: [[T13:%.*]] = xor i32 [[B:%.*]], 1 404; CHECK-NEXT: ret i32 [[T13]] 405; 406 %t4.mask = and i32 %b, 1 407 %t10 = xor i32 %t4.mask, 1 408 %t12 = and i32 %b, -2 409 %t13 = or i32 %t12, %t10 410 ret i32 %t13 411} 412 413define i32 @test33b(i32 %b) { 414; CHECK-LABEL: @test33b( 415; CHECK-NEXT: [[T13:%.*]] = xor i32 [[B:%.*]], 1 416; CHECK-NEXT: ret i32 [[T13]] 417; 418 %t4.mask = and i32 %b, 1 419 %t10 = xor i32 %t4.mask, 1 420 %t12 = and i32 %b, -2 421 %t13 = or i32 %t10, %t12 422 ret i32 %t13 423} 424 425define <2 x i32> @test33vec(<2 x i32> %b) { 426; CHECK-LABEL: @test33vec( 427; CHECK-NEXT: [[T13:%.*]] = xor <2 x i32> [[B:%.*]], <i32 1, i32 1> 428; CHECK-NEXT: ret <2 x i32> [[T13]] 429; 430 %t4.mask = and <2 x i32> %b, <i32 1, i32 1> 431 %t10 = xor <2 x i32> %t4.mask, <i32 1, i32 1> 432 %t12 = and <2 x i32> %b, <i32 -2, i32 -2> 433 %t13 = or <2 x i32> %t12, %t10 434 ret <2 x i32> %t13 435} 436 437define <2 x i32> @test33vecb(<2 x i32> %b) { 438; CHECK-LABEL: @test33vecb( 439; CHECK-NEXT: [[T13:%.*]] = xor <2 x i32> [[B:%.*]], <i32 1, i32 1> 440; CHECK-NEXT: ret <2 x i32> [[T13]] 441; 442 %t4.mask = and <2 x i32> %b, <i32 1, i32 1> 443 %t10 = xor <2 x i32> %t4.mask, <i32 1, i32 1> 444 %t12 = and <2 x i32> %b, <i32 -2, i32 -2> 445 %t13 = or <2 x i32> %t10, %t12 446 ret <2 x i32> %t13 447} 448 449define i32 @test34(i32 %A, i32 %B) { 450; CHECK-LABEL: @test34( 451; CHECK-NEXT: ret i32 [[B:%.*]] 452; 453 %t2 = or i32 %B, %A 454 %t4 = and i32 %t2, %B 455 ret i32 %t4 456} 457 458; FIXME: This test should only need -instsimplify (ValueTracking / computeKnownBits), not -instcombine. 459 460define <2 x i32> @PR24942(<2 x i32> %x) { 461; CHECK-LABEL: @PR24942( 462; CHECK-NEXT: ret <2 x i32> zeroinitializer 463; 464 %lshr = lshr <2 x i32> %x, <i32 31, i32 31> 465 %and = and <2 x i32> %lshr, <i32 2, i32 2> 466 ret <2 x i32> %and 467} 468 469define i64 @test35(i32 %X) { 470; CHECK-LABEL: @test35( 471; CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[X:%.*]] 472; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 240 473; CHECK-NEXT: [[RES:%.*]] = zext i32 [[TMP2]] to i64 474; CHECK-NEXT: ret i64 [[RES]] 475; 476 %zext = zext i32 %X to i64 477 %zsub = sub i64 0, %zext 478 %res = and i64 %zsub, 240 479 ret i64 %res 480} 481 482define <2 x i64> @test35_uniform(<2 x i32> %X) { 483; CHECK-LABEL: @test35_uniform( 484; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64> 485; CHECK-NEXT: [[ZSUB:%.*]] = sub nsw <2 x i64> zeroinitializer, [[ZEXT]] 486; CHECK-NEXT: [[RES:%.*]] = and <2 x i64> [[ZSUB]], <i64 240, i64 240> 487; CHECK-NEXT: ret <2 x i64> [[RES]] 488; 489 %zext = zext <2 x i32> %X to <2 x i64> 490 %zsub = sub <2 x i64> zeroinitializer, %zext 491 %res = and <2 x i64> %zsub, <i64 240, i64 240> 492 ret <2 x i64> %res 493} 494 495define i64 @test36(i32 %X) { 496; CHECK-LABEL: @test36( 497; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], 7 498; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 240 499; CHECK-NEXT: [[RES:%.*]] = zext i32 [[TMP2]] to i64 500; CHECK-NEXT: ret i64 [[RES]] 501; 502 %zext = zext i32 %X to i64 503 %zsub = add i64 %zext, 7 504 %res = and i64 %zsub, 240 505 ret i64 %res 506} 507 508define <2 x i64> @test36_undef(<2 x i32> %X) { 509; CHECK-LABEL: @test36_undef( 510; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64> 511; CHECK-NEXT: [[ZSUB:%.*]] = add <2 x i64> [[ZEXT]], <i64 7, i64 undef> 512; CHECK-NEXT: [[RES:%.*]] = and <2 x i64> [[ZSUB]], <i64 240, i64 undef> 513; CHECK-NEXT: ret <2 x i64> [[RES]] 514; 515 %zext = zext <2 x i32> %X to <2 x i64> 516 %zsub = add <2 x i64> %zext, <i64 7, i64 undef> 517 %res = and <2 x i64> %zsub, <i64 240, i64 undef> 518 ret <2 x i64> %res 519} 520 521define i64 @test37(i32 %X) { 522; CHECK-LABEL: @test37( 523; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[X:%.*]], 7 524; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], 240 525; CHECK-NEXT: [[RES:%.*]] = zext i32 [[TMP2]] to i64 526; CHECK-NEXT: ret i64 [[RES]] 527; 528 %zext = zext i32 %X to i64 529 %zsub = mul i64 %zext, 7 530 %res = and i64 %zsub, 240 531 ret i64 %res 532} 533 534define <2 x i64> @test37_nonuniform(<2 x i32> %X) { 535; CHECK-LABEL: @test37_nonuniform( 536; CHECK-NEXT: [[ZEXT:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64> 537; CHECK-NEXT: [[ZSUB:%.*]] = mul nuw nsw <2 x i64> [[ZEXT]], <i64 7, i64 9> 538; CHECK-NEXT: [[RES:%.*]] = and <2 x i64> [[ZSUB]], <i64 240, i64 110> 539; CHECK-NEXT: ret <2 x i64> [[RES]] 540; 541 %zext = zext <2 x i32> %X to <2 x i64> 542 %zsub = mul <2 x i64> %zext, <i64 7, i64 9> 543 %res = and <2 x i64> %zsub, <i64 240, i64 110> 544 ret <2 x i64> %res 545} 546 547define i64 @test38(i32 %X) { 548; CHECK-LABEL: @test38( 549; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 240 550; CHECK-NEXT: [[RES:%.*]] = zext i32 [[TMP1]] to i64 551; CHECK-NEXT: ret i64 [[RES]] 552; 553 %zext = zext i32 %X to i64 554 %zsub = xor i64 %zext, 7 555 %res = and i64 %zsub, 240 556 ret i64 %res 557} 558 559define i64 @test39(i32 %X) { 560; CHECK-LABEL: @test39( 561; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[X:%.*]], 240 562; CHECK-NEXT: [[RES:%.*]] = zext i32 [[TMP1]] to i64 563; CHECK-NEXT: ret i64 [[RES]] 564; 565 %zext = zext i32 %X to i64 566 %zsub = or i64 %zext, 7 567 %res = and i64 %zsub, 240 568 ret i64 %res 569} 570 571define i32 @test40(i1 %C) { 572; CHECK-LABEL: @test40( 573; CHECK-NEXT: [[A:%.*]] = select i1 [[C:%.*]], i32 104, i32 10 574; CHECK-NEXT: ret i32 [[A]] 575; 576 %A = select i1 %C, i32 1000, i32 10 577 %V = and i32 %A, 123 578 ret i32 %V 579} 580 581define <2 x i32> @test40vec(i1 %C) { 582; CHECK-LABEL: @test40vec( 583; CHECK-NEXT: [[A:%.*]] = select i1 [[C:%.*]], <2 x i32> <i32 104, i32 104>, <2 x i32> <i32 10, i32 10> 584; CHECK-NEXT: ret <2 x i32> [[A]] 585; 586 %A = select i1 %C, <2 x i32> <i32 1000, i32 1000>, <2 x i32> <i32 10, i32 10> 587 %V = and <2 x i32> %A, <i32 123, i32 123> 588 ret <2 x i32> %V 589} 590 591define <2 x i32> @test40vec2(i1 %C) { 592; CHECK-LABEL: @test40vec2( 593; CHECK-NEXT: [[V:%.*]] = select i1 [[C:%.*]], <2 x i32> <i32 104, i32 324>, <2 x i32> <i32 10, i32 12> 594; CHECK-NEXT: ret <2 x i32> [[V]] 595; 596 %A = select i1 %C, <2 x i32> <i32 1000, i32 2500>, <2 x i32> <i32 10, i32 30> 597 %V = and <2 x i32> %A, <i32 123, i32 333> 598 ret <2 x i32> %V 599} 600 601define i32 @test41(i1 %which) { 602; CHECK-LABEL: @test41( 603; CHECK-NEXT: entry: 604; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]] 605; CHECK: delay: 606; CHECK-NEXT: br label [[FINAL]] 607; CHECK: final: 608; CHECK-NEXT: [[A:%.*]] = phi i32 [ 104, [[ENTRY:%.*]] ], [ 10, [[DELAY]] ] 609; CHECK-NEXT: ret i32 [[A]] 610; 611entry: 612 br i1 %which, label %final, label %delay 613 614delay: 615 br label %final 616 617final: 618 %A = phi i32 [ 1000, %entry ], [ 10, %delay ] 619 %value = and i32 %A, 123 620 ret i32 %value 621} 622 623define <2 x i32> @test41vec(i1 %which) { 624; CHECK-LABEL: @test41vec( 625; CHECK-NEXT: entry: 626; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]] 627; CHECK: delay: 628; CHECK-NEXT: br label [[FINAL]] 629; CHECK: final: 630; CHECK-NEXT: [[A:%.*]] = phi <2 x i32> [ <i32 104, i32 104>, [[ENTRY:%.*]] ], [ <i32 10, i32 10>, [[DELAY]] ] 631; CHECK-NEXT: ret <2 x i32> [[A]] 632; 633entry: 634 br i1 %which, label %final, label %delay 635 636delay: 637 br label %final 638 639final: 640 %A = phi <2 x i32> [ <i32 1000, i32 1000>, %entry ], [ <i32 10, i32 10>, %delay ] 641 %value = and <2 x i32> %A, <i32 123, i32 123> 642 ret <2 x i32> %value 643} 644 645define <2 x i32> @test41vec2(i1 %which) { 646; CHECK-LABEL: @test41vec2( 647; CHECK-NEXT: entry: 648; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]] 649; CHECK: delay: 650; CHECK-NEXT: br label [[FINAL]] 651; CHECK: final: 652; CHECK-NEXT: [[A:%.*]] = phi <2 x i32> [ <i32 104, i32 324>, [[ENTRY:%.*]] ], [ <i32 10, i32 12>, [[DELAY]] ] 653; CHECK-NEXT: ret <2 x i32> [[A]] 654; 655entry: 656 br i1 %which, label %final, label %delay 657 658delay: 659 br label %final 660 661final: 662 %A = phi <2 x i32> [ <i32 1000, i32 2500>, %entry ], [ <i32 10, i32 30>, %delay ] 663 %value = and <2 x i32> %A, <i32 123, i32 333> 664 ret <2 x i32> %value 665} 666 667define i32 @test42(i32 %a, i32 %c, i32 %d) { 668; CHECK-LABEL: @test42( 669; CHECK-NEXT: [[FORCE:%.*]] = mul i32 [[C:%.*]], [[D:%.*]] 670; CHECK-NEXT: [[AND:%.*]] = and i32 [[FORCE]], [[A:%.*]] 671; CHECK-NEXT: ret i32 [[AND]] 672; 673 %force = mul i32 %c, %d ; forces the complexity sorting 674 %or = or i32 %a, %force 675 %nota = xor i32 %a, -1 676 %xor = xor i32 %nota, %force 677 %and = and i32 %xor, %or 678 ret i32 %and 679} 680 681define i32 @test43(i32 %a, i32 %c, i32 %d) { 682; CHECK-LABEL: @test43( 683; CHECK-NEXT: [[FORCE:%.*]] = mul i32 [[C:%.*]], [[D:%.*]] 684; CHECK-NEXT: [[AND:%.*]] = and i32 [[FORCE]], [[A:%.*]] 685; CHECK-NEXT: ret i32 [[AND]] 686; 687 %force = mul i32 %c, %d ; forces the complexity sorting 688 %or = or i32 %a, %force 689 %nota = xor i32 %a, -1 690 %xor = xor i32 %nota, %force 691 %and = and i32 %or, %xor 692 ret i32 %and 693} 694 695; (~y | x) & y -> x & y 696define i32 @test44(i32 %x, i32 %y) nounwind { 697; CHECK-LABEL: @test44( 698; CHECK-NEXT: [[A:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] 699; CHECK-NEXT: ret i32 [[A]] 700; 701 %n = xor i32 %y, -1 702 %o = or i32 %n, %x 703 %a = and i32 %o, %y 704 ret i32 %a 705} 706 707; (x | ~y) & y -> x & y 708define i32 @test45(i32 %x, i32 %y) nounwind { 709; CHECK-LABEL: @test45( 710; CHECK-NEXT: [[A:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] 711; CHECK-NEXT: ret i32 [[A]] 712; 713 %n = xor i32 %y, -1 714 %o = or i32 %x, %n 715 %a = and i32 %o, %y 716 ret i32 %a 717} 718 719; y & (~y | x) -> y | x 720define i32 @test46(i32 %x, i32 %y) nounwind { 721; CHECK-LABEL: @test46( 722; CHECK-NEXT: [[A:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] 723; CHECK-NEXT: ret i32 [[A]] 724; 725 %n = xor i32 %y, -1 726 %o = or i32 %n, %x 727 %a = and i32 %y, %o 728 ret i32 %a 729} 730 731; y & (x | ~y) -> y | x 732define i32 @test47(i32 %x, i32 %y) nounwind { 733; CHECK-LABEL: @test47( 734; CHECK-NEXT: [[A:%.*]] = and i32 [[X:%.*]], [[Y:%.*]] 735; CHECK-NEXT: ret i32 [[A]] 736; 737 %n = xor i32 %y, -1 738 %o = or i32 %x, %n 739 %a = and i32 %y, %o 740 ret i32 %a 741} 742 743; In the next 4 tests, vary the types and predicates for extra coverage. 744; (X & (Y | ~X)) -> (X & Y), where 'not' is an inverted cmp 745 746define i1 @and_orn_cmp_1(i32 %a, i32 %b, i32 %c) { 747; CHECK-LABEL: @and_orn_cmp_1( 748; CHECK-NEXT: [[X:%.*]] = icmp sgt i32 [[A:%.*]], [[B:%.*]] 749; CHECK-NEXT: [[Y:%.*]] = icmp ugt i32 [[C:%.*]], 42 750; CHECK-NEXT: [[AND:%.*]] = and i1 [[X]], [[Y]] 751; CHECK-NEXT: ret i1 [[AND]] 752; 753 %x = icmp sgt i32 %a, %b 754 %x_inv = icmp sle i32 %a, %b 755 %y = icmp ugt i32 %c, 42 ; thwart complexity-based ordering 756 %or = or i1 %y, %x_inv 757 %and = and i1 %x, %or 758 ret i1 %and 759} 760 761; Commute the 'and': 762; ((Y | ~X) & X) -> (X & Y), where 'not' is an inverted cmp 763 764define <2 x i1> @and_orn_cmp_2(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c) { 765; CHECK-LABEL: @and_orn_cmp_2( 766; CHECK-NEXT: [[X:%.*]] = icmp sge <2 x i32> [[A:%.*]], [[B:%.*]] 767; CHECK-NEXT: [[Y:%.*]] = icmp ugt <2 x i32> [[C:%.*]], <i32 42, i32 47> 768; CHECK-NEXT: [[AND:%.*]] = and <2 x i1> [[Y]], [[X]] 769; CHECK-NEXT: ret <2 x i1> [[AND]] 770; 771 %x = icmp sge <2 x i32> %a, %b 772 %x_inv = icmp slt <2 x i32> %a, %b 773 %y = icmp ugt <2 x i32> %c, <i32 42, i32 47> ; thwart complexity-based ordering 774 %or = or <2 x i1> %y, %x_inv 775 %and = and <2 x i1> %or, %x 776 ret <2 x i1> %and 777} 778 779; Commute the 'or': 780; (X & (~X | Y)) -> (X & Y), where 'not' is an inverted cmp 781 782define i1 @and_orn_cmp_3(i72 %a, i72 %b, i72 %c) { 783; CHECK-LABEL: @and_orn_cmp_3( 784; CHECK-NEXT: [[X:%.*]] = icmp ugt i72 [[A:%.*]], [[B:%.*]] 785; CHECK-NEXT: [[Y:%.*]] = icmp ugt i72 [[C:%.*]], 42 786; CHECK-NEXT: [[AND:%.*]] = and i1 [[X]], [[Y]] 787; CHECK-NEXT: ret i1 [[AND]] 788; 789 %x = icmp ugt i72 %a, %b 790 %x_inv = icmp ule i72 %a, %b 791 %y = icmp ugt i72 %c, 42 ; thwart complexity-based ordering 792 %or = or i1 %x_inv, %y 793 %and = and i1 %x, %or 794 ret i1 %and 795} 796 797; Commute the 'and': 798; ((~X | Y) & X) -> (X & Y), where 'not' is an inverted cmp 799 800define <3 x i1> @or_andn_cmp_4(<3 x i32> %a, <3 x i32> %b, <3 x i32> %c) { 801; CHECK-LABEL: @or_andn_cmp_4( 802; CHECK-NEXT: [[X:%.*]] = icmp eq <3 x i32> [[A:%.*]], [[B:%.*]] 803; CHECK-NEXT: [[Y:%.*]] = icmp ugt <3 x i32> [[C:%.*]], <i32 42, i32 43, i32 -1> 804; CHECK-NEXT: [[AND:%.*]] = and <3 x i1> [[Y]], [[X]] 805; CHECK-NEXT: ret <3 x i1> [[AND]] 806; 807 %x = icmp eq <3 x i32> %a, %b 808 %x_inv = icmp ne <3 x i32> %a, %b 809 %y = icmp ugt <3 x i32> %c, <i32 42, i32 43, i32 -1> ; thwart complexity-based ordering 810 %or = or <3 x i1> %x_inv, %y 811 %and = and <3 x i1> %or, %x 812 ret <3 x i1> %and 813} 814 815; In the next 4 tests, vary the types and predicates for extra coverage. 816; (~X & (Y | X)) -> (~X & Y), where 'not' is an inverted cmp 817 818define i1 @andn_or_cmp_1(i37 %a, i37 %b, i37 %c) { 819; CHECK-LABEL: @andn_or_cmp_1( 820; CHECK-NEXT: [[X_INV:%.*]] = icmp sle i37 [[A:%.*]], [[B:%.*]] 821; CHECK-NEXT: [[Y:%.*]] = icmp ugt i37 [[C:%.*]], 42 822; CHECK-NEXT: [[AND:%.*]] = and i1 [[X_INV]], [[Y]] 823; CHECK-NEXT: ret i1 [[AND]] 824; 825 %x = icmp sgt i37 %a, %b 826 %x_inv = icmp sle i37 %a, %b 827 %y = icmp ugt i37 %c, 42 ; thwart complexity-based ordering 828 %or = or i1 %y, %x 829 %and = and i1 %x_inv, %or 830 ret i1 %and 831} 832 833; Commute the 'and': 834; ((Y | X) & ~X) -> (~X & Y), where 'not' is an inverted cmp 835 836define i1 @andn_or_cmp_2(i16 %a, i16 %b, i16 %c) { 837; CHECK-LABEL: @andn_or_cmp_2( 838; CHECK-NEXT: [[X_INV:%.*]] = icmp slt i16 [[A:%.*]], [[B:%.*]] 839; CHECK-NEXT: [[Y:%.*]] = icmp ugt i16 [[C:%.*]], 42 840; CHECK-NEXT: [[AND:%.*]] = and i1 [[Y]], [[X_INV]] 841; CHECK-NEXT: ret i1 [[AND]] 842; 843 %x = icmp sge i16 %a, %b 844 %x_inv = icmp slt i16 %a, %b 845 %y = icmp ugt i16 %c, 42 ; thwart complexity-based ordering 846 %or = or i1 %y, %x 847 %and = and i1 %or, %x_inv 848 ret i1 %and 849} 850 851; Commute the 'or': 852; (~X & (X | Y)) -> (~X & Y), where 'not' is an inverted cmp 853 854define <4 x i1> @andn_or_cmp_3(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) { 855; CHECK-LABEL: @andn_or_cmp_3( 856; CHECK-NEXT: [[X_INV:%.*]] = icmp ule <4 x i32> [[A:%.*]], [[B:%.*]] 857; CHECK-NEXT: [[Y:%.*]] = icmp ugt <4 x i32> [[C:%.*]], <i32 42, i32 0, i32 1, i32 -1> 858; CHECK-NEXT: [[AND:%.*]] = and <4 x i1> [[X_INV]], [[Y]] 859; CHECK-NEXT: ret <4 x i1> [[AND]] 860; 861 %x = icmp ugt <4 x i32> %a, %b 862 %x_inv = icmp ule <4 x i32> %a, %b 863 %y = icmp ugt <4 x i32> %c, <i32 42, i32 0, i32 1, i32 -1> ; thwart complexity-based ordering 864 %or = or <4 x i1> %x, %y 865 %and = and <4 x i1> %x_inv, %or 866 ret <4 x i1> %and 867} 868 869; Commute the 'and': 870; ((X | Y) & ~X) -> (~X & Y), where 'not' is an inverted cmp 871 872define i1 @andn_or_cmp_4(i32 %a, i32 %b, i32 %c) { 873; CHECK-LABEL: @andn_or_cmp_4( 874; CHECK-NEXT: [[X_INV:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] 875; CHECK-NEXT: [[Y:%.*]] = icmp ugt i32 [[C:%.*]], 42 876; CHECK-NEXT: [[AND:%.*]] = and i1 [[Y]], [[X_INV]] 877; CHECK-NEXT: ret i1 [[AND]] 878; 879 %x = icmp eq i32 %a, %b 880 %x_inv = icmp ne i32 %a, %b 881 %y = icmp ugt i32 %c, 42 ; thwart complexity-based ordering 882 %or = or i1 %x, %y 883 %and = and i1 %or, %x_inv 884 ret i1 %and 885} 886 887define i32 @lowbitmask_casted_shift(i8 %x) { 888; CHECK-LABEL: @lowbitmask_casted_shift( 889; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X:%.*]] to i32 890; CHECK-NEXT: [[R:%.*]] = lshr i32 [[TMP1]], 1 891; CHECK-NEXT: ret i32 [[R]] 892; 893 %a = ashr i8 %x, 1 894 %s = sext i8 %a to i32 895 %r = and i32 %s, 2147483647 896 ret i32 %r 897} 898 899; Negative test - mask constant is too big. 900 901define i32 @lowbitmask_casted_shift_wrong_mask1(i8 %x) { 902; CHECK-LABEL: @lowbitmask_casted_shift_wrong_mask1( 903; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 2 904; CHECK-NEXT: [[S:%.*]] = sext i8 [[A]] to i32 905; CHECK-NEXT: [[R:%.*]] = and i32 [[S]], 2147483647 906; CHECK-NEXT: ret i32 [[R]] 907; 908 %a = ashr i8 %x, 2 909 %s = sext i8 %a to i32 910 %r = and i32 %s, 2147483647 ; 0x7fffffff 911 ret i32 %r 912} 913 914; Negative test - mask constant is too small. 915 916define i32 @lowbitmask_casted_shift_wrong_mask2(i8 %x) { 917; CHECK-LABEL: @lowbitmask_casted_shift_wrong_mask2( 918; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 2 919; CHECK-NEXT: [[S:%.*]] = sext i8 [[A]] to i32 920; CHECK-NEXT: [[R:%.*]] = and i32 [[S]], 536870911 921; CHECK-NEXT: ret i32 [[R]] 922; 923 %a = ashr i8 %x, 2 924 %s = sext i8 %a to i32 925 %r = and i32 %s, 536870911 ; 0x1fffffff 926 ret i32 %r 927} 928 929; Extra use of shift is ok. 930 931define i32 @lowbitmask_casted_shift_use1(i8 %x) { 932; CHECK-LABEL: @lowbitmask_casted_shift_use1( 933; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 3 934; CHECK-NEXT: call void @use8(i8 [[A]]) 935; CHECK-NEXT: [[TMP1:%.*]] = sext i8 [[X]] to i32 936; CHECK-NEXT: [[R:%.*]] = lshr i32 [[TMP1]], 3 937; CHECK-NEXT: ret i32 [[R]] 938; 939 %a = ashr i8 %x, 3 940 call void @use8(i8 %a) 941 %s = sext i8 %a to i32 942 %r = and i32 %s, 536870911 943 ret i32 %r 944} 945 946; Negative test - extra use of sext requires more instructions. 947 948define i32 @lowbitmask_casted_shift_use2(i8 %x) { 949; CHECK-LABEL: @lowbitmask_casted_shift_use2( 950; CHECK-NEXT: [[A:%.*]] = ashr i8 [[X:%.*]], 3 951; CHECK-NEXT: [[S:%.*]] = sext i8 [[A]] to i32 952; CHECK-NEXT: call void @use32(i32 [[S]]) 953; CHECK-NEXT: [[R:%.*]] = and i32 [[S]], 536870911 954; CHECK-NEXT: ret i32 [[R]] 955; 956 %a = ashr i8 %x, 3 957 %s = sext i8 %a to i32 958 call void @use32(i32 %s) 959 %r = and i32 %s, 536870911 960 ret i32 %r 961} 962 963; Vectors/weird types are ok. 964 965define <2 x i59> @lowbitmask_casted_shift_vec_splat(<2 x i47> %x) { 966; CHECK-LABEL: @lowbitmask_casted_shift_vec_splat( 967; CHECK-NEXT: [[TMP1:%.*]] = sext <2 x i47> [[X:%.*]] to <2 x i59> 968; CHECK-NEXT: [[R:%.*]] = lshr <2 x i59> [[TMP1]], <i59 5, i59 5> 969; CHECK-NEXT: ret <2 x i59> [[R]] 970; 971 %a = ashr <2 x i47> %x, <i47 5, i47 5> 972 %s = sext <2 x i47> %a to <2 x i59> 973 %r = and <2 x i59> %s, <i59 18014398509481983, i59 18014398509481983> ; -1 u>> 5 == 0x3f_ffff_ffff_ffff 974 ret <2 x i59> %r 975} 976 977define i32 @lowmask_sext_in_reg(i32 %x) { 978; CHECK-LABEL: @lowmask_sext_in_reg( 979; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 20 980; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[L]], 20 981; CHECK-NEXT: call void @use32(i32 [[R]]) 982; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 4095 983; CHECK-NEXT: ret i32 [[AND]] 984; 985 %l = shl i32 %x, 20 986 %r = ashr i32 %l, 20 987 call void @use32(i32 %r) 988 %and = and i32 %r, 4095 989 ret i32 %and 990} 991 992; Negative test - mismatched shift amounts 993 994define i32 @lowmask_not_sext_in_reg(i32 %x) { 995; CHECK-LABEL: @lowmask_not_sext_in_reg( 996; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 19 997; CHECK-NEXT: [[R:%.*]] = ashr i32 [[L]], 20 998; CHECK-NEXT: call void @use32(i32 [[R]]) 999; CHECK-NEXT: [[AND:%.*]] = and i32 [[R]], 4095 1000; CHECK-NEXT: ret i32 [[AND]] 1001; 1002 %l = shl i32 %x, 19 1003 %r = ashr i32 %l, 20 1004 call void @use32(i32 %r) 1005 %and = and i32 %r, 4095 1006 ret i32 %and 1007} 1008 1009; Negative test - too much shift for mask 1010 1011define i32 @not_lowmask_sext_in_reg(i32 %x) { 1012; CHECK-LABEL: @not_lowmask_sext_in_reg( 1013; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 20 1014; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[L]], 20 1015; CHECK-NEXT: call void @use32(i32 [[R]]) 1016; CHECK-NEXT: [[AND:%.*]] = and i32 [[R]], 4096 1017; CHECK-NEXT: ret i32 [[AND]] 1018; 1019 %l = shl i32 %x, 20 1020 %r = ashr i32 %l, 20 1021 call void @use32(i32 %r) 1022 %and = and i32 %r, 4096 1023 ret i32 %and 1024} 1025 1026; Negative test - too much shift for mask 1027 1028define i32 @not_lowmask_sext_in_reg2(i32 %x) { 1029; CHECK-LABEL: @not_lowmask_sext_in_reg2( 1030; CHECK-NEXT: [[L:%.*]] = shl i32 [[X:%.*]], 21 1031; CHECK-NEXT: [[R:%.*]] = ashr exact i32 [[L]], 21 1032; CHECK-NEXT: call void @use32(i32 [[R]]) 1033; CHECK-NEXT: [[AND:%.*]] = and i32 [[R]], 4095 1034; CHECK-NEXT: ret i32 [[AND]] 1035; 1036 %l = shl i32 %x, 21 1037 %r = ashr i32 %l, 21 1038 call void @use32(i32 %r) 1039 %and = and i32 %r, 4095 1040 ret i32 %and 1041} 1042 1043define <2 x i32> @lowmask_sext_in_reg_splat(<2 x i32> %x, <2 x i32>* %p) { 1044; CHECK-LABEL: @lowmask_sext_in_reg_splat( 1045; CHECK-NEXT: [[L:%.*]] = shl <2 x i32> [[X:%.*]], <i32 20, i32 20> 1046; CHECK-NEXT: [[R:%.*]] = ashr exact <2 x i32> [[L]], <i32 20, i32 20> 1047; CHECK-NEXT: store <2 x i32> [[R]], <2 x i32>* [[P:%.*]], align 8 1048; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[X]], <i32 4095, i32 4095> 1049; CHECK-NEXT: ret <2 x i32> [[AND]] 1050; 1051 %l = shl <2 x i32> %x, <i32 20, i32 20> 1052 %r = ashr <2 x i32> %l, <i32 20, i32 20> 1053 store <2 x i32> %r, <2 x i32>* %p 1054 %and = and <2 x i32> %r, <i32 4095, i32 4095> 1055 ret <2 x i32> %and 1056} 1057 1058define i8 @lowmask_add(i8 %x) { 1059; CHECK-LABEL: @lowmask_add( 1060; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -64 1061; CHECK-NEXT: call void @use8(i8 [[A]]) 1062; CHECK-NEXT: [[R:%.*]] = and i8 [[X]], 32 1063; CHECK-NEXT: ret i8 [[R]] 1064; 1065 %a = add i8 %x, -64 ; 0xc0 1066 call void @use8(i8 %a) 1067 %r = and i8 %a, 32 ; 0x20 1068 ret i8 %r 1069} 1070 1071define i8 @lowmask_add_2(i8 %x) { 1072; CHECK-LABEL: @lowmask_add_2( 1073; CHECK-NEXT: [[R:%.*]] = and i8 [[X:%.*]], 63 1074; CHECK-NEXT: ret i8 [[R]] 1075; 1076 %a = add i8 %x, -64 ; 0xc0 1077 %r = and i8 %a, 63 ; 0x3f 1078 ret i8 %r 1079} 1080 1081define i8 @lowmask_add_2_uses(i8 %x) { 1082; CHECK-LABEL: @lowmask_add_2_uses( 1083; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -64 1084; CHECK-NEXT: call void @use8(i8 [[A]]) 1085; CHECK-NEXT: [[R:%.*]] = and i8 [[X]], 63 1086; CHECK-NEXT: ret i8 [[R]] 1087; 1088 %a = add i8 %x, -64 ; 0xc0 1089 call void @use8(i8 %a) 1090 %r = and i8 %a, 63 ; 0x3f 1091 ret i8 %r 1092} 1093 1094define <2 x i8> @lowmask_add_2_splat(<2 x i8> %x, <2 x i8>* %p) { 1095; CHECK-LABEL: @lowmask_add_2_splat( 1096; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X:%.*]], <i8 -64, i8 -64> 1097; CHECK-NEXT: store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2 1098; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[X]], <i8 63, i8 63> 1099; CHECK-NEXT: ret <2 x i8> [[R]] 1100; 1101 %a = add <2 x i8> %x, <i8 -64, i8 -64> ; 0xc0 1102 store <2 x i8> %a, <2 x i8>* %p 1103 %r = and <2 x i8> %a, <i8 63, i8 63> ; 0x3f 1104 ret <2 x i8> %r 1105} 1106 1107; Negative test - mask overlaps low bit of add 1108 1109define i8 @not_lowmask_add(i8 %x) { 1110; CHECK-LABEL: @not_lowmask_add( 1111; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -64 1112; CHECK-NEXT: call void @use8(i8 [[A]]) 1113; CHECK-NEXT: [[R:%.*]] = and i8 [[A]], 64 1114; CHECK-NEXT: ret i8 [[R]] 1115; 1116 %a = add i8 %x, -64 ; 0xc0 1117 call void @use8(i8 %a) 1118 %r = and i8 %a, 64 ; 0x40 1119 ret i8 %r 1120} 1121 1122; Negative test - mask overlaps low bit of add 1123 1124define i8 @not_lowmask_add2(i8 %x) { 1125; CHECK-LABEL: @not_lowmask_add2( 1126; CHECK-NEXT: [[A:%.*]] = add i8 [[X:%.*]], -96 1127; CHECK-NEXT: call void @use8(i8 [[A]]) 1128; CHECK-NEXT: [[R:%.*]] = and i8 [[A]], 63 1129; CHECK-NEXT: ret i8 [[R]] 1130; 1131 %a = add i8 %x, -96 ; 0xe0 1132 call void @use8(i8 %a) 1133 %r = and i8 %a, 63 ; 0x3f 1134 ret i8 %r 1135} 1136 1137define <2 x i8> @lowmask_add_splat(<2 x i8> %x, <2 x i8>* %p) { 1138; CHECK-LABEL: @lowmask_add_splat( 1139; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X:%.*]], <i8 -64, i8 -64> 1140; CHECK-NEXT: store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2 1141; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[X]], <i8 32, i8 32> 1142; CHECK-NEXT: ret <2 x i8> [[R]] 1143; 1144 %a = add <2 x i8> %x, <i8 -64, i8 -64> ; 0xc0 1145 store <2 x i8> %a, <2 x i8>* %p 1146 %r = and <2 x i8> %a, <i8 32, i8 32> ; 0x20 1147 ret <2 x i8> %r 1148} 1149 1150define <2 x i8> @lowmask_add_splat_undef(<2 x i8> %x, <2 x i8>* %p) { 1151; CHECK-LABEL: @lowmask_add_splat_undef( 1152; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X:%.*]], <i8 -64, i8 undef> 1153; CHECK-NEXT: store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2 1154; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[A]], <i8 undef, i8 32> 1155; CHECK-NEXT: ret <2 x i8> [[R]] 1156; 1157 %a = add <2 x i8> %x, <i8 -64, i8 undef> ; 0xc0 1158 store <2 x i8> %a, <2 x i8>* %p 1159 %r = and <2 x i8> %a, <i8 undef, i8 32> ; 0x20 1160 ret <2 x i8> %r 1161} 1162 1163define <2 x i8> @lowmask_add_vec(<2 x i8> %x, <2 x i8>* %p) { 1164; CHECK-LABEL: @lowmask_add_vec( 1165; CHECK-NEXT: [[A:%.*]] = add <2 x i8> [[X:%.*]], <i8 -96, i8 -64> 1166; CHECK-NEXT: store <2 x i8> [[A]], <2 x i8>* [[P:%.*]], align 2 1167; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[A]], <i8 16, i8 32> 1168; CHECK-NEXT: ret <2 x i8> [[R]] 1169; 1170 %a = add <2 x i8> %x, <i8 -96, i8 -64> ; 0xe0, 0xc0 1171 store <2 x i8> %a, <2 x i8>* %p 1172 %r = and <2 x i8> %a, <i8 16, i8 32> ; 0x10, 0x20 1173 ret <2 x i8> %r 1174} 1175 1176; Only one bit set 1177define i8 @flip_masked_bit(i8 %A) { 1178; CHECK-LABEL: @flip_masked_bit( 1179; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[A:%.*]], 16 1180; CHECK-NEXT: [[C:%.*]] = xor i8 [[TMP1]], 16 1181; CHECK-NEXT: ret i8 [[C]] 1182; 1183 %B = add i8 %A, 16 1184 %C = and i8 %B, 16 1185 ret i8 %C 1186} 1187 1188define <2 x i8> @flip_masked_bit_uniform(<2 x i8> %A) { 1189; CHECK-LABEL: @flip_masked_bit_uniform( 1190; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[A:%.*]], <i8 16, i8 16> 1191; CHECK-NEXT: [[C:%.*]] = xor <2 x i8> [[TMP1]], <i8 16, i8 16> 1192; CHECK-NEXT: ret <2 x i8> [[C]] 1193; 1194 %B = add <2 x i8> %A, <i8 16, i8 16> 1195 %C = and <2 x i8> %B, <i8 16, i8 16> 1196 ret <2 x i8> %C 1197} 1198 1199define <2 x i8> @flip_masked_bit_undef(<2 x i8> %A) { 1200; CHECK-LABEL: @flip_masked_bit_undef( 1201; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 undef> 1202; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 undef> 1203; CHECK-NEXT: ret <2 x i8> [[C]] 1204; 1205 %B = add <2 x i8> %A, <i8 16, i8 undef> 1206 %C = and <2 x i8> %B, <i8 16, i8 undef> 1207 ret <2 x i8> %C 1208} 1209 1210define <2 x i8> @flip_masked_bit_nonuniform(<2 x i8> %A) { 1211; CHECK-LABEL: @flip_masked_bit_nonuniform( 1212; CHECK-NEXT: [[B:%.*]] = add <2 x i8> [[A:%.*]], <i8 16, i8 4> 1213; CHECK-NEXT: [[C:%.*]] = and <2 x i8> [[B]], <i8 16, i8 4> 1214; CHECK-NEXT: ret <2 x i8> [[C]] 1215; 1216 %B = add <2 x i8> %A, <i8 16, i8 4> 1217 %C = and <2 x i8> %B, <i8 16, i8 4> 1218 ret <2 x i8> %C 1219} 1220