[llvm] 24fb629 - [LoongArch] Legalize LASX truncate with XVPICKEV instruction (#202485)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 28 18:46:17 PDT 2026
Author: lrzlin
Date: 2026-06-29T09:46:12+08:00
New Revision: 24fb629a8b43dd443a4d854d2ea18af786251df2
URL: https://github.com/llvm/llvm-project/commit/24fb629a8b43dd443a4d854d2ea18af786251df2
DIFF: https://github.com/llvm/llvm-project/commit/24fb629a8b43dd443a4d854d2ea18af786251df2.diff
LOG: [LoongArch] Legalize LASX truncate with XVPICKEV instruction (#202485)
Add LASX truncate patterns for wide truncates (e.g. `v8i64 trunc to
v8i8`) with `XVPICKEV` instructions.
To merge two registers into one, return concat_vectors as is while its
two operations are `ISD::TRUNCATE`, also dealing with illegal results in
`ReplaceNodeResults`.
Added:
llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
Modified:
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
llvm/test/CodeGen/LoongArch/pr177863.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 61e77c35fef9d..702006221934f 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -494,6 +494,8 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, VT, Legal);
setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, VT, Legal);
}
+ for (MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
+ setOperationAction(ISD::TRUNCATE, VT, Legal);
}
// Set DAG combine for LA32 and LA64.
@@ -3822,6 +3824,10 @@ SDValue LoongArchTargetLowering::lowerCONCAT_VECTORS(SDValue Op,
MVT ResVT = Op.getSimpleValueType();
assert(ResVT.is256BitVector() && Op.getNumOperands() == 2);
+ if (Op.getOperand(0).getOpcode() == ISD::TRUNCATE &&
+ Op.getOperand(1).getOpcode() == ISD::TRUNCATE)
+ return Op;
+
unsigned NumOperands = Op.getNumOperands();
unsigned NumFreezeUndef = 0;
unsigned NumZero = 0;
@@ -5821,6 +5827,22 @@ void LoongArchTargetLowering::ReplaceNodeResults(
unsigned WidenNumElts = WidenVT.getVectorNumElements();
unsigned InBits = InVT.getSizeInBits();
+ // v8i64 -> (v8i32) -> v8i8
+ if (InVT == MVT::v8i64 && WidenVT.is128BitVector()) {
+ InVT = MVT::getVectorVT(MVT::getIntegerVT(256 / MinElts), MinElts);
+ In = DAG.getNode(N->getOpcode(), DL, InVT, In);
+ InBits = 256;
+ }
+
+ // v8i32 -> v8i8 / v4i64 -> v4i16 / v4i64 -> v4i8
+ if ((InVT == MVT::v8i32 || InVT == MVT::v4i64) &&
+ WidenVT.is128BitVector()) {
+ InVT = MVT::getVectorVT(MVT::getIntegerVT(128 / MinElts), MinElts);
+ In = DAG.getNode(N->getOpcode(), DL, InVT, In);
+ InBits = 128;
+ InEltVT = InVT.getVectorElementType();
+ }
+
if ((128 % InBits) == 0 && WidenVT.is128BitVector()) {
if ((InEltVT.getSizeInBits() % EltVT.getSizeInBits()) == 0) {
int Scale = InEltVT.getSizeInBits() / EltVT.getSizeInBits();
diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index aac824252dd41..21d937d5b4275 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -2168,6 +2168,25 @@ def : Pat<(v4i32(fp_to_uint v4f64:$vj)),
def : Pat<(v8i32 (loongarch_vftintrz_w_d (v4f64 LASX256:$xj), (v4f64 LASX256:$xk))),
(XVFTINTRZ_W_D LASX256:$xj, LASX256:$xk)>;
+// truncate
+def : Pat<(v4i32 (trunc v4i64:$xj)),
+ (EXTRACT_SUBREG(XVPERMI_D(XVPICKEV_W v4i64:$xj, v4i64:$xj), 216), sub_128)>;
+
+def : Pat<(v8i16 (trunc v8i32:$xj)),
+ (EXTRACT_SUBREG(XVPERMI_D(XVPICKEV_H v8i32:$xj, v8i32:$xj), 216), sub_128)>;
+
+def : Pat<(v16i8 (trunc v16i16:$xj)),
+ (EXTRACT_SUBREG(XVPERMI_D(XVPICKEV_B v16i16:$xj, v16i16:$xj), 216), sub_128)>;
+
+def : Pat<(v8i32 (concat_vectors (v4i32 (trunc v4i64:$xj)), (v4i32 (trunc v4i64:$xk)))),
+ (XVPERMI_D(XVPICKEV_W v4i64:$xk, v4i64:$xj), 216)>;
+
+def : Pat<(v16i16 (concat_vectors (v8i16 (trunc v8i32:$xj)), (v8i16 (trunc v8i32:$xk)))),
+ (XVPERMI_D(XVPICKEV_H v8i32:$xk, v8i32:$xj), 216)>;
+
+def : Pat<(v32i8 (concat_vectors (v16i8 (trunc v16i16:$xj)), (v16i8 (trunc v16i16:$xk)))),
+ (XVPERMI_D(XVPICKEV_B v16i16:$xk, v16i16:$xj), 216)>;
+
// XVAVG_{B/H/W/D/BU/HU/WU/DU}, XVAVGR_{B/H/W/D/BU/HU/WU/DU}
defm : PatXrXr<avgfloors, "XVAVG">;
defm : PatXrXr<avgceils, "XVAVGR">;
diff --git a/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll b/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
new file mode 100644
index 0000000000000..a152053eceb06
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/vec-trunc-combine.ll
@@ -0,0 +1,348 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lasx %s -o - | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lasx %s -o - | FileCheck %s --check-prefixes=CHECK,LA64
+
+define void @test_trunc_v4i16_to_v4i8(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v4i16_to_v4i8:
+; LA32: # %bb.0:
+; LA32-NEXT: ld.w $a2, $a0, 0
+; LA32-NEXT: ld.w $a0, $a0, 4
+; LA32-NEXT: vinsgr2vr.w $vr0, $a2, 0
+; LA32-NEXT: vinsgr2vr.w $vr0, $a0, 1
+; LA32-NEXT: vpickev.b $vr0, $vr0, $vr0
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: test_trunc_v4i16_to_v4i8:
+; LA64: # %bb.0:
+; LA64-NEXT: ld.d $a0, $a0, 0
+; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
+; LA64-NEXT: vpickev.b $vr0, $vr0, $vr0
+; LA64-NEXT: vstelm.w $vr0, $a1, 0, 0
+; LA64-NEXT: ret
+ %vec = load <4 x i16>, ptr %src
+ %trunc = trunc <4 x i16> %vec to <4 x i8>
+ store <4 x i8> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v4i32_to_v4i8(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v4i32_to_v4i8:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a0, 0
+; LA32-NEXT: pcalau12i $a0, %pc_hi20(.LCPI1_0)
+; LA32-NEXT: vld $vr1, $a0, %pc_lo12(.LCPI1_0)
+; LA32-NEXT: vshuf.b $vr0, $vr0, $vr0, $vr1
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: test_trunc_v4i32_to_v4i8:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a0, 0
+; LA64-NEXT: pcalau12i $a0, %pc_hi20(.LCPI1_0)
+; LA64-NEXT: vld $vr1, $a0, %pc_lo12(.LCPI1_0)
+; LA64-NEXT: vshuf.b $vr0, $vr0, $vr0, $vr1
+; LA64-NEXT: vstelm.w $vr0, $a1, 0, 0
+; LA64-NEXT: ret
+ %vec = load <4 x i32>, ptr %src
+ %trunc = trunc <4 x i32> %vec to <4 x i8>
+ store <4 x i8> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v4i32_to_v4i16(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v4i32_to_v4i16:
+; LA32: # %bb.0:
+; LA32-NEXT: vld $vr0, $a0, 0
+; LA32-NEXT: vpickev.h $vr0, $vr0, $vr0
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 1
+; LA32-NEXT: st.w $a0, $a1, 4
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: test_trunc_v4i32_to_v4i16:
+; LA64: # %bb.0:
+; LA64-NEXT: vld $vr0, $a0, 0
+; LA64-NEXT: vpickev.h $vr0, $vr0, $vr0
+; LA64-NEXT: vstelm.d $vr0, $a1, 0, 0
+; LA64-NEXT: ret
+ %vec = load <4 x i32>, ptr %src
+ %trunc = trunc <4 x i32> %vec to <4 x i16>
+ store <4 x i16> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v4i64_to_v4i8(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v4i64_to_v4i8:
+; LA32: # %bb.0:
+; LA32-NEXT: xvld $xr0, $a0, 0
+; LA32-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_0)
+; LA32-NEXT: vld $vr1, $a0, %pc_lo12(.LCPI3_0)
+; LA32-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vshuf.b $vr0, $vr0, $vr0, $vr1
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: test_trunc_v4i64_to_v4i8:
+; LA64: # %bb.0:
+; LA64-NEXT: xvld $xr0, $a0, 0
+; LA64-NEXT: pcalau12i $a0, %pc_hi20(.LCPI3_0)
+; LA64-NEXT: vld $vr1, $a0, %pc_lo12(.LCPI3_0)
+; LA64-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT: vshuf.b $vr0, $vr0, $vr0, $vr1
+; LA64-NEXT: vstelm.w $vr0, $a1, 0, 0
+; LA64-NEXT: ret
+ %vec = load <4 x i64>, ptr %src
+ %trunc = trunc <4 x i64> %vec to <4 x i8>
+ store <4 x i8> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v4i64_to_v4i16(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v4i64_to_v4i16:
+; LA32: # %bb.0:
+; LA32-NEXT: xvld $xr0, $a0, 0
+; LA32-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vpickev.h $vr0, $vr0, $vr0
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 1
+; LA32-NEXT: st.w $a0, $a1, 4
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: test_trunc_v4i64_to_v4i16:
+; LA64: # %bb.0:
+; LA64-NEXT: xvld $xr0, $a0, 0
+; LA64-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT: vpickev.h $vr0, $vr0, $vr0
+; LA64-NEXT: vstelm.d $vr0, $a1, 0, 0
+; LA64-NEXT: ret
+ %vec = load <4 x i64>, ptr %src
+ %trunc = trunc <4 x i64> %vec to <4 x i16>
+ store <4 x i16> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v4i64_to_v4i32(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v4i64_to_v4i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %vec = load <4 x i64>, ptr %src
+ %trunc = trunc <4 x i64> %vec to <4 x i32>
+ store <4 x i32> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v8i32_to_v8i8(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v8i32_to_v8i8:
+; LA32: # %bb.0:
+; LA32-NEXT: xvld $xr0, $a0, 0
+; LA32-NEXT: xvpickev.h $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vpickev.b $vr0, $vr0, $vr0
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 1
+; LA32-NEXT: st.w $a0, $a1, 4
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: test_trunc_v8i32_to_v8i8:
+; LA64: # %bb.0:
+; LA64-NEXT: xvld $xr0, $a0, 0
+; LA64-NEXT: xvpickev.h $xr0, $xr0, $xr0
+; LA64-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT: vpickev.b $vr0, $vr0, $vr0
+; LA64-NEXT: vstelm.d $vr0, $a1, 0, 0
+; LA64-NEXT: ret
+ %vec = load <8 x i32>, ptr %src
+ %trunc = trunc <8 x i32> %vec to <8 x i8>
+ store <8 x i8> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v8i32_to_v8i16(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v8i32_to_v8i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: xvpickev.h $xr0, $xr0, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %vec = load <8 x i32>, ptr %src
+ %trunc = trunc <8 x i32> %vec to <8 x i16>
+ store <8 x i16> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v8i64_to_v8i8(ptr %src, ptr %dst) {
+; LA32-LABEL: test_trunc_v8i64_to_v8i8:
+; LA32: # %bb.0:
+; LA32-NEXT: xvld $xr0, $a0, 0
+; LA32-NEXT: xvld $xr1, $a0, 32
+; LA32-NEXT: xvpickev.w $xr0, $xr1, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: xvpickev.h $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vpickev.b $vr0, $vr0, $vr0
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 1
+; LA32-NEXT: st.w $a0, $a1, 4
+; LA32-NEXT: vpickve2gr.w $a0, $vr0, 0
+; LA32-NEXT: st.w $a0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: test_trunc_v8i64_to_v8i8:
+; LA64: # %bb.0:
+; LA64-NEXT: xvld $xr0, $a0, 0
+; LA64-NEXT: xvld $xr1, $a0, 32
+; LA64-NEXT: xvpickev.w $xr0, $xr1, $xr0
+; LA64-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT: xvpickev.h $xr0, $xr0, $xr0
+; LA64-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT: vpickev.b $vr0, $vr0, $vr0
+; LA64-NEXT: vstelm.d $vr0, $a1, 0, 0
+; LA64-NEXT: ret
+ %vec = load <8 x i64>, ptr %src
+ %trunc = trunc <8 x i64> %vec to <8 x i8>
+ store <8 x i8> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v8i64_to_v8i16(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v8i64_to_v8i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: xvld $xr1, $a0, 32
+; CHECK-NEXT: xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: xvpickev.h $xr0, $xr0, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %vec = load <8 x i64>, ptr %src
+ %trunc = trunc <8 x i64> %vec to <8 x i16>
+ store <8 x i16> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v8i64_to_v8i32(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v8i64_to_v8i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: xvld $xr1, $a0, 32
+; CHECK-NEXT: xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %vec = load <8 x i64>, ptr %src
+ %trunc = trunc <8 x i64> %vec to <8 x i32>
+ store <8 x i32> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v16i32_to_v16i8(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v16i32_to_v16i8:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: xvld $xr1, $a0, 32
+; CHECK-NEXT: xvpickev.h $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: xvpickev.b $xr0, $xr0, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %vec = load <16 x i32>, ptr %src
+ %trunc = trunc <16 x i32> %vec to <16 x i8>
+ store <16 x i8> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v16i32_to_v16i16(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v16i32_to_v16i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: xvld $xr1, $a0, 32
+; CHECK-NEXT: xvpickev.h $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %vec = load <16 x i32>, ptr %src
+ %trunc = trunc <16 x i32> %vec to <16 x i16>
+ store <16 x i16> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v16i64_to_v16i8(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v16i64_to_v16i8:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: xvld $xr1, $a0, 32
+; CHECK-NEXT: xvld $xr2, $a0, 64
+; CHECK-NEXT: xvld $xr3, $a0, 96
+; CHECK-NEXT: xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: xvpickev.w $xr1, $xr3, $xr2
+; CHECK-NEXT: xvpermi.d $xr1, $xr1, 216
+; CHECK-NEXT: xvpickev.h $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: xvpickev.b $xr0, $xr0, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %vec = load <16 x i64>, ptr %src
+ %trunc = trunc <16 x i64> %vec to <16 x i8>
+ store <16 x i8> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v16i64_to_v16i16(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v16i64_to_v16i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: xvld $xr1, $a0, 32
+; CHECK-NEXT: xvld $xr2, $a0, 64
+; CHECK-NEXT: xvld $xr3, $a0, 96
+; CHECK-NEXT: xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: xvpickev.w $xr1, $xr3, $xr2
+; CHECK-NEXT: xvpermi.d $xr1, $xr1, 216
+; CHECK-NEXT: xvpickev.h $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %vec = load <16 x i64>, ptr %src
+ %trunc = trunc <16 x i64> %vec to <16 x i16>
+ store <16 x i16> %trunc, ptr %dst
+ ret void
+}
+
+define void @test_trunc_v16i64_to_v16i32(ptr %src, ptr %dst) {
+; CHECK-LABEL: test_trunc_v16i64_to_v16i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: xvld $xr1, $a0, 32
+; CHECK-NEXT: xvld $xr2, $a0, 64
+; CHECK-NEXT: xvld $xr3, $a0, 96
+; CHECK-NEXT: xvpickev.w $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: xvpickev.w $xr1, $xr3, $xr2
+; CHECK-NEXT: xvpermi.d $xr1, $xr1, 216
+; CHECK-NEXT: xvst $xr1, $a1, 32
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %vec = load <16 x i64>, ptr %src
+ %trunc = trunc <16 x i64> %vec to <16 x i32>
+ store <16 x i32> %trunc, ptr %dst
+ ret void
+}
diff --git a/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll b/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
index cb28d79b0dd51..bd17e67d19fa3 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
@@ -8,16 +8,10 @@ define void @xor_zext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
; LA32-NEXT: xvld $xr0, $a1, 0
; LA32-NEXT: xvld $xr1, $a2, 0
; LA32-NEXT: xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 0
-; LA32-NEXT: vinsgr2vr.w $vr1, $a1, 0
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 2
-; LA32-NEXT: vinsgr2vr.w $vr1, $a1, 1
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT: vinsgr2vr.w $vr1, $a1, 2
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT: vinsgr2vr.w $vr1, $a1, 3
-; LA32-NEXT: vldi $vr0, -1777
-; LA32-NEXT: vxor.v $vr0, $vr1, $vr0
+; LA32-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vldi $vr1, -1777
+; LA32-NEXT: vxor.v $vr0, $vr0, $vr1
; LA32-NEXT: vextrins.w $vr1, $vr0, 2
; LA32-NEXT: vextrins.w $vr1, $vr0, 35
; LA32-NEXT: vextrins.w $vr0, $vr0, 33
@@ -97,16 +91,10 @@ define void @xor_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
; LA32-NEXT: xvld $xr0, $a1, 0
; LA32-NEXT: xvld $xr1, $a2, 0
; LA32-NEXT: xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 0
-; LA32-NEXT: vinsgr2vr.w $vr1, $a1, 0
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 2
-; LA32-NEXT: vinsgr2vr.w $vr1, $a1, 1
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT: vinsgr2vr.w $vr1, $a1, 2
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT: vinsgr2vr.w $vr1, $a1, 3
-; LA32-NEXT: vldi $vr0, -1777
-; LA32-NEXT: vxor.v $vr0, $vr1, $vr0
+; LA32-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vldi $vr1, -1777
+; LA32-NEXT: vxor.v $vr0, $vr0, $vr1
; LA32-NEXT: vext2xv.d.w $xr0, $xr0
; LA32-NEXT: xvst $xr0, $a0, 0
; LA32-NEXT: ret
@@ -181,14 +169,13 @@ define void @or_zext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
; LA32-NEXT: xvld $xr0, $a1, 0
; LA32-NEXT: xvld $xr1, $a2, 0
; LA32-NEXT: xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT: xvpickve2gr.w $a2, $xr0, 2
-; LA32-NEXT: vrepli.b $vr0, -1
-; LA32-NEXT: vinsgr2vr.w $vr0, $a2, 1
-; LA32-NEXT: vinsgr2vr.w $vr0, $a1, 3
+; LA32-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vldi $vr1, -1777
+; LA32-NEXT: vor.v $vr0, $vr0, $vr1
; LA32-NEXT: vextrins.w $vr1, $vr0, 2
+; LA32-NEXT: vextrins.w $vr1, $vr0, 35
; LA32-NEXT: vextrins.w $vr0, $vr0, 33
-; LA32-NEXT: vinsgr2vr.w $vr1, $a1, 2
; LA32-NEXT: xvpermi.q $xr0, $xr1, 2
; LA32-NEXT: xvrepli.d $xr1, 1
; LA32-NEXT: xvand.v $xr0, $xr0, $xr1
@@ -265,11 +252,10 @@ define void @or_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
; LA32-NEXT: xvld $xr0, $a1, 0
; LA32-NEXT: xvld $xr1, $a2, 0
; LA32-NEXT: xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 6
-; LA32-NEXT: xvpickve2gr.w $a2, $xr0, 2
-; LA32-NEXT: vrepli.b $vr0, -1
-; LA32-NEXT: vinsgr2vr.w $vr0, $a2, 1
-; LA32-NEXT: vinsgr2vr.w $vr0, $a1, 3
+; LA32-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vldi $vr1, -1777
+; LA32-NEXT: vor.v $vr0, $vr0, $vr1
; LA32-NEXT: vext2xv.d.w $xr0, $xr0
; LA32-NEXT: xvst $xr0, $a0, 0
; LA32-NEXT: ret
@@ -341,10 +327,16 @@ define void @and_zext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
; LA32-NEXT: xvld $xr0, $a1, 0
; LA32-NEXT: xvld $xr1, $a2, 0
; LA32-NEXT: xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT: xvrepli.b $xr1, 0
-; LA32-NEXT: xvextrins.w $xr1, $xr0, 0
-; LA32-NEXT: xvrepli.d $xr0, 1
-; LA32-NEXT: xvand.v $xr0, $xr1, $xr0
+; LA32-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vldi $vr1, -1777
+; LA32-NEXT: vand.v $vr0, $vr0, $vr1
+; LA32-NEXT: vextrins.w $vr1, $vr0, 2
+; LA32-NEXT: vextrins.w $vr1, $vr0, 35
+; LA32-NEXT: vextrins.w $vr0, $vr0, 33
+; LA32-NEXT: xvpermi.q $xr0, $xr1, 2
+; LA32-NEXT: xvrepli.d $xr1, 1
+; LA32-NEXT: xvand.v $xr0, $xr0, $xr1
; LA32-NEXT: xvst $xr0, $a0, 0
; LA32-NEXT: ret
;
@@ -412,11 +404,10 @@ define void @and_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
; LA32-NEXT: xvld $xr0, $a1, 0
; LA32-NEXT: xvld $xr1, $a2, 0
; LA32-NEXT: xvfcmp.clt.d $xr0, $xr0, $xr1
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT: xvpickve2gr.w $a2, $xr0, 0
-; LA32-NEXT: vrepli.b $vr0, 0
-; LA32-NEXT: vinsgr2vr.w $vr0, $a2, 0
-; LA32-NEXT: vinsgr2vr.w $vr0, $a1, 2
+; LA32-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vldi $vr1, -1777
+; LA32-NEXT: vand.v $vr0, $vr0, $vr1
; LA32-NEXT: vext2xv.d.w $xr0, $xr0
; LA32-NEXT: xvst $xr0, $a0, 0
; LA32-NEXT: ret
diff --git a/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll b/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
index ca61e69f1b378..bb8cc2abbec35 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/xvmskcond.ll
@@ -883,39 +883,24 @@ define i8 @xvmsk_ne_v4i32_concat_poison(<4 x i32> %vec) {
}
define i8 @xvmsk_ogt_v4f64_concat_poison(<4 x double> %vec) {
-; LA32-LABEL: xvmsk_ogt_v4f64_concat_poison:
-; LA32: # %bb.0:
-; LA32-NEXT: xvrepli.b $xr1, 0
-; LA32-NEXT: xvfcmp.clt.d $xr0, $xr1, $xr0
-; LA32-NEXT: xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT: xvpickve2gr.w $a1, $xr0, 4
-; LA32-NEXT: xvpickve2gr.w $a2, $xr0, 2
-; LA32-NEXT: xvpickve2gr.w $a3, $xr0, 0
-; LA32-NEXT: vinsgr2vr.h $vr0, $a3, 0
-; LA32-NEXT: vinsgr2vr.h $vr0, $a2, 1
-; LA32-NEXT: vinsgr2vr.h $vr0, $a1, 2
-; LA32-NEXT: vinsgr2vr.h $vr0, $a0, 3
-; LA32-NEXT: vslli.h $vr0, $vr0, 15
-; LA32-NEXT: vmskltz.h $vr0, $vr0
-; LA32-NEXT: vpickve2gr.hu $a0, $vr0, 0
-; LA32-NEXT: ret
-;
-; LA64-LABEL: xvmsk_ogt_v4f64_concat_poison:
-; LA64: # %bb.0:
-; LA64-NEXT: xvrepli.b $xr1, 0
-; LA64-NEXT: xvfcmp.clt.d $xr0, $xr1, $xr0
-; LA64-NEXT: xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT: xvpickve2gr.d $a1, $xr0, 2
-; LA64-NEXT: xvpickve2gr.d $a2, $xr0, 1
-; LA64-NEXT: xvpickve2gr.d $a3, $xr0, 0
-; LA64-NEXT: vinsgr2vr.h $vr0, $a3, 0
-; LA64-NEXT: vinsgr2vr.h $vr0, $a2, 1
-; LA64-NEXT: vinsgr2vr.h $vr0, $a1, 2
-; LA64-NEXT: vinsgr2vr.h $vr0, $a0, 3
-; LA64-NEXT: vslli.h $vr0, $vr0, 15
-; LA64-NEXT: vmskltz.h $vr0, $vr0
-; LA64-NEXT: vpickve2gr.hu $a0, $vr0, 0
-; LA64-NEXT: ret
+; CHECK-LABEL: xvmsk_ogt_v4f64_concat_poison:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvrepli.b $xr1, 0
+; CHECK-NEXT: xvfcmp.clt.d $xr0, $xr1, $xr0
+; CHECK-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; CHECK-NEXT: xvpermi.d $xr0, $xr0, 216
+; CHECK-NEXT: vpickve2gr.w $a0, $vr0, 0
+; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 0
+; CHECK-NEXT: vpickve2gr.w $a0, $vr0, 1
+; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 1
+; CHECK-NEXT: vpickve2gr.w $a0, $vr0, 2
+; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 2
+; CHECK-NEXT: vpickve2gr.w $a0, $vr0, 3
+; CHECK-NEXT: vinsgr2vr.h $vr1, $a0, 3
+; CHECK-NEXT: vslli.h $vr0, $vr1, 15
+; CHECK-NEXT: vmskltz.h $vr0, $vr0
+; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0
+; CHECK-NEXT: ret
%tobool = fcmp ogt <4 x double> %vec, zeroinitializer
%insertvec = shufflevector <4 x i1> %tobool, <4 x i1> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
%res = bitcast <8 x i1> %insertvec to i8
diff --git a/llvm/test/CodeGen/LoongArch/pr177863.ll b/llvm/test/CodeGen/LoongArch/pr177863.ll
index 54fa02162ee0d..c8fbba8500fc2 100644
--- a/llvm/test/CodeGen/LoongArch/pr177863.ll
+++ b/llvm/test/CodeGen/LoongArch/pr177863.ll
@@ -7,29 +7,17 @@ define <4 x i1> @test(<4 x i64> %shuffle2, <4 x i64> %shuffle4) {
; LA32-LABEL: test:
; LA32: # %bb.0: # %entry
; LA32-NEXT: xvseq.d $xr0, $xr1, $xr0
-; LA32-NEXT: xvpickve2gr.w $a0, $xr0, 0
-; LA32-NEXT: vinsgr2vr.w $vr1, $a0, 0
-; LA32-NEXT: xvpickve2gr.w $a0, $xr0, 2
-; LA32-NEXT: vinsgr2vr.w $vr1, $a0, 1
-; LA32-NEXT: xvpickve2gr.w $a0, $xr0, 4
-; LA32-NEXT: vinsgr2vr.w $vr1, $a0, 2
-; LA32-NEXT: xvpickve2gr.w $a0, $xr0, 6
-; LA32-NEXT: vinsgr2vr.w $vr1, $a0, 3
-; LA32-NEXT: vxori.b $vr0, $vr1, 255
+; LA32-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA32-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA32-NEXT: vxori.b $vr0, $vr0, 255
; LA32-NEXT: ret
;
; LA64-LABEL: test:
; LA64: # %bb.0: # %entry
; LA64-NEXT: xvseq.d $xr0, $xr1, $xr0
-; LA64-NEXT: xvpickve2gr.d $a0, $xr0, 0
-; LA64-NEXT: vinsgr2vr.w $vr1, $a0, 0
-; LA64-NEXT: xvpickve2gr.d $a0, $xr0, 1
-; LA64-NEXT: vinsgr2vr.w $vr1, $a0, 1
-; LA64-NEXT: xvpickve2gr.d $a0, $xr0, 2
-; LA64-NEXT: vinsgr2vr.w $vr1, $a0, 2
-; LA64-NEXT: xvpickve2gr.d $a0, $xr0, 3
-; LA64-NEXT: vinsgr2vr.w $vr1, $a0, 3
-; LA64-NEXT: vxori.b $vr0, $vr1, 255
+; LA64-NEXT: xvpickev.w $xr0, $xr0, $xr0
+; LA64-NEXT: xvpermi.d $xr0, $xr0, 216
+; LA64-NEXT: vxori.b $vr0, $vr0, 255
; LA64-NEXT: ret
entry:
%conv5 = trunc nuw <4 x i64> %shuffle4 to <4 x i32>
More information about the llvm-commits
mailing list