[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:
parent
324ac838ae
commit
6be5e875be
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) &&
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue