[llvm] [LoongArch] Custom LSX and LASX truncate with [X]VPICKEV instruction (PR #201548)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 4 04:12:16 PDT 2026


https://github.com/lrzlin created https://github.com/llvm/llvm-project/pull/201548

Custom wide truncate (e.g. `v8i64` trunc to `v8i8`) with `[X]VPICKEV` instructions.

When LASX is enabled, only use `XVPICKEV` to avoid illegal VR to XR reg copy, but optimize `XVPERMI_D` out as valid data is in lower 128-bits.

>From b540a2f5adad8ef82e9ebcd7edd2534d7d61919b Mon Sep 17 00:00:00 2001
From: Lin Runze <linrunze at loongson.cn>
Date: Thu, 4 Jun 2026 19:01:49 +0800
Subject: [PATCH 1/2] [LoongArch][NFC] Add more truncate tests for LSX and LASX

---
 .../LoongArch/lasx/vec-trunc-combine.ll       | 769 ++++++++++++++++++
 .../LoongArch/lsx/vec-trunc-combine.ll        | 375 +++++++++
 2 files changed, 1144 insertions(+)
 create mode 100644 llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
 create mode 100644 llvm/test/CodeGen/LoongArch/lsx/vec-trunc-combine.ll

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..77136eb165149
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
@@ -0,0 +1,769 @@
+; 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-prefix=LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx %s -o - | FileCheck %s --check-prefix=LA64
+
+define <4 x i8> @test_trunc_v4i16_to_v4i8(<4 x i16> %arg) {
+; LA32-LABEL: test_trunc_v4i16_to_v4i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.b $vr0, $vr0, $vr0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i16_to_v4i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.b $vr0, $vr0, $vr0
+; LA64-NEXT:    ret
+  %trunc = trunc <4 x i16> %arg to <4 x i8>
+  ret <4 x i8> %trunc
+}
+
+define <4 x i8> @test_trunc_v4i32_to_v4i8(<4 x i32> %arg) {
+; LA32-LABEL: test_trunc_v4i32_to_v4i8:
+; LA32:       # %bb.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:    ret
+;
+; LA64-LABEL: test_trunc_v4i32_to_v4i8:
+; LA64:       # %bb.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:    ret
+  %trunc = trunc <4 x i32> %arg to <4 x i8>
+  ret <4 x i8> %trunc
+}
+
+define <4 x i16> @test_trunc_v4i32_to_v4i16(<4 x i32> %arg) {
+; LA32-LABEL: test_trunc_v4i32_to_v4i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.h $vr0, $vr0, $vr0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i32_to_v4i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.h $vr0, $vr0, $vr0
+; LA64-NEXT:    ret
+  %trunc = trunc <4 x i32> %arg to <4 x i16>
+  ret <4 x i16> %trunc
+}
+
+define <4 x i8> @test_trunc_v4i64_to_v4i8(<4 x i64> %arg) {
+; LA32-LABEL: test_trunc_v4i64_to_v4i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 3
+; LA32-NEXT:    vori.b $vr0, $vr1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i64_to_v4i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 3
+; LA64-NEXT:    vori.b $vr0, $vr1, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <4 x i64> %arg to <4 x i8>
+  ret <4 x i8> %trunc
+}
+
+define <4 x i16> @test_trunc_v4i64_to_v4i16(<4 x i64> %arg) {
+; LA32-LABEL: test_trunc_v4i64_to_v4i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 3
+; LA32-NEXT:    vori.b $vr0, $vr1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i64_to_v4i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 3
+; LA64-NEXT:    vori.b $vr0, $vr1, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <4 x i64> %arg to <4 x i16>
+  ret <4 x i16> %trunc
+}
+
+define <4 x i32> @test_trunc_v4i64_to_v4i32(<4 x i64> %arg) {
+; LA32-LABEL: test_trunc_v4i64_to_v4i32:
+; LA32:       # %bb.0:
+; 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:    vori.b $vr0, $vr1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i64_to_v4i32:
+; LA64:       # %bb.0:
+; 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:    vori.b $vr0, $vr1, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <4 x i64> %arg to <4 x i32>
+  ret <4 x i32> %trunc
+}
+
+define <8 x i8> @test_trunc_v8i32_to_v8i8(<8 x i32> %arg) {
+; LA32-LABEL: test_trunc_v8i32_to_v8i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 1
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 3
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 4
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 5
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 5
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 6
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 7
+; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 7
+; LA32-NEXT:    vori.b $vr0, $vr1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i32_to_v8i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 0
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 1
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 2
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 3
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 4
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 5
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 5
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 6
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 7
+; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 7
+; LA64-NEXT:    vori.b $vr0, $vr1, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <8 x i32> %arg to <8 x i8>
+  ret <8 x i8> %trunc
+}
+
+define <8 x i16> @test_trunc_v8i32_to_v8i16(<8 x i32> %arg) {
+; LA32-LABEL: test_trunc_v8i32_to_v8i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 1
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 3
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 4
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 5
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 5
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 6
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 7
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 7
+; LA32-NEXT:    vori.b $vr0, $vr1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i32_to_v8i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 0
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 1
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 2
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 3
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 4
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 5
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 5
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 6
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 7
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 7
+; LA64-NEXT:    vori.b $vr0, $vr1, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <8 x i32> %arg to <8 x i16>
+  ret <8 x i16> %trunc
+}
+
+define <8 x i8> @test_trunc_v8i64_to_v8i8(<8 x i64> %arg) {
+; LA32-LABEL: test_trunc_v8i64_to_v8i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 4
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 5
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 6
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 7
+; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i64_to_v8i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 3
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 4
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 5
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 6
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 7
+; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <8 x i64> %arg to <8 x i8>
+  ret <8 x i8> %trunc
+}
+
+define <8 x i16> @test_trunc_v8i64_to_v8i16(<8 x i64> %arg) {
+; LA32-LABEL: test_trunc_v8i64_to_v8i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 4
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 5
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 6
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 7
+; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i64_to_v8i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 3
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 4
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 5
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 6
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 7
+; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <8 x i64> %arg to <8 x i16>
+  ret <8 x i16> %trunc
+}
+
+define <8 x i32> @test_trunc_v8i64_to_v8i32(<8 x i64> %arg) {
+; LA32-LABEL: test_trunc_v8i64_to_v8i32:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
+; LA32-NEXT:    vinsgr2vr.w $vr2, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
+; LA32-NEXT:    vinsgr2vr.w $vr2, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
+; LA32-NEXT:    vinsgr2vr.w $vr2, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
+; LA32-NEXT:    vinsgr2vr.w $vr2, $a0, 3
+; 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:    xvpermi.q $xr1, $xr2, 2
+; LA32-NEXT:    xvori.b $xr0, $xr1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i64_to_v8i32:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
+; LA64-NEXT:    vinsgr2vr.w $vr2, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
+; LA64-NEXT:    vinsgr2vr.w $vr2, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
+; LA64-NEXT:    vinsgr2vr.w $vr2, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
+; LA64-NEXT:    vinsgr2vr.w $vr2, $a0, 3
+; 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:    xvpermi.q $xr1, $xr2, 2
+; LA64-NEXT:    xvori.b $xr0, $xr1, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <8 x i64> %arg to <8 x i32>
+  ret <8 x i32> %trunc
+}
+
+define <16 x i8> @test_trunc_v16i32_to_v16i8(<16 x i32> %arg) {
+; LA32-LABEL: test_trunc_v16i32_to_v16i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 1
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 3
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 4
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 5
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 5
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 6
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 7
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 7
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 8
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 1
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 9
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 10
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 3
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 11
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 12
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 5
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 13
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 14
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 7
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 15
+; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v16i32_to_v16i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 0
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 1
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 2
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 3
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 4
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 5
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 5
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 6
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 7
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 7
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 0
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 8
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 1
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 9
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 2
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 10
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 3
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 11
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 4
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 12
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 5
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 13
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 6
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 14
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 7
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 15
+; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <16 x i32> %arg to <16 x i8>
+  ret <16 x i8> %trunc
+}
+
+define <16 x i16> @test_trunc_v16i32_to_v16i16(<16 x i32> %arg) {
+; LA32-LABEL: test_trunc_v16i32_to_v16i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 1
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 3
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 4
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 5
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 5
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 6
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 7
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 7
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 1
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 3
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 4
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 5
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 5
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 6
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 7
+; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 7
+; LA32-NEXT:    xvpermi.q $xr1, $xr2, 2
+; LA32-NEXT:    xvori.b $xr0, $xr1, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v16i32_to_v16i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 0
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 0
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 1
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 1
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 2
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 2
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 3
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 3
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 4
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 4
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 5
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 5
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 6
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 6
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 7
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 7
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 0
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 1
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 2
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 3
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 4
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 5
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 5
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 6
+; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 7
+; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 7
+; LA64-NEXT:    xvpermi.q $xr1, $xr2, 2
+; LA64-NEXT:    xvori.b $xr0, $xr1, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <16 x i32> %arg to <16 x i16>
+  ret <16 x i16> %trunc
+}
+
+define <16 x i8> @test_trunc_v16i64_to_v16i8(<16 x i64> %arg) {
+; LA32-LABEL: test_trunc_v16i64_to_v16i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 4
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 5
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 6
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 7
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 0
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 8
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 2
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 9
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 4
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 10
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 6
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 11
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 0
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 12
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 2
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 13
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 4
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 14
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 6
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 15
+; LA32-NEXT:    vori.b $vr0, $vr4, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v16i64_to_v16i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 3
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 4
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 5
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 6
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 7
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 0
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 8
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 1
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 9
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 2
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 10
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 3
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 11
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 0
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 12
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 1
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 13
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 2
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 14
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 3
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 15
+; LA64-NEXT:    vori.b $vr0, $vr4, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <16 x i64> %arg to <16 x i8>
+  ret <16 x i8> %trunc
+}
+
+define <16 x i16> @test_trunc_v16i64_to_v16i16(<16 x i64> %arg) {
+; LA32-LABEL: test_trunc_v16i64_to_v16i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 0
+; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 2
+; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 4
+; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 6
+; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 0
+; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 4
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 2
+; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 5
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 4
+; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 6
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 6
+; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 7
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 4
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 5
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 6
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 7
+; LA32-NEXT:    xvpermi.q $xr2, $xr4, 2
+; LA32-NEXT:    xvori.b $xr0, $xr2, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v16i64_to_v16i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 0
+; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 1
+; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 2
+; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 3
+; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 3
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 0
+; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 4
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 1
+; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 5
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 2
+; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 6
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 3
+; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 7
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 3
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 4
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 5
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 6
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 7
+; LA64-NEXT:    xvpermi.q $xr2, $xr4, 2
+; LA64-NEXT:    xvori.b $xr0, $xr2, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <16 x i64> %arg to <16 x i16>
+  ret <16 x i16> %trunc
+}
+
+define <16 x i32> @test_trunc_v16i64_to_v16i32(<16 x i64> %arg) {
+; LA32-LABEL: test_trunc_v16i64_to_v16i32:
+; LA32:       # %bb.0:
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
+; LA32-NEXT:    vinsgr2vr.w $vr5, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
+; LA32-NEXT:    vinsgr2vr.w $vr5, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
+; LA32-NEXT:    vinsgr2vr.w $vr5, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
+; LA32-NEXT:    vinsgr2vr.w $vr5, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
+; LA32-NEXT:    vinsgr2vr.w $vr4, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
+; LA32-NEXT:    vinsgr2vr.w $vr4, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
+; LA32-NEXT:    vinsgr2vr.w $vr4, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
+; LA32-NEXT:    vinsgr2vr.w $vr4, $a0, 3
+; LA32-NEXT:    xvpermi.q $xr4, $xr5, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 0
+; LA32-NEXT:    vinsgr2vr.w $vr0, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 2
+; LA32-NEXT:    vinsgr2vr.w $vr0, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 4
+; LA32-NEXT:    vinsgr2vr.w $vr0, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 6
+; LA32-NEXT:    vinsgr2vr.w $vr0, $a0, 3
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 0
+; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 0
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 2
+; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 1
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 4
+; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 2
+; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 6
+; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 3
+; LA32-NEXT:    xvpermi.q $xr1, $xr0, 2
+; LA32-NEXT:    xvori.b $xr0, $xr4, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v16i64_to_v16i32:
+; LA64:       # %bb.0:
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
+; LA64-NEXT:    vinsgr2vr.w $vr5, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
+; LA64-NEXT:    vinsgr2vr.w $vr5, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
+; LA64-NEXT:    vinsgr2vr.w $vr5, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
+; LA64-NEXT:    vinsgr2vr.w $vr5, $a0, 3
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
+; LA64-NEXT:    vinsgr2vr.w $vr4, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
+; LA64-NEXT:    vinsgr2vr.w $vr4, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
+; LA64-NEXT:    vinsgr2vr.w $vr4, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
+; LA64-NEXT:    vinsgr2vr.w $vr4, $a0, 3
+; LA64-NEXT:    xvpermi.q $xr4, $xr5, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 0
+; LA64-NEXT:    vinsgr2vr.w $vr0, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 1
+; LA64-NEXT:    vinsgr2vr.w $vr0, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 2
+; LA64-NEXT:    vinsgr2vr.w $vr0, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 3
+; LA64-NEXT:    vinsgr2vr.w $vr0, $a0, 3
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 0
+; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 0
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 1
+; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 1
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 2
+; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 2
+; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 3
+; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 3
+; LA64-NEXT:    xvpermi.q $xr1, $xr0, 2
+; LA64-NEXT:    xvori.b $xr0, $xr4, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <16 x i64> %arg to <16 x i32>
+  ret <16 x i32> %trunc
+}
diff --git a/llvm/test/CodeGen/LoongArch/lsx/vec-trunc-combine.ll b/llvm/test/CodeGen/LoongArch/lsx/vec-trunc-combine.ll
new file mode 100644
index 0000000000000..2ce0ad7831cb9
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lsx/vec-trunc-combine.ll
@@ -0,0 +1,375 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx %s -o - | FileCheck %s --check-prefix=LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx %s -o - | FileCheck %s --check-prefix=LA64
+
+define <4 x i8> @test_trunc_v4i16_to_v4i8(<4 x i16> %arg) {
+; LA32-LABEL: test_trunc_v4i16_to_v4i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.b $vr0, $vr0, $vr0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i16_to_v4i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.b $vr0, $vr0, $vr0
+; LA64-NEXT:    ret
+  %trunc = trunc <4 x i16> %arg to <4 x i8>
+  ret <4 x i8> %trunc
+}
+
+define <4 x i8> @test_trunc_v4i32_to_v4i8(<4 x i32> %arg) {
+; LA32-LABEL: test_trunc_v4i32_to_v4i8:
+; LA32:       # %bb.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:    ret
+;
+; LA64-LABEL: test_trunc_v4i32_to_v4i8:
+; LA64:       # %bb.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:    ret
+  %trunc = trunc <4 x i32> %arg to <4 x i8>
+  ret <4 x i8> %trunc
+}
+
+define <4 x i16> @test_trunc_v4i32_to_v4i16(<4 x i32> %arg) {
+; LA32-LABEL: test_trunc_v4i32_to_v4i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.h $vr0, $vr0, $vr0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i32_to_v4i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.h $vr0, $vr0, $vr0
+; LA64-NEXT:    ret
+  %trunc = trunc <4 x i32> %arg to <4 x i16>
+  ret <4 x i16> %trunc
+}
+
+define <4 x i8> @test_trunc_v4i64_to_v4i8(<4 x i64> %arg) {
+; LA32-LABEL: test_trunc_v4i64_to_v4i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 2
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 1
+; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 0
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 2
+; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 2
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 3
+; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i64_to_v4i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 0
+; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 1
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 1
+; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 0
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 2
+; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 1
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 3
+; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <4 x i64> %arg to <4 x i8>
+  ret <4 x i8> %trunc
+}
+
+define <4 x i16> @test_trunc_v4i64_to_v4i16(<4 x i64> %arg) {
+; LA32-LABEL: test_trunc_v4i64_to_v4i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 2
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 1
+; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 0
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 2
+; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 2
+; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 3
+; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i64_to_v4i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 0
+; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 1
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 1
+; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 0
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 2
+; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 1
+; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 3
+; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <4 x i64> %arg to <4 x i16>
+  ret <4 x i16> %trunc
+}
+
+define <4 x i32> @test_trunc_v4i64_to_v4i32(<4 x i64> %arg) {
+; LA32-LABEL: test_trunc_v4i64_to_v4i32:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v4i64_to_v4i32:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA64-NEXT:    ret
+  %trunc = trunc <4 x i64> %arg to <4 x i32>
+  ret <4 x i32> %trunc
+}
+
+define <8 x i8> @test_trunc_v8i32_to_v8i8(<8 x i32> %arg) {
+; LA32-LABEL: test_trunc_v8i32_to_v8i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 1
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 1
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 2
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 2
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 3
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 3
+; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 0
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 4
+; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 1
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 5
+; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 2
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 6
+; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 3
+; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 7
+; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i32_to_v8i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 0
+; LA64-NEXT:    vpickve2gr.w $a0, $vr0, 1
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 1
+; LA64-NEXT:    vpickve2gr.w $a0, $vr0, 2
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 2
+; LA64-NEXT:    vpickve2gr.w $a0, $vr0, 3
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 3
+; LA64-NEXT:    vpickve2gr.w $a0, $vr1, 0
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 4
+; LA64-NEXT:    vpickve2gr.w $a0, $vr1, 1
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 5
+; LA64-NEXT:    vpickve2gr.w $a0, $vr1, 2
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 6
+; LA64-NEXT:    vpickve2gr.w $a0, $vr1, 3
+; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 7
+; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <8 x i32> %arg to <8 x i8>
+  ret <8 x i8> %trunc
+}
+
+define <8 x i16> @test_trunc_v8i32_to_v8i16(<8 x i32> %arg) {
+; LA32-LABEL: test_trunc_v8i32_to_v8i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i32_to_v8i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA64-NEXT:    ret
+  %trunc = trunc <8 x i32> %arg to <8 x i16>
+  ret <8 x i16> %trunc
+}
+
+define <8 x i8> @test_trunc_v8i64_to_v8i8(<8 x i64> %arg) {
+; LA32-LABEL: test_trunc_v8i64_to_v8i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 0
+; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 2
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 1
+; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 0
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 2
+; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 2
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 3
+; LA32-NEXT:    vpickve2gr.w $a0, $vr2, 0
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 4
+; LA32-NEXT:    vpickve2gr.w $a0, $vr2, 2
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 5
+; LA32-NEXT:    vpickve2gr.w $a0, $vr3, 0
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 6
+; LA32-NEXT:    vpickve2gr.w $a0, $vr3, 2
+; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 7
+; LA32-NEXT:    vori.b $vr0, $vr4, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i64_to_v8i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 0
+; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 1
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 1
+; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 0
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 2
+; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 1
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 3
+; LA64-NEXT:    vpickve2gr.d $a0, $vr2, 0
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 4
+; LA64-NEXT:    vpickve2gr.d $a0, $vr2, 1
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 5
+; LA64-NEXT:    vpickve2gr.d $a0, $vr3, 0
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 6
+; LA64-NEXT:    vpickve2gr.d $a0, $vr3, 1
+; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 7
+; LA64-NEXT:    vori.b $vr0, $vr4, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <8 x i64> %arg to <8 x i8>
+  ret <8 x i8> %trunc
+}
+
+define <8 x i16> @test_trunc_v8i64_to_v8i16(<8 x i64> %arg) {
+; LA32-LABEL: test_trunc_v8i64_to_v8i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA32-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i64_to_v8i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA64-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA64-NEXT:    ret
+  %trunc = trunc <8 x i64> %arg to <8 x i16>
+  ret <8 x i16> %trunc
+}
+
+define <8 x i32> @test_trunc_v8i64_to_v8i32(<8 x i64> %arg) {
+; LA32-LABEL: test_trunc_v8i64_to_v8i32:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v8i64_to_v8i32:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA64-NEXT:    ret
+  %trunc = trunc <8 x i64> %arg to <8 x i32>
+  ret <8 x i32> %trunc
+}
+
+define <16 x i8> @test_trunc_v16i32_to_v16i8(<16 x i32> %arg) {
+; LA32-LABEL: test_trunc_v16i32_to_v16i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.h $vr1, $vr3, $vr2
+; LA32-NEXT:    vpickev.b $vr0, $vr1, $vr0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v16i32_to_v16i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.h $vr1, $vr3, $vr2
+; LA64-NEXT:    vpickev.b $vr0, $vr1, $vr0
+; LA64-NEXT:    ret
+  %trunc = trunc <16 x i32> %arg to <16 x i8>
+  ret <16 x i8> %trunc
+}
+
+define <16 x i16> @test_trunc_v16i32_to_v16i16(<16 x i32> %arg) {
+; LA32-LABEL: test_trunc_v16i32_to_v16i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.h $vr1, $vr3, $vr2
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v16i32_to_v16i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.h $vr1, $vr3, $vr2
+; LA64-NEXT:    ret
+  %trunc = trunc <16 x i32> %arg to <16 x i16>
+  ret <16 x i16> %trunc
+}
+
+define <16 x i8> @test_trunc_v16i64_to_v16i8(<16 x i64> %arg) {
+; LA32-LABEL: test_trunc_v16i64_to_v16i8:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA32-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.w $vr1, $vr5, $vr4
+; LA32-NEXT:    vpickev.w $vr2, $vr7, $vr6
+; LA32-NEXT:    vpickev.h $vr1, $vr2, $vr1
+; LA32-NEXT:    vpickev.b $vr0, $vr1, $vr0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v16i64_to_v16i8:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA64-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.w $vr1, $vr5, $vr4
+; LA64-NEXT:    vpickev.w $vr2, $vr7, $vr6
+; LA64-NEXT:    vpickev.h $vr1, $vr2, $vr1
+; LA64-NEXT:    vpickev.b $vr0, $vr1, $vr0
+; LA64-NEXT:    ret
+  %trunc = trunc <16 x i64> %arg to <16 x i8>
+  ret <16 x i8> %trunc
+}
+
+define <16 x i16> @test_trunc_v16i64_to_v16i16(<16 x i64> %arg) {
+; LA32-LABEL: test_trunc_v16i64_to_v16i16:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA32-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.w $vr1, $vr5, $vr4
+; LA32-NEXT:    vpickev.w $vr2, $vr7, $vr6
+; LA32-NEXT:    vpickev.h $vr1, $vr2, $vr1
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v16i64_to_v16i16:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA64-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.w $vr1, $vr5, $vr4
+; LA64-NEXT:    vpickev.w $vr2, $vr7, $vr6
+; LA64-NEXT:    vpickev.h $vr1, $vr2, $vr1
+; LA64-NEXT:    ret
+  %trunc = trunc <16 x i64> %arg to <16 x i16>
+  ret <16 x i16> %trunc
+}
+
+define <16 x i32> @test_trunc_v16i64_to_v16i32(<16 x i64> %arg) {
+; LA32-LABEL: test_trunc_v16i64_to_v16i32:
+; LA32:       # %bb.0:
+; LA32-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA32-NEXT:    vpickev.w $vr2, $vr5, $vr4
+; LA32-NEXT:    vpickev.w $vr3, $vr7, $vr6
+; LA32-NEXT:    vst $vr3, $a0, 48
+; LA32-NEXT:    vst $vr2, $a0, 32
+; LA32-NEXT:    vst $vr1, $a0, 16
+; LA32-NEXT:    vst $vr0, $a0, 0
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: test_trunc_v16i64_to_v16i32:
+; LA64:       # %bb.0:
+; LA64-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA64-NEXT:    vpickev.w $vr2, $vr5, $vr4
+; LA64-NEXT:    vpickev.w $vr3, $vr7, $vr6
+; LA64-NEXT:    vst $vr3, $a0, 48
+; LA64-NEXT:    vst $vr2, $a0, 32
+; LA64-NEXT:    vst $vr1, $a0, 16
+; LA64-NEXT:    vst $vr0, $a0, 0
+; LA64-NEXT:    ret
+  %trunc = trunc <16 x i64> %arg to <16 x i32>
+  ret <16 x i32> %trunc
+}

>From c8ed8e733e77266d6ce3fd7faec613ced55c89b5 Mon Sep 17 00:00:00 2001
From: Lin Runze <linrunze at loongson.cn>
Date: Thu, 4 Jun 2026 19:04:21 +0800
Subject: [PATCH 2/2] [LoongArch] Custom LSX and LASX truncate with [X]VPICKEV
 instruction

---
 .../LoongArch/LoongArchISelLowering.cpp       |  82 +++
 .../Target/LoongArch/LoongArchISelLowering.h  |   1 +
 .../LoongArch/lasx/vec-trunc-combine.ll       | 680 +++---------------
 .../LoongArch/lsx/vec-trunc-combine.ll        | 126 +---
 4 files changed, 221 insertions(+), 668 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 561064b3e1090..9234630f85848 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -408,6 +408,9 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
     for (MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
                    MVT::v16i64})
       setOperationAction(ISD::SIGN_EXTEND, VT, Custom);
