From 3caa427f8ecbf9f5845c15b53e1021db94b3db03 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 24 Feb 2023 09:36:58 -0800 Subject: [PATCH] [RISCV] Use ComplexPattern to reduce the number of patterns for XVentanaCondOps. XVentanaCondOps check the condition operand for zero or non-zero. We use this to optimize seteq/setne that would otherwise becomes xor/xori/addi+snez/seqz. These patterns avoid the snez/seqz. This patch adds two ComplexPatterns to match the varous cases and emit the xor/xori/addi instruction. These patterns can also be used by D144681. Reviewed By: philipp.tomsich Differential Revision: https://reviews.llvm.org/D144700 --- llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 66 +++++++++++++++++++++++++ llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h | 8 +++ llvm/lib/Target/RISCV/RISCVInstrInfo.td | 9 ++++ llvm/lib/Target/RISCV/RISCVInstrInfoXVentana.td | 48 +++--------------- 4 files changed, 91 insertions(+), 40 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index 604ad1f..8516520 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -2423,6 +2423,72 @@ bool RISCVDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth, return true; } +/// Some instructions have a condition operand that is compared against zero. +/// Since RISC-V doesn't have seteq/setne instructions, we can use this +/// property to avoid a seqz or snez instruction after an xor/addi/xori. +/// When \p Inverse is false, we match seteq or any unknown operation. When +/// \p Inverse is true, we only match setne. +bool RISCVDAGToDAGISel::selectCondOp(SDValue N, bool Inverse, SDValue &Val) { + // Start with this node as the output. + Val = N; + + // If the node isn't a setcc, there's nothing we can do. Return success + // if we aren't looking for an inverse condition. + if (N->getOpcode() != ISD::SETCC) + return !Inverse; + + // If it isn't an equality comparison, we also can't do anything. + ISD::CondCode CCVal = cast(N->getOperand(2))->get(); + if (!isIntEqualitySetCC(CCVal)) + return !Inverse; + + // This ComplexPattern occurs in pairs with both polarities of Inverse. + // If this isn't the one we're looking for, let the other polarity match it. + if (isTrueWhenEqual(CCVal) != Inverse) + return false; + + SDValue LHS = N->getOperand(0); + SDValue RHS = N->getOperand(1); + + // If the RHS side is 0, we don't need any extra instructions, return the LHS. + if (isNullConstant(RHS)) { + Val = LHS; + return true; + } + + SDLoc DL(N); + + if (auto *C = dyn_cast(RHS)) { + int64_t CVal = C->getSExtValue(); + // If the RHS is -2048, we can use xori to produce 0 if the LHS is -2048 and + // non-zero otherwise. + if (CVal == -2048) { + Val = + SDValue(CurDAG->getMachineNode( + RISCV::XORI, DL, N->getValueType(0), LHS, + CurDAG->getTargetConstant(CVal, DL, N->getValueType(0))), + 0); + return true; + } + // If the RHS is [-2047,2048], we can use addi with -RHS to produce 0 if the + // LHS is equal to the RHS and non-zero otherwise. + if (isInt<12>(CVal) || CVal == 2048) { + Val = + SDValue(CurDAG->getMachineNode( + RISCV::ADDI, DL, N->getValueType(0), LHS, + CurDAG->getTargetConstant(-CVal, DL, N->getValueType(0))), + 0); + return true; + } + } + + // If nothing else we can XOR the LHS and RHS to produce zero if they are + // equal and a non-zero value if they aren't. + Val = SDValue( + CurDAG->getMachineNode(RISCV::XOR, DL, N->getValueType(0), LHS, RHS), 0); + return true; +} + bool RISCVDAGToDAGISel::selectSExtBits(SDValue N, unsigned Bits, SDValue &Val) { if (N.getOpcode() == ISD::SIGN_EXTEND_INREG && cast(N.getOperand(1))->getVT().getSizeInBits() == Bits) { diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h index 3e023f4..df4671d 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h @@ -86,6 +86,14 @@ public: return selectShiftMask(N, 32, ShAmt); } + bool selectCondOp(SDValue N, bool Inverse, SDValue &Val); + bool selectCondOp(SDValue N, SDValue &Val) { + return selectCondOp(N, /*Inverse*/ false, Val); + } + bool selectInverseCondOp(SDValue N, SDValue &Val) { + return selectCondOp(N, /*Inverse*/ true, Val); + } + bool selectSExtBits(SDValue N, unsigned Bits, SDValue &Val); template bool selectSExtBits(SDValue N, SDValue &Val) { return selectSExtBits(N, Bits, Val); diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td index 52d8a0e..e6a292d 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -1870,6 +1870,15 @@ def : Pat<(binop_allwusers GPR:$rs1, (AddiPair:$rs2)), (AddiPairImmSmall AddiPair:$rs2))>; } +// Some instructions have a condition operand that is compared against zero. +// Since RISC-V doesn't have seteq/setne instructions, we can use this +// property to avoid a seqz or snez instruction after an xor/addi/xori. +// condop matches a setne or any unknown operation. +// invcondop only matches a seteq. +// This ComplexPatterns must be used in pairs. +def condop : ComplexPattern; +def invcondop : ComplexPattern; + /// Empty pseudo for RISCVInitUndefPass let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 0, isCodeGenOnly = 1 in { def PseudoRVVInitUndefM1 : Pseudo<(outs VR:$vd), (ins), [], "">; diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoXVentana.td b/llvm/lib/Target/RISCV/RISCVInstrInfoXVentana.td index 68c3a21..73a06e0 100644 --- a/llvm/lib/Target/RISCV/RISCVInstrInfoXVentana.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoXVentana.td @@ -30,46 +30,14 @@ def VT_MASKCN : VTMaskedMove<0b111, "vt.maskcn">, let Predicates = [IsRV64, HasVendorXVentanaCondOps] in { // Directly use MASKC/MASKCN in case of any of the operands being 0. -def : Pat<(select GPR:$rc, GPR:$rs1, (i64 0)), - (VT_MASKC $rs1, $rc)>; -def : Pat<(select GPR:$rc, (i64 0), GPR:$rs1), - (VT_MASKCN $rs1, $rc)>; - -def : Pat<(select (i64 (setne GPR:$rc, (i64 0))), GPR:$rs1, (i64 0)), - (VT_MASKC GPR:$rs1, GPR:$rc)>; -def : Pat<(select (i64 (seteq GPR:$rc, (i64 0))), GPR:$rs1, (i64 0)), - (VT_MASKCN GPR:$rs1, GPR:$rc)>; -def : Pat<(select (i64 (setne GPR:$rc, (i64 0))), (i64 0), GPR:$rs1), - (VT_MASKCN GPR:$rs1, GPR:$rc)>; -def : Pat<(select (i64 (seteq GPR:$rc, (i64 0))), (i64 0), GPR:$rs1), - (VT_MASKC GPR:$rs1, GPR:$rc)>; - -def : Pat<(select (i64 (setne GPR:$x, simm12_plus1:$y)), GPR:$rs1, (i64 0)), - (VT_MASKC GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y)))>; -def : Pat<(select (i64 (seteq GPR:$x, simm12_plus1:$y)), GPR:$rs1, (i64 0)), - (VT_MASKCN GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y)))>; -def : Pat<(select (i64 (setne GPR:$x, simm12_plus1:$y)), (i64 0), GPR:$rs1), - (VT_MASKCN GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y)))>; -def : Pat<(select (i64 (seteq GPR:$x, simm12_plus1:$y)), (i64 0), GPR:$rs1), - (VT_MASKC GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y)))>; - -def : Pat<(select (i64 (setne GPR:$x, (i64 -2048))), GPR:$rs1, (i64 0)), - (VT_MASKC GPR:$rs1, (XORI GPR:$x, -2048))>; -def : Pat<(select (i64 (seteq GPR:$x, (i64 -2048))), GPR:$rs1, (i64 0)), - (VT_MASKCN GPR:$rs1, (XORI GPR:$x, -2048))>; -def : Pat<(select (i64 (setne GPR:$x, (i64 -2048))), (i64 0), GPR:$rs1), - (VT_MASKCN GPR:$rs1, (XORI GPR:$x, -2048))>; -def : Pat<(select (i64 (seteq GPR:$x, (i64 -2048))), (i64 0), GPR:$rs1), - (VT_MASKC GPR:$rs1, (XORI GPR:$x, -2048))>; - -def : Pat<(select (i64 (setne GPR:$x, GPR:$y)), GPR:$rs1, (i64 0)), - (VT_MASKC GPR:$rs1, (XOR GPR:$x, GPR:$y))>; -def : Pat<(select (i64 (seteq GPR:$x, GPR:$y)), GPR:$rs1, (i64 0)), - (VT_MASKCN GPR:$rs1, (XOR GPR:$x, GPR:$y))>; -def : Pat<(select (i64 (setne GPR:$x, GPR:$y)), (i64 0), GPR:$rs1), - (VT_MASKCN GPR:$rs1, (XOR GPR:$x, GPR:$y))>; -def : Pat<(select (i64 (seteq GPR:$x, GPR:$y)), (i64 0), GPR:$rs1), - (VT_MASKC GPR:$rs1, (XOR GPR:$x, GPR:$y))>; +def : Pat<(select condop:$rc, GPR:$rs1, (i64 0)), + (VT_MASKC GPR:$rs1, condop:$rc)>; +def : Pat<(select invcondop:$rc, GPR:$rs1, (i64 0)), + (VT_MASKCN GPR:$rs1, invcondop:$rc)>; +def : Pat<(select condop:$rc, (i64 0), GPR:$rs1), + (VT_MASKCN GPR:$rs1, condop:$rc)>; +def : Pat<(select invcondop:$rc, (i64 0), GPR:$rs1), + (VT_MASKC GPR:$rs1, invcondop:$rc)>; // Conditional AND operation patterns. def : Pat<(i64 (select GPR:$rc, (and GPR:$rs1, GPR:$rs2), GPR:$rs1)), -- 2.7.4