summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoryangzhaoxin <yangzhaoxin@loongson.cn>2025-09-30 19:57:55 +0800
committeryangzhaoxin <yangzhaoxin@loongson.cn>2025-09-30 19:57:55 +0800
commita04beba6e4f3adf37e94b36ce57629cf325a2646 (patch)
tree0fad882c4edaad2e700d00f72e236f3359ee79ab
parentfd81493e90331fe4753da1d3a65d5757e9cd3390 (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.cpp106
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) {