[llvm] r301774 - [InstCombine] consolidate tests for DeMorgan folds; NFC

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 30 11:57:13 PDT 2017


Author: spatel
Date: Sun Apr 30 13:57:12 2017
New Revision: 301774

URL: http://llvm.org/viewvc/llvm-project?rev=301774&view=rev
Log:
[InstCombine] consolidate tests for DeMorgan folds; NFC

I'm proposing to add tests and change behavior in D32665.

Added:
    llvm/trunk/test/Transforms/InstCombine/demorgan.ll
      - copied, changed from r301773, llvm/trunk/test/Transforms/InstCombine/demorgan-zext.ll
Removed:
    llvm/trunk/test/Transforms/InstCombine/demorgan-zext.ll
Modified:
    llvm/trunk/test/Transforms/InstCombine/and-or-not.ll
    llvm/trunk/test/Transforms/InstCombine/and-or.ll
    llvm/trunk/test/Transforms/InstCombine/apint-and1.ll
    llvm/trunk/test/Transforms/InstCombine/apint-and2.ll
    llvm/trunk/test/Transforms/InstCombine/apint-not.ll
    llvm/trunk/test/Transforms/InstCombine/apint-or.ll
    llvm/trunk/test/Transforms/InstCombine/not.ll

Modified: llvm/trunk/test/Transforms/InstCombine/and-or-not.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/and-or-not.ll?rev=301774&r1=301773&r2=301774&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/and-or-not.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/and-or-not.ll Sun Apr 30 13:57:12 2017
@@ -496,34 +496,6 @@ define i32 @xor_to_xor12(float %fa, floa
   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.
 

Modified: llvm/trunk/test/Transforms/InstCombine/and-or.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/and-or.ll?rev=301774&r1=301773&r2=301774&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/and-or.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/and-or.ll Sun Apr 30 13:57:12 2017
@@ -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
-}
-

Modified: llvm/trunk/test/Transforms/InstCombine/apint-and1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/apint-and1.ll?rev=301774&r1=301773&r2=301774&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/apint-and1.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/apint-and1.ll Sun Apr 30 13:57:12 2017
@@ -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

Modified: llvm/trunk/test/Transforms/InstCombine/apint-and2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/apint-and2.ll?rev=301774&r1=301773&r2=301774&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/apint-and2.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/apint-and2.ll Sun Apr 30 13:57:12 2017
@@ -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

Modified: llvm/trunk/test/Transforms/InstCombine/apint-not.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/apint-not.ll?rev=301774&r1=301773&r2=301774&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/apint-not.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/apint-not.ll Sun Apr 30 13:57:12 2017
@@ -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
-}

Modified: llvm/trunk/test/Transforms/InstCombine/apint-or.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/apint-or.ll?rev=301774&r1=301773&r2=301774&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/apint-or.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/apint-or.ll Sun Apr 30 13:57:12 2017
@@ -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
-}

Removed: llvm/trunk/test/Transforms/InstCombine/demorgan-zext.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/demorgan-zext.ll?rev=301773&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/demorgan-zext.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/demorgan-zext.ll (removed)
@@ -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]], <i1 true, i1 true>
-; 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, <i32 1, i32 1>
-  %notY  = xor <2 x i32> %zextY, <i32 1, i32 1>
-  %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]], <i1 true, i1 true>
-; 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, <i32 1, i32 1>
-  %notY  = xor <2 x i32> %zextY, <i32 1, i32 1>
-  %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
-}
-

Copied: llvm/trunk/test/Transforms/InstCombine/demorgan.ll (from r301773, llvm/trunk/test/Transforms/InstCombine/demorgan-zext.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/demorgan.ll?p2=llvm/trunk/test/Transforms/InstCombine/demorgan.ll&p1=llvm/trunk/test/Transforms/InstCombine/demorgan-zext.ll&r1=301773&r2=301774&rev=301774&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/demorgan-zext.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/demorgan.ll Sun Apr 30 13:57:12 2017
@@ -1,10 +1,221 @@
 ; 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.
+; (~A | ~B) == ~(A & B)
 
-define i32 @demorgan_or(i1 %X, i1 %Y) {
-; CHECK-LABEL: @demorgan_or(
+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
@@ -18,8 +229,8 @@ define i32 @demorgan_or(i1 %X, i1 %Y) {
   ret i32 %or
 }
 
-define i32 @demorgan_and(i1 %X, i1 %Y) {
-; CHECK-LABEL: @demorgan_and(
+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
@@ -33,8 +244,8 @@ define i32 @demorgan_and(i1 %X, i1 %Y) {
   ret i32 %and
 }
 
-define <2 x i32> @demorgan_or_vec(<2 x i1> %X, <2 x i1> %Y) {
-; CHECK-LABEL: @demorgan_or_vec(
+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]], <i1 true, i1 true>
 ; CHECK-NEXT:    [[OR:%.*]] = zext <2 x i1> [[OR:%.*]]1 to <2 x i32>
@@ -48,8 +259,8 @@ define <2 x i32> @demorgan_or_vec(<2 x i
   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(
+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]], <i1 true, i1 true>
 ; CHECK-NEXT:    [[AND:%.*]] = zext <2 x i1> [[AND:%.*]]1 to <2 x i32>
@@ -65,9 +276,9 @@ define <2 x i32> @demorgan_and_vec(<2 x
 
 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:    [[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]]
 ;
@@ -79,3 +290,31 @@ define i32 @PR28476(i32 %x, i32 %y) {
   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
+}
+

Modified: llvm/trunk/test/Transforms/InstCombine/not.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/not.ll?rev=301774&r1=301773&r2=301774&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/not.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/not.ll Sun Apr 30 13:57:12 2017
@@ -31,45 +31,8 @@ define i1 @invert_fcmp(float %X, float %
   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




More information about the llvm-commits mailing list