Skip to content

Commit 393dfe4

Browse files
author
Mikhail Gudim
committed
[RISCV] Remove unnecessary dependencies on vtype register.
1 parent 8ac7210 commit 393dfe4

File tree

4 files changed

+180
-0
lines changed

4 files changed

+180
-0
lines changed

llvm/lib/Target/RISCV/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ add_llvm_target(RISCVCodeGen
6767
RISCVVectorMaskDAGMutation.cpp
6868
RISCVVectorPeephole.cpp
6969
RISCVVLOptimizer.cpp
70+
RISCVVTypeRegDepMutation.cpp
7071
RISCVVMV0Elimination.cpp
7172
RISCVZacasABIFix.cpp
7273
GISel/RISCVCallLowering.cpp

llvm/lib/Target/RISCV/RISCVTargetMachine.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ static cl::opt<bool> EnablePostMISchedLoadStoreClustering(
104104
cl::desc("Enable PostRA load and store clustering in the machine scheduler"),
105105
cl::init(true));
106106

107+
static cl::opt<bool> EnableVTypeRegDepMutation(
108+
"riscv-postmisched-vtype-reg-dep-mutation", cl::Hidden,
109+
cl::desc("Remove unnecessary dependencies on vtype register"),
110+
cl::init(false));
111+
107112
static cl::opt<bool>
108113
EnableVLOptimizer("riscv-enable-vl-optimizer",
109114
cl::desc("Enable the RISC-V VL Optimizer pass"),
@@ -323,6 +328,8 @@ RISCVTargetMachine::createPostMachineScheduler(MachineSchedContext *C) const {
323328
DAG->addMutation(createStoreClusterDAGMutation(
324329
DAG->TII, DAG->TRI, /*ReorderWhileClustering=*/true));
325330
}
331+
if (EnableVTypeRegDepMutation)
332+
DAG->addMutation(createRISCVVTypeRegDepMutation(DAG->TRI));
326333

327334
return DAG;
328335
}

llvm/lib/Target/RISCV/RISCVTargetMachine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ class RISCVTargetMachine : public CodeGenTargetMachineImpl {
6868
std::unique_ptr<ScheduleDAGMutation>
6969
createRISCVVectorMaskDAGMutation(const TargetRegisterInfo *TRI);
7070

71+
std::unique_ptr<ScheduleDAGMutation>
72+
createRISCVVTypeRegDepMutation(const TargetRegisterInfo *TRI);
7173
} // namespace llvm
7274

7375
#endif
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
//===- RISCVVTypeRegDepMutation.cpp - RISC-V Vector Mask DAGMutation ----===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
#include "MCTargetDesc/RISCVBaseInfo.h"
10+
#include "MCTargetDesc/RISCVMCTargetDesc.h"
11+
#include "RISCVRegisterInfo.h"
12+
#include "RISCVTargetMachine.h"
13+
#include "llvm/CodeGen/LiveIntervals.h"
14+
#include "llvm/CodeGen/MachineInstr.h"
15+
#include "llvm/CodeGen/ScheduleDAGInstrs.h"
16+
#include "llvm/CodeGen/ScheduleDAGMutation.h"
17+
#include "llvm/TargetParser/RISCVTargetParser.h"
18+
19+
#define DEBUG_TYPE "machine-scheduler"
20+
21+
namespace llvm {
22+
23+
static void collectPossibleVSetsForMI(
24+
MachineInstr *MI, int RequiredVL, unsigned PossibleVType,
25+
SmallVector<std::tuple<MachineInstr *, int>> &VSetInstrVLs,
26+
SmallVector<MachineInstr *> &PossibleVSets) {
27+
unsigned VTypeMask = unsigned(-1);
28+
if (MI->getOpcode() == RISCV::PseudoVLE8_V_MF4 ||
29+
MI->getOpcode() == RISCV::PseudoVLE8_V_MF8) {
30+
// TODO: actually, we care about the ratio lmul / sew
31+
VTypeMask = ~((0x7 << 3) | 0x7);
32+
}
33+
unsigned RequiredMaskedVType = PossibleVType & VTypeMask;
34+
for (auto &VSetInstrVL : VSetInstrVLs) {
35+
MachineInstr *VSetInstr = std::get<0>(VSetInstrVL);
36+
if ((std::get<1>(VSetInstrVL) == RequiredVL) &&
37+
((VSetInstr->getOperand(2).getImm() & VTypeMask) ==
38+
RequiredMaskedVType)) {
39+
PossibleVSets.push_back(VSetInstr);
40+
}
41+
}
42+
return;
43+
}
44+
45+
class RISCVVTypeRegDepMutation : public ScheduleDAGMutation {
46+
private:
47+
const TargetRegisterInfo *TRI;
48+
49+
public:
50+
RISCVVTypeRegDepMutation(const TargetRegisterInfo *TRI) : TRI(TRI) {}
51+
void apply(ScheduleDAGInstrs *DAG) override;
52+
};
53+
54+
// For each instruction I that reads vtype register:
55+
// (1) compute reaching definitions of vtype register.
56+
// (2) From all vtype reg definitions in the basic block collect the ones
57+
// compatible with those found in (1) (call this set Comp(I)).
58+
// (3) for each instruction vset in Comp(I) if there is data dependence on
59+
// vtype reg vset->I, remove it, also, remove all anti-depencies I->vset (4)
60+
// Choose by some heuristic an instruction best_vset from Comp(I) and insert
61+
// data dependence on vtype: best_vset->I. NOTE: code below is not correct,
62+
// but by luck it doesn't cause any issues on SPEC.
63+
void RISCVVTypeRegDepMutation::apply(ScheduleDAGInstrs *DAG) {
64+
SmallVector<std::tuple<MachineInstr *, int>> VSetInstrVLs;
65+
SmallVector<std::tuple<MachineInstr *, int, MachineInstr *>> MIVLVSetInstrs;
66+
int CurrentVL = -1;
67+
for (auto MBBI = DAG->begin(); MBBI != DAG->end(); ++MBBI) {
68+
switch (MBBI->getOpcode()) {
69+
default:
70+
continue;
71+
case RISCV::PseudoVSETIVLI: {
72+
CurrentVL = MBBI->getOperand(1).getImm();
73+
VSetInstrVLs.push_back({&*MBBI, CurrentVL});
74+
continue;
75+
}
76+
case RISCV::PseudoVSETVLI: {
77+
continue;
78+
}
79+
case RISCV::PseudoVSETVLIX0X0: {
80+
// TODO: the case when we're setting to VLMax
81+
// if (MBBI->getOperand(0).getReg() != RISCV::X0) {
82+
// continue;
83+
// }
84+
VSetInstrVLs.push_back(std::make_pair(&*MBBI, CurrentVL));
85+
continue;
86+
}
87+
case RISCV::PseudoVLE8_V_MF8:
88+
case RISCV::PseudoVLE8_V_MF4: {
89+
if (!VSetInstrVLs.empty())
90+
MIVLVSetInstrs.push_back(
91+
{&*MBBI, CurrentVL, std::get<0>(VSetInstrVLs.back())});
92+
continue;
93+
}
94+
}
95+
}
96+
97+
DenseMap<MachineInstr *,
98+
std::tuple<SmallVector<MachineInstr *>, MachineInstr *>>
99+
MIToPossibleVSetsMap;
100+
for (auto &MIVLVSetInstr : MIVLVSetInstrs) {
101+
MachineInstr *OrigVSetInstr = std::get<2>(MIVLVSetInstr);
102+
int RequiredVL = std::get<1>(MIVLVSetInstr);
103+
int PossibleVType = OrigVSetInstr->getOperand(2).getImm();
104+
SmallVector<MachineInstr *> PossibleVSets;
105+
MachineInstr *MI = std::get<0>(MIVLVSetInstr);
106+
collectPossibleVSetsForMI(MI, RequiredVL, PossibleVType, VSetInstrVLs,
107+
PossibleVSets);
108+
MIToPossibleVSetsMap[MI] = {PossibleVSets, OrigVSetInstr};
109+
}
110+
111+
DenseMap<MachineInstr *, SUnit *> VSetToSUMap;
112+
for (SUnit &SU : DAG->SUnits) {
113+
if (!SU.isInstr())
114+
continue;
115+
MachineInstr *MI = SU.getInstr();
116+
unsigned Opc = MI->getOpcode();
117+
if ((Opc == RISCV::PseudoVSETIVLI) || (Opc == RISCV::PseudoVSETVLI) ||
118+
(Opc == RISCV::PseudoVSETVLIX0))
119+
VSetToSUMap[MI] = &SU;
120+
}
121+
122+
for (SUnit &SU : DAG->SUnits) {
123+
if (!SU.isInstr())
124+
continue;
125+
MachineInstr *MI = SU.getInstr();
126+
SmallVector<MachineInstr *> &PossibleVSets =
127+
std::get<0>(MIToPossibleVSetsMap[MI]);
128+
if (PossibleVSets.size() < 2)
129+
continue;
130+
// Choose the earliest (in the original program order) VSET insruction
131+
// satisfying the vtype requirements of MI.
132+
SUnit *NewVSetSU = VSetToSUMap[PossibleVSets[0]];
133+
SUnit *OldVSetSU = VSetToSUMap[std::get<1>(MIToPossibleVSetsMap[MI])];
134+
for (auto &D : SU.Succs) {
135+
if (D.getKind() != SDep::Kind::Anti)
136+
continue;
137+
unsigned Reg = D.getReg();
138+
if (Reg != RISCV::VL && Reg != RISCV::VTYPE)
139+
continue;
140+
SUnit &AntiDepSucc = *D.getSUnit();
141+
// TODO: we can only remove anti-depence to compatible vsets.
142+
for (auto &P : AntiDepSucc.Preds) {
143+
if (P.getSUnit() == &SU) {
144+
AntiDepSucc.removePred(P);
145+
}
146+
}
147+
}
148+
for (auto &D : SU.Preds) {
149+
if (D.getSUnit() != OldVSetSU)
150+
continue;
151+
if (D.getKind() != SDep::Kind::Data)
152+
continue;
153+
unsigned Reg = D.getReg();
154+
if (Reg != RISCV::VL && Reg != RISCV::VTYPE)
155+
continue;
156+
unsigned Latency = D.getLatency();
157+
SU.removePred(D);
158+
SDep NewSDep(NewVSetSU, SDep::Kind::Data, Reg);
159+
NewSDep.setLatency(Latency);
160+
SU.addPred(NewSDep);
161+
}
162+
}
163+
return;
164+
}
165+
166+
std::unique_ptr<ScheduleDAGMutation>
167+
createRISCVVTypeRegDepMutation(const TargetRegisterInfo *TRI) {
168+
return std::make_unique<RISCVVTypeRegDepMutation>(TRI);
169+
}
170+
} // namespace llvm

0 commit comments

Comments
 (0)