[llvm] [LoongArch] Custom lowering for LSX vector sign extensions (PR #194325)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 27 02:50:44 PDT 2026
https://github.com/lrzlin updated https://github.com/llvm/llvm-project/pull/194325
>From 823a517fe8ef54446cf05613f6c53077a763641d Mon Sep 17 00:00:00 2001
From: Lin Runze <lrzlin at 163.com>
Date: Mon, 27 Apr 2026 17:33:24 +0800
Subject: [PATCH] [LoongArch] Custom lowering for LSX vector sign extensions
---
.../LoongArch/LoongArchISelLowering.cpp | 107 ++++++++++
.../Target/LoongArch/LoongArchISelLowering.h | 2 +
llvm/test/CodeGen/LoongArch/lsx/vec-sext.ll | 185 +++++++-----------
llvm/test/CodeGen/LoongArch/lsx/vmskcond.ll | 10 +-
4 files changed, 187 insertions(+), 117 deletions(-)
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index a3f2ff2b88efb..3066895847cd3 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -399,6 +399,11 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::FP_EXTEND, MVT::v2f32, Custom);
// We want to legalize this to an f64 load rather than an i64 load.
setOperationAction(ISD::LOAD, MVT::v2f32, Custom);
+ for (MVT VT : {MVT::v2i64, MVT::v4i32, MVT::v8i16})
+ setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, VT, Custom);
+ for (MVT VT : {MVT::v16i16, MVT::v8i32, MVT::v4i64, MVT::v16i32, MVT::v8i64,
+ MVT::v16i64})
+ setOperationAction(ISD::SIGN_EXTEND, VT, Custom);
}
// Set operations for 'LASX' feature.
@@ -635,6 +640,8 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
return lowerFP_ROUND(Op, DAG);
case ISD::FP_EXTEND:
return lowerFP_EXTEND(Op, DAG);
+ case ISD::SIGN_EXTEND_VECTOR_INREG:
+ return lowerSIGN_EXTEND_VECTOR_INREG(Op, DAG);
}
return SDValue();
}
@@ -942,6 +949,36 @@ SDValue LoongArchTargetLowering::lowerSETCC(SDValue Op,
return SetCCNode;
}
+// Lower sext_invec using vslti instructions.
+// For example:
+// %b = sext <4 x i16> %a to <4 x i32>
+// can be lowered to:
+// VSLTI_H vr2, vr1, 0
+// VILVL.H vr1, vr2, vr1
+SDValue LoongArchTargetLowering::lowerSIGN_EXTEND_VECTOR_INREG(
+ SDValue Op, SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ SDValue Src = Op.getOperand(0);
+ MVT SrcVT = Src.getSimpleValueType();
+ MVT DstVT = Op.getSimpleValueType();
+
+ if (!SrcVT.is128BitVector())
+ return SDValue();
+
+ // lower to VSLTI + VILVL if extend could be done in single step.
+ if (DstVT.getScalarSizeInBits() / SrcVT.getScalarSizeInBits() == 2) {
+ SDValue Zero = DAG.getConstant(0, DL, SrcVT);
+ SDValue Mask = DAG.getNode(ISD::SETCC, DL, SrcVT, Src, Zero,
+ DAG.getCondCode(ISD::SETLT));
+ SDValue LoInterleaved =
+ DAG.getNode(LoongArchISD::VILVL, DL, SrcVT, Mask, Src);
+
+ return DAG.getBitcast(DstVT, LoInterleaved);
+ }
+
+ return SDValue();
+}
+
// Lower vecreduce_add using vhaddw instructions.
// For Example:
// call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %a)
@@ -5618,6 +5655,76 @@ void LoongArchTargetLowering::ReplaceNodeResults(
break;
}
+ case ISD::SIGN_EXTEND: {
+ // LASX has native VEXT2XV_* for sign extension.
+ if (!Subtarget.hasExtLSX() || Subtarget.hasExtLASX())
+ return;
+
+ EVT DstVT = N->getValueType(0);
+ SDValue Src = N->getOperand(0);
+ MVT SrcVT = Src.getSimpleValueType();
+
+ unsigned SrcEltBits = SrcVT.getScalarSizeInBits();
+ unsigned DstEltBits = DstVT.getScalarSizeInBits();
+ unsigned NumElts = DstVT.getVectorNumElements();
+
+ if (SrcVT.getSizeInBits() > 128)
+ return;
+
+ if (!DstVT.isVector() || DstVT.getSizeInBits() <= 128)
+ return;
+
+ // Legalize and extend the src to 128-bit first.
+ if (SrcVT.getSizeInBits() < 128) {
+ unsigned WidenSrcElts = 128 / SrcEltBits;
+ MVT WidenSrcVT = MVT::getVectorVT(SrcVT.getScalarType(), WidenSrcElts);
+ Src = DAG.getNode(ISD::INSERT_SUBVECTOR, DL, WidenSrcVT,
+ DAG.getUNDEF(WidenSrcVT), Src,
+ DAG.getVectorIdxConstant(0, DL));
+ SrcVT = WidenSrcVT;
+
+ unsigned FirstStageEltBits = 128 / NumElts;
+ MVT FirstStageEltVT = MVT::getIntegerVT(FirstStageEltBits);
+ MVT FirstStageVT = MVT::getVectorVT(FirstStageEltVT, NumElts);
+ Src = DAG.getNode(ISD::SIGN_EXTEND_VECTOR_INREG, DL, FirstStageVT, Src);
+ SrcVT = FirstStageVT;
+ SrcEltBits = FirstStageEltBits;
+ }
+
+ SmallVector<SDValue, 8> Blocks;
+ Blocks.push_back(Src);
+
+ // Sign-extend the src by using SLTI + VILVL + VILVH recursively.
+ while (SrcEltBits < DstEltBits) {
+ unsigned NextEltBits = SrcEltBits * 2;
+ MVT NextEltVT = MVT::getIntegerVT(NextEltBits);
+ unsigned CurEltsPerBlock = SrcVT.getVectorNumElements();
+ unsigned NextEltsPerBlock = CurEltsPerBlock / 2;
+ MVT NextBlockVT = MVT::getVectorVT(NextEltVT, NextEltsPerBlock);
+
+ SmallVector<SDValue, 8> NextBlocks;
+ NextBlocks.reserve(Blocks.size() * 2);
+ for (SDValue Block : Blocks) {
+ SDValue Zero = DAG.getConstant(0, DL, SrcVT);
+ SDValue Mask = DAG.getNode(ISD::SETCC, DL, SrcVT, Block, Zero,
+ DAG.getCondCode(ISD::SETLT));
+ SDValue LoInterleaved =
+ DAG.getNode(LoongArchISD::VILVL, DL, SrcVT, Mask, Block);
+ SDValue HiInterleaved =
+ DAG.getNode(LoongArchISD::VILVH, DL, SrcVT, Mask, Block);
+
+ NextBlocks.push_back(DAG.getBitcast(NextBlockVT, LoInterleaved));
+ NextBlocks.push_back(DAG.getBitcast(NextBlockVT, HiInterleaved));
+ }
+
+ Blocks = std::move(NextBlocks);
+ SrcVT = NextBlockVT;
+ SrcEltBits = NextEltBits;
+ }
+
+ Results.push_back(DAG.getNode(ISD::CONCAT_VECTORS, DL, DstVT, Blocks));
+ break;
+ }
}
}
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index c945b8226e07d..4cc1aa2261ecc 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -17,6 +17,7 @@
#include "LoongArch.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/CodeGen/TargetLowering.h"
namespace llvm {
@@ -248,6 +249,7 @@ class LoongArchTargetLowering : public TargetLowering {
SDValue lowerRotate(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFP_ROUND(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerFP_EXTEND(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerSIGN_EXTEND_VECTOR_INREG(SDValue Op, SelectionDAG &DAG) const;
bool isFPImmLegal(const APFloat &Imm, EVT VT,
bool ForCodeSize) const override;
diff --git a/llvm/test/CodeGen/LoongArch/lsx/vec-sext.ll b/llvm/test/CodeGen/LoongArch/lsx/vec-sext.ll
index 9fa0b3838967b..22e87d812eafa 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/vec-sext.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/vec-sext.ll
@@ -44,9 +44,8 @@ define void @load_sext_8i8_to_8i16(ptr %ptr, ptr %dst) {
; LA32-NEXT: ld.w $a0, $a0, 4
; LA32-NEXT: vinsgr2vr.w $vr0, $a2, 0
; LA32-NEXT: vinsgr2vr.w $vr0, $a0, 1
-; LA32-NEXT: vilvl.b $vr0, $vr0, $vr0
-; LA32-NEXT: vslli.h $vr0, $vr0, 8
-; LA32-NEXT: vsrai.h $vr0, $vr0, 8
+; LA32-NEXT: vslti.b $vr1, $vr0, 0
+; LA32-NEXT: vilvl.b $vr0, $vr1, $vr0
; LA32-NEXT: vst $vr0, $a1, 0
; LA32-NEXT: ret
;
@@ -54,9 +53,8 @@ define void @load_sext_8i8_to_8i16(ptr %ptr, ptr %dst) {
; LA64: # %bb.0: # %entry
; LA64-NEXT: ld.d $a0, $a0, 0
; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
-; LA64-NEXT: vilvl.b $vr0, $vr0, $vr0
-; LA64-NEXT: vslli.h $vr0, $vr0, 8
-; LA64-NEXT: vsrai.h $vr0, $vr0, 8
+; LA64-NEXT: vslti.b $vr1, $vr0, 0
+; LA64-NEXT: vilvl.b $vr0, $vr1, $vr0
; LA64-NEXT: vst $vr0, $a1, 0
; LA64-NEXT: ret
entry:
@@ -90,9 +88,8 @@ define void @load_sext_4i16_to_4i32(ptr %ptr, ptr %dst) {
; LA32-NEXT: ld.w $a0, $a0, 4
; LA32-NEXT: vinsgr2vr.w $vr0, $a2, 0
; LA32-NEXT: vinsgr2vr.w $vr0, $a0, 1
-; LA32-NEXT: vilvl.h $vr0, $vr0, $vr0
-; LA32-NEXT: vslli.w $vr0, $vr0, 16
-; LA32-NEXT: vsrai.w $vr0, $vr0, 16
+; LA32-NEXT: vslti.h $vr1, $vr0, 0
+; LA32-NEXT: vilvl.h $vr0, $vr1, $vr0
; LA32-NEXT: vst $vr0, $a1, 0
; LA32-NEXT: ret
;
@@ -100,9 +97,8 @@ define void @load_sext_4i16_to_4i32(ptr %ptr, ptr %dst) {
; LA64: # %bb.0: # %entry
; LA64-NEXT: ld.d $a0, $a0, 0
; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
-; LA64-NEXT: vilvl.h $vr0, $vr0, $vr0
-; LA64-NEXT: vslli.w $vr0, $vr0, 16
-; LA64-NEXT: vsrai.w $vr0, $vr0, 16
+; LA64-NEXT: vslti.h $vr1, $vr0, 0
+; LA64-NEXT: vilvl.h $vr0, $vr1, $vr0
; LA64-NEXT: vst $vr0, $a1, 0
; LA64-NEXT: ret
entry:
@@ -118,9 +114,9 @@ define void @load_sext_2i32_to_2i64(ptr %ptr, ptr %dst) {
; 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, 2
-; LA32-NEXT: vslli.d $vr0, $vr0, 32
-; LA32-NEXT: vsrai.d $vr0, $vr0, 32
+; LA32-NEXT: vinsgr2vr.w $vr0, $a0, 1
+; LA32-NEXT: vslti.w $vr1, $vr0, 0
+; LA32-NEXT: vilvl.w $vr0, $vr1, $vr0
; LA32-NEXT: vst $vr0, $a1, 0
; LA32-NEXT: ret
;
@@ -128,9 +124,8 @@ define void @load_sext_2i32_to_2i64(ptr %ptr, ptr %dst) {
; LA64: # %bb.0: # %entry
; LA64-NEXT: ld.d $a0, $a0, 0
; LA64-NEXT: vinsgr2vr.d $vr0, $a0, 0
-; LA64-NEXT: vshuf4i.w $vr0, $vr0, 16
-; LA64-NEXT: vslli.d $vr0, $vr0, 32
-; LA64-NEXT: vsrai.d $vr0, $vr0, 32
+; LA64-NEXT: vslti.w $vr1, $vr0, 0
+; LA64-NEXT: vilvl.w $vr0, $vr1, $vr0
; LA64-NEXT: vst $vr0, $a1, 0
; LA64-NEXT: ret
entry:
@@ -144,14 +139,11 @@ 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: vilvl.b $vr1, $vr0, $vr0
-; CHECK-NEXT: vslli.h $vr1, $vr1, 8
-; CHECK-NEXT: vsrai.h $vr1, $vr1, 8
-; CHECK-NEXT: vilvh.b $vr0, $vr0, $vr0
-; CHECK-NEXT: vslli.h $vr0, $vr0, 8
-; CHECK-NEXT: vsrai.h $vr0, $vr0, 8
+; CHECK-NEXT: vslti.b $vr1, $vr0, 0
+; CHECK-NEXT: vilvl.b $vr2, $vr1, $vr0
+; CHECK-NEXT: vilvh.b $vr0, $vr1, $vr0
; CHECK-NEXT: vst $vr0, $a1, 16
-; CHECK-NEXT: vst $vr1, $a1, 0
+; CHECK-NEXT: vst $vr2, $a1, 0
; CHECK-NEXT: ret
entry:
%A = load <16 x i8>, ptr %ptr
@@ -164,24 +156,19 @@ 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: vilvl.b $vr1, $vr0, $vr0
-; CHECK-NEXT: vilvl.h $vr2, $vr1, $vr1
-; CHECK-NEXT: vslli.w $vr2, $vr2, 24
-; CHECK-NEXT: vsrai.w $vr2, $vr2, 24
-; CHECK-NEXT: vilvh.h $vr1, $vr1, $vr1
-; CHECK-NEXT: vslli.w $vr1, $vr1, 24
-; CHECK-NEXT: vsrai.w $vr1, $vr1, 24
-; CHECK-NEXT: vilvh.b $vr0, $vr0, $vr0
-; CHECK-NEXT: vilvl.h $vr3, $vr0, $vr0
-; CHECK-NEXT: vslli.w $vr3, $vr3, 24
-; CHECK-NEXT: vsrai.w $vr3, $vr3, 24
-; CHECK-NEXT: vilvh.h $vr0, $vr0, $vr0
-; CHECK-NEXT: vslli.w $vr0, $vr0, 24
-; CHECK-NEXT: vsrai.w $vr0, $vr0, 24
+; CHECK-NEXT: vslti.b $vr1, $vr0, 0
+; CHECK-NEXT: vilvl.b $vr2, $vr1, $vr0
+; CHECK-NEXT: vslti.h $vr3, $vr2, 0
+; CHECK-NEXT: vilvl.h $vr4, $vr3, $vr2
+; CHECK-NEXT: vilvh.h $vr2, $vr3, $vr2
+; CHECK-NEXT: vilvh.b $vr0, $vr1, $vr0
+; CHECK-NEXT: vslti.h $vr1, $vr0, 0
+; CHECK-NEXT: vilvl.h $vr3, $vr1, $vr0
+; CHECK-NEXT: vilvh.h $vr0, $vr1, $vr0
; CHECK-NEXT: vst $vr0, $a1, 48
; CHECK-NEXT: vst $vr3, $a1, 32
-; CHECK-NEXT: vst $vr1, $a1, 16
-; CHECK-NEXT: vst $vr2, $a1, 0
+; CHECK-NEXT: vst $vr2, $a1, 16
+; CHECK-NEXT: vst $vr4, $a1, 0
; CHECK-NEXT: ret
entry:
%A = load <16 x i8>, ptr %ptr
@@ -194,44 +181,35 @@ 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: vilvl.b $vr1, $vr0, $vr0
-; CHECK-NEXT: vilvl.h $vr2, $vr1, $vr1
-; CHECK-NEXT: vilvh.w $vr2, $vr2, $vr2
-; CHECK-NEXT: vslli.d $vr2, $vr2, 56
-; CHECK-NEXT: vsrai.d $vr2, $vr2, 56
-; CHECK-NEXT: vilvh.h $vr1, $vr1, $vr1
-; CHECK-NEXT: vilvl.w $vr3, $vr1, $vr1
-; CHECK-NEXT: vslli.d $vr3, $vr3, 56
-; CHECK-NEXT: vsrai.d $vr3, $vr3, 56
-; CHECK-NEXT: vilvh.w $vr1, $vr1, $vr1
-; CHECK-NEXT: vslli.d $vr1, $vr1, 56
-; CHECK-NEXT: vsrai.d $vr1, $vr1, 56
-; CHECK-NEXT: vilvh.b $vr4, $vr0, $vr0
-; CHECK-NEXT: vilvl.h $vr5, $vr4, $vr4
-; CHECK-NEXT: vilvl.w $vr6, $vr5, $vr5
-; CHECK-NEXT: vslli.d $vr6, $vr6, 56
-; CHECK-NEXT: vsrai.d $vr6, $vr6, 56
-; CHECK-NEXT: vilvh.w $vr5, $vr5, $vr5
-; CHECK-NEXT: vslli.d $vr5, $vr5, 56
-; CHECK-NEXT: vsrai.d $vr5, $vr5, 56
-; CHECK-NEXT: vilvh.h $vr4, $vr4, $vr4
-; CHECK-NEXT: vilvl.w $vr7, $vr4, $vr4
-; CHECK-NEXT: vslli.d $vr7, $vr7, 56
-; CHECK-NEXT: vsrai.d $vr7, $vr7, 56
-; CHECK-NEXT: vilvh.w $vr4, $vr4, $vr4
-; CHECK-NEXT: vslli.d $vr4, $vr4, 56
-; CHECK-NEXT: vsrai.d $vr4, $vr4, 56
-; CHECK-NEXT: vextrins.b $vr0, $vr0, 129
-; CHECK-NEXT: vslli.d $vr0, $vr0, 56
-; CHECK-NEXT: vsrai.d $vr0, $vr0, 56
-; CHECK-NEXT: vst $vr0, $a1, 0
-; CHECK-NEXT: vst $vr4, $a1, 112
+; CHECK-NEXT: vslti.b $vr1, $vr0, 0
+; CHECK-NEXT: vilvl.b $vr2, $vr1, $vr0
+; CHECK-NEXT: vslti.h $vr3, $vr2, 0
+; CHECK-NEXT: vilvl.h $vr4, $vr3, $vr2
+; CHECK-NEXT: vslti.w $vr5, $vr4, 0
+; CHECK-NEXT: vilvl.w $vr6, $vr5, $vr4
+; CHECK-NEXT: vilvh.w $vr4, $vr5, $vr4
+; CHECK-NEXT: vilvh.h $vr2, $vr3, $vr2
+; CHECK-NEXT: vslti.w $vr3, $vr2, 0
+; CHECK-NEXT: vilvl.w $vr5, $vr3, $vr2
+; CHECK-NEXT: vilvh.w $vr2, $vr3, $vr2
+; CHECK-NEXT: vilvh.b $vr0, $vr1, $vr0
+; CHECK-NEXT: vslti.h $vr1, $vr0, 0
+; CHECK-NEXT: vilvl.h $vr3, $vr1, $vr0
+; CHECK-NEXT: vslti.w $vr7, $vr3, 0
+; CHECK-NEXT: vilvl.w $vr8, $vr7, $vr3
+; CHECK-NEXT: vilvh.w $vr3, $vr7, $vr3
+; CHECK-NEXT: vilvh.h $vr0, $vr1, $vr0
+; CHECK-NEXT: vslti.w $vr1, $vr0, 0
+; CHECK-NEXT: vilvl.w $vr7, $vr1, $vr0
+; CHECK-NEXT: vilvh.w $vr0, $vr1, $vr0
+; CHECK-NEXT: vst $vr0, $a1, 112
; CHECK-NEXT: vst $vr7, $a1, 96
-; CHECK-NEXT: vst $vr5, $a1, 80
-; CHECK-NEXT: vst $vr6, $a1, 64
-; CHECK-NEXT: vst $vr1, $a1, 48
-; CHECK-NEXT: vst $vr3, $a1, 32
-; CHECK-NEXT: vst $vr2, $a1, 16
+; CHECK-NEXT: vst $vr3, $a1, 80
+; CHECK-NEXT: vst $vr8, $a1, 64
+; CHECK-NEXT: vst $vr2, $a1, 48
+; CHECK-NEXT: vst $vr5, $a1, 32
+; CHECK-NEXT: vst $vr4, $a1, 16
+; CHECK-NEXT: vst $vr6, $a1, 0
; CHECK-NEXT: ret
entry:
%A = load <16 x i8>, ptr %ptr
@@ -244,14 +222,11 @@ 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: vilvl.h $vr1, $vr0, $vr0
-; CHECK-NEXT: vslli.w $vr1, $vr1, 16
-; CHECK-NEXT: vsrai.w $vr1, $vr1, 16
-; CHECK-NEXT: vilvh.h $vr0, $vr0, $vr0
-; CHECK-NEXT: vslli.w $vr0, $vr0, 16
-; CHECK-NEXT: vsrai.w $vr0, $vr0, 16
+; CHECK-NEXT: vslti.h $vr1, $vr0, 0
+; CHECK-NEXT: vilvl.h $vr2, $vr1, $vr0
+; CHECK-NEXT: vilvh.h $vr0, $vr1, $vr0
; CHECK-NEXT: vst $vr0, $a1, 16
-; CHECK-NEXT: vst $vr1, $a1, 0
+; CHECK-NEXT: vst $vr2, $a1, 0
; CHECK-NEXT: ret
entry:
%A = load <8 x i16>, ptr %ptr
@@ -264,24 +239,19 @@ 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: vilvl.h $vr1, $vr0, $vr0
-; CHECK-NEXT: vilvh.w $vr1, $vr1, $vr1
-; CHECK-NEXT: vslli.d $vr1, $vr1, 48
-; CHECK-NEXT: vsrai.d $vr1, $vr1, 48
-; CHECK-NEXT: vilvh.h $vr2, $vr0, $vr0
-; CHECK-NEXT: vilvl.w $vr3, $vr2, $vr2
-; CHECK-NEXT: vslli.d $vr3, $vr3, 48
-; CHECK-NEXT: vsrai.d $vr3, $vr3, 48
-; CHECK-NEXT: vilvh.w $vr2, $vr2, $vr2
-; CHECK-NEXT: vslli.d $vr2, $vr2, 48
-; CHECK-NEXT: vsrai.d $vr2, $vr2, 48
-; CHECK-NEXT: vextrins.h $vr0, $vr0, 65
-; CHECK-NEXT: vslli.d $vr0, $vr0, 48
-; CHECK-NEXT: vsrai.d $vr0, $vr0, 48
-; CHECK-NEXT: vst $vr0, $a1, 0
-; CHECK-NEXT: vst $vr2, $a1, 48
+; CHECK-NEXT: vslti.h $vr1, $vr0, 0
+; CHECK-NEXT: vilvl.h $vr2, $vr1, $vr0
+; CHECK-NEXT: vslti.w $vr3, $vr2, 0
+; CHECK-NEXT: vilvl.w $vr4, $vr3, $vr2
+; CHECK-NEXT: vilvh.w $vr2, $vr3, $vr2
+; CHECK-NEXT: vilvh.h $vr0, $vr1, $vr0
+; CHECK-NEXT: vslti.w $vr1, $vr0, 0
+; CHECK-NEXT: vilvl.w $vr3, $vr1, $vr0
+; CHECK-NEXT: vilvh.w $vr0, $vr1, $vr0
+; CHECK-NEXT: vst $vr0, $a1, 48
; CHECK-NEXT: vst $vr3, $a1, 32
-; CHECK-NEXT: vst $vr1, $a1, 16
+; CHECK-NEXT: vst $vr2, $a1, 16
+; CHECK-NEXT: vst $vr4, $a1, 0
; CHECK-NEXT: ret
entry:
%A = load <8 x i16>, ptr %ptr
@@ -294,14 +264,11 @@ 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: vshuf4i.w $vr1, $vr0, 16
-; CHECK-NEXT: vslli.d $vr1, $vr1, 32
-; CHECK-NEXT: vsrai.d $vr1, $vr1, 32
-; CHECK-NEXT: vshuf4i.w $vr0, $vr0, 50
-; CHECK-NEXT: vslli.d $vr0, $vr0, 32
-; CHECK-NEXT: vsrai.d $vr0, $vr0, 32
+; CHECK-NEXT: vslti.w $vr1, $vr0, 0
+; CHECK-NEXT: vilvl.w $vr2, $vr1, $vr0
+; CHECK-NEXT: vilvh.w $vr0, $vr1, $vr0
; CHECK-NEXT: vst $vr0, $a1, 16
-; CHECK-NEXT: vst $vr1, $a1, 0
+; CHECK-NEXT: vst $vr2, $a1, 0
; CHECK-NEXT: ret
entry:
%A = load <4 x i32>, ptr %ptr
diff --git a/llvm/test/CodeGen/LoongArch/lsx/vmskcond.ll b/llvm/test/CodeGen/LoongArch/lsx/vmskcond.ll
index b72df478e73a1..2963c40e8d1b4 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/vmskcond.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/vmskcond.ll
@@ -206,8 +206,7 @@ define i2 @vmsk_sgt_v2i32(<2 x i32> %a, <2 x i32> %b) {
; CHECK-LABEL: vmsk_sgt_v2i32:
; CHECK: # %bb.0:
; CHECK-NEXT: vslt.w $vr0, $vr1, $vr0
-; CHECK-NEXT: vshuf4i.w $vr0, $vr0, 16
-; CHECK-NEXT: vslli.d $vr0, $vr0, 32
+; CHECK-NEXT: vilvl.w $vr0, $vr0, $vr0
; CHECK-NEXT: vmskltz.d $vr0, $vr0
; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0
; CHECK-NEXT: ret
@@ -260,7 +259,6 @@ define i4 @vmsk_sgt_v4i16(<4 x i16> %a, <4 x i16> %b) {
; CHECK: # %bb.0:
; CHECK-NEXT: vslt.h $vr0, $vr1, $vr0
; CHECK-NEXT: vilvl.h $vr0, $vr0, $vr0
-; CHECK-NEXT: vslli.w $vr0, $vr0, 16
; CHECK-NEXT: vmskltz.w $vr0, $vr0
; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0
; CHECK-NEXT: ret
@@ -298,7 +296,6 @@ define i8 @vmsk_sgt_v8i8(<8 x i8> %a, <8 x i8> %b) {
; CHECK: # %bb.0:
; CHECK-NEXT: vslt.b $vr0, $vr1, $vr0
; CHECK-NEXT: vilvl.b $vr0, $vr0, $vr0
-; CHECK-NEXT: vslli.h $vr0, $vr0, 8
; CHECK-NEXT: vmskltz.h $vr0, $vr0
; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0
; CHECK-NEXT: ret
@@ -373,8 +370,7 @@ define i2 @vmsk_sgt_and_sgt_v2i32(<2 x i32> %a, <2 x i32> %b, <2 x i32> %c, <2 x
; CHECK-NEXT: vslt.w $vr0, $vr1, $vr0
; CHECK-NEXT: vslt.w $vr1, $vr3, $vr2
; CHECK-NEXT: vand.v $vr0, $vr0, $vr1
-; CHECK-NEXT: vshuf4i.w $vr0, $vr0, 16
-; CHECK-NEXT: vslli.d $vr0, $vr0, 32
+; CHECK-NEXT: vilvl.w $vr0, $vr0, $vr0
; CHECK-NEXT: vmskltz.d $vr0, $vr0
; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0
; CHECK-NEXT: ret
@@ -443,7 +439,6 @@ define i4 @vmsk_sgt_and_sgt_v4i16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c, <4 x
; CHECK-NEXT: vslt.h $vr1, $vr3, $vr2
; CHECK-NEXT: vand.v $vr0, $vr0, $vr1
; CHECK-NEXT: vilvl.h $vr0, $vr0, $vr0
-; CHECK-NEXT: vslli.w $vr0, $vr0, 16
; CHECK-NEXT: vmskltz.w $vr0, $vr0
; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0
; CHECK-NEXT: ret
@@ -493,7 +488,6 @@ define i8 @vmsk_sgt_and_sgt_v8i8(<8 x i8> %a, <8 x i8> %b, <8 x i8> %c, <8 x i8>
; CHECK-NEXT: vslt.b $vr1, $vr3, $vr2
; CHECK-NEXT: vand.v $vr0, $vr0, $vr1
; CHECK-NEXT: vilvl.b $vr0, $vr0, $vr0
-; CHECK-NEXT: vslli.h $vr0, $vr0, 8
; CHECK-NEXT: vmskltz.h $vr0, $vr0
; CHECK-NEXT: vpickve2gr.hu $a0, $vr0, 0
; CHECK-NEXT: ret
More information about the llvm-commits
mailing list