mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 04:32:44 +01:00
[VP][SelectionDAG] Add a target-configurable EVL operand type
This patch adds a way for the target to configure the type it uses for the explicit vector length operands of VP SDNodes. The type must be a legal integer type (there is still no target-independent legalization of this operand) and must currently be at least as big as i32, the type used by the IR intrinsics. An implicit zero-extension takes place on targets which choose a larger type. All VP nodes should be created with this type used for the EVL operand. This allows 64-bit RISC-V to avoid custom legalization of all VP nodes, keeping them in their target-independent form for that bit longer. Reviewed By: simoll Differential Revision: https://reviews.llvm.org/D103027
This commit is contained in:
parent
caa14ae743
commit
58a6d02787
@ -393,6 +393,12 @@ public:
|
|||||||
return getPointerTy(DL);
|
return getPointerTy(DL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the type to be used for the EVL/AVL operand of VP nodes:
|
||||||
|
/// ISD::VP_ADD, ISD::VP_SUB, etc. It must be a legal scalar integer type,
|
||||||
|
/// and must be at least as large as i32. The EVL is implicitly zero-extended
|
||||||
|
/// to any larger type.
|
||||||
|
virtual MVT getVPExplicitVectorLengthTy() const { return MVT::i32; }
|
||||||
|
|
||||||
/// This callback is used to inspect load/store instructions and add
|
/// This callback is used to inspect load/store instructions and add
|
||||||
/// target-specific MachineMemOperand flags to them. The default
|
/// target-specific MachineMemOperand flags to them. The default
|
||||||
/// implementation does nothing.
|
/// implementation does nothing.
|
||||||
|
@ -7296,6 +7296,7 @@ static unsigned getISDForVPIntrinsic(const VPIntrinsic &VPIntrin) {
|
|||||||
|
|
||||||
void SelectionDAGBuilder::visitVectorPredicationIntrinsic(
|
void SelectionDAGBuilder::visitVectorPredicationIntrinsic(
|
||||||
const VPIntrinsic &VPIntrin) {
|
const VPIntrinsic &VPIntrin) {
|
||||||
|
SDLoc DL = getCurSDLoc();
|
||||||
unsigned Opcode = getISDForVPIntrinsic(VPIntrin);
|
unsigned Opcode = getISDForVPIntrinsic(VPIntrin);
|
||||||
|
|
||||||
SmallVector<EVT, 4> ValueVTs;
|
SmallVector<EVT, 4> ValueVTs;
|
||||||
@ -7303,12 +7304,22 @@ void SelectionDAGBuilder::visitVectorPredicationIntrinsic(
|
|||||||
ComputeValueVTs(TLI, DAG.getDataLayout(), VPIntrin.getType(), ValueVTs);
|
ComputeValueVTs(TLI, DAG.getDataLayout(), VPIntrin.getType(), ValueVTs);
|
||||||
SDVTList VTs = DAG.getVTList(ValueVTs);
|
SDVTList VTs = DAG.getVTList(ValueVTs);
|
||||||
|
|
||||||
|
auto EVLParamPos =
|
||||||
|
VPIntrinsic::GetVectorLengthParamPos(VPIntrin.getIntrinsicID());
|
||||||
|
|
||||||
|
MVT EVLParamVT = TLI.getVPExplicitVectorLengthTy();
|
||||||
|
assert(EVLParamVT.isScalarInteger() && EVLParamVT.bitsGE(MVT::i32) &&
|
||||||
|
"Unexpected target EVL type");
|
||||||
|
|
||||||
// Request operands.
|
// Request operands.
|
||||||
SmallVector<SDValue, 7> OpValues;
|
SmallVector<SDValue, 7> OpValues;
|
||||||
for (int i = 0; i < (int)VPIntrin.getNumArgOperands(); ++i)
|
for (int I = 0; I < (int)VPIntrin.getNumArgOperands(); ++I) {
|
||||||
OpValues.push_back(getValue(VPIntrin.getArgOperand(i)));
|
auto Op = getValue(VPIntrin.getArgOperand(I));
|
||||||
|
if (I == EVLParamPos)
|
||||||
|
Op = DAG.getNode(ISD::ZERO_EXTEND, DL, EVLParamVT, Op);
|
||||||
|
OpValues.push_back(Op);
|
||||||
|
}
|
||||||
|
|
||||||
SDLoc DL = getCurSDLoc();
|
|
||||||
SDValue Result = DAG.getNode(Opcode, DL, VTs, OpValues);
|
SDValue Result = DAG.getNode(Opcode, DL, VTs, OpValues);
|
||||||
setValue(&VPIntrin, Result);
|
setValue(&VPIntrin, Result);
|
||||||
}
|
}
|
||||||
|
@ -506,12 +506,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
|
|||||||
setOperationAction(ISD::VECREDUCE_UMAX, VT, Custom);
|
setOperationAction(ISD::VECREDUCE_UMAX, VT, Custom);
|
||||||
setOperationAction(ISD::VECREDUCE_UMIN, VT, Custom);
|
setOperationAction(ISD::VECREDUCE_UMIN, VT, Custom);
|
||||||
|
|
||||||
for (unsigned VPOpc : IntegerVPOps) {
|
for (unsigned VPOpc : IntegerVPOps)
|
||||||
setOperationAction(VPOpc, VT, Custom);
|
setOperationAction(VPOpc, VT, Custom);
|
||||||
// RV64 must custom-legalize the i32 EVL parameter.
|
|
||||||
if (Subtarget.is64Bit())
|
|
||||||
setOperationAction(VPOpc, MVT::i32, Custom);
|
|
||||||
}
|
|
||||||
|
|
||||||
setOperationAction(ISD::MLOAD, VT, Custom);
|
setOperationAction(ISD::MLOAD, VT, Custom);
|
||||||
setOperationAction(ISD::MSTORE, VT, Custom);
|
setOperationAction(ISD::MSTORE, VT, Custom);
|
||||||
@ -722,12 +718,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
|
|||||||
setOperationAction(ISD::VECREDUCE_UMAX, VT, Custom);
|
setOperationAction(ISD::VECREDUCE_UMAX, VT, Custom);
|
||||||
setOperationAction(ISD::VECREDUCE_UMIN, VT, Custom);
|
setOperationAction(ISD::VECREDUCE_UMIN, VT, Custom);
|
||||||
|
|
||||||
for (unsigned VPOpc : IntegerVPOps) {
|
for (unsigned VPOpc : IntegerVPOps)
|
||||||
setOperationAction(VPOpc, VT, Custom);
|
setOperationAction(VPOpc, VT, Custom);
|
||||||
// RV64 must custom-legalize the i32 EVL parameter.
|
|
||||||
if (Subtarget.is64Bit())
|
|
||||||
setOperationAction(VPOpc, MVT::i32, Custom);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MVT VT : MVT::fp_fixedlen_vector_valuetypes()) {
|
for (MVT VT : MVT::fp_fixedlen_vector_valuetypes()) {
|
||||||
@ -835,6 +827,10 @@ EVT RISCVTargetLowering::getSetCCResultType(const DataLayout &DL,
|
|||||||
return VT.changeVectorElementTypeToInteger();
|
return VT.changeVectorElementTypeToInteger();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MVT RISCVTargetLowering::getVPExplicitVectorLengthTy() const {
|
||||||
|
return Subtarget.getXLenVT();
|
||||||
|
}
|
||||||
|
|
||||||
bool RISCVTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
|
bool RISCVTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
|
||||||
const CallInst &I,
|
const CallInst &I,
|
||||||
MachineFunction &MF,
|
MachineFunction &MF,
|
||||||
@ -4282,17 +4278,10 @@ SDValue RISCVTargetLowering::lowerVPOp(SDValue Op, SelectionDAG &DAG,
|
|||||||
unsigned RISCVISDOpc) const {
|
unsigned RISCVISDOpc) const {
|
||||||
SDLoc DL(Op);
|
SDLoc DL(Op);
|
||||||
MVT VT = Op.getSimpleValueType();
|
MVT VT = Op.getSimpleValueType();
|
||||||
Optional<unsigned> EVLIdx = ISD::getVPExplicitVectorLengthIdx(Op.getOpcode());
|
|
||||||
|
|
||||||
SmallVector<SDValue, 4> Ops;
|
SmallVector<SDValue, 4> Ops;
|
||||||
MVT XLenVT = Subtarget.getXLenVT();
|
|
||||||
|
|
||||||
for (const auto &OpIdx : enumerate(Op->ops())) {
|
for (const auto &OpIdx : enumerate(Op->ops())) {
|
||||||
SDValue V = OpIdx.value();
|
SDValue V = OpIdx.value();
|
||||||
if ((unsigned)OpIdx.index() == EVLIdx) {
|
|
||||||
Ops.push_back(DAG.getZExtOrTrunc(V, DL, XLenVT));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
assert(!isa<VTSDNode>(V) && "Unexpected VTSDNode node!");
|
assert(!isa<VTSDNode>(V) && "Unexpected VTSDNode node!");
|
||||||
// Pass through operands which aren't fixed-length vectors.
|
// Pass through operands which aren't fixed-length vectors.
|
||||||
if (!V.getValueType().isFixedLengthVector()) {
|
if (!V.getValueType().isFixedLengthVector()) {
|
||||||
|
@ -561,6 +561,8 @@ private:
|
|||||||
|
|
||||||
bool useRVVForFixedLengthVectorVT(MVT VT) const;
|
bool useRVVForFixedLengthVectorVT(MVT VT) const;
|
||||||
|
|
||||||
|
MVT getVPExplicitVectorLengthTy() const override;
|
||||||
|
|
||||||
/// RVV code generation for fixed length vectors does not lower all
|
/// RVV code generation for fixed length vectors does not lower all
|
||||||
/// BUILD_VECTORs. This makes BUILD_VECTOR legalisation a source of stores to
|
/// BUILD_VECTORs. This makes BUILD_VECTOR legalisation a source of stores to
|
||||||
/// merge. However, merging them creates a BUILD_VECTOR that is just as
|
/// merge. However, merging them creates a BUILD_VECTOR that is just as
|
||||||
|
Loading…
Reference in New Issue
Block a user