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(i4) 5 6; PR1510 7 8; (a | b) & ~(a & b) --> a ^ b 9 10define i32 @and_to_xor1(i32 %a, i32 %b) { 11; CHECK-LABEL: @and_to_xor1( 12; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 13; CHECK-NEXT: ret i32 [[AND2]] 14; 15 %or = or i32 %a, %b 16 %and = and i32 %a, %b 17 %not = xor i32 %and, -1 18 %and2 = and i32 %or, %not 19 ret i32 %and2 20} 21 22; ~(a & b) & (a | b) --> a ^ b 23 24define i32 @and_to_xor2(i32 %a, i32 %b) { 25; CHECK-LABEL: @and_to_xor2( 26; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 27; CHECK-NEXT: ret i32 [[AND2]] 28; 29 %or = or i32 %a, %b 30 %and = and i32 %a, %b 31 %not = xor i32 %and, -1 32 %and2 = and i32 %not, %or 33 ret i32 %and2 34} 35 36; (a | b) & ~(b & a) --> a ^ b 37 38define i32 @and_to_xor3(i32 %a, i32 %b) { 39; CHECK-LABEL: @and_to_xor3( 40; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 41; CHECK-NEXT: ret i32 [[AND2]] 42; 43 %or = or i32 %a, %b 44 %and = and i32 %b, %a 45 %not = xor i32 %and, -1 46 %and2 = and i32 %or, %not 47 ret i32 %and2 48} 49 50; ~(a & b) & (b | a) --> a ^ b 51 52define i32 @and_to_xor4(i32 %a, i32 %b) { 53; CHECK-LABEL: @and_to_xor4( 54; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[B:%.*]], [[A:%.*]] 55; CHECK-NEXT: ret i32 [[AND2]] 56; 57 %or = or i32 %b, %a 58 %and = and i32 %a, %b 59 %not = xor i32 %and, -1 60 %and2 = and i32 %not, %or 61 ret i32 %and2 62} 63 64define <4 x i32> @and_to_xor1_vec(<4 x i32> %a, <4 x i32> %b) { 65; CHECK-LABEL: @and_to_xor1_vec( 66; CHECK-NEXT: [[AND2:%.*]] = xor <4 x i32> [[A:%.*]], [[B:%.*]] 67; CHECK-NEXT: ret <4 x i32> [[AND2]] 68; 69 %or = or <4 x i32> %a, %b 70 %and = and <4 x i32> %a, %b 71 %not = xor <4 x i32> %and, < i32 -1, i32 -1, i32 -1, i32 -1 > 72 %and2 = and <4 x i32> %or, %not 73 ret <4 x i32> %and2 74} 75 76; In the next 4 tests, cast instructions are used to thwart operand complexity 77; canonicalizations, so we can test all of the commuted patterns. 78 79; (a | ~b) & (~a | b) --> ~(a ^ b) 80 81define i32 @and_to_nxor1(float %fa, float %fb) { 82; CHECK-LABEL: @and_to_nxor1( 83; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 84; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 85; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] 86; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 87; CHECK-NEXT: ret i32 [[AND]] 88; 89 %a = fptosi float %fa to i32 90 %b = fptosi float %fb to i32 91 %nota = xor i32 %a, -1 92 %notb = xor i32 %b, -1 93 %or1 = or i32 %a, %notb 94 %or2 = or i32 %nota, %b 95 %and = and i32 %or1, %or2 96 ret i32 %and 97} 98 99; (a | ~b) & (b | ~a) --> ~(a ^ b) 100 101define i32 @and_to_nxor2(float %fa, float %fb) { 102; CHECK-LABEL: @and_to_nxor2( 103; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 104; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 105; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] 106; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 107; CHECK-NEXT: ret i32 [[AND]] 108; 109 %a = fptosi float %fa to i32 110 %b = fptosi float %fb to i32 111 %nota = xor i32 %a, -1 112 %notb = xor i32 %b, -1 113 %or1 = or i32 %a, %notb 114 %or2 = or i32 %b, %nota 115 %and = and i32 %or1, %or2 116 ret i32 %and 117} 118 119; (~a | b) & (a | ~b) --> ~(a ^ b) 120 121define i32 @and_to_nxor3(float %fa, float %fb) { 122; CHECK-LABEL: @and_to_nxor3( 123; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 124; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 125; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[A]] 126; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 127; CHECK-NEXT: ret i32 [[AND]] 128; 129 %a = fptosi float %fa to i32 130 %b = fptosi float %fb to i32 131 %nota = xor i32 %a, -1 132 %notb = xor i32 %b, -1 133 %or1 = or i32 %nota, %b 134 %or2 = or i32 %a, %notb 135 %and = and i32 %or1, %or2 136 ret i32 %and 137} 138 139; (~a | b) & (~b | a) --> ~(a ^ b) 140 141define i32 @and_to_nxor4(float %fa, float %fb) { 142; CHECK-LABEL: @and_to_nxor4( 143; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 144; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 145; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[A]] 146; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 147; CHECK-NEXT: ret i32 [[AND]] 148; 149 %a = fptosi float %fa to i32 150 %b = fptosi float %fb to i32 151 %nota = xor i32 %a, -1 152 %notb = xor i32 %b, -1 153 %or1 = or i32 %nota, %b 154 %or2 = or i32 %notb, %a 155 %and = and i32 %or1, %or2 156 ret i32 %and 157} 158 159; (a & ~b) | (~a & b) --> a ^ b 160 161define i32 @or_to_xor1(float %fa, float %fb) { 162; CHECK-LABEL: @or_to_xor1( 163; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 164; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 165; CHECK-NEXT: [[OR:%.*]] = xor i32 [[A]], [[B]] 166; CHECK-NEXT: ret i32 [[OR]] 167; 168 %a = fptosi float %fa to i32 169 %b = fptosi float %fb to i32 170 %nota = xor i32 %a, -1 171 %notb = xor i32 %b, -1 172 %and1 = and i32 %a, %notb 173 %and2 = and i32 %nota, %b 174 %or = or i32 %and1, %and2 175 ret i32 %or 176} 177 178; (a & ~b) | (b & ~a) --> a ^ b 179 180define i32 @or_to_xor2(float %fa, float %fb) { 181; CHECK-LABEL: @or_to_xor2( 182; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 183; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 184; CHECK-NEXT: [[OR:%.*]] = xor i32 [[A]], [[B]] 185; CHECK-NEXT: ret i32 [[OR]] 186; 187 %a = fptosi float %fa to i32 188 %b = fptosi float %fb to i32 189 %nota = xor i32 %a, -1 190 %notb = xor i32 %b, -1 191 %and1 = and i32 %a, %notb 192 %and2 = and i32 %b, %nota 193 %or = or i32 %and1, %and2 194 ret i32 %or 195} 196 197; (~a & b) | (~b & a) --> a ^ b 198 199define i32 @or_to_xor3(float %fa, float %fb) { 200; CHECK-LABEL: @or_to_xor3( 201; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 202; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 203; CHECK-NEXT: [[OR:%.*]] = xor i32 [[B]], [[A]] 204; CHECK-NEXT: ret i32 [[OR]] 205; 206 %a = fptosi float %fa to i32 207 %b = fptosi float %fb to i32 208 %nota = xor i32 %a, -1 209 %notb = xor i32 %b, -1 210 %and1 = and i32 %nota, %b 211 %and2 = and i32 %notb, %a 212 %or = or i32 %and1, %and2 213 ret i32 %or 214} 215 216; (~a & b) | (a & ~b) --> a ^ b 217 218define i32 @or_to_xor4(float %fa, float %fb) { 219; CHECK-LABEL: @or_to_xor4( 220; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 221; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 222; CHECK-NEXT: [[OR:%.*]] = xor i32 [[B]], [[A]] 223; CHECK-NEXT: ret i32 [[OR]] 224; 225 %a = fptosi float %fa to i32 226 %b = fptosi float %fb to i32 227 %nota = xor i32 %a, -1 228 %notb = xor i32 %b, -1 229 %and1 = and i32 %nota, %b 230 %and2 = and i32 %a, %notb 231 %or = or i32 %and1, %and2 232 ret i32 %or 233} 234 235; (a & b) | ~(a | b) --> ~(a ^ b) 236 237define i32 @or_to_nxor1(i32 %a, i32 %b) { 238; CHECK-LABEL: @or_to_nxor1( 239; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 240; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 241; CHECK-NEXT: ret i32 [[OR2]] 242; 243 %and = and i32 %a, %b 244 %or = or i32 %a, %b 245 %notor = xor i32 %or, -1 246 %or2 = or i32 %and, %notor 247 ret i32 %or2 248} 249 250; (a & b) | ~(b | a) --> ~(a ^ b) 251 252define i32 @or_to_nxor2(i32 %a, i32 %b) { 253; CHECK-LABEL: @or_to_nxor2( 254; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 255; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 256; CHECK-NEXT: ret i32 [[OR2]] 257; 258 %and = and i32 %a, %b 259 %or = or i32 %b, %a 260 %notor = xor i32 %or, -1 261 %or2 = or i32 %and, %notor 262 ret i32 %or2 263} 264 265; ~(a | b) | (a & b) --> ~(a ^ b) 266 267define i32 @or_to_nxor3(i32 %a, i32 %b) { 268; CHECK-LABEL: @or_to_nxor3( 269; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 270; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 271; CHECK-NEXT: ret i32 [[OR2]] 272; 273 %and = and i32 %a, %b 274 %or = or i32 %a, %b 275 %notor = xor i32 %or, -1 276 %or2 = or i32 %notor, %and 277 ret i32 %or2 278} 279 280; ~(a | b) | (b & a) --> ~(a ^ b) 281 282define i32 @or_to_nxor4(i32 %a, i32 %b) { 283; CHECK-LABEL: @or_to_nxor4( 284; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], [[A:%.*]] 285; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 286; CHECK-NEXT: ret i32 [[OR2]] 287; 288 %and = and i32 %b, %a 289 %or = or i32 %a, %b 290 %notor = xor i32 %or, -1 291 %or2 = or i32 %notor, %and 292 ret i32 %or2 293} 294 295; (a & b) ^ (a | b) --> a ^ b 296 297define i32 @xor_to_xor1(i32 %a, i32 %b) { 298; CHECK-LABEL: @xor_to_xor1( 299; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 300; CHECK-NEXT: ret i32 [[XOR]] 301; 302 %and = and i32 %a, %b 303 %or = or i32 %a, %b 304 %xor = xor i32 %and, %or 305 ret i32 %xor 306} 307 308; (a & b) ^ (b | a) --> a ^ b 309 310define i32 @xor_to_xor2(i32 %a, i32 %b) { 311; CHECK-LABEL: @xor_to_xor2( 312; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 313; CHECK-NEXT: ret i32 [[XOR]] 314; 315 %and = and i32 %a, %b 316 %or = or i32 %b, %a 317 %xor = xor i32 %and, %or 318 ret i32 %xor 319} 320 321; (a | b) ^ (a & b) --> a ^ b 322 323define i32 @xor_to_xor3(i32 %a, i32 %b) { 324; CHECK-LABEL: @xor_to_xor3( 325; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 326; CHECK-NEXT: ret i32 [[XOR]] 327; 328 %or = or i32 %a, %b 329 %and = and i32 %a, %b 330 %xor = xor i32 %or, %and 331 ret i32 %xor 332} 333 334; (a | b) ^ (b & a) --> a ^ b 335 336define i32 @xor_to_xor4(i32 %a, i32 %b) { 337; CHECK-LABEL: @xor_to_xor4( 338; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B:%.*]], [[A:%.*]] 339; CHECK-NEXT: ret i32 [[XOR]] 340; 341 %or = or i32 %a, %b 342 %and = and i32 %b, %a 343 %xor = xor i32 %or, %and 344 ret i32 %xor 345} 346 347; (a | ~b) ^ (~a | b) --> a ^ b 348 349; In the next 8 tests, cast instructions are used to thwart operand complexity 350; canonicalizations, so we can test all of the commuted patterns. 351 352define i32 @xor_to_xor5(float %fa, float %fb) { 353; CHECK-LABEL: @xor_to_xor5( 354; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 355; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 356; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] 357; CHECK-NEXT: ret i32 [[XOR]] 358; 359 %a = fptosi float %fa to i32 360 %b = fptosi float %fb to i32 361 %nota = xor i32 %a, -1 362 %notb = xor i32 %b, -1 363 %or1 = or i32 %a, %notb 364 %or2 = or i32 %nota, %b 365 %xor = xor i32 %or1, %or2 366 ret i32 %xor 367} 368 369; (a | ~b) ^ (b | ~a) --> a ^ b 370 371define i32 @xor_to_xor6(float %fa, float %fb) { 372; CHECK-LABEL: @xor_to_xor6( 373; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 374; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 375; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] 376; CHECK-NEXT: ret i32 [[XOR]] 377; 378 %a = fptosi float %fa to i32 379 %b = fptosi float %fb to i32 380 %nota = xor i32 %a, -1 381 %notb = xor i32 %b, -1 382 %or1 = or i32 %a, %notb 383 %or2 = or i32 %b, %nota 384 %xor = xor i32 %or1, %or2 385 ret i32 %xor 386} 387 388; (~a | b) ^ (a | ~b) --> a ^ b 389 390define i32 @xor_to_xor7(float %fa, float %fb) { 391; CHECK-LABEL: @xor_to_xor7( 392; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 393; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 394; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] 395; CHECK-NEXT: ret i32 [[XOR]] 396; 397 %a = fptosi float %fa to i32 398 %b = fptosi float %fb to i32 399 %nota = xor i32 %a, -1 400 %notb = xor i32 %b, -1 401 %or1 = or i32 %a, %notb 402 %or2 = or i32 %nota, %b 403 %xor = xor i32 %or2, %or1 404 ret i32 %xor 405} 406 407; (~a | b) ^ (~b | a) --> a ^ b 408 409define i32 @xor_to_xor8(float %fa, float %fb) { 410; CHECK-LABEL: @xor_to_xor8( 411; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 412; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 413; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] 414; CHECK-NEXT: ret i32 [[XOR]] 415; 416 %a = fptosi float %fa to i32 417 %b = fptosi float %fb to i32 418 %nota = xor i32 %a, -1 419 %notb = xor i32 %b, -1 420 %or1 = or i32 %notb, %a 421 %or2 = or i32 %nota, %b 422 %xor = xor i32 %or2, %or1 423 ret i32 %xor 424} 425 426; (a & ~b) ^ (~a & b) --> a ^ b 427 428define i32 @xor_to_xor9(float %fa, float %fb) { 429; CHECK-LABEL: @xor_to_xor9( 430; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 431; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 432; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] 433; CHECK-NEXT: ret i32 [[XOR]] 434; 435 %a = fptosi float %fa to i32 436 %b = fptosi float %fb to i32 437 %nota = xor i32 %a, -1 438 %notb = xor i32 %b, -1 439 %and1 = and i32 %a, %notb 440 %and2 = and i32 %nota, %b 441 %xor = xor i32 %and1, %and2 442 ret i32 %xor 443} 444 445; (a & ~b) ^ (b & ~a) --> a ^ b 446 447define i32 @xor_to_xor10(float %fa, float %fb) { 448; CHECK-LABEL: @xor_to_xor10( 449; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 450; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 451; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] 452; CHECK-NEXT: ret i32 [[XOR]] 453; 454 %a = fptosi float %fa to i32 455 %b = fptosi float %fb to i32 456 %nota = xor i32 %a, -1 457 %notb = xor i32 %b, -1 458 %and1 = and i32 %a, %notb 459 %and2 = and i32 %b, %nota 460 %xor = xor i32 %and1, %and2 461 ret i32 %xor 462} 463 464; (~a & b) ^ (a & ~b) --> a ^ b 465 466define i32 @xor_to_xor11(float %fa, float %fb) { 467; CHECK-LABEL: @xor_to_xor11( 468; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 469; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 470; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] 471; CHECK-NEXT: ret i32 [[XOR]] 472; 473 %a = fptosi float %fa to i32 474 %b = fptosi float %fb to i32 475 %nota = xor i32 %a, -1 476 %notb = xor i32 %b, -1 477 %and1 = and i32 %a, %notb 478 %and2 = and i32 %nota, %b 479 %xor = xor i32 %and2, %and1 480 ret i32 %xor 481} 482 483; (~a & b) ^ (~b & a) --> a ^ b 484 485define i32 @xor_to_xor12(float %fa, float %fb) { 486; CHECK-LABEL: @xor_to_xor12( 487; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 488; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 489; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] 490; CHECK-NEXT: ret i32 [[XOR]] 491; 492 %a = fptosi float %fa to i32 493 %b = fptosi float %fb to i32 494 %nota = xor i32 %a, -1 495 %notb = xor i32 %b, -1 496 %and1 = and i32 %notb, %a 497 %and2 = and i32 %nota, %b 498 %xor = xor i32 %and2, %and1 499 ret i32 %xor 500} 501 502; https://bugs.llvm.org/show_bug.cgi?id=32830 503; Make sure we're matching operands correctly and not folding things wrongly. 504 505define i64 @PR32830(i64 %a, i64 %b, i64 %c) { 506; CHECK-LABEL: @PR32830( 507; CHECK-NEXT: [[NOTA:%.*]] = xor i64 [[A:%.*]], -1 508; CHECK-NEXT: [[NOTB:%.*]] = xor i64 [[B:%.*]], -1 509; CHECK-NEXT: [[OR1:%.*]] = or i64 [[A]], [[NOTB]] 510; CHECK-NEXT: [[OR2:%.*]] = or i64 [[C:%.*]], [[NOTA]] 511; CHECK-NEXT: [[AND:%.*]] = and i64 [[OR1]], [[OR2]] 512; CHECK-NEXT: ret i64 [[AND]] 513; 514 %nota = xor i64 %a, -1 515 %notb = xor i64 %b, -1 516 %or1 = or i64 %notb, %a 517 %or2 = or i64 %nota, %c 518 %and = and i64 %or1, %or2 519 ret i64 %and 520} 521 522; (~a | b) & (~b | a) --> ~(a ^ b) 523; TODO: this increases instruction count if the pieces have additional users 524define i32 @and_to_nxor_multiuse(float %fa, float %fb) { 525; CHECK-LABEL: @and_to_nxor_multiuse( 526; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 527; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 528; CHECK-NEXT: [[NOTA:%.*]] = xor i32 [[A]], -1 529; CHECK-NEXT: [[NOTB:%.*]] = xor i32 [[B]], -1 530; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOTA]], [[B]] 531; CHECK-NEXT: [[OR2:%.*]] = or i32 [[NOTB]], [[A]] 532; CHECK-NEXT: [[AND:%.*]] = and i32 [[OR1]], [[OR2]] 533; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[OR1]], [[OR2]] 534; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], [[AND]] 535; CHECK-NEXT: ret i32 [[MUL2]] 536; 537 %a = fptosi float %fa to i32 538 %b = fptosi float %fb to i32 539 %nota = xor i32 %a, -1 540 %notb = xor i32 %b, -1 541 %or1 = or i32 %nota, %b 542 %or2 = or i32 %notb, %a 543 %and = and i32 %or1, %or2 544 %mul1 = mul i32 %or1, %or2 ; here to increase the use count of the inputs to the and 545 %mul2 = mul i32 %mul1, %and 546 ret i32 %mul2 547} 548 549; (a & b) | ~(a | b) --> ~(a ^ b) 550; TODO: this increases instruction count if the pieces have additional users 551define i32 @or_to_nxor_multiuse(i32 noundef %a, i32 noundef %b) { 552; CHECK-LABEL: @or_to_nxor_multiuse( 553; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]] 554; CHECK-NEXT: [[OR:%.*]] = or i32 [[A]], [[B]] 555; CHECK-NEXT: [[NOTOR:%.*]] = xor i32 [[OR]], -1 556; CHECK-NEXT: [[OR2:%.*]] = or disjoint i32 [[AND]], [[NOTOR]] 557; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[AND]], [[NOTOR]] 558; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], [[OR2]] 559; CHECK-NEXT: ret i32 [[MUL2]] 560; 561 %and = and i32 %a, %b 562 %or = or i32 %a, %b 563 %notor = xor i32 %or, -1 564 %or2 = or i32 %and, %notor 565 %mul1 = mul i32 %and, %notor ; here to increase the use count of the inputs to the or 566 %mul2 = mul i32 %mul1, %or2 567 ret i32 %mul2 568} 569 570; (a | b) ^ (~a | ~b) --> ~(a ^ b) 571define i32 @xor_to_xnor1(float %fa, float %fb) { 572; CHECK-LABEL: @xor_to_xnor1( 573; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 574; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 575; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] 576; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[TMP1]], -1 577; CHECK-NEXT: ret i32 [[XOR]] 578; 579 %a = fptosi float %fa to i32 580 %b = fptosi float %fb to i32 581 %nota = xor i32 %a, -1 582 %notb = xor i32 %b, -1 583 %or1 = or i32 %a, %b 584 %or2 = or i32 %nota, %notb 585 %xor = xor i32 %or1, %or2 586 ret i32 %xor 587} 588 589; (a | b) ^ (~b | ~a) --> ~(a ^ b) 590define i32 @xor_to_xnor2(float %fa, float %fb) { 591; CHECK-LABEL: @xor_to_xnor2( 592; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 593; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 594; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] 595; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[TMP1]], -1 596; CHECK-NEXT: ret i32 [[XOR]] 597; 598 %a = fptosi float %fa to i32 599 %b = fptosi float %fb to i32 600 %nota = xor i32 %a, -1 601 %notb = xor i32 %b, -1 602 %or1 = or i32 %a, %b 603 %or2 = or i32 %notb, %nota 604 %xor = xor i32 %or1, %or2 605 ret i32 %xor 606} 607 608; (~a | ~b) ^ (a | b) --> ~(a ^ b) 609define i32 @xor_to_xnor3(float %fa, float %fb) { 610; CHECK-LABEL: @xor_to_xnor3( 611; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 612; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 613; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] 614; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[TMP1]], -1 615; CHECK-NEXT: ret i32 [[XOR]] 616; 617 %a = fptosi float %fa to i32 618 %b = fptosi float %fb to i32 619 %nota = xor i32 %a, -1 620 %notb = xor i32 %b, -1 621 %or1 = or i32 %nota, %notb 622 %or2 = or i32 %a, %b 623 %xor = xor i32 %or1, %or2 624 ret i32 %xor 625} 626 627; (~a | ~b) ^ (b | a) --> ~(a ^ b) 628define i32 @xor_to_xnor4(float %fa, float %fb) { 629; CHECK-LABEL: @xor_to_xnor4( 630; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 631; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 632; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[A]] 633; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[TMP1]], -1 634; CHECK-NEXT: ret i32 [[XOR]] 635; 636 %a = fptosi float %fa to i32 637 %b = fptosi float %fb to i32 638 %nota = xor i32 %a, -1 639 %notb = xor i32 %b, -1 640 %or1 = or i32 %nota, %notb 641 %or2 = or i32 %b, %a 642 %xor = xor i32 %or1, %or2 643 ret i32 %xor 644} 645 646define i4 @simplify_or_common_op_commute0(i4 %x, i4 %y, i4 %z) { 647; CHECK-LABEL: @simplify_or_common_op_commute0( 648; CHECK-NEXT: ret i4 -1 649; 650 %xy = and i4 %x, %y 651 %xyz = and i4 %xy, %z 652 %not_xyz = xor i4 %xyz, -1 653 %r = or i4 %not_xyz, %x 654 ret i4 %r 655} 656 657define i4 @simplify_or_common_op_commute1(i4 %x, i4 %y, i4 %z) { 658; CHECK-LABEL: @simplify_or_common_op_commute1( 659; CHECK-NEXT: ret i4 -1 660; 661 %xy = and i4 %y, %x 662 %xyz = and i4 %xy, %z 663 %not_xyz = xor i4 %xyz, -1 664 %r = or i4 %not_xyz, %x 665 ret i4 %r 666} 667 668; The common operand may bubble through multiple instructions. 669 670define i4 @simplify_or_common_op_commute2(i4 %x, i4 %y, i4 %p, i4 %q) { 671; CHECK-LABEL: @simplify_or_common_op_commute2( 672; CHECK-NEXT: ret i4 -1 673; 674 %z = mul i4 %p, %p ; thwart complexity-based canonicalization 675 %xy = and i4 %x, %y 676 %xyz = and i4 %z, %xy 677 %xyzq = and i4 %xyz, %q 678 %not_xyzq = xor i4 %xyzq, -1 679 %r = or i4 %not_xyzq, %x 680 ret i4 %r 681} 682 683define <2 x i4> @simplify_or_common_op_commute3(<2 x i4> %x, <2 x i4> %y, <2 x i4> %p) { 684; CHECK-LABEL: @simplify_or_common_op_commute3( 685; CHECK-NEXT: ret <2 x i4> splat (i4 -1) 686; 687 %z = mul <2 x i4> %p, %p ; thwart complexity-based canonicalization 688 %xy = and <2 x i4> %y, %x 689 %xyz = and <2 x i4> %z, %xy 690 %not_xyz = xor <2 x i4> %xyz, <i4 -1, i4 -1> 691 %r = or <2 x i4> %x, %not_xyz 692 ret <2 x i4> %r 693} 694 695define i4 @simplify_and_common_op_commute0(i4 %x, i4 %y, i4 %z) { 696; CHECK-LABEL: @simplify_and_common_op_commute0( 697; CHECK-NEXT: call void @use(i4 [[X:%.*]]) 698; CHECK-NEXT: ret i4 0 699; 700 %xy = or i4 %x, %y 701 call void @use(i4 %x) 702 %xyz = or i4 %xy, %z 703 %not_xyz = xor i4 %xyz, -1 704 %r = and i4 %not_xyz, %x 705 ret i4 %r 706} 707 708define i4 @simplify_and_common_op_commute1(i4 %x, i4 %y, i4 %z) { 709; CHECK-LABEL: @simplify_and_common_op_commute1( 710; CHECK-NEXT: ret i4 0 711; 712 %xy = or i4 %y, %x 713 %xyz = or i4 %xy, %z 714 %not_xyz = xor i4 %xyz, -1 715 %r = and i4 %not_xyz, %x 716 ret i4 %r 717} 718 719; The common operand may bubble through multiple instructions. 720 721define i4 @simplify_and_common_op_commute2(i4 %x, i4 %y, i4 %p, i4 %q) { 722; CHECK-LABEL: @simplify_and_common_op_commute2( 723; CHECK-NEXT: ret i4 0 724; 725 %z = mul i4 %p, %p ; thwart complexity-based canonicalization 726 %xy = or i4 %x, %y 727 %xyz = or i4 %z, %xy 728 %xyzq = or i4 %xyz, %q 729 %not_xyzq = xor i4 %xyzq, -1 730 %r = and i4 %not_xyzq, %x 731 ret i4 %r 732} 733 734define <2 x i4> @simplify_and_common_op_commute3(<2 x i4> %x, <2 x i4> %y, <2 x i4> %p) { 735; CHECK-LABEL: @simplify_and_common_op_commute3( 736; CHECK-NEXT: ret <2 x i4> zeroinitializer 737; 738 %z = mul <2 x i4> %p, %p ; thwart complexity-based canonicalization 739 %xy = or <2 x i4> %y, %x 740 %xyz = or <2 x i4> %z, %xy 741 %not_xyz = xor <2 x i4> %xyz, <i4 -1, i4 -1> 742 %r = and <2 x i4> %x, %not_xyz 743 ret <2 x i4> %r 744} 745 746define i4 @simplify_and_common_op_use1(i4 %x, i4 %y, i4 %z) { 747; CHECK-LABEL: @simplify_and_common_op_use1( 748; CHECK-NEXT: call void @use(i4 [[Y:%.*]]) 749; CHECK-NEXT: ret i4 0 750; 751 %xy = or i4 %x, %y 752 call void @use(i4 %y) 753 %xyz = or i4 %xy, %z 754 %not_xyz = xor i4 %xyz, -1 755 %r = and i4 %not_xyz, %x 756 ret i4 %r 757} 758 759; TODO: This should simplify. 760 761define i4 @simplify_and_common_op_use2(i4 %x, i4 %y, i4 %z) { 762; CHECK-LABEL: @simplify_and_common_op_use2( 763; CHECK-NEXT: call void @use(i4 [[Y:%.*]]) 764; CHECK-NEXT: ret i4 0 765; 766 %xy = or i4 %y, %x 767 call void @use(i4 %y) 768 %xyz = or i4 %xy, %z 769 %not_xyz = xor i4 %xyz, -1 770 %r = and i4 %not_xyz, %x 771 ret i4 %r 772} 773 774; TODO: This should simplify. 775 776define i4 @simplify_and_common_op_use3(i4 %x, i4 %y, i4 %z) { 777; CHECK-LABEL: @simplify_and_common_op_use3( 778; CHECK-NEXT: call void @use(i4 [[Z:%.*]]) 779; CHECK-NEXT: ret i4 0 780; 781 %xy = or i4 %x, %y 782 %xyz = or i4 %xy, %z 783 call void @use(i4 %z) 784 %not_xyz = xor i4 %xyz, -1 785 %r = and i4 %not_xyz, %x 786 ret i4 %r 787} 788 789define i4 @reduce_xor_common_op_commute0(i4 %x, i4 %y, i4 %z) { 790; CHECK-LABEL: @reduce_xor_common_op_commute0( 791; CHECK-NEXT: [[TMP1:%.*]] = xor i4 [[Y:%.*]], [[Z:%.*]] 792; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[X:%.*]] 793; CHECK-NEXT: ret i4 [[R]] 794; 795 %xy = xor i4 %x, %y 796 %xyz = xor i4 %xy, %z 797 %r = or i4 %xyz, %x 798 ret i4 %r 799} 800 801define i4 @reduce_xor_common_op_commute1(i4 %x, i4 %y, i4 %z) { 802; CHECK-LABEL: @reduce_xor_common_op_commute1( 803; CHECK-NEXT: [[TMP1:%.*]] = xor i4 [[Y:%.*]], [[Z:%.*]] 804; CHECK-NEXT: [[R:%.*]] = or i4 [[TMP1]], [[X:%.*]] 805; CHECK-NEXT: ret i4 [[R]] 806; 807 %xy = xor i4 %y, %x 808 %xyz = xor i4 %xy, %z 809 %r = or i4 %xyz, %x 810 ret i4 %r 811} 812 813define i4 @annihilate_xor_common_op_commute2(i4 %x, i4 %y, i4 %p, i4 %q) { 814; CHECK-LABEL: @annihilate_xor_common_op_commute2( 815; CHECK-NEXT: [[Z:%.*]] = mul i4 [[P:%.*]], [[P]] 816; CHECK-NEXT: [[TMP1:%.*]] = xor i4 [[Y:%.*]], [[Z]] 817; CHECK-NEXT: [[TMP2:%.*]] = xor i4 [[TMP1]], [[Q:%.*]] 818; CHECK-NEXT: ret i4 [[TMP2]] 819; 820 %z = mul i4 %p, %p ; thwart complexity-based canonicalization 821 %xy = xor i4 %x, %y 822 %xyz = xor i4 %z, %xy 823 %xyzq = xor i4 %xyz, %q 824 %r = xor i4 %xyzq, %x 825 ret i4 %r 826} 827 828define <2 x i4> @reduce_xor_common_op_commute3(<2 x i4> %x, <2 x i4> %y, <2 x i4> %p) { 829; CHECK-LABEL: @reduce_xor_common_op_commute3( 830; CHECK-NEXT: [[Z:%.*]] = mul <2 x i4> [[P:%.*]], [[P]] 831; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i4> [[Y:%.*]], [[Z]] 832; CHECK-NEXT: [[R:%.*]] = or <2 x i4> [[X:%.*]], [[TMP1]] 833; CHECK-NEXT: ret <2 x i4> [[R]] 834; 835 %z = mul <2 x i4> %p, %p ; thwart complexity-based canonicalization 836 %xy = xor <2 x i4> %y, %x 837 %xyz = xor <2 x i4> %z, %xy 838 %r = or <2 x i4> %x, %xyz 839 ret <2 x i4> %r 840} 841