Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2832,6 +2832,15 @@ DAG.getVTList(VT, Carry.getValueType()), N0, DAG.getConstant(0, DL, VT), Carry); + if (N1.getOpcode() == ISD::AND) { + // (add X, (and ~X, Y)) -> (or X, Y) + if (isBitwiseNot(N1.getOperand(0)) && N1.getOperand(0).getOperand(0) == N0) + return DAG.getNode(ISD::OR, DL, VT, N0, N1.getOperand(1)); + // (add X, (and Y, ~X)) -> (or X, Y) + if (isBitwiseNot(N1.getOperand(1)) && N1.getOperand(1).getOperand(0) == N0) + return DAG.getNode(ISD::OR, DL, VT, N0, N1.getOperand(0)); + } + return SDValue(); } Index: llvm/test/CodeGen/X86/add-and-not.ll =================================================================== --- llvm/test/CodeGen/X86/add-and-not.ll +++ 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 @@ -103,11 +99,10 @@ ; CHECK-NEXT: movl %ebx, %edi ; CHECK-NEXT: callq use@PLT ; CHECK-NEXT: andb %r14b, %bl -; CHECK-NEXT: movzbl %bl, %ebx -; CHECK-NEXT: movl %ebx, %edi +; CHECK-NEXT: movzbl %bl, %edi ; CHECK-NEXT: callq use@PLT -; CHECK-NEXT: addb %bpl, %bl -; CHECK-NEXT: movl %ebx, %eax +; CHECK-NEXT: orb %r14b, %bpl +; CHECK-NEXT: movl %ebp, %eax ; CHECK-NEXT: popq %rbx ; CHECK-NEXT: popq %r14 ; CHECK-NEXT: popq %rbp