[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