+    for (MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
+                   MVT::v16i64})
+      setOperationAction(ISD::TRUNCATE, VT, Custom);
   }
 
   // Set operations for 'LASX' feature.
@@ -661,6 +664,8 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
     return lowerSIGN_EXTEND_VECTOR_INREG(Op, DAG);
   case ISD::DYNAMIC_STACKALLOC:
     return lowerDYNAMIC_STACKALLOC(Op, DAG);
+  case ISD::TRUNCATE:
+    return lowerTRUNCATE(Op, DAG);
   }
   return SDValue();
 }
@@ -1010,6 +1015,82 @@ SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
   return SDValue();
 }
 
+// For large vectors, we can use [X]VPICKEV to narrow the vector
+// recursively until it matches the destination type.
+// This is more efficient than bitcasting to a wider one
+// then shuffling, especially when the source vector is illegal
+// and needs to be constructed from multiple registers.
+SDValue LoongArchTargetLowering::lowerTRUNCATE(
+    SDValue Op, SelectionDAG &DAG) const {
+  SDLoc DL(Op);
+  SDValue Src = Op.getOperand(0);
+  EVT VT = Op.getValueType();
+  EVT SrcVT = Src.getValueType();
+
+  unsigned SrcBits = SrcVT.getSizeInBits();
+  unsigned SrcEltBits = SrcVT.getScalarSizeInBits();
+  unsigned DstEltBits = VT.getScalarSizeInBits();
+  unsigned BlockBits = Subtarget.hasExtLASX() ? 256 : 128;
+
+  SmallVector<SDValue, 8> Blocks;
+  unsigned MidNumElts = BlockBits / SrcEltBits;
+  MVT MidVT = MVT::getVectorVT(MVT::getIntegerVT(SrcEltBits), MidNumElts);
+  if (Src.getOpcode() == ISD::CONCAT_VECTORS &&
+      Src.getOperand(0).getValueSizeInBits() == BlockBits)
+    for (unsigned i = 0; i < Src.getNumOperands(); i++)
+      Blocks.push_back(Src.getOperand(i));
+  else if (SrcBits > BlockBits)
+    for (unsigned i = 0; i < SrcBits / BlockBits; i++)
+      Blocks.push_back(
+          DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, MidVT, Src,
+                      DAG.getVectorIdxConstant(i * MidNumElts, DL)));
+  else if (SrcBits < BlockBits)
+    Blocks.push_back(DAG.getNode(ISD::INSERT_SUBVECTOR, DL, MidVT,
+                                 DAG.getUNDEF(MidVT), Src,
+                                 DAG.getVectorIdxConstant(0, DL)));
+  else
+    Blocks.push_back(Src);
+
+
+  unsigned CurEltBits = SrcEltBits;
+  bool IsValidUpperBits = SrcBits >= BlockBits;
+  while (CurEltBits > DstEltBits) {
+    unsigned NarrowBits = CurEltBits / 2;
+    unsigned NarrowNumElts = BlockBits / NarrowBits;
+    MVT NarrowVT =
+        MVT::getVectorVT(MVT::getIntegerVT(NarrowBits), NarrowNumElts);
+
+    SmallVector<SDValue, 4> Next;
+    bool SelfPair = Blocks.size() <= 1;
+    for (unsigned i = 0; i < Blocks.size(); i += 2) {
+      SDValue Lo = Blocks[i];
+      SDValue Hi = SelfPair ? Lo : Blocks[i + 1];
+      SDValue Res = DAG.getNode(LoongArchISD::VPICKEV, DL, NarrowVT, Hi, Lo);
+
+      // Fix the data layout under LASX due to XVPICKEV is per 128-bit lane.
+      if (BlockBits == 256 && IsValidUpperBits) {
+        MVT PermVT = MVT::v4i64;
+        Res = DAG.getBitcast(PermVT, Res);
+        Res = DAG.getNode(
+            LoongArchISD::XVPERMI, DL, PermVT, Res,
+            DAG.getConstant(0b11011000, DL, Subtarget.getGRLenVT()));
+        Res = DAG.getBitcast(NarrowVT, Res);
+        // After the first self-pair, all valid data lives in the low 128 bits.
+        if (SelfPair)
+          IsValidUpperBits = false;
+      }
+
+      Next.push_back(Res);
+    }
+
+    Blocks = std::move(Next);
+    CurEltBits = NarrowBits;
+  }
+
+  return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, VT, Blocks[0],
+                     DAG.getVectorIdxConstant(0, DL));
+}
+
 // Lower vecreduce_add using vhaddw instructions.
 // For Example:
 //  call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %a)
