[llvm-branch-commits] [llvm] [LoongArch] Add DAG combine for widening shift-left (PR #202602)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jun 9 06:01:07 PDT 2026


https://github.com/heiher created https://github.com/llvm/llvm-project/pull/202602

Add DAG combines to recognize vector widening left-shift idioms and lower them to VSLLWIL instructions.

The following pattern is matched for both signed and unsigned variants:

```
  SEXT/ZEXT(Low-Half-Lanes(vec)) << Imm
```

This covers the following instructions:

```
  LSX:  VSLLWIL.H.B, VSLLWIL.W.H, VSLLWIL.D.W
        VSLLWIL.HU.BU, VSLLWIL.WU.HU, VSLLWIL.DU.WU

  LASX: XVSLLWIL.H.B, XVSLLWIL.W.H, XVSLLWIL.D.W
        XVSLLWIL.HU.BU, XVSLLWIL.WU.HU, XVSLLWIL.DU.WU
```

>From f7fc4d91f03a4a23e8049ebff87557fea52f07f8 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Fri, 5 Jun 2026 15:47:13 +0800
Subject: [PATCH] [LoongArch] Add DAG combine for widening shift-left

Add DAG combines to recognize vector widening left-shift idioms and
lower them to VSLLWIL instructions.

The following pattern is matched for both signed and unsigned variants:

```
  SEXT/ZEXT(Low-Half-Lanes(vec)) << Imm
```

This covers the following instructions:

```
  LSX:  VSLLWIL.H.B, VSLLWIL.W.H, VSLLWIL.D.W
        VSLLWIL.HU.BU, VSLLWIL.WU.HU, VSLLWIL.DU.WU

  LASX: XVSLLWIL.H.B, XVSLLWIL.W.H, XVSLLWIL.D.W
        XVSLLWIL.HU.BU, XVSLLWIL.WU.HU, XVSLLWIL.DU.WU
```
---
 .../LoongArch/LoongArchISelLowering.cpp       | 131 +++++++++++++++++
 .../LoongArch/LoongArchLASXInstrInfo.td       |  24 ++++
 .../Target/LoongArch/LoongArchLSXInstrInfo.td |  29 ++++
 llvm/test/CodeGen/LoongArch/lasx/vsllwil.ll   | 134 +-----------------
 llvm/test/CodeGen/LoongArch/lsx/vsllwil.ll    |  24 +---
 5 files changed, 196 insertions(+), 146 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 1b2258df77fa1..fa9096e0f1ef0 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -510,6 +510,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
   if (Subtarget.hasExtLSX()) {
     setTargetDAGCombine(ISD::ADD);
     setTargetDAGCombine(ISD::SUB);
+    setTargetDAGCombine(ISD::SHL);
     setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
     setTargetDAGCombine(ISD::BITCAST);
     setTargetDAGCombine(ISD::VSELECT);
@@ -6222,6 +6223,134 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
                      DAG.getConstant(lsb, DL, GRLenVT));
 }
 
