[llvm] 24fb629 - [LoongArch] Legalize LASX truncate with XVPICKEV instruction (#202485)

via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 28 18:46:17 PDT 2026


Author: lrzlin
Date: 2026-06-29T09:46:12+08:00
New Revision: 24fb629a8b43dd443a4d854d2ea18af786251df2

URL: https://github.com/llvm/llvm-project/commit/24fb629a8b43dd443a4d854d2ea18af786251df2
DIFF: https://github.com/llvm/llvm-project/commit/24fb629a8b43dd443a4d854d2ea18af786251df2.diff

LOG: [LoongArch] Legalize LASX truncate with XVPICKEV instruction (#202485)

Add LASX truncate patterns for wide truncates (e.g. `v8i64 trunc to
v8i8`) with `XVPICKEV` instructions.

To merge two registers into one, return concat_vectors as is while its
two operations are `ISD::TRUNCATE`, also dealing with illegal results in
`ReplaceNodeResults`.

Added: 
    llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll

Modified: 
    llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
    llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
    llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
    llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
    llvm/test/CodeGen/LoongArch/pr177863.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 61e77c35fef9d..702006221934f 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -494,6 +494,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
       setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, VT, Legal);
       setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, VT, Legal);
     }
+    for (MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
+      setOperationAction(ISD::TRUNCATE, VT, Legal);
   }
 
   // Set DAG combine for LA32 and LA64.
