[llvm] a6f8af6 - [RISCV] Improve vmsge and vmsgeu selection (#115435)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 12 23:05:13 PST 2024
Author: Jianjian Guan
Date: 2024-11-13T15:05:08+08:00
New Revision: a6f8af676a36bd43dd0c7f6229e6c91161a56819
URL: https://github.com/llvm/llvm-project/commit/a6f8af676a36bd43dd0c7f6229e6c91161a56819
DIFF: https://github.com/llvm/llvm-project/commit/a6f8af676a36bd43dd0c7f6229e6c91161a56819.diff
LOG: [RISCV] Improve vmsge and vmsgeu selection (#115435)
Select vmsge(u) vs, C to vmsgt(u) vs, C-1 if C is not in the imm range
and not the minimum value.
Fix https://github.com/llvm/llvm-project/issues/114505.
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
llvm/test/CodeGen/RISCV/rvv/vmsge.ll
llvm/test/CodeGen/RISCV/rvv/vmsgeu.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 95bca928a10e95..a1b74faf17fab3 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1615,21 +1615,28 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
SDValue Src1 = Node->getOperand(1);
SDValue Src2 = Node->getOperand(2);
bool IsUnsigned = IntNo == Intrinsic::riscv_vmsgeu;
- bool IsCmpUnsignedZero = false;
+ bool IsCmpConstant = false;
+ bool IsCmpMinimum = false;
// Only custom select scalar second operand.
if (Src2.getValueType() != XLenVT)
break;
// Small constants are handled with patterns.
+ int64_t CVal = 0;
+ MVT Src1VT = Src1.getSimpleValueType();
if (auto *C = dyn_cast<ConstantSDNode>(Src2)) {
- int64_t CVal = C->getSExtValue();
+ IsCmpConstant = true;
+ CVal = C->getSExtValue();
if (CVal >= -15 && CVal <= 16) {
if (!IsUnsigned || CVal != 0)
break;
- IsCmpUnsignedZero = true;
+ IsCmpMinimum = true;
+ } else if (!IsUnsigned && CVal == APInt::getSignedMinValue(
+ Src1VT.getScalarSizeInBits())
+ .getSExtValue()) {
+ IsCmpMinimum = true;
}
}
- MVT Src1VT = Src1.getSimpleValueType();
- unsigned VMSLTOpcode, VMNANDOpcode, VMSetOpcode;
+ unsigned VMSLTOpcode, VMNANDOpcode, VMSetOpcode, VMSGTOpcode;
switch (RISCVTargetLowering::getLMUL(Src1VT)) {
default:
llvm_unreachable("Unexpected LMUL!");
@@ -1637,6 +1644,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
case RISCVII::VLMUL::lmulenum: \
VMSLTOpcode = IsUnsigned ? RISCV::PseudoVMSLTU_VX_##suffix \
: RISCV::PseudoVMSLT_VX_##suffix; \
+ VMSGTOpcode = IsUnsigned ? RISCV::PseudoVMSGTU_VX_##suffix \
+ : RISCV::PseudoVMSGT_VX_##suffix; \
VMNANDOpcode = RISCV::PseudoVMNAND_MM_##suffix; \
VMSetOpcode = RISCV::PseudoVMSET_M_##suffix_b; \
break;
@@ -1654,12 +1663,21 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
SDValue VL;
selectVLOp(Node->getOperand(3), VL);
- // If vmsgeu with 0 immediate, expand it to vmset.
- if (IsCmpUnsignedZero) {
+ // If vmsge(u) with minimum value, expand it to vmset.
+ if (IsCmpMinimum) {
ReplaceNode(Node, CurDAG->getMachineNode(VMSetOpcode, DL, VT, VL, SEW));
return;
}
+ if (IsCmpConstant) {
+ SDValue Imm =
+ selectImm(CurDAG, SDLoc(Src2), XLenVT, CVal - 1, *Subtarget);
+
+ ReplaceNode(Node, CurDAG->getMachineNode(VMSGTOpcode, DL, VT,
+ {Src1, Imm, VL, SEW}));
+ return;
+ }
+
// Expand to
// vmslt{u}.vx vd, va, x; vmnand.mm vd, vd, vd
SDValue Cmp = SDValue(
@@ -1674,22 +1692,29 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
SDValue Src1 = Node->getOperand(2);
SDValue Src2 = Node->getOperand(3);
bool IsUnsigned = IntNo == Intrinsic::riscv_vmsgeu_mask;
- bool IsCmpUnsignedZero = false;
+ bool IsCmpConstant = false;
+ bool IsCmpMinimum = false;
// Only custom select scalar second operand.
if (Src2.getValueType() != XLenVT)
break;
// Small constants are handled with patterns.
+ MVT Src1VT = Src1.getSimpleValueType();
+ int64_t CVal = 0;
if (auto *C = dyn_cast<ConstantSDNode>(Src2)) {
- int64_t CVal = C->getSExtValue();
+ IsCmpConstant = true;
+ CVal = C->getSExtValue();
if (CVal >= -15 && CVal <= 16) {
if (!IsUnsigned || CVal != 0)
break;
- IsCmpUnsignedZero = true;
+ IsCmpMinimum = true;
+ } else if (!IsUnsigned && CVal == APInt::getSignedMinValue(
+ Src1VT.getScalarSizeInBits())
+ .getSExtValue()) {
+ IsCmpMinimum = true;
}
}
- MVT Src1VT = Src1.getSimpleValueType();
unsigned VMSLTOpcode, VMSLTMaskOpcode, VMXOROpcode, VMANDNOpcode,
- VMOROpcode;
+ VMOROpcode, VMSGTMaskOpcode;
switch (RISCVTargetLowering::getLMUL(Src1VT)) {
default:
llvm_unreachable("Unexpected LMUL!");
@@ -1699,6 +1724,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
: RISCV::PseudoVMSLT_VX_##suffix; \
VMSLTMaskOpcode = IsUnsigned ? RISCV::PseudoVMSLTU_VX_##suffix##_MASK \
: RISCV::PseudoVMSLT_VX_##suffix##_MASK; \
+ VMSGTMaskOpcode = IsUnsigned ? RISCV::PseudoVMSGTU_VX_##suffix##_MASK \
+ : RISCV::PseudoVMSGT_VX_##suffix##_MASK; \
break;
CASE_VMSLT_OPCODES(LMUL_F8, MF8, B1)
CASE_VMSLT_OPCODES(LMUL_F4, MF4, B2)
@@ -1736,8 +1763,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
SDValue MaskedOff = Node->getOperand(1);
SDValue Mask = Node->getOperand(4);
- // If vmsgeu_mask with 0 immediate, expand it to vmor mask, maskedoff.
- if (IsCmpUnsignedZero) {
+ // If vmsge(u) with minimum value, expand it to vmor mask, maskedoff.
+ if (IsCmpMinimum) {
// We don't need vmor if the MaskedOff and the Mask are the same
// value.
if (Mask == MaskedOff) {
@@ -1768,6 +1795,16 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
SDValue Glue = Chain.getValue(1);
SDValue V0 = CurDAG->getRegister(RISCV::V0, VT);
+ if (IsCmpConstant) {
+ SDValue Imm =
+ selectImm(CurDAG, SDLoc(Src2), XLenVT, CVal - 1, *Subtarget);
+
+ ReplaceNode(Node, CurDAG->getMachineNode(
+ VMSGTMaskOpcode, DL, VT,
+ {MaskedOff, Src1, Imm, V0, VL, SEW, Glue}));
+ return;
+ }
+
// Otherwise use
// vmslt{u}.vx vd, va, x, v0.t; vmxor.mm vd, vd, v0
// The result is mask undisturbed.
diff --git a/llvm/test/CodeGen/RISCV/rvv/vmsge.ll b/llvm/test/CodeGen/RISCV/rvv/vmsge.ll
index 1ec304609699a6..e6d775dee5b22b 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vmsge.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vmsge.ll
@@ -1084,6 +1084,45 @@ entry:
ret <vscale x 4 x i1> %a
}
+define <vscale x 4 x i1> @intrinsic_vmsge_mask_vx_nxv4i8_i8_1(<vscale x 4 x i1> %0, <vscale x 4 x i8> %1, <vscale x 4 x i1> %2, iXLen %3) nounwind {
+; CHECK-LABEL: intrinsic_vmsge_mask_vx_nxv4i8_i8_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vmv1r.v v10, v0
+; CHECK-NEXT: li a1, 99
+; CHECK-NEXT: vmv1r.v v0, v9
+; CHECK-NEXT: vsetvli zero, a0, e8, mf2, ta, mu
+; CHECK-NEXT: vmsgt.vx v10, v8, a1, v0.t
+; CHECK-NEXT: vmv1r.v v0, v10
+; CHECK-NEXT: ret
+entry:
+ %a = call <vscale x 4 x i1> @llvm.riscv.vmsge.mask.nxv4i8.i8(
+ <vscale x 4 x i1> %0,
+ <vscale x 4 x i8> %1,
+ i8 100,
+ <vscale x 4 x i1> %2,
+ iXLen %3)
+
+ ret <vscale x 4 x i1> %a
+}
+
+define <vscale x 4 x i1> @intrinsic_vmsge_mask_vx_nxv4i8_i8_2(<vscale x 4 x i1> %0, <vscale x 4 x i8> %1, <vscale x 4 x i1> %2, iXLen %3) nounwind {
+; CHECK-LABEL: intrinsic_vmsge_mask_vx_nxv4i8_i8_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vsetvli zero, a0, e8, mf2, ta, ma
+; CHECK-NEXT: vmor.mm v0, v9, v0
+; CHECK-NEXT: ret
+entry:
+ %a = call <vscale x 4 x i1> @llvm.riscv.vmsge.mask.nxv4i8.i8(
+ <vscale x 4 x i1> %0,
+ <vscale x 4 x i8> %1,
+ i8 -128,
+ <vscale x 4 x i1> %2,
+ iXLen %3)
+
+ ret <vscale x 4 x i1> %a
+}
+
+
declare <vscale x 8 x i1> @llvm.riscv.vmsge.nxv8i8.i8(
<vscale x 8 x i8>,
i8,
@@ -1970,6 +2009,37 @@ entry:
ret <vscale x 4 x i1> %a
}
+define <vscale x 4 x i1> @intrinsic_vmsge_vi_nxv4i8_i8_1(<vscale x 4 x i8> %0, iXLen %1) nounwind {
+; CHECK-LABEL: intrinsic_vmsge_vi_nxv4i8_i8_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li a1, 99
+; CHECK-NEXT: vsetvli zero, a0, e8, mf2, ta, ma
+; CHECK-NEXT: vmsgt.vx v0, v8, a1
+; CHECK-NEXT: ret
+entry:
+ %a = call <vscale x 4 x i1> @llvm.riscv.vmsge.nxv4i8.i8(
+ <vscale x 4 x i8> %0,
+ i8 100,
+ iXLen %1)
+
+ ret <vscale x 4 x i1> %a
+}
+
+define <vscale x 4 x i1> @intrinsic_vmsge_vi_nxv4i8_i8_2(<vscale x 4 x i8> %0, iXLen %1) nounwind {
+; CHECK-LABEL: intrinsic_vmsge_vi_nxv4i8_i8_2:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vsetvli zero, a0, e8, mf2, ta, ma
+; CHECK-NEXT: vmset.m v0
+; CHECK-NEXT: ret
+entry:
+ %a = call <vscale x 4 x i1> @llvm.riscv.vmsge.nxv4i8.i8(
+ <vscale x 4 x i8> %0,
+ i8 -128,
+ iXLen %1)
+
+ ret <vscale x 4 x i1> %a
+}
+
define <vscale x 4 x i1> @intrinsic_vmsge_mask_vi_nxv4i8_i8(<vscale x 4 x i1> %0, <vscale x 4 x i8> %1, <vscale x 4 x i1> %2, iXLen %3) nounwind {
; CHECK-LABEL: intrinsic_vmsge_mask_vi_nxv4i8_i8:
; CHECK: # %bb.0: # %entry
diff --git a/llvm/test/CodeGen/RISCV/rvv/vmsgeu.ll b/llvm/test/CodeGen/RISCV/rvv/vmsgeu.ll
index 05cc7a9d8f7b42..68aa912ae42ea4 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vmsgeu.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vmsgeu.ll
@@ -1990,6 +1990,27 @@ entry:
ret <vscale x 4 x i1> %a
}
+define <vscale x 4 x i1> @intrinsic_vmsgeu_mask_vi_nxv4i8_i8_1(<vscale x 4 x i1> %0, <vscale x 4 x i8> %1, <vscale x 4 x i1> %2, iXLen %3) nounwind {
+; CHECK-LABEL: intrinsic_vmsgeu_mask_vi_nxv4i8_i8_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: vmv1r.v v10, v0
+; CHECK-NEXT: li a1, 99
+; CHECK-NEXT: vmv1r.v v0, v9
+; CHECK-NEXT: vsetvli zero, a0, e8, mf2, ta, mu
+; CHECK-NEXT: vmsgtu.vx v10, v8, a1, v0.t
+; CHECK-NEXT: vmv1r.v v0, v10
+; CHECK-NEXT: ret
+entry:
+ %a = call <vscale x 4 x i1> @llvm.riscv.vmsgeu.mask.nxv4i8.i8(
+ <vscale x 4 x i1> %0,
+ <vscale x 4 x i8> %1,
+ i8 100,
+ <vscale x 4 x i1> %2,
+ iXLen %3)
+
+ ret <vscale x 4 x i1> %a
+}
+
define <vscale x 8 x i1> @intrinsic_vmsgeu_vi_nxv8i8_i8(<vscale x 8 x i8> %0, iXLen %1) nounwind {
; CHECK-LABEL: intrinsic_vmsgeu_vi_nxv8i8_i8:
; CHECK: # %bb.0: # %entry
@@ -2192,6 +2213,22 @@ entry:
ret <vscale x 4 x i1> %a
}
+define <vscale x 4 x i1> @intrinsic_vmsgeu_vi_nxv4i16_i16_1(<vscale x 4 x i16> %0, iXLen %1) nounwind {
+; CHECK-LABEL: intrinsic_vmsgeu_vi_nxv4i16_i16_1:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li a1, 99
+; CHECK-NEXT: vsetvli zero, a0, e16, m1, ta, ma
+; CHECK-NEXT: vmsgtu.vx v0, v8, a1
+; CHECK-NEXT: ret
+entry:
+ %a = call <vscale x 4 x i1> @llvm.riscv.vmsgeu.nxv4i16.i16(
+ <vscale x 4 x i16> %0,
+ i16 100,
+ iXLen %1)
+
+ ret <vscale x 4 x i1> %a
+}
+
define <vscale x 4 x i1> @intrinsic_vmsgeu_mask_vi_nxv4i16_i16(<vscale x 4 x i1> %0, <vscale x 4 x i16> %1, <vscale x 4 x i1> %2, iXLen %3) nounwind {
; CHECK-LABEL: intrinsic_vmsgeu_mask_vi_nxv4i16_i16:
; CHECK: # %bb.0: # %entry
More information about the llvm-commits
mailing list