[llvm] [LoongArch] Custom legalize vector_shuffle to bswap (PR #170625)

via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 4 00:42:45 PST 2025


https://github.com/zhaoqi5 created https://github.com/llvm/llvm-project/pull/170625

None

>From c439a45b0bfd20fbaf36317645c58a9d23f9bc3c Mon Sep 17 00:00:00 2001
From: Qi Zhao <zhaoqi01 at loongson.cn>
Date: Thu, 4 Dec 2025 16:35:16 +0800
Subject: [PATCH] [LoongArch] Custom legalize vector_shuffle to bswap

---
 .../LoongArch/LoongArchISelLowering.cpp       | 37 +++++++++++++++++++
 .../test/CodeGen/LoongArch/lasx/bitreverse.ll |  5 +--
 .../LoongArch/lasx/shuffle-as-bswap.ll        |  5 +--
 llvm/test/CodeGen/LoongArch/lsx/bitreverse.ll |  5 +--
 .../CodeGen/LoongArch/lsx/shuffle-as-bswap.ll |  5 +--
 5 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 32ea2198f7898..344cdb64573d7 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -1832,6 +1832,39 @@ lowerVECTOR_SHUFFLE_VSHUF4I(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,
                      DAG.getConstant(Imm, DL, GRLenVT));
 }
 
+/// Lower VECTOR_SHUFFLE into BSWAP (if possible).
+///
+/// It is possible to do optimization for VECTOR_SHUFFLE performing vector
+/// byte swap in each subvector whose mask likes:
+///   <7, 6, ..., 0, 15, 14, ..., 8>
+///
+/// When undef's appear in the mask they are treated as if they were whatever
+/// value is necessary in order to fit the above forms.
+static SDValue lowerVECTOR_SHUFFLEAsBSWAP(const SDLoc &DL, ArrayRef<int> Mask,
+                                          MVT VT, SDValue V1,
+                                          SelectionDAG &DAG) {
+  // Only vectors with i8 type elements can be converted to BSWAP.
+  if (VT != MVT::v16i8 && VT != MVT::v32i8)
+    return SDValue();
+
+  // Only consider byte swap in each 64-bit subvector. Other cases (i.e.
+  // in each 32-bit or 16-bit subvector) can match VSHUF4I directly.
+  unsigned NumElts = VT.getVectorNumElements();
+  for (unsigned i = 0; i < NumElts; ++i) {
+    int M = Mask[i];
+    if (M == -1)
+      continue;
+    // Check that performing byte swap within each 8 elements.
+    if (M != (int)(i ^ 7))
+      return SDValue();
+  }
+
+  MVT ResVT = VT == MVT::v16i8 ? MVT::v2i64 : MVT::v4i64;
+  SDValue Result =
+      DAG.getNode(ISD::BSWAP, DL, ResVT, DAG.getBitcast(ResVT, V1));
+  return DAG.getBitcast(VT, Result);
+}
+
 /// Lower VECTOR_SHUFFLE whose result is the reversed source vector.
 ///
 /// It is possible to do optimization for VECTOR_SHUFFLE performing vector
