[llvm] [LoongArch] Legalize LASX truncate with XVPICKEV instruction (PR #202485)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 9 06:19:11 PDT 2026


https://github.com/lrzlin updated https://github.com/llvm/llvm-project/pull/202485

>From 6fe72619cd4ebf41033dd0278f9f059e4372ec0c 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 truncate tests for LASX

---
 .../LoongArch/lasx/vec-trunc-combine.ll       | 769 ++++++++++++++++++
 1 file changed, 769 insertions(+)
 create mode 100644 llvm/test/CodeGen/LoongArch/lasx/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
+}

>From 6e43cd102d8412c87b8d0d25384e6b3d024dc47d Mon Sep 17 00:00:00 2001
From: Lin Runze <linrunze at loongson.cn>
Date: Sat, 6 Jun 2026 17:26:42 +0800
Subject: [PATCH 2/2] [LoongArch] Legalize LASX truncate with XVPICKEV
 instruction

---
 .../LoongArch/LoongArchISelLowering.cpp       |  19 +
 .../LoongArch/LoongArchLASXInstrInfo.td       |  19 +
 .../LoongArch/lasx/vec-trunc-combine.ll       | 674 +++---------------
 .../test/CodeGen/LoongArch/lasx/vxi1-masks.ll |  71 +-
 llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll |  51 +-
 llvm/test/CodeGen/LoongArch/pr177863.ll       |  24 +-
 6 files changed, 203 insertions(+), 655 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 561064b3e1090..02e341f26fd54 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -493,6 +493,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
       setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, VT, Legal);
       setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, VT, Legal);
     }
+    for (MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
+      setOperationAction(ISD::TRUNCATE, VT, Legal);
   }
 
   // Set DAG combine for LA32 and LA64.