@@ -5788,6 +5869,7 @@ void LoongArchTargetLowering::ReplaceNodeResults(
       }
     }
 
+    Results.push_back(lowerTRUNCATE(SDValue(N, 0), DAG));
     break;
   }
   case ISD::SIGN_EXTEND: {
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index 189ecbe4820d2..36874fc964dc1 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -259,6 +259,7 @@ class LoongArchTargetLowering : public TargetLowering {
   SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerSIGN_EXTEND_VECTOR_INREG(SDValue Op, SelectionDAG &DAG) const;
   SDValue lowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
+  SDValue lowerTRUNCATE(SDValue Op, SelectionDAG &DAG) const;
 
   bool isFPImmLegal(const APFloat &Imm, EVT VT,
                     bool ForCodeSize) const override;
diff --git a/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll b/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
index 77136eb165149..2a4ff9120de4c 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
@@ -51,28 +51,20 @@ define <4 x i16> @test_trunc_v4i32_to_v4i16(<4 x i32> %arg) {
 define <4 x i8> @test_trunc_v4i64_to_v4i8(<4 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v4i64_to_v4i8:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 3
-; LA32-NEXT:    vori.b $vr0, $vr1, 0
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; LA32-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v4i64_to_v4i8:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 3
-; LA64-NEXT:    vori.b $vr0, $vr1, 0
+; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; LA64-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA64-NEXT:    ret
   %trunc = trunc <4 x i64> %arg to <4 x i8>
   ret <4 x i8> %trunc
@@ -81,28 +73,18 @@ define <4 x i8> @test_trunc_v4i64_to_v4i8(<4 x i64> %arg) {
 define <4 x i16> @test_trunc_v4i64_to_v4i16(<4 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v4i64_to_v4i16:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 3
-; LA32-NEXT:    vori.b $vr0, $vr1, 0
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA32-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v4i64_to_v4i16:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 3
-; LA64-NEXT:    vori.b $vr0, $vr1, 0
+; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA64-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA64-NEXT:    ret
   %trunc = trunc <4 x i64> %arg to <4 x i16>
   ret <4 x i16> %trunc
@@ -111,28 +93,16 @@ define <4 x i16> @test_trunc_v4i64_to_v4i16(<4 x i64> %arg) {
 define <4 x i32> @test_trunc_v4i64_to_v4i32(<4 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v4i64_to_v4i32:
 ; LA32:       # %bb.0:
-; 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:    vori.b $vr0, $vr1, 0
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v4i64_to_v4i32:
 ; LA64:       # %bb.0:
-; 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:    vori.b $vr0, $vr1, 0
+; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA64-NEXT:    ret
   %trunc = trunc <4 x i64> %arg to <4 x i32>
   ret <4 x i32> %trunc
@@ -141,44 +111,18 @@ define <4 x i32> @test_trunc_v4i64_to_v4i32(<4 x i64> %arg) {
 define <8 x i8> @test_trunc_v8i32_to_v8i8(<8 x i32> %arg) {
 ; LA32-LABEL: test_trunc_v8i32_to_v8i8:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 1
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 3
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 4
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 5
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 5
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 6
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 7
-; LA32-NEXT:    vinsgr2vr.b $vr1, $a0, 7
-; LA32-NEXT:    vori.b $vr0, $vr1, 0
+; LA32-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; LA32-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v8i32_to_v8i8:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 0
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 1
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 2
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 3
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 4
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 5
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 5
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 6
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 7
-; LA64-NEXT:    vinsgr2vr.b $vr1, $a0, 7
-; LA64-NEXT:    vori.b $vr0, $vr1, 0
+; LA64-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; LA64-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA64-NEXT:    ret
   %trunc = trunc <8 x i32> %arg to <8 x i8>
   ret <8 x i8> %trunc
@@ -187,44 +131,16 @@ define <8 x i8> @test_trunc_v8i32_to_v8i8(<8 x i32> %arg) {
 define <8 x i16> @test_trunc_v8i32_to_v8i16(<8 x i32> %arg) {
 ; LA32-LABEL: test_trunc_v8i32_to_v8i16:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 1
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 3
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 4
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 5
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 5
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 6
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 7
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 7
-; LA32-NEXT:    vori.b $vr0, $vr1, 0
+; LA32-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v8i32_to_v8i16:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 0
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 1
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 2
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 3
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 4
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 5
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 5
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 6
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 7
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 7
-; LA64-NEXT:    vori.b $vr0, $vr1, 0
+; LA64-NEXT:    xvpickev.h $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA64-NEXT:    ret
   %trunc = trunc <8 x i32> %arg to <8 x i16>
   ret <8 x i16> %trunc
@@ -233,44 +149,22 @@ define <8 x i16> @test_trunc_v8i32_to_v8i16(<8 x i32> %arg) {
 define <8 x i8> @test_trunc_v8i64_to_v8i8(<8 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v8i64_to_v8i8:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 4
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 5
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 6
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 7
-; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; 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:    xvpickev.b $xr0, $xr0, $xr0
+; LA32-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v8i64_to_v8i8:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 3
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 4
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 5
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 6
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 7
-; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; 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:    xvpickev.b $xr0, $xr0, $xr0
+; LA64-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA64-NEXT:    ret
   %trunc = trunc <8 x i64> %arg to <8 x i8>
   ret <8 x i8> %trunc
@@ -279,44 +173,20 @@ define <8 x i8> @test_trunc_v8i64_to_v8i8(<8 x i64> %arg) {
 define <8 x i16> @test_trunc_v8i64_to_v8i16(<8 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v8i64_to_v8i16:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 4
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 5
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 6
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 7
-; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; 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:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v8i64_to_v8i16:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 3
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 4
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 5
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 6
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 7
-; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; 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:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA64-NEXT:    ret
   %trunc = trunc <8 x i64> %arg to <8 x i16>
   ret <8 x i16> %trunc
@@ -325,46 +195,14 @@ define <8 x i16> @test_trunc_v8i64_to_v8i16(<8 x i64> %arg) {
 define <8 x i32> @test_trunc_v8i64_to_v8i32(<8 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v8i64_to_v8i32:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
-; LA32-NEXT:    vinsgr2vr.w $vr2, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
-; LA32-NEXT:    vinsgr2vr.w $vr2, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
-; LA32-NEXT:    vinsgr2vr.w $vr2, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
-; LA32-NEXT:    vinsgr2vr.w $vr2, $a0, 3
-; 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:    xvpermi.q $xr1, $xr2, 2
-; LA32-NEXT:    xvori.b $xr0, $xr1, 0
+; LA32-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v8i64_to_v8i32:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
-; LA64-NEXT:    vinsgr2vr.w $vr2, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
-; LA64-NEXT:    vinsgr2vr.w $vr2, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
-; LA64-NEXT:    vinsgr2vr.w $vr2, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
-; LA64-NEXT:    vinsgr2vr.w $vr2, $a0, 3
-; 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:    xvpermi.q $xr1, $xr2, 2
-; LA64-NEXT:    xvori.b $xr0, $xr1, 0
+; LA64-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
 ; LA64-NEXT:    ret
   %trunc = trunc <8 x i64> %arg to <8 x i32>
   ret <8 x i32> %trunc
@@ -373,76 +211,20 @@ define <8 x i32> @test_trunc_v8i64_to_v8i32(<8 x i64> %arg) {
 define <16 x i8> @test_trunc_v16i32_to_v16i8(<16 x i32> %arg) {
 ; LA32-LABEL: test_trunc_v16i32_to_v16i8:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 1
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 3
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 4
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 5
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 5
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 6
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 7
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 7
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 8
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 1
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 9
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 10
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 3
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 11
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 12
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 5
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 13
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 14
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 7
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 15
-; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; LA32-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v16i32_to_v16i8:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 0
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 1
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 2
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 3
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 4
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 5
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 5
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 6
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 7
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 7
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 0
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 8
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 1
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 9
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 2
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 10
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 3
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 11
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 4
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 12
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 5
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 13
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 6
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 14
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 7
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 15
-; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; LA64-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA64-NEXT:    ret
   %trunc = trunc <16 x i32> %arg to <16 x i8>
   ret <16 x i8> %trunc
@@ -451,78 +233,14 @@ define <16 x i8> @test_trunc_v16i32_to_v16i8(<16 x i32> %arg) {
 define <16 x i16> @test_trunc_v16i32_to_v16i16(<16 x i32> %arg) {
 ; LA32-LABEL: test_trunc_v16i32_to_v16i16:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 1
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 3
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 4
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 5
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 5
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 6
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 7
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 7
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 1
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 3
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 4
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 5
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 5
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 6
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 7
-; LA32-NEXT:    vinsgr2vr.h $vr1, $a0, 7
-; LA32-NEXT:    xvpermi.q $xr1, $xr2, 2
-; LA32-NEXT:    xvori.b $xr0, $xr1, 0
+; LA32-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v16i32_to_v16i16:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 0
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 0
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 1
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 1
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 2
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 2
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 3
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 3
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 4
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 4
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 5
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 5
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 6
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 6
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr1, 7
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 7
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 0
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 1
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 2
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 3
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 4
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 5
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 5
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 6
-; LA64-NEXT:    xvpickve2gr.w $a0, $xr0, 7
-; LA64-NEXT:    vinsgr2vr.h $vr1, $a0, 7
-; LA64-NEXT:    xvpermi.q $xr1, $xr2, 2
-; LA64-NEXT:    xvori.b $xr0, $xr1, 0
+; LA64-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
 ; LA64-NEXT:    ret
   %trunc = trunc <16 x i32> %arg to <16 x i16>
   ret <16 x i16> %trunc
@@ -531,76 +249,28 @@ define <16 x i16> @test_trunc_v16i32_to_v16i16(<16 x i32> %arg) {
 define <16 x i8> @test_trunc_v16i64_to_v16i8(<16 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v16i64_to_v16i8:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 4
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 5
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 6
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 7
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 0
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 8
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 2
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 9
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 4
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 10
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 6
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 11
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 0
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 12
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 2
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 13
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 4
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 14
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 6
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 15
-; LA32-NEXT:    vori.b $vr0, $vr4, 0
+; LA32-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    xvpickev.w $xr1, $xr3, $xr2
+; LA32-NEXT:    xvpermi.d $xr1, $xr1, 216
+; LA32-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v16i64_to_v16i8:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 3
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 4
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 5
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 6
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 7
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 0
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 8
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 1
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 9
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 2
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 10
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 3
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 11
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 0
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 12
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 1
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 13
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 2
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 14
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 3
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 15
-; LA64-NEXT:    vori.b $vr0, $vr4, 0
+; LA64-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    xvpickev.w $xr1, $xr3, $xr2
+; LA64-NEXT:    xvpermi.d $xr1, $xr1, 216
+; LA64-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    xvpickev.b $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    # kill: def $vr0 killed $vr0 killed $xr0
 ; LA64-NEXT:    ret
   %trunc = trunc <16 x i64> %arg to <16 x i8>
   ret <16 x i8> %trunc
@@ -609,78 +279,22 @@ define <16 x i8> @test_trunc_v16i64_to_v16i8(<16 x i64> %arg) {
 define <16 x i16> @test_trunc_v16i64_to_v16i16(<16 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v16i64_to_v16i16:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 0
-; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 2
-; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 4
-; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 6
-; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 0
-; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 4
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 2
-; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 5
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 4
-; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 6
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 6
-; LA32-NEXT:    vinsgr2vr.h $vr4, $a0, 7
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 4
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 5
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 6
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 7
-; LA32-NEXT:    xvpermi.q $xr2, $xr4, 2
-; LA32-NEXT:    xvori.b $xr0, $xr2, 0
+; LA32-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    xvpickev.w $xr1, $xr3, $xr2
+; LA32-NEXT:    xvpermi.d $xr1, $xr1, 216
+; LA32-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v16i64_to_v16i16:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 0
-; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 1
-; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 2
-; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 3
-; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 3
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 0
-; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 4
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 1
-; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 5
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 2
-; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 6
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 3
-; LA64-NEXT:    vinsgr2vr.h $vr4, $a0, 7
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 3
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 4
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 5
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 6
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 7
-; LA64-NEXT:    xvpermi.q $xr2, $xr4, 2
-; LA64-NEXT:    xvori.b $xr0, $xr2, 0
+; LA64-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    xvpickev.w $xr1, $xr3, $xr2
+; LA64-NEXT:    xvpermi.d $xr1, $xr1, 216
+; LA64-NEXT:    xvpickev.h $xr0, $xr1, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
 ; LA64-NEXT:    ret
   %trunc = trunc <16 x i64> %arg to <16 x i16>
   ret <16 x i16> %trunc
@@ -689,80 +303,18 @@ define <16 x i16> @test_trunc_v16i64_to_v16i16(<16 x i64> %arg) {
 define <16 x i32> @test_trunc_v16i64_to_v16i32(<16 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v16i64_to_v16i32:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 0
-; LA32-NEXT:    vinsgr2vr.w $vr5, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 2
-; LA32-NEXT:    vinsgr2vr.w $vr5, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 4
-; LA32-NEXT:    vinsgr2vr.w $vr5, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr1, 6
-; LA32-NEXT:    vinsgr2vr.w $vr5, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.w $vr4, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.w $vr4, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.w $vr4, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.w $vr4, $a0, 3
-; LA32-NEXT:    xvpermi.q $xr4, $xr5, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 0
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 2
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 4
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr3, 6
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a0, 3
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 0
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 2
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 4
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr2, 6
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 3
-; LA32-NEXT:    xvpermi.q $xr1, $xr0, 2
-; LA32-NEXT:    xvori.b $xr0, $xr4, 0
+; LA32-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    xvpickev.w $xr1, $xr3, $xr2
+; LA32-NEXT:    xvpermi.d $xr1, $xr1, 216
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v16i64_to_v16i32:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 0
-; LA64-NEXT:    vinsgr2vr.w $vr5, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 1
-; LA64-NEXT:    vinsgr2vr.w $vr5, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 2
-; LA64-NEXT:    vinsgr2vr.w $vr5, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr1, 3
-; LA64-NEXT:    vinsgr2vr.w $vr5, $a0, 3
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.w $vr4, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.w $vr4, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.w $vr4, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.w $vr4, $a0, 3
-; LA64-NEXT:    xvpermi.q $xr4, $xr5, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 0
-; LA64-NEXT:    vinsgr2vr.w $vr0, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 1
-; LA64-NEXT:    vinsgr2vr.w $vr0, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 2
-; LA64-NEXT:    vinsgr2vr.w $vr0, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr3, 3
-; LA64-NEXT:    vinsgr2vr.w $vr0, $a0, 3
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 0
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 1
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 2
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr2, 3
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 3
-; LA64-NEXT:    xvpermi.q $xr1, $xr0, 2
-; LA64-NEXT:    xvori.b $xr0, $xr4, 0
+; LA64-NEXT:    xvpickev.w $xr0, $xr1, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    xvpickev.w $xr1, $xr3, $xr2
+; LA64-NEXT:    xvpermi.d $xr1, $xr1, 216
 ; LA64-NEXT:    ret
   %trunc = trunc <16 x i64> %arg to <16 x i32>
   ret <16 x i32> %trunc
diff --git a/llvm/test/CodeGen/LoongArch/lsx/vec-trunc-combine.ll b/llvm/test/CodeGen/LoongArch/lsx/vec-trunc-combine.ll
index 2ce0ad7831cb9..51ef91846e3c5 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/vec-trunc-combine.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/vec-trunc-combine.ll
@@ -51,28 +51,16 @@ define <4 x i16> @test_trunc_v4i32_to_v4i16(<4 x i32> %arg) {
 define <4 x i8> @test_trunc_v4i64_to_v4i8(<4 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v4i64_to_v4i8:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 0
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 2
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 1
-; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 0
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 2
-; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 2
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 3
-; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; LA32-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.h $vr0, $vr0, $vr0
+; LA32-NEXT:    vpickev.b $vr0, $vr0, $vr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v4i64_to_v4i8:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 0
-; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 1
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 1
-; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 0
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 2
-; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 1
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 3
-; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; LA64-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.h $vr0, $vr0, $vr0
+; LA64-NEXT:    vpickev.b $vr0, $vr0, $vr0
 ; LA64-NEXT:    ret
   %trunc = trunc <4 x i64> %arg to <4 x i8>
   ret <4 x i8> %trunc
@@ -81,28 +69,14 @@ define <4 x i8> @test_trunc_v4i64_to_v4i8(<4 x i64> %arg) {
 define <4 x i16> @test_trunc_v4i64_to_v4i16(<4 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v4i64_to_v4i16:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 0
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 2
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 1
-; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 0
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 2
-; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 2
-; LA32-NEXT:    vinsgr2vr.h $vr2, $a0, 3
-; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; LA32-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.h $vr0, $vr0, $vr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v4i64_to_v4i16:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 0
-; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 1
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 1
-; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 0
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 2
-; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 1
-; LA64-NEXT:    vinsgr2vr.h $vr2, $a0, 3
-; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; LA64-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.h $vr0, $vr0, $vr0
 ; LA64-NEXT:    ret
   %trunc = trunc <4 x i64> %arg to <4 x i16>
   ret <4 x i16> %trunc
@@ -125,44 +99,14 @@ define <4 x i32> @test_trunc_v4i64_to_v4i32(<4 x i64> %arg) {
 define <8 x i8> @test_trunc_v8i32_to_v8i8(<8 x i32> %arg) {
 ; LA32-LABEL: test_trunc_v8i32_to_v8i8:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 0
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 1
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 1
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 2
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 2
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 3
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 3
-; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 0
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 4
-; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 1
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 5
-; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 2
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 6
-; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 3
-; LA32-NEXT:    vinsgr2vr.b $vr2, $a0, 7
-; LA32-NEXT:    vori.b $vr0, $vr2, 0
+; LA32-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.b $vr0, $vr0, $vr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v8i32_to_v8i8:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    vpickve2gr.w $a0, $vr0, 0
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 0
-; LA64-NEXT:    vpickve2gr.w $a0, $vr0, 1
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 1
-; LA64-NEXT:    vpickve2gr.w $a0, $vr0, 2
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 2
-; LA64-NEXT:    vpickve2gr.w $a0, $vr0, 3
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 3
-; LA64-NEXT:    vpickve2gr.w $a0, $vr1, 0
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 4
-; LA64-NEXT:    vpickve2gr.w $a0, $vr1, 1
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 5
-; LA64-NEXT:    vpickve2gr.w $a0, $vr1, 2
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 6
-; LA64-NEXT:    vpickve2gr.w $a0, $vr1, 3
-; LA64-NEXT:    vinsgr2vr.b $vr2, $a0, 7
-; LA64-NEXT:    vori.b $vr0, $vr2, 0
+; LA64-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.b $vr0, $vr0, $vr0
 ; LA64-NEXT:    ret
   %trunc = trunc <8 x i32> %arg to <8 x i8>
   ret <8 x i8> %trunc
@@ -185,44 +129,18 @@ define <8 x i16> @test_trunc_v8i32_to_v8i16(<8 x i32> %arg) {
 define <8 x i8> @test_trunc_v8i64_to_v8i8(<8 x i64> %arg) {
 ; LA32-LABEL: test_trunc_v8i64_to_v8i8:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 0
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 0
-; LA32-NEXT:    vpickve2gr.w $a0, $vr0, 2
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 1
-; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 0
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 2
-; LA32-NEXT:    vpickve2gr.w $a0, $vr1, 2
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 3
-; LA32-NEXT:    vpickve2gr.w $a0, $vr2, 0
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 4
-; LA32-NEXT:    vpickve2gr.w $a0, $vr2, 2
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 5
-; LA32-NEXT:    vpickve2gr.w $a0, $vr3, 0
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 6
-; LA32-NEXT:    vpickve2gr.w $a0, $vr3, 2
-; LA32-NEXT:    vinsgr2vr.b $vr4, $a0, 7
-; LA32-NEXT:    vori.b $vr0, $vr4, 0
+; LA32-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA32-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA32-NEXT:    vpickev.b $vr0, $vr0, $vr0
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_trunc_v8i64_to_v8i8:
 ; LA64:       # %bb.0:
-; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 0
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 0
-; LA64-NEXT:    vpickve2gr.d $a0, $vr0, 1
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 1
-; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 0
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 2
-; LA64-NEXT:    vpickve2gr.d $a0, $vr1, 1
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 3
-; LA64-NEXT:    vpickve2gr.d $a0, $vr2, 0
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 4
-; LA64-NEXT:    vpickve2gr.d $a0, $vr2, 1
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 5
-; LA64-NEXT:    vpickve2gr.d $a0, $vr3, 0
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 6
-; LA64-NEXT:    vpickve2gr.d $a0, $vr3, 1
-; LA64-NEXT:    vinsgr2vr.b $vr4, $a0, 7
-; LA64-NEXT:    vori.b $vr0, $vr4, 0
+; LA64-NEXT:    vpickev.w $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.w $vr1, $vr3, $vr2
+; LA64-NEXT:    vpickev.h $vr0, $vr1, $vr0
+; LA64-NEXT:    vpickev.b $vr0, $vr0, $vr0
 ; LA64-NEXT:    ret
   %trunc = trunc <8 x i64> %arg to <8 x i8>
   ret <8 x i8> %trunc



More information about the llvm-commits mailing list