[llvm] c054402 - [InstSimplify] fold or-nand-xor

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 31 13:28:14 PST 2021


Author: Sanjay Patel
Date: 2021-12-31T15:11:13-05:00
New Revision: c054402170cd8466683a20385befc0523aba3359

URL: https://github.com/llvm/llvm-project/commit/c054402170cd8466683a20385befc0523aba3359
DIFF: https://github.com/llvm/llvm-project/commit/c054402170cd8466683a20385befc0523aba3359.diff

LOG: [InstSimplify] fold or-nand-xor

~(A & B) | (A ^ B) --> ~(A & B)

https://alive2.llvm.org/ce/z/hXQucg

Added: 
    

Modified: 
    llvm/lib/Analysis/InstructionSimplify.cpp
    llvm/test/Transforms/InstSimplify/or.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 4a8dc754349bd..15800898a15a1 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2258,14 +2258,21 @@ static Value *simplifyOrLogic(Value *X, Value *Y) {
       match(Y, m_Not(m_c_Or(m_Specific(A), m_Specific(B)))))
     return NotA;
 
-  // ~(A ^ B) | (A & B) --> ~(A & B)
-  // ~(A ^ B) | (B & A) --> ~(A & B)
+  // ~(A ^ B) | (A & B) --> ~(A ^ B)
+  // ~(A ^ B) | (B & A) --> ~(A ^ B)
   Value *NotAB;
   if (match(X, m_CombineAnd(m_NotForbidUndef(m_Xor(m_Value(A), m_Value(B))),
                             m_Value(NotAB))) &&
       match(Y, m_c_And(m_Specific(A), m_Specific(B))))
     return NotAB;
 
+  // ~(A & B) | (A ^ B) --> ~(A & B)
+  // ~(A & B) | (B ^ A) --> ~(A & B)
+  if (match(X, m_CombineAnd(m_NotForbidUndef(m_And(m_Value(A), m_Value(B))),
+                            m_Value(NotAB))) &&
+      match(Y, m_c_Xor(m_Specific(A), m_Specific(B))))
+    return NotAB;
+
   return nullptr;
 }
 

diff  --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll
index bb5144bad1b4c..3e8e0fa9de7fc 100644
--- a/llvm/test/Transforms/InstSimplify/or.ll
+++ b/llvm/test/Transforms/InstSimplify/or.ll
@@ -952,13 +952,13 @@ define i16 @or_xor_not_op_or_wrong_val(i16 %a, i16 %b, i16 %c) {
   ret i16 %r
 }
 
+; ~(x & y) | (x ^ y) --> ~(x & y)
+
 define i4 @or_nand_xor(i4 %x, i4 %y) {
 ; CHECK-LABEL: @or_nand_xor(
 ; CHECK-NEXT:    [[AND:%.*]] = and i4 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i4 [[X]], [[Y]]
 ; CHECK-NEXT:    [[NAND:%.*]] = xor i4 [[AND]], -1
-; CHECK-NEXT:    [[OR:%.*]] = or i4 [[XOR]], [[NAND]]
-; CHECK-NEXT:    ret i4 [[OR]]
+; CHECK-NEXT:    ret i4 [[NAND]]
 ;
   %and = and i4 %x, %y
   %xor = xor i4 %x, %y
@@ -970,10 +970,8 @@ define i4 @or_nand_xor(i4 %x, i4 %y) {
 define <2 x i4> @or_nand_xor_commute1(<2 x i4> %x, <2 x i4> %y) {
 ; CHECK-LABEL: @or_nand_xor_commute1(
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i4> [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i4> [[X]], [[Y]]
 ; CHECK-NEXT:    [[NAND:%.*]] = xor <2 x i4> [[AND]], <i4 -1, i4 -1>
-; CHECK-NEXT:    [[OR:%.*]] = or <2 x i4> [[XOR]], [[NAND]]
-; CHECK-NEXT:    ret <2 x i4> [[OR]]
+; CHECK-NEXT:    ret <2 x i4> [[NAND]]
 ;
   %and = and <2 x i4> %y, %x
   %xor = xor <2 x i4> %x, %y
@@ -985,10 +983,8 @@ define <2 x i4> @or_nand_xor_commute1(<2 x i4> %x, <2 x i4> %y) {
 define i71 @or_nand_xor_commute2(i71 %x, i71 %y) {
 ; CHECK-LABEL: @or_nand_xor_commute2(
 ; CHECK-NEXT:    [[AND:%.*]] = and i71 [[X:%.*]], [[Y:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i71 [[X]], [[Y]]
 ; CHECK-NEXT:    [[NAND:%.*]] = xor i71 [[AND]], -1
-; CHECK-NEXT:    [[OR:%.*]] = or i71 [[NAND]], [[XOR]]
-; CHECK-NEXT:    ret i71 [[OR]]
+; CHECK-NEXT:    ret i71 [[NAND]]
 ;
   %and = and i71 %x, %y
   %xor = xor i71 %x, %y
@@ -1000,10 +996,8 @@ define i71 @or_nand_xor_commute2(i71 %x, i71 %y) {
 define i4 @or_nand_xor_commute3(i4 %x, i4 %y) {
 ; CHECK-LABEL: @or_nand_xor_commute3(
 ; CHECK-NEXT:    [[AND:%.*]] = and i4 [[Y:%.*]], [[X:%.*]]
-; CHECK-NEXT:    [[XOR:%.*]] = xor i4 [[X]], [[Y]]
 ; CHECK-NEXT:    [[NAND:%.*]] = xor i4 [[AND]], -1
-; CHECK-NEXT:    [[OR:%.*]] = or i4 [[NAND]], [[XOR]]
-; CHECK-NEXT:    ret i4 [[OR]]
+; CHECK-NEXT:    ret i4 [[NAND]]
 ;
   %and = and i4 %y, %x
   %xor = xor i4 %x, %y
@@ -1012,6 +1006,8 @@ define i4 @or_nand_xor_commute3(i4 %x, i4 %y) {
   ret i4 %or
 }
 
+; negative test wrong operand
+
 define i4 @or_nand_xor_wrong_val(i4 %x, i4 %y, i4 %z) {
 ; CHECK-LABEL: @or_nand_xor_wrong_val(
 ; CHECK-NEXT:    [[AND:%.*]] = and i4 [[X:%.*]], [[Y:%.*]]
@@ -1027,6 +1023,8 @@ define i4 @or_nand_xor_wrong_val(i4 %x, i4 %y, i4 %z) {
   ret i4 %or
 }
 
+; negative test - undef element in 'not' is not allowed
+
 define <2 x i4> @or_nand_xor_undef_elt(<2 x i4> %x, <2 x i4> %y) {
 ; CHECK-LABEL: @or_nand_xor_undef_elt(
 ; CHECK-NEXT:    [[AND:%.*]] = and <2 x i4> [[Y:%.*]], [[X:%.*]]


        


More information about the llvm-commits mailing list