1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -instcombine -S | FileCheck %s 3 4; (~A | ~B) == ~(A & B) 5 6define i43 @demorgan_or_apint1(i43 %A, i43 %B) { 7; CHECK-LABEL: @demorgan_or_apint1( 8; CHECK-NEXT: [[C_DEMORGAN:%.*]] = and i43 [[A:%.*]], [[B:%.*]] 9; CHECK-NEXT: [[C:%.*]] = xor i43 [[C_DEMORGAN]], -1 10; CHECK-NEXT: ret i43 [[C]] 11; 12 %NotA = xor i43 %A, -1 13 %NotB = xor i43 %B, -1 14 %C = or i43 %NotA, %NotB 15 ret i43 %C 16} 17 18; (~A | ~B) == ~(A & B) 19 20define i129 @demorgan_or_apint2(i129 %A, i129 %B) { 21; CHECK-LABEL: @demorgan_or_apint2( 22; CHECK-NEXT: [[C_DEMORGAN:%.*]] = and i129 [[A:%.*]], [[B:%.*]] 23; CHECK-NEXT: [[C:%.*]] = xor i129 [[C_DEMORGAN]], -1 24; CHECK-NEXT: ret i129 [[C]] 25; 26 %NotA = xor i129 %A, -1 27 %NotB = xor i129 %B, -1 28 %C = or i129 %NotA, %NotB 29 ret i129 %C 30} 31 32; (~A & ~B) == ~(A | B) 33 34define i477 @demorgan_and_apint1(i477 %A, i477 %B) { 35; CHECK-LABEL: @demorgan_and_apint1( 36; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i477 [[A:%.*]], [[B:%.*]] 37; CHECK-NEXT: [[C:%.*]] = xor i477 [[C_DEMORGAN]], -1 38; CHECK-NEXT: ret i477 [[C]] 39; 40 %NotA = xor i477 %A, -1 41 %NotB = xor i477 %B, -1 42 %C = and i477 %NotA, %NotB 43 ret i477 %C 44} 45 46; (~A & ~B) == ~(A | B) 47 48define i129 @demorgan_and_apint2(i129 %A, i129 %B) { 49; CHECK-LABEL: @demorgan_and_apint2( 50; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i129 [[A:%.*]], [[B:%.*]] 51; CHECK-NEXT: [[C:%.*]] = xor i129 [[C_DEMORGAN]], -1 52; CHECK-NEXT: ret i129 [[C]] 53; 54 %NotA = xor i129 %A, -1 55 %NotB = xor i129 %B, -1 56 %C = and i129 %NotA, %NotB 57 ret i129 %C 58} 59 60; (~A & ~B) == ~(A | B) 61 62define i65 @demorgan_and_apint3(i65 %A, i65 %B) { 63; CHECK-LABEL: @demorgan_and_apint3( 64; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i65 [[A:%.*]], [[B:%.*]] 65; CHECK-NEXT: [[C:%.*]] = xor i65 [[C_DEMORGAN]], -1 66; CHECK-NEXT: ret i65 [[C]] 67; 68 %NotA = xor i65 %A, -1 69 %NotB = xor i65 -1, %B 70 %C = and i65 %NotA, %NotB 71 ret i65 %C 72} 73 74; (~A & ~B) == ~(A | B) 75 76define i66 @demorgan_and_apint4(i66 %A, i66 %B) { 77; CHECK-LABEL: @demorgan_and_apint4( 78; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i66 [[A:%.*]], [[B:%.*]] 79; CHECK-NEXT: [[C:%.*]] = xor i66 [[C_DEMORGAN]], -1 80; CHECK-NEXT: ret i66 [[C]] 81; 82 %NotA = xor i66 %A, -1 83 %NotB = xor i66 %B, -1 84 %C = and i66 %NotA, %NotB 85 ret i66 %C 86} 87 88; (~A & ~B) == ~(A | B) 89 90define i47 @demorgan_and_apint5(i47 %A, i47 %B) { 91; CHECK-LABEL: @demorgan_and_apint5( 92; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i47 [[A:%.*]], [[B:%.*]] 93; CHECK-NEXT: [[C:%.*]] = xor i47 [[C_DEMORGAN]], -1 94; CHECK-NEXT: ret i47 [[C]] 95; 96 %NotA = xor i47 %A, -1 97 %NotB = xor i47 %B, -1 98 %C = and i47 %NotA, %NotB 99 ret i47 %C 100} 101 102; This is confirming that 2 transforms work together: 103; ~(~A & ~B) --> A | B 104 105define i32 @test3(i32 %A, i32 %B) { 106; CHECK-LABEL: @test3( 107; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i32 [[A:%.*]], [[B:%.*]] 108; CHECK-NEXT: ret i32 [[C_DEMORGAN]] 109; 110 %nota = xor i32 %A, -1 111 %notb = xor i32 %B, -1 112 %c = and i32 %nota, %notb 113 %notc = xor i32 %c, -1 114 ret i32 %notc 115} 116 117; Invert a constant if needed: 118; ~(~A & 5) --> A | ~5 119 120define i32 @test4(i32 %A) { 121; CHECK-LABEL: @test4( 122; CHECK-NEXT: [[NOTC1:%.*]] = or i32 [[A:%.*]], -6 123; CHECK-NEXT: ret i32 [[NOTC1]] 124; 125 %nota = xor i32 %A, -1 126 %c = and i32 %nota, 5 127 %notc = xor i32 %c, -1 128 ret i32 %notc 129} 130 131; Test the mirror of DeMorgan's law with an extra 'not'. 132; ~(~A | ~B) --> A & B 133 134define i32 @test5(i32 %A, i32 %B) { 135; CHECK-LABEL: @test5( 136; CHECK-NEXT: [[C_DEMORGAN:%.*]] = and i32 [[A:%.*]], [[B:%.*]] 137; CHECK-NEXT: ret i32 [[C_DEMORGAN]] 138; 139 %nota = xor i32 %A, -1 140 %notb = xor i32 %B, -1 141 %c = or i32 %nota, %notb 142 %notc = xor i32 %c, -1 143 ret i32 %notc 144} 145 146; Repeat with weird types for extra coverage. 147; ~(~A & ~B) --> A | B 148 149define i47 @test3_apint(i47 %A, i47 %B) { 150; CHECK-LABEL: @test3_apint( 151; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i47 [[A:%.*]], [[B:%.*]] 152; CHECK-NEXT: ret i47 [[C_DEMORGAN]] 153; 154 %nota = xor i47 %A, -1 155 %notb = xor i47 %B, -1 156 %c = and i47 %nota, %notb 157 %notc = xor i47 %c, -1 158 ret i47 %notc 159} 160 161; ~(~A & 5) --> A | ~5 162 163define i61 @test4_apint(i61 %A) { 164; CHECK-LABEL: @test4_apint( 165; CHECK-NEXT: [[NOTA:%.*]] = and i61 [[A:%.*]], 5 166; CHECK-NEXT: [[C:%.*]] = xor i61 [[NOTA]], 5 167; CHECK-NEXT: ret i61 [[C]] 168; 169 %nota = xor i61 %A, -1 170 %c = and i61 %nota, 5 ; 5 = ~c2 171 %notc = xor i61 %c, -1 172 ret i61 %c 173} 174 175; ~(~A | ~B) --> A & B 176 177define i71 @test5_apint(i71 %A, i71 %B) { 178; CHECK-LABEL: @test5_apint( 179; CHECK-NEXT: [[C_DEMORGAN:%.*]] = and i71 [[A:%.*]], [[B:%.*]] 180; CHECK-NEXT: ret i71 [[C_DEMORGAN]] 181; 182 %nota = xor i71 %A, -1 183 %notb = xor i71 %B, -1 184 %c = or i71 %nota, %notb 185 %notc = xor i71 %c, -1 186 ret i71 %notc 187} 188 189; ~(~A & B) --> (A | ~B) 190 191define i8 @demorgan_nand(i8 %A, i8 %B) { 192; CHECK-LABEL: @demorgan_nand( 193; CHECK-NEXT: [[B_NOT:%.*]] = xor i8 [[B:%.*]], -1 194; CHECK-NEXT: [[NOTC:%.*]] = or i8 [[B_NOT]], [[A:%.*]] 195; CHECK-NEXT: ret i8 [[NOTC]] 196; 197 %notx = xor i8 %A, -1 198 %c = and i8 %notx, %B 199 %notc = xor i8 %c, -1 200 ret i8 %notc 201} 202 203; ~(~A & B) --> (A | ~B) 204 205define i7 @demorgan_nand_apint1(i7 %A, i7 %B) { 206; CHECK-LABEL: @demorgan_nand_apint1( 207; CHECK-NEXT: [[B_NOT:%.*]] = xor i7 [[B:%.*]], -1 208; CHECK-NEXT: [[NOTC:%.*]] = or i7 [[B_NOT]], [[A:%.*]] 209; CHECK-NEXT: ret i7 [[NOTC]] 210; 211 %nota = xor i7 %A, -1 212 %c = and i7 %nota, %B 213 %notc = xor i7 %c, -1 214 ret i7 %notc 215} 216 217; ~(~A & B) --> (A | ~B) 218 219define i117 @demorgan_nand_apint2(i117 %A, i117 %B) { 220; CHECK-LABEL: @demorgan_nand_apint2( 221; CHECK-NEXT: [[B_NOT:%.*]] = xor i117 [[B:%.*]], -1 222; CHECK-NEXT: [[NOTC:%.*]] = or i117 [[B_NOT]], [[A:%.*]] 223; CHECK-NEXT: ret i117 [[NOTC]] 224; 225 %nota = xor i117 %A, -1 226 %c = and i117 %nota, %B 227 %notc = xor i117 %c, -1 228 ret i117 %notc 229} 230 231; ~(~A | B) --> (A & ~B) 232 233define i8 @demorgan_nor(i8 %A, i8 %B) { 234; CHECK-LABEL: @demorgan_nor( 235; CHECK-NEXT: [[B_NOT:%.*]] = xor i8 [[B:%.*]], -1 236; CHECK-NEXT: [[NOTC:%.*]] = and i8 [[B_NOT]], [[A:%.*]] 237; CHECK-NEXT: ret i8 [[NOTC]] 238; 239 %notx = xor i8 %A, -1 240 %c = or i8 %notx, %B 241 %notc = xor i8 %c, -1 242 ret i8 %notc 243} 244 245; ~(~A | B) --> (A & ~B) - what if we use one of the intermediate results? 246 247define i8 @demorgan_nor_use2a(i8 %A, i8 %B) { 248; CHECK-LABEL: @demorgan_nor_use2a( 249; CHECK-NEXT: [[NOTA:%.*]] = xor i8 [[A:%.*]], -1 250; CHECK-NEXT: [[USE2A:%.*]] = mul i8 [[NOTA]], 23 251; CHECK-NEXT: [[B_NOT:%.*]] = xor i8 [[B:%.*]], -1 252; CHECK-NEXT: [[NOTC:%.*]] = and i8 [[B_NOT]], [[A]] 253; CHECK-NEXT: [[R:%.*]] = sdiv i8 [[NOTC]], [[USE2A]] 254; CHECK-NEXT: ret i8 [[R]] 255; 256 %nota = xor i8 %A, -1 257 %use2a = mul i8 %nota, 23 258 %c = or i8 %nota, %B 259 %notc = xor i8 %c, -1 260 %r = sdiv i8 %notc, %use2a 261 ret i8 %r 262} 263 264; ~(~A | B) --> (A & ~B) - what if we use one of the intermediate results? 265 266define i8 @demorgan_nor_use2b(i8 %A, i8 %B) { 267; CHECK-LABEL: @demorgan_nor_use2b( 268; CHECK-NEXT: [[USE2B:%.*]] = mul i8 [[B:%.*]], 23 269; CHECK-NEXT: [[B_NOT:%.*]] = xor i8 [[B]], -1 270; CHECK-NEXT: [[NOTC:%.*]] = and i8 [[B_NOT]], [[A:%.*]] 271; CHECK-NEXT: [[R:%.*]] = sdiv i8 [[NOTC]], [[USE2B]] 272; CHECK-NEXT: ret i8 [[R]] 273; 274 %use2b = mul i8 %B, 23 275 %nota = xor i8 %A, -1 276 %c = or i8 %nota, %B 277 %notc = xor i8 %c, -1 278 %r = sdiv i8 %notc, %use2b 279 ret i8 %r 280} 281 282; ~(~A | B) --> (A & ~B) - what if we use one of the intermediate results? 283 284define i8 @demorgan_nor_use2c(i8 %A, i8 %B) { 285; CHECK-LABEL: @demorgan_nor_use2c( 286; CHECK-NEXT: [[NOTA:%.*]] = xor i8 [[A:%.*]], -1 287; CHECK-NEXT: [[C:%.*]] = or i8 [[NOTA]], [[B:%.*]] 288; CHECK-NEXT: [[USE2C:%.*]] = mul i8 [[C]], 23 289; CHECK-NEXT: [[NOTC:%.*]] = xor i8 [[C]], -1 290; CHECK-NEXT: [[R:%.*]] = sdiv i8 [[NOTC]], [[USE2C]] 291; CHECK-NEXT: ret i8 [[R]] 292; 293 %nota = xor i8 %A, -1 294 %c = or i8 %nota, %B 295 %use2c = mul i8 %c, 23 296 %notc = xor i8 %c, -1 297 %r = sdiv i8 %notc, %use2c 298 ret i8 %r 299} 300 301; ~(~A | B) --> (A & ~B) - what if we use two of the intermediate results? 302 303define i8 @demorgan_nor_use2ab(i8 %A, i8 %B) { 304; CHECK-LABEL: @demorgan_nor_use2ab( 305; CHECK-NEXT: [[USE2B:%.*]] = mul i8 [[B:%.*]], 23 306; CHECK-NEXT: [[NOTA:%.*]] = xor i8 [[A:%.*]], -1 307; CHECK-NEXT: [[USE2A:%.*]] = mul i8 [[NOTA]], 17 308; CHECK-NEXT: [[B_NOT:%.*]] = xor i8 [[B]], -1 309; CHECK-NEXT: [[NOTC:%.*]] = and i8 [[B_NOT]], [[A]] 310; CHECK-NEXT: [[R1:%.*]] = sdiv i8 [[NOTC]], [[USE2B]] 311; CHECK-NEXT: [[R2:%.*]] = sdiv i8 [[R1]], [[USE2A]] 312; CHECK-NEXT: ret i8 [[R2]] 313; 314 %use2b = mul i8 %B, 23 315 %nota = xor i8 %A, -1 316 %use2a = mul i8 %nota, 17 317 %c = or i8 %nota, %B 318 %notc = xor i8 %c, -1 319 %r1 = sdiv i8 %notc, %use2b 320 %r2 = sdiv i8 %r1, %use2a 321 ret i8 %r2 322} 323 324; ~(~A | B) --> (A & ~B) - what if we use two of the intermediate results? 325 326define i8 @demorgan_nor_use2ac(i8 %A, i8 %B) { 327; CHECK-LABEL: @demorgan_nor_use2ac( 328; CHECK-NEXT: [[NOTA:%.*]] = xor i8 [[A:%.*]], -1 329; CHECK-NEXT: [[USE2A:%.*]] = mul i8 [[NOTA]], 17 330; CHECK-NEXT: [[C:%.*]] = or i8 [[NOTA]], [[B:%.*]] 331; CHECK-NEXT: [[USE2C:%.*]] = mul i8 [[C]], 23 332; CHECK-NEXT: [[NOTC:%.*]] = xor i8 [[C]], -1 333; CHECK-NEXT: [[R1:%.*]] = sdiv i8 [[NOTC]], [[USE2C]] 334; CHECK-NEXT: [[R2:%.*]] = sdiv i8 [[R1]], [[USE2A]] 335; CHECK-NEXT: ret i8 [[R2]] 336; 337 %nota = xor i8 %A, -1 338 %use2a = mul i8 %nota, 17 339 %c = or i8 %nota, %B 340 %use2c = mul i8 %c, 23 341 %notc = xor i8 %c, -1 342 %r1 = sdiv i8 %notc, %use2c 343 %r2 = sdiv i8 %r1, %use2a 344 ret i8 %r2 345} 346 347; ~(~A | B) --> (A & ~B) - what if we use two of the intermediate results? 348 349define i8 @demorgan_nor_use2bc(i8 %A, i8 %B) { 350; CHECK-LABEL: @demorgan_nor_use2bc( 351; CHECK-NEXT: [[USE2B:%.*]] = mul i8 [[B:%.*]], 23 352; CHECK-NEXT: [[NOTA:%.*]] = xor i8 [[A:%.*]], -1 353; CHECK-NEXT: [[C:%.*]] = or i8 [[NOTA]], [[B]] 354; CHECK-NEXT: [[USE2C:%.*]] = mul i8 [[C]], 23 355; CHECK-NEXT: [[NOTC:%.*]] = xor i8 [[C]], -1 356; CHECK-NEXT: [[R1:%.*]] = sdiv i8 [[NOTC]], [[USE2C]] 357; CHECK-NEXT: [[R2:%.*]] = sdiv i8 [[R1]], [[USE2B]] 358; CHECK-NEXT: ret i8 [[R2]] 359; 360 %use2b = mul i8 %B, 23 361 %nota = xor i8 %A, -1 362 %c = or i8 %nota, %B 363 %use2c = mul i8 %c, 23 364 %notc = xor i8 %c, -1 365 %r1 = sdiv i8 %notc, %use2c 366 %r2 = sdiv i8 %r1, %use2b 367 ret i8 %r2 368} 369 370; Do not apply DeMorgan's Law to constants. We prefer 'not' ops. 371 372define i32 @demorganize_constant1(i32 %a) { 373; CHECK-LABEL: @demorganize_constant1( 374; CHECK-NEXT: [[AND:%.*]] = and i32 [[A:%.*]], 15 375; CHECK-NEXT: [[AND1:%.*]] = xor i32 [[AND]], -1 376; CHECK-NEXT: ret i32 [[AND1]] 377; 378 %and = and i32 %a, 15 379 %and1 = xor i32 %and, -1 380 ret i32 %and1 381} 382 383; Do not apply DeMorgan's Law to constants. We prefer 'not' ops. 384 385define i32 @demorganize_constant2(i32 %a) { 386; CHECK-LABEL: @demorganize_constant2( 387; CHECK-NEXT: [[AND:%.*]] = or i32 [[A:%.*]], 15 388; CHECK-NEXT: [[AND1:%.*]] = xor i32 [[AND]], -1 389; CHECK-NEXT: ret i32 [[AND1]] 390; 391 %and = or i32 %a, 15 392 %and1 = xor i32 %and, -1 393 ret i32 %and1 394} 395 396; PR22723: Recognize DeMorgan's Laws when obfuscated by zexts. 397 398define i32 @demorgan_or_zext(i1 %X, i1 %Y) { 399; CHECK-LABEL: @demorgan_or_zext( 400; CHECK-NEXT: [[OR1_DEMORGAN:%.*]] = and i1 [[X:%.*]], [[Y:%.*]] 401; CHECK-NEXT: [[OR1:%.*]] = xor i1 [[OR1_DEMORGAN]], true 402; CHECK-NEXT: [[OR:%.*]] = zext i1 [[OR1]] to i32 403; CHECK-NEXT: ret i32 [[OR]] 404; 405 %zextX = zext i1 %X to i32 406 %zextY = zext i1 %Y to i32 407 %notX = xor i32 %zextX, 1 408 %notY = xor i32 %zextY, 1 409 %or = or i32 %notX, %notY 410 ret i32 %or 411} 412 413define i32 @demorgan_and_zext(i1 %X, i1 %Y) { 414; CHECK-LABEL: @demorgan_and_zext( 415; CHECK-NEXT: [[AND1_DEMORGAN:%.*]] = or i1 [[X:%.*]], [[Y:%.*]] 416; CHECK-NEXT: [[AND1:%.*]] = xor i1 [[AND1_DEMORGAN]], true 417; CHECK-NEXT: [[AND:%.*]] = zext i1 [[AND1]] to i32 418; CHECK-NEXT: ret i32 [[AND]] 419; 420 %zextX = zext i1 %X to i32 421 %zextY = zext i1 %Y to i32 422 %notX = xor i32 %zextX, 1 423 %notY = xor i32 %zextY, 1 424 %and = and i32 %notX, %notY 425 ret i32 %and 426} 427 428define <2 x i32> @demorgan_or_zext_vec(<2 x i1> %X, <2 x i1> %Y) { 429; CHECK-LABEL: @demorgan_or_zext_vec( 430; CHECK-NEXT: [[OR1_DEMORGAN:%.*]] = and <2 x i1> [[X:%.*]], [[Y:%.*]] 431; CHECK-NEXT: [[OR1:%.*]] = xor <2 x i1> [[OR1_DEMORGAN]], <i1 true, i1 true> 432; CHECK-NEXT: [[OR:%.*]] = zext <2 x i1> [[OR1]] to <2 x i32> 433; CHECK-NEXT: ret <2 x i32> [[OR]] 434; 435 %zextX = zext <2 x i1> %X to <2 x i32> 436 %zextY = zext <2 x i1> %Y to <2 x i32> 437 %notX = xor <2 x i32> %zextX, <i32 1, i32 1> 438 %notY = xor <2 x i32> %zextY, <i32 1, i32 1> 439 %or = or <2 x i32> %notX, %notY 440 ret <2 x i32> %or 441} 442 443define <2 x i32> @demorgan_and_zext_vec(<2 x i1> %X, <2 x i1> %Y) { 444; CHECK-LABEL: @demorgan_and_zext_vec( 445; CHECK-NEXT: [[AND1_DEMORGAN:%.*]] = or <2 x i1> [[X:%.*]], [[Y:%.*]] 446; CHECK-NEXT: [[AND1:%.*]] = xor <2 x i1> [[AND1_DEMORGAN]], <i1 true, i1 true> 447; CHECK-NEXT: [[AND:%.*]] = zext <2 x i1> [[AND1]] to <2 x i32> 448; CHECK-NEXT: ret <2 x i32> [[AND]] 449; 450 %zextX = zext <2 x i1> %X to <2 x i32> 451 %zextY = zext <2 x i1> %Y to <2 x i32> 452 %notX = xor <2 x i32> %zextX, <i32 1, i32 1> 453 %notY = xor <2 x i32> %zextY, <i32 1, i32 1> 454 %and = and <2 x i32> %notX, %notY 455 ret <2 x i32> %and 456} 457 458define i32 @PR28476(i32 %x, i32 %y) { 459; CHECK-LABEL: @PR28476( 460; CHECK-NEXT: [[CMP0:%.*]] = icmp eq i32 [[X:%.*]], 0 461; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[Y:%.*]], 0 462; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[CMP0]], [[CMP1]] 463; CHECK-NEXT: [[COND:%.*]] = zext i1 [[TMP1]] to i32 464; CHECK-NEXT: ret i32 [[COND]] 465; 466 %cmp0 = icmp ne i32 %x, 0 467 %cmp1 = icmp ne i32 %y, 0 468 %and = and i1 %cmp0, %cmp1 469 %zext = zext i1 %and to i32 470 %cond = xor i32 %zext, 1 471 ret i32 %cond 472} 473 474define i32 @PR28476_logical(i32 %x, i32 %y) { 475; CHECK-LABEL: @PR28476_logical( 476; CHECK-NEXT: [[CMP0:%.*]] = icmp eq i32 [[X:%.*]], 0 477; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[Y:%.*]], 0 478; CHECK-NEXT: [[AND:%.*]] = select i1 [[CMP0]], i1 true, i1 [[CMP1]] 479; CHECK-NEXT: [[COND:%.*]] = zext i1 [[AND]] to i32 480; CHECK-NEXT: ret i32 [[COND]] 481; 482 %cmp0 = icmp ne i32 %x, 0 483 %cmp1 = icmp ne i32 %y, 0 484 %and = select i1 %cmp0, i1 %cmp1, i1 false 485 %zext = zext i1 %and to i32 486 %cond = xor i32 %zext, 1 487 ret i32 %cond 488} 489 490; ~(~(a | b) | (a & b)) --> (a | b) & ~(a & b) -> a ^ b 491 492define i32 @demorgan_plus_and_to_xor(i32 %a, i32 %b) { 493; CHECK-LABEL: @demorgan_plus_and_to_xor( 494; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[B:%.*]], [[A:%.*]] 495; CHECK-NEXT: ret i32 [[TMP1]] 496; 497 %or = or i32 %b, %a 498 %notor = xor i32 %or, -1 499 %and = and i32 %b, %a 500 %or2 = or i32 %and, %notor 501 %not = xor i32 %or2, -1 502 ret i32 %not 503} 504 505define <4 x i32> @demorgan_plus_and_to_xor_vec(<4 x i32> %a, <4 x i32> %b) { 506; CHECK-LABEL: @demorgan_plus_and_to_xor_vec( 507; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i32> [[A:%.*]], [[B:%.*]] 508; CHECK-NEXT: ret <4 x i32> [[TMP1]] 509; 510 %or = or <4 x i32> %a, %b 511 %notor = xor <4 x i32> %or, < i32 -1, i32 -1, i32 -1, i32 -1 > 512 %and = and <4 x i32> %a, %b 513 %or2 = or <4 x i32> %and, %notor 514 %not = xor <4 x i32> %or2, < i32 -1, i32 -1, i32 -1, i32 -1 > 515 ret <4 x i32> %not 516} 517 518; (a ^ b) | ~(a | b) --> ~(a & b) 519 520define i32 @PR45984(i32 %0, i32 %1) { 521; CHECK-LABEL: @PR45984( 522; CHECK-NEXT: [[TMP3:%.*]] = and i32 [[TMP1:%.*]], [[TMP0:%.*]] 523; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP3]], -1 524; CHECK-NEXT: ret i32 [[TMP4]] 525; 526 %3 = xor i32 %1, %0 527 %4 = or i32 %1, %0 528 %5 = xor i32 %4, -1 529 %6 = or i32 %3, %5 530 ret i32 %6 531} 532