[llvm] 54e969c - [InstCombine] allow vector splat matching for bitwise logic folds
Sanjay Patel via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 1 05:48:20 PDT 2021
Author: Sanjay Patel
Date: 2021-11-01T08:26:42-04:00
New Revision: 54e969cffddb2fbe555c65c0275b4f5accc6906c
URL: https://github.com/llvm/llvm-project/commit/54e969cffddb2fbe555c65c0275b4f5accc6906c
DIFF: https://github.com/llvm/llvm-project/commit/54e969cffddb2fbe555c65c0275b4f5accc6906c.diff
LOG: [InstCombine] allow vector splat matching for bitwise logic folds
This fold was added long ago (part of fixing PR4216),
and it matched scalars only. Intermediate folds have
been added subsequently, so extra uses are required
to exercise this code.
General proof:
https://alive2.llvm.org/ce/z/G6BBhB
One of the specific tests:
https://alive2.llvm.org/ce/z/t0JhEB
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/test/Transforms/InstCombine/and-or.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 6745b1b394cf..aa60b0fa58cc 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2706,43 +2706,45 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
// (A & MaskC0) | (B & MaskC1)
const APInt *MaskC0, *MaskC1;
- if (match(C, m_APInt(MaskC0)) && match(D, m_APInt(MaskC1)) &&
- *MaskC0 == ~*MaskC1) {
+ if (match(C, m_APInt(MaskC0)) && match(D, m_APInt(MaskC1))) {
Value *X;
+ if (*MaskC0 == ~*MaskC1) {
+ // ((X | B) & MaskC) | (B & ~MaskC) -> (X & MaskC) | B
+ if (match(A, m_c_Or(m_Value(X), m_Specific(B))))
+ return BinaryOperator::CreateOr(Builder.CreateAnd(X, *MaskC0), B);
+ // (A & MaskC) | ((X | A) & ~MaskC) -> (X & ~MaskC) | A
+ if (match(B, m_c_Or(m_Specific(A), m_Value(X))))
+ return BinaryOperator::CreateOr(Builder.CreateAnd(X, *MaskC1), A);
+
+ // ((X ^ B) & MaskC) | (B & ~MaskC) -> (X & MaskC) ^ B
+ if (match(A, m_c_Xor(m_Value(X), m_Specific(B))))
+ return BinaryOperator::CreateXor(Builder.CreateAnd(X, *MaskC0), B);
+ // (A & MaskC) | ((X ^ A) & ~MaskC) -> (X & ~MaskC) ^ A
+ if (match(B, m_c_Xor(m_Specific(A), m_Value(X))))
+ return BinaryOperator::CreateXor(Builder.CreateAnd(X, *MaskC1), A);
+ }
- // ((X | B) & MaskC) | (B & ~MaskC) -> (X & MaskC) | B
- if (match(A, m_c_Or(m_Value(X), m_Specific(B))))
- return BinaryOperator::CreateOr(Builder.CreateAnd(X, *MaskC0), B);
- // (A & MaskC) | ((X | A) & ~MaskC) -> (X & ~MaskC) | A
- if (match(B, m_c_Or(m_Specific(A), m_Value(X))))
- return BinaryOperator::CreateOr(Builder.CreateAnd(X, *MaskC1), A);
+ if ((*MaskC0 & *MaskC1).isZero()) {
+ // ((X | B) & C1) | (B & C2) --> (X | B) & (C1 | C2)
+ // iff (C1 & C2) == 0 and (X & ~C1) == 0
+ if (match(A, m_c_Or(m_Value(X), m_Specific(B))) &&
+ MaskedValueIsZero(X, ~*MaskC0, 0, &I))
+ return BinaryOperator::CreateAnd(
+ A, ConstantInt::get(I.getType(), *MaskC0 | *MaskC1));
- // ((X ^ B) & MaskC) | (B & ~MaskC) -> (X & MaskC) ^ B
- if (match(A, m_c_Xor(m_Value(X), m_Specific(B))))
- return BinaryOperator::CreateXor(Builder.CreateAnd(X, *MaskC0), B);
- // (A & MaskC) | ((X ^ A) & ~MaskC) -> (X & ~MaskC) ^ A
- if (match(B, m_c_Xor(m_Specific(A), m_Value(X))))
- return BinaryOperator::CreateXor(Builder.CreateAnd(X, *MaskC1), A);
+ // (A & C1) | ((X | A) & C2) --> (X | A) & (C1 | C2)
+ // iff (C1 & C2) == 0 and (X & ~C1) == 0
+ if (match(B, m_c_Or(m_Value(X), m_Specific(A))) &&
+ MaskedValueIsZero(X, ~*MaskC1, 0, &I))
+ return BinaryOperator::CreateAnd(
+ B, ConstantInt::get(I.getType(), *MaskC0 | *MaskC1));
+ }
}
// (A & C1)|(B & C2)
ConstantInt *C1, *C2;
if (match(C, m_ConstantInt(C1)) && match(D, m_ConstantInt(C2))) {
- Value *N;
if ((C1->getValue() & C2->getValue()).isZero()) {
- // ((B | N) & C1) | (B & C2) --> (B | N) & (C1 | C2)
- // iff (C1 & C2) == 0 and (N & ~C1) == 0
- if (match(A, m_c_Or(m_Specific(B), m_Value(N))) &&
- MaskedValueIsZero(N, ~C1->getValue(), 0, &I))
- return BinaryOperator::CreateAnd(
- A, Builder.getInt(C1->getValue() | C2->getValue()));
- // (A & C1) | ((A | N) & C2) --> (A | N) & (C1 | C2)
- // iff (C1 & C2) == 0 and (N & ~C1) == 0
- if (match(B, m_c_Or(m_Specific(A), m_Value(N))) &&
- MaskedValueIsZero(N, ~C2->getValue(), 0, &I))
- return BinaryOperator::CreateAnd(
- B, Builder.getInt(C1->getValue() | C2->getValue()));
-
// ((V|C3)&C1) | ((V|C4)&C2) --> (V|C3|C4)&(C1|C2)
// iff (C1&C2) == 0 and (C3&~C1) == 0 and (C4&~C2) == 0.
Value *V1 = nullptr, *V2 = nullptr;
diff --git a/llvm/test/Transforms/InstCombine/and-or.ll b/llvm/test/Transforms/InstCombine/and-or.ll
index 7996fd3c63f6..1e13be014919 100644
--- a/llvm/test/Transforms/InstCombine/and-or.ll
+++ b/llvm/test/Transforms/InstCombine/and-or.ll
@@ -124,7 +124,7 @@ define <2 x i8> @or_and_or_commute1_splat(<2 x i8> %x) {
; CHECK-NEXT: call void @use_vec(<2 x i8> [[X1]])
; CHECK-NEXT: [[X2:%.*]] = and <2 x i8> [[X]], <i8 64, i8 64>
; CHECK-NEXT: call void @use_vec(<2 x i8> [[X2]])
-; CHECK-NEXT: [[R:%.*]] = or <2 x i8> [[X2]], [[X1]]
+; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[XN]], <i8 123, i8 123>
; CHECK-NEXT: ret <2 x i8> [[R]]
;
%xn = or <2 x i8> %x, <i8 16, i8 16>
@@ -169,7 +169,7 @@ define <2 x i8> @or_and_or_commute2_splat(<2 x i8> %x, <2 x i8> %y) {
; CHECK-NEXT: call void @use_vec(<2 x i8> [[X1]])
; CHECK-NEXT: [[X2:%.*]] = and <2 x i8> [[X]], <i8 64, i8 64>
; CHECK-NEXT: call void @use_vec(<2 x i8> [[X2]])
-; CHECK-NEXT: [[R:%.*]] = or <2 x i8> [[X1]], [[X2]]
+; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[XN]], <i8 -5, i8 -5>
; CHECK-NEXT: ret <2 x i8> [[R]]
;
%n = lshr <2 x i8> %y, <i8 6, i8 6>
More information about the llvm-commits
mailing list