[SDAG] Handle A and B&~A in haveNoCommonBitsSet()

This is the DAG variant of D124763. The code already handles the
general pattern, but not this degenerate case.

This allows folding A + (B&~A) to A | (B&~A) which further holds
to A | B.

Handling on the SDAG level is needed because in the motivating
case the add is actually a getelementptr, which only gets converted
into an add on the SDAG level. However, this patch is not quite
sufficient to handle the getelementptr case yet, because of an
interfering demanded bits simplification.

Differential Revision: https://reviews.llvm.org/D124772
This commit is contained in:
Nikita Popov 2022-05-03 12:16:29 +02:00
parent ed2d4da732
commit 2171a896ed
2 changed files with 29 additions and 31 deletions

View File

@ -4686,18 +4686,21 @@ bool SelectionDAG::isEqualTo(SDValue A, SDValue B) const {
static bool haveNoCommonBitsSetCommutative(SDValue A, SDValue B) {
// 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;
};
// Including degenerate case (X & ~M) op M
auto MatchNoCommonBitsPattern = [&](SDValue NotM, SDValue Other) {
if (isBitwiseNot(NotM, true)) {
SDValue NotOperand = NotM->getOperand(0);
if (Other == NotOperand)
return true;
if (Other->getOpcode() == ISD::AND)
return NotOperand == Other->getOperand(0) ||
NotOperand == Other->getOperand(1);
}
return false;
};
if (A->getOpcode() == ISD::AND)
return MatchNoCommonBitsPattern(A->getOperand(0), B) ||
MatchNoCommonBitsPattern(A->getOperand(1), B);
}
return false;
}

View File

@ -7,9 +7,8 @@ define i8 @add_and_xor(i8 %x, i8 %y) {
; CHECK-LABEL: add_and_xor:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: notb %al
; CHECK-NEXT: andb %sil, %al
; CHECK-NEXT: addb %dil, %al
; CHECK-NEXT: orl %esi, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
; CHECK-NEXT: retq
%xor = xor i8 %x, -1
%and = and i8 %xor, %y
@ -51,9 +50,8 @@ define i8 @add_and_xor_commuted1(i8 %x, i8 %y) {
; CHECK-LABEL: add_and_xor_commuted1:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: notb %al
; CHECK-NEXT: andb %sil, %al
; CHECK-NEXT: addb %dil, %al
; CHECK-NEXT: orl %esi, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
; CHECK-NEXT: retq
%xor = xor i8 %x, -1
%and = and i8 %y, %xor
@ -65,9 +63,8 @@ define i8 @add_and_xor_commuted2(i8 %x, i8 %y) {
; CHECK-LABEL: add_and_xor_commuted2:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: notb %al
; CHECK-NEXT: andb %sil, %al
; CHECK-NEXT: addb %dil, %al
; CHECK-NEXT: orl %esi, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
; CHECK-NEXT: retq
%xor = xor i8 %x, -1
%and = and i8 %xor, %y
@ -79,9 +76,8 @@ define i8 @add_and_xor_commuted3(i8 %x, i8 %y) {
; CHECK-LABEL: add_and_xor_commuted3:
; CHECK: # %bb.0:
; CHECK-NEXT: movl %edi, %eax
; CHECK-NEXT: notb %al
; CHECK-NEXT: andb %sil, %al
; CHECK-NEXT: addb %dil, %al
; CHECK-NEXT: orl %esi, %eax
; CHECK-NEXT: # kill: def $al killed $al killed $eax
; CHECK-NEXT: retq
%xor = xor i8 %x, -1
%and = and i8 %y, %xor
@ -95,18 +91,17 @@ define i8 @add_and_xor_extra_use(i8 %x, i8 %y) nounwind {
; CHECK-NEXT: pushq %rbp
; CHECK-NEXT: pushq %r14
; CHECK-NEXT: pushq %rbx
; CHECK-NEXT: movl %esi, %r14d
; CHECK-NEXT: movl %edi, %ebp
; CHECK-NEXT: movl %ebp, %eax
; CHECK-NEXT: movl %esi, %ebx
; CHECK-NEXT: movl %edi, %r14d
; CHECK-NEXT: movl %r14d, %eax
; CHECK-NEXT: notb %al
; CHECK-NEXT: movzbl %al, %ebx
; CHECK-NEXT: movl %ebx, %edi
; CHECK-NEXT: movzbl %al, %ebp
; CHECK-NEXT: movl %ebp, %edi
; CHECK-NEXT: callq use@PLT
; CHECK-NEXT: andb %r14b, %bl
; CHECK-NEXT: movzbl %bl, %ebx
; CHECK-NEXT: movl %ebx, %edi
; CHECK-NEXT: andb %bl, %bpl
; CHECK-NEXT: movzbl %bpl, %edi
; CHECK-NEXT: callq use@PLT
; CHECK-NEXT: addb %bpl, %bl
; CHECK-NEXT: orb %r14b, %bl
; CHECK-NEXT: movl %ebx, %eax
; CHECK-NEXT: popq %rbx
; CHECK-NEXT: popq %r14