Skip to content

Commit

Permalink
[RISCV] Use ComplexPattern to reduce the number of patterns for XVent…
Browse files Browse the repository at this point in the history
…anaCondOps.

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
  • Loading branch information
topperc committed Feb 24, 2023
1 parent dc07867 commit 3caa427
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 40 deletions.
66 changes: 66 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
Expand Up @@ -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<CondCodeSDNode>(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<ConstantSDNode>(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<VTSDNode>(N.getOperand(1))->getVT().getSizeInBits() == Bits) {
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h
Expand Up @@ -86,6 +86,14 @@ class RISCVDAGToDAGISel : public SelectionDAGISel {
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 <unsigned Bits> bool selectSExtBits(SDValue N, SDValue &Val) {
return selectSExtBits(N, Bits, Val);
Expand Down
9 changes: 9 additions & 0 deletions llvm/lib/Target/RISCV/RISCVInstrInfo.td
Expand Up @@ -1870,6 +1870,15 @@ def : Pat<(binop_allwusers<add> 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<XLenVT, 1, "selectCondOp">;
def invcondop : ComplexPattern<XLenVT, 1, "selectInverseCondOp">;

/// Empty pseudo for RISCVInitUndefPass
let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 0, isCodeGenOnly = 1 in {
def PseudoRVVInitUndefM1 : Pseudo<(outs VR:$vd), (ins), [], "">;
Expand Down
48 changes: 8 additions & 40 deletions llvm/lib/Target/RISCV/RISCVInstrInfoXVentana.td
Expand Up @@ -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)),
Expand Down

0 comments on commit 3caa427

Please sign in to comment.