[llvm] [VP][RISCV] Add llvm.experimental.vp.reverse. (PR #70405)
Luke Lau via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 3 03:24:52 PDT 2023
================
@@ -10223,6 +10231,129 @@ SDValue RISCVTargetLowering::lowerVPFPIntConvOp(SDValue Op,
return convertFromScalableVector(VT, Result, DAG, Subtarget);
}
+SDValue
+RISCVTargetLowering::lowerVPReverseExperimental(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ MVT VT = Op.getSimpleValueType();
+ MVT XLenVT = Subtarget.getXLenVT();
+
+ SDValue Op1 = Op.getOperand(0);
+ SDValue Mask = Op.getOperand(1);
+ SDValue EVL = Op.getOperand(2);
+
+ MVT ContainerVT = VT;
+ if (VT.isFixedLengthVector()) {
+ ContainerVT = getContainerForFixedLengthVector(VT);
+ Op1 = convertToScalableVector(ContainerVT, Op1, DAG, Subtarget);
+ MVT MaskVT = getMaskTypeFor(ContainerVT);
+ Mask = convertToScalableVector(MaskVT, Mask, DAG, Subtarget);
+ }
+
+ MVT GatherVT = ContainerVT;
+ MVT IndicesVT = ContainerVT.changeVectorElementTypeToInteger();
+ // Check if we are working with mask vectors
+ bool IsMaskVector = ContainerVT.getVectorElementType() == MVT::i1;
+ if (IsMaskVector) {
+ GatherVT = IndicesVT = ContainerVT.changeVectorElementType(MVT::i8);
+
+ // Expand input operand
+ SDValue SplatOne = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, IndicesVT,
+ DAG.getUNDEF(IndicesVT),
+ DAG.getConstant(1, DL, XLenVT), EVL);
+ SDValue SplatZero = DAG.getNode(RISCVISD::VMV_V_X_VL, DL, IndicesVT,
+ DAG.getUNDEF(IndicesVT),
+ DAG.getConstant(0, DL, XLenVT), EVL);
+ Op1 = DAG.getNode(RISCVISD::VSELECT_VL, DL, IndicesVT, Op1, SplatOne,
+ SplatZero, EVL);
+ }
+
+ unsigned EltSize = GatherVT.getScalarSizeInBits();
+ unsigned MinSize = GatherVT.getSizeInBits().getKnownMinValue();
+ unsigned VectorBitsMax = Subtarget.getRealMaxVLen();
+ unsigned MaxVLMAX =
+ RISCVTargetLowering::computeVLMAX(VectorBitsMax, EltSize, MinSize);
+
+ unsigned GatherOpc = RISCVISD::VRGATHER_VV_VL;
+ // If this is SEW=8 and VLMAX is unknown or more than 256, we need
+ // to use vrgatherei16.vv.
+ // TODO: It's also possible to use vrgatherei16.vv for other types to
+ // decrease register width for the index calculation.
+ // NOTE: This code assumes VLMAX <= 65536 for LMUL=8 SEW=16.
+ if (MaxVLMAX > 256 && EltSize == 8) {
+ // If this is LMUL=8, we have to split before using vrgatherei16.vv.
+ // Split the vector in half and reverse each half using a full register
+ // reverse.
+ // Swap the halves and concatenate them.
+ // Slide the concatenated result by (VLMax - VL).
+ if (MinSize == (8 * RISCV::RVVBitsPerBlock)) {
+ auto [LoVT, HiVT] = DAG.GetSplitDestVTs(GatherVT);
+ auto [Lo, Hi] = DAG.SplitVector(Op1, DL);
+
+ SDValue LoRev = DAG.getNode(ISD::VECTOR_REVERSE, DL, LoVT, Lo);
+ SDValue HiRev = DAG.getNode(ISD::VECTOR_REVERSE, DL, HiVT, Hi);
+
+ // Reassemble the low and high pieces reversed.
+ // NOTE: this Result is unmasked (because we do not need masks for
+ // shuffles). If in the future this has to change, we can use a SELECT_VL
+ // between Result and UNDEF using the mask originally passed to VP_REVERSE
+ SDValue Result =
+ DAG.getNode(ISD::CONCAT_VECTORS, DL, GatherVT, HiRev, LoRev);
+
+ // Slide off any elements from past EVL that were reversed into the low
+ // elements.
+ unsigned MinElts = GatherVT.getVectorMinNumElements();
+ SDValue VLMax = DAG.getNode(ISD::VSCALE, DL, XLenVT,
+ DAG.getConstant(MinElts, DL, XLenVT));
+ SDValue Diff = DAG.getNode(ISD::SUB, DL, XLenVT, VLMax, EVL);
+
+ SDValue TrueMask = getAllOnesMask(ContainerVT, EVL, DL, DAG);
+ Result =
+ getVSlidedown(DAG, Subtarget, DL, GatherVT, DAG.getUNDEF(GatherVT),
+ Result, Diff, TrueMask, EVL);
----------------
lukel97 wrote:
Does using the input mask here like
```suggestion
Result, Diff, Mask, EVL);
```
work? So we get "poison" in the expected lanes
https://github.com/llvm/llvm-project/pull/70405
More information about the llvm-commits
mailing list