[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