diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -4686,18 +4686,21 @@ 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; } diff --git a/llvm/test/CodeGen/X86/add-and-not.ll b/llvm/test/CodeGen/X86/add-and-not.ll --- a/llvm/test/CodeGen/X86/add-and-not.ll +++ b/llvm/test/CodeGen/X86/add-and-not.ll @@ -7,9 +7,8 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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