diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp index 7e37bbd652114..85c28025fdc98 100644 --- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp @@ -31,6 +31,7 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/KnownBits.h" #include "llvm/Support/MathExtras.h" +#include using namespace llvm; @@ -543,6 +544,37 @@ SDValue LoongArchTargetLowering::lowerBITREVERSE(SDValue Op, } } +// Widen element type to get a new mask value (if possible). +// For example: +// shufflevector <4 x i32> %a, <4 x i32> %b, +// <4 x i32> +// is equivalent to: +// shufflevector <2 x i64> %a, <2 x i64> %b, <2 x i32> +// can be lowered to: +// VPACKOD_D vr0, vr0, vr1 +static SDValue widenShuffleMask(const SDLoc &DL, ArrayRef Mask, MVT VT, + SDValue V1, SDValue V2, SelectionDAG &DAG) { + unsigned EltBits = VT.getScalarSizeInBits(); + + if (EltBits > 32 || EltBits == 1) + return SDValue(); + + SmallVector NewMask; + if (widenShuffleMaskElts(Mask, NewMask)) { + MVT NewEltVT = VT.isFloatingPoint() ? MVT::getFloatingPointVT(EltBits * 2) + : MVT::getIntegerVT(EltBits * 2); + MVT NewVT = MVT::getVectorVT(NewEltVT, VT.getVectorNumElements() / 2); + if (DAG.getTargetLoweringInfo().isTypeLegal(NewVT)) { + SDValue NewV1 = DAG.getBitcast(NewVT, V1); + SDValue NewV2 = DAG.getBitcast(NewVT, V2); + return DAG.getBitcast( + VT, DAG.getVectorShuffle(NewVT, DL, NewV1, NewV2, NewMask)); + } + } + + return SDValue(); +} + /// Attempts to match a shuffle mask against the VBSLL, VBSRL, VSLLI and VSRLI /// instruction. // The funciton matches elements from one of the input vector shuffled to the @@ -1365,6 +1397,8 @@ static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef Mask, MVT VT, return Result; if ((Result = lowerVECTOR_SHUFFLEAsByteRotate(DL, Mask, VT, V1, V2, DAG))) return Result; + if (SDValue NewShuffle = widenShuffleMask(DL, Mask, VT, V1, V2, DAG)) + return NewShuffle; if ((Result = lowerVECTOR_SHUFFLE_VSHUF(DL, Mask, VT, V1, V2, DAG))) return Result; return SDValue(); @@ -1803,6 +1837,8 @@ static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef Mask, MVT VT, return Result; if ((Result = lowerVECTOR_SHUFFLEAsByteRotate(DL, NewMask, VT, V1, V2, DAG))) return Result; + if (SDValue NewShuffle = widenShuffleMask(DL, NewMask, VT, V1, V2, DAG)) + return NewShuffle; if ((Result = lowerVECTOR_SHUFFLE_XVSHUF(DL, NewMask, VT, V1, V2, DAG))) return Result;