[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