1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; PR1510 5 6; (a | b) & ~(a & b) --> a ^ b 7 8define i32 @and_to_xor1(i32 %a, i32 %b) { 9; CHECK-LABEL: @and_to_xor1( 10; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 11; CHECK-NEXT: ret i32 [[AND2]] 12; 13 %or = or i32 %a, %b 14 %and = and i32 %a, %b 15 %not = xor i32 %and, -1 16 %and2 = and i32 %or, %not 17 ret i32 %and2 18} 19 20; ~(a & b) & (a | b) --> a ^ b 21 22define i32 @and_to_xor2(i32 %a, i32 %b) { 23; CHECK-LABEL: @and_to_xor2( 24; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 25; CHECK-NEXT: ret i32 [[AND2]] 26; 27 %or = or i32 %a, %b 28 %and = and i32 %a, %b 29 %not = xor i32 %and, -1 30 %and2 = and i32 %not, %or 31 ret i32 %and2 32} 33 34; (a | b) & ~(b & a) --> a ^ b 35 36define i32 @and_to_xor3(i32 %a, i32 %b) { 37; CHECK-LABEL: @and_to_xor3( 38; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 39; CHECK-NEXT: ret i32 [[AND2]] 40; 41 %or = or i32 %a, %b 42 %and = and i32 %b, %a 43 %not = xor i32 %and, -1 44 %and2 = and i32 %or, %not 45 ret i32 %and2 46} 47 48; ~(a & b) & (b | a) --> a ^ b 49 50define i32 @and_to_xor4(i32 %a, i32 %b) { 51; CHECK-LABEL: @and_to_xor4( 52; CHECK-NEXT: [[AND2:%.*]] = xor i32 [[B:%.*]], [[A:%.*]] 53; CHECK-NEXT: ret i32 [[AND2]] 54; 55 %or = or i32 %b, %a 56 %and = and i32 %a, %b 57 %not = xor i32 %and, -1 58 %and2 = and i32 %not, %or 59 ret i32 %and2 60} 61 62define <4 x i32> @and_to_xor1_vec(<4 x i32> %a, <4 x i32> %b) { 63; CHECK-LABEL: @and_to_xor1_vec( 64; CHECK-NEXT: [[AND2:%.*]] = xor <4 x i32> [[A:%.*]], [[B:%.*]] 65; CHECK-NEXT: ret <4 x i32> [[AND2]] 66; 67 %or = or <4 x i32> %a, %b 68 %and = and <4 x i32> %a, %b 69 %not = xor <4 x i32> %and, < i32 -1, i32 -1, i32 -1, i32 -1 > 70 %and2 = and <4 x i32> %or, %not 71 ret <4 x i32> %and2 72} 73 74; In the next 4 tests, cast instructions are used to thwart operand complexity 75; canonicalizations, so we can test all of the commuted patterns. 76 77; (a | ~b) & (~a | b) --> ~(a ^ b) 78 79define i32 @and_to_nxor1(float %fa, float %fb) { 80; CHECK-LABEL: @and_to_nxor1( 81; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 82; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 83; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] 84; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 85; CHECK-NEXT: ret i32 [[AND]] 86; 87 %a = fptosi float %fa to i32 88 %b = fptosi float %fb to i32 89 %nota = xor i32 %a, -1 90 %notb = xor i32 %b, -1 91 %or1 = or i32 %a, %notb 92 %or2 = or i32 %nota, %b 93 %and = and i32 %or1, %or2 94 ret i32 %and 95} 96 97; (a | ~b) & (b | ~a) --> ~(a ^ b) 98 99define i32 @and_to_nxor2(float %fa, float %fb) { 100; CHECK-LABEL: @and_to_nxor2( 101; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 102; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 103; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] 104; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 105; CHECK-NEXT: ret i32 [[AND]] 106; 107 %a = fptosi float %fa to i32 108 %b = fptosi float %fb to i32 109 %nota = xor i32 %a, -1 110 %notb = xor i32 %b, -1 111 %or1 = or i32 %a, %notb 112 %or2 = or i32 %b, %nota 113 %and = and i32 %or1, %or2 114 ret i32 %and 115} 116 117; (~a | b) & (a | ~b) --> ~(a ^ b) 118 119define i32 @and_to_nxor3(float %fa, float %fb) { 120; CHECK-LABEL: @and_to_nxor3( 121; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 122; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 123; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[A]] 124; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 125; CHECK-NEXT: ret i32 [[AND]] 126; 127 %a = fptosi float %fa to i32 128 %b = fptosi float %fb to i32 129 %nota = xor i32 %a, -1 130 %notb = xor i32 %b, -1 131 %or1 = or i32 %nota, %b 132 %or2 = or i32 %a, %notb 133 %and = and i32 %or1, %or2 134 ret i32 %and 135} 136 137; (~a | b) & (~b | a) --> ~(a ^ b) 138 139define i32 @and_to_nxor4(float %fa, float %fb) { 140; CHECK-LABEL: @and_to_nxor4( 141; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 142; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 143; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[A]] 144; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP1]], -1 145; CHECK-NEXT: ret i32 [[AND]] 146; 147 %a = fptosi float %fa to i32 148 %b = fptosi float %fb to i32 149 %nota = xor i32 %a, -1 150 %notb = xor i32 %b, -1 151 %or1 = or i32 %nota, %b 152 %or2 = or i32 %notb, %a 153 %and = and i32 %or1, %or2 154 ret i32 %and 155} 156 157; (a & ~b) | (~a & b) --> a ^ b 158 159define i32 @or_to_xor1(float %fa, float %fb) { 160; CHECK-LABEL: @or_to_xor1( 161; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 162; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 163; CHECK-NEXT: [[OR:%.*]] = xor i32 [[A]], [[B]] 164; CHECK-NEXT: ret i32 [[OR]] 165; 166 %a = fptosi float %fa to i32 167 %b = fptosi float %fb to i32 168 %nota = xor i32 %a, -1 169 %notb = xor i32 %b, -1 170 %and1 = and i32 %a, %notb 171 %and2 = and i32 %nota, %b 172 %or = or i32 %and1, %and2 173 ret i32 %or 174} 175 176; (a & ~b) | (b & ~a) --> a ^ b 177 178define i32 @or_to_xor2(float %fa, float %fb) { 179; CHECK-LABEL: @or_to_xor2( 180; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 181; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 182; CHECK-NEXT: [[OR:%.*]] = xor i32 [[A]], [[B]] 183; CHECK-NEXT: ret i32 [[OR]] 184; 185 %a = fptosi float %fa to i32 186 %b = fptosi float %fb to i32 187 %nota = xor i32 %a, -1 188 %notb = xor i32 %b, -1 189 %and1 = and i32 %a, %notb 190 %and2 = and i32 %b, %nota 191 %or = or i32 %and1, %and2 192 ret i32 %or 193} 194 195; (~a & b) | (~b & a) --> a ^ b 196 197define i32 @or_to_xor3(float %fa, float %fb) { 198; CHECK-LABEL: @or_to_xor3( 199; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 200; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 201; CHECK-NEXT: [[OR:%.*]] = xor i32 [[B]], [[A]] 202; CHECK-NEXT: ret i32 [[OR]] 203; 204 %a = fptosi float %fa to i32 205 %b = fptosi float %fb to i32 206 %nota = xor i32 %a, -1 207 %notb = xor i32 %b, -1 208 %and1 = and i32 %nota, %b 209 %and2 = and i32 %notb, %a 210 %or = or i32 %and1, %and2 211 ret i32 %or 212} 213 214; (~a & b) | (a & ~b) --> a ^ b 215 216define i32 @or_to_xor4(float %fa, float %fb) { 217; CHECK-LABEL: @or_to_xor4( 218; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 219; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 220; CHECK-NEXT: [[OR:%.*]] = xor i32 [[B]], [[A]] 221; CHECK-NEXT: ret i32 [[OR]] 222; 223 %a = fptosi float %fa to i32 224 %b = fptosi float %fb to i32 225 %nota = xor i32 %a, -1 226 %notb = xor i32 %b, -1 227 %and1 = and i32 %nota, %b 228 %and2 = and i32 %a, %notb 229 %or = or i32 %and1, %and2 230 ret i32 %or 231} 232 233; (a & b) | ~(a | b) --> ~(a ^ b) 234 235define i32 @or_to_nxor1(i32 %a, i32 %b) { 236; CHECK-LABEL: @or_to_nxor1( 237; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 238; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 239; CHECK-NEXT: ret i32 [[OR2]] 240; 241 %and = and i32 %a, %b 242 %or = or i32 %a, %b 243 %notor = xor i32 %or, -1 244 %or2 = or i32 %and, %notor 245 ret i32 %or2 246} 247 248; (a & b) | ~(b | a) --> ~(a ^ b) 249 250define i32 @or_to_nxor2(i32 %a, i32 %b) { 251; CHECK-LABEL: @or_to_nxor2( 252; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 253; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 254; CHECK-NEXT: ret i32 [[OR2]] 255; 256 %and = and i32 %a, %b 257 %or = or i32 %b, %a 258 %notor = xor i32 %or, -1 259 %or2 = or i32 %and, %notor 260 ret i32 %or2 261} 262 263; ~(a | b) | (a & b) --> ~(a ^ b) 264 265define i32 @or_to_nxor3(i32 %a, i32 %b) { 266; CHECK-LABEL: @or_to_nxor3( 267; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 268; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 269; CHECK-NEXT: ret i32 [[OR2]] 270; 271 %and = and i32 %a, %b 272 %or = or i32 %a, %b 273 %notor = xor i32 %or, -1 274 %or2 = or i32 %notor, %and 275 ret i32 %or2 276} 277 278; ~(a | b) | (b & a) --> ~(a ^ b) 279 280define i32 @or_to_nxor4(i32 %a, i32 %b) { 281; CHECK-LABEL: @or_to_nxor4( 282; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], [[A:%.*]] 283; CHECK-NEXT: [[OR2:%.*]] = xor i32 [[TMP1]], -1 284; CHECK-NEXT: ret i32 [[OR2]] 285; 286 %and = and i32 %b, %a 287 %or = or i32 %a, %b 288 %notor = xor i32 %or, -1 289 %or2 = or i32 %notor, %and 290 ret i32 %or2 291} 292 293; (a & b) ^ (a | b) --> a ^ b 294 295define i32 @xor_to_xor1(i32 %a, i32 %b) { 296; CHECK-LABEL: @xor_to_xor1( 297; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 298; CHECK-NEXT: ret i32 [[XOR]] 299; 300 %and = and i32 %a, %b 301 %or = or i32 %a, %b 302 %xor = xor i32 %and, %or 303 ret i32 %xor 304} 305 306; (a & b) ^ (b | a) --> a ^ b 307 308define i32 @xor_to_xor2(i32 %a, i32 %b) { 309; CHECK-LABEL: @xor_to_xor2( 310; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 311; CHECK-NEXT: ret i32 [[XOR]] 312; 313 %and = and i32 %a, %b 314 %or = or i32 %b, %a 315 %xor = xor i32 %and, %or 316 ret i32 %xor 317} 318 319; (a | b) ^ (a & b) --> a ^ b 320 321define i32 @xor_to_xor3(i32 %a, i32 %b) { 322; CHECK-LABEL: @xor_to_xor3( 323; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A:%.*]], [[B:%.*]] 324; CHECK-NEXT: ret i32 [[XOR]] 325; 326 %or = or i32 %a, %b 327 %and = and i32 %a, %b 328 %xor = xor i32 %or, %and 329 ret i32 %xor 330} 331 332; (a | b) ^ (b & a) --> a ^ b 333 334define i32 @xor_to_xor4(i32 %a, i32 %b) { 335; CHECK-LABEL: @xor_to_xor4( 336; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B:%.*]], [[A:%.*]] 337; CHECK-NEXT: ret i32 [[XOR]] 338; 339 %or = or i32 %a, %b 340 %and = and i32 %b, %a 341 %xor = xor i32 %or, %and 342 ret i32 %xor 343} 344 345; (a | ~b) ^ (~a | b) --> a ^ b 346 347; In the next 8 tests, cast instructions are used to thwart operand complexity 348; canonicalizations, so we can test all of the commuted patterns. 349 350define i32 @xor_to_xor5(float %fa, float %fb) { 351; CHECK-LABEL: @xor_to_xor5( 352; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 353; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 354; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] 355; CHECK-NEXT: ret i32 [[XOR]] 356; 357 %a = fptosi float %fa to i32 358 %b = fptosi float %fb to i32 359 %nota = xor i32 %a, -1 360 %notb = xor i32 %b, -1 361 %or1 = or i32 %a, %notb 362 %or2 = or i32 %nota, %b 363 %xor = xor i32 %or1, %or2 364 ret i32 %xor 365} 366 367; (a | ~b) ^ (b | ~a) --> a ^ b 368 369define i32 @xor_to_xor6(float %fa, float %fb) { 370; CHECK-LABEL: @xor_to_xor6( 371; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 372; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 373; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] 374; CHECK-NEXT: ret i32 [[XOR]] 375; 376 %a = fptosi float %fa to i32 377 %b = fptosi float %fb to i32 378 %nota = xor i32 %a, -1 379 %notb = xor i32 %b, -1 380 %or1 = or i32 %a, %notb 381 %or2 = or i32 %b, %nota 382 %xor = xor i32 %or1, %or2 383 ret i32 %xor 384} 385 386; (~a | b) ^ (a | ~b) --> a ^ b 387 388define i32 @xor_to_xor7(float %fa, float %fb) { 389; CHECK-LABEL: @xor_to_xor7( 390; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 391; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 392; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] 393; CHECK-NEXT: ret i32 [[XOR]] 394; 395 %a = fptosi float %fa to i32 396 %b = fptosi float %fb to i32 397 %nota = xor i32 %a, -1 398 %notb = xor i32 %b, -1 399 %or1 = or i32 %a, %notb 400 %or2 = or i32 %nota, %b 401 %xor = xor i32 %or2, %or1 402 ret i32 %xor 403} 404 405; (~a | b) ^ (~b | a) --> a ^ b 406 407define i32 @xor_to_xor8(float %fa, float %fb) { 408; CHECK-LABEL: @xor_to_xor8( 409; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 410; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 411; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] 412; CHECK-NEXT: ret i32 [[XOR]] 413; 414 %a = fptosi float %fa to i32 415 %b = fptosi float %fb to i32 416 %nota = xor i32 %a, -1 417 %notb = xor i32 %b, -1 418 %or1 = or i32 %notb, %a 419 %or2 = or i32 %nota, %b 420 %xor = xor i32 %or2, %or1 421 ret i32 %xor 422} 423 424; (a & ~b) ^ (~a & b) --> a ^ b 425 426define i32 @xor_to_xor9(float %fa, float %fb) { 427; CHECK-LABEL: @xor_to_xor9( 428; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 429; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 430; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] 431; CHECK-NEXT: ret i32 [[XOR]] 432; 433 %a = fptosi float %fa to i32 434 %b = fptosi float %fb to i32 435 %nota = xor i32 %a, -1 436 %notb = xor i32 %b, -1 437 %and1 = and i32 %a, %notb 438 %and2 = and i32 %nota, %b 439 %xor = xor i32 %and1, %and2 440 ret i32 %xor 441} 442 443; (a & ~b) ^ (b & ~a) --> a ^ b 444 445define i32 @xor_to_xor10(float %fa, float %fb) { 446; CHECK-LABEL: @xor_to_xor10( 447; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 448; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 449; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[A]], [[B]] 450; CHECK-NEXT: ret i32 [[XOR]] 451; 452 %a = fptosi float %fa to i32 453 %b = fptosi float %fb to i32 454 %nota = xor i32 %a, -1 455 %notb = xor i32 %b, -1 456 %and1 = and i32 %a, %notb 457 %and2 = and i32 %b, %nota 458 %xor = xor i32 %and1, %and2 459 ret i32 %xor 460} 461 462; (~a & b) ^ (a & ~b) --> a ^ b 463 464define i32 @xor_to_xor11(float %fa, float %fb) { 465; CHECK-LABEL: @xor_to_xor11( 466; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 467; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 468; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] 469; CHECK-NEXT: ret i32 [[XOR]] 470; 471 %a = fptosi float %fa to i32 472 %b = fptosi float %fb to i32 473 %nota = xor i32 %a, -1 474 %notb = xor i32 %b, -1 475 %and1 = and i32 %a, %notb 476 %and2 = and i32 %nota, %b 477 %xor = xor i32 %and2, %and1 478 ret i32 %xor 479} 480 481; (~a & b) ^ (~b & a) --> a ^ b 482 483define i32 @xor_to_xor12(float %fa, float %fb) { 484; CHECK-LABEL: @xor_to_xor12( 485; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 486; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 487; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[B]], [[A]] 488; CHECK-NEXT: ret i32 [[XOR]] 489; 490 %a = fptosi float %fa to i32 491 %b = fptosi float %fb to i32 492 %nota = xor i32 %a, -1 493 %notb = xor i32 %b, -1 494 %and1 = and i32 %notb, %a 495 %and2 = and i32 %nota, %b 496 %xor = xor i32 %and2, %and1 497 ret i32 %xor 498} 499 500; https://bugs.llvm.org/show_bug.cgi?id=32830 501; Make sure we're matching operands correctly and not folding things wrongly. 502 503define i64 @PR32830(i64 %a, i64 %b, i64 %c) { 504; CHECK-LABEL: @PR32830( 505; CHECK-NEXT: [[NOTA:%.*]] = xor i64 [[A:%.*]], -1 506; CHECK-NEXT: [[NOTB:%.*]] = xor i64 [[B:%.*]], -1 507; CHECK-NEXT: [[OR1:%.*]] = or i64 [[NOTB]], [[A]] 508; CHECK-NEXT: [[OR2:%.*]] = or i64 [[NOTA]], [[C:%.*]] 509; CHECK-NEXT: [[AND:%.*]] = and i64 [[OR1]], [[OR2]] 510; CHECK-NEXT: ret i64 [[AND]] 511; 512 %nota = xor i64 %a, -1 513 %notb = xor i64 %b, -1 514 %or1 = or i64 %notb, %a 515 %or2 = or i64 %nota, %c 516 %and = and i64 %or1, %or2 517 ret i64 %and 518} 519 520; (~a | b) & (~b | a) --> ~(a ^ b) 521; TODO: this increases instruction count if the pieces have additional users 522define i32 @and_to_nxor_multiuse(float %fa, float %fb) { 523; CHECK-LABEL: @and_to_nxor_multiuse( 524; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 525; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 526; CHECK-NEXT: [[NOTA:%.*]] = xor i32 [[A]], -1 527; CHECK-NEXT: [[NOTB:%.*]] = xor i32 [[B]], -1 528; CHECK-NEXT: [[OR1:%.*]] = or i32 [[NOTA]], [[B]] 529; CHECK-NEXT: [[OR2:%.*]] = or i32 [[NOTB]], [[A]] 530; CHECK-NEXT: [[AND:%.*]] = and i32 [[OR1]], [[OR2]] 531; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[OR1]], [[OR2]] 532; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], [[AND]] 533; CHECK-NEXT: ret i32 [[MUL2]] 534; 535 %a = fptosi float %fa to i32 536 %b = fptosi float %fb to i32 537 %nota = xor i32 %a, -1 538 %notb = xor i32 %b, -1 539 %or1 = or i32 %nota, %b 540 %or2 = or i32 %notb, %a 541 %and = and i32 %or1, %or2 542 %mul1 = mul i32 %or1, %or2 ; here to increase the use count of the inputs to the and 543 %mul2 = mul i32 %mul1, %and 544 ret i32 %mul2 545} 546 547; (a & b) | ~(a | b) --> ~(a ^ b) 548; TODO: this increases instruction count if the pieces have additional users 549define i32 @or_to_nxor_multiuse(i32 %a, i32 %b) { 550; CHECK-LABEL: @or_to_nxor_multiuse( 551; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], [[B:%.*]] 552; CHECK-NEXT: [[OR:%.*]] = or i32 [[A]], [[B]] 553; CHECK-NEXT: [[NOTOR:%.*]] = xor i32 [[OR]], -1 554; CHECK-NEXT: [[OR2:%.*]] = or i32 [[AND]], [[NOTOR]] 555; CHECK-NEXT: [[MUL1:%.*]] = mul i32 [[AND]], [[NOTOR]] 556; CHECK-NEXT: [[MUL2:%.*]] = mul i32 [[MUL1]], [[OR2]] 557; CHECK-NEXT: ret i32 [[MUL2]] 558; 559 %and = and i32 %a, %b 560 %or = or i32 %a, %b 561 %notor = xor i32 %or, -1 562 %or2 = or i32 %and, %notor 563 %mul1 = mul i32 %and, %notor ; here to increase the use count of the inputs to the or 564 %mul2 = mul i32 %mul1, %or2 565 ret i32 %mul2 566} 567 568; (a | b) ^ (~a | ~b) --> ~(a ^ b) 569define i32 @xor_to_xnor1(float %fa, float %fb) { 570; CHECK-LABEL: @xor_to_xnor1( 571; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 572; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 573; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] 574; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[TMP1]], -1 575; CHECK-NEXT: ret i32 [[XOR]] 576; 577 %a = fptosi float %fa to i32 578 %b = fptosi float %fb to i32 579 %nota = xor i32 %a, -1 580 %notb = xor i32 %b, -1 581 %or1 = or i32 %a, %b 582 %or2 = or i32 %nota, %notb 583 %xor = xor i32 %or1, %or2 584 ret i32 %xor 585} 586 587; (a | b) ^ (~b | ~a) --> ~(a ^ b) 588define i32 @xor_to_xnor2(float %fa, float %fb) { 589; CHECK-LABEL: @xor_to_xnor2( 590; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 591; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 592; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] 593; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[TMP1]], -1 594; CHECK-NEXT: ret i32 [[XOR]] 595; 596 %a = fptosi float %fa to i32 597 %b = fptosi float %fb to i32 598 %nota = xor i32 %a, -1 599 %notb = xor i32 %b, -1 600 %or1 = or i32 %a, %b 601 %or2 = or i32 %notb, %nota 602 %xor = xor i32 %or1, %or2 603 ret i32 %xor 604} 605 606; (~a | ~b) ^ (a | b) --> ~(a ^ b) 607define i32 @xor_to_xnor3(float %fa, float %fb) { 608; CHECK-LABEL: @xor_to_xnor3( 609; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 610; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 611; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[A]], [[B]] 612; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[TMP1]], -1 613; CHECK-NEXT: ret i32 [[XOR]] 614; 615 %a = fptosi float %fa to i32 616 %b = fptosi float %fb to i32 617 %nota = xor i32 %a, -1 618 %notb = xor i32 %b, -1 619 %or1 = or i32 %nota, %notb 620 %or2 = or i32 %a, %b 621 %xor = xor i32 %or1, %or2 622 ret i32 %xor 623} 624 625; (~a | ~b) ^ (b | a) --> ~(a ^ b) 626define i32 @xor_to_xnor4(float %fa, float %fb) { 627; CHECK-LABEL: @xor_to_xnor4( 628; CHECK-NEXT: [[A:%.*]] = fptosi float [[FA:%.*]] to i32 629; CHECK-NEXT: [[B:%.*]] = fptosi float [[FB:%.*]] to i32 630; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B]], [[A]] 631; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[TMP1]], -1 632; CHECK-NEXT: ret i32 [[XOR]] 633; 634 %a = fptosi float %fa to i32 635 %b = fptosi float %fb to i32 636 %nota = xor i32 %a, -1 637 %notb = xor i32 %b, -1 638 %or1 = or i32 %nota, %notb 639 %or2 = or i32 %b, %a 640 %xor = xor i32 %or1, %or2 641 ret i32 %xor 642} 643