@@ -3813,6 +3815,10 @@ SDValue LoongArchTargetLowering::lowerCONCAT_VECTORS(SDValue Op,
   MVT ResVT = Op.getSimpleValueType();
   assert(ResVT.is256BitVector() && Op.getNumOperands() == 2);
 
+  if (Op.getOperand(0).getOpcode() == ISD::TRUNCATE &&
+      Op.getOperand(1).getOpcode() == ISD::TRUNCATE)
+    return Op;
+
   unsigned NumOperands = Op.getNumOperands();
   unsigned NumFreezeUndef = 0;
   unsigned NumZero = 0;
@@ -5766,6 +5772,19 @@ void LoongArchTargetLowering::ReplaceNodeResults(
     unsigned WidenNumElts = WidenVT.getVectorNumElements();
     unsigned InBits = InVT.getSizeInBits();
 
+    if (InBits == 512 && WidenVT.is128BitVector()) {
+      InVT = MVT::getVectorVT(MVT::getIntegerVT(256 / MinElts), MinElts);
+      In = DAG.getNode(N->getOpcode(), DL, InVT, In);
+      InBits = 256;
+    }
+
+    if (InBits == 256 && WidenVT.is128BitVector()) {
+      InVT = MVT::getVectorVT(MVT::getIntegerVT(128 / MinElts), MinElts);
+      In = DAG.getNode(N->getOpcode(), DL, InVT, In);
+      InBits = 128;
+      InEltVT = InVT.getVectorElementType();
+    }
+
     if ((128 % InBits) == 0 && WidenVT.is128BitVector()) {
       if ((InEltVT.getSizeInBits() % EltVT.getSizeInBits()) == 0) {
         int Scale = InEltVT.getSizeInBits() / EltVT.getSizeInBits();
diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index 0fb2b1d332f60..24e68822dd7dc 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -2120,6 +2120,25 @@ def : Pat<(v4i32(fp_to_uint v4f64:$vj)),
                (XVFTINTRZ_LU_D v4f64:$vj)),
               sub_128)>;
 
+// truncate
+def : Pat<(v4i32 (trunc v4i64:$xj)),
+          (EXTRACT_SUBREG(XVPERMI_D(XVPICKEV_W v4i64:$xj, v4i64:$xj), 216), sub_128)>;
+
+def : Pat<(v8i16 (trunc v8i32:$xj)),
+          (EXTRACT_SUBREG(XVPERMI_D(XVPICKEV_H v8i32:$xj, v8i32:$xj), 216), sub_128)>;
+
+def : Pat<(v16i8 (trunc v16i16:$xj)),
+          (EXTRACT_SUBREG(XVPERMI_D(XVPICKEV_B v16i16:$xj, v16i16:$xj), 216), sub_128)>;
+
+def : Pat<(v8i32 (concat_vectors (v4i32 (trunc v4i64:$xj)), (v4i32 (trunc v4i64:$xk)))),
+          (XVPERMI_D(XVPICKEV_W v4i64:$xk, v4i64:$xj), 216)>;
+
+def : Pat<(v16i16 (concat_vectors (v8i16 (trunc v8i32:$xj)), (v8i16 (trunc v8i32:$xk)))),
+          (XVPERMI_D(XVPICKEV_H v8i32:$xk, v8i32:$xj), 216)>;
+
+def : Pat<(v32i8 (concat_vectors (v16i8 (trunc v16i16:$xj)), (v16i8 (trunc v16i16:$xk)))),
+          (XVPERMI_D(XVPICKEV_B v16i16:$xk, v16i16:$xj), 216)>;
+
 // XVAVG_{B/H/W/D/BU/HU/WU/DU}, XVAVGR_{B/H/W/D/BU/HU/WU/DU}
 defm : PatXrXr<avgfloors, "XVAVG">;
 defm : PatXrXr<avgceils, "XVAVGR">;
diff --git a/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll b/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
index 77136eb165149..7ec3cf05e63e7 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:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
+; LA32-NEXT:    vld $vr1, $a0, %pc_lo12(.LCPI3_0)
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vshuf.b $vr0, $vr0, $vr0, $vr1
 ; LA32-NEXT:    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:    pcalau12i $a0, %pc_hi20(.LCPI3_0)
+; LA64-NEXT:    vld $vr1, $a0, %pc_lo12(.LCPI3_0)
+; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vshuf.b $vr0, $vr0, $vr0, $vr1
 ; LA64-NEXT:    ret
   %trunc = trunc <4 x i64> %arg to <4 x i8>
   ret <4 x i8> %trunc
@@ -81,28 +73,16 @@ 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:    vpickev.h $vr0, $vr0, $vr0
 ; 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:    vpickev.h $vr0, $vr0, $vr0
 ; LA64-NEXT:    ret
   %trunc = trunc <4 x i64> %arg to <4 x i16>
   ret <4 x i16> %trunc
@@ -111,28 +91,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 +109,16 @@ 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:    vpickev.b $vr0, $vr0, $vr0
 ; 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:    vpickev.b $vr0, $vr0, $vr0
 ; LA64-NEXT:    ret
   %trunc = trunc <8 x i32> %arg to <8 x i8>
   ret <8 x i8> %trunc
@@ -187,44 +127,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 +145,20 @@ 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:    vpickev.b $vr0, $vr0, $vr0
 ; 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:    vpickev.b $vr0, $vr0, $vr0
 ; LA64-NEXT:    ret
   %trunc = trunc <8 x i64> %arg to <8 x i8>
   ret <8 x i8> %trunc
@@ -279,44 +167,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 +189,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 +205,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 +227,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 +243,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 +273,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 +297,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/lasx/vxi1-masks.ll b/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
index cb28d79b0dd51..bd17e67d19fa3 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
@@ -8,16 +8,10 @@ define void @xor_zext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 0
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 2
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 3
-; LA32-NEXT:    vldi $vr0, -1777
-; LA32-NEXT:    vxor.v $vr0, $vr1, $vr0
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vxor.v $vr0, $vr0, $vr1
 ; LA32-NEXT:    vextrins.w $vr1, $vr0, 2
 ; LA32-NEXT:    vextrins.w $vr1, $vr0, 35
 ; LA32-NEXT:    vextrins.w $vr0, $vr0, 33
@@ -97,16 +91,10 @@ define void @xor_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 0
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 2
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 3
-; LA32-NEXT:    vldi $vr0, -1777
-; LA32-NEXT:    vxor.v $vr0, $vr1, $vr0
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vxor.v $vr0, $vr0, $vr1
 ; LA32-NEXT:    vext2xv.d.w $xr0, $xr0
 ; LA32-NEXT:    xvst $xr0, $a0, 0
 ; LA32-NEXT:    ret
@@ -181,14 +169,13 @@ define void @or_zext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT:    xvpickve2gr.w $a2, $xr0, 2
-; LA32-NEXT:    vrepli.b $vr0, -1
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a2, 1
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a1, 3
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vor.v $vr0, $vr0, $vr1
 ; LA32-NEXT:    vextrins.w $vr1, $vr0, 2
+; LA32-NEXT:    vextrins.w $vr1, $vr0, 35
 ; LA32-NEXT:    vextrins.w $vr0, $vr0, 33
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a1, 2
 ; LA32-NEXT:    xvpermi.q $xr0, $xr1, 2
 ; LA32-NEXT:    xvrepli.d $xr1, 1
 ; LA32-NEXT:    xvand.v $xr0, $xr0, $xr1
@@ -265,11 +252,10 @@ define void @or_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT:    xvpickve2gr.w $a2, $xr0, 2
-; LA32-NEXT:    vrepli.b $vr0, -1
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a2, 1
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a1, 3
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vor.v $vr0, $vr0, $vr1
 ; LA32-NEXT:    vext2xv.d.w $xr0, $xr0
 ; LA32-NEXT:    xvst $xr0, $a0, 0
 ; LA32-NEXT:    ret
@@ -341,10 +327,16 @@ define void @and_zext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvrepli.b $xr1, 0
-; LA32-NEXT:    xvextrins.w $xr1, $xr0, 0
-; LA32-NEXT:    xvrepli.d $xr0, 1
-; LA32-NEXT:    xvand.v $xr0, $xr1, $xr0
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr1
+; LA32-NEXT:    vextrins.w $vr1, $vr0, 2
+; LA32-NEXT:    vextrins.w $vr1, $vr0, 35
+; LA32-NEXT:    vextrins.w $vr0, $vr0, 33
+; LA32-NEXT:    xvpermi.q $xr0, $xr1, 2
+; LA32-NEXT:    xvrepli.d $xr1, 1
+; LA32-NEXT:    xvand.v $xr0, $xr0, $xr1
 ; LA32-NEXT:    xvst $xr0, $a0, 0
 ; LA32-NEXT:    ret
 ;
@@ -412,11 +404,10 @@ define void @and_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
 ; LA32-NEXT:    xvld $xr0, $a1, 0
 ; LA32-NEXT:    xvld $xr1, $a2, 0
 ; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT:    xvpickve2gr.w $a2, $xr0, 0
-; LA32-NEXT:    vrepli.b $vr0, 0
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a2, 0
-; LA32-NEXT:    vinsgr2vr.w $vr0, $a1, 2
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vldi $vr1, -1777
+; LA32-NEXT:    vand.v $vr0, $vr0, $vr1
 ; LA32-NEXT:    vext2xv.d.w $xr0, $xr0
 ; LA32-NEXT:    xvst $xr0, $a0, 0
 ; LA32-NEXT:    ret
diff --git a/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll b/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
index ca61e69f1b378..bb8cc2abbec35 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
@@ -883,39 +883,24 @@ define i8 @xvmsk_ne_v4i32_concat_poison(<4 x i32> %vec) {
 }
 
 define i8 @xvmsk_ogt_v4f64_concat_poison(<4 x double> %vec) {
-; LA32-LABEL: xvmsk_ogt_v4f64_concat_poison:
-; LA32:       # %bb.0:
-; LA32-NEXT:    xvrepli.b $xr1, 0
-; LA32-NEXT:    xvfcmp.clt.d $xr0, $xr1, $xr0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT:    xvpickve2gr.w $a2, $xr0, 2
-; LA32-NEXT:    xvpickve2gr.w $a3, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.h $vr0, $a3, 0
-; LA32-NEXT:    vinsgr2vr.h $vr0, $a2, 1
-; LA32-NEXT:    vinsgr2vr.h $vr0, $a1, 2
-; LA32-NEXT:    vinsgr2vr.h $vr0, $a0, 3
-; LA32-NEXT:    vslli.h $vr0, $vr0, 15
-; LA32-NEXT:    vmskltz.h $vr0, $vr0
-; LA32-NEXT:    vpickve2gr.hu $a0, $vr0, 0
-; LA32-NEXT:    ret
-;
-; LA64-LABEL: xvmsk_ogt_v4f64_concat_poison:
-; LA64:       # %bb.0:
-; LA64-NEXT:    xvrepli.b $xr1, 0
-; LA64-NEXT:    xvfcmp.clt.d $xr0, $xr1, $xr0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    xvpickve2gr.d $a1, $xr0, 2
-; LA64-NEXT:    xvpickve2gr.d $a2, $xr0, 1
-; LA64-NEXT:    xvpickve2gr.d $a3, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.h $vr0, $a3, 0
-; LA64-NEXT:    vinsgr2vr.h $vr0, $a2, 1
-; LA64-NEXT:    vinsgr2vr.h $vr0, $a1, 2
-; LA64-NEXT:    vinsgr2vr.h $vr0, $a0, 3
-; LA64-NEXT:    vslli.h $vr0, $vr0, 15
-; LA64-NEXT:    vmskltz.h $vr0, $vr0
-; LA64-NEXT:    vpickve2gr.hu $a0, $vr0, 0
-; LA64-NEXT:    ret
+; CHECK-LABEL: xvmsk_ogt_v4f64_concat_poison:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    xvrepli.b $xr1, 0
+; CHECK-NEXT:    xvfcmp.clt.d $xr0, $xr1, $xr0
+; CHECK-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 0
+; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 0
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 1
+; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 1
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 2
+; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 2
+; CHECK-NEXT:    vpickve2gr.w $a0, $vr0, 3
+; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 3
+; CHECK-NEXT:    vslli.h $vr0, $vr1, 15
+; CHECK-NEXT:    vmskltz.h $vr0, $vr0
+; CHECK-NEXT:    vpickve2gr.hu $a0, $vr0, 0
+; CHECK-NEXT:    ret
   %tobool = fcmp ogt <4 x double> %vec, zeroinitializer
   %insertvec = shufflevector <4 x i1> %tobool, <4 x i1> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
   %res = bitcast <8 x i1> %insertvec to i8
diff --git a/llvm/test/CodeGen/LoongArch/pr177863.ll b/llvm/test/CodeGen/LoongArch/pr177863.ll
index 54fa02162ee0d..c8fbba8500fc2 100644
--- a/llvm/test/CodeGen/LoongArch/pr177863.ll
+++ b/llvm/test/CodeGen/LoongArch/pr177863.ll
@@ -7,29 +7,17 @@ define <4 x i1> @test(<4 x i64> %shuffle2, <4 x i64> %shuffle4) {
 ; LA32-LABEL: test:
 ; LA32:       # %bb.0: # %entry
 ; LA32-NEXT:    xvseq.d $xr0, $xr1, $xr0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 0
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 1
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 2
-; LA32-NEXT:    xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT:    vinsgr2vr.w $vr1, $a0, 3
-; LA32-NEXT:    vxori.b $vr0, $vr1, 255
+; LA32-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT:    vxori.b $vr0, $vr0, 255
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test:
 ; LA64:       # %bb.0: # %entry
 ; LA64-NEXT:    xvseq.d $xr0, $xr1, $xr0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 0
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 0
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 1
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 1
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 2
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 2
-; LA64-NEXT:    xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT:    vinsgr2vr.w $vr1, $a0, 3
-; LA64-NEXT:    vxori.b $vr0, $vr1, 255
+; LA64-NEXT:    xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT:    xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT:    vxori.b $vr0, $vr0, 255
 ; LA64-NEXT:    ret
 entry:
   %conv5 = trunc nuw <4 x i64> %shuffle4 to <4 x i32>



More information about the llvm-commits mailing list