[llvm] fb92fde - [RISCV] Canonicalize the true operand of vselect to fold more vmerge.vvm instructions (#206449)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 1 18:54:55 PDT 2026
Author: Liao Chunyu
Date: 2026-07-02T09:54:50+08:00
New Revision: fb92fdee85de92b03d3f30d7030f915a8471b845
URL: https://github.com/llvm/llvm-project/commit/fb92fdee85de92b03d3f30d7030f915a8471b845
DIFF: https://github.com/llvm/llvm-project/commit/fb92fdee85de92b03d3f30d7030f915a8471b845.diff
LOG: [RISCV] Canonicalize the true operand of vselect to fold more vmerge.vvm instructions (#206449)
Convert (vselect CC, true, false) to (vselect InvertCC, false, true)
when false has one use, true has multiple use and CC is SETEQ or ISD::SETNE.
When compile llvm-test-suite with --march=rv64gcv -O3 -ffast-math,
Without this patch, foldVMergeToMask removes `441` PseudoVMERGE_VVM
instructions.
With this patch, foldVMergeToMask removes `794` PseudoVMERGE_VVM
instructions.
Added:
Modified:
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/test/CodeGen/RISCV/rvv/vselect-fp.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 6d6bd13040a67..a994b9fc5961f 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20406,6 +20406,37 @@ static SDValue useInversedSetcc(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
+static SDValue
+canonicalizeVSelectTrueToOneUse(SDNode *N, SelectionDAG &DAG,
+ const RISCVSubtarget &Subtarget) {
+ SDValue CC = N->getOperand(0);
+ SDValue TrueVal = N->getOperand(1);
+ SDValue FalseVal = N->getOperand(2);
+
+ if (CC.getOpcode() != ISD::SETCC || !CC.hasOneUse() || TrueVal.hasOneUse() ||
+ !FalseVal.hasOneUse())
+ return SDValue();
+
+ // Only handles ISD::SETEQ and ISD::SETNE; no extra RVV introduced.
+ ISD::CondCode CCVal = cast<CondCodeSDNode>(CC.getOperand(2))->get();
+ if (!isIntEqualitySetCC(CCVal))
+ return SDValue();
+
+ if (DAG.isSplatValue(TrueVal) || DAG.isSplatValue(FalseVal) ||
+ TrueVal.getOpcode() == ISD::SPLAT_VECTOR_PARTS ||
+ FalseVal.getOpcode() == ISD::SPLAT_VECTOR_PARTS ||
+ TrueVal.getOpcode() == RISCVISD::VMV_V_X_VL ||
+ FalseVal.getOpcode() == RISCVISD::VMV_V_X_VL)
+ return SDValue();
+
+ SDLoc DL(N);
+ EVT CVT = CC.getValueType();
+ SDValue InvertedCC = DAG.getSetCC(DL, CVT, CC.getOperand(0), CC.getOperand(1),
+ ISD::getSetCCInverse(CCVal, CVT));
+ return DAG.getNode(ISD::VSELECT, DL, N->getValueType(0), InvertedCC, FalseVal,
+ TrueVal);
+}
+
static bool matchSelectAddSub(SDValue TrueVal, SDValue FalseVal, bool &SwapCC) {
if (!TrueVal.hasOneUse() || !FalseVal.hasOneUse())
return false;
@@ -20426,16 +20457,24 @@ static bool matchSelectAddSub(SDValue TrueVal, SDValue FalseVal, bool &SwapCC) {
(TrueVal.getOperand(1) == A && TrueVal.getOperand(0) == B));
}
-/// Convert vselect CC, (add a, b), (sub a, b) to add a, (vselect CC, -b, b).
-/// This allows us match a vadd.vv fed by a masked vrsub, which reduces
-/// register pressure over the add followed by masked vsub sequence.
-static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) {
+static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG,
+ const RISCVSubtarget &Subtarget) {
SDLoc DL(N);
EVT VT = N->getValueType(0);
SDValue CC = N->getOperand(0);
SDValue TrueVal = N->getOperand(1);
SDValue FalseVal = N->getOperand(2);
+ // Convert (vselect CC, true, false) to (vselect InvertCC, false, true) when
+ // false has one use and true has multiple use.
+ // It relies on RISCVVectorPeephole.cpp foldVMergeToMask to eliminate
+ // vmerge.vv
+ if (SDValue V = canonicalizeVSelectTrueToOneUse(N, DAG, Subtarget))
+ return V;
+
+ // Convert vselect CC, (add a, b), (sub a, b) to add a, (vselect CC, -b, b).
+ // This allows us match a vadd.vv fed by a masked vrsub, which reduces
+ // register pressure over the add followed by masked vsub sequence.
bool SwapCC;
if (!matchSelectAddSub(TrueVal, FalseVal, SwapCC))
return SDValue();
@@ -22194,7 +22233,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
case ISD::SELECT:
return performSELECTCombine(N, DAG, Subtarget);
case ISD::VSELECT:
- return performVSELECTCombine(N, DAG);
+ return performVSELECTCombine(N, DAG, Subtarget);
case RISCVISD::CZERO_EQZ:
case RISCVISD::CZERO_NEZ: {
SDValue Val = N->getOperand(0);
diff --git a/llvm/test/CodeGen/RISCV/rvv/vselect-fp.ll b/llvm/test/CodeGen/RISCV/rvv/vselect-fp.ll
index 1d8daf2667ffa..e267c98c59efd 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vselect-fp.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vselect-fp.ll
@@ -537,3 +537,33 @@ define void @vselect_legalize_regression(<vscale x 16 x double> %a, <vscale x 16
store <vscale x 16 x double> %sel, ptr %out
ret void
}
+
+
+define <vscale x 2 x double> @vselect_true_hasmultipleuse(<vscale x 2 x i32> %vc, <vscale x 2 x double> %va) {
+; RV32-LABEL: vselect_true_hasmultipleuse:
+; RV32: # %bb.0:
+; RV32-NEXT: vsetvli a0, zero, e32, m1, ta, ma
+; RV32-NEXT: vmsne.vi v0, v8, 1
+; RV32-NEXT: lui a0, %hi(.LCPI40_0)
+; RV32-NEXT: fld fa5, %lo(.LCPI40_0)(a0)
+; RV32-NEXT: vsetvli zero, zero, e64, m2, ta, mu
+; RV32-NEXT: vfmin.vf v10, v10, fa5, v0.t
+; RV32-NEXT: vmv.v.v v8, v10
+; RV32-NEXT: ret
+;
+; RV64-LABEL: vselect_true_hasmultipleuse:
+; RV64: # %bb.0:
+; RV64-NEXT: vsetvli a0, zero, e32, m1, ta, ma
+; RV64-NEXT: vmsne.vi v0, v8, 1
+; RV64-NEXT: li a0, 1
+; RV64-NEXT: slli a0, a0, 62
+; RV64-NEXT: fmv.d.x fa5, a0
+; RV64-NEXT: vsetvli zero, zero, e64, m2, ta, mu
+; RV64-NEXT: vfmin.vf v10, v10, fa5, v0.t
+; RV64-NEXT: vmv.v.v v8, v10
+; RV64-NEXT: ret
+ %cmp = icmp eq <vscale x 2 x i32> %vc, splat (i32 1)
+ %min = tail call fast <vscale x 2 x double> @llvm.minnum.nxv2f64(<vscale x 2 x double> %va, <vscale x 2 x double> splat (double 2.000000e+00))
+ %sel = select fast <vscale x 2 x i1> %cmp, <vscale x 2 x double> %va, <vscale x 2 x double> %min
+ ret <vscale x 2 x double> %sel
+}
More information about the llvm-commits
mailing list