[llvm] [LoongArch] Refine 256-bit vector_shuffle legalization for LASX (PR #160254)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 23 01:09:58 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-loongarch
Author: ZhaoQi (zhaoqi5)
<details>
<summary>Changes</summary>
---
Full diff: https://github.com/llvm/llvm-project/pull/160254.diff
2 Files Affected:
- (modified) llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp (+40-30)
- (modified) llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fix-xvshuf.ll (+1-1)
``````````diff
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 32baa2d111270..c264a8a0f6a54 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -2060,7 +2060,10 @@ lowerVECTOR_SHUFFLE_XVREPLVEI(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,
const auto &Begin = Mask.begin();
const auto &End = Mask.end();
- unsigned HalfSize = Mask.size() / 2;
+ int HalfSize = Mask.size() / 2;
+
+ if (SplatIndex >= HalfSize)
+ return SDValue();
assert(SplatIndex < (int)Mask.size() && "Out of bounds mask index");
if (fitsRegularPattern<int>(Begin, 1, End - HalfSize, SplatIndex, 0) &&
@@ -2354,7 +2357,7 @@ static SDValue lowerVECTOR_SHUFFLE_XVSHUF(const SDLoc &DL, ArrayRef<int> Mask,
/// cases need to be converted to it for processing.
///
/// This function may modify V1, V2 and Mask
-static void canonicalizeShuffleVectorByLane(
+static bool canonicalizeShuffleVectorByLane(
const SDLoc &DL, MutableArrayRef<int> Mask, MVT VT, SDValue &V1,
SDValue &V2, SelectionDAG &DAG, const LoongArchSubtarget &Subtarget) {
@@ -2378,15 +2381,15 @@ static void canonicalizeShuffleVectorByLane(
preMask = LowLaneTy;
if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](int M) {
- return M < 0 || (M >= 0 && M < HalfSize) ||
- (M >= MaskSize && M < MaskSize + HalfSize);
+ return M < 0 || (M >= HalfSize && M < MaskSize) ||
+ (M >= MaskSize + HalfSize && M < MaskSize * 2);
}))
- postMask = HighLaneTy;
+ postMask = LowLaneTy;
else if (std::all_of(Mask.begin() + HalfSize, Mask.end(), [&](int M) {
- return M < 0 || (M >= HalfSize && M < MaskSize) ||
- (M >= MaskSize + HalfSize && M < MaskSize * 2);
+ return M < 0 || (M >= 0 && M < HalfSize) ||
+ (M >= MaskSize && M < MaskSize + HalfSize);
}))
- postMask = LowLaneTy;
+ postMask = HighLaneTy;
// The pre-half of mask is high lane type, and the post-half of mask
// is low lane type, which is closest to the LoongArch instructions.
@@ -2395,7 +2398,7 @@ static void canonicalizeShuffleVectorByLane(
// to the lower 128-bit of vector register, and the low lane of mask
// corresponds the higher 128-bit of vector register.
if (preMask == HighLaneTy && postMask == LowLaneTy) {
- return;
+ return false;
}
if (preMask == LowLaneTy && postMask == HighLaneTy) {
V1 = DAG.getBitcast(MVT::v4i64, V1);
@@ -2449,8 +2452,10 @@ static void canonicalizeShuffleVectorByLane(
*it = *it < 0 ? *it : *it + HalfSize;
}
} else { // cross-lane
- return;
+ return false;
}
+
+ return true;
}
/// Lower VECTOR_SHUFFLE as lane permute and then shuffle (if possible).
@@ -2516,27 +2521,20 @@ static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,
assert(Mask.size() % 2 == 0 && "Expected even mask size.");
assert(Mask.size() >= 4 && "Mask size is less than 4.");
- // canonicalize non cross-lane shuffle vector
- SmallVector<int> NewMask(Mask);
- canonicalizeShuffleVectorByLane(DL, NewMask, VT, V1, V2, DAG, Subtarget);
-
APInt KnownUndef, KnownZero;
- computeZeroableShuffleElements(NewMask, V1, V2, KnownUndef, KnownZero);
+ computeZeroableShuffleElements(Mask, V1, V2, KnownUndef, KnownZero);
APInt Zeroable = KnownUndef | KnownZero;
SDValue Result;
// TODO: Add more comparison patterns.
if (V2.isUndef()) {
- if ((Result = lowerVECTOR_SHUFFLE_XVREPLVEI(DL, NewMask, VT, V1, V2, DAG,
+ if ((Result = lowerVECTOR_SHUFFLE_XVREPLVEI(DL, Mask, VT, V1, V2, DAG,
Subtarget)))
return Result;
- if ((Result = lowerVECTOR_SHUFFLE_XVSHUF4I(DL, NewMask, VT, V1, V2, DAG,
+ if ((Result = lowerVECTOR_SHUFFLE_XVSHUF4I(DL, Mask, VT, V1, V2, DAG,
Subtarget)))
return Result;
- if ((Result = lowerVECTOR_SHUFFLE_XVPERM(DL, NewMask, VT, V1, V2, DAG)))
- return Result;
- if ((Result = lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(DL, NewMask, VT,
- V1, V2, DAG)))
+ if ((Result = lowerVECTOR_SHUFFLE_XVPERM(DL, Mask, VT, V1, V2, DAG)))
return Result;
// TODO: This comment may be enabled in the future to better match the
@@ -2546,24 +2544,36 @@ static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,
// It is recommended not to change the pattern comparison order for better
// performance.
- if ((Result = lowerVECTOR_SHUFFLE_XVPACKEV(DL, NewMask, VT, V1, V2, DAG)))
+ if ((Result = lowerVECTOR_SHUFFLE_XVPACKEV(DL, Mask, VT, V1, V2, DAG)))
return Result;
- if ((Result = lowerVECTOR_SHUFFLE_XVPACKOD(DL, NewMask, VT, V1, V2, DAG)))
+ if ((Result = lowerVECTOR_SHUFFLE_XVPACKOD(DL, Mask, VT, V1, V2, DAG)))
return Result;
- if ((Result = lowerVECTOR_SHUFFLE_XVILVH(DL, NewMask, VT, V1, V2, DAG)))
+ if ((Result = lowerVECTOR_SHUFFLE_XVILVH(DL, Mask, VT, V1, V2, DAG)))
return Result;
- if ((Result = lowerVECTOR_SHUFFLE_XVILVL(DL, NewMask, VT, V1, V2, DAG)))
+ if ((Result = lowerVECTOR_SHUFFLE_XVILVL(DL, Mask, VT, V1, V2, DAG)))
return Result;
- if ((Result = lowerVECTOR_SHUFFLE_XVPICKEV(DL, NewMask, VT, V1, V2, DAG)))
+ if ((Result = lowerVECTOR_SHUFFLE_XVPICKEV(DL, Mask, VT, V1, V2, DAG)))
return Result;
- if ((Result = lowerVECTOR_SHUFFLE_XVPICKOD(DL, NewMask, VT, V1, V2, DAG)))
+ if ((Result = lowerVECTOR_SHUFFLE_XVPICKOD(DL, Mask, VT, V1, V2, DAG)))
return Result;
- if ((Result = lowerVECTOR_SHUFFLEAsShift(DL, NewMask, VT, V1, V2, DAG,
- Subtarget, Zeroable)))
+ if ((Result = lowerVECTOR_SHUFFLEAsShift(DL, Mask, VT, V1, V2, DAG, Subtarget,
+ Zeroable)))
return Result;
- if ((Result = lowerVECTOR_SHUFFLEAsByteRotate(DL, NewMask, VT, V1, V2, DAG,
+ if ((Result = lowerVECTOR_SHUFFLEAsByteRotate(DL, Mask, VT, V1, V2, DAG,
Subtarget)))
return Result;
+
+ // canonicalize non cross-lane shuffle vector
+ SmallVector<int> NewMask(Mask);
+ if (canonicalizeShuffleVectorByLane(DL, NewMask, VT, V1, V2, DAG, Subtarget))
+ return lower256BitShuffle(DL, NewMask, VT, V1, V2, DAG, Subtarget);
+
+ if (V2.isUndef()) {
+ if ((Result = lowerVECTOR_SHUFFLEAsLanePermuteAndShuffle(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)))
diff --git a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fix-xvshuf.ll b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fix-xvshuf.ll
index 765473ce166df..30539427a1a0a 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fix-xvshuf.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/ir-instruction/fix-xvshuf.ll
@@ -8,7 +8,7 @@ define <4 x double> @shufflevector_v4f64(<4 x double> %a, <4 x double> %b) {
; CHECK-LABEL: shufflevector_v4f64:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: xvpickve.d $xr2, $xr1, 3
-; CHECK-NEXT: xvpermi.d $xr3, $xr0, 78
+; CHECK-NEXT: xvpermi.d $xr3, $xr0, 238
; CHECK-NEXT: xvrepl128vei.d $xr3, $xr3, 1
; CHECK-NEXT: vextrins.d $vr3, $vr2, 16
; CHECK-NEXT: xvpickve.d $xr1, $xr1, 2
``````````
</details>
https://github.com/llvm/llvm-project/pull/160254
More information about the llvm-commits
mailing list