-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[RISCV] Add codegen support for ri.vinsert.v.x and ri.vextract.x.v #136708
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
84ff8d8
e29f829
7122db2
9c0b760
c37b00f
92e2acb
874a86a
e98da02
011538e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6935,7 +6935,7 @@ static bool hasPassthruOp(unsigned Opcode) { | |
| Opcode <= RISCVISD::LAST_STRICTFP_OPCODE && | ||
| "not a RISC-V target specific op"); | ||
| static_assert( | ||
| RISCVISD::LAST_VL_VECTOR_OP - RISCVISD::FIRST_VL_VECTOR_OP == 132 && | ||
| RISCVISD::LAST_VL_VECTOR_OP - RISCVISD::FIRST_VL_VECTOR_OP == 133 && | ||
| RISCVISD::LAST_STRICTFP_OPCODE - RISCVISD::FIRST_STRICTFP_OPCODE == 21 && | ||
| "adding target specific op should update this function"); | ||
| if (Opcode >= RISCVISD::ADD_VL && Opcode <= RISCVISD::VFMAX_VL) | ||
|
|
@@ -6959,7 +6959,7 @@ static bool hasMaskOp(unsigned Opcode) { | |
| Opcode <= RISCVISD::LAST_STRICTFP_OPCODE && | ||
| "not a RISC-V target specific op"); | ||
| static_assert( | ||
| RISCVISD::LAST_VL_VECTOR_OP - RISCVISD::FIRST_VL_VECTOR_OP == 132 && | ||
| RISCVISD::LAST_VL_VECTOR_OP - RISCVISD::FIRST_VL_VECTOR_OP == 133 && | ||
| RISCVISD::LAST_STRICTFP_OPCODE - RISCVISD::FIRST_STRICTFP_OPCODE == 21 && | ||
| "adding target specific op should update this function"); | ||
| if (Opcode >= RISCVISD::TRUNCATE_VECTOR_VL && Opcode <= RISCVISD::SETCC_VL) | ||
|
|
@@ -9567,6 +9567,13 @@ getSmallestVTForIndex(MVT VecVT, unsigned MaxIdx, SDLoc DL, SelectionDAG &DAG, | |
| return SmallerVT; | ||
| } | ||
|
|
||
| static bool isValidInsertExtractIndex(SDValue Idx) { | ||
| auto *IdxC = dyn_cast<ConstantSDNode>(Idx); | ||
| if (!IdxC || isNullConstant(Idx)) | ||
| return false; | ||
| return IdxC->getZExtValue() < 32; | ||
preames marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| // Custom-legalize INSERT_VECTOR_ELT so that the value is inserted into the | ||
| // first position of a vector, and that vector is slid up to the insert index. | ||
| // By limiting the active vector length to index+1 and merging with the | ||
|
|
@@ -9677,6 +9684,26 @@ SDValue RISCVTargetLowering::lowerINSERT_VECTOR_ELT(SDValue Op, | |
| return Vec; | ||
| return convertFromScalableVector(VecVT, Vec, DAG, Subtarget); | ||
| } | ||
|
|
||
| // Use ri.vinsert.v.x if available. | ||
| if (Subtarget.hasVendorXRivosVisni() && VecVT.isInteger() && | ||
| isValidInsertExtractIndex(Idx)) { | ||
preames marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| unsigned Policy = RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED; | ||
| if (VecVT.isFixedLengthVector() && isa<ConstantSDNode>(Idx) && | ||
| Idx->getAsZExtVal() + 1 == VecVT.getVectorNumElements()) | ||
| Policy = RISCVVType::TAIL_AGNOSTIC; | ||
|
||
| SDValue PolicyOp = | ||
| DAG.getTargetConstant(Policy, DL, Subtarget.getXLenVT()); | ||
| Vec = DAG.getNode(RISCVISD::RI_VINSERT_VL, DL, ContainerVT, Vec, Val, Idx, | ||
preames marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| VL, PolicyOp); | ||
| if (AlignedIdx) | ||
| Vec = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, OrigContainerVT, OrigVec, | ||
| Vec, AlignedIdx); | ||
| if (!VecVT.isFixedLengthVector()) | ||
| return Vec; | ||
| return convertFromScalableVector(VecVT, Vec, DAG, Subtarget); | ||
| } | ||
|
|
||
| ValInVec = lowerScalarInsert(Val, VL, ContainerVT, DL, DAG, Subtarget); | ||
| } else { | ||
| // On RV32, i64-element vectors must be specially handled to place the | ||
|
|
@@ -9876,6 +9903,14 @@ SDValue RISCVTargetLowering::lowerEXTRACT_VECTOR_ELT(SDValue Op, | |
| } | ||
| } | ||
|
|
||
| // Use ri.vextract.x.v if available. | ||
| // TODO: Avoid index 0 and just use the vmv.x.s | ||
| if (Subtarget.hasVendorXRivosVisni() && EltVT.isInteger() && | ||
| isValidInsertExtractIndex(Idx)) { | ||
| SDValue Elt = DAG.getNode(RISCVISD::RI_VEXTRACT, DL, XLenVT, Vec, Idx); | ||
| return DAG.getNode(ISD::TRUNCATE, DL, EltVT, Elt); | ||
| } | ||
|
|
||
| // If after narrowing, the required slide is still greater than LMUL2, | ||
| // fallback to generic expansion and go through the stack. This is done | ||
| // for a subtle reason: extracting *all* elements out of a vector is | ||
|
|
@@ -22253,11 +22288,13 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const { | |
| NODE_NAME_CASE(VZEXT_VL) | ||
| NODE_NAME_CASE(VCPOP_VL) | ||
| NODE_NAME_CASE(VFIRST_VL) | ||
| NODE_NAME_CASE(RI_VINSERT_VL) | ||
| NODE_NAME_CASE(RI_VZIPEVEN_VL) | ||
| NODE_NAME_CASE(RI_VZIPODD_VL) | ||
| NODE_NAME_CASE(RI_VZIP2A_VL) | ||
| NODE_NAME_CASE(RI_VUNZIP2A_VL) | ||
| NODE_NAME_CASE(RI_VUNZIP2B_VL) | ||
| NODE_NAME_CASE(RI_VEXTRACT) | ||
| NODE_NAME_CASE(READ_CSR) | ||
| NODE_NAME_CASE(WRITE_CSR) | ||
| NODE_NAME_CASE(SWAP_CSR) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -94,6 +94,14 @@ static bool isFloatScalarMoveOrScalarSplatInstr(const MachineInstr &MI) { | |
| } | ||
| } | ||
|
|
||
| static bool isVInsertInstr(const MachineInstr &MI) { | ||
| return RISCV::getRVVMCOpcode(MI.getOpcode()) == RISCV::RI_VINSERT; | ||
| } | ||
|
|
||
| static bool isVExtractInstr(const MachineInstr &MI) { | ||
| return RISCV::getRVVMCOpcode(MI.getOpcode()) == RISCV::RI_VEXTRACT; | ||
| } | ||
|
|
||
| static bool isScalarExtractInstr(const MachineInstr &MI) { | ||
| switch (RISCV::getRVVMCOpcode(MI.getOpcode())) { | ||
| default: | ||
|
|
@@ -538,6 +546,18 @@ DemandedFields getDemanded(const MachineInstr &MI, const RISCVSubtarget *ST) { | |
| Res.MaskPolicy = false; | ||
| } | ||
|
|
||
| if (isVExtractInstr(MI)) { | ||
| assert(!RISCVII::hasVLOp(TSFlags)); | ||
| // TODO: LMUL can be any larger value (without cost) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This would be an interesting optimisation. I could imagine us having more demanded LMUL types e.g.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In a sense, we sort of already have this for vmv.s.x and vmv.x.s, it's just that the MX value is the smallest legal LMUL, and thus GTE becomes any LMUL. |
||
| Res.TailPolicy = false; | ||
| Res.MaskPolicy = false; | ||
| } | ||
|
|
||
| if (isVInsertInstr(MI)) { | ||
| // TODO: LMUL can be any larger value (without cost) | ||
| Res.MaskPolicy = false; | ||
preames marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| return Res; | ||
| } | ||
|
|
||
|
|
@@ -1085,7 +1105,7 @@ RISCVInsertVSETVLI::computeInfoForInstr(const MachineInstr &MI) const { | |
| InstrInfo.setAVLRegDef(VNI, VLOp.getReg()); | ||
| } | ||
| } else { | ||
| assert(isScalarExtractInstr(MI)); | ||
| assert(isScalarExtractInstr(MI) || isVExtractInstr(MI)); | ||
| // Pick a random value for state tracking purposes, will be ignored via | ||
| // the demanded fields mechanism | ||
| InstrInfo.setAVLImm(1); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -125,3 +125,58 @@ def RI_VEXTRACT : CustomRivosXVI<0b010111, OPMVV, (outs GPR:$rd), | |
| (ins VR:$vs2, uimm5:$imm), | ||
| "ri.vextract.x.v", "$rd, $vs2, $imm">; | ||
| } | ||
|
|
||
|
|
||
| def ri_vextract : SDNode<"RISCVISD::RI_VEXTRACT", | ||
| SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVec<1>, | ||
preames marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| SDTCisInt<2>, | ||
| SDTCisInt<1>]>>; | ||
|
|
||
| def ri_vinsert_vl : SDNode<"RISCVISD::RI_VINSERT_VL", | ||
| SDTypeProfile<1, 5, [SDTCisSameAs<0, 1>, | ||
preames marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| SDTCisInt<0>, | ||
| SDTCisVT<2, XLenVT>, | ||
| SDTCisVT<3, XLenVT>, | ||
| SDTCisVT<4, XLenVT>]>>; | ||
|
|
||
|
|
||
| let Predicates = [HasVendorXRivosVisni], mayLoad = 0, mayStore = 0, | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not thrilled with this bit of tablegen, if anyone has suggestions on how to improve, please let me know!
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks fine to me, is there anything in particular that you're worried about? |
||
| hasSideEffects = 0, HasSEWOp = 1 in | ||
| foreach m = MxList in { | ||
| defvar mx = m.MX; | ||
| let VLMul = m.value in { | ||
| let BaseInstr = RI_VEXTRACT in | ||
| def PseudoRI_VEXTRACT_ # mx : | ||
| Pseudo<(outs GPR:$rd), (ins m.vrclass:$rs2, uimm6:$idx, ixlenimm:$sew), | ||
preames marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| []>, | ||
| RISCVVPseudo; | ||
|
|
||
| let HasVLOp = 1, BaseInstr = RI_VINSERT, HasVecPolicyOp = 1, | ||
| Constraints = "$rd = $rs1" in | ||
| def PseudoRI_VINSERT_ # mx : | ||
| Pseudo<(outs m.vrclass:$rd), | ||
| (ins m.vrclass:$rs1, GPR:$rs2, uimm5:$idx, AVL:$vl, | ||
| ixlenimm:$sew, ixlenimm:$policy), | ||
| []>, | ||
| RISCVVPseudo; | ||
| } | ||
| } | ||
|
|
||
|
|
||
|
|
||
| foreach vti = AllIntegerVectors in | ||
| let Predicates = GetVTypePredicates<vti>.Predicates in { | ||
| def : Pat<(XLenVT (ri_vextract (vti.Vector vti.RegClass:$vs2), uimm5:$imm)), | ||
| (!cast<Instruction>("PseudoRI_VEXTRACT_" # vti.LMul.MX) | ||
| $vs2, uimm5:$imm, vti.Log2SEW)>; | ||
|
|
||
| def : Pat<(vti.Vector (ri_vinsert_vl (vti.Vector vti.RegClass:$merge), | ||
| vti.ScalarRegClass:$rs1, | ||
| uimm5:$imm, | ||
| VLOpFrag, | ||
| (XLenVT timm:$policy))), | ||
| (!cast<Instruction>("PseudoRI_VINSERT_" # vti.LMul.MX) | ||
| $merge, vti.ScalarRegClass:$rs1, uimm5:$imm, | ||
| GPR:$vl, vti.Log2SEW, (XLenVT timm:$policy))>; | ||
|
|
||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.