[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