[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