From 6a6e6f04ec2cd2f4f07ec4943036c5c2d47ce0c7 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sun, 5 Jan 2020 17:17:41 +0000 Subject: [PATCH] [X86] Move combineLogicBlendIntoConditionalNegate before combineSelect. NFCI. Updates function order in preparation of future fix for PR43660 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 124 ++++++++++++------------ 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 63ba9c7ab9b2..ba29d9e513d0 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -37618,6 +37618,68 @@ static SDValue combineVSelectToBLENDV(SDNode *N, SelectionDAG &DAG, return SDValue(); } +// Try to match: +// (or (and (M, (sub 0, X)), (pandn M, X))) +// which is a special case of: +// (select M, (sub 0, X), X) +// Per: +// http://graphics.stanford.edu/~seander/bithacks.html#ConditionalNegate +// We know that, if fNegate is 0 or 1: +// (fNegate ? -v : v) == ((v ^ -fNegate) + fNegate) +// +// Here, we have a mask, M (all 1s or 0), and, similarly, we know that: +// ((M & 1) ? -X : X) == ((X ^ -(M & 1)) + (M & 1)) +// ( M ? -X : X) == ((X ^ M ) + (M & 1)) +// This lets us transform our vselect to: +// (add (xor X, M), (and M, 1)) +// And further to: +// (sub (xor X, M), M) +static SDValue combineLogicBlendIntoConditionalNegate( + EVT VT, SDValue Mask, SDValue X, SDValue Y, const SDLoc &DL, + SelectionDAG &DAG, const X86Subtarget &Subtarget) { + EVT MaskVT = Mask.getValueType(); + assert(MaskVT.isInteger() && + DAG.ComputeNumSignBits(Mask) == MaskVT.getScalarSizeInBits() && + "Mask must be zero/all-bits"); + + if (X.getValueType() != MaskVT || Y.getValueType() != MaskVT) + return SDValue(); + if (!DAG.getTargetLoweringInfo().isOperationLegal(ISD::SUB, MaskVT)) + return SDValue(); + + auto IsNegV = [](SDNode *N, SDValue V) { + return N->getOpcode() == ISD::SUB && N->getOperand(1) == V && + ISD::isBuildVectorAllZeros(N->getOperand(0).getNode()); + }; + + SDValue V; + if (IsNegV(Y.getNode(), X)) + V = X; + else if (IsNegV(X.getNode(), Y)) + V = Y; + else + return SDValue(); + + SDValue SubOp1 = DAG.getNode(ISD::XOR, DL, MaskVT, V, Mask); + SDValue SubOp2 = Mask; + + // If the negate was on the false side of the select, then + // the operands of the SUB need to be swapped. PR 27251. + // This is because the pattern being matched above is + // (vselect M, (sub (0, X), X) -> (sub (xor X, M), M) + // but if the pattern matched was + // (vselect M, X, (sub (0, X))), that is really negation of the pattern + // above, -(vselect M, (sub 0, X), X), and therefore the replacement + // pattern also needs to be a negation of the replacement pattern above. + // And -(sub X, Y) is just sub (Y, X), so swapping the operands of the + // sub accomplishes the negation of the replacement pattern. + if (V == Y) + std::swap(SubOp1, SubOp2); + + SDValue Res = DAG.getNode(ISD::SUB, DL, MaskVT, SubOp1, SubOp2); + return DAG.getBitcast(VT, Res); +} + /// Do target-specific dag combines on SELECT and VSELECT nodes. static SDValue combineSelect(SDNode *N, SelectionDAG &DAG, TargetLowering::DAGCombinerInfo &DCI, @@ -40186,68 +40248,6 @@ static bool matchLogicBlend(SDNode *N, SDValue &X, SDValue &Y, SDValue &Mask) { return true; } -// Try to match: -// (or (and (M, (sub 0, X)), (pandn M, X))) -// which is a special case of vselect: -// (vselect M, (sub 0, X), X) -// Per: -// http://graphics.stanford.edu/~seander/bithacks.html#ConditionalNegate -// We know that, if fNegate is 0 or 1: -// (fNegate ? -v : v) == ((v ^ -fNegate) + fNegate) -// -// Here, we have a mask, M (all 1s or 0), and, similarly, we know that: -// ((M & 1) ? -X : X) == ((X ^ -(M & 1)) + (M & 1)) -// ( M ? -X : X) == ((X ^ M ) + (M & 1)) -// This lets us transform our vselect to: -// (add (xor X, M), (and M, 1)) -// And further to: -// (sub (xor X, M), M) -static SDValue combineLogicBlendIntoConditionalNegate( - EVT VT, SDValue Mask, SDValue X, SDValue Y, const SDLoc &DL, - SelectionDAG &DAG, const X86Subtarget &Subtarget) { - EVT MaskVT = Mask.getValueType(); - assert(MaskVT.isInteger() && - DAG.ComputeNumSignBits(Mask) == MaskVT.getScalarSizeInBits() && - "Mask must be zero/all-bits"); - - if (X.getValueType() != MaskVT || Y.getValueType() != MaskVT) - return SDValue(); - if (!DAG.getTargetLoweringInfo().isOperationLegal(ISD::SUB, MaskVT)) - return SDValue(); - - auto IsNegV = [](SDNode *N, SDValue V) { - return N->getOpcode() == ISD::SUB && N->getOperand(1) == V && - ISD::isBuildVectorAllZeros(N->getOperand(0).getNode()); - }; - - SDValue V; - if (IsNegV(Y.getNode(), X)) - V = X; - else if (IsNegV(X.getNode(), Y)) - V = Y; - else - return SDValue(); - - SDValue SubOp1 = DAG.getNode(ISD::XOR, DL, MaskVT, V, Mask); - SDValue SubOp2 = Mask; - - // If the negate was on the false side of the select, then - // the operands of the SUB need to be swapped. PR 27251. - // This is because the pattern being matched above is - // (vselect M, (sub (0, X), X) -> (sub (xor X, M), M) - // but if the pattern matched was - // (vselect M, X, (sub (0, X))), that is really negation of the pattern - // above, -(vselect M, (sub 0, X), X), and therefore the replacement - // pattern also needs to be a negation of the replacement pattern above. - // And -(sub X, Y) is just sub (Y, X), so swapping the operands of the - // sub accomplishes the negation of the replacement pattern. - if (V == Y) - std::swap(SubOp1, SubOp2); - - SDValue Res = DAG.getNode(ISD::SUB, DL, MaskVT, SubOp1, SubOp2); - return DAG.getBitcast(VT, Res); -} - // Try to fold: // (or (and (m, y), (pandn m, x))) // into: