From 07255f2be8a791c8d8982400b41cb36a5594bd6d Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sun, 30 Apr 2017 18:57:12 +0000 Subject: [PATCH] [InstCombine] consolidate tests for DeMorgan folds; NFC I'm proposing to add tests and change behavior in D32665. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301774 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Transforms/InstCombine/and-or-not.ll | 28 -- test/Transforms/InstCombine/and-or.ll | 22 -- test/Transforms/InstCombine/apint-and1.ll | 8 - test/Transforms/InstCombine/apint-and2.ll | 32 -- test/Transforms/InstCombine/apint-not.ll | 25 -- test/Transforms/InstCombine/apint-or.ll | 23 -- test/Transforms/InstCombine/demorgan-zext.ll | 81 ----- test/Transforms/InstCombine/demorgan.ll | 320 +++++++++++++++++++ test/Transforms/InstCombine/not.ll | 39 +-- 9 files changed, 321 insertions(+), 257 deletions(-) delete mode 100644 test/Transforms/InstCombine/demorgan-zext.ll create mode 100644 test/Transforms/InstCombine/demorgan.ll diff --git a/test/Transforms/InstCombine/and-or-not.ll b/test/Transforms/InstCombine/and-or-not.ll index 4015b340cae..a8e32bd77f7 100644 --- a/test/Transforms/InstCombine/and-or-not.ll +++ b/test/Transforms/InstCombine/and-or-not.ll @@ -496,34 +496,6 @@ define i32 @xor_to_xor12(float %fa, float %fb) { ret i32 %xor } -; ~(~(a | b) | (a & b)) --> (a | b) & ~(a & b) -> a ^ b - -define i32 @demorgan_plus_and_to_xor(i32 %a, i32 %b) { -; CHECK-LABEL: @demorgan_plus_and_to_xor( -; CHECK-NEXT: [[NOT:%.*]] = xor i32 %b, %a -; CHECK-NEXT: ret i32 [[NOT]] -; - %or = or i32 %b, %a - %notor = xor i32 %or, -1 - %and = and i32 %b, %a - %or2 = or i32 %and, %notor - %not = xor i32 %or2, -1 - ret i32 %not -} - -define <4 x i32> @demorgan_plus_and_to_xor_vec(<4 x i32> %a, <4 x i32> %b) { -; CHECK-LABEL: @demorgan_plus_and_to_xor_vec( -; CHECK-NEXT: [[NOT:%.*]] = xor <4 x i32> %a, %b -; CHECK-NEXT: ret <4 x i32> [[NOT]] -; - %or = or <4 x i32> %a, %b - %notor = xor <4 x i32> %or, < i32 -1, i32 -1, i32 -1, i32 -1 > - %and = and <4 x i32> %a, %b - %or2 = or <4 x i32> %and, %notor - %not = xor <4 x i32> %or2, < i32 -1, i32 -1, i32 -1, i32 -1 > - ret <4 x i32> %not -} - ; https://bugs.llvm.org/show_bug.cgi?id=32830 ; Make sure we're matching operands correctly and not folding things wrongly. diff --git a/test/Transforms/InstCombine/and-or.ll b/test/Transforms/InstCombine/and-or.ll index ce8c7664744..2ad90ad98e7 100644 --- a/test/Transforms/InstCombine/and-or.ll +++ b/test/Transforms/InstCombine/and-or.ll @@ -53,25 +53,3 @@ define i32 @func4(i32 %a, i32 %b) { ret i32 %tmp3 } -define i32 @demorganize_constant1(i32 %a) { -; CHECK-LABEL: @demorganize_constant1( -; CHECK-NEXT: [[A_NOT:%.*]] = or i32 %a, -16 -; CHECK-NEXT: [[AND1:%.*]] = xor i32 [[A_NOT]], 15 -; CHECK-NEXT: ret i32 [[AND1]] -; - %and = and i32 %a, 15 - %and1 = xor i32 %and, -1 - ret i32 %and1 -} - -define i32 @demorganize_constant2(i32 %a) { -; CHECK-LABEL: @demorganize_constant2( -; CHECK-NEXT: [[A_NOT:%.*]] = and i32 %a, -16 -; CHECK-NEXT: [[AND1:%.*]] = xor i32 [[A_NOT]], -16 -; CHECK-NEXT: ret i32 [[AND1]] -; - %and = or i32 %a, 15 - %and1 = xor i32 %and, -1 - ret i32 %and1 -} - diff --git a/test/Transforms/InstCombine/apint-and1.ll b/test/Transforms/InstCombine/apint-and1.ll index fcd2dcd23ad..495e687ae4c 100644 --- a/test/Transforms/InstCombine/apint-and1.ll +++ b/test/Transforms/InstCombine/apint-and1.ll @@ -9,14 +9,6 @@ define i39 @test0(i39 %A) { ret i39 %B } -define i47 @test1(i47 %A, i47 %B) { - ;; (~A & ~B) == (~(A | B)) - De Morgan's Law - %NotA = xor i47 %A, -1 - %NotB = xor i47 %B, -1 - %C1 = and i47 %NotA, %NotB - ret i47 %C1 -} - define i15 @test2(i15 %x) { %tmp.2 = and i15 %x, -1 ; noop ret i15 %tmp.2 diff --git a/test/Transforms/InstCombine/apint-and2.ll b/test/Transforms/InstCombine/apint-and2.ll index 78dc8f990d0..427c9e63d7c 100644 --- a/test/Transforms/InstCombine/apint-and2.ll +++ b/test/Transforms/InstCombine/apint-and2.ll @@ -10,38 +10,6 @@ define i999 @test0(i999 %A) { ret i999 %B } -define i477 @test1(i477 %A, i477 %B) { - ;; (~A & ~B) == (~(A | B)) - De Morgan's Law - %NotA = xor i477 %A, -1 - %NotB = xor i477 %B, -1 - %C1 = and i477 %NotA, %NotB - ret i477 %C1 -} - -define i129 @tst(i129 %A, i129 %B) { - ;; (~A & ~B) == (~(A | B)) - De Morgan's Law - %NotA = xor i129 %A, -1 - %NotB = xor i129 %B, -1 - %C1 = and i129 %NotA, %NotB - ret i129 %C1 -} - -define i65 @test(i65 %A, i65 %B) { - ;; (~A & ~B) == (~(A | B)) - De Morgan's Law - %NotA = xor i65 %A, -1 - %NotB = xor i65 -1, %B - %C1 = and i65 %NotA, %NotB - ret i65 %C1 -} - -define i66 @tes(i66 %A, i66 %B) { - ;; (~A & ~B) == (~(A | B)) - De Morgan's Law - %NotA = xor i66 %A, -1 - %NotB = xor i66 %B, -1 - %C1 = and i66 %NotA, %NotB - ret i66 %C1 -} - define i1005 @test2(i1005 %x) { %tmp.2 = and i1005 %x, -1 ; noop ret i1005 %tmp.2 diff --git a/test/Transforms/InstCombine/apint-not.ll b/test/Transforms/InstCombine/apint-not.ll index 488b7f2c98e..c5b12fd5dee 100644 --- a/test/Transforms/InstCombine/apint-not.ll +++ b/test/Transforms/InstCombine/apint-not.ll @@ -15,28 +15,3 @@ define i1 @test2(i52 %A, i52 %B) { ret i1 %Ret } -; Test that demorgans law can be instcombined -define i47 @test3(i47 %A, i47 %B) { - %a = xor i47 %A, -1 - %b = xor i47 %B, -1 - %c = and i47 %a, %b - %d = xor i47 %c, -1 - ret i47 %d -} - -; Test that demorgens law can work with constants -define i61 @test4(i61 %A, i61 %B) { - %a = xor i61 %A, -1 - %c = and i61 %a, 5 ; 5 = ~c2 - %d = xor i61 %c, -1 - ret i61 %d -} - -; test the mirror of demorgans law... -define i71 @test5(i71 %A, i71 %B) { - %a = xor i71 %A, -1 - %b = xor i71 %B, -1 - %c = or i71 %a, %b - %d = xor i71 %c, -1 - ret i71 %d -} diff --git a/test/Transforms/InstCombine/apint-or.ll b/test/Transforms/InstCombine/apint-or.ll index e2312b61f2b..33304bf8ad6 100644 --- a/test/Transforms/InstCombine/apint-or.ll +++ b/test/Transforms/InstCombine/apint-or.ll @@ -27,18 +27,6 @@ define i39 @test2(i39 %V, i39 %M) { ; CHECK-NEXT: ret i39 %A } -define i43 @test3(i43 %A, i43 %B) { - ;; (~A | ~B) == (~(A & B)) - De Morgan's Law - %NotA = xor i43 %A, -1 - %NotB = xor i43 %B, -1 - %C1 = or i43 %NotA, %NotB - ret i43 %C1 -; CHECK-LABEL: @test3 -; CHECK-NEXT: %C1.demorgan = and i43 %A, %B -; CHECK-NEXT: %C1 = xor i43 %C1.demorgan, -1 -; CHECK-NEXT: ret i43 %C1 -} - ; These tests are for Integer BitWidth > 64 && BitWidth <= 1024. define i1023 @test4(i1023 %A) { ;; A | ~A == -1 @@ -66,14 +54,3 @@ define i399 @test5(i399 %V, i399 %M) { ; CHECK-NEXT: ret i399 %A } -define i129 @test6(i129 %A, i129 %B) { - ;; (~A | ~B) == (~(A & B)) - De Morgan's Law - %NotA = xor i129 %A, -1 - %NotB = xor i129 %B, -1 - %C1 = or i129 %NotA, %NotB - ret i129 %C1 -; CHECK-LABEL: @test6 -; CHECK-NEXT: %C1.demorgan = and i129 %A, %B -; CHECK-NEXT: %C1 = xor i129 %C1.demorgan, -1 -; CHECK-NEXT: ret i129 %C1 -} diff --git a/test/Transforms/InstCombine/demorgan-zext.ll b/test/Transforms/InstCombine/demorgan-zext.ll deleted file mode 100644 index d537730ba9a..00000000000 --- a/test/Transforms/InstCombine/demorgan-zext.ll +++ /dev/null @@ -1,81 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -instcombine -S | FileCheck %s - -; PR22723: Recognize De Morgan's Laws when obfuscated by zexts. - -define i32 @demorgan_or(i1 %X, i1 %Y) { -; CHECK-LABEL: @demorgan_or( -; CHECK-NEXT: [[OR1_DEMORGAN:%.*]] = and i1 %X, %Y -; CHECK-NEXT: [[OR1:%.*]] = xor i1 [[OR1_DEMORGAN]], true -; CHECK-NEXT: [[OR:%.*]] = zext i1 [[OR:%.*]]1 to i32 -; CHECK-NEXT: ret i32 [[OR]] -; - %zextX = zext i1 %X to i32 - %zextY = zext i1 %Y to i32 - %notX = xor i32 %zextX, 1 - %notY = xor i32 %zextY, 1 - %or = or i32 %notX, %notY - ret i32 %or -} - -define i32 @demorgan_and(i1 %X, i1 %Y) { -; CHECK-LABEL: @demorgan_and( -; CHECK-NEXT: [[AND1_DEMORGAN:%.*]] = or i1 %X, %Y -; CHECK-NEXT: [[AND1:%.*]] = xor i1 [[AND1_DEMORGAN]], true -; CHECK-NEXT: [[AND:%.*]] = zext i1 [[AND:%.*]]1 to i32 -; CHECK-NEXT: ret i32 [[AND]] -; - %zextX = zext i1 %X to i32 - %zextY = zext i1 %Y to i32 - %notX = xor i32 %zextX, 1 - %notY = xor i32 %zextY, 1 - %and = and i32 %notX, %notY - ret i32 %and -} - -define <2 x i32> @demorgan_or_vec(<2 x i1> %X, <2 x i1> %Y) { -; CHECK-LABEL: @demorgan_or_vec( -; CHECK-NEXT: [[OR1_DEMORGAN:%.*]] = and <2 x i1> %X, %Y -; CHECK-NEXT: [[OR1:%.*]] = xor <2 x i1> [[OR1_DEMORGAN]], -; CHECK-NEXT: [[OR:%.*]] = zext <2 x i1> [[OR:%.*]]1 to <2 x i32> -; CHECK-NEXT: ret <2 x i32> [[OR]] -; - %zextX = zext <2 x i1> %X to <2 x i32> - %zextY = zext <2 x i1> %Y to <2 x i32> - %notX = xor <2 x i32> %zextX, - %notY = xor <2 x i32> %zextY, - %or = or <2 x i32> %notX, %notY - ret <2 x i32> %or -} - -define <2 x i32> @demorgan_and_vec(<2 x i1> %X, <2 x i1> %Y) { -; CHECK-LABEL: @demorgan_and_vec( -; CHECK-NEXT: [[AND1_DEMORGAN:%.*]] = or <2 x i1> %X, %Y -; CHECK-NEXT: [[AND1:%.*]] = xor <2 x i1> [[AND1_DEMORGAN]], -; CHECK-NEXT: [[AND:%.*]] = zext <2 x i1> [[AND:%.*]]1 to <2 x i32> -; CHECK-NEXT: ret <2 x i32> [[AND]] -; - %zextX = zext <2 x i1> %X to <2 x i32> - %zextY = zext <2 x i1> %Y to <2 x i32> - %notX = xor <2 x i32> %zextX, - %notY = xor <2 x i32> %zextY, - %and = and <2 x i32> %notX, %notY - ret <2 x i32> %and -} - -define i32 @PR28476(i32 %x, i32 %y) { -; CHECK-LABEL: @PR28476( -; CHECK-NEXT: [[NOTLHS:%.*]] = icmp eq i32 %x, 0 -; CHECK-NEXT: [[NOTRHS:%.*]] = icmp eq i32 %y, 0 -; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[NOTRHS]], [[NOTLHS]] -; CHECK-NEXT: [[COND:%.*]] = zext i1 [[TMP1]] to i32 -; CHECK-NEXT: ret i32 [[COND]] -; - %cmp0 = icmp ne i32 %x, 0 - %cmp1 = icmp ne i32 %y, 0 - %and = and i1 %cmp0, %cmp1 - %zext = zext i1 %and to i32 - %cond = xor i32 %zext, 1 - ret i32 %cond -} - diff --git a/test/Transforms/InstCombine/demorgan.ll b/test/Transforms/InstCombine/demorgan.ll new file mode 100644 index 00000000000..30413ce521f --- /dev/null +++ b/test/Transforms/InstCombine/demorgan.ll @@ -0,0 +1,320 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +; (~A | ~B) == ~(A & B) + +define i43 @demorgan_or_apint1(i43 %A, i43 %B) { +; CHECK-LABEL: @demorgan_or_apint1( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = and i43 %A, %B +; CHECK-NEXT: [[C:%.*]] = xor i43 [[C_DEMORGAN]], -1 +; CHECK-NEXT: ret i43 [[C]] +; + %NotA = xor i43 %A, -1 + %NotB = xor i43 %B, -1 + %C = or i43 %NotA, %NotB + ret i43 %C +} + +; (~A | ~B) == ~(A & B) + +define i129 @demorgan_or_apint2(i129 %A, i129 %B) { +; CHECK-LABEL: @demorgan_or_apint2( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = and i129 %A, %B +; CHECK-NEXT: [[C:%.*]] = xor i129 [[C_DEMORGAN]], -1 +; CHECK-NEXT: ret i129 [[C]] +; + %NotA = xor i129 %A, -1 + %NotB = xor i129 %B, -1 + %C = or i129 %NotA, %NotB + ret i129 %C +} + +; (~A & ~B) == ~(A | B) + +define i477 @demorgan_and_apint1(i477 %A, i477 %B) { +; CHECK-LABEL: @demorgan_and_apint1( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i477 %A, %B +; CHECK-NEXT: [[C:%.*]] = xor i477 [[C_DEMORGAN]], -1 +; CHECK-NEXT: ret i477 [[C]] +; + %NotA = xor i477 %A, -1 + %NotB = xor i477 %B, -1 + %C = and i477 %NotA, %NotB + ret i477 %C +} + +; (~A & ~B) == ~(A | B) + +define i129 @demorgan_and_apint2(i129 %A, i129 %B) { +; CHECK-LABEL: @demorgan_and_apint2( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i129 %A, %B +; CHECK-NEXT: [[C:%.*]] = xor i129 [[C_DEMORGAN]], -1 +; CHECK-NEXT: ret i129 [[C]] +; + %NotA = xor i129 %A, -1 + %NotB = xor i129 %B, -1 + %C = and i129 %NotA, %NotB + ret i129 %C +} + +; (~A & ~B) == ~(A | B) + +define i65 @demorgan_and_apint3(i65 %A, i65 %B) { +; CHECK-LABEL: @demorgan_and_apint3( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i65 %A, %B +; CHECK-NEXT: [[C:%.*]] = xor i65 [[C_DEMORGAN]], -1 +; CHECK-NEXT: ret i65 [[C]] +; + %NotA = xor i65 %A, -1 + %NotB = xor i65 -1, %B + %C = and i65 %NotA, %NotB + ret i65 %C +} + +; (~A & ~B) == ~(A | B) + +define i66 @demorgan_and_apint4(i66 %A, i66 %B) { +; CHECK-LABEL: @demorgan_and_apint4( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i66 %A, %B +; CHECK-NEXT: [[C:%.*]] = xor i66 [[C_DEMORGAN]], -1 +; CHECK-NEXT: ret i66 [[C]] +; + %NotA = xor i66 %A, -1 + %NotB = xor i66 %B, -1 + %C = and i66 %NotA, %NotB + ret i66 %C +} + +; (~A & ~B) == ~(A | B) + +define i47 @demorgan_and_apint5(i47 %A, i47 %B) { +; CHECK-LABEL: @demorgan_and_apint5( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i47 %A, %B +; CHECK-NEXT: [[C:%.*]] = xor i47 [[C_DEMORGAN]], -1 +; CHECK-NEXT: ret i47 [[C]] +; + %NotA = xor i47 %A, -1 + %NotB = xor i47 %B, -1 + %C = and i47 %NotA, %NotB + ret i47 %C +} + +; This is confirming that 2 transforms work together: +; ~(~A & ~B) --> A | B + +define i32 @test3(i32 %A, i32 %B) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i32 %A, %B +; CHECK-NEXT: ret i32 [[C_DEMORGAN]] +; + %nota = xor i32 %A, -1 + %notb = xor i32 %B, -1 + %c = and i32 %nota, %notb + %notc = xor i32 %c, -1 + ret i32 %notc +} + +; Invert a constant if needed: +; ~(~A & 5) --> A | ~5 + +define i32 @test4(i32 %A) { +; CHECK-LABEL: @test4( +; CHECK-NEXT: [[NOTC1:%.*]] = or i32 %A, -6 +; CHECK-NEXT: ret i32 [[NOTC1]] +; + %nota = xor i32 %A, -1 + %c = and i32 %nota, 5 + %notc = xor i32 %c, -1 + ret i32 %notc +} + +; Test the mirror of DeMorgan's law with an extra 'not'. +; ~(~A | ~B) --> A & B + +define i32 @test5(i32 %A, i32 %B) { +; CHECK-LABEL: @test5( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = and i32 %A, %B +; CHECK-NEXT: ret i32 [[C_DEMORGAN]] +; + %nota = xor i32 %A, -1 + %notb = xor i32 %B, -1 + %c = or i32 %nota, %notb + %notc = xor i32 %c, -1 + ret i32 %notc +} + +; Repeat with weird types for extra coverage. +; ~(~A & ~B) --> A | B + +define i47 @test3_apint(i47 %A, i47 %B) { +; CHECK-LABEL: @test3_apint( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i47 %A, %B +; CHECK-NEXT: ret i47 [[C_DEMORGAN]] +; + %nota = xor i47 %A, -1 + %notb = xor i47 %B, -1 + %c = and i47 %nota, %notb + %notc = xor i47 %c, -1 + ret i47 %notc +} + +; ~(~A & 5) --> A | ~5 + +define i61 @test4_apint(i61 %A) { +; CHECK-LABEL: @test4_apint( +; CHECK-NEXT: [[NOTA:%.*]] = and i61 %A, 5 +; CHECK-NEXT: [[C:%.*]] = xor i61 [[NOTA]], 5 +; CHECK-NEXT: ret i61 [[C]] +; + %nota = xor i61 %A, -1 + %c = and i61 %nota, 5 ; 5 = ~c2 + %notc = xor i61 %c, -1 + ret i61 %c +} + +; ~(~A | ~B) --> A & B + +define i71 @test5_apint(i71 %A, i71 %B) { +; CHECK-LABEL: @test5_apint( +; CHECK-NEXT: [[C_DEMORGAN:%.*]] = and i71 %A, %B +; CHECK-NEXT: ret i71 [[C_DEMORGAN]] +; + %nota = xor i71 %A, -1 + %notb = xor i71 %B, -1 + %c = or i71 %nota, %notb + %notc = xor i71 %c, -1 + ret i71 %notc +} + +; FIXME: Do not apply DeMorgan's Law to constants. We prefer 'not' ops. + +define i32 @demorganize_constant1(i32 %a) { +; CHECK-LABEL: @demorganize_constant1( +; CHECK-NEXT: [[A_NOT:%.*]] = or i32 %a, -16 +; CHECK-NEXT: [[AND1:%.*]] = xor i32 [[A_NOT]], 15 +; CHECK-NEXT: ret i32 [[AND1]] +; + %and = and i32 %a, 15 + %and1 = xor i32 %and, -1 + ret i32 %and1 +} + +; FIXME: Do not apply DeMorgan's Law to constants. We prefer 'not' ops. + +define i32 @demorganize_constant2(i32 %a) { +; CHECK-LABEL: @demorganize_constant2( +; CHECK-NEXT: [[A_NOT:%.*]] = and i32 %a, -16 +; CHECK-NEXT: [[AND1:%.*]] = xor i32 [[A_NOT]], -16 +; CHECK-NEXT: ret i32 [[AND1]] +; + %and = or i32 %a, 15 + %and1 = xor i32 %and, -1 + ret i32 %and1 +} + +; PR22723: Recognize DeMorgan's Laws when obfuscated by zexts. + +define i32 @demorgan_or_zext(i1 %X, i1 %Y) { +; CHECK-LABEL: @demorgan_or_zext( +; CHECK-NEXT: [[OR1_DEMORGAN:%.*]] = and i1 %X, %Y +; CHECK-NEXT: [[OR1:%.*]] = xor i1 [[OR1_DEMORGAN]], true +; CHECK-NEXT: [[OR:%.*]] = zext i1 [[OR:%.*]]1 to i32 +; CHECK-NEXT: ret i32 [[OR]] +; + %zextX = zext i1 %X to i32 + %zextY = zext i1 %Y to i32 + %notX = xor i32 %zextX, 1 + %notY = xor i32 %zextY, 1 + %or = or i32 %notX, %notY + ret i32 %or +} + +define i32 @demorgan_and_zext(i1 %X, i1 %Y) { +; CHECK-LABEL: @demorgan_and_zext( +; CHECK-NEXT: [[AND1_DEMORGAN:%.*]] = or i1 %X, %Y +; CHECK-NEXT: [[AND1:%.*]] = xor i1 [[AND1_DEMORGAN]], true +; CHECK-NEXT: [[AND:%.*]] = zext i1 [[AND:%.*]]1 to i32 +; CHECK-NEXT: ret i32 [[AND]] +; + %zextX = zext i1 %X to i32 + %zextY = zext i1 %Y to i32 + %notX = xor i32 %zextX, 1 + %notY = xor i32 %zextY, 1 + %and = and i32 %notX, %notY + ret i32 %and +} + +define <2 x i32> @demorgan_or_zext_vec(<2 x i1> %X, <2 x i1> %Y) { +; CHECK-LABEL: @demorgan_or_zext_vec( +; CHECK-NEXT: [[OR1_DEMORGAN:%.*]] = and <2 x i1> %X, %Y +; CHECK-NEXT: [[OR1:%.*]] = xor <2 x i1> [[OR1_DEMORGAN]], +; CHECK-NEXT: [[OR:%.*]] = zext <2 x i1> [[OR:%.*]]1 to <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[OR]] +; + %zextX = zext <2 x i1> %X to <2 x i32> + %zextY = zext <2 x i1> %Y to <2 x i32> + %notX = xor <2 x i32> %zextX, + %notY = xor <2 x i32> %zextY, + %or = or <2 x i32> %notX, %notY + ret <2 x i32> %or +} + +define <2 x i32> @demorgan_and_zext_vec(<2 x i1> %X, <2 x i1> %Y) { +; CHECK-LABEL: @demorgan_and_zext_vec( +; CHECK-NEXT: [[AND1_DEMORGAN:%.*]] = or <2 x i1> %X, %Y +; CHECK-NEXT: [[AND1:%.*]] = xor <2 x i1> [[AND1_DEMORGAN]], +; CHECK-NEXT: [[AND:%.*]] = zext <2 x i1> [[AND:%.*]]1 to <2 x i32> +; CHECK-NEXT: ret <2 x i32> [[AND]] +; + %zextX = zext <2 x i1> %X to <2 x i32> + %zextY = zext <2 x i1> %Y to <2 x i32> + %notX = xor <2 x i32> %zextX, + %notY = xor <2 x i32> %zextY, + %and = and <2 x i32> %notX, %notY + ret <2 x i32> %and +} + +define i32 @PR28476(i32 %x, i32 %y) { +; CHECK-LABEL: @PR28476( +; CHECK-NEXT: [[CMP0:%.*]] = icmp eq i32 %x, 0 +; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 %y, 0 +; CHECK-NEXT: [[TMP1:%.*]] = or i1 [[CMP1]], [[CMP0]] +; CHECK-NEXT: [[COND:%.*]] = zext i1 [[TMP1]] to i32 +; CHECK-NEXT: ret i32 [[COND]] +; + %cmp0 = icmp ne i32 %x, 0 + %cmp1 = icmp ne i32 %y, 0 + %and = and i1 %cmp0, %cmp1 + %zext = zext i1 %and to i32 + %cond = xor i32 %zext, 1 + ret i32 %cond +} + +; ~(~(a | b) | (a & b)) --> (a | b) & ~(a & b) -> a ^ b + +define i32 @demorgan_plus_and_to_xor(i32 %a, i32 %b) { +; CHECK-LABEL: @demorgan_plus_and_to_xor( +; CHECK-NEXT: [[NOT:%.*]] = xor i32 %b, %a +; CHECK-NEXT: ret i32 [[NOT]] +; + %or = or i32 %b, %a + %notor = xor i32 %or, -1 + %and = and i32 %b, %a + %or2 = or i32 %and, %notor + %not = xor i32 %or2, -1 + ret i32 %not +} + +define <4 x i32> @demorgan_plus_and_to_xor_vec(<4 x i32> %a, <4 x i32> %b) { +; CHECK-LABEL: @demorgan_plus_and_to_xor_vec( +; CHECK-NEXT: [[NOT:%.*]] = xor <4 x i32> %a, %b +; CHECK-NEXT: ret <4 x i32> [[NOT]] +; + %or = or <4 x i32> %a, %b + %notor = xor <4 x i32> %or, < i32 -1, i32 -1, i32 -1, i32 -1 > + %and = and <4 x i32> %a, %b + %or2 = or <4 x i32> %and, %notor + %not = xor <4 x i32> %or2, < i32 -1, i32 -1, i32 -1, i32 -1 > + ret <4 x i32> %not +} + diff --git a/test/Transforms/InstCombine/not.ll b/test/Transforms/InstCombine/not.ll index d0c242f6555..2760d4ae044 100644 --- a/test/Transforms/InstCombine/not.ll +++ b/test/Transforms/InstCombine/not.ll @@ -31,45 +31,8 @@ define i1 @invert_fcmp(float %X, float %Y) { ret i1 %not } -; Test that De Morgan's law can be instcombined. -define i32 @test3(i32 %A, i32 %B) { -; CHECK-LABEL: @test3( -; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i32 %A, %B -; CHECK-NEXT: ret i32 [[C_DEMORGAN]] -; - %a = xor i32 %A, -1 - %b = xor i32 %B, -1 - %c = and i32 %a, %b - %d = xor i32 %c, -1 - ret i32 %d -} - -; Test that De Morgan's law can work with constants. -define i32 @test4(i32 %A, i32 %B) { -; CHECK-LABEL: @test4( -; CHECK-NEXT: [[D1:%.*]] = or i32 %A, -6 -; CHECK-NEXT: ret i32 [[D1]] -; - %a = xor i32 %A, -1 - %c = and i32 %a, 5 - %d = xor i32 %c, -1 - ret i32 %d -} - -; Test the mirror of De Morgan's law. -define i32 @test5(i32 %A, i32 %B) { -; CHECK-LABEL: @test5( -; CHECK-NEXT: [[C_DEMORGAN:%.*]] = and i32 %A, %B -; CHECK-NEXT: ret i32 [[C_DEMORGAN]] -; - %a = xor i32 %A, -1 - %b = xor i32 %B, -1 - %c = or i32 %a, %b - %d = xor i32 %c, -1 - ret i32 %d -} - ; PR2298 + define zeroext i8 @test6(i32 %a, i32 %b) { ; CHECK-LABEL: @test6( ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 %b, %a -- 2.50.1