[llvm-branch-commits] [llvm] [LoongArch] Combine rounded vector shifts to VSRLR/VSRAR (PR #192921)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Apr 24 01:24:04 PDT 2026
https://github.com/heiher updated https://github.com/llvm/llvm-project/pull/192921
>From 234bc0242f8dd2080df20bc33a2c0e98934cada0 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Mon, 20 Apr 2026 14:32:03 +0800
Subject: [PATCH 1/2] [LoongArch] Combine rounded vector shifts to VSRLR/VSRAR
Add DAG combines to recognize canonical rounded shift patterns and
lower them to target-specific vector rounded shift instructions.
The combines match vector arithmetic and logical right shifts with
rounding implemented as:
```
add (srl/sra X, shift),
(and (srl X, shift-1), 1)
```
and the shift-by-1 variant:
```
add (srl/sra X, 1),
(and X, 1)
```
Additionally, handle the guarded form generated when shift may be zero:
```
vselect (setcc shift, 0, seteq),
X,
rounded_shift
```
and fold it to the corresponding rounded shift instruction.
Define new target DAG nodes VSRLR and VSRAR and add instruction
selection patterns for both LSX and LASX, including register and
immediate shift forms.
---
.../LoongArch/LoongArchISelLowering.cpp | 272 ++++++++++++++++++
.../LoongArch/LoongArchLASXInstrInfo.td | 8 +
.../Target/LoongArch/LoongArchLSXInstrInfo.td | 12 +
llvm/test/CodeGen/LoongArch/lasx/srar.ll | 77 +----
llvm/test/CodeGen/LoongArch/lasx/srlr.ll | 77 +----
llvm/test/CodeGen/LoongArch/lsx/srar.ll | 77 +----
llvm/test/CodeGen/LoongArch/lsx/srlr.ll | 77 +----
7 files changed, 340 insertions(+), 260 deletions(-)
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 446d27805fb35..71edc58ff7640 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -482,8 +482,10 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
// Set DAG combine for 'LSX' feature.
if (Subtarget.hasExtLSX()) {
+ setTargetDAGCombine(ISD::ADD);
setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);
setTargetDAGCombine(ISD::BITCAST);
+ setTargetDAGCombine(ISD::VSELECT);
}
// Set DAG combine for 'LASX' feature.
@@ -5439,6 +5441,139 @@ static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL,
return DAG.getNode(LoongArchISD::VANDN, DL, VT, X, Y);
}
+static bool isConstantSplatVector(SDValue N, APInt &SplatValue,
+ unsigned MinSizeInBits) {
+ if (N->getOpcode() == ISD::BITCAST)
+ N = N->getOperand(0);
+
+ BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N);
+
+ if (!Node)
+ return false;
+
+ APInt SplatUndef;
+ unsigned SplatBitSize;
+ bool HasAnyUndefs;
+
+ return Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
+ HasAnyUndefs, MinSizeInBits,
+ /*IsBigEndian=*/false);
+}
+
+static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const LoongArchSubtarget &Subtarget) {
+ if (DCI.isBeforeLegalizeOps())
+ return SDValue();
+
+ EVT VT = N->getValueType(0);
+ if (!VT.isVector())
+ return SDValue();
+
+ if (!DAG.getTargetLoweringInfo().isTypeLegal(VT))
+ return SDValue();
+
+ EVT EltVT = VT.getVectorElementType();
+ if (!EltVT.isInteger())
+ return SDValue();
+
+ // match:
+ //
+ // add
+ // (and
+ // (srl X, shift-1) / X
+ // 1)
+ // (srl/sra X, shift)
+
+ SDValue Add0 = N->getOperand(0);
+ SDValue Add1 = N->getOperand(1);
+ SDValue And;
+ SDValue Shr;
+
+ if (Add0.getOpcode() == ISD::AND) {
+ And = Add0;
+ Shr = Add1;
+ } else if (Add1.getOpcode() == ISD::AND) {
+ And = Add1;
+ Shr = Add0;
+ } else {
+ return SDValue();
+ }
+
+ // match:
+ //
+ // srl/sra X, shift
+
+ if (Shr.getOpcode() != ISD::SRL && Shr.getOpcode() != ISD::SRA)
+ return SDValue();
+
+ SDValue X = Shr.getOperand(0);
+ SDValue Shift = Shr.getOperand(1);
+ APInt ShiftVal;
+
+ if (!isConstantSplatVector(Shift, ShiftVal, EltVT.getSizeInBits()))
+ return SDValue();
+
+ if (ShiftVal == 0)
+ return SDValue();
+
+ // match:
+ //
+ // and
+ // (srl X, shift-1) / X
+ // 1
+
+ SDValue One = And.getOperand(1);
+ APInt SplatVal;
+
+ if (!isConstantSplatVector(One, SplatVal, EltVT.getSizeInBits()))
+ return SDValue();
+
+ if (SplatVal != 1)
+ return SDValue();
+
+ if (And.getOperand(0) == X) {
+ // match:
+ //
+ // shift == 1
+
+ if (ShiftVal != 1)
+ return SDValue();
+ } else {
+ // match:
+ //
+ // srl X, shift-1
+
+ SDValue Srl = And.getOperand(0);
+
+ if (Srl.getOpcode() != ISD::SRL)
+ return SDValue();
+
+ if (Srl.getOperand(0) != X)
+ return SDValue();
+
+ // match:
+ //
+ // shift-1
+
+ SDValue ShiftMinus1 = Srl.getOperand(1);
+
+ if (!isConstantSplatVector(ShiftMinus1, SplatVal, EltVT.getSizeInBits()))
+ return SDValue();
+
+ if (ShiftVal != (SplatVal + 1))
+ return SDValue();
+ }
+
+ // We matched a rounded right shift pattern and can lower it
+ // to a single vector rounded shift instruction.
+
+ SDLoc DL(N);
+ return DAG.getNode(Shr.getOpcode() == ISD::SRL ? LoongArchISD::VSRLR
+ : LoongArchISD::VSRAR,
+ DL, VT, X, Shift);
+}
+
static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const LoongArchSubtarget &Subtarget) {
@@ -7332,12 +7467,147 @@ performCONCAT_VECTORSCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const LoongArchSubtarget &Subtarget) {
+ if (DCI.isBeforeLegalizeOps())
+ return SDValue();
+
+ EVT VT = N->getValueType(0);
+ if (!VT.isVector())
+ return SDValue();
+
+ if (!DAG.getTargetLoweringInfo().isTypeLegal(VT))
+ return SDValue();
+
+ EVT EltVT = VT.getVectorElementType();
+ if (!EltVT.isInteger())
+ return SDValue();
+
+ SDValue Cond = N->getOperand(0);
+ SDValue TrueVal = N->getOperand(1);
+ SDValue FalseVal = N->getOperand(2);
+
+ // match:
+ //
+ // vselect (setcc shift, 0, seteq),
+ // x,
+ // rounded_shift
+
+ if (Cond.getOpcode() != ISD::SETCC)
+ return SDValue();
+
+ if (!ISD::isConstantSplatVectorAllZeros(Cond.getOperand(1).getNode()))
+ return SDValue();
+
+ auto *CC = cast<CondCodeSDNode>(Cond.getOperand(2));
+ if (CC->get() != ISD::SETEQ)
+ return SDValue();
+
+ SDValue Shift = Cond.getOperand(0);
+
+ // True branch must be original value:
+ //
+ // vselect cond, x, ...
+
+ SDValue X = TrueVal;
+
+ // Now match rounded shift pattern:
+ //
+ // add
+ // (and
+ // (srl X, shift-1)
+ // 1)
+ // (srl/sra X, shift)
+
+ if (FalseVal.getOpcode() != ISD::ADD)
+ return SDValue();
+
+ SDValue Add0 = FalseVal.getOperand(0);
+ SDValue Add1 = FalseVal.getOperand(1);
+ SDValue And;
+ SDValue Shr;
+
+ if (Add0.getOpcode() == ISD::AND) {
+ And = Add0;
+ Shr = Add1;
+ } else if (Add1.getOpcode() == ISD::AND) {
+ And = Add1;
+ Shr = Add0;
+ } else {
+ return SDValue();
+ }
+
+ // match:
+ //
+ // srl/sra X, shift
+
+ if (Shr.getOpcode() != ISD::SRL && Shr.getOpcode() != ISD::SRA)
+ return SDValue();
+
+ if (Shr.getOperand(0) != X)
+ return SDValue();
+
+ if (Shr.getOperand(1) != Shift)
+ return SDValue();
+
+ // match:
+ //
+ // and
+ // (srl X, shift-1)
+ // 1
+
+ SDValue Srl = And.getOperand(0);
+ SDValue One = And.getOperand(1);
+ APInt SplatVal;
+
+ if (Srl.getOpcode() != ISD::SRL)
+ return SDValue();
+
+ if (One.getOpcode() == ISD::BITCAST)
+ One = One.getOperand(0);
+
+ if (!isConstantSplatVector(One, SplatVal, EltVT.getSizeInBits()))
+ return SDValue();
+
+ if (SplatVal != 1)
+ return SDValue();
+
+ if (Srl.getOperand(0) != X)
+ return SDValue();
+
+ // match:
+ //
+ // shift-1
+
+ SDValue ShiftMinus1 = Srl.getOperand(1);
+
+ if (ShiftMinus1.getOpcode() != ISD::ADD)
+ return SDValue();
+
+ if (ShiftMinus1.getOperand(0) != Shift)
+ return SDValue();
+
+ if (!ISD::isConstantSplatVectorAllOnes(ShiftMinus1.getOperand(1).getNode()))
+ return SDValue();
+
+ // We matched a rounded right shift pattern and can lower it
+ // to a single vector rounded shift instruction.
+
+ SDLoc DL(N);
+ return DAG.getNode(Shr.getOpcode() == ISD::SRL ? LoongArchISD::VSRLR
+ : LoongArchISD::VSRAR,
+ DL, VT, X, Shift);
+}
+
SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N,
DAGCombinerInfo &DCI) const {
SelectionDAG &DAG = DCI.DAG;
switch (N->getOpcode()) {
default:
break;
+ case ISD::ADD:
+ return performADDCombine(N, DAG, DCI, Subtarget);
case ISD::AND:
return performANDCombine(N, DAG, DCI, Subtarget);
case ISD::OR:
@@ -7375,6 +7645,8 @@ SDValue LoongArchTargetLowering::PerformDAGCombine(SDNode *N,
return performVANDNCombine(N, DAG, DCI, Subtarget);
case ISD::CONCAT_VECTORS:
return performCONCAT_VECTORSCombine(N, DAG, DCI, Subtarget);
+ case ISD::VSELECT:
+ return performVSELECTCombine(N, DAG, DCI, Subtarget);
case LoongArchISD::VPACKEV:
if (SDValue Result =
combineFP_ROUND(SDValue(N, 0), SDLoc(N), DAG, Subtarget))
diff --git a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
index b807b5927585b..133226e474f62 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLASXInstrInfo.td
@@ -1469,11 +1469,19 @@ defm : PatShiftXrXr<srl, "XVSRL">;
defm : PatShiftXrSplatUimm<srl, "XVSRLI">;
defm : PatShiftXrUimm<loongarch_vsrli, "XVSRLI">;
+// XVSRLR[I]_{B/H/W/D}
+defm : PatXrXr<loongarch_vsrlr, "XVSRLR">;
+defm : PatShiftXrSplatUimm<loongarch_vsrlr, "XVSRLRI">;
+
// XVSRA[I]_{B/H/W/D}
defm : PatXrXr<sra, "XVSRA">;
defm : PatShiftXrXr<sra, "XVSRA">;
defm : PatShiftXrSplatUimm<sra, "XVSRAI">;
+// XVSRAR[I]_{B/H/W/D}
+defm : PatXrXr<loongarch_vsrar, "XVSRAR">;
+defm : PatShiftXrSplatUimm<loongarch_vsrar, "XVSRARI">;
+
// XVROTR[I]_{B/H/W/D}
defm : PatXrXr<rotr, "XVROTR">;
defm : PatShiftXrXr<rotr, "XVROTR">;
diff --git a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
index 92d3214363f7b..b7539730e7524 100644
--- a/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchLSXInstrInfo.td
@@ -98,6 +98,10 @@ def loongarch_vmsknez: SDNode<"LoongArchISD::VMSKNEZ", SDT_LoongArchVMSKCOND>;
def loongarch_vfcvt_s_d: SDNode<"LoongArchISD::VFCVT", SDT_LoongArchVFCVT_S_D>;
+// Vector rounded shift
+def loongarch_vsrlr: SDNode<"LoongArchISD::VSRLR", SDT_LoongArchV2R>;
+def loongarch_vsrar: SDNode<"LoongArchISD::VSRAR", SDT_LoongArchV2R>;
+
def immZExt1 : ImmLeaf<GRLenVT, [{return isUInt<1>(Imm);}]>;
def immZExt2 : ImmLeaf<GRLenVT, [{return isUInt<2>(Imm);}]>;
def immZExt3 : ImmLeaf<GRLenVT, [{return isUInt<3>(Imm);}]>;
@@ -1690,11 +1694,19 @@ defm : PatShiftVrVr<srl, "VSRL">;
defm : PatShiftVrSplatUimm<srl, "VSRLI">;
defm : PatShiftVrUimm<loongarch_vsrli, "VSRLI">;
+// VSRLR[I]_{B/H/W/D}
+defm : PatVrVr<loongarch_vsrlr, "VSRLR">;
+defm : PatShiftVrSplatUimm<loongarch_vsrlr, "VSRLRI">;
+
// VSRA[I]_{B/H/W/D}
defm : PatVrVr<sra, "VSRA">;
defm : PatShiftVrVr<sra, "VSRA">;
defm : PatShiftVrSplatUimm<sra, "VSRAI">;
+// VSRAR[I]_{B/H/W/D}
+defm : PatVrVr<loongarch_vsrar, "VSRAR">;
+defm : PatShiftVrSplatUimm<loongarch_vsrar, "VSRARI">;
+
// VROTR[I]_{B/H/W/D}
defm : PatVrVr<rotr, "VROTR">;
defm : PatShiftVrVr<rotr, "VROTR">;
diff --git a/llvm/test/CodeGen/LoongArch/lasx/srar.ll b/llvm/test/CodeGen/LoongArch/lasx/srar.ll
index 289b2296a3d88..4fb641020e74c 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/srar.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/srar.ll
@@ -5,13 +5,7 @@
define <32 x i8> @srar_b(<32 x i8> %a, <32 x i8> %b) nounwind {
; CHECK-LABEL: srar_b:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsra.b $xr2, $xr0, $xr1
-; CHECK-NEXT: xvsubi.bu $xr3, $xr1, 1
-; CHECK-NEXT: xvsrl.b $xr3, $xr0, $xr3
-; CHECK-NEXT: xvandi.b $xr3, $xr3, 1
-; CHECK-NEXT: xvadd.b $xr2, $xr3, $xr2
-; CHECK-NEXT: xvseqi.b $xr1, $xr1, 0
-; CHECK-NEXT: xvbitsel.v $xr0, $xr2, $xr0, $xr1
+; CHECK-NEXT: xvsrar.b $xr0, $xr0, $xr1
; CHECK-NEXT: ret
entry:
%0 = ashr <32 x i8> %a, %b
@@ -27,14 +21,7 @@ entry:
define <16 x i16> @srar_h(<16 x i16> %a, <16 x i16> %b) nounwind {
; CHECK-LABEL: srar_h:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsra.h $xr2, $xr0, $xr1
-; CHECK-NEXT: xvsubi.hu $xr3, $xr1, 1
-; CHECK-NEXT: xvsrl.h $xr3, $xr0, $xr3
-; CHECK-NEXT: xvrepli.h $xr4, 1
-; CHECK-NEXT: xvand.v $xr3, $xr3, $xr4
-; CHECK-NEXT: xvadd.h $xr2, $xr3, $xr2
-; CHECK-NEXT: xvseqi.h $xr1, $xr1, 0
-; CHECK-NEXT: xvbitsel.v $xr0, $xr2, $xr0, $xr1
+; CHECK-NEXT: xvsrar.h $xr0, $xr0, $xr1
; CHECK-NEXT: ret
entry:
%0 = ashr <16 x i16> %a, %b
@@ -50,14 +37,7 @@ entry:
define <8 x i32> @srar_w(<8 x i32> %a, <8 x i32> %b) nounwind {
; CHECK-LABEL: srar_w:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsra.w $xr2, $xr0, $xr1
-; CHECK-NEXT: xvsubi.wu $xr3, $xr1, 1
-; CHECK-NEXT: xvsrl.w $xr3, $xr0, $xr3
-; CHECK-NEXT: xvrepli.w $xr4, 1
-; CHECK-NEXT: xvand.v $xr3, $xr3, $xr4
-; CHECK-NEXT: xvadd.w $xr2, $xr3, $xr2
-; CHECK-NEXT: xvseqi.w $xr1, $xr1, 0
-; CHECK-NEXT: xvbitsel.v $xr0, $xr2, $xr0, $xr1
+; CHECK-NEXT: xvsrar.w $xr0, $xr0, $xr1
; CHECK-NEXT: ret
entry:
%0 = ashr <8 x i32> %a, %b
@@ -73,14 +53,7 @@ entry:
define <4 x i64> @srar_d(<4 x i64> %a, <4 x i64> %b) nounwind {
; CHECK-LABEL: srar_d:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsra.d $xr2, $xr0, $xr1
-; CHECK-NEXT: xvsubi.du $xr3, $xr1, 1
-; CHECK-NEXT: xvsrl.d $xr3, $xr0, $xr3
-; CHECK-NEXT: xvrepli.d $xr4, 1
-; CHECK-NEXT: xvand.v $xr3, $xr3, $xr4
-; CHECK-NEXT: xvadd.d $xr2, $xr3, $xr2
-; CHECK-NEXT: xvseqi.d $xr1, $xr1, 0
-; CHECK-NEXT: xvbitsel.v $xr0, $xr2, $xr0, $xr1
+; CHECK-NEXT: xvsrar.d $xr0, $xr0, $xr1
; CHECK-NEXT: ret
entry:
%0 = ashr <4 x i64> %a, %b
@@ -96,9 +69,7 @@ entry:
define <32 x i8> @srar_b_1(<32 x i8> %a) nounwind {
; CHECK-LABEL: srar_b_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrai.b $xr1, $xr0, 1
-; CHECK-NEXT: xvandi.b $xr0, $xr0, 1
-; CHECK-NEXT: xvadd.b $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrari.b $xr0, $xr0, 1
; CHECK-NEXT: ret
entry:
%0 = ashr <32 x i8> %a, splat (i8 1)
@@ -110,10 +81,7 @@ entry:
define <32 x i8> @srar_b_7(<32 x i8> %a) nounwind {
; CHECK-LABEL: srar_b_7:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrai.b $xr1, $xr0, 7
-; CHECK-NEXT: xvsrli.b $xr0, $xr0, 6
-; CHECK-NEXT: xvandi.b $xr0, $xr0, 1
-; CHECK-NEXT: xvadd.b $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrari.b $xr0, $xr0, 7
; CHECK-NEXT: ret
entry:
%0 = ashr <32 x i8> %a, splat (i8 7)
@@ -126,10 +94,7 @@ entry:
define <16 x i16> @srar_h_1(<16 x i16> %a) nounwind {
; CHECK-LABEL: srar_h_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrai.h $xr1, $xr0, 1
-; CHECK-NEXT: xvrepli.h $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.h $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrari.h $xr0, $xr0, 1
; CHECK-NEXT: ret
entry:
%0 = ashr <16 x i16> %a, splat (i16 1)
@@ -141,11 +106,7 @@ entry:
define <16 x i16> @srar_h_15(<16 x i16> %a) nounwind {
; CHECK-LABEL: srar_h_15:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrai.h $xr1, $xr0, 15
-; CHECK-NEXT: xvsrli.h $xr0, $xr0, 14
-; CHECK-NEXT: xvrepli.h $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.h $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrari.h $xr0, $xr0, 15
; CHECK-NEXT: ret
entry:
%0 = ashr <16 x i16> %a, splat (i16 15)
@@ -158,10 +119,7 @@ entry:
define <8 x i32> @srar_w_1(<8 x i32> %a) nounwind {
; CHECK-LABEL: srar_w_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrai.w $xr1, $xr0, 1
-; CHECK-NEXT: xvrepli.w $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.w $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrari.w $xr0, $xr0, 1
; CHECK-NEXT: ret
entry:
%0 = ashr <8 x i32> %a, splat (i32 1)
@@ -173,11 +131,7 @@ entry:
define <8 x i32> @srar_w_31(<8 x i32> %a) nounwind {
; CHECK-LABEL: srar_w_31:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrai.w $xr1, $xr0, 31
-; CHECK-NEXT: xvsrli.w $xr0, $xr0, 30
-; CHECK-NEXT: xvrepli.w $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.w $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrari.w $xr0, $xr0, 31
; CHECK-NEXT: ret
entry:
%0 = ashr <8 x i32> %a, splat (i32 31)
@@ -190,10 +144,7 @@ entry:
define <4 x i64> @srar_d_1(<4 x i64> %a) nounwind {
; CHECK-LABEL: srar_d_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrai.d $xr1, $xr0, 1
-; CHECK-NEXT: xvrepli.d $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrari.d $xr0, $xr0, 1
; CHECK-NEXT: ret
entry:
%0 = ashr <4 x i64> %a, splat (i64 1)
@@ -205,11 +156,7 @@ entry:
define <4 x i64> @srar_d_63(<4 x i64> %a) nounwind {
; CHECK-LABEL: srar_d_63:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrai.d $xr1, $xr0, 63
-; CHECK-NEXT: xvsrli.d $xr0, $xr0, 62
-; CHECK-NEXT: xvrepli.d $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrari.d $xr0, $xr0, 63
; CHECK-NEXT: ret
entry:
%0 = ashr <4 x i64> %a, splat (i64 63)
diff --git a/llvm/test/CodeGen/LoongArch/lasx/srlr.ll b/llvm/test/CodeGen/LoongArch/lasx/srlr.ll
index 3087ceb928451..cadbf154201d5 100644
--- a/llvm/test/CodeGen/LoongArch/lasx/srlr.ll
+++ b/llvm/test/CodeGen/LoongArch/lasx/srlr.ll
@@ -5,13 +5,7 @@
define <32 x i8> @srlr_b(<32 x i8> %a, <32 x i8> %b) nounwind {
; CHECK-LABEL: srlr_b:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrl.b $xr2, $xr0, $xr1
-; CHECK-NEXT: xvsubi.bu $xr3, $xr1, 1
-; CHECK-NEXT: xvsrl.b $xr3, $xr0, $xr3
-; CHECK-NEXT: xvandi.b $xr3, $xr3, 1
-; CHECK-NEXT: xvadd.b $xr2, $xr3, $xr2
-; CHECK-NEXT: xvseqi.b $xr1, $xr1, 0
-; CHECK-NEXT: xvbitsel.v $xr0, $xr2, $xr0, $xr1
+; CHECK-NEXT: xvsrlr.b $xr0, $xr0, $xr1
; CHECK-NEXT: ret
entry:
%0 = lshr <32 x i8> %a, %b
@@ -27,14 +21,7 @@ entry:
define <16 x i16> @srlr_h(<16 x i16> %a, <16 x i16> %b) nounwind {
; CHECK-LABEL: srlr_h:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrl.h $xr2, $xr0, $xr1
-; CHECK-NEXT: xvsubi.hu $xr3, $xr1, 1
-; CHECK-NEXT: xvsrl.h $xr3, $xr0, $xr3
-; CHECK-NEXT: xvrepli.h $xr4, 1
-; CHECK-NEXT: xvand.v $xr3, $xr3, $xr4
-; CHECK-NEXT: xvadd.h $xr2, $xr3, $xr2
-; CHECK-NEXT: xvseqi.h $xr1, $xr1, 0
-; CHECK-NEXT: xvbitsel.v $xr0, $xr2, $xr0, $xr1
+; CHECK-NEXT: xvsrlr.h $xr0, $xr0, $xr1
; CHECK-NEXT: ret
entry:
%0 = lshr <16 x i16> %a, %b
@@ -50,14 +37,7 @@ entry:
define <8 x i32> @srlr_w(<8 x i32> %a, <8 x i32> %b) nounwind {
; CHECK-LABEL: srlr_w:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrl.w $xr2, $xr0, $xr1
-; CHECK-NEXT: xvsubi.wu $xr3, $xr1, 1
-; CHECK-NEXT: xvsrl.w $xr3, $xr0, $xr3
-; CHECK-NEXT: xvrepli.w $xr4, 1
-; CHECK-NEXT: xvand.v $xr3, $xr3, $xr4
-; CHECK-NEXT: xvadd.w $xr2, $xr3, $xr2
-; CHECK-NEXT: xvseqi.w $xr1, $xr1, 0
-; CHECK-NEXT: xvbitsel.v $xr0, $xr2, $xr0, $xr1
+; CHECK-NEXT: xvsrlr.w $xr0, $xr0, $xr1
; CHECK-NEXT: ret
entry:
%0 = lshr <8 x i32> %a, %b
@@ -73,14 +53,7 @@ entry:
define <4 x i64> @srlr_d(<4 x i64> %a, <4 x i64> %b) nounwind {
; CHECK-LABEL: srlr_d:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrl.d $xr2, $xr0, $xr1
-; CHECK-NEXT: xvsubi.du $xr3, $xr1, 1
-; CHECK-NEXT: xvsrl.d $xr3, $xr0, $xr3
-; CHECK-NEXT: xvrepli.d $xr4, 1
-; CHECK-NEXT: xvand.v $xr3, $xr3, $xr4
-; CHECK-NEXT: xvadd.d $xr2, $xr3, $xr2
-; CHECK-NEXT: xvseqi.d $xr1, $xr1, 0
-; CHECK-NEXT: xvbitsel.v $xr0, $xr2, $xr0, $xr1
+; CHECK-NEXT: xvsrlr.d $xr0, $xr0, $xr1
; CHECK-NEXT: ret
entry:
%0 = lshr <4 x i64> %a, %b
@@ -96,9 +69,7 @@ entry:
define <32 x i8> @srlr_b_1(<32 x i8> %a) nounwind {
; CHECK-LABEL: srlr_b_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrli.b $xr1, $xr0, 1
-; CHECK-NEXT: xvandi.b $xr0, $xr0, 1
-; CHECK-NEXT: xvadd.b $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrlri.b $xr0, $xr0, 1
; CHECK-NEXT: ret
entry:
%0 = lshr <32 x i8> %a, splat (i8 1)
@@ -110,10 +81,7 @@ entry:
define <32 x i8> @srlr_b_7(<32 x i8> %a) nounwind {
; CHECK-LABEL: srlr_b_7:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrli.b $xr1, $xr0, 7
-; CHECK-NEXT: xvsrli.b $xr0, $xr0, 6
-; CHECK-NEXT: xvandi.b $xr0, $xr0, 1
-; CHECK-NEXT: xvadd.b $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrlri.b $xr0, $xr0, 7
; CHECK-NEXT: ret
entry:
%0 = lshr <32 x i8> %a, splat (i8 7)
@@ -126,10 +94,7 @@ entry:
define <16 x i16> @srlr_h_1(<16 x i16> %a) nounwind {
; CHECK-LABEL: srlr_h_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrli.h $xr1, $xr0, 1
-; CHECK-NEXT: xvrepli.h $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.h $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrlri.h $xr0, $xr0, 1
; CHECK-NEXT: ret
entry:
%0 = lshr <16 x i16> %a, splat (i16 1)
@@ -141,11 +106,7 @@ entry:
define <16 x i16> @srlr_h_15(<16 x i16> %a) nounwind {
; CHECK-LABEL: srlr_h_15:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrli.h $xr1, $xr0, 15
-; CHECK-NEXT: xvsrli.h $xr0, $xr0, 14
-; CHECK-NEXT: xvrepli.h $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.h $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrlri.h $xr0, $xr0, 15
; CHECK-NEXT: ret
entry:
%0 = lshr <16 x i16> %a, splat (i16 15)
@@ -158,10 +119,7 @@ entry:
define <8 x i32> @srlr_w_1(<8 x i32> %a) nounwind {
; CHECK-LABEL: srlr_w_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrli.w $xr1, $xr0, 1
-; CHECK-NEXT: xvrepli.w $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.w $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrlri.w $xr0, $xr0, 1
; CHECK-NEXT: ret
entry:
%0 = lshr <8 x i32> %a, splat (i32 1)
@@ -173,11 +131,7 @@ entry:
define <8 x i32> @srlr_w_31(<8 x i32> %a) nounwind {
; CHECK-LABEL: srlr_w_31:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrli.w $xr1, $xr0, 31
-; CHECK-NEXT: xvsrli.w $xr0, $xr0, 30
-; CHECK-NEXT: xvrepli.w $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.w $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrlri.w $xr0, $xr0, 31
; CHECK-NEXT: ret
entry:
%0 = lshr <8 x i32> %a, splat (i32 31)
@@ -190,10 +144,7 @@ entry:
define <4 x i64> @srlr_d_1(<4 x i64> %a) nounwind {
; CHECK-LABEL: srlr_d_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrli.d $xr1, $xr0, 1
-; CHECK-NEXT: xvrepli.d $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrlri.d $xr0, $xr0, 1
; CHECK-NEXT: ret
entry:
%0 = lshr <4 x i64> %a, splat (i64 1)
@@ -205,11 +156,7 @@ entry:
define <4 x i64> @srlr_d_63(<4 x i64> %a) nounwind {
; CHECK-LABEL: srlr_d_63:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: xvsrli.d $xr1, $xr0, 63
-; CHECK-NEXT: xvsrli.d $xr0, $xr0, 62
-; CHECK-NEXT: xvrepli.d $xr2, 1
-; CHECK-NEXT: xvand.v $xr0, $xr0, $xr2
-; CHECK-NEXT: xvadd.d $xr0, $xr0, $xr1
+; CHECK-NEXT: xvsrlri.d $xr0, $xr0, 63
; CHECK-NEXT: ret
entry:
%0 = lshr <4 x i64> %a, splat (i64 63)
diff --git a/llvm/test/CodeGen/LoongArch/lsx/srar.ll b/llvm/test/CodeGen/LoongArch/lsx/srar.ll
index a57c8077b0f0b..888b78688b821 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/srar.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/srar.ll
@@ -5,13 +5,7 @@
define <16 x i8> @srar_b(<16 x i8> %a, <16 x i8> %b) nounwind {
; CHECK-LABEL: srar_b:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsra.b $vr2, $vr0, $vr1
-; CHECK-NEXT: vsubi.bu $vr3, $vr1, 1
-; CHECK-NEXT: vsrl.b $vr3, $vr0, $vr3
-; CHECK-NEXT: vandi.b $vr3, $vr3, 1
-; CHECK-NEXT: vadd.b $vr2, $vr3, $vr2
-; CHECK-NEXT: vseqi.b $vr1, $vr1, 0
-; CHECK-NEXT: vbitsel.v $vr0, $vr2, $vr0, $vr1
+; CHECK-NEXT: vsrar.b $vr0, $vr0, $vr1
; CHECK-NEXT: ret
entry:
%0 = ashr <16 x i8> %a, %b
@@ -27,14 +21,7 @@ entry:
define <8 x i16> @srar_h(<8 x i16> %a, <8 x i16> %b) nounwind {
; CHECK-LABEL: srar_h:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsra.h $vr2, $vr0, $vr1
-; CHECK-NEXT: vsubi.hu $vr3, $vr1, 1
-; CHECK-NEXT: vsrl.h $vr3, $vr0, $vr3
-; CHECK-NEXT: vrepli.h $vr4, 1
-; CHECK-NEXT: vand.v $vr3, $vr3, $vr4
-; CHECK-NEXT: vadd.h $vr2, $vr3, $vr2
-; CHECK-NEXT: vseqi.h $vr1, $vr1, 0
-; CHECK-NEXT: vbitsel.v $vr0, $vr2, $vr0, $vr1
+; CHECK-NEXT: vsrar.h $vr0, $vr0, $vr1
; CHECK-NEXT: ret
entry:
%0 = ashr <8 x i16> %a, %b
@@ -50,14 +37,7 @@ entry:
define <4 x i32> @srar_w(<4 x i32> %a, <4 x i32> %b) nounwind {
; CHECK-LABEL: srar_w:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsra.w $vr2, $vr0, $vr1
-; CHECK-NEXT: vsubi.wu $vr3, $vr1, 1
-; CHECK-NEXT: vsrl.w $vr3, $vr0, $vr3
-; CHECK-NEXT: vrepli.w $vr4, 1
-; CHECK-NEXT: vand.v $vr3, $vr3, $vr4
-; CHECK-NEXT: vadd.w $vr2, $vr3, $vr2
-; CHECK-NEXT: vseqi.w $vr1, $vr1, 0
-; CHECK-NEXT: vbitsel.v $vr0, $vr2, $vr0, $vr1
+; CHECK-NEXT: vsrar.w $vr0, $vr0, $vr1
; CHECK-NEXT: ret
entry:
%0 = ashr <4 x i32> %a, %b
@@ -73,14 +53,7 @@ entry:
define <2 x i64> @srar_d(<2 x i64> %a, <2 x i64> %b) nounwind {
; CHECK-LABEL: srar_d:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsra.d $vr2, $vr0, $vr1
-; CHECK-NEXT: vsubi.du $vr3, $vr1, 1
-; CHECK-NEXT: vsrl.d $vr3, $vr0, $vr3
-; CHECK-NEXT: vrepli.d $vr4, 1
-; CHECK-NEXT: vand.v $vr3, $vr3, $vr4
-; CHECK-NEXT: vadd.d $vr2, $vr3, $vr2
-; CHECK-NEXT: vseqi.d $vr1, $vr1, 0
-; CHECK-NEXT: vbitsel.v $vr0, $vr2, $vr0, $vr1
+; CHECK-NEXT: vsrar.d $vr0, $vr0, $vr1
; CHECK-NEXT: ret
entry:
%0 = ashr <2 x i64> %a, %b
@@ -96,9 +69,7 @@ entry:
define <16 x i8> @srar_b_1(<16 x i8> %a) nounwind {
; CHECK-LABEL: srar_b_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrai.b $vr1, $vr0, 1
-; CHECK-NEXT: vandi.b $vr0, $vr0, 1
-; CHECK-NEXT: vadd.b $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrari.b $vr0, $vr0, 1
; CHECK-NEXT: ret
entry:
%0 = ashr <16 x i8> %a, splat (i8 1)
@@ -110,10 +81,7 @@ entry:
define <16 x i8> @srar_b_7(<16 x i8> %a) nounwind {
; CHECK-LABEL: srar_b_7:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrai.b $vr1, $vr0, 7
-; CHECK-NEXT: vsrli.b $vr0, $vr0, 6
-; CHECK-NEXT: vandi.b $vr0, $vr0, 1
-; CHECK-NEXT: vadd.b $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrari.b $vr0, $vr0, 7
; CHECK-NEXT: ret
entry:
%0 = ashr <16 x i8> %a, splat (i8 7)
@@ -126,10 +94,7 @@ entry:
define <8 x i16> @srar_h_1(<8 x i16> %a) nounwind {
; CHECK-LABEL: srar_h_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrai.h $vr1, $vr0, 1
-; CHECK-NEXT: vrepli.h $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.h $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrari.h $vr0, $vr0, 1
; CHECK-NEXT: ret
entry:
%0 = ashr <8 x i16> %a, splat (i16 1)
@@ -141,11 +106,7 @@ entry:
define <8 x i16> @srar_h_15(<8 x i16> %a) nounwind {
; CHECK-LABEL: srar_h_15:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrai.h $vr1, $vr0, 15
-; CHECK-NEXT: vsrli.h $vr0, $vr0, 14
-; CHECK-NEXT: vrepli.h $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.h $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrari.h $vr0, $vr0, 15
; CHECK-NEXT: ret
entry:
%0 = ashr <8 x i16> %a, splat (i16 15)
@@ -158,10 +119,7 @@ entry:
define <4 x i32> @srar_w_1(<4 x i32> %a) nounwind {
; CHECK-LABEL: srar_w_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrai.w $vr1, $vr0, 1
-; CHECK-NEXT: vrepli.w $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.w $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrari.w $vr0, $vr0, 1
; CHECK-NEXT: ret
entry:
%0 = ashr <4 x i32> %a, splat (i32 1)
@@ -173,11 +131,7 @@ entry:
define <4 x i32> @srar_w_31(<4 x i32> %a) nounwind {
; CHECK-LABEL: srar_w_31:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrai.w $vr1, $vr0, 31
-; CHECK-NEXT: vsrli.w $vr0, $vr0, 30
-; CHECK-NEXT: vrepli.w $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.w $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrari.w $vr0, $vr0, 31
; CHECK-NEXT: ret
entry:
%0 = ashr <4 x i32> %a, splat (i32 31)
@@ -190,10 +144,7 @@ entry:
define <2 x i64> @srar_d_1(<2 x i64> %a) nounwind {
; CHECK-LABEL: srar_d_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrai.d $vr1, $vr0, 1
-; CHECK-NEXT: vrepli.d $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrari.d $vr0, $vr0, 1
; CHECK-NEXT: ret
entry:
%0 = ashr <2 x i64> %a, splat (i64 1)
@@ -205,11 +156,7 @@ entry:
define <2 x i64> @srar_d_63(<2 x i64> %a) nounwind {
; CHECK-LABEL: srar_d_63:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrai.d $vr1, $vr0, 63
-; CHECK-NEXT: vsrli.d $vr0, $vr0, 62
-; CHECK-NEXT: vrepli.d $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrari.d $vr0, $vr0, 63
; CHECK-NEXT: ret
entry:
%0 = ashr <2 x i64> %a, splat (i64 63)
diff --git a/llvm/test/CodeGen/LoongArch/lsx/srlr.ll b/llvm/test/CodeGen/LoongArch/lsx/srlr.ll
index 42f1b8f2d9d9a..55e14199a83f0 100644
--- a/llvm/test/CodeGen/LoongArch/lsx/srlr.ll
+++ b/llvm/test/CodeGen/LoongArch/lsx/srlr.ll
@@ -5,13 +5,7 @@
define <16 x i8> @srlr_b(<16 x i8> %a, <16 x i8> %b) nounwind {
; CHECK-LABEL: srlr_b:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrl.b $vr2, $vr0, $vr1
-; CHECK-NEXT: vsubi.bu $vr3, $vr1, 1
-; CHECK-NEXT: vsrl.b $vr3, $vr0, $vr3
-; CHECK-NEXT: vandi.b $vr3, $vr3, 1
-; CHECK-NEXT: vadd.b $vr2, $vr3, $vr2
-; CHECK-NEXT: vseqi.b $vr1, $vr1, 0
-; CHECK-NEXT: vbitsel.v $vr0, $vr2, $vr0, $vr1
+; CHECK-NEXT: vsrlr.b $vr0, $vr0, $vr1
; CHECK-NEXT: ret
entry:
%0 = lshr <16 x i8> %a, %b
@@ -27,14 +21,7 @@ entry:
define <8 x i16> @srlr_h(<8 x i16> %a, <8 x i16> %b) nounwind {
; CHECK-LABEL: srlr_h:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrl.h $vr2, $vr0, $vr1
-; CHECK-NEXT: vsubi.hu $vr3, $vr1, 1
-; CHECK-NEXT: vsrl.h $vr3, $vr0, $vr3
-; CHECK-NEXT: vrepli.h $vr4, 1
-; CHECK-NEXT: vand.v $vr3, $vr3, $vr4
-; CHECK-NEXT: vadd.h $vr2, $vr3, $vr2
-; CHECK-NEXT: vseqi.h $vr1, $vr1, 0
-; CHECK-NEXT: vbitsel.v $vr0, $vr2, $vr0, $vr1
+; CHECK-NEXT: vsrlr.h $vr0, $vr0, $vr1
; CHECK-NEXT: ret
entry:
%0 = lshr <8 x i16> %a, %b
@@ -50,14 +37,7 @@ entry:
define <4 x i32> @srlr_w(<4 x i32> %a, <4 x i32> %b) nounwind {
; CHECK-LABEL: srlr_w:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrl.w $vr2, $vr0, $vr1
-; CHECK-NEXT: vsubi.wu $vr3, $vr1, 1
-; CHECK-NEXT: vsrl.w $vr3, $vr0, $vr3
-; CHECK-NEXT: vrepli.w $vr4, 1
-; CHECK-NEXT: vand.v $vr3, $vr3, $vr4
-; CHECK-NEXT: vadd.w $vr2, $vr3, $vr2
-; CHECK-NEXT: vseqi.w $vr1, $vr1, 0
-; CHECK-NEXT: vbitsel.v $vr0, $vr2, $vr0, $vr1
+; CHECK-NEXT: vsrlr.w $vr0, $vr0, $vr1
; CHECK-NEXT: ret
entry:
%0 = lshr <4 x i32> %a, %b
@@ -73,14 +53,7 @@ entry:
define <2 x i64> @srlr_d(<2 x i64> %a, <2 x i64> %b) nounwind {
; CHECK-LABEL: srlr_d:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrl.d $vr2, $vr0, $vr1
-; CHECK-NEXT: vsubi.du $vr3, $vr1, 1
-; CHECK-NEXT: vsrl.d $vr3, $vr0, $vr3
-; CHECK-NEXT: vrepli.d $vr4, 1
-; CHECK-NEXT: vand.v $vr3, $vr3, $vr4
-; CHECK-NEXT: vadd.d $vr2, $vr3, $vr2
-; CHECK-NEXT: vseqi.d $vr1, $vr1, 0
-; CHECK-NEXT: vbitsel.v $vr0, $vr2, $vr0, $vr1
+; CHECK-NEXT: vsrlr.d $vr0, $vr0, $vr1
; CHECK-NEXT: ret
entry:
%0 = lshr <2 x i64> %a, %b
@@ -96,9 +69,7 @@ entry:
define <16 x i8> @srlr_b_1(<16 x i8> %a) nounwind {
; CHECK-LABEL: srlr_b_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrli.b $vr1, $vr0, 1
-; CHECK-NEXT: vandi.b $vr0, $vr0, 1
-; CHECK-NEXT: vadd.b $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrlri.b $vr0, $vr0, 1
; CHECK-NEXT: ret
entry:
%0 = lshr <16 x i8> %a, splat (i8 1)
@@ -110,10 +81,7 @@ entry:
define <16 x i8> @srlr_b_7(<16 x i8> %a) nounwind {
; CHECK-LABEL: srlr_b_7:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrli.b $vr1, $vr0, 7
-; CHECK-NEXT: vsrli.b $vr0, $vr0, 6
-; CHECK-NEXT: vandi.b $vr0, $vr0, 1
-; CHECK-NEXT: vadd.b $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrlri.b $vr0, $vr0, 7
; CHECK-NEXT: ret
entry:
%0 = lshr <16 x i8> %a, splat (i8 7)
@@ -126,10 +94,7 @@ entry:
define <8 x i16> @srlr_h_1(<8 x i16> %a) nounwind {
; CHECK-LABEL: srlr_h_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrli.h $vr1, $vr0, 1
-; CHECK-NEXT: vrepli.h $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.h $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrlri.h $vr0, $vr0, 1
; CHECK-NEXT: ret
entry:
%0 = lshr <8 x i16> %a, splat (i16 1)
@@ -141,11 +106,7 @@ entry:
define <8 x i16> @srlr_h_15(<8 x i16> %a) nounwind {
; CHECK-LABEL: srlr_h_15:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrli.h $vr1, $vr0, 15
-; CHECK-NEXT: vsrli.h $vr0, $vr0, 14
-; CHECK-NEXT: vrepli.h $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.h $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrlri.h $vr0, $vr0, 15
; CHECK-NEXT: ret
entry:
%0 = lshr <8 x i16> %a, splat (i16 15)
@@ -158,10 +119,7 @@ entry:
define <4 x i32> @srlr_w_1(<4 x i32> %a) nounwind {
; CHECK-LABEL: srlr_w_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrli.w $vr1, $vr0, 1
-; CHECK-NEXT: vrepli.w $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.w $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrlri.w $vr0, $vr0, 1
; CHECK-NEXT: ret
entry:
%0 = lshr <4 x i32> %a, splat (i32 1)
@@ -173,11 +131,7 @@ entry:
define <4 x i32> @srlr_w_31(<4 x i32> %a) nounwind {
; CHECK-LABEL: srlr_w_31:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrli.w $vr1, $vr0, 31
-; CHECK-NEXT: vsrli.w $vr0, $vr0, 30
-; CHECK-NEXT: vrepli.w $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.w $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrlri.w $vr0, $vr0, 31
; CHECK-NEXT: ret
entry:
%0 = lshr <4 x i32> %a, splat (i32 31)
@@ -190,10 +144,7 @@ entry:
define <2 x i64> @srlr_d_1(<2 x i64> %a) nounwind {
; CHECK-LABEL: srlr_d_1:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrli.d $vr1, $vr0, 1
-; CHECK-NEXT: vrepli.d $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrlri.d $vr0, $vr0, 1
; CHECK-NEXT: ret
entry:
%0 = lshr <2 x i64> %a, splat (i64 1)
@@ -205,11 +156,7 @@ entry:
define <2 x i64> @srlr_d_63(<2 x i64> %a) nounwind {
; CHECK-LABEL: srlr_d_63:
; CHECK: # %bb.0: # %entry
-; CHECK-NEXT: vsrli.d $vr1, $vr0, 63
-; CHECK-NEXT: vsrli.d $vr0, $vr0, 62
-; CHECK-NEXT: vrepli.d $vr2, 1
-; CHECK-NEXT: vand.v $vr0, $vr0, $vr2
-; CHECK-NEXT: vadd.d $vr0, $vr0, $vr1
+; CHECK-NEXT: vsrlri.d $vr0, $vr0, 63
; CHECK-NEXT: ret
entry:
%0 = lshr <2 x i64> %a, splat (i64 63)
>From 676987687a1c1fdf562c5043496debb60e9e5134 Mon Sep 17 00:00:00 2001
From: WANG Rui <wangrui at loongson.cn>
Date: Fri, 24 Apr 2026 16:21:57 +0800
Subject: [PATCH 2/2] Address wanglei's comments
---
llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
index 71edc58ff7640..2f30b3aebbaac 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
@@ -5443,9 +5443,7 @@ static SDValue combineAndNotIntoVANDN(SDNode *N, const SDLoc &DL,
static bool isConstantSplatVector(SDValue N, APInt &SplatValue,
unsigned MinSizeInBits) {
- if (N->getOpcode() == ISD::BITCAST)
- N = N->getOperand(0);
-
+ N = peekThroughBitcasts(N);
BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N);
if (!Node)
@@ -7564,9 +7562,7 @@ static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG,
if (Srl.getOpcode() != ISD::SRL)
return SDValue();
- if (One.getOpcode() == ISD::BITCAST)
- One = One.getOperand(0);
-
+ One = peekThroughBitcasts(One);
if (!isConstantSplatVector(One, SplatVal, EltVT.getSizeInBits()))
return SDValue();
More information about the llvm-branch-commits
mailing list