@@ -2317,6 +2317,54 @@ static SDValue lowerVECTOR_SHUFFLE_XVPICKOD(const SDLoc &DL, ArrayRef<int> Mask,
23172317 return DAG.getNode (LoongArchISD::VPICKOD, DL, VT, V2, V1);
23182318}
23192319
2320+ // Check if exactly one element of the Mask is replaced by 'Replaced', while
2321+ // all other elements are either 'Base + i' or undef (-1). On success, return
2322+ // the index of the replaced element. Otherwise, just return -1.
2323+ static int checkReplaceOne (ArrayRef<int > Mask, int Base, int Replaced) {
2324+ int MaskSize = Mask.size ();
2325+ int Idx = -1 ;
2326+ for (int i = 0 ; i < MaskSize; ++i) {
2327+ if (Mask[i] == Base + i || Mask[i] == -1 )
2328+ continue ;
2329+ if (Mask[i] != Replaced)
2330+ return -1 ;
2331+ if (Idx == -1 )
2332+ Idx = i;
2333+ else
2334+ return -1 ;
2335+ }
2336+ return Idx;
2337+ }
2338+
2339+ // / Lower VECTOR_SHUFFLE into XVINSVE0 (if possible).
2340+ static SDValue
2341+ lowerVECTOR_SHUFFLE_XVINSVE0 (const SDLoc &DL, ArrayRef<int > Mask, MVT VT,
2342+ SDValue V1, SDValue V2, SelectionDAG &DAG,
2343+ const LoongArchSubtarget &Subtarget) {
2344+ // LoongArch LASX only supports xvinsve0.{w/d}.
2345+ if (VT != MVT::v8i32 && VT != MVT::v8f32 && VT != MVT::v4i64 &&
2346+ VT != MVT::v4f64)
2347+ return SDValue ();
2348+
2349+ MVT GRLenVT = Subtarget.getGRLenVT ();
2350+ int MaskSize = Mask.size ();
2351+ assert (MaskSize == (int )VT.getVectorNumElements () && " Unexpected mask size" );
2352+
2353+ // Case 1: the lowest element of V2 replaces one element in V1.
2354+ int Idx = checkReplaceOne (Mask, 0 , MaskSize);
2355+ if (Idx != -1 )
2356+ return DAG.getNode (LoongArchISD::XVINSVE0, DL, VT, V1, V2,
2357+ DAG.getConstant (Idx, DL, GRLenVT));
2358+
2359+ // Case 2: the lowest element of V1 replaces one element in V2.
2360+ Idx = checkReplaceOne (Mask, MaskSize, 0 );
2361+ if (Idx != -1 )
2362+ return DAG.getNode (LoongArchISD::XVINSVE0, DL, VT, V2, V1,
2363+ DAG.getConstant (Idx, DL, GRLenVT));
2364+
2365+ return SDValue ();
2366+ }
2367+
23202368// / Lower VECTOR_SHUFFLE into XVSHUF (if possible).
23212369static SDValue lowerVECTOR_SHUFFLE_XVSHUF (const SDLoc &DL, ArrayRef<int > Mask,
23222370 MVT VT, SDValue V1, SDValue V2,
@@ -2593,6 +2641,9 @@ static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,
25932641 if ((Result = lowerVECTOR_SHUFFLEAsShift (DL, Mask, VT, V1, V2, DAG, Subtarget,
25942642 Zeroable)))
25952643 return Result;
2644+ if ((Result =
2645+ lowerVECTOR_SHUFFLE_XVINSVE0 (DL, Mask, VT, V1, V2, DAG, Subtarget)))
2646+ return Result;
25962647 if ((Result = lowerVECTOR_SHUFFLEAsByteRotate (DL, Mask, VT, V1, V2, DAG,
25972648 Subtarget)))
25982649 return Result;
@@ -7450,6 +7501,7 @@ const char *LoongArchTargetLowering::getTargetNodeName(unsigned Opcode) const {
74507501 NODE_NAME_CASE (XVPERM)
74517502 NODE_NAME_CASE (XVREPLVE0)
74527503 NODE_NAME_CASE (XVREPLVE0Q)
7504+ NODE_NAME_CASE (XVINSVE0)
74537505 NODE_NAME_CASE (VPICK_SEXT_ELT)
74547506 NODE_NAME_CASE (VPICK_ZEXT_ELT)
74557507 NODE_NAME_CASE (VREPLVE)
0 commit comments