From 91105df3dfeb6c5589de987c1c1bdd3d7fe781d8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Amaury=20S=C3=A9chet?= Date: Fri, 7 Apr 2023 23:31:13 +0000 Subject: [PATCH] [DAG] Peek through zext/trunc when matching (or (and X, (not Y)), Y). This shows up in the wild, notably as a regression in D127115 . Depends on D147821 Reviewed By: RKSimon Differential Revision: https://reviews.llvm.org/D147827 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 35 +++++++++++++++++++-------- llvm/test/CodeGen/X86/add-and-not.ll | 10 +++----- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 84c0632..5f3c652 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -7449,24 +7449,39 @@ SDValue DAGCombiner::visitORLike(SDValue N0, SDValue N1, SDNode *N) { 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 index 4f2a307..10e3a6b 100644 --- a/llvm/test/CodeGen/X86/add-and-not.ll +++ b/llvm/test/CodeGen/X86/add-and-not.ll @@ -318,10 +318,8 @@ define i64 @add_and_xor_const_zext_trunc(i64 %x) { ; ; 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 @@ define i64 @add_and_xor_const_zext_trunc_var(i64 %x, i64 %y) { ; ; 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 -- 2.7.4