LLVM: lib/CodeGen/MacroFusion.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
24
25#define DEBUG_TYPE "machine-scheduler"
26
27STATISTIC(NumFused, "Number of instr pairs fused");
28
29using namespace llvm;
30
32 cl::desc("Enable scheduling for macro fusion."), cl::init(true));
33
37
40 if (SI.isCluster())
41 return SI.getSUnit();
42
43 return nullptr;
44}
45
47 unsigned Num = 1;
48 const SUnit *CurrentSU = &SU;
49 while ((CurrentSU = getPredClusterSU(*CurrentSU)) && Num < FuseLimit) Num ++;
50 return Num < FuseLimit;
51}
52
54 SUnit &SecondSU) {
55
56
58 if (SI.isCluster())
59 return false;
60
62 if (SI.isCluster())
63 return false;
64
67
68
69
70
71
72
73
75 return false;
76
78
81
83 Clusters.push_back(Cluster);
84
85
86
87
88
89
91 "Currently we only support chaining together two instructions");
92
93
95 if (SI.getSUnit() == &SecondSU)
96 SI.setLatency(0);
97
99 if (SI.getSUnit() == &FirstSU)
100 SI.setLatency(0);
101
107
108
109
110 if (&SecondSU != &DAG.ExitSU)
112 SUnit *SU = SI.getSUnit();
114 SU == &DAG.ExitSU || SU == &SecondSU || SU->isPred(&SecondSU))
115 continue;
119 }
120
121
122
123 if (&FirstSU != &DAG.EntrySU) {
125 SUnit *SU = SI.getSUnit();
126 if (SI.isWeak() || isHazard(SI) || &FirstSU == SU || FirstSU.isSucc(SU))
127 continue;
131 }
132
133
134
135 if (&SecondSU == &DAG.ExitSU) {
137 if (SU.Succs.empty())
139 }
140 }
141 }
142
143 ++NumFused;
144 return true;
145}
146
147namespace {
148
149
150
152 std::vector Predicates;
153 bool FuseBlock;
155
156public:
158 : Predicates(Predicates.begin(), Predicates.end()), FuseBlock(FuseBlock) {
159 }
160
161 void apply(ScheduleDAGInstrs *DAGInstrs) override;
162
164 const TargetSubtargetInfo &STI,
165 const MachineInstr *FirstMI,
166 const MachineInstr &SecondMI);
167};
168
169}
170
176 return Predicate(TII, STI, FirstMI, SecondMI);
177 });
178}
179
180void MacroFusion::apply(ScheduleDAGInstrs *DAG) {
181 if (FuseBlock)
182
183
184 for (SUnit &ISU : DAG->SUnits)
185 scheduleAdjacentImpl(*DAG, ISU);
186
188
189 scheduleAdjacentImpl(*DAG, DAG->ExitSU);
190}
191
192
193
194bool MacroFusion::scheduleAdjacentImpl(ScheduleDAGInstrs &DAG, SUnit &AnchorSU) {
195 const MachineInstr &AnchorMI = *AnchorSU.getInstr();
196 const TargetInstrInfo &TII = *DAG.TII;
198
199
201 return false;
202
203
204 for (SDep &Dep : AnchorSU.Preds) {
205
207 continue;
208
209 SUnit &DepSU = *Dep.getSUnit();
211 continue;
212
213
214 const MachineInstr *DepMI = DepSU.getInstr();
217 continue;
218
220 return true;
221 }
222
223 return false;
224}
225
226std::unique_ptr
228 bool BranchOnly) {
230 return std::make_unique(Predicates, !BranchOnly);
231 return nullptr;
232}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, const TargetSubtargetInfo &TSI, const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Check if the instr pair, FirstMI and SecondMI, should be fused together.
const TargetInstrInfo & TII
static cl::opt< bool > EnableMacroFusion("misched-fusion", cl::Hidden, cl::desc("Enable scheduling for macro fusion."), cl::init(true))
static SUnit * getPredClusterSU(const SUnit &SU)
Definition MacroFusion.cpp:38
static bool isHazard(const SDep &Dep)
Definition MacroFusion.cpp:34
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Kind getKind() const
Returns an enum value representing the kind of the dependence.
@ Output
A register output-dependence (aka WAW).
@ Anti
A register anti-dependence (aka WAR).
bool isWeak() const
Tests if this a weak dependence.
@ Cluster
Weak DAG edge linking a chain of clustered instrs.
@ Artificial
Arbitrary strong DAG edge (no real dependence).
Scheduling unit. This is a node in the scheduling DAG.
bool isSucc(const SUnit *N) const
Tests if node N is a successor of this node.
bool isPred(const SUnit *N) const
Tests if node N is a predecessor of this node.
bool isBoundaryNode() const
Boundary nodes are placeholders for the boundary of the scheduling region.
unsigned ParentClusterIdx
The parent cluster id.
SmallVector< SDep, 4 > Succs
All sunit successors.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
MachineInstr * getInstr() const
Returns the representative MachineInstr for this SUnit.
A ScheduleDAG for scheduling lists of MachineInstr.
SmallVector< ClusterInfo > & getClusters()
Returns the array of the clusters.
bool addEdge(SUnit *SuccSU, const SDep &PredDep)
Add a DAG edge to the given SU with the given predecessor dependence data.
Mutate the DAG as a postpass after normal DAG building.
const TargetInstrInfo * TII
Target instruction information.
std::vector< SUnit > SUnits
The scheduling units.
SUnit EntrySU
Special node for the region entry.
MachineFunction & MF
Machine function.
void dumpNodeName(const SUnit &SU) const
SUnit ExitSU
Special node for the region exit.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
TargetInstrInfo - Interface to description of machine instruction set.
TargetSubtargetInfo - Generic base class for all target subtargets.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
void apply(Opt *O, const Mod &M, const Mods &... Ms)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::unique_ptr< ScheduleDAGMutation > createMacroFusionDAGMutation(ArrayRef< MacroFusionPredTy > Predicates, bool BranchOnly=false)
Create a DAG scheduling mutation to pair instructions back to back for instructions that benefit acco...
Definition MacroFusion.cpp:227
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI bool fuseInstructionPair(ScheduleDAGInstrs &DAG, SUnit &FirstSU, SUnit &SecondSU)
Create an artificial edge between FirstSU and SecondSU.
Definition MacroFusion.cpp:53
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr unsigned InvalidClusterId
bool(*)(const TargetInstrInfo &TII, const TargetSubtargetInfo &STI, const MachineInstr *FirstMI, const MachineInstr &SecondMI) MacroFusionPredTy
Check if the instr pair, FirstMI and SecondMI, should be fused together.
static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, const TargetSubtargetInfo &TSI, const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Check if the instr pair, FirstMI and SecondMI, should be fused together.
LLVM_ABI bool hasLessThanNumFused(const SUnit &SU, unsigned FuseLimit)
Checks if the number of cluster edges between SU and its predecessors is less than FuseLimit.
Definition MacroFusion.cpp:46