[llvm] [LoongArch] Introduce LASX instruction patterns for vector sign/zero extensions (PR #193727)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 28 06:10:29 PDT 2026
https://github.com/lrzlin updated https://github.com/llvm/llvm-project/pull/193727
>From de1ef822d6a082b0746c87ee002033fceb058400 Mon Sep 17 00:00:00 2001
From: Lin Runze <linrunze at loongson.cn>
Date: Thu, 23 Apr 2026 20:27:46 +0800
Subject: [PATCH] [LoongArch] Introduce LASX instruction patterns for vector
sign/zero extensions
---
.../LoongArch/LoongArchISelLowering.cpp | 9 +
.../LoongArch/LoongArchLASXInstrInfo.td | 81 +++-
llvm/test/CodeGen/LoongArch/lasx/vec-sext.ll | 423 +++++++++++++++++
llvm/test/CodeGen/LoongArch/lasx/vec-zext.ll | 424 ++++++++++++++++++
.../test/CodeGen/LoongArch/lasx/vxi1-masks.ll | 38 +-
5 files changed, 943 insertions(+), 32 deletions(-)
create mode 100644 llvm/test/CodeGen/LoongArch/lasx/vec-sext.ll
create mode 100644 llvm/test/CodeGen/LoongArch/lasx/vec-zext.ll
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index a3f2ff2b88efb..9f9f2a3a22b7f 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -471,6 +471,15 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
}
setOperationAction(ISD::FP_ROUND, MVT::v4f32, Custom);
setOperationAction(ISD::FP_EXTEND, MVT::v4f64, Custom);
+ for (MVT VT : {MVT::v4i64, MVT::v8i32, MVT::v16i16}) {
+ setOperationAction(ISD::SIGN_EXTEND, VT, Legal);
+ setOperationAction(ISD::ZERO_EXTEND, VT, Legal);
+ }
+ for (MVT VT :
+ {MVT::v2i64, MVT::v4i32, MVT::v4i64, MVT::v8i16, MVT::v8i32}) {
+ setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, VT, Legal);
+ setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, VT, Legal);
+ }
}
// Set DAG combine for LA32 and LA64.
diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index 6b1f7fd59afbc..ac388847c5240 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -1776,7 +1776,7 @@ def : Pat<(vector_insert v4f64:$xd, FPR64:$fj, uimm2:$imm),
def : Pat<(v8f32 (scalar_to_vector FPR32:$fj)),
(SUBREG_TO_REG FPR32:$fj, sub_32)>;
def : Pat<(v4f64 (scalar_to_vector FPR64:$fj)),
- (SUBREG_TO_REG FPR64:$fj, sub_64)>;
+ (SUBREG_TO_REG FPR64:$fj, sub_64)>;
// XVPICKVE2GR_W[U]
def : Pat<(loongarch_vpick_sext_elt v8i32:$xd, uimm3:$imm, i32),
@@ -2185,6 +2185,77 @@ def : Pat<(int_loongarch_lasx_insert_128_hi_d (v4f64 LASX256:$src), (v2f64 LSX12
(XVPERMI_Q LASX256:$src, (INSERT_SUBREG (IMPLICIT_DEF), LSX128:$lo, sub_128), 2)>;
def : Pat<(int_loongarch_lasx_insert_128_hi (v4i64 LASX256:$src), (v2i64 LSX128:$lo)),
(XVPERMI_Q LASX256:$src, (INSERT_SUBREG (IMPLICIT_DEF), LSX128:$lo, sub_128), 2)>;
+
+// Sign extensions
+def : Pat<(v4i64 (sext v4i32:$vj)),
+ (v4i64 (VEXT2XV_D_W (SUBREG_TO_REG v4i32:$vj, sub_128)))>;
+def : Pat<(v8i32 (sext v8i16:$vj)),
+ (v8i32 (VEXT2XV_W_H (SUBREG_TO_REG v8i16:$vj, sub_128)))>;
+def : Pat<(v16i16 (sext v16i8:$vj)),
+ (v16i16 (VEXT2XV_H_B (SUBREG_TO_REG v16i8:$vj, sub_128)))>;
+
+def : Pat<(v2i64 (sext_invec v16i8:$vj)),
+ (v2i64 (EXTRACT_SUBREG (VEXT2XV_D_B (SUBREG_TO_REG v16i8:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v2i64 (sext_invec v8i16:$vj)),
+ (v2i64 (EXTRACT_SUBREG (VEXT2XV_D_H (SUBREG_TO_REG v8i16:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v2i64 (sext_invec v4i32:$vj)),
+ (v2i64 (EXTRACT_SUBREG (VEXT2XV_D_W (SUBREG_TO_REG v4i32:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v4i32 (sext_invec v16i8:$vj)),
+ (v4i32 (EXTRACT_SUBREG (VEXT2XV_W_B (SUBREG_TO_REG v16i8:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v4i32 (sext_invec v8i16:$vj)),
+ (v4i32 (EXTRACT_SUBREG (VEXT2XV_W_H (SUBREG_TO_REG v8i16:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v4i64 (sext_invec v32i8:$xj)), (v4i64 (VEXT2XV_D_B v32i8:$xj))>;
+def : Pat<(v4i64 (sext_invec v16i16:$xj)), (v4i64 (VEXT2XV_D_H v16i16:$xj))>;
+def : Pat<(v4i64 (sext_invec v8i32:$xj)), (v4i64 (VEXT2XV_D_W v8i32:$xj))>;
+def : Pat<(v8i16 (sext_invec v16i8:$vj)),
+ (v8i16 (EXTRACT_SUBREG (VEXT2XV_H_B (SUBREG_TO_REG v16i8:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v16i16 (sext_invec v32i8:$xj)), (v16i16 (VEXT2XV_H_B v32i8:$xj))>;
+def : Pat<(v8i32 (sext_invec v32i8:$xj)), (v8i32 (VEXT2XV_W_B v32i8:$xj))>;
+def : Pat<(v8i32 (sext_invec v16i16:$xj)), (v8i32 (VEXT2XV_W_H v16i16:$xj))>;
+def : Pat<(v8i32 (sext_invec v16i8:$vj)),
+ (v8i32 (VEXT2XV_W_B (SUBREG_TO_REG v16i8:$vj, sub_128)))>;
+
+// Zero extensions
+def : Pat<(v4i64 (zext v4i32:$vj)),
+ (v4i64 (VEXT2XV_DU_WU (SUBREG_TO_REG v4i32:$vj, sub_128)))>;
+def : Pat<(v8i32 (zext v8i16:$vj)),
+ (v8i32 (VEXT2XV_WU_HU (SUBREG_TO_REG v8i16:$vj, sub_128)))>;
+def : Pat<(v16i16 (zext v16i8:$vj)),
+ (v16i16 (VEXT2XV_HU_BU (SUBREG_TO_REG v16i8:$vj, sub_128)))>;
+
+def : Pat<(v2i64 (zext_invec v16i8:$vj)),
+ (v2i64 (EXTRACT_SUBREG (VEXT2XV_DU_BU (SUBREG_TO_REG v16i8:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v2i64 (zext_invec v8i16:$vj)),
+ (v2i64 (EXTRACT_SUBREG (VEXT2XV_DU_HU (SUBREG_TO_REG v8i16:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v2i64 (zext_invec v4i32:$vj)),
+ (v2i64 (EXTRACT_SUBREG (VEXT2XV_DU_WU (SUBREG_TO_REG v4i32:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v4i32 (zext_invec v16i8:$vj)),
+ (v4i32 (EXTRACT_SUBREG (VEXT2XV_WU_BU (SUBREG_TO_REG v16i8:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v4i32 (zext_invec v8i16:$vj)),
+ (v4i32 (EXTRACT_SUBREG (VEXT2XV_WU_HU (SUBREG_TO_REG v8i16:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v4i64 (zext_invec v32i8:$xj)), (v4i64 (VEXT2XV_DU_BU v32i8:$xj))>;
+def : Pat<(v4i64 (zext_invec v16i16:$xj)), (v4i64 (VEXT2XV_DU_HU v16i16:$xj))>;
+def : Pat<(v4i64 (zext_invec v8i32:$xj)), (v4i64 (VEXT2XV_DU_WU v8i32:$xj))>;
+def : Pat<(v8i16 (zext_invec v16i8:$vj)),
+ (v8i16 (EXTRACT_SUBREG (VEXT2XV_HU_BU (SUBREG_TO_REG v16i8:$vj, sub_128)),
+ sub_128))>;
+def : Pat<(v16i16 (zext_invec v32i8:$xj)), (v16i16 (VEXT2XV_HU_BU v32i8:$xj))>;
+def : Pat<(v8i32 (zext_invec v32i8:$xj)), (v8i32 (VEXT2XV_WU_BU v32i8:$xj))>;
+def : Pat<(v8i32 (zext_invec v16i16:$xj)), (v8i32 (VEXT2XV_WU_HU v16i16:$xj))>;
+def : Pat<(v8i32 (zext_invec v16i8:$vj)),
+ (v8i32 (VEXT2XV_WU_BU (SUBREG_TO_REG v16i8:$vj, sub_128)))>;
+
} // Predicates = [HasExtLASX]
/// Intrinsic pattern
@@ -2485,13 +2556,13 @@ foreach Inst = ["XVFRECIPE_D", "XVFRSQRTE_D"] in
def : Pat<(deriveLASXIntrinsic<Inst>.ret (v4f64 LASX256:$xj)),
(!cast<LAInst>(Inst) LASX256:$xj)>;
-def : Pat<(loongarch_vfrecipe v8f32:$src),
+def : Pat<(loongarch_vfrecipe v8f32:$src),
(XVFRECIPE_S v8f32:$src)>;
-def : Pat<(loongarch_vfrecipe v4f64:$src),
+def : Pat<(loongarch_vfrecipe v4f64:$src),
(XVFRECIPE_D v4f64:$src)>;
-def : Pat<(loongarch_vfrsqrte v8f32:$src),
+def : Pat<(loongarch_vfrsqrte v8f32:$src),
(XVFRSQRTE_S v8f32:$src)>;
-def : Pat<(loongarch_vfrsqrte v4f64:$src),
+def : Pat<(loongarch_vfrsqrte v4f64:$src),
(XVFRSQRTE_D v4f64:$src)>;
}
diff --git a/llvm/test/CodeGen/LoongArch/lasx/vec-sext.ll b/llvm/test/CodeGen/LoongArch/lasx/vec-sext.ll
new file mode 100644
index 0000000000000..a0d4ab009f0ce
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/vec-sext.ll
@@ -0,0 +1,423 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx,+lasx %s -o - | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx,+lasx %s -o - | FileCheck %s --check-prefixes=CHECK,LA64
+
+define void @load_sext_2i8_to_2i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_2i8_to_2i64:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: ld.h $a0, $a0, 0
+; CHECK-NEXT: vinsgr2vr.h $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.d.b $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <2 x i8>, ptr %ptr
+ %B = sext <2 x i8> %A to <2 x i64>
+ store <2 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_4i8_to_4i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_4i8_to_4i32:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: ld.w $a0, $a0, 0
+; CHECK-NEXT: vinsgr2vr.w $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.w.b $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <4 x i8>, ptr %ptr
+ %B = sext <4 x i8> %A to <4 x i32>
+ store <4 x i32> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_8i8_to_8i16(ptr %ptr, ptr %dst) {
+; LA32-LABEL: load_sext_8i8_to_8i16:
+; LA32: # %bb.0: # %entry
+; 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: vext2xv.h.b $xr0, $xr0
+; LA32-NEXT: vst $vr0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: load_sext_8i8_to_8i16:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: ld.d $a0, $a0, 0
+; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
+; LA64-NEXT: vext2xv.h.b $xr0, $xr0
+; LA64-NEXT: vst $vr0, $a1, 0
+; LA64-NEXT: ret
+entry:
+ %A = load <8 x i8>, ptr %ptr
+ %B = sext <8 x i8> %A to <8 x i16>
+ store <8 x i16> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_2i16_to_2i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_2i16_to_2i64:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: ld.w $a0, $a0, 0
+; CHECK-NEXT: vinsgr2vr.w $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.d.h $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <2 x i16>, ptr %ptr
+ %B = sext <2 x i16> %A to <2 x i64>
+ store <2 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_4i16_to_4i32(ptr %ptr, ptr %dst) {
+; LA32-LABEL: load_sext_4i16_to_4i32:
+; LA32: # %bb.0: # %entry
+; 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: vext2xv.w.h $xr0, $xr0
+; LA32-NEXT: vst $vr0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: load_sext_4i16_to_4i32:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: ld.d $a0, $a0, 0
+; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
+; LA64-NEXT: vext2xv.w.h $xr0, $xr0
+; LA64-NEXT: vst $vr0, $a1, 0
+; LA64-NEXT: ret
+entry:
+ %A = load <4 x i16>, ptr %ptr
+ %B = sext <4 x i16> %A to <4 x i32>
+ store <4 x i32> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_2i32_to_2i64(ptr %ptr, ptr %dst) {
+; LA32-LABEL: load_sext_2i32_to_2i64:
+; LA32: # %bb.0: # %entry
+; 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: vext2xv.d.w $xr0, $xr0
+; LA32-NEXT: vst $vr0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: load_sext_2i32_to_2i64:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: ld.d $a0, $a0, 0
+; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
+; LA64-NEXT: vext2xv.d.w $xr0, $xr0
+; LA64-NEXT: vst $vr0, $a1, 0
+; LA64-NEXT: ret
+entry:
+ %A = load <2 x i32>, ptr %ptr
+ %B = sext <2 x i32> %A to <2 x i64>
+ store <2 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_16i8_to_16i16(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_16i8_to_16i16:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.h.b $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <16 x i8>, ptr %ptr
+ %B = sext <16 x i8> %A to <16 x i16>
+ store <16 x i16> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_16i8_to_16i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_16i8_to_16i32:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.h.b $xr0, $xr0
+; CHECK-NEXT: xvpermi.q $xr1, $xr0, 1
+; CHECK-NEXT: vext2xv.w.h $xr1, $xr1
+; CHECK-NEXT: vext2xv.w.h $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: xvst $xr1, $a1, 32
+; CHECK-NEXT: ret
+entry:
+ %A = load <16 x i8>, ptr %ptr
+ %B = sext <16 x i8> %A to <16 x i32>
+ store <16 x i32> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_16i8_to_16i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_16i8_to_16i64:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.h.b $xr0, $xr0
+; CHECK-NEXT: xvpermi.q $xr1, $xr0, 1
+; CHECK-NEXT: vext2xv.w.h $xr1, $xr1
+; CHECK-NEXT: xvpermi.q $xr2, $xr1, 1
+; CHECK-NEXT: vext2xv.d.w $xr2, $xr2
+; CHECK-NEXT: vext2xv.w.h $xr0, $xr0
+; CHECK-NEXT: xvpermi.q $xr3, $xr0, 1
+; CHECK-NEXT: vext2xv.d.w $xr3, $xr3
+; CHECK-NEXT: vext2xv.d.w $xr1, $xr1
+; CHECK-NEXT: vext2xv.d.w $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: xvst $xr1, $a1, 64
+; CHECK-NEXT: xvst $xr3, $a1, 32
+; CHECK-NEXT: xvst $xr2, $a1, 96
+; CHECK-NEXT: ret
+entry:
+ %A = load <16 x i8>, ptr %ptr
+ %B = sext <16 x i8> %A to <16 x i64>
+ store <16 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_8i16_to_8i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_8i16_to_8i32:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.w.h $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <8 x i16>, ptr %ptr
+ %B = sext <8 x i16> %A to <8 x i32>
+ store <8 x i32> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_8i16_to_8i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_8i16_to_8i64:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.w.h $xr0, $xr0
+; CHECK-NEXT: xvpermi.q $xr1, $xr0, 1
+; CHECK-NEXT: vext2xv.d.w $xr1, $xr1
+; CHECK-NEXT: vext2xv.d.w $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: xvst $xr1, $a1, 32
+; CHECK-NEXT: ret
+entry:
+ %A = load <8 x i16>, ptr %ptr
+ %B = sext <8 x i16> %A to <8 x i64>
+ store <8 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_4i32_to_4i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_4i32_to_4i64:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.d.w $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <4 x i32>, ptr %ptr
+ %B = sext <4 x i32> %A to <4 x i64>
+ store <4 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v16i8_to_v2i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v16i8_to_v2i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.d.b $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i8>, ptr %ptr
+ %B = shufflevector <16 x i8> %A, <16 x i8> poison,
+ <2 x i32> <i32 0, i32 1>
+ %C = sext <2 x i8> %B to <2 x i64>
+ store <2 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v8i16_to_v2i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v8i16_to_v2i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.d.h $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <8 x i16>, ptr %ptr
+ %B = shufflevector <8 x i16> %A, <8 x i16> poison,
+ <2 x i32> <i32 0, i32 1>
+ %C = sext <2 x i16> %B to <2 x i64>
+ store <2 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v4i32_to_v2i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v4i32_to_v2i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.d.w $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <4 x i32>, ptr %ptr
+ %B = shufflevector <4 x i32> %A, <4 x i32> poison,
+ <2 x i32> <i32 0, i32 1>
+ %C = sext <2 x i32> %B to <2 x i64>
+ store <2 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v16i8_to_v4i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v16i8_to_v4i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.w.b $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i8>, ptr %ptr
+ %B = shufflevector <16 x i8> %A, <16 x i8> poison,
+ <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %C = sext <4 x i8> %B to <4 x i32>
+ store <4 x i32> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v8i16_to_v4i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v8i16_to_v4i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.w.h $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <8 x i16>, ptr %ptr
+ %B = shufflevector <8 x i16> %A, <8 x i16> poison,
+ <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %C = sext <4 x i16> %B to <4 x i32>
+ store <4 x i32> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v32i8_to_v4i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v32i8_to_v4i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: vext2xv.d.b $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <32 x i8>, ptr %ptr
+ %B = shufflevector <32 x i8> %A, <32 x i8> poison,
+ <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %C = sext <4 x i8> %B to <4 x i64>
+ store <4 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v16i16_to_v4i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v16i16_to_v4i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: vext2xv.d.h $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i16>, ptr %ptr
+ %B = shufflevector <16 x i16> %A, <16 x i16> poison,
+ <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %C = sext <4 x i16> %B to <4 x i64>
+ store <4 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v8i32_to_v4i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v8i32_to_v4i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.d.w $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <8 x i32>, ptr %ptr
+ %B = shufflevector <8 x i32> %A, <8 x i32> poison,
+ <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %C = sext <4 x i32> %B to <4 x i64>
+ store <4 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v16i8_to_v8i16(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v16i8_to_v8i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.h.b $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i8>, ptr %ptr
+ %B = shufflevector <16 x i8> %A, <16 x i8> poison,
+ <8 x i32> <i32 0, i32 1, i32 2, i32 3,
+ i32 4, i32 5, i32 6, i32 7>
+ %C = sext <8 x i8> %B to <8 x i16>
+ store <8 x i16> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v32i8_to_v16i16(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v32i8_to_v16i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.h.b $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <32 x i8>, ptr %ptr
+ %B = shufflevector <32 x i8> %A, <32 x i8> poison,
+ <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ %C = sext <16 x i8> %B to <16 x i16>
+ store <16 x i16> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v32i8_to_v8i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v32i8_to_v8i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: vext2xv.w.b $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <32 x i8>, ptr %ptr
+ %B = shufflevector <32 x i8> %A, <32 x i8> poison,
+ <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %C = sext <8 x i8> %B to <8 x i32>
+ store <8 x i32> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v16i16_to_v8i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v16i16_to_v8i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.w.h $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i16>, ptr %ptr
+ %B = shufflevector <16 x i16> %A, <16 x i16> poison,
+ <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %C = sext <8 x i16> %B to <8 x i32>
+ store <8 x i32> %C, ptr %dst
+ ret void
+}
+
+define void @load_sext_invec_v16i8_to_v8i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_sext_invec_v16i8_to_v8i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.w.b $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i8>, ptr %ptr
+ %B = shufflevector <16 x i8> %A, <16 x i8> poison,
+ <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %C = sext <8 x i8> %B to <8 x i32>
+ store <8 x i32> %C, ptr %dst
+ ret void
+}
diff --git a/llvm/test/CodeGen/LoongArch/lasx/vec-zext.ll b/llvm/test/CodeGen/LoongArch/lasx/vec-zext.ll
new file mode 100644
index 0000000000000..e2dfe30874251
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/lasx/vec-zext.ll
@@ -0,0 +1,424 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc --mtriple=loongarch32 --mattr=+32s,+lsx,+lasx < %s | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 --mattr=+lsx,+lasx %s -o - | FileCheck %s --check-prefixes=CHECK,LA64
+
+
+define void @load_zext_2i8_to_2i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_2i8_to_2i64:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: ld.h $a0, $a0, 0
+; CHECK-NEXT: vinsgr2vr.h $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.du.bu $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <2 x i8>, ptr %ptr
+ %B = zext <2 x i8> %A to <2 x i64>
+ store <2 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_4i8_to_4i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_4i8_to_4i32:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: ld.w $a0, $a0, 0
+; CHECK-NEXT: vinsgr2vr.w $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.wu.bu $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <4 x i8>, ptr %ptr
+ %B = zext <4 x i8> %A to <4 x i32>
+ store <4 x i32> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_8i8_to_8i16(ptr %ptr, ptr %dst) {
+; LA32-LABEL: load_zext_8i8_to_8i16:
+; LA32: # %bb.0: # %entry
+; 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: vext2xv.hu.bu $xr0, $xr0
+; LA32-NEXT: vst $vr0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: load_zext_8i8_to_8i16:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: ld.d $a0, $a0, 0
+; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
+; LA64-NEXT: vext2xv.hu.bu $xr0, $xr0
+; LA64-NEXT: vst $vr0, $a1, 0
+; LA64-NEXT: ret
+entry:
+ %A = load <8 x i8>, ptr %ptr
+ %B = zext <8 x i8> %A to <8 x i16>
+ store <8 x i16> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_2i16_to_2i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_2i16_to_2i64:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: ld.w $a0, $a0, 0
+; CHECK-NEXT: vinsgr2vr.w $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.du.hu $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <2 x i16>, ptr %ptr
+ %B = zext <2 x i16> %A to <2 x i64>
+ store <2 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_4i16_to_4i32(ptr %ptr, ptr %dst) {
+; LA32-LABEL: load_zext_4i16_to_4i32:
+; LA32: # %bb.0: # %entry
+; 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: vext2xv.wu.hu $xr0, $xr0
+; LA32-NEXT: vst $vr0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: load_zext_4i16_to_4i32:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: ld.d $a0, $a0, 0
+; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
+; LA64-NEXT: vext2xv.wu.hu $xr0, $xr0
+; LA64-NEXT: vst $vr0, $a1, 0
+; LA64-NEXT: ret
+entry:
+ %A = load <4 x i16>, ptr %ptr
+ %B = zext <4 x i16> %A to <4 x i32>
+ store <4 x i32> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_2i32_to_2i64(ptr %ptr, ptr %dst) {
+; LA32-LABEL: load_zext_2i32_to_2i64:
+; LA32: # %bb.0: # %entry
+; 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: vext2xv.du.wu $xr0, $xr0
+; LA32-NEXT: vst $vr0, $a1, 0
+; LA32-NEXT: ret
+;
+; LA64-LABEL: load_zext_2i32_to_2i64:
+; LA64: # %bb.0: # %entry
+; LA64-NEXT: ld.d $a0, $a0, 0
+; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
+; LA64-NEXT: vext2xv.du.wu $xr0, $xr0
+; LA64-NEXT: vst $vr0, $a1, 0
+; LA64-NEXT: ret
+entry:
+ %A = load <2 x i32>, ptr %ptr
+ %B = zext <2 x i32> %A to <2 x i64>
+ store <2 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_16i8_to_16i16(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_16i8_to_16i16:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.hu.bu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <16 x i8>, ptr %ptr
+ %B = zext <16 x i8> %A to <16 x i16>
+ store <16 x i16> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_16i8_to_16i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_16i8_to_16i32:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.hu.bu $xr0, $xr0
+; CHECK-NEXT: xvpermi.q $xr1, $xr0, 1
+; CHECK-NEXT: vext2xv.wu.hu $xr1, $xr1
+; CHECK-NEXT: vext2xv.wu.hu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: xvst $xr1, $a1, 32
+; CHECK-NEXT: ret
+entry:
+ %A = load <16 x i8>, ptr %ptr
+ %B = zext <16 x i8> %A to <16 x i32>
+ store <16 x i32> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_16i8_to_16i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_16i8_to_16i64:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.hu.bu $xr0, $xr0
+; CHECK-NEXT: xvpermi.q $xr1, $xr0, 1
+; CHECK-NEXT: vext2xv.wu.hu $xr1, $xr1
+; CHECK-NEXT: xvpermi.q $xr2, $xr1, 1
+; CHECK-NEXT: vext2xv.du.wu $xr2, $xr2
+; CHECK-NEXT: vext2xv.wu.hu $xr0, $xr0
+; CHECK-NEXT: xvpermi.q $xr3, $xr0, 1
+; CHECK-NEXT: vext2xv.du.wu $xr3, $xr3
+; CHECK-NEXT: vext2xv.du.wu $xr1, $xr1
+; CHECK-NEXT: vext2xv.du.wu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: xvst $xr1, $a1, 64
+; CHECK-NEXT: xvst $xr3, $a1, 32
+; CHECK-NEXT: xvst $xr2, $a1, 96
+; CHECK-NEXT: ret
+entry:
+ %A = load <16 x i8>, ptr %ptr
+ %B = zext <16 x i8> %A to <16 x i64>
+ store <16 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_8i16_to_8i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_8i16_to_8i32:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.wu.hu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <8 x i16>, ptr %ptr
+ %B = zext <8 x i16> %A to <8 x i32>
+ store <8 x i32> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_8i16_to_8i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_8i16_to_8i64:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.wu.hu $xr0, $xr0
+; CHECK-NEXT: xvpermi.q $xr1, $xr0, 1
+; CHECK-NEXT: vext2xv.du.wu $xr1, $xr1
+; CHECK-NEXT: vext2xv.du.wu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: xvst $xr1, $a1, 32
+; CHECK-NEXT: ret
+entry:
+ %A = load <8 x i16>, ptr %ptr
+ %B = zext <8 x i16> %A to <8 x i64>
+ store <8 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_4i32_to_4i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_4i32_to_4i64:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.du.wu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+entry:
+ %A = load <4 x i32>, ptr %ptr
+ %B = zext <4 x i32> %A to <4 x i64>
+ store <4 x i64> %B, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v16i8_to_v2i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v16i8_to_v2i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.du.bu $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i8>, ptr %ptr
+ %B = shufflevector <16 x i8> %A, <16 x i8> poison,
+ <2 x i32> <i32 0, i32 1>
+ %C = zext <2 x i8> %B to <2 x i64>
+ store <2 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v8i16_to_v2i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v8i16_to_v2i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.du.hu $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <8 x i16>, ptr %ptr
+ %B = shufflevector <8 x i16> %A, <8 x i16> poison,
+ <2 x i32> <i32 0, i32 1>
+ %C = zext <2 x i16> %B to <2 x i64>
+ store <2 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v4i32_to_v2i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v4i32_to_v2i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.du.wu $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <4 x i32>, ptr %ptr
+ %B = shufflevector <4 x i32> %A, <4 x i32> poison,
+ <2 x i32> <i32 0, i32 1>
+ %C = zext <2 x i32> %B to <2 x i64>
+ store <2 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v16i8_to_v4i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v16i8_to_v4i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.wu.bu $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i8>, ptr %ptr
+ %B = shufflevector <16 x i8> %A, <16 x i8> poison,
+ <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %C = zext <4 x i8> %B to <4 x i32>
+ store <4 x i32> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v8i16_to_v4i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v8i16_to_v4i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.wu.hu $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <8 x i16>, ptr %ptr
+ %B = shufflevector <8 x i16> %A, <8 x i16> poison,
+ <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %C = zext <4 x i16> %B to <4 x i32>
+ store <4 x i32> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v32i8_to_v4i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v32i8_to_v4i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: vext2xv.du.bu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <32 x i8>, ptr %ptr
+ %B = shufflevector <32 x i8> %A, <32 x i8> poison,
+ <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %C = zext <4 x i8> %B to <4 x i64>
+ store <4 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v16i16_to_v4i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v16i16_to_v4i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: vext2xv.du.hu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i16>, ptr %ptr
+ %B = shufflevector <16 x i16> %A, <16 x i16> poison,
+ <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %C = zext <4 x i16> %B to <4 x i64>
+ store <4 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v8i32_to_v4i64(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v8i32_to_v4i64:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.du.wu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <8 x i32>, ptr %ptr
+ %B = shufflevector <8 x i32> %A, <8 x i32> poison,
+ <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+ %C = zext <4 x i32> %B to <4 x i64>
+ store <4 x i64> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v16i8_to_v8i16(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v16i8_to_v8i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.hu.bu $xr0, $xr0
+; CHECK-NEXT: vst $vr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i8>, ptr %ptr
+ %B = shufflevector <16 x i8> %A, <16 x i8> poison,
+ <8 x i32> <i32 0, i32 1, i32 2, i32 3,
+ i32 4, i32 5, i32 6, i32 7>
+ %C = zext <8 x i8> %B to <8 x i16>
+ store <8 x i16> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v32i8_to_v16i16(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v32i8_to_v16i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.hu.bu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <32 x i8>, ptr %ptr
+ %B = shufflevector <32 x i8> %A, <32 x i8> poison,
+ <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
+ %C = zext <16 x i8> %B to <16 x i16>
+ store <16 x i16> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v32i8_to_v8i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v32i8_to_v8i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: xvld $xr0, $a0, 0
+; CHECK-NEXT: vext2xv.wu.bu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <32 x i8>, ptr %ptr
+ %B = shufflevector <32 x i8> %A, <32 x i8> poison,
+ <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %C = zext <8 x i8> %B to <8 x i32>
+ store <8 x i32> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v16i16_to_v8i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v16i16_to_v8i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.wu.hu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i16>, ptr %ptr
+ %B = shufflevector <16 x i16> %A, <16 x i16> poison,
+ <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %C = zext <8 x i16> %B to <8 x i32>
+ store <8 x i32> %C, ptr %dst
+ ret void
+}
+
+define void @load_zext_invec_v16i8_to_v8i32(ptr %ptr, ptr %dst) {
+; CHECK-LABEL: load_zext_invec_v16i8_to_v8i32:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vld $vr0, $a0, 0
+; CHECK-NEXT: vext2xv.wu.bu $xr0, $xr0
+; CHECK-NEXT: xvst $xr0, $a1, 0
+; CHECK-NEXT: ret
+ %A = load <16 x i8>, ptr %ptr
+ %B = shufflevector <16 x i8> %A, <16 x i8> poison,
+ <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+ %C = zext <8 x i8> %B to <8 x i32>
+ store <8 x i32> %C, 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 c07597c912a36..cb28d79b0dd51 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/vxi1-masks.ll
@@ -107,16 +107,8 @@ define void @xor_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
; LA32-NEXT: vinsgr2vr.w $vr1, $a1, 3
; LA32-NEXT: vldi $vr0, -1777
; LA32-NEXT: vxor.v $vr0, $vr1, $vr0
-; LA32-NEXT: vori.b $vr1, $vr0, 0
-; LA32-NEXT: vextrins.w $vr1, $vr1, 16
-; LA32-NEXT: vextrins.w $vr1, $vr0, 33
-; LA32-NEXT: vextrins.w $vr1, $vr0, 49
-; LA32-NEXT: vextrins.w $vr2, $vr0, 2
-; LA32-NEXT: vextrins.w $vr2, $vr0, 18
-; LA32-NEXT: vextrins.w $vr2, $vr0, 35
-; LA32-NEXT: vextrins.w $vr2, $vr0, 51
-; LA32-NEXT: xvpermi.q $xr1, $xr2, 2
-; LA32-NEXT: xvst $xr1, $a0, 0
+; LA32-NEXT: vext2xv.d.w $xr0, $xr0
+; LA32-NEXT: xvst $xr0, $a0, 0
; LA32-NEXT: ret
;
; LA64-LABEL: xor_sext_masks_v4i64:
@@ -278,16 +270,8 @@ define void @or_sext_masks_v4i64(ptr %res, ptr %a, ptr %b) nounwind {
; LA32-NEXT: vrepli.b $vr0, -1
; LA32-NEXT: vinsgr2vr.w $vr0, $a2, 1
; LA32-NEXT: vinsgr2vr.w $vr0, $a1, 3
-; LA32-NEXT: vori.b $vr1, $vr0, 0
-; LA32-NEXT: vextrins.w $vr1, $vr1, 16
-; LA32-NEXT: vextrins.w $vr1, $vr0, 33
-; LA32-NEXT: vextrins.w $vr1, $vr0, 49
-; LA32-NEXT: vextrins.w $vr2, $vr0, 2
-; LA32-NEXT: vextrins.w $vr2, $vr0, 18
-; LA32-NEXT: vinsgr2vr.w $vr2, $a1, 2
-; LA32-NEXT: vinsgr2vr.w $vr2, $a1, 3
-; LA32-NEXT: xvpermi.q $xr1, $xr2, 2
-; LA32-NEXT: xvst $xr1, $a0, 0
+; LA32-NEXT: vext2xv.d.w $xr0, $xr0
+; LA32-NEXT: xvst $xr0, $a0, 0
; LA32-NEXT: ret
;
; LA64-LABEL: or_sext_masks_v4i64:
@@ -428,13 +412,13 @@ 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: xvrepli.b $xr1, 0
-; LA32-NEXT: xvinsve0.w $xr1, $xr0, 0
-; LA32-NEXT: xvinsve0.w $xr1, $xr0, 1
-; LA32-NEXT: xvpickve.w $xr0, $xr0, 4
-; LA32-NEXT: xvinsve0.w $xr1, $xr0, 4
-; LA32-NEXT: xvinsve0.w $xr1, $xr0, 5
-; LA32-NEXT: xvst $xr1, $a0, 0
+; 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: vext2xv.d.w $xr0, $xr0
+; LA32-NEXT: xvst $xr0, $a0, 0
; LA32-NEXT: ret
;
; LA64-LABEL: and_sext_masks_v4i64:
More information about the llvm-commits
mailing list