Skip to content

Commit faa326d

Browse files
authored
[RISCV] Add branch+c.mv macrofusion for sifive-p450. (#76169)
sifive-p450 supports a very restricted version of the short forward branch optimization from the sifive-7-series. For sifive-p450, a branch over a single c.mv can be macrofused as a conditional move operation. Due to encoding restrictions on c.mv, we can't conditionally move from X0. That would require c.li instead.
1 parent f5145f4 commit faa326d

8 files changed

+505
-8
lines changed

llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
109109
return expandRV32ZdinxStore(MBB, MBBI);
110110
case RISCV::PseudoRV32ZdinxLD:
111111
return expandRV32ZdinxLoad(MBB, MBBI);
112+
case RISCV::PseudoCCMOVGPRNoX0:
112113
case RISCV::PseudoCCMOVGPR:
113114
case RISCV::PseudoCCADD:
114115
case RISCV::PseudoCCSUB:
@@ -191,7 +192,8 @@ bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,
191192
Register DestReg = MI.getOperand(0).getReg();
192193
assert(MI.getOperand(4).getReg() == DestReg);
193194

194-
if (MI.getOpcode() == RISCV::PseudoCCMOVGPR) {
195+
if (MI.getOpcode() == RISCV::PseudoCCMOVGPR ||
196+
MI.getOpcode() == RISCV::PseudoCCMOVGPRNoX0) {
195197
// Add MV.
196198
BuildMI(TrueBB, DL, TII->get(RISCV::ADDI), DestReg)
197199
.add(MI.getOperand(5))

llvm/lib/Target/RISCV/RISCVFeatures.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,12 @@ def TuneShortForwardBranchOpt
10211021
def HasShortForwardBranchOpt : Predicate<"Subtarget->hasShortForwardBranchOpt()">;
10221022
def NoShortForwardBranchOpt : Predicate<"!Subtarget->hasShortForwardBranchOpt()">;
10231023

1024+
def TuneConditionalCompressedMoveFusion
1025+
: SubtargetFeature<"conditional-cmv-fusion", "HasConditionalCompressedMoveFusion",
1026+
"true", "Enable branch+c.mv fusion">;
1027+
def HasConditionalMoveFusion : Predicate<"Subtarget->hasConditionalMoveFusion()">;
1028+
def NoConditionalMoveFusion : Predicate<"!Subtarget->hasConditionalMoveFusion()">;
1029+
10241030
def TuneSiFive7 : SubtargetFeature<"sifive7", "RISCVProcFamily", "SiFive7",
10251031
"SiFive 7-Series processors",
10261032
[TuneNoDefaultUnroll,

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6920,7 +6920,7 @@ static SDValue combineSelectToBinOp(SDNode *N, SelectionDAG &DAG,
69206920
MVT VT = N->getSimpleValueType(0);
69216921
SDLoc DL(N);
69226922

6923-
if (!Subtarget.hasShortForwardBranchOpt()) {
6923+
if (!Subtarget.hasConditionalMoveFusion()) {
69246924
// (select c, -1, y) -> -c | y
69256925
if (isAllOnesConstant(TrueV)) {
69266926
SDValue Neg = DAG.getNegative(CondV, DL, VT);
@@ -7084,7 +7084,7 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
70847084

70857085
// (select c, t, f) -> (or (czero_eqz t, c), (czero_nez f, c))
70867086
// Unless we have the short forward branch optimization.
7087-
if (!Subtarget.hasShortForwardBranchOpt())
7087+
if (!Subtarget.hasConditionalMoveFusion())
70887088
return DAG.getNode(
70897089
ISD::OR, DL, VT,
70907090
DAG.getNode(RISCVISD::CZERO_EQZ, DL, VT, TrueV, CondV),
@@ -12209,7 +12209,7 @@ static SDValue combineSelectAndUse(SDNode *N, SDValue Slct, SDValue OtherOp,
1220912209
if (VT.isVector())
1221012210
return SDValue();
1221112211

12212-
if (!Subtarget.hasShortForwardBranchOpt()) {
12212+
if (!Subtarget.hasConditionalMoveFusion()) {
1221312213
// (select cond, x, (and x, c)) has custom lowering with Zicond.
1221412214
if ((!Subtarget.hasStdExtZicond() &&
1221512215
!Subtarget.hasVendorXVentanaCondOps()) ||
@@ -14440,7 +14440,7 @@ static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG,
1444014440
if (SDValue V = useInversedSetcc(N, DAG, Subtarget))
1444114441
return V;
1444214442

14443-
if (Subtarget.hasShortForwardBranchOpt())
14443+
if (Subtarget.hasConditionalMoveFusion())
1444414444
return SDValue();
1444514445

1444614446
SDValue TrueVal = N->getOperand(1);
@@ -15178,7 +15178,7 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
1517815178
return DAG.getNode(RISCVISD::SELECT_CC, DL, N->getValueType(0),
1517915179
{LHS, RHS, CC, TrueV, FalseV});
1518015180

15181-
if (!Subtarget.hasShortForwardBranchOpt()) {
15181+
if (!Subtarget.hasConditionalMoveFusion()) {
1518215182
// (select c, -1, y) -> -c | y
1518315183
if (isAllOnesConstant(TrueV)) {
1518415184
SDValue C = DAG.getSetCC(DL, VT, LHS, RHS, CCVal);

llvm/lib/Target/RISCV/RISCVInstrInfo.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,6 +2650,7 @@ bool RISCVInstrInfo::findCommutedOpIndices(const MachineInstr &MI,
26502650
case RISCV::TH_MULSH:
26512651
// Operands 2 and 3 are commutable.
26522652
return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 2, 3);
2653+
case RISCV::PseudoCCMOVGPRNoX0:
26532654
case RISCV::PseudoCCMOVGPR:
26542655
// Operands 4 and 5 are commutable.
26552656
return fixCommutedOpIndices(SrcOpIdx1, SrcOpIdx2, 4, 5);
@@ -2806,6 +2807,7 @@ MachineInstr *RISCVInstrInfo::commuteInstructionImpl(MachineInstr &MI,
28062807
return TargetInstrInfo::commuteInstructionImpl(WorkingMI, false, OpIdx1,
28072808
OpIdx2);
28082809
}
2810+
case RISCV::PseudoCCMOVGPRNoX0:
28092811
case RISCV::PseudoCCMOVGPR: {
28102812
// CCMOV can be commuted by inverting the condition.
28112813
auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());

llvm/lib/Target/RISCV/RISCVInstrInfo.td

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1371,6 +1371,24 @@ def PseudoCCMOVGPR : Pseudo<(outs GPR:$dst),
13711371
ReadSFBALU, ReadSFBALU]>;
13721372
}
13731373

1374+
// This should always expand to a branch+c.mv so the size is 6 or 4 if the
1375+
// branch is compressible.
1376+
let Predicates = [HasConditionalMoveFusion, NoShortForwardBranchOpt],
1377+
Constraints = "$dst = $falsev", isCommutable = 1, Size = 6 in {
1378+
// This instruction moves $truev to $dst when the condition is true. It will
1379+
// be expanded to control flow in RISCVExpandPseudoInsts.
1380+
// We use GPRNoX0 because c.mv cannot encode X0.
1381+
def PseudoCCMOVGPRNoX0 : Pseudo<(outs GPRNoX0:$dst),
1382+
(ins GPR:$lhs, GPR:$rhs, ixlenimm:$cc,
1383+
GPRNoX0:$falsev, GPRNoX0:$truev),
1384+
[(set GPRNoX0:$dst,
1385+
(riscv_selectcc_frag:$cc (XLenVT GPR:$lhs),
1386+
(XLenVT GPR:$rhs),
1387+
cond, (XLenVT GPRNoX0:$truev),
1388+
(XLenVT GPRNoX0:$falsev)))]>,
1389+
Sched<[]>;
1390+
}
1391+
13741392
// Conditional binops, that updates update $dst to (op rs1, rs2) when condition
13751393
// is true. Returns $falsev otherwise. Selected by optimizeSelect.
13761394
// TODO: Can we use DefaultOperands on the regular binop to accomplish this more
@@ -1519,7 +1537,7 @@ multiclass SelectCC_GPR_rrirr<DAGOperand valty, ValueType vt> {
15191537
(IntCCtoRISCVCC $cc), valty:$truev, valty:$falsev)>;
15201538
}
15211539

1522-
let Predicates = [NoShortForwardBranchOpt] in
1540+
let Predicates = [NoConditionalMoveFusion] in
15231541
defm Select_GPR : SelectCC_GPR_rrirr<GPR, XLenVT>;
15241542

15251543
class SelectCompressOpt<CondCode Cond>

llvm/lib/Target/RISCV/RISCVProcessors.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ def SIFIVE_P450 : RISCVProcessorModel<"sifive-p450", NoSchedModel,
232232
FeatureStdExtZba,
233233
FeatureStdExtZbb,
234234
FeatureStdExtZbs,
235-
FeatureStdExtZfhmin]>;
235+
FeatureStdExtZfhmin],
236+
[TuneConditionalCompressedMoveFusion]>;
236237

237238
def SYNTACORE_SCR1_BASE : RISCVProcessorModel<"syntacore-scr1-base",
238239
SyntacoreSCR1Model,

llvm/lib/Target/RISCV/RISCVSubtarget.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
150150
bool hasHalfFPLoadStoreMove() const {
151151
return HasStdExtZfhmin || HasStdExtZfbfmin;
152152
}
153+
154+
bool hasConditionalMoveFusion() const {
155+
// Do we support fusing a branch+mv or branch+c.mv as a conditional move.
156+
return (hasConditionalCompressedMoveFusion() && hasStdExtCOrZca()) ||
157+
hasShortForwardBranchOpt();
158+
}
159+
153160
bool is64Bit() const { return IsRV64; }
154161
MVT getXLenVT() const {
155162
return is64Bit() ? MVT::i64 : MVT::i32;

0 commit comments

Comments
 (0)