[llvm] [RISCV] Improve vmsge and vmsgeu selection (PR #115435)
Jianjian Guan via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 12 19:03:03 PST 2024
https://github.com/jacquesguan updated https://github.com/llvm/llvm-project/pull/115435
>From 88f3ddd1417de3f67d99ab6b7538e6477ca08e6e Mon Sep 17 00:00:00 2001
From: Jianjian GUAN <jacquesguan at me.com>
Date: Fri, 8 Nov 2024 14:59:18 +0800
Subject: [PATCH 1/3] [RISCV] Improve vmsge and vmsgeu selection
Select vmsge(u) vs, C to vmsgt(u) vs, C-1 if C is not in the imm range and not the minimum value.
---
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 61 ++++++++++++++----
llvm/test/CodeGen/RISCV/rvv/vmsge.ll | 70 +++++++++++++++++++++
llvm/test/CodeGen/RISCV/rvv/vmsgeu.ll | 37 +++++++++++
3 files changed, 156 insertions(+), 12 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 17b617c502ca90..ae348a1a0bf6bc 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1616,21 +1616,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 == APSInt::getMinValue(Src1VT.getScalarSizeInBits(),
+ /*Unsigned=*/false)) {
+ IsCmpMinimum = true;
}
}
- MVT Src1VT = Src1.getSimpleValueType();
- unsigned VMSLTOpcode, VMNANDOpcode, VMSetOpcode;
+ unsigned VMSLTOpcode, VMNANDOpcode, VMSetOpcode, VMSGTOpcode;
switch (RISCVTargetLowering::getLMUL(Src1VT)) {
default:
llvm_unreachable("Unexpected LMUL!");
@@ -1638,6 +1645,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;
@@ -1656,11 +1665,20 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
selectVLOp(Node->getOperand(3), VL);
// If vmsgeu with 0 immediate, expand it to vmset.
- if (IsCmpUnsignedZero) {
+ 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(
@@ -1675,22 +1693,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 == APSInt::getMinValue(Src1VT.getScalarSizeInBits(),
+ /*Unsigned=*/false)) {
+ IsCmpMinimum = true;
}
}
- MVT Src1VT = Src1.getSimpleValueType();
unsigned VMSLTOpcode, VMSLTMaskOpcode, VMXOROpcode, VMANDNOpcode,
- VMOROpcode;
+ VMOROpcode, VMSGTMaskOpcode;
switch (RISCVTargetLowering::getLMUL(Src1VT)) {
default:
llvm_unreachable("Unexpected LMUL!");
@@ -1700,6 +1725,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)
@@ -1738,7 +1765,7 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
SDValue Mask = Node->getOperand(4);
// If vmsgeu_mask with 0 immediate, expand it to vmor mask, maskedoff.
- if (IsCmpUnsignedZero) {
+ if (IsCmpMinimum) {
// We don't need vmor if the MaskedOff and the Mask are the same
// value.
if (Mask == MaskedOff) {
@@ -1769,6 +1796,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
>From ec4ce897616671070812f30d223b752d03dd15d3 Mon Sep 17 00:00:00 2001
From: Jianjian GUAN <jacquesguan at me.com>
Date: Tue, 12 Nov 2024 14:20:01 +0800
Subject: [PATCH 2/3] Address comment
---
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 14 ++++++--------
1 file changed, 6 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index ae348a1a0bf6bc..a084f3566fbf25 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1631,9 +1631,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
if (!IsUnsigned || CVal != 0)
break;
IsCmpMinimum = true;
- } else if (!IsUnsigned &&
- CVal == APSInt::getMinValue(Src1VT.getScalarSizeInBits(),
- /*Unsigned=*/false)) {
+ } else if (!IsUnsigned && CVal == APInt::getSignedMinValue(
+ Src1VT.getScalarSizeInBits())) {
IsCmpMinimum = true;
}
}
@@ -1664,7 +1663,7 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
SDValue VL;
selectVLOp(Node->getOperand(3), VL);
- // If vmsgeu with 0 immediate, expand it to vmset.
+ // If vmsge(u) with minimum value, expand it to vmset.
if (IsCmpMinimum) {
ReplaceNode(Node, CurDAG->getMachineNode(VMSetOpcode, DL, VT, VL, SEW));
return;
@@ -1708,9 +1707,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
if (!IsUnsigned || CVal != 0)
break;
IsCmpMinimum = true;
- } else if (!IsUnsigned &&
- CVal == APSInt::getMinValue(Src1VT.getScalarSizeInBits(),
- /*Unsigned=*/false)) {
+ } else if (!IsUnsigned && CVal == APInt::getSignedMinValue(
+ Src1VT.getScalarSizeInBits())) {
IsCmpMinimum = true;
}
}
@@ -1764,7 +1762,7 @@ 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 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.
>From c1eb4101ff6b1501200db541358a6184a60caf13 Mon Sep 17 00:00:00 2001
From: Jianjian GUAN <jacquesguan at me.com>
Date: Wed, 13 Nov 2024 11:02:33 +0800
Subject: [PATCH 3/3] fix vmsge
---
llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index a084f3566fbf25..76ff0c3be2a0f4 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -1632,7 +1632,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
break;
IsCmpMinimum = true;
} else if (!IsUnsigned && CVal == APInt::getSignedMinValue(
- Src1VT.getScalarSizeInBits())) {
+ Src1VT.getScalarSizeInBits())
+ .getSExtValue()) {
IsCmpMinimum = true;
}
}
@@ -1708,7 +1709,8 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
break;
IsCmpMinimum = true;
} else if (!IsUnsigned && CVal == APInt::getSignedMinValue(
- Src1VT.getScalarSizeInBits())) {
+ Src1VT.getScalarSizeInBits())
+ .getSExtValue()) {
IsCmpMinimum = true;
}
}
More information about the llvm-commits
mailing list