[RISCV][VP] Add basic RVV codegen for vp.icmp

This patch adds the minimum required to successfully lower vp.icmp via
the new ISD::VP_SETCC node to RVV instructions.

Regular ISD::SETCC goes through a lot of canonicalization which targets
may rely on which has not hereto been ported to VP_SETCC. It also
supports expansion of individual condition codes and a non-boolean
return type. Support for all of that will follow in later patches.

In the case of RVV this largely isn't a problem as the vector integer
comparison instructions are plentiful enough that it can lower all
VP_SETCC nodes on legal integer vectors except for boolean vectors,
which regular SETCC folds away immediately into logical operations.

Floating-point VP_SETCC operations aren't as well supported in RVV and
the backend relies on condition code expansion, so support for those
operations will come in later patches.

Portions of this code were taken from the VP reference patches.

Reviewed By: craig.topper

Differential Revision: https://reviews.llvm.org/D122743
This commit is contained in:
Fraser Cormack 2022-03-30 17:01:30 +01:00
parent 324ac838ae
commit 6be5e875be
8 changed files with 5882 additions and 18 deletions

View file

@ -1079,6 +1079,18 @@ public:
return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond));
}
/// Helper function to make it easier to build VP_SETCCs if you just have an
/// ISD::CondCode instead of an SDValue.
SDValue getSetCCVP(const SDLoc &DL, EVT VT, SDValue LHS, SDValue RHS,
ISD::CondCode Cond, SDValue Mask, SDValue EVL) {
assert(LHS.getValueType().isVector() && RHS.getValueType().isVector() &&
"Cannot compare scalars");
assert(Cond != ISD::SETCC_INVALID &&
"Cannot create a setCC of an invalid node.");
return getNode(ISD::VP_SETCC, DL, VT, LHS, RHS, getCondCode(Cond), Mask,
EVL);
}
/// Helper function to make it easier to build Select's if you just have
/// operands and don't want to check for vector.
SDValue getSelect(const SDLoc &DL, EVT VT, SDValue Cond, SDValue LHS,

View file

@ -309,10 +309,14 @@ VP_PROPERTY_CONSTRAINEDFP(0, 1, experimental_constrained_fcmp)
END_REGISTER_VP(vp_fcmp, VP_FCMP)
// llvm.vp.icmp(x,y,cc,mask,vlen)
BEGIN_REGISTER_VP(vp_icmp, 3, 4, VP_ICMP, -1)
BEGIN_REGISTER_VP_INTRINSIC(vp_icmp, 3, 4)
VP_PROPERTY_FUNCTIONAL_OPC(ICmp)
VP_PROPERTY_CMP(2, false)
END_REGISTER_VP(vp_icmp, VP_ICMP)
END_REGISTER_VP_INTRINSIC(vp_icmp)
// VP_SETCC (ISel only)
BEGIN_REGISTER_VP_SDNODE(VP_SETCC, -1, vp_setcc, 3, 4)
END_REGISTER_VP_SDNODE(VP_SETCC)
///// } Comparisons

View file

@ -1033,14 +1033,18 @@ void SelectionDAGLegalize::LegalizeOp(SDNode *Node) {
case ISD::STRICT_FSETCC:
case ISD::STRICT_FSETCCS:
case ISD::SETCC:
case ISD::VP_SETCC:
case ISD::BR_CC: {
unsigned CCOperand = Node->getOpcode() == ISD::SELECT_CC ? 4 :
Node->getOpcode() == ISD::STRICT_FSETCC ? 3 :
Node->getOpcode() == ISD::STRICT_FSETCCS ? 3 :
Node->getOpcode() == ISD::SETCC ? 2 : 1;
unsigned CompareOperand = Node->getOpcode() == ISD::BR_CC ? 2 :
Node->getOpcode() == ISD::STRICT_FSETCC ? 1 :
Node->getOpcode() == ISD::STRICT_FSETCCS ? 1 : 0;
unsigned Opc = Node->getOpcode();
unsigned CCOperand = Opc == ISD::SELECT_CC ? 4
: Opc == ISD::STRICT_FSETCC ? 3
: Opc == ISD::STRICT_FSETCCS ? 3
: (Opc == ISD::SETCC || Opc == ISD::VP_SETCC) ? 2
: 1;
unsigned CompareOperand = Opc == ISD::BR_CC ? 2
: Opc == ISD::STRICT_FSETCC ? 1
: Opc == ISD::STRICT_FSETCCS ? 1
: 0;
MVT OpVT = Node->getOperand(CompareOperand).getSimpleValueType();
ISD::CondCode CCCode =
cast<CondCodeSDNode>(Node->getOperand(CCOperand))->get();

View file

@ -7321,7 +7321,12 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic(
static unsigned getISDForVPIntrinsic(const VPIntrinsic &VPIntrin) {
Optional<unsigned> ResOPC;
switch (VPIntrin.getIntrinsicID()) {
auto IID = VPIntrin.getIntrinsicID();
// vp.fcmp and vp.icmp are handled specially
if (IID == Intrinsic::vp_fcmp || IID == Intrinsic::vp_icmp)
return ISD::VP_SETCC;
switch (IID) {
#define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
#define BEGIN_REGISTER_VP_SDNODE(VPSD, ...) ResOPC = ISD::VPSD;
#define END_REGISTER_VP_INTRINSIC(VPID) break;
@ -7504,18 +7509,56 @@ void SelectionDAGBuilder::visitVPStridedStore(
setValue(&VPIntrin, ST);
}
void SelectionDAGBuilder::visitVPCmp(const VPCmpIntrinsic &VPIntrin) {
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
SDLoc DL = getCurSDLoc();
ISD::CondCode Condition;
CmpInst::Predicate CondCode = VPIntrin.getPredicate();
bool IsFP = VPIntrin.getOperand(0)->getType()->isFPOrFPVectorTy();
if (IsFP) {
// FIXME: Regular fcmps are FPMathOperators which may have fast-math (nnan)
// flags, but calls that don't return floating-point types can't be
// FPMathOperators, like vp.fcmp. This affects constrained fcmp too.
Condition = getFCmpCondCode(CondCode);
if (TM.Options.NoNaNsFPMath)
Condition = getFCmpCodeWithoutNaN(Condition);
} else {
Condition = getICmpCondCode(CondCode);
}
SDValue Op1 = getValue(VPIntrin.getOperand(0));
SDValue Op2 = getValue(VPIntrin.getOperand(1));
// #2 is the condition code
SDValue MaskOp = getValue(VPIntrin.getOperand(3));
SDValue EVL = getValue(VPIntrin.getOperand(4));
MVT EVLParamVT = TLI.getVPExplicitVectorLengthTy();
assert(EVLParamVT.isScalarInteger() && EVLParamVT.bitsGE(MVT::i32) &&
"Unexpected target EVL type");
EVL = DAG.getNode(ISD::ZERO_EXTEND, DL, EVLParamVT, EVL);
EVT DestVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
VPIntrin.getType());
setValue(&VPIntrin,
DAG.getSetCCVP(DL, DestVT, Op1, Op2, Condition, MaskOp, EVL));
}
void SelectionDAGBuilder::visitVectorPredicationIntrinsic(
const VPIntrinsic &VPIntrin) {
SDLoc DL = getCurSDLoc();
unsigned Opcode = getISDForVPIntrinsic(VPIntrin);
auto IID = VPIntrin.getIntrinsicID();
if (const auto *CmpI = dyn_cast<VPCmpIntrinsic>(&VPIntrin))
return visitVPCmp(*CmpI);
SmallVector<EVT, 4> ValueVTs;
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
ComputeValueVTs(TLI, DAG.getDataLayout(), VPIntrin.getType(), ValueVTs);
SDVTList VTs = DAG.getVTList(ValueVTs);
auto EVLParamPos =
VPIntrinsic::getVectorLengthParamPos(VPIntrin.getIntrinsicID());
auto EVLParamPos = VPIntrinsic::getVectorLengthParamPos(IID);
MVT EVLParamVT = TLI.getVPExplicitVectorLengthTy();
assert(EVLParamVT.isScalarInteger() && EVLParamVT.bitsGE(MVT::i32) &&

View file

@ -575,6 +575,7 @@ private:
SmallVectorImpl<SDValue> &OpValues);
void visitVPStridedStore(const VPIntrinsic &VPIntrin,
SmallVectorImpl<SDValue> &OpValues);
void visitVPCmp(const VPCmpIntrinsic &VPIntrin);
void visitVectorPredicationIntrinsic(const VPIntrinsic &VPIntrin);
void visitVAStart(const CallInst &I);

View file

@ -491,14 +491,17 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
ISD::VP_REDUCE_OR, ISD::VP_REDUCE_XOR, ISD::VP_REDUCE_SMAX,
ISD::VP_REDUCE_SMIN, ISD::VP_REDUCE_UMAX, ISD::VP_REDUCE_UMIN,
ISD::VP_MERGE, ISD::VP_SELECT, ISD::VP_FPTOSI,
ISD::VP_FPTOUI};
ISD::VP_FPTOUI, ISD::VP_SETCC};
static const unsigned FloatingPointVPOps[] = {
ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
ISD::VP_FDIV, ISD::VP_FNEG, ISD::VP_FMA,
ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD, ISD::VP_REDUCE_FMIN,
ISD::VP_REDUCE_FMAX, ISD::VP_MERGE, ISD::VP_SELECT,
ISD::VP_SITOFP, ISD::VP_UITOFP};
ISD::VP_FADD, ISD::VP_FSUB,
ISD::VP_FMUL, ISD::VP_FDIV,
ISD::VP_FNEG, ISD::VP_FMA,
ISD::VP_REDUCE_FADD, ISD::VP_REDUCE_SEQ_FADD,
ISD::VP_REDUCE_FMIN, ISD::VP_REDUCE_FMAX,
ISD::VP_MERGE, ISD::VP_SELECT,
ISD::VP_SITOFP, ISD::VP_UITOFP,
ISD::VP_SETCC};
if (!Subtarget.is64Bit()) {
// We must custom-lower certain vXi64 operations on RV32 due to the vector
@ -854,6 +857,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::VP_FPTOSI, VT, Custom);
setOperationAction(ISD::VP_FPTOUI, VT, Custom);
setOperationAction(ISD::VP_SETCC, VT, Custom);
continue;
}
@ -3697,6 +3701,8 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
return lowerVPFPIntConvOp(Op, DAG, RISCVISD::SINT_TO_FP_VL);
case ISD::VP_UITOFP:
return lowerVPFPIntConvOp(Op, DAG, RISCVISD::UINT_TO_FP_VL);
case ISD::VP_SETCC:
return lowerVPOp(Op, DAG, RISCVISD::SETCC_VL);
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff