[SelectionDAG] Add pattern to haveNoCommonBitsSet

Correctly identify the following pattern, which has no common bits: (X & ~M) op (Y & M).

Differential Revision: https://reviews.llvm.org/D113970
This commit is contained in:
Omer Aviram 2021-12-01 12:03:22 -05:00 committed by Sanjay Patel
parent 09859113ed
commit 617ad14060
3 changed files with 36 additions and 69 deletions

View File

@ -4542,10 +4542,25 @@ bool SelectionDAG::isEqualTo(SDValue A, SDValue B) const {
}
// FIXME: unify with llvm::haveNoCommonBitsSet.
// FIXME: could also handle masked merge pattern (X & ~M) op (Y & M)
bool SelectionDAG::haveNoCommonBitsSet(SDValue A, SDValue B) const {
assert(A.getValueType() == B.getValueType() &&
"Values must have the same type");
// Match masked merge pattern (X & ~M) op (Y & M)
if (A->getOpcode() == ISD::AND && B->getOpcode() == ISD::AND) {
auto MatchNoCommonBitsPattern = [&](SDValue NotM, SDValue And) {
if (isBitwiseNot(NotM, true)) {
SDValue NotOperand = NotM->getOperand(0);
return NotOperand == And->getOperand(0) ||
NotOperand == And->getOperand(1);
}
return false;
};
if (MatchNoCommonBitsPattern(A->getOperand(0), B) ||
MatchNoCommonBitsPattern(A->getOperand(1), B) ||
MatchNoCommonBitsPattern(B->getOperand(0), A) ||
MatchNoCommonBitsPattern(B->getOperand(1), A))
return true;
}
return KnownBits::haveNoCommonBitsSet(computeKnownBits(A),
computeKnownBits(B));
}

View File