+// Return the original source vector if N consists of the low half
+// of each 128-bit lane.
+static SDValue matchLowHalfOf128BitLanes(SDValue N) {
+  N = peekThroughBitcasts(N);
+
+  EVT DstVT = N.getValueType();
+  if (!DstVT.isVector())
+    return SDValue();
+
+  // LSX canonical form:
+  if (N.getOpcode() == ISD::EXTRACT_SUBVECTOR) {
+    SDValue Src = N.getOperand(0);
+    EVT SrcVT = Src.getValueType();
+
+    if (!SrcVT.isVector() || !SrcVT.is128BitVector())
+      return SDValue();
+    if (N.getConstantOperandVal(1) != 0)
+      return SDValue();
+    if (SrcVT.getSizeInBits() != DstVT.getSizeInBits() * 2)
+      return SDValue();
+    if (SrcVT.getVectorNumElements() != DstVT.getVectorNumElements() * 2)
+      return SDValue();
+
+    return Src;
+  }
+
+  // LASX canonical form:
+  auto *BV = dyn_cast<BuildVectorSDNode>(N);
+  if (!BV)
+    return SDValue();
+
+  unsigned NumElts = DstVT.getVectorNumElements();
+  if (NumElts % 2 != 0)
+    return SDValue();
+
+  SDValue Src;
+  EVT SrcVT;
+
+  for (unsigned I = 0; I != NumElts; ++I) {
+    SDValue Elt = BV->getOperand(I);
+    if (Elt.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
+      return SDValue();
+
+    SDValue ThisSrc = Elt.getOperand(0);
+    SDValue Idx = Elt.getOperand(1);
+    auto *CI = dyn_cast<ConstantSDNode>(Idx);
+    if (!CI)
+      return SDValue();
+
+    if (!Src) {
+      Src = ThisSrc;
+      SrcVT = Src.getValueType();
+      if (!SrcVT.isVector())
+        return SDValue();
+
+      if (SrcVT.getSizeInBits() != DstVT.getSizeInBits() * 2)
+        return SDValue();
+      if (SrcVT.getVectorNumElements() != NumElts * 2)
+        return SDValue();
+      if (!SrcVT.is256BitVector())
+        return SDValue();
+    } else if (ThisSrc != Src) {
+      return SDValue();
+    }
+
+    unsigned Half = NumElts / 2;
+    unsigned ExpectedIdx = (I < Half) ? I : (I + Half);
+    if (CI->getZExtValue() != ExpectedIdx)
+      return SDValue();
+  }
+
+  return Src;
+}
+
+static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
+                                 TargetLowering::DAGCombinerInfo &DCI,
+                                 const LoongArchSubtarget &Subtarget) {
+  if (!Subtarget.hasExtLSX())
+    return SDValue();
+
+  assert(N->getOpcode() == ISD::SHL && "Unexpected opcode");
+
+  EVT VT = N->getValueType(0);
+  SDLoc DL(N);
+
+  SDValue LHS = N->getOperand(0);
+  SDValue RHS = N->getOperand(1);
+
+  bool isSigned;
+  unsigned ExtOpc = LHS.getOpcode();
+  if (ExtOpc == ISD::SIGN_EXTEND)
+    isSigned = true;
+  else if (ExtOpc == ISD::ZERO_EXTEND)
+    isSigned = false;
+  else
+    return SDValue();
+
+  if (!LHS.hasOneUse())
+    return SDValue();
+
+  SDValue Vec = matchLowHalfOf128BitLanes(LHS.getOperand(0));
+  if (!Vec)
+    return SDValue();
+
+  EVT SrcVT = Vec.getValueType();
+  EVT SrcEltVT = SrcVT.getVectorElementType();
+  EVT DstEltVT = VT.getVectorElementType();
+
+  if (!SrcVT.isVector() || !VT.isVector())
+    return SDValue();
+  if (SrcVT.getSizeInBits() != VT.getSizeInBits())
+    return SDValue();
+  if (DstEltVT.getSizeInBits() != SrcEltVT.getSizeInBits() * 2)
+    return SDValue();
+  if (!SrcEltVT.isInteger() || SrcEltVT.getSizeInBits() > 32)
+    return SDValue();
+
+  APInt Imm;
+  if (!isConstantSplatVector(RHS, Imm, DstEltVT.getSizeInBits()))
+    return SDValue();
+  if (!Imm.ult(SrcEltVT.getSizeInBits()))
+    return SDValue();
+
+  unsigned Opc = isSigned ? LoongArchISD::VSLLWIL : LoongArchISD::VSLLWIL_U;
+  SDValue Sht = DAG.getConstant(Imm.getZExtValue(), DL, Subtarget.getGRLenVT());
+  return DAG.getNode(Opc, DL, VT, Vec, Sht);
+}
+
 static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG,
                                  TargetLowering::DAGCombinerInfo &DCI,
                                  const LoongArchSubtarget &Subtarget) {
@@ -8176,6 +8305,8 @@ SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N,
     return performORCombine(N, DAG, DCI, Subtarget);
   case ISD::SETCC:
     return performSETCCCombine(N, DAG, DCI, Subtarget);
+  case ISD::SHL:
+    return performSHLCombine(N, DAG, DCI, Subtarget);
   case ISD::SRL:
     return performSRLCombine(N, DAG, DCI, Subtarget);
   case ISD::SUB:
diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index 24a03d592dc92..43dc267213001 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -1234,6 +1234,24 @@ multiclass PatXrXrWU<SDPatternOperator OpNode, string Inst> {
             (!cast<LAInst>(Inst#"_QU_DU") LASX256:$vj, LASX256:$vk)>;
 }
 
+multiclass PatXrUimmW<SDPatternOperator OpNode, string Inst> {
+  def : Pat<(v16i16 (OpNode(v32i8 LASX256:$vj), uimm3:$imm)),
+            (!cast<LAInst>(Inst#"_H_B") LASX256:$vj, uimm3:$imm)>;
+  def : Pat<(v8i32 (OpNode(v16i16 LASX256:$vj), uimm4:$imm)),
+            (!cast<LAInst>(Inst#"_W_H") LASX256:$vj, uimm4:$imm)>;
+  def : Pat<(v4i64 (OpNode(v8i32 LASX256:$vj), uimm5:$imm)),
+            (!cast<LAInst>(Inst#"_D_W") LASX256:$vj, uimm5:$imm)>;
+}
+
+multiclass PatXrUimmWU<SDPatternOperator OpNode, string Inst> {
+  def : Pat<(v16i16 (OpNode(v32i8 LASX256:$vj), uimm3:$imm)),
+            (!cast<LAInst>(Inst#"_HU_BU") LASX256:$vj, uimm3:$imm)>;
+  def : Pat<(v8i32 (OpNode(v16i16 LASX256:$vj), uimm4:$imm)),
+            (!cast<LAInst>(Inst#"_WU_HU") LASX256:$vj, uimm4:$imm)>;
+  def : Pat<(v4i64 (OpNode(v8i32 LASX256:$vj), uimm5:$imm)),
+            (!cast<LAInst>(Inst#"_DU_WU") LASX256:$vj, uimm5:$imm)>;
+}
+
 multiclass PatShiftXrXr<SDPatternOperator OpNode, string Inst> {
   def : Pat<(OpNode (v32i8 LASX256:$xj), (and vsplati8_imm_eq_7,
                                               (v32i8 LASX256:$xk))),
@@ -1498,6 +1516,12 @@ defm : PatXrXr<rotr, "XVROTR">;
 defm : PatShiftXrXr<rotr, "XVROTR">;
 defm : PatShiftXrSplatUimm<rotr, "XVROTRI">;
 
+// XVSLLWIL_{H_B/W_H/D_W}
+defm : PatXrUimmW<loongarch_vsllwil, "XVSLLWIL">;
+
+// XVSLLWIL_{HU_BU/WU_HU/DU_WU}
+defm : PatXrUimmWU<loongarch_vsllwil_u, "XVSLLWIL">;
+
 // XVCLO_{B/H/W/D}
 def : Pat<(ctlz (vnot v32i8:$xj)), (XVCLO_B v32i8:$xj)>;
 def : Pat<(ctlz (vnot v16i16:$xj)), (XVCLO_H v16i16:$xj)>;
diff --git a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
index 21861378cbb3d..23ef4981df772 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
@@ -28,6 +28,7 @@ def SDT_LoongArchV2RUimm
                     [SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<1, 2>,
                      SDTCisVT<3, GRLenVT>]>;
 def SDT_LoongArchVHW : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisSameAs<1, 2>]>;
+def SDT_LoongArchVSW : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisVec<1>, SDTCisVT<2, GRLenVT>]>;
 def SDT_LoongArchVreplgr2vr : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisVec<0>, SDTCisInt<1>]>;
 def SDT_LoongArchVFRECIPE : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVec<0>, SDTCisSameAs<0, 1>]>;
 def SDT_LoongArchVFRSQRTE : SDTypeProfile<1, 1, [SDTCisFP<0>, SDTCisVec<0>, SDTCisSameAs<0, 1>]>;
@@ -86,6 +87,10 @@ def loongarch_vsrli : SDNode<"LoongArchISD::VSRLI", SDT_LoongArchV1RUimm>;
 def loongarch_vbsll : SDNode<"LoongArchISD::VBSLL", SDT_LoongArchV1RUimm>;
 def loongarch_vbsrl : SDNode<"LoongArchISD::VBSRL", SDT_LoongArchV1RUimm>;
 
+// Vector Logicial Left Shift with Widening
+def loongarch_vsllwil : SDNode<"LoongArchISD::VSLLWIL", SDT_LoongArchVSW>;
+def loongarch_vsllwil_u : SDNode<"LoongArchISD::VSLLWIL_U", SDT_LoongArchVSW>;
+
 // Vector Horizontal Addition with Widening
 def loongarch_vhaddw : SDNode<"LoongArchISD::VHADDW", SDT_LoongArchVHW>;
 def loongarch_vhaddw_u : SDNode<"LoongArchISD::VHADDW_U", SDT_LoongArchVHW>;
@@ -1466,6 +1471,24 @@ multiclass PatVrVrWU<SDPatternOperator OpNode, string Inst> {
             (!cast<LAInst>(Inst#"_QU_DU") LSX128:$vj, LSX128:$vk)>;
 }
 
+multiclass PatVrUimmW<SDPatternOperator OpNode, string Inst> {
+  def : Pat<(v8i16 (OpNode(v16i8 LSX128:$vj), uimm3:$imm)),
+            (!cast<LAInst>(Inst#"_H_B") LSX128:$vj, uimm3:$imm)>;
+  def : Pat<(v4i32 (OpNode(v8i16 LSX128:$vj), uimm4:$imm)),
+            (!cast<LAInst>(Inst#"_W_H") LSX128:$vj, uimm4:$imm)>;
+  def : Pat<(v2i64 (OpNode(v4i32 LSX128:$vj), uimm5:$imm)),
+            (!cast<LAInst>(Inst#"_D_W") LSX128:$vj, uimm5:$imm)>;
+}
+
+multiclass PatVrUimmWU<SDPatternOperator OpNode, string Inst> {
+  def : Pat<(v8i16 (OpNode(v16i8 LSX128:$vj), uimm3:$imm)),
+            (!cast<LAInst>(Inst#"_HU_BU") LSX128:$vj, uimm3:$imm)>;
+  def : Pat<(v4i32 (OpNode(v8i16 LSX128:$vj), uimm4:$imm)),
+            (!cast<LAInst>(Inst#"_WU_HU") LSX128:$vj, uimm4:$imm)>;
+  def : Pat<(v2i64 (OpNode(v4i32 LSX128:$vj), uimm5:$imm)),
+            (!cast<LAInst>(Inst#"_DU_WU") LSX128:$vj, uimm5:$imm)>;
+}
+
 multiclass PatShiftVrVr<SDPatternOperator OpNode, string Inst> {
   def : Pat<(OpNode (v16i8 LSX128:$vj), (and vsplati8_imm_eq_7,
                                              (v16i8 LSX128:$vk))),
@@ -1748,6 +1771,12 @@ defm : PatVrVr<rotr, "VROTR">;
 defm : PatShiftVrVr<rotr, "VROTR">;
 defm : PatShiftVrSplatUimm<rotr, "VROTRI">;
 
+// VSLLWIL_{H_B/W_H/D_W}
+defm : PatVrUimmW<loongarch_vsllwil, "VSLLWIL">;
+
+// VSLLWIL_{HU_BU/WU_HU/DU_WU}
+defm : PatVrUimmWU<loongarch_vsllwil_u, "VSLLWIL">;
+
 // VCLO_{B/H/W/D}
 def : Pat<(ctlz (vnot v16i8:$vj)), (VCLO_B v16i8:$vj)>;
 def : Pat<(ctlz (vnot v8i16:$vj)), (VCLO_H v8i16:$vj)>;
diff --git a/llvm/test/CodeGen/LoongArch/lasx/vsllwil.ll b/llvm/test/CodeGen/LoongArch/lasx/vsllwil.ll
index b85c3310d9525..53e8e9959ef73 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/vsllwil.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/vsllwil.ll
@@ -5,41 +5,7 @@
 define <16 x i16> @vsllwil_h_b(<32 x i8> %a) nounwind {
 ; CHECK-LABEL: vsllwil_h_b:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 0
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 0
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 1
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 1
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 2
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 2
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 3
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 3
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 4
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 4
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 5
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 5
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 6
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 6
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 7
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 7
-; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 14
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 0
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 8
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 1
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 9
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 2
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 10
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 3
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 11
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 4
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 12
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 5
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 13
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 6
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 14
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 7
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 15
-; CHECK-NEXT:    vext2xv.h.b $xr0, $xr1
-; CHECK-NEXT:    xvslli.h $xr0, $xr0, 1
+; CHECK-NEXT:    xvsllwil.h.b $xr0, $xr0, 1
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <32 x i8> %a, <32 x i8> poison,
@@ -53,25 +19,7 @@ entry:
 define <8 x i32> @vsllwil_w_h(<16 x i16> %a) nounwind {
 ; CHECK-LABEL: vsllwil_w_h:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 0
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 0
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 1
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 1
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 2
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 2
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 3
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 3
-; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 14
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 0
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 4
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 1
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 5
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 2
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 6
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 3
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 7
-; CHECK-NEXT:    vext2xv.w.h $xr0, $xr1
-; CHECK-NEXT:    xvslli.w $xr0, $xr0, 15
+; CHECK-NEXT:    xvsllwil.w.h $xr0, $xr0, 15
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <16 x i16> %a, <16 x i16> poison,
@@ -84,16 +32,7 @@ entry:
 define <4 x i64> @vsllwil_d_w(<8 x i32> %a) nounwind {
 ; CHECK-LABEL: vsllwil_d_w:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; CHECK-NEXT:    vinsgr2vr.w $vr1, $a0, 0
-; CHECK-NEXT:    xvpickve2gr.w $a0, $xr0, 1
-; CHECK-NEXT:    vinsgr2vr.w $vr1, $a0, 1
-; CHECK-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; CHECK-NEXT:    vinsgr2vr.w $vr1, $a0, 2
-; CHECK-NEXT:    xvpickve2gr.w $a0, $xr0, 5
-; CHECK-NEXT:    vinsgr2vr.w $vr1, $a0, 3
-; CHECK-NEXT:    vext2xv.d.w $xr0, $xr1
-; CHECK-NEXT:    xvslli.d $xr0, $xr0, 31
+; CHECK-NEXT:    xvsllwil.d.w $xr0, $xr0, 31
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <8 x i32> %a, <8 x i32> poison,
@@ -106,41 +45,7 @@ entry:
 define <16 x i16> @vsllwil_hu_bu(<32 x i8> %a) nounwind {
 ; CHECK-LABEL: vsllwil_hu_bu:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 0
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 0
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 1
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 1
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 2
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 2
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 3
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 3
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 4
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 4
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 5
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 5
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 6
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 6
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 7
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 7
-; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 14
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 0
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 8
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 1
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 9
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 2
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 10
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 3
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 11
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 4
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 12
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 5
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 13
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 6
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 14
-; CHECK-NEXT:    vpickve2gr.b $a0, $vr0, 7
-; CHECK-NEXT:    vinsgr2vr.b $vr1, $a0, 15
-; CHECK-NEXT:    vext2xv.hu.bu $xr0, $xr1
-; CHECK-NEXT:    xvslli.h $xr0, $xr0, 1
+; CHECK-NEXT:    xvsllwil.hu.bu $xr0, $xr0, 1
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <32 x i8> %a, <32 x i8> poison,
@@ -154,25 +59,7 @@ entry:
 define <8 x i32> @vsllwil_wu_hu(<16 x i16> %a) nounwind {
 ; CHECK-LABEL: vsllwil_wu_hu:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 0
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 0
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 1
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 1
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 2
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 2
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 3
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 3
-; CHECK-NEXT:    xvpermi.d $xr0, $xr0, 14
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 0
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 4
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 1
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 5
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 2
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 6
-; CHECK-NEXT:    vpickve2gr.h $a0, $vr0, 3
-; CHECK-NEXT:    vinsgr2vr.h $vr1, $a0, 7
-; CHECK-NEXT:    vext2xv.wu.hu $xr0, $xr1
-; CHECK-NEXT:    xvslli.w $xr0, $xr0, 15
+; CHECK-NEXT:    xvsllwil.wu.hu $xr0, $xr0, 15
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <16 x i16> %a, <16 x i16> poison,
@@ -185,16 +72,7 @@ entry:
 define <4 x i64> @vsllwil_du_wu(<8 x i32> %a) nounwind {
 ; CHECK-LABEL: vsllwil_du_wu:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    xvpickve2gr.w $a0, $xr0, 0
-; CHECK-NEXT:    vinsgr2vr.w $vr1, $a0, 0
-; CHECK-NEXT:    xvpickve2gr.w $a0, $xr0, 1
-; CHECK-NEXT:    vinsgr2vr.w $vr1, $a0, 1
-; CHECK-NEXT:    xvpickve2gr.w $a0, $xr0, 4
-; CHECK-NEXT:    vinsgr2vr.w $vr1, $a0, 2
-; CHECK-NEXT:    xvpickve2gr.w $a0, $xr0, 5
-; CHECK-NEXT:    vinsgr2vr.w $vr1, $a0, 3
-; CHECK-NEXT:    vext2xv.du.wu $xr0, $xr1
-; CHECK-NEXT:    xvslli.d $xr0, $xr0, 31
+; CHECK-NEXT:    xvsllwil.du.wu $xr0, $xr0, 31
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <8 x i32> %a, <8 x i32> poison,
diff --git a/llvm/test/CodeGen/LoongArch/lsx/vsllwil.ll b/llvm/test/CodeGen/LoongArch/lsx/vsllwil.ll
index 597c5cecb844a..ac56b2bd46297 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/vsllwil.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/vsllwil.ll
@@ -5,9 +5,7 @@
 define <8 x i16> @vsllwil_h_b(<16 x i8> %a) nounwind {
 ; CHECK-LABEL: vsllwil_h_b:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vslti.b $vr1, $vr0, 0
-; CHECK-NEXT:    vilvl.b $vr0, $vr1, $vr0
-; CHECK-NEXT:    vslli.h $vr0, $vr0, 1
+; CHECK-NEXT:    vsllwil.h.b $vr0, $vr0, 1
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <16 x i8> %a, <16 x i8> poison,
@@ -20,9 +18,7 @@ entry:
 define <4 x i32> @vsllwil_w_h(<8 x i16> %a) nounwind {
 ; CHECK-LABEL: vsllwil_w_h:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vslti.h $vr1, $vr0, 0
-; CHECK-NEXT:    vilvl.h $vr0, $vr1, $vr0
-; CHECK-NEXT:    vslli.w $vr0, $vr0, 15
+; CHECK-NEXT:    vsllwil.w.h $vr0, $vr0, 15
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -34,9 +30,7 @@ entry:
 define <2 x i64> @vsllwil_d_w(<4 x i32> %a) nounwind {
 ; CHECK-LABEL: vsllwil_d_w:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vslti.w $vr1, $vr0, 0
-; CHECK-NEXT:    vilvl.w $vr0, $vr1, $vr0
-; CHECK-NEXT:    vslli.d $vr0, $vr0, 31
+; CHECK-NEXT:    vsllwil.d.w $vr0, $vr0, 31
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 0, i32 1>
@@ -48,9 +42,7 @@ entry:
 define <8 x i16> @vsllwil_hu_bu(<16 x i8> %a) nounwind {
 ; CHECK-LABEL: vsllwil_hu_bu:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vrepli.b $vr1, 0
-; CHECK-NEXT:    vilvl.b $vr0, $vr1, $vr0
-; CHECK-NEXT:    vslli.h $vr0, $vr0, 1
+; CHECK-NEXT:    vsllwil.hu.bu $vr0, $vr0, 1
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <16 x i8> %a, <16 x i8> poison,
@@ -63,9 +55,7 @@ entry:
 define <4 x i32> @vsllwil_wu_hu(<8 x i16> %a) nounwind {
 ; CHECK-LABEL: vsllwil_wu_hu:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vrepli.b $vr1, 0
-; CHECK-NEXT:    vilvl.h $vr0, $vr1, $vr0
-; CHECK-NEXT:    vslli.w $vr0, $vr0, 15
+; CHECK-NEXT:    vsllwil.wu.hu $vr0, $vr0, 15
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <8 x i16> %a, <8 x i16> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -77,9 +67,7 @@ entry:
 define <2 x i64> @vsllwil_du_wu(<4 x i32> %a) nounwind {
 ; CHECK-LABEL: vsllwil_du_wu:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vrepli.b $vr1, 0
-; CHECK-NEXT:    vilvl.w $vr0, $vr1, $vr0
-; CHECK-NEXT:    vslli.d $vr0, $vr0, 31
+; CHECK-NEXT:    vsllwil.du.wu $vr0, $vr0, 31
 ; CHECK-NEXT:    ret
 entry:
   %0 = shufflevector <4 x i32> %a, <4 x i32> poison, <2 x i32> <i32 0, i32 1>



More information about the llvm-branch-commits mailing list