@@ -2172,6 +2205,8 @@ static SDValue lower128BitShuffle(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,
     if ((Result =
              lowerVECTOR_SHUFFLE_VSHUF4I(DL, Mask, VT, V1, V2, DAG, Subtarget)))
       return Result;
+    if ((Result = lowerVECTOR_SHUFFLEAsBSWAP(DL, Mask, VT, V1, DAG)))
+      return Result;
     if ((Result =
              lowerVECTOR_SHUFFLE_IsReverse(DL, Mask, VT, V1, DAG, Subtarget)))
       return Result;
@@ -2785,6 +2820,8 @@ static SDValue lower256BitShuffle(const SDLoc &DL, ArrayRef<int> Mask, MVT VT,
     if ((Result = lowerVECTOR_SHUFFLE_XVSHUF4I(DL, Mask, VT, V1, V2, DAG,
                                                Subtarget)))
       return Result;
+    if ((Result = lowerVECTOR_SHUFFLEAsBSWAP(DL, Mask, VT, V1, DAG)))
+      return Result;
     // Try to widen vectors to gain more optimization opportunities.
     if (SDValue NewShuffle = widenShuffleMask(DL, Mask, VT, V1, V2, DAG))
       return NewShuffle;
diff --git a/llvm/test/CodeGen/LoongArch/lasx/bitreverse.ll b/llvm/test/CodeGen/LoongArch/lasx/bitreverse.ll
index 8b12216d0f856..c5b9d5be1f241 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/bitreverse.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/bitreverse.ll
@@ -158,9 +158,8 @@ declare <4 x i64> @llvm.bitreverse.v4i64(<4 x i64>)
 define <4 x i64> @test_bitreverse_v4i64(<4 x i64> %a) nounwind {
 ; LA32-LABEL: test_bitreverse_v4i64:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
-; LA32-NEXT:    xvld $xr1, $a0, %pc_lo12(.LCPI3_0)
-; LA32-NEXT:    xvshuf.b $xr0, $xr0, $xr0, $xr1
+; LA32-NEXT:    xvshuf4i.b $xr0, $xr0, 27
+; LA32-NEXT:    xvshuf4i.w $xr0, $xr0, 177
 ; LA32-NEXT:    xvslli.b $xr1, $xr0, 4
 ; LA32-NEXT:    xvsrli.b $xr0, $xr0, 4
 ; LA32-NEXT:    xvor.v $xr0, $xr0, $xr1
diff --git a/llvm/test/CodeGen/LoongArch/lasx/shuffle-as-bswap.ll b/llvm/test/CodeGen/LoongArch/lasx/shuffle-as-bswap.ll
index 1c9038af1d676..a05f969bc0aba 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/shuffle-as-bswap.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/shuffle-as-bswap.ll
@@ -34,9 +34,8 @@ define void @shufflevector_bswap_d(ptr %res, ptr %a) nounwind {
 ; CHECK-LABEL: shufflevector_bswap_d:
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    xvld $xr0, $a1, 0
-; CHECK-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI2_0)
-; CHECK-NEXT:    xvld $xr1, $a1, %pc_lo12(.LCPI2_0)
-; CHECK-NEXT:    xvshuf.b $xr0, $xr0, $xr0, $xr1
+; CHECK-NEXT:    xvshuf4i.b $xr0, $xr0, 27
+; CHECK-NEXT:    xvshuf4i.w $xr0, $xr0, 177
 ; CHECK-NEXT:    xvst $xr0, $a0, 0
 ; CHECK-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/LoongArch/lsx/bitreverse.ll b/llvm/test/CodeGen/LoongArch/lsx/bitreverse.ll
index b0d36a8143fa1..b350144e22216 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/bitreverse.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/bitreverse.ll
@@ -111,9 +111,8 @@ declare <2 x i64> @llvm.bitreverse.v2i64(<2 x i64>)
 define <2 x i64> @test_bitreverse_v2i64(<2 x i64> %a) nounwind {
 ; LA32-LABEL: test_bitreverse_v2i64:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
-; LA32-NEXT:    vld $vr1, $a0, %pc_lo12(.LCPI3_0)
-; LA32-NEXT:    vshuf.b $vr0, $vr0, $vr0, $vr1
+; LA32-NEXT:    vshuf4i.b $vr0, $vr0, 27
+; LA32-NEXT:    vshuf4i.w $vr0, $vr0, 177
 ; LA32-NEXT:    vslli.b $vr1, $vr0, 4
 ; LA32-NEXT:    vsrli.b $vr0, $vr0, 4
 ; LA32-NEXT:    vor.v $vr0, $vr0, $vr1
diff --git a/llvm/test/CodeGen/LoongArch/lsx/shuffle-as-bswap.ll b/llvm/test/CodeGen/LoongArch/lsx/shuffle-as-bswap.ll
index a6b61dc5a250e..6ced562296e01 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/shuffle-as-bswap.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/shuffle-as-bswap.ll
@@ -34,9 +34,8 @@ define void @shufflevector_bswap_d(ptr %res, ptr %a) nounwind {
 ; CHECK-LABEL: shufflevector_bswap_d:
 ; CHECK:       # %bb.0: # %entry
 ; CHECK-NEXT:    vld $vr0, $a1, 0
-; CHECK-NEXT:    pcalau12i $a1, %pc_hi20(.LCPI2_0)
-; CHECK-NEXT:    vld $vr1, $a1, %pc_lo12(.LCPI2_0)
-; CHECK-NEXT:    vshuf.b $vr0, $vr0, $vr0, $vr1
+; CHECK-NEXT:    vshuf4i.b $vr0, $vr0, 27
+; CHECK-NEXT:    vshuf4i.w $vr0, $vr0, 177
 ; CHECK-NEXT:    vst $vr0, $a0, 0
 ; CHECK-NEXT:    ret
 entry:



More information about the llvm-commits mailing list