[llvm] d0e9879 - [InstCombine] allow vector splat matching for bitwise logic folds

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 29 11:38:03 PDT 2021


Author: Sanjay Patel
Date: 2021-10-29T14:22:50-04:00
New Revision: d0e9879d9627c82a9c1b97cdf0d8da8829905574

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

LOG: [InstCombine] allow vector splat matching for bitwise logic folds

These transforms are also likely missing a one-use check,
but that's another patch.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
    llvm/test/Transforms/InstCombine/and-or.ll
    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 ad2ed1371caf..e95900555536 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2699,10 +2699,31 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
     return BinaryOperator::CreateXor(Or, ConstantInt::get(I.getType(), *CV));
   }
 
-  // (A & C)|(B & D)
+  // (A & C) | (B & D)
   Value *A, *B, *C, *D;
   if (match(Op0, m_And(m_Value(A), m_Value(C))) &&
       match(Op1, m_And(m_Value(B), m_Value(D)))) {
+
+    const APInt *MaskC0, *MaskC1;
+    if (match(C, m_APInt(MaskC0)) && match(D, m_APInt(MaskC1)) &&
+        *MaskC0 == ~*MaskC1) {
+      Value *X;
+
+      // ((X | B) & C1) | (B & C2) -> (X & C1) | B iff C1 == ~C2
+      if (match(A, m_c_Or(m_Value(X), m_Specific(B))))
+        return BinaryOperator::CreateOr(Builder.CreateAnd(X, *MaskC0), B);
+      // (A & C2) | ((X | A) & C1) -> (X & C2) | A iff C1 == ~C2
+      if (match(B, m_c_Or(m_Specific(A), m_Value(X))))
+        return BinaryOperator::CreateOr(Builder.CreateAnd(X, *MaskC1), A);
+
+      // ((X ^ B) & C1) | (B & C2) -> (X & C1) ^ B iff C1 == ~C2
+      if (match(A, m_c_Xor(m_Value(X), m_Specific(B))))
+        return BinaryOperator::CreateXor(Builder.CreateAnd(X, *MaskC0), B);
+      // (A & C2) | ((X ^ A) & C1) -> (X & C2) ^ A iff C1 == ~C2
+      if (match(B, m_c_Xor(m_Specific(A), m_Value(X))))
+        return BinaryOperator::CreateXor(Builder.CreateAnd(X, *MaskC1), A);
+    }
+
     // (A & C1)|(B & C2)
     ConstantInt *C1, *C2;
     if (match(C, m_ConstantInt(C1)) && match(D, m_ConstantInt(C2))) {
@@ -2738,24 +2759,6 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
                                  Builder.getInt(C1->getValue()|C2->getValue()));
         }
       }
-
-      if (C1->getValue() == ~C2->getValue()) {
-        Value *X;
-
-        // ((X|B)&C1)|(B&C2) -> (X&C1) | B iff C1 == ~C2
-        if (match(A, m_c_Or(m_Value(X), m_Specific(B))))
-          return BinaryOperator::CreateOr(Builder.CreateAnd(X, C1), B);
-        // (A&C2)|((X|A)&C1) -> (X&C2) | A iff C1 == ~C2
-        if (match(B, m_c_Or(m_Specific(A), m_Value(X))))
-          return BinaryOperator::CreateOr(Builder.CreateAnd(X, C2), A);
-
-        // ((X^B)&C1)|(B&C2) -> (X&C1) ^ B iff C1 == ~C2
-        if (match(A, m_c_Xor(m_Value(X), m_Specific(B))))
-          return BinaryOperator::CreateXor(Builder.CreateAnd(X, C1), B);
-        // (A&C2)|((X^A)&C1) -> (X&C2) ^ A iff C1 == ~C2
-        if (match(B, m_c_Xor(m_Specific(A), m_Value(X))))
-          return BinaryOperator::CreateXor(Builder.CreateAnd(X, C2), A);
-      }
     }
 
     // Don't try to form a select if it's unlikely that we'll get rid of at

