diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -7449,24 +7449,39 @@ static SDValue visitORCommutative(SelectionDAG &DAG, SDValue N0, SDValue N1, SDNode *N) { EVT VT = N0.getValueType(); - if (N0.getOpcode() == ISD::AND) { - SDValue N00 = N0.getOperand(0); - SDValue N01 = N0.getOperand(1); + + auto peekThroughResize = [](SDValue V) { + if (V->getOpcode() == ISD::ZERO_EXTEND || V->getOpcode() == ISD::TRUNCATE) + return V->getOperand(0); + return V; + }; + + SDValue N0Resized = peekThroughResize(N0); + if (N0Resized.getOpcode() == ISD::AND) { + SDValue N1Resized = peekThroughResize(N1); + SDValue N00 = N0Resized.getOperand(0); + SDValue N01 = N0Resized.getOperand(1); // fold or (and x, y), x --> x - if (N00 == N1 || N01 == N1) + if (N00 == N1Resized || N01 == N1Resized) return N1; // fold (or (and X, (xor Y, -1)), Y) -> (or X, Y) // TODO: Set AllowUndefs = true. - if (getBitwiseNotOperand(N01, N00, - /* AllowUndefs */ false) == N1) - return DAG.getNode(ISD::OR, SDLoc(N), VT, N00, N1); + if (SDValue NotOperand = getBitwiseNotOperand(N01, N00, + /* AllowUndefs */ false)) { + if (peekThroughResize(NotOperand) == N1Resized) + return DAG.getNode(ISD::OR, SDLoc(N), VT, + DAG.getZExtOrTrunc(N00, SDLoc(N), VT), N1); + } // fold (or (and (xor Y, -1), X), Y) -> (or X, Y) - if (getBitwiseNotOperand(N00, N01, - /* AllowUndefs */ false) == N1) - return DAG.getNode(ISD::OR, SDLoc(N), VT, N01, N1); + if (SDValue NotOperand = getBitwiseNotOperand(N00, N01, + /* AllowUndefs */ false)) { + if (peekThroughResize(NotOperand) == N1Resized) + return DAG.getNode(ISD::OR, SDLoc(N), VT, + DAG.getZExtOrTrunc(N01, SDLoc(N), VT), N1); + } } if (N0.getOpcode() == ISD::XOR) { 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 @@ -318,10 +318,8 @@ ; ; X64-LABEL: add_and_xor_const_zext_trunc: ; X64: # %bb.0: -; X64-NEXT: movl %edi, %eax -; X64-NEXT: notl %eax -; X64-NEXT: andl $1, %eax -; X64-NEXT: orq %rdi, %rax +; X64-NEXT: movq %rdi, %rax +; X64-NEXT: orq $1, %rax ; X64-NEXT: retq %t = trunc i64 %x to i32 %xor = xor i32 %t, -1 @@ -341,9 +339,7 @@ ; ; X64-LABEL: add_and_xor_const_zext_trunc_var: ; X64: # %bb.0: -; X64-NEXT: movl %edi, %eax -; X64-NEXT: notl %eax -; X64-NEXT: andl %esi, %eax +; X64-NEXT: movl %esi, %eax ; X64-NEXT: orq %rdi, %rax ; X64-NEXT: retq %tx = trunc i64 %x to i32