diff options
| author | yangzhaoxin <yangzhaoxin@loongson.cn> | 2025-09-30 19:57:55 +0800 |
|---|---|---|
| committer | yangzhaoxin <yangzhaoxin@loongson.cn> | 2025-09-30 19:57:55 +0800 |
| commit | a04beba6e4f3adf37e94b36ce57629cf325a2646 (patch) | |
| tree | 0fad882c4edaad2e700d00f72e236f3359ee79ab | |
| parent | fd81493e90331fe4753da1d3a65d5757e9cd3390 (diff) | |
[NFC] Moved IsNOT helper earlier.users/ylzsx/andn-combine
Makes it available for more combines to use without adding declarations.
| -rw-r--r-- | llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp | 106 |
1 files changed, 53 insertions, 53 deletions
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 049382d8ebbf..d41f31105b09 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -594,6 +594,59 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op, return SDValue(); } +// Helper to attempt to return a cheaper, bit-inverted version of \p V. +static SDValue isNOT(SDValue V, SelectionDAG &DAG) { + // TODO: don't always ignore oneuse constraints. + V = peekThroughBitcasts(V); + EVT VT = V.getValueType(); + + // Match not(xor X, -1) -> X. + if (V.getOpcode() == ISD::XOR && + (ISD::isBuildVectorAllOnes(V.getOperand(1).getNode()) || + isAllOnesConstant(V.getOperand(1)))) + return V.getOperand(0); + + // Match not(extract_subvector(not(X)) -> extract_subvector(X). + if (V.getOpcode() == ISD::EXTRACT_SUBVECTOR && + (isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) { + if (SDValue Not = isNOT(V.getOperand(0), DAG)) { + Not = DAG.getBitcast(V.getOperand(0).getValueType(), Not); + return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(Not), VT, Not, + V.getOperand(1)); + } + } + + // Match not(SplatVector(not(X)) -> SplatVector(X). + if (V.getOpcode() == ISD::BUILD_VECTOR) { + if (SDValue SplatValue = + cast<BuildVectorSDNode>(V.getNode())->getSplatValue()) { + if (!V->isOnlyUserOf(SplatValue.getNode())) + return SDValue(); + + if (SDValue Not = isNOT(SplatValue, DAG)) { + Not = DAG.getBitcast(V.getOperand(0).getValueType(), Not); + return DAG.getSplat(VT, SDLoc(Not), Not); + } + } + } + + // Match not(or(not(X),not(Y))) -> and(X, Y). + if (V.getOpcode() == ISD::OR && DAG.getTargetLoweringInfo().isTypeLegal(VT) && + V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) { + // TODO: Handle cases with single NOT operand -> VANDN + if (SDValue Op1 = isNOT(V.getOperand(1), DAG)) + if (SDValue Op0 = isNOT(V.getOperand(0), DAG)) + return DAG.getNode(ISD::AND, SDLoc(V), VT, DAG.getBitcast(VT, Op0), + DAG.getBitcast(VT, Op1)); + } + + // TODO: Add more matching patterns. Such as, + // not(concat_vectors(not(X), not(Y))) -> concat_vectors(X, Y). + // not(slt(C, X)) -> slt(X - 1, C) + + return SDValue(); +} + SDValue LoongArchTargetLowering::lowerConstantFP(SDValue Op, SelectionDAG &DAG) const { EVT VT = Op.getValueType(); @@ -4939,59 +4992,6 @@ void LoongArchTargetLowering::ReplaceNodeResults( } } -// Helper to attempt to return a cheaper, bit-inverted version of \p V. -static SDValue isNOT(SDValue V, SelectionDAG &DAG) { - // TODO: don't always ignore oneuse constraints. - V = peekThroughBitcasts(V); - EVT VT = V.getValueType(); - - // Match not(xor X, -1) -> X. - if (V.getOpcode() == ISD::XOR && - (ISD::isBuildVectorAllOnes(V.getOperand(1).getNode()) || - isAllOnesConstant(V.getOperand(1)))) - return V.getOperand(0); - - // Match not(extract_subvector(not(X)) -> extract_subvector(X). - if (V.getOpcode() == ISD::EXTRACT_SUBVECTOR && - (isNullConstant(V.getOperand(1)) || V.getOperand(0).hasOneUse())) { - if (SDValue Not = isNOT(V.getOperand(0), DAG)) { - Not = DAG.getBitcast(V.getOperand(0).getValueType(), Not); - return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SDLoc(Not), VT, Not, - V.getOperand(1)); - } - } - - // Match not(SplatVector(not(X)) -> SplatVector(X). - if (V.getOpcode() == ISD::BUILD_VECTOR) { - if (SDValue SplatValue = - cast<BuildVectorSDNode>(V.getNode())->getSplatValue()) { - if (!V->isOnlyUserOf(SplatValue.getNode())) - return SDValue(); - - if (SDValue Not = isNOT(SplatValue, DAG)) { - Not = DAG.getBitcast(V.getOperand(0).getValueType(), Not); - return DAG.getSplat(VT, SDLoc(Not), Not); - } - } - } - - // Match not(or(not(X),not(Y))) -> and(X, Y). - if (V.getOpcode() == ISD::OR && DAG.getTargetLoweringInfo().isTypeLegal(VT) && - V.getOperand(0).hasOneUse() && V.getOperand(1).hasOneUse()) { - // TODO: Handle cases with single NOT operand -> VANDN - if (SDValue Op1 = isNOT(V.getOperand(1), DAG)) - if (SDValue Op0 = isNOT(V.getOperand(0), DAG)) - return DAG.getNode(ISD::AND, SDLoc(V), VT, DAG.getBitcast(VT, Op0), - DAG.getBitcast(VT, Op1)); - } - - // TODO: Add more matching patterns. Such as, - // not(concat_vectors(not(X), not(Y))) -> concat_vectors(X, Y). - // not(slt(C, X)) -> slt(X - 1, C) - - return SDValue(); -} - /// Try to fold: (and (xor X, -1), Y) -> (vandn X, Y). static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL, SelectionDAG &DAG) { |
