@@ -662,7 +662,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
662662 ISD::VP_FP_TO_UINT, ISD::VP_SETCC, ISD::VP_SIGN_EXTEND,
663663 ISD::VP_ZERO_EXTEND, ISD::VP_TRUNCATE, ISD::VP_SMIN,
664664 ISD::VP_SMAX, ISD::VP_UMIN, ISD::VP_UMAX,
665- ISD::VP_ABS};
665+ ISD::VP_ABS, ISD::EXPERIMENTAL_VP_REVERSE };
666666
667667 static const unsigned FloatingPointVPOps[] = {
668668 ISD::VP_FADD, ISD::VP_FSUB, ISD::VP_FMUL,
@@ -674,7 +674,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
674674 ISD::VP_SQRT, ISD::VP_FMINNUM, ISD::VP_FMAXNUM,
675675 ISD::VP_FCEIL, ISD::VP_FFLOOR, ISD::VP_FROUND,
676676 ISD::VP_FROUNDEVEN, ISD::VP_FCOPYSIGN, ISD::VP_FROUNDTOZERO,
677- ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS};
677+ ISD::VP_FRINT, ISD::VP_FNEARBYINT, ISD::VP_IS_FPCLASS,
678+ ISD::EXPERIMENTAL_VP_REVERSE};
678679
679680 static const unsigned IntegerVecReduceOps[] = {
680681 ISD::VECREDUCE_ADD, ISD::VECREDUCE_AND, ISD::VECREDUCE_OR,
@@ -759,6 +760,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
759760
760761 setOperationAction(ISD::VECTOR_REVERSE, VT, Custom);
761762
763+ setOperationAction(ISD::EXPERIMENTAL_VP_REVERSE, VT, Custom);
764+
762765 setOperationPromotedToType(
763766 ISD::VECTOR_SPLICE, VT,
764767 MVT::getVectorVT(MVT::i8, VT.getVectorElementCount()));
@@ -1129,6 +1132,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
11291132 setOperationAction({ISD::VP_FP_TO_SINT, ISD::VP_FP_TO_UINT,
11301133 ISD::VP_SETCC, ISD::VP_TRUNCATE},
11311134 VT, Custom);
1135+
1136+ setOperationAction(ISD::EXPERIMENTAL_VP_REVERSE, VT, Custom);
11321137 continue;
11331138 }
11341139
@@ -1383,7 +1388,8 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
13831388 setTargetDAGCombine({ISD::FCOPYSIGN, ISD::MGATHER, ISD::MSCATTER,
13841389 ISD::VP_GATHER, ISD::VP_SCATTER, ISD::SRA, ISD::SRL,
13851390 ISD::SHL, ISD::STORE, ISD::SPLAT_VECTOR,
1386- ISD::BUILD_VECTOR, ISD::CONCAT_VECTORS});
1391+ ISD::BUILD_VECTOR, ISD::CONCAT_VECTORS,
1392+ ISD::EXPERIMENTAL_VP_REVERSE});
13871393 if (Subtarget.hasVendorXTHeadMemPair())
13881394 setTargetDAGCombine({ISD::LOAD, ISD::STORE});
13891395 if (Subtarget.useRVVForFixedLengthVectors())
@@ -6518,6 +6524,8 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
65186524 !Subtarget.hasVInstructionsF16()))
65196525 return SplitVPOp(Op, DAG);
65206526 return lowerVectorFTRUNC_FCEIL_FFLOOR_FROUND(Op, DAG, Subtarget);
6527+ case ISD::EXPERIMENTAL_VP_REVERSE:
6528+ return lowerVPReverseExperimental(Op, DAG);
65216529 }
65226530}
65236531
@@ -10378,6 +10386,127 @@ SDValue RISCVTargetLowering::lowerVPFPIntConvOp(SDValue Op,
1037810386 return convertFromScalableVector(VT, Result, DAG, Subtarget);
1037910387}
1038010388
10389+ SDValue
10390+ RISCVTargetLowering::lowerVPReverseExperimental(SDValue Op,
10391+ SelectionDAG &DAG) const {
10392+ SDLoc DL(Op);
10393+ MVT VT = Op.getSimpleValueType();
10394+ MVT XLenVT = Subtarget.getXLenVT();
10395+
10396+ SDValue Op1 = Op.getOperand(0);
10397+ SDValue Mask = Op.getOperand(1);
10398+ SDValue EVL = Op.getOperand(2);
10399+
10400+ MVT ContainerVT = VT;
10401+ if (VT.isFixedLengthVector()) {
10402+ ContainerVT = getContainerForFixedLengthVector(VT);
10403+ Op1 = convertToScalableVector(ContainerVT, Op1, DAG, Subtarget);
10404+ MVT MaskVT = getMaskTypeFor(ContainerVT);
10405+ Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
10406+ }
10407+
10408+ MVT GatherVT = ContainerVT;
10409+ MVT IndicesVT = ContainerVT.changeVectorElementTypeToInteger();
10410+ // Check if we are working with mask vectors
10411+ bool IsMaskVector = ContainerVT.getVectorElementType() == MVT::i1;
10412+ if (IsMaskVector) {
10413+ GatherVT = IndicesVT = ContainerVT.changeVectorElementType(MVT::i8);
10414+
10415+ // Expand input operand
10416+ SDValue SplatOne = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, IndicesVT,
10417+ DAG.getUNDEF(IndicesVT),
10418+ DAG.getConstant(1, DL, XLenVT), EVL);
10419+ SDValue SplatZero = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, IndicesVT,
10420+ DAG.getUNDEF(IndicesVT),
10421+ DAG.getConstant(0, DL, XLenVT), EVL);
10422+ Op1 = DAG.getNode(RISCVISD::VSELECT_VL, DL, IndicesVT, Op1, SplatOne,
10423+ SplatZero, EVL);
10424+ }
10425+
10426+ unsigned EltSize = GatherVT.getScalarSizeInBits();
10427+ unsigned MinSize = GatherVT.getSizeInBits().getKnownMinValue();
10428+ unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
10429+ unsigned MaxVLMAX =
10430+ RISCVTargetLowering::computeVLMAX(VectorBitsMax, EltSize, MinSize);
10431+
10432+ unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
10433+ // If this is SEW=8 and VLMAX is unknown or more than 256, we need
10434+ // to use vrgatherei16.vv.
10435+ // TODO: It's also possible to use vrgatherei16.vv for other types to
10436+ // decrease register width for the index calculation.
10437+ // NOTE: This code assumes VLMAX <= 65536 for LMUL=8 SEW=16.
10438+ if (MaxVLMAX > 256 && EltSize == 8) {
10439+ // If this is LMUL=8, we have to split before using vrgatherei16.vv.
10440+ // Split the vector in half and reverse each half using a full register
10441+ // reverse.
10442+ // Swap the halves and concatenate them.
10443+ // Slide the concatenated result by (VLMax - VL).
10444+ if (MinSize == (8 * RISCV::RVVBitsPerBlock)) {
10445+ auto [LoVT, HiVT] = DAG.GetSplitDestVTs(GatherVT);
10446+ auto [Lo, Hi] = DAG.SplitVector(Op1, DL);
10447+
10448+ SDValue LoRev = DAG.getNode(ISD::VECTOR_REVERSE, DL, LoVT, Lo);
10449+ SDValue HiRev = DAG.getNode(ISD::VECTOR_REVERSE, DL, HiVT, Hi);
10450+
10451+ // Reassemble the low and high pieces reversed.
10452+ // NOTE: this Result is unmasked (because we do not need masks for
10453+ // shuffles). If in the future this has to change, we can use a SELECT_VL
10454+ // between Result and UNDEF using the mask originally passed to VP_REVERSE
10455+ SDValue Result =
10456+ DAG.getNode(ISD::CONCAT_VECTORS, DL, GatherVT, HiRev, LoRev);
10457+
10458+ // Slide off any elements from past EVL that were reversed into the low
10459+ // elements.
10460+ unsigned MinElts = GatherVT.getVectorMinNumElements();
10461+ SDValue VLMax = DAG.getNode(ISD::VSCALE, DL, XLenVT,
10462+ DAG.getConstant(MinElts, DL, XLenVT));
10463+ SDValue Diff = DAG.getNode(ISD::SUB, DL, XLenVT, VLMax, EVL);
10464+
10465+ Result = getVSlidedown(DAG, Subtarget, DL, GatherVT,
10466+ DAG.getUNDEF(GatherVT), Result, Diff, Mask, EVL);
10467+
10468+ if (IsMaskVector) {
10469+ // Truncate Result back to a mask vector
10470+ Result =
10471+ DAG.getNode(RISCVISD::SETCC_VL, DL, ContainerVT,
10472+ {Result, DAG.getConstant(0, DL, GatherVT),
10473+ DAG.getCondCode(ISD::SETNE),
10474+ DAG.getUNDEF(getMaskTypeFor(ContainerVT)), Mask, EVL});
10475+ }
10476+
10477+ if (!VT.isFixedLengthVector())
10478+ return Result;
10479+ return convertFromScalableVector(VT, Result, DAG, Subtarget);
10480+ }
10481+
10482+ // Just promote the int type to i16 which will double the LMUL.
10483+ IndicesVT = MVT::getVectorVT(MVT::i16, IndicesVT.getVectorElementCount());
10484+ GatherOpc = RISCVISD::VRGATHEREI16_VV_VL;
10485+ }
10486+
10487+ SDValue VID = DAG.getNode(RISCVISD::VID_VL, DL, IndicesVT, Mask, EVL);
10488+ SDValue VecLen =
10489+ DAG.getNode(ISD::SUB, DL, XLenVT, EVL, DAG.getConstant(1, DL, XLenVT));
10490+ SDValue VecLenSplat = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, IndicesVT,
10491+ DAG.getUNDEF(IndicesVT), VecLen, EVL);
10492+ SDValue VRSUB = DAG.getNode(RISCVISD::SUB_VL, DL, IndicesVT, VecLenSplat, VID,
10493+ DAG.getUNDEF(IndicesVT), Mask, EVL);
10494+ SDValue Result = DAG.getNode(GatherOpc, DL, GatherVT, Op1, VRSUB,
10495+ DAG.getUNDEF(GatherVT), Mask, EVL);
10496+
10497+ if (IsMaskVector) {
10498+ // Truncate Result back to a mask vector
10499+ Result = DAG.getNode(
10500+ RISCVISD::SETCC_VL, DL, ContainerVT,
10501+ {Result, DAG.getConstant(0, DL, GatherVT), DAG.getCondCode(ISD::SETNE),
10502+ DAG.getUNDEF(getMaskTypeFor(ContainerVT)), Mask, EVL});
10503+ }
10504+
10505+ if (!VT.isFixedLengthVector())
10506+ return Result;
10507+ return convertFromScalableVector(VT, Result, DAG, Subtarget);
10508+ }
10509+
1038110510SDValue RISCVTargetLowering::lowerLogicVPOp(SDValue Op,
1038210511 SelectionDAG &DAG) const {
1038310512 MVT VT = Op.getSimpleValueType();
0 commit comments