[llvm] 534701d - [InstCombine] Handle commuted variants in or of xor pattern
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Wed May 8 23:16:39 PDT 2024
Author: Nikita Popov
Date: 2024-05-09T15:16:25+09:00
New Revision: 534701d5f93369e822f3afc9670e3a42b08dfc6f
URL: https://github.com/llvm/llvm-project/commit/534701d5f93369e822f3afc9670e3a42b08dfc6f
DIFF: https://github.com/llvm/llvm-project/commit/534701d5f93369e822f3afc9670e3a42b08dfc6f.diff
LOG: [InstCombine] Handle commuted variants in or of xor pattern
This pattern only handled commutation in the "or", while all
involved operations are commutative. Make sure we handle all
sixteen patterns.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/or-xor.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index ed9a89b14efc..a52c70dbdf3f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3599,12 +3599,16 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
// (A ^ B) | ((B ^ C) ^ A) -> (A ^ B) | C
if (match(Op0, m_Xor(m_Value(A), m_Value(B))))
- if (match(Op1, m_Xor(m_Xor(m_Specific(B), m_Value(C)), m_Specific(A))))
+ if (match(Op1,
+ m_c_Xor(m_c_Xor(m_Specific(B), m_Value(C)), m_Specific(A))) ||
+ match(Op1, m_c_Xor(m_c_Xor(m_Specific(A), m_Value(C)), m_Specific(B))))
return BinaryOperator::CreateOr(Op0, C);
- // ((A ^ C) ^ B) | (B ^ A) -> (B ^ A) | C
- if (match(Op0, m_Xor(m_Xor(m_Value(A), m_Value(C)), m_Value(B))))
- if (match(Op1, m_Xor(m_Specific(B), m_Specific(A))))
+ // ((B ^ C) ^ A) | (A ^ B) -> (A ^ B) | C
+ if (match(Op1, m_Xor(m_Value(A), m_Value(B))))
+ if (match(Op0,
+ m_c_Xor(m_c_Xor(m_Specific(B), m_Value(C)), m_Specific(A))) ||
+ match(Op0, m_c_Xor(m_c_Xor(m_Specific(A), m_Value(C)), m_Specific(B))))
return BinaryOperator::CreateOr(Op1, C);
if (Instruction *DeMorgan = matchDeMorgansLaws(I, *this))
diff --git a/llvm/test/Transforms/InstCombine/or-xor.ll b/llvm/test/Transforms/InstCombine/or-xor.ll
index 32198c0a81dd..cf6b9000182d 100644
--- a/llvm/test/Transforms/InstCombine/or-xor.ll
+++ b/llvm/test/Transforms/InstCombine/or-xor.ll
@@ -1194,9 +1194,7 @@ define i32 @or_xor_tree_0001(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1215,9 +1213,7 @@ define i32 @or_xor_tree_0010(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1236,9 +1232,7 @@ define i32 @or_xor_tree_0011(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1257,9 +1251,7 @@ define i32 @or_xor_tree_0100(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1278,9 +1270,7 @@ define i32 @or_xor_tree_0101(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1299,9 +1289,7 @@ define i32 @or_xor_tree_0110(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1320,9 +1308,7 @@ define i32 @or_xor_tree_0111(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[XOR3]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1360,9 +1346,7 @@ define i32 @or_xor_tree_1001(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1381,9 +1365,7 @@ define i32 @or_xor_tree_1010(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1402,9 +1384,7 @@ define i32 @or_xor_tree_1011(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[XOR2]], [[A]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1423,9 +1403,7 @@ define i32 @or_xor_tree_1100(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1444,9 +1422,7 @@ define i32 @or_xor_tree_1101(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[B]], [[C]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1465,9 +1441,7 @@ define i32 @or_xor_tree_1110(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[A]], [[B]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
@@ -1486,9 +1460,7 @@ define i32 @or_xor_tree_1111(i32 %ax, i32 %bx, i32 %cx) {
; CHECK-NEXT: [[B:%.*]] = mul i32 [[BX:%.*]], 42
; CHECK-NEXT: [[C:%.*]] = mul i32 [[CX:%.*]], 42
; CHECK-NEXT: [[XOR1:%.*]] = xor i32 [[B]], [[A]]
-; CHECK-NEXT: [[XOR2:%.*]] = xor i32 [[C]], [[B]]
-; CHECK-NEXT: [[XOR3:%.*]] = xor i32 [[A]], [[XOR2]]
-; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR3]], [[XOR1]]
+; CHECK-NEXT: [[OR:%.*]] = or i32 [[XOR1]], [[C]]
; CHECK-NEXT: ret i32 [[OR]]
;
%a = mul i32 %ax, 42
More information about the llvm-commits
mailing list