[llvm] [RISCV] Lower VP_SELECT constant false to use vmerge.vxm/vmerge.vim (PR #144461)
Liao Chunyu via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 17 22:13:59 PDT 2025
https://github.com/ChunyuLiao updated https://github.com/llvm/llvm-project/pull/144461
>From d7354fae3861bf1bc503b5b78ec662fcc9681dbd Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Mon, 16 Jun 2025 21:40:22 -0400
Subject: [PATCH] [RISCV] Lower VP_SELECT constant false to use
vmerge.vxm/vmerge.vim
Currently, when the false path of a vp_select is a splat vector,
it is lowered to a vmv_v_x/vmv_v_i. The vmv is hoisted out of
the loop and the whole copy in loop body by MachineLICM.
By inverting the mask register and swapping the true and false values
in the vp_select, we can eliminate some instructions inside the loop.
corrent: https://godbolt.org/z/EnGMn3xeM
expected similar form: https://godbolt.org/z/nWhGM6Ej5
---
llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 22 ++++++++++++++++++-
llvm/lib/Target/RISCV/RISCVISelLowering.h | 1 +
.../test/CodeGen/RISCV/rvv/masked-load-int.ll | 6 ++---
llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll | 6 ++---
4 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index e670567bd1844..7221a767ec024 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -8168,11 +8168,17 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
return lowerRESET_FPENV(Op, DAG);
case ISD::EH_DWARF_CFA:
return lowerEH_DWARF_CFA(Op, DAG);
+ case ISD::VP_SELECT:
+ if (SDValue Op2 = Op.getOperand(2);
+ Op2.hasOneUse() && (Op2.getOpcode() == ISD::SPLAT_VECTOR ||
+ Op2.getOpcode() == ISD::SPLAT_VECTOR_PARTS))
+ return lowerVPSelectConstantFalse(Op, DAG);
+ else
+ return lowerVPOp(Op, DAG);
case ISD::VP_MERGE:
if (Op.getSimpleValueType().getVectorElementType() == MVT::i1)
return lowerVPMergeMask(Op, DAG);
[[fallthrough]];
- case ISD::VP_SELECT:
case ISD::VP_ADD:
case ISD::VP_SUB:
case ISD::VP_MUL:
@@ -13175,6 +13181,20 @@ SDValue RISCVTargetLowering::lowerVPFPIntConvOp(SDValue Op,
return convertFromScalableVector(VT, Result, DAG, Subtarget);
}
+SDValue
+RISCVTargetLowering::lowerVPSelectConstantFalse(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDLoc DL(Op);
+ MVT VT = Op.getSimpleValueType();
+ SDValue TrueVal = Op.getOperand(1);
+ SDValue FalseVal = Op.getOperand(2);
+ SDValue VL = Op.getOperand(3);
+ SDValue Op0 = Op.getOperand(0);
+ SDValue Val = DAG.getLogicalNOT(DL, Op0, Op0.getValueType());
+ return DAG.getNode(RISCVISD::VMERGE_VL, DL, VT, Val, FalseVal, TrueVal,
+ DAG.getUNDEF(VT), VL);
+}
+
SDValue RISCVTargetLowering::lowerVPMergeMask(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index f67d7f155c9d0..a36c9c2c664e3 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -486,6 +486,7 @@ class RISCVTargetLowering : public TargetLowering {
SDValue getTLSDescAddr(GlobalAddressSDNode *N, SelectionDAG &DAG) const;
SDValue lowerConstantFP(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerVPSelectConstantFalse(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/test/CodeGen/RISCV/rvv/masked-load-int.ll b/llvm/test/CodeGen/RISCV/rvv/masked-load-int.ll
index 75537406f3515..a9ed70b94c90f 100644
--- a/llvm/test/CodeGen/RISCV/rvv/masked-load-int.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/masked-load-int.ll
@@ -34,10 +34,10 @@ define <vscale x 1 x i8> @masked_load_passthru_nxv1i8(ptr %a, <vscale x 1 x i1>
; ZVE32: # %bb.0:
; ZVE32-NEXT: csrr a1, vlenb
; ZVE32-NEXT: srli a1, a1, 3
-; ZVE32-NEXT: vsetvli a2, zero, e8, mf4, ta, ma
-; ZVE32-NEXT: vmv.v.i v8, 0
-; ZVE32-NEXT: vsetvli zero, a1, e8, mf4, ta, mu
+; ZVE32-NEXT: vsetvli zero, a1, e8, mf4, ta, ma
; ZVE32-NEXT: vle8.v v8, (a0), v0.t
+; ZVE32-NEXT: vmnot.m v0, v0
+; ZVE32-NEXT: vmerge.vim v8, v8, 0, v0
; ZVE32-NEXT: ret
%load = call <vscale x 1 x i8> @llvm.masked.load.nxv1i8(ptr %a, i32 1, <vscale x 1 x i1> %mask, <vscale x 1 x i8> zeroinitializer)
ret <vscale x 1 x i8> %load
diff --git a/llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll b/llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll
index 522c83fd9fa99..3918a8009fde8 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vselect-vp.ll
@@ -483,10 +483,10 @@ define <vscale x 2 x i64> @select_nxv2i64_constant_true(<vscale x 2 x i1> %a, <v
define <vscale x 2 x i64> @select_nxv2i64_constant_false(<vscale x 2 x i1> %a, <vscale x 2 x i64> %b, i32 zeroext %evl) {
; CHECK-LABEL: select_nxv2i64_constant_false:
; CHECK: # %bb.0:
-; CHECK-NEXT: li a1, 100
; CHECK-NEXT: vsetvli zero, a0, e64, m2, ta, ma
-; CHECK-NEXT: vmv.v.x v10, a1
-; CHECK-NEXT: vmerge.vvm v8, v10, v8, v0
+; CHECK-NEXT: vmnot.m v0, v0
+; CHECK-NEXT: li a0, 100
+; CHECK-NEXT: vmerge.vxm v8, v8, a0, v0
; CHECK-NEXT: ret
%v = call <vscale x 2 x i64> @llvm.vp.select.nxv2i64(<vscale x 2 x i1> %a, <vscale x 2 x i64> %b, <vscale x 2 x i64> splat (i64 100), i32 %evl)
ret <vscale x 2 x i64> %v
More information about the llvm-commits
mailing list