diff  --git a/llvm/test/Transforms/InstCombine/and-or.ll b/llvm/test/Transforms/InstCombine/and-or.ll
index 9fb020bed9e3..82d60ce89539 100644
--- a/llvm/test/Transforms/InstCombine/and-or.ll
+++ b/llvm/test/Transforms/InstCombine/and-or.ll
@@ -57,10 +57,8 @@ define i32 @or_and_not_constant_commute3(i32 %a, i32 %b) {
 
 define <2 x i7> @or_and_not_constant_commute0_splat(<2 x i7> %a, <2 x i7> %b) {
 ; CHECK-LABEL: @or_and_not_constant_commute0_splat(
-; CHECK-NEXT:    [[T:%.*]] = or <2 x i7> [[B:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[T1:%.*]] = and <2 x i7> [[T]], <i7 42, i7 42>
-; CHECK-NEXT:    [[T2:%.*]] = and <2 x i7> [[B]], <i7 -43, i7 -43>
-; CHECK-NEXT:    [[T3:%.*]] = or <2 x i7> [[T1]], [[T2]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i7> [[A:%.*]], <i7 42, i7 42>
+; CHECK-NEXT:    [[T3:%.*]] = or <2 x i7> [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret <2 x i7> [[T3]]
 ;
   %t = or <2 x i7> %b, %a

diff  --git a/llvm/test/Transforms/InstCombine/or-xor.ll b/llvm/test/Transforms/InstCombine/or-xor.ll
index 4dd86c66018e..cb1b871d66d6 100644
--- a/llvm/test/Transforms/InstCombine/or-xor.ll
+++ b/llvm/test/Transforms/InstCombine/or-xor.ll
@@ -303,10 +303,8 @@ define i9 @or_and_xor_not_constant_commute1(i9 %a, i9 %b) {
 
 define <2 x i9> @or_and_xor_not_constant_commute2_splat(<2 x i9> %a, <2 x i9> %b) {
 ; CHECK-LABEL: @or_and_xor_not_constant_commute2_splat(
-; CHECK-NEXT:    [[OR:%.*]] = xor <2 x i9> [[B:%.*]], [[A:%.*]]
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i9> [[OR]], <i9 42, i9 42>
-; CHECK-NEXT:    [[AND2:%.*]] = and <2 x i9> [[B]], <i9 -43, i9 -43>
-; CHECK-NEXT:    [[XOR:%.*]] = or <2 x i9> [[AND2]], [[AND1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i9> [[A:%.*]], <i9 42, i9 42>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i9> [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret <2 x i9> [[XOR]]
 ;
   %or = xor <2 x i9> %b, %a
@@ -318,10 +316,8 @@ define <2 x i9> @or_and_xor_not_constant_commute2_splat(<2 x i9> %a, <2 x i9> %b
 
 define <2 x i9> @or_and_xor_not_constant_commute3_splat(<2 x i9> %a, <2 x i9> %b) {
 ; CHECK-LABEL: @or_and_xor_not_constant_commute3_splat(
-; CHECK-NEXT:    [[OR:%.*]] = xor <2 x i9> [[A:%.*]], [[B:%.*]]
-; CHECK-NEXT:    [[AND1:%.*]] = and <2 x i9> [[OR]], <i9 42, i9 42>
-; CHECK-NEXT:    [[AND2:%.*]] = and <2 x i9> [[B]], <i9 -43, i9 -43>
-; CHECK-NEXT:    [[XOR:%.*]] = or <2 x i9> [[AND2]], [[AND1]]
+; CHECK-NEXT:    [[TMP1:%.*]] = and <2 x i9> [[A:%.*]], <i9 42, i9 42>
+; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i9> [[TMP1]], [[B:%.*]]
 ; CHECK-NEXT:    ret <2 x i9> [[XOR]]
 ;
   %or = xor <2 x i9> %a, %b


        


More information about the llvm-commits mailing list