To do this we need to remove the always matching behavior from condop.
This requires us to add more 'select' isel patterns with a bare GPR
as the condition.
Rename condop/invcondop to riscv_setne/riscv_seteq.
This centralizes the ADDI/XORI/XOR tricks into one place.
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.
+/// RISC-V doesn't have general instructions for integer setne/seteq, but we can
+/// check for equality with 0. This function emits instructions that convert the
+/// seteq/setne into something that can be compared with 0.
+/// When \p Equal is false, we match setne. When \p Equal is true, we match
+/// seteq.
+bool RISCVDAGToDAGISel::selectSETCC(SDValue N, ISD::CondCode ExpectedCCVal,
+ SDValue &Val) {
+ assert(ISD::isIntEqualitySetCC(ExpectedCCVal) &&
+ "Unexpected condition code!");
+
+ // We're looking for a setcc.
if (N->getOpcode() != ISD::SETCC)
- return !Inverse;
+ return false;
- // If it isn't an equality comparison, we also can't do anything.
+ // Must be an equality comparison.
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)
+ if (CCVal != ExpectedCCVal)
return false;
SDValue LHS = N->getOperand(0);
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 selectSETCC(SDValue N, ISD::CondCode ExpectedCCVal, SDValue &Val);
+ bool selectSETNE(SDValue N, SDValue &Val) {
+ return selectSETCC(N, ISD::SETNE, Val);
}
- bool selectInverseCondOp(SDValue N, SDValue &Val) {
- return selectCondOp(N, /*Inverse*/ true, Val);
+ bool selectSETEQ(SDValue N, SDValue &Val) {
+ return selectSETCC(N, ISD::SETEQ, Val);
}
bool selectSExtBits(SDValue N, unsigned Bits, SDValue &Val);
def : PatGprGpr<setult, SLTU>;
def : PatGprSimm12<setult, SLTIU>;
+// RISC-V doesn't have general instructions for integer setne/seteq, but we can
+// check for equality with 0. These ComplexPatterns rewrite the setne/seteq into
+// something that can be compared with 0.
+// These ComplexPatterns must be used in pairs.
+def riscv_setne : ComplexPattern<XLenVT, 1, "selectSETNE", [setcc]>;
+def riscv_seteq : ComplexPattern<XLenVT, 1, "selectSETEQ", [setcc]>;
+
// Define pattern expansions for setcc operations that aren't directly
// handled by a RISC-V instruction.
-def : Pat<(seteq GPR:$rs1, 0), (SLTIU GPR:$rs1, 1)>;
-def : Pat<(seteq GPR:$rs1, GPR:$rs2), (SLTIU (XOR GPR:$rs1, GPR:$rs2), 1)>;
-def : Pat<(seteq GPR:$rs1, simm12_plus1:$imm12),
- (SLTIU (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)), 1)>;
-def : Pat<(seteq GPR:$rs1, -2048),
- (SLTIU (XORI GPR:$rs1, -2048), 1)>;
-def : Pat<(setne GPR:$rs1, 0), (SLTU X0, GPR:$rs1)>;
-def : Pat<(setne GPR:$rs1, GPR:$rs2), (SLTU X0, (XOR GPR:$rs1, GPR:$rs2))>;
-def : Pat<(setne GPR:$rs1, simm12_plus1:$imm12),
- (SLTU X0, (ADDI GPR:$rs1, (NegImm simm12_plus1:$imm12)))>;
-def : Pat<(setne GPR:$rs1, -2048),
- (SLTU X0, (XORI GPR:$rs1, -2048))>;
+def : Pat<(riscv_seteq GPR:$rs1), (SLTIU GPR:$rs1, 1)>;
+def : Pat<(riscv_setne GPR:$rs1), (SLTU X0, GPR:$rs1)>;
def : Pat<(setne GPR:$rs1, -1), (SLTIU GPR:$rs1, -1)>;
def IntCCtoRISCVCC : SDNodeXForm<riscv_selectcc, [{
(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), [], "">;
} // Predicates = [HasVendorXTHeadBs]
let Predicates = [HasVendorXTHeadCondMov] in {
-def : Pat<(select invcondop:$cond, GPR:$a, GPR:$b),
- (TH_MVNEZ $a, $b, $cond)>;
-def : Pat<(select condop:$cond, GPR:$a, GPR:$b),
- (TH_MVEQZ $a, $b, $cond)>;
-def : Pat<(select invcondop:$cond, GPR:$a, (XLenVT 0)),
- (TH_MVNEZ $a, X0, $cond)>;
-def : Pat<(select condop:$cond, GPR:$a, (XLenVT 0)),
- (TH_MVEQZ $a, X0, $cond)>;
-def : Pat<(select invcondop:$cond, (XLenVT 0), GPR:$b),
- (TH_MVEQZ $b, X0, $cond)>;
-def : Pat<(select condop:$cond, (XLenVT 0), GPR:$b),
- (TH_MVNEZ $b, X0, $cond)>;
+def : Pat<(select GPR:$cond, GPR:$a, GPR:$b),
+ (TH_MVEQZ GPR:$a, GPR:$b, GPR:$cond)>;
+def : Pat<(select GPR:$cond, GPR:$a, (XLenVT 0)),
+ (TH_MVEQZ GPR:$a, X0, GPR:$cond)>;
+def : Pat<(select GPR:$cond, (XLenVT 0), GPR:$b),
+ (TH_MVNEZ GPR:$b, X0, GPR:$cond)>;
+
+def : Pat<(select (riscv_seteq GPR:$cond), GPR:$a, GPR:$b),
+ (TH_MVNEZ GPR:$a, GPR:$b, GPR:$cond)>;
+def : Pat<(select (riscv_setne GPR:$cond), GPR:$a, GPR:$b),
+ (TH_MVEQZ GPR:$a, GPR:$b, GPR:$cond)>;
+def : Pat<(select (riscv_seteq GPR:$cond), GPR:$a, (XLenVT 0)),
+ (TH_MVNEZ GPR:$a, X0, GPR:$cond)>;
+def : Pat<(select (riscv_setne GPR:$cond), GPR:$a, (XLenVT 0)),
+ (TH_MVEQZ GPR:$a, X0, GPR:$cond)>;
+def : Pat<(select (riscv_seteq GPR:$cond), (XLenVT 0), GPR:$b),
+ (TH_MVEQZ GPR:$b, X0, GPR:$cond)>;
+def : Pat<(select (riscv_setne GPR:$cond), (XLenVT 0), GPR:$b),
+ (TH_MVNEZ GPR:$b, X0, GPR:$cond)>;
} // Predicates = [HasVendorXTHeadCondMov]
let Predicates = [HasVendorXTHeadMac] in {
let Predicates = [IsRV64, HasVendorXVentanaCondOps] in {
// Directly use MASKC/MASKCN in case of any of the operands being 0.
-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)>;
+def : Pat<(select GPR:$rc, GPR:$rs1, (i64 0)),
+ (VT_MASKC GPR:$rs1, GPR:$rc)>;
+def : Pat<(select GPR:$rc, (i64 0), GPR:$rs1),
+ (VT_MASKCN GPR:$rs1, GPR:$rc)>;
+
+def : Pat<(select (riscv_setne GPR:$rc), GPR:$rs1, (i64 0)),
+ (VT_MASKC GPR:$rs1, GPR:$rc)>;
+def : Pat<(select (riscv_seteq GPR:$rc), GPR:$rs1, (i64 0)),
+ (VT_MASKCN GPR:$rs1, GPR:$rc)>;
+def : Pat<(select (riscv_setne GPR:$rc), (i64 0), GPR:$rs1),
+ (VT_MASKCN GPR:$rs1, GPR:$rc)>;
+def : Pat<(select (riscv_seteq GPR:$rc), (i64 0), GPR:$rs1),
+ (VT_MASKC GPR:$rs1, GPR:$rc)>;
// Conditional AND operation patterns.
def : Pat<(i64 (select GPR:$rc, (and GPR:$rs1, GPR:$rs2), GPR:$rs1)),
def : Pat<(i64 (select GPR:$rc, GPR:$rs1, GPR:$rs2)),
(OR (VT_MASKC $rs1, $rc), (VT_MASKCN $rs2, $rc))>;
-def : Pat<(i64 (select (i64 (setne GPR:$rc, (i64 0))), GPR:$rs1, GPR:$rs2)),
+def : Pat<(i64 (select (riscv_setne GPR:$rc), GPR:$rs1, GPR:$rs2)),
(OR (VT_MASKC GPR:$rs1, GPR:$rc), (VT_MASKCN GPR:$rs2, GPR:$rc))>;
-def : Pat<(i64 (select (i64 (seteq GPR:$rc, (i64 0))), GPR:$rs2, GPR:$rs1)),
+def : Pat<(i64 (select (riscv_seteq GPR:$rc), GPR:$rs2, GPR:$rs1)),
(OR (VT_MASKC GPR:$rs1, GPR:$rc), (VT_MASKCN GPR:$rs2, GPR:$rc))>;
-def : Pat<(i64 (select (i64 (setne GPR:$x, simm12_plus1:$y)), GPR:$rs1, GPR:$rs2)),
- (OR (VT_MASKC GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y))),
- (VT_MASKCN GPR:$rs2, (ADDI GPR:$x, (NegImm simm12_plus1:$y))))>;
-def : Pat<(i64 (select (i64 (seteq GPR:$x, simm12_plus1:$y)), GPR:$rs2, GPR:$rs1)),
- (OR (VT_MASKC GPR:$rs1, (ADDI GPR:$x, (NegImm simm12_plus1:$y))),
- (VT_MASKCN GPR:$rs2, (ADDI GPR:$x, (NegImm simm12_plus1:$y))))>;
-
-def : Pat<(i64 (select (i64 (setne GPR:$x, (i64 -2048))), GPR:$rs1, GPR:$rs2)),
- (OR (VT_MASKC GPR:$rs1, (XORI GPR:$x, -2048)),
- (VT_MASKCN GPR:$rs2, (XORI GPR:$x, -2048)))>;
-def : Pat<(i64 (select (i64 (seteq GPR:$x, (i64 -2048))), GPR:$rs2, GPR:$rs1)),
- (OR (VT_MASKC GPR:$rs1, (XORI GPR:$x, -2048)),
- (VT_MASKCN GPR:$rs2, (XORI GPR:$x, -2048)))>;
-
-def : Pat<(i64 (select (i64 (setne GPR:$x, GPR:$y)), GPR:$rs1, GPR:$rs2)),
- (OR (VT_MASKC GPR:$rs1, (XOR GPR:$x, GPR:$y)),
- (VT_MASKCN GPR:$rs2, (XOR GPR:$x, GPR:$y)))>;
-def : Pat<(i64 (select (i64 (seteq GPR:$x, GPR:$y)), GPR:$rs2, GPR:$rs1)),
- (OR (VT_MASKC GPR:$rs1, (XOR GPR:$x, GPR:$y)),
- (VT_MASKCN GPR:$rs2, (XOR GPR:$x, GPR:$y)))>;
-
} // Predicates = [IsRV64, HasVendorXVentanaCondOps]