@ -146,10 +146,10 @@ define i32 @or_and_and_rhs_neg_i32(i32 %x, i32 %y, i32 %z) {
;
; BMI-LABEL: or_and_and_rhs_neg_i32:
; BMI: # %bb.0: # %entry
; BMI-NEXT: # kill: def $edx killed $edx def $rdx
; BMI-NEXT: andl %esi, %edx
; BMI-NEXT: andnl %edi, %esi, %eax
; BMI-NEXT: orl %edx, %eax
; BMI-NEXT: incl %eax
; BMI-NEXT: leal 1(%rdx,%rax), %eax
; BMI-NEXT: retq
entry:
%and1 = and i32 %z, %y
@ -172,10 +172,10 @@ define i32 @or_and_and_lhs_neg_i32(i32 %x, i32 %y, i32 %z) {
;
; BMI-LABEL: or_and_and_lhs_neg_i32:
; BMI: # %bb.0: # %entry
; BMI-NEXT: # kill: def $edx killed $edx def $rdx
; BMI-NEXT: andl %esi, %edx
; BMI-NEXT: andnl %edi, %esi, %eax
; BMI-NEXT: orl %edx, %eax
; BMI-NEXT: incl %eax
; BMI-NEXT: leal 1(%rdx,%rax), %eax
; BMI-NEXT: retq
entry:
%and1 = and i32 %z, %y
@ -198,10 +198,10 @@ define i32 @or_and_rhs_neg_and_i32(i32 %x, i32 %y, i32 %z) {
;
; BMI-LABEL: or_and_rhs_neg_and_i32:
; BMI: # %bb.0: # %entry
; BMI-NEXT: # kill: def $edi killed $edi def $rdi
; BMI-NEXT: andnl %edx, %esi, %eax
; BMI-NEXT: andl %esi, %edi
; BMI-NEXT: orl %edi, %eax
; BMI-NEXT: incl %eax
; BMI-NEXT: leal 1(%rax,%rdi), %eax
; BMI-NEXT: retq
entry:
%xor = xor i32 %y, -1
@ -224,10 +224,10 @@ define i32 @or_and_lhs_neg_and_i32(i32 %x, i32 %y, i32 %z) {
;
; BMI-LABEL: or_and_lhs_neg_and_i32:
; BMI: # %bb.0: # %entry
; BMI-NEXT: # kill: def $edi killed $edi def $rdi
; BMI-NEXT: andnl %edx, %esi, %eax
; BMI-NEXT: andl %esi, %edi
; BMI-NEXT: orl %edi, %eax
; BMI-NEXT: incl %eax
; BMI-NEXT: leal 1(%rax,%rdi), %eax
; BMI-NEXT: retq
entry:
%xor = xor i32 %y, -1
@ -251,8 +251,7 @@ define i64 @or_and_and_rhs_neg_i64(i64 %x, i64 %y, i64 %z) {
; BMI: # %bb.0: # %entry
; BMI-NEXT: andq %rsi, %rdx
; BMI-NEXT: andnq %rdi, %rsi, %rax
; BMI-NEXT: orq %rdx, %rax
; BMI-NEXT: incq %rax
; BMI-NEXT: leaq 1(%rdx,%rax), %rax
; BMI-NEXT: retq
entry:
%and1 = and i64 %z, %y
@ -276,8 +275,7 @@ define i64 @or_and_and_lhs_neg_i64(i64 %x, i64 %y, i64 %z) {
; BMI: # %bb.0: # %entry
; BMI-NEXT: andq %rsi, %rdx
; BMI-NEXT: andnq %rdi, %rsi, %rax
; BMI-NEXT: orq %rdx, %rax
; BMI-NEXT: incq %rax
; BMI-NEXT: leaq 1(%rdx,%rax), %rax
; BMI-NEXT: retq
entry:
%and1 = and i64 %z, %y
@ -301,8 +299,7 @@ define i64 @or_and_rhs_neg_and_i64(i64 %x, i64 %y, i64 %z) {
; BMI: # %bb.0: # %entry
; BMI-NEXT: andnq %rdx, %rsi, %rax
; BMI-NEXT: andq %rsi, %rdi
; BMI-NEXT: orq %rdi, %rax
; BMI-NEXT: incq %rax
; BMI-NEXT: leaq 1(%rax,%rdi), %rax
; BMI-NEXT: retq
entry:
%xor = xor i64 %y, -1
@ -326,8 +323,7 @@ define i64 @or_and_lhs_neg_and_i64(i64 %x, i64 %y, i64 %z) {
; BMI: # %bb.0: # %entry
; BMI-NEXT: andnq %rdx, %rsi, %rax
; BMI-NEXT: andq %rsi, %rdi
; BMI-NEXT: orq %rdi, %rax
; BMI-NEXT: incq %rax
; BMI-NEXT: leaq 1(%rax,%rdi), %rax
; BMI-NEXT: retq
entry:
%xor = xor i64 %y, -1

View File

@ -7,12 +7,7 @@
define <2 x i32> @or_and_and_rhs_neg_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z) {
; CHECK-LABEL: or_and_and_rhs_neg_vec_i32:
; CHECK: # %bb.0:
; CHECK-NEXT: pand %xmm1, %xmm2
; CHECK-NEXT: pandn %xmm0, %xmm1
; CHECK-NEXT: movdqa %xmm2, %xmm0
; CHECK-NEXT: por %xmm1, %xmm0
; CHECK-NEXT: paddd %xmm2, %xmm1
; CHECK-NEXT: psubd %xmm1, %xmm0
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
%and1 = and <2 x i32> %z, %y
%xor = xor <2 x i32> %y, <i32 -1, i32 -1>
@ -26,12 +21,7 @@ define <2 x i32> @or_and_and_rhs_neg_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i3
define <2 x i32> @or_and_and_lhs_neg_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z) {
; CHECK-LABEL: or_and_and_lhs_neg_vec_i32:
; CHECK: # %bb.0:
; CHECK-NEXT: pand %xmm1, %xmm2
; CHECK-NEXT: pandn %xmm0, %xmm1
; CHECK-NEXT: movdqa %xmm2, %xmm0
; CHECK-NEXT: por %xmm1, %xmm0
; CHECK-NEXT: paddd %xmm2, %xmm1
; CHECK-NEXT: psubd %xmm1, %xmm0
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
%and1 = and <2 x i32> %z, %y
%xor = xor <2 x i32> %y, <i32 -1, i32 -1>
@ -45,13 +35,7 @@ define <2 x i32> @or_and_and_lhs_neg_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i3
define <2 x i32> @or_and_rhs_neg_and_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z) {
; CHECK-LABEL: or_and_rhs_neg_and_vec_i32:
; CHECK: # %bb.0:
; CHECK-NEXT: pand %xmm1, %xmm0
; CHECK-NEXT: pandn %xmm2, %xmm1
; CHECK-NEXT: movdqa %xmm1, %xmm2
; CHECK-NEXT: por %xmm0, %xmm2
; CHECK-NEXT: paddd %xmm0, %xmm1
; CHECK-NEXT: psubd %xmm1, %xmm2
; CHECK-NEXT: movdqa %xmm2, %xmm0
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
%xor = xor <2 x i32> %y, <i32 -1, i32 -1>
%and1 = and <2 x i32> %z, %xor
@ -65,13 +49,7 @@ define <2 x i32> @or_and_rhs_neg_and_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i3
define <2 x i32> @or_and_lhs_neg_and_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i32> %z) {
; CHECK-LABEL: or_and_lhs_neg_and_vec_i32:
; CHECK: # %bb.0:
; CHECK-NEXT: pand %xmm1, %xmm0
; CHECK-NEXT: pandn %xmm2, %xmm1
; CHECK-NEXT: movdqa %xmm1, %xmm2
; CHECK-NEXT: por %xmm0, %xmm2
; CHECK-NEXT: paddd %xmm0, %xmm1
; CHECK-NEXT: psubd %xmm1, %xmm2
; CHECK-NEXT: movdqa %xmm2, %xmm0
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
%xor = xor <2 x i32> %y, <i32 -1, i32 -1>
%and1 = and <2 x i32> %xor, %z
@ -85,12 +63,7 @@ define <2 x i32> @or_and_lhs_neg_and_vec_i32(<2 x i32> %x, <2 x i32> %y, <2 x i3
define <2 x i64> @or_and_and_rhs_neg_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i64> %z) {
; CHECK-LABEL: or_and_and_rhs_neg_vec_i64:
; CHECK: # %bb.0:
; CHECK-NEXT: pand %xmm1, %xmm2
; CHECK-NEXT: pandn %xmm0, %xmm1
; CHECK-NEXT: movdqa %xmm2, %xmm0
; CHECK-NEXT: por %xmm1, %xmm0
; CHECK-NEXT: paddq %xmm2, %xmm1
; CHECK-NEXT: psubq %xmm1, %xmm0
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
%and1 = and <2 x i64> %z, %y
%xor = xor <2 x i64> %y, <i64 -1, i64 -1>
@ -104,12 +77,7 @@ define <2 x i64> @or_and_and_rhs_neg_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i6
define <2 x i64> @or_and_and_lhs_neg_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i64> %z) {
; CHECK-LABEL: or_and_and_lhs_neg_vec_i64:
; CHECK: # %bb.0:
; CHECK-NEXT: pand %xmm1, %xmm2
; CHECK-NEXT: pandn %xmm0, %xmm1
; CHECK-NEXT: movdqa %xmm2, %xmm0
; CHECK-NEXT: por %xmm1, %xmm0
; CHECK-NEXT: paddq %xmm2, %xmm1
; CHECK-NEXT: psubq %xmm1, %xmm0
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
%and1 = and <2 x i64> %z, %y
%xor = xor <2 x i64> %y, <i64 -1, i64 -1>
@ -123,13 +91,7 @@ define <2 x i64> @or_and_and_lhs_neg_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i6
define <2 x i64> @or_and_rhs_neg_and_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i64> %z) {
; CHECK-LABEL: or_and_rhs_neg_and_vec_i64:
; CHECK: # %bb.0:
; CHECK-NEXT: pand %xmm1, %xmm0
; CHECK-NEXT: pandn %xmm2, %xmm1
; CHECK-NEXT: movdqa %xmm1, %xmm2
; CHECK-NEXT: por %xmm0, %xmm2
; CHECK-NEXT: paddq %xmm0, %xmm1
; CHECK-NEXT: psubq %xmm1, %xmm2
; CHECK-NEXT: movdqa %xmm2, %xmm0
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
%xor = xor <2 x i64> %y, <i64 -1, i64 -1>
%and1 = and <2 x i64> %z, %xor
@ -143,13 +105,7 @@ define <2 x i64> @or_and_rhs_neg_and_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i6
define <2 x i64> @or_and_lhs_neg_and_vec_i64(<2 x i64> %x, <2 x i64> %y, <2 x i64> %z) {
; CHECK-LABEL: or_and_lhs_neg_and_vec_i64:
; CHECK: # %bb.0:
; CHECK-NEXT: pand %xmm1, %xmm0
; CHECK-NEXT: pandn %xmm2, %xmm1
; CHECK-NEXT: movdqa %xmm1, %xmm2
; CHECK-NEXT: por %xmm0, %xmm2
; CHECK-NEXT: paddq %xmm0, %xmm1
; CHECK-NEXT: psubq %xmm1, %xmm2
; CHECK-NEXT: movdqa %xmm2, %xmm0
; CHECK-NEXT: xorps %xmm0, %xmm0
; CHECK-NEXT: retq
%xor = xor <2 x i64> %y, <i64 -1, i64 -1>
%and1 = and <2 x i64> %xor, %z