LLVM: lib/CodeGen/SelectionDAG/ScheduleDAGVLIW.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
31using namespace llvm;
32
33#define DEBUG_TYPE "pre-RA-sched"
34
35STATISTIC(NumNoops , "Number of noops inserted");
36STATISTIC(NumStalls, "Number of pipeline stalls");
37
41
42namespace {
43
44
45
46
48private:
49
50
52
53
54
55
56
57 std::vector<SUnit*> PendingQueue;
58
59
61
62public:
66 HazardRec = STI.getInstrInfo()->CreateTargetHazardRecognizer(&STI, this);
67 }
68
69 ~ScheduleDAGVLIW() override {
70 delete HazardRec;
71 delete AvailableQueue;
72 }
73
74 void Schedule() override;
75
76private:
77 void releaseSucc(SUnit *SU, const SDep &D);
78 void releaseSuccessors(SUnit *SU);
79 void scheduleNodeTopDown(SUnit *SU, unsigned CurCycle);
80 void listScheduleTopDown();
81};
82}
83
84
85void ScheduleDAGVLIW::Schedule() {
87 << " '" << BB->getName() << "' **********\n");
88
89
90 BuildSchedGraph();
91
92 AvailableQueue->initNodes(SUnits);
93
94 listScheduleTopDown();
95
97}
98
99
100
101
102
103
104
105void ScheduleDAGVLIW::releaseSucc(SUnit *SU, const SDep &D) {
106 SUnit *SuccSU = D.getSUnit();
107
108#ifndef NDEBUG
110 dbgs() << "*** Scheduling failed! ***\n";
111 dumpNode(*SuccSU);
112 dbgs() << " has been released too many times!\n";
114 }
115#endif
116 assert(.isWeak() && "unexpected artificial DAG edge");
117
119
121
122
123
124 if (SuccSU->NumPredsLeft == 0 && SuccSU != &ExitSU) {
125 PendingQueue.push_back(SuccSU);
126 }
127}
128
129void ScheduleDAGVLIW::releaseSuccessors(SUnit *SU) {
130
131 for (SDep &Succ : SU->Succs) {
133 "The list-td scheduler doesn't yet support physreg dependencies!");
134
135 releaseSucc(SU, Succ);
136 }
137}
138
139
140
141
142void ScheduleDAGVLIW::scheduleNodeTopDown(SUnit *SU, unsigned CurCycle) {
143 LLVM_DEBUG(dbgs() << "*** Scheduling [" << CurCycle << "]: ");
145
147 assert(CurCycle >= SU->getDepth() && "Node scheduled above its depth!");
149
150 releaseSuccessors(SU);
153}
154
155
156
157void ScheduleDAGVLIW::listScheduleTopDown() {
158 unsigned CurCycle = 0;
159
160
161 releaseSuccessors(&EntrySU);
162
163
164 for (SUnit &SU : SUnits) {
165
166 if (SU.Preds.empty()) {
167 AvailableQueue->push(&SU);
169 }
170 }
171
172
173
174 std::vector<SUnit*> NotReady;
175 Sequence.reserve(SUnits.size());
176 while (!AvailableQueue->empty() || !PendingQueue.empty()) {
177
178
179 for (unsigned i = 0, e = PendingQueue.size(); i != e; ++i) {
180 if (PendingQueue[i]->getDepth() == CurCycle) {
181 AvailableQueue->push(PendingQueue[i]);
182 PendingQueue[i]->isAvailable = true;
183 PendingQueue[i] = PendingQueue.back();
184 PendingQueue.pop_back();
185 --i; --e;
186 }
187 else {
188 assert(PendingQueue[i]->getDepth() > CurCycle && "Negative latency?");
189 }
190 }
191
192
193
194 if (AvailableQueue->empty()) {
195
197 ++CurCycle;
198 continue;
199 }
200
201 SUnit *FoundSUnit = nullptr;
202
203 bool HasNoopHazards = false;
204 while (!AvailableQueue->empty()) {
205 SUnit *CurSUnit = AvailableQueue->pop();
206
208 HazardRec->getHazardType(CurSUnit, 0);
210 FoundSUnit = CurSUnit;
211 break;
212 }
213
214
216
217 NotReady.push_back(CurSUnit);
218 }
219
220
221 if (!NotReady.empty()) {
222 AvailableQueue->push_all(NotReady);
223 NotReady.clear();
224 }
225
226
227 if (FoundSUnit) {
228 scheduleNodeTopDown(FoundSUnit, CurCycle);
230
231
232
233 if (FoundSUnit->Latency)
234 ++CurCycle;
235 } else if (!HasNoopHazards) {
236
237
238 LLVM_DEBUG(dbgs() << "*** Advancing cycle, no work to do\n");
240 ++NumStalls;
241 ++CurCycle;
242 } else {
243
244
245
248 Sequence.push_back(nullptr);
249 ++NumNoops;
250 ++CurCycle;
251 }
252 }
253
254#ifndef NDEBUG
255 VerifyScheduledSequence(false);
256#endif
257}
258
259
260
261
262
263
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static RegisterScheduler VLIWScheduler("vliw-td", "VLIW scheduler", createVLIWDAGScheduler)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool isAssignedRegDep() const
Tests if this is a Data dependence that is associated with a register.
unsigned short Latency
Node latency.
unsigned getDepth() const
Returns the depth of this node, which is the length of the maximum path up to any node which has no p...
bool isScheduled
True once scheduled.
bool isAvailable
True once available.
SmallVector< SDep, 4 > Succs
All sunit successors.
SmallVector< SDep, 4 > Preds
All sunit predecessors.
LLVM_ABI void setDepthToAtLeast(unsigned NewDepth)
If NewDepth is greater than this node's depth value, sets it to be the new depth value.
ScheduleDAGSDNodes - A ScheduleDAG for scheduling SDNode-based DAGs.
HazardRecognizer - This determines whether or not an instruction can be issued this cycle,...
virtual void EmitInstruction(SUnit *)
EmitInstruction - This callback is invoked when an instruction is emitted, to advance the hazard stat...
virtual void EmitNoop()
EmitNoop - This callback is invoked when a noop was added to the instruction stream.
virtual void AdvanceCycle()
AdvanceCycle - This callback is invoked whenever the next top-down instruction to be scheduled cannot...
virtual HazardType getHazardType(SUnit *, int Stalls=0)
getHazardType - Return the hazard type of emitting this node.
This interface is used to plug different priorities computation algorithms into the list scheduler.
virtual void releaseState()=0
virtual void scheduledNode(SUnit *)
As each node is scheduled, this method is invoked.
virtual void initNodes(std::vector< SUnit > &SUnits)=0
virtual bool empty() const =0
void push_all(const std::vector< SUnit * > &Nodes)
virtual void push(SUnit *U)=0
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Sequence
A sequence of states that a pointer may go through in which an objc_retain and objc_release are actua...
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CodeGenOptLevel
Code generation optimization level.
LLVM_ABI ScheduleDAGSDNodes * createVLIWDAGScheduler(SelectionDAGISel *IS, CodeGenOptLevel OptLevel)
createVLIWDAGScheduler - Scheduler for VLIW targets.
Definition ScheduleDAGVLIW.cpp:264
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.