@@ -3822,6 +3824,10 @@ SDValue LoongArchTargetLowering::lowerCONCAT_VECTORS(SDValue Op,
   MVT ResVT = Op.getSimpleValueType();
   assert(ResVT.is256BitVector() && Op.getNumOperands() == 2);
 
+  if (Op.getOperand(0).getOpcode() == ISD::TRUNCATE &&
+      Op.getOperand(1).getOpcode() == ISD::TRUNCATE)
+    return Op;
+
   unsigned NumOperands = Op.getNumOperands();
   unsigned NumFreezeUndef = 0;
   unsigned NumZero = 0;
@@ -5821,6 +5827,22 @@ void LoongArchTargetLowering::ReplaceNodeResults(
     unsigned WidenNumElts = WidenVT.getVectorNumElements();
     unsigned InBits = InVT.getSizeInBits();
 
+    // v8i64 -> (v8i32) -> v8i8
+    if (InVT == MVT::v8i64 && WidenVT.is128BitVector()) {
+      InVT = MVT::getVectorVT(MVT::getIntegerVT(256 / MinElts), MinElts);
+      In = DAG.getNode(N->getOpcode(), DL, InVT, In);
+      InBits = 256;
+    }
+
+    // v8i32 -> v8i8 / v4i64 -> v4i16 / v4i64 -> v4i8
+    if ((InVT == MVT::v8i32 || InVT == MVT::v4i64) &&
+        WidenVT.is128BitVector()) {
+      InVT = MVT::getVectorVT(MVT::getIntegerVT(128 / MinElts), MinElts);
+      In = DAG.getNode(N->getOpcode(), DL, InVT, In);
+      InBits = 128;
+      InEltVT = InVT.getVectorElementType();
+    }
+
     if ((128 % InBits) == 0 && WidenVT.is128BitVector()) {
       if ((InEltVT.getSizeInBits() % EltVT.getSizeInBits()) == 0) {
         int Scale = InEltVT.getSizeInBits() / EltVT.getSizeInBits();

diff  --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index aac824252dd41..21d937d5b4275 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -2168,6 +2168,25 @@ def : Pat<(v4i32(fp_to_uint v4f64:$vj)),
 def : Pat<(v8i32 (loongarch_vftintrz_w_d (v4f64 LASX256:$xj), (v4f64 LASX256:$xk))),
           (XVFTINTRZ_W_D LASX256:$xj, LASX256:$xk)>;
 
+// truncate
+def : Pat<(v4i32 (trunc v4i64:$xj)),
+          (EXTRACT_SUBREG(XVPERMI_D(XVPICKEV_W v4i64:$xj, v4i64:$xj), 216), sub_128)>;
+
+def : Pat<(v8i16 (trunc v8i32:$xj)),
+          (EXTRACT_SUBREG(XVPERMI_D(XVPICKEV_H v8i32:$xj, v8i32:$xj), 216), sub_128)>;
+
+def : Pat<(v16i8 (trunc v16i16:$xj)),
+          (EXTRACT_SUBREG(XVPERMI_D(XVPICKEV_B v16i16:$xj, v16i16:$xj), 216), sub_128)>;
+
+def : Pat<(v8i32 (concat_vectors (v4i32 (trunc v4i64:$xj)), (v4i32 (trunc v4i64:$xk)))),
+          (XVPERMI_D(XVPICKEV_W v4i64:$xk, v4i64:$xj), 216)>;
+
+def : Pat<(v16i16 (concat_vectors (v8i16 (trunc v8i32:$xj)), (v8i16 (trunc v8i32:$xk)))),
+          (XVPERMI_D(XVPICKEV_H v8i32:$xk, v8i32:$xj), 216)>;
+
+def : Pat<(v32i8 (concat_vectors (v16i8 (trunc v16i16:$xj)), (v16i8 (trunc v16i16:$xk)))),
+          (XVPERMI_D(XVPICKEV_B v16i16:$xk, v16i16:$xj), 216)>;
+
 // XVAVG_{B/H/W/D/BU/HU/WU/DU}, XVAVGR_{B/H/W/D/BU/HU/WU/DU}
 defm : PatXrXr<avgfloors, "XVAVG">;
 defm : PatXrXr<avgceils, "XVAVGR">;

diff  --git a/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll b/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
new file mode 100644
index 0000000000000..a152053eceb06
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
@@ -0,0 +1,348 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lasx %s -o - | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx %s -o - | FileCheck %s --check-prefixes=CHECK,LA64
+
+define void @test_trunc_v4i16_to_v4i8(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v4i16_to_v4i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    ld.w $a2, $a0, 0
+; LA32-NEXT:    ld.w $a0, $a0, 4
+; LA32-NEXT:    vinsgr2vr.w $vr0, $a2, 0
+; LA32-NEXT:    vinsgr2vr.w $vr0, $a0, 1
+; LA32-NEXT:    vpickev.b $vr0, $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i16_to_v4i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    ld.d $a0, $a0, 0
+; LA64-NEXT:    vinsgr2vr.d $vr0, $a0, 0
+; LA64-NEXT:    vpickev.b $vr0, $vr0, $vr0
+; LA64-NEXT:    vstelm.w $vr0, $a1, 0, 0
+; LA64-NEXT:    ret
+  %vec = load <4 x i16>, ptr %src
+  %trunc = trunc <4 x i16> %vec to <4 x i8>
+  store <4 x i8> %trunc, ptr %dst
+  ret void
+}
+
+define void @test_trunc_v4i32_to_v4i8(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v4i32_to_v4i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vld $vr0, $a0, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI1_0)
+; LA32-NEXT:    vld $vr1, $a0, %pc_lo12(.LCPI1_0)
+; LA32-NEXT:    vshuf.b $vr0, $vr0, $vr0, $vr1
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i32_to_v4i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vld $vr0, $a0, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI1_0)
+; LA64-NEXT:    vld $vr1, $a0, %pc_lo12(.LCPI1_0)
+; LA64-NEXT:    vshuf.b $vr0, $vr0, $vr0, $vr1
+; LA64-NEXT:    vstelm.w $vr0, $a1, 0, 0
+; LA64-NEXT:    ret
+  %vec = load <4 x i32>, ptr %src
+  %trunc = trunc <4 x i32> %vec to <4 x i8>
+  store <4 x i8> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v4i32_to_v4i16(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v4i32_to_v4i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vld $vr0, $a0, 0
+; LA32-NEXT:    vpickev.h $vr0, $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 1
+; LA32-NEXT:    st.w $a0, $a1, 4
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i32_to_v4i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vld $vr0, $a0, 0
+; LA64-NEXT:    vpickev.h $vr0, $vr0, $vr0
+; LA64-NEXT:    vstelm.d $vr0, $a1, 0, 0
+; LA64-NEXT:    ret
+  %vec = load <4 x i32>, ptr %src
+  %trunc = trunc <4 x i32> %vec to <4 x i16>
+  store <4 x i16> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v4i64_to_v4i8(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v4i64_to_v4i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvld $xr0, $a0, 0
+; LA32-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
+; LA32-NEXT:    vld $vr1, $a0, %pc_lo12(.LCPI3_0)
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vshuf.b $vr0, $vr0, $vr0, $vr1
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i64_to_v4i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvld $xr0, $a0, 0
+; LA64-NEXT:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
+; LA64-NEXT:    vld $vr1, $a0, %pc_lo12(.LCPI3_0)
+; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vshuf.b $vr0, $vr0, $vr0, $vr1
+; LA64-NEXT:    vstelm.w $vr0, $a1, 0, 0
+; LA64-NEXT:    ret
+  %vec = load <4 x i64>, ptr %src
+  %trunc = trunc <4 x i64> %vec to <4 x i8>
+  store <4 x i8> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v4i64_to_v4i16(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v4i64_to_v4i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvld $xr0, $a0, 0
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vpickev.h $vr0, $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 1
+; LA32-NEXT:    st.w $a0, $a1, 4
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i64_to_v4i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvld $xr0, $a0, 0
+; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vpickev.h $vr0, $vr0, $vr0
+; LA64-NEXT:    vstelm.d $vr0, $a1, 0, 0
+; LA64-NEXT:    ret
+  %vec = load <4 x i64>, ptr %src
+  %trunc = trunc <4 x i64> %vec to <4 x i16>
+  store <4 x i16> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v4i64_to_v4i32(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v4i64_to_v4i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a0, 0
+; CHECK-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    vst $vr0, $a1, 0
+; CHECK-NEXT:    ret
+  %vec = load <4 x i64>, ptr %src
+  %trunc = trunc <4 x i64> %vec to <4 x i32>
+  store <4 x i32> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v8i32_to_v8i8(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v8i32_to_v8i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvld $xr0, $a0, 0
+; LA32-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vpickev.b $vr0, $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 1
+; LA32-NEXT:    st.w $a0, $a1, 4
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i32_to_v8i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvld $xr0, $a0, 0
+; LA64-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vpickev.b $vr0, $vr0, $vr0
+; LA64-NEXT:    vstelm.d $vr0, $a1, 0, 0
+; LA64-NEXT:    ret
+  %vec = load <8 x i32>, ptr %src
+  %trunc = trunc <8 x i32> %vec to <8 x i8>
+  store <8 x i8> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v8i32_to_v8i16(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v8i32_to_v8i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a0, 0
+; CHECK-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    vst $vr0, $a1, 0
+; CHECK-NEXT:    ret
+  %vec = load <8 x i32>, ptr %src
+  %trunc = trunc <8 x i32> %vec to <8 x i16>
+  store <8 x i16> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v8i64_to_v8i8(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v8i64_to_v8i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvld $xr0, $a0, 0
+; LA32-NEXT:    xvld $xr1, $a0, 32
+; LA32-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vpickev.b $vr0, $vr0, $vr0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 1
+; LA32-NEXT:    st.w $a0, $a1, 4
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    st.w $a0, $a1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i64_to_v8i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvld $xr0, $a0, 0
+; LA64-NEXT:    xvld $xr1, $a0, 32
+; LA64-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vpickev.b $vr0, $vr0, $vr0
+; LA64-NEXT:    vstelm.d $vr0, $a1, 0, 0
+; LA64-NEXT:    ret
+  %vec = load <8 x i64>, ptr %src
+  %trunc = trunc <8 x i64> %vec to <8 x i8>
+  store <8 x i8> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v8i64_to_v8i16(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v8i64_to_v8i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a0, 0
+; CHECK-NEXT:    xvld $xr1, $a0, 32
+; CHECK-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    vst $vr0, $a1, 0
+; CHECK-NEXT:    ret
+  %vec = load <8 x i64>, ptr %src
+  %trunc = trunc <8 x i64> %vec to <8 x i16>
+  store <8 x i16> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v8i64_to_v8i32(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v8i64_to_v8i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a0, 0
+; CHECK-NEXT:    xvld $xr1, $a0, 32
+; CHECK-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvst $xr0, $a1, 0
+; CHECK-NEXT:    ret
+  %vec = load <8 x i64>, ptr %src
+  %trunc = trunc <8 x i64> %vec to <8 x i32>
+  store <8 x i32> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v16i32_to_v16i8(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v16i32_to_v16i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a0, 0
+; CHECK-NEXT:    xvld $xr1, $a0, 32
+; CHECK-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    vst $vr0, $a1, 0
+; CHECK-NEXT:    ret
+  %vec = load <16 x i32>, ptr %src
+  %trunc = trunc <16 x i32> %vec to <16 x i8>
+  store <16 x i8> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v16i32_to_v16i16(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v16i32_to_v16i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a0, 0
+; CHECK-NEXT:    xvld $xr1, $a0, 32
+; CHECK-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvst $xr0, $a1, 0
+; CHECK-NEXT:    ret
+  %vec = load <16 x i32>, ptr %src
+  %trunc = trunc <16 x i32> %vec to <16 x i16>
+  store <16 x i16> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v16i64_to_v16i8(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v16i64_to_v16i8:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a0, 0
+; CHECK-NEXT:    xvld $xr1, $a0, 32
+; CHECK-NEXT:    xvld $xr2, $a0, 64
+; CHECK-NEXT:    xvld $xr3, $a0, 96
+; CHECK-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvpickev.w $xr1, $xr3, $xr2
+; CHECK-NEXT:    xvpermi.d $xr1, $xr1, 216
+; CHECK-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    vst $vr0, $a1, 0
+; CHECK-NEXT:    ret
+  %vec = load <16 x i64>, ptr %src
+  %trunc = trunc <16 x i64> %vec to <16 x i8>
+  store <16 x i8> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v16i64_to_v16i16(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v16i64_to_v16i16:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a0, 0
+; CHECK-NEXT:    xvld $xr1, $a0, 32
+; CHECK-NEXT:    xvld $xr2, $a0, 64
+; CHECK-NEXT:    xvld $xr3, $a0, 96
+; CHECK-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvpickev.w $xr1, $xr3, $xr2
+; CHECK-NEXT:    xvpermi.d $xr1, $xr1, 216
+; CHECK-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvst $xr0, $a1, 0
+; CHECK-NEXT:    ret
+  %vec = load <16 x i64>, ptr %src
+  %trunc = trunc <16 x i64> %vec to <16 x i16>
+  store <16 x i16> %trunc, ptr %dst
+	ret void
+}
+
+define void @test_trunc_v16i64_to_v16i32(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v16i64_to_v16i32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvld $xr0, $a0, 0
+; CHECK-NEXT:    xvld $xr1, $a0, 32
+; CHECK-NEXT:    xvld $xr2, $a0, 64
+; CHECK-NEXT:    xvld $xr3, $a0, 96
+; CHECK-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    xvpickev.w $xr1, $xr3, $xr2
+; CHECK-NEXT:    xvpermi.d $xr1, $xr1, 216
+; CHECK-NEXT:    xvst $xr1, $a1, 32
+; CHECK-NEXT:    xvst $xr0, $a1, 0
+; CHECK-NEXT:    ret
+  %vec = load <16 x i64>, ptr %src
+  %trunc = trunc <16 x i64> %vec to <16 x i32>
+  store <16 x i32> %trunc, ptr %dst
+	ret void
+}

diff  --git a/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll b/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
index cb28d79b0dd51..bd17e67d19fa3 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
@@ -8,16 +8,10 @@ define void @xor_zext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 0
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 2
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 3
-; LA32-NEXT:    vldi $vr0, -1777
-; LA32-NEXT:    vxor.v $vr0, $vr1, $vr0
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vxor.v $vr0, $vr0, $vr1
 ; LA32-NEXT:    vextrins.w $vr1, $vr0, 2
 ; LA32-NEXT:    vextrins.w $vr1, $vr0, 35
 ; LA32-NEXT:    vextrins.w $vr0, $vr0, 33
@@ -97,16 +91,10 @@ define void @xor_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 0
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 2
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 3
-; LA32-NEXT:    vldi $vr0, -1777
-; LA32-NEXT:    vxor.v $vr0, $vr1, $vr0
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vxor.v $vr0, $vr0, $vr1
 ; LA32-NEXT:    vext2xv.d.w $xr0, $xr0
 ; LA32-NEXT:    xvst $xr0, $a0, 0
 ; LA32-NEXT:    ret
@@ -181,14 +169,13 @@ define void @or_zext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT:    xvpickve2gr.w $a2, $xr0, 2
-; LA32-NEXT:    vrepli.b $vr0, -1
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a2, 1
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a1, 3
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vor.v $vr0, $vr0, $vr1
 ; LA32-NEXT:    vextrins.w $vr1, $vr0, 2
+; LA32-NEXT:    vextrins.w $vr1, $vr0, 35
 ; LA32-NEXT:    vextrins.w $vr0, $vr0, 33
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 2
 ; LA32-NEXT:    xvpermi.q $xr0, $xr1, 2
 ; LA32-NEXT:    xvrepli.d $xr1, 1
 ; LA32-NEXT:    xvand.v $xr0, $xr0, $xr1
@@ -265,11 +252,10 @@ define void @or_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT:    xvpickve2gr.w $a2, $xr0, 2
-; LA32-NEXT:    vrepli.b $vr0, -1
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a2, 1
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a1, 3
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vor.v $vr0, $vr0, $vr1
 ; LA32-NEXT:    vext2xv.d.w $xr0, $xr0
 ; LA32-NEXT:    xvst $xr0, $a0, 0
 ; LA32-NEXT:    ret
@@ -341,10 +327,16 @@ define void @and_zext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvrepli.b $xr1, 0
-; LA32-NEXT:    xvextrins.w $xr1, $xr0, 0
-; LA32-NEXT:    xvrepli.d $xr0, 1
-; LA32-NEXT:    xvand.v $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr1
+; LA32-NEXT:    vextrins.w $vr1, $vr0, 2
+; LA32-NEXT:    vextrins.w $vr1, $vr0, 35
+; LA32-NEXT:    vextrins.w $vr0, $vr0, 33
+; LA32-NEXT:    xvpermi.q $xr0, $xr1, 2
+; LA32-NEXT:    xvrepli.d $xr1, 1
+; LA32-NEXT:    xvand.v $xr0, $xr0, $xr1
 ; LA32-NEXT:    xvst $xr0, $a0, 0
 ; LA32-NEXT:    ret
 ;
@@ -412,11 +404,10 @@ define void @and_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT:    xvpickve2gr.w $a2, $xr0, 0
-; LA32-NEXT:    vrepli.b $vr0, 0
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a2, 0
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a1, 2
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr1
 ; LA32-NEXT:    vext2xv.d.w $xr0, $xr0
 ; LA32-NEXT:    xvst $xr0, $a0, 0
 ; LA32-NEXT:    ret

diff  --git a/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll b/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
index ca61e69f1b378..bb8cc2abbec35 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
@@ -883,39 +883,24 @@ define i8 @xvmsk_ne_v4i32_concat_poison(<4 x i32> %vec) {
 }
 
 define i8 @xvmsk_ogt_v4f64_concat_poison(<4 x double> %vec) {
-; LA32-LABEL: xvmsk_ogt_v4f64_concat_poison:
-; LA32:       # %bb.0:
-; LA32-NEXT:    xvrepli.b $xr1, 0
-; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr1, $xr0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT:    xvpickve2gr.w $a2, $xr0, 2
-; LA32-NEXT:    xvpickve2gr.w $a3, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.h $vr0, $a3, 0
-; LA32-NEXT:    vinsgr2vr.h $vr0, $a2, 1
-; LA32-NEXT:    vinsgr2vr.h $vr0, $a1, 2
-; LA32-NEXT:    vinsgr2vr.h $vr0, $a0, 3
-; LA32-NEXT:    vslli.h $vr0, $vr0, 15
-; LA32-NEXT:    vmskltz.h $vr0, $vr0
-; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
-; LA32-NEXT:    ret
-;
-; LA64-LABEL: xvmsk_ogt_v4f64_concat_poison:
-; LA64:       # %bb.0:
-; LA64-NEXT:    xvrepli.b $xr1, 0
-; LA64-NEXT:    xvfcmp.clt.d $xr0, $xr1, $xr0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    xvpickve2gr.d $a1, $xr0, 2
-; LA64-NEXT:    xvpickve2gr.d $a2, $xr0, 1
-; LA64-NEXT:    xvpickve2gr.d $a3, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.h $vr0, $a3, 0
-; LA64-NEXT:    vinsgr2vr.h $vr0, $a2, 1
-; LA64-NEXT:    vinsgr2vr.h $vr0, $a1, 2
-; LA64-NEXT:    vinsgr2vr.h $vr0, $a0, 3
-; LA64-NEXT:    vslli.h $vr0, $vr0, 15
-; LA64-NEXT:    vmskltz.h $vr0, $vr0
-; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
-; LA64-NEXT:    ret
+; CHECK-LABEL: xvmsk_ogt_v4f64_concat_poison:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvrepli.b $xr1, 0
+; CHECK-NEXT:    xvfcmp.clt.d $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 0
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 1
+; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 1
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 2
+; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 2
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 3
+; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 3
+; CHECK-NEXT:    vslli.h $vr0, $vr1, 15
+; CHECK-NEXT:    vmskltz.h $vr0, $vr0
+; CHECK-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; CHECK-NEXT:    ret
   %tobool = fcmp ogt <4 x double> %vec, zeroinitializer
   %insertvec = shufflevector <4 x i1> %tobool, <4 x i1> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
   %res = bitcast <8 x i1> %insertvec to i8

diff  --git a/llvm/test/CodeGen/LoongArch/pr177863.ll b/llvm/test/CodeGen/LoongArch/pr177863.ll
index 54fa02162ee0d..c8fbba8500fc2 100644
--- a/llvm/test/CodeGen/LoongArch/pr177863.ll
+++ b/llvm/test/CodeGen/LoongArch/pr177863.ll
@@ -7,29 +7,17 @@ define <4 x i1> @test(<4 x i64> %shuffle2, <4 x i64> %shuffle4) {
 ; LA32-LABEL: test:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    xvseq.d $xr0, $xr1, $xr0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 3
-; LA32-NEXT:    vxori.b $vr0, $vr1, 255
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vxori.b $vr0, $vr0, 255
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    xvseq.d $xr0, $xr1, $xr0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 3
-; LA64-NEXT:    vxori.b $vr0, $vr1, 255
+; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vxori.b $vr0, $vr0, 255
 ; LA64-NEXT:    ret
 entry:
   %conv5 = trunc nuw <4 x i64> %shuffle4 to <4 x i32>


        


More information about the llvm-commits mailing list