blob: d219ef6b6dfde791bce0b13c8cae9d52d1ac3127 [file] [log] [blame]
Chris Lattneraf50d002002-04-09 05:45:58 +00001//===- InstrScheduling.cpp - Generic Instruction Scheduling support -------===//
2//
3// This file implements the llvm/CodeGen/InstrScheduling.h interface, along with
4// generic support routines for instruction scheduling.
5//
6//===----------------------------------------------------------------------===//
Vikram S. Advec5b46322001-09-30 23:43:34 +00007
Chris Lattnerc6f3ae52002-04-29 17:42:12 +00008#include "SchedPriorities.h"
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00009#include "llvm/CodeGen/MachineInstr.h"
Chris Lattner3462cae2002-02-03 07:28:30 +000010#include "llvm/CodeGen/MachineCodeForInstruction.h"
11#include "llvm/CodeGen/MachineCodeForMethod.h"
Chris Lattner483e14e2002-04-27 07:27:19 +000012#include "llvm/Analysis/LiveVar/FunctionLiveVarInfo.h" // FIXME: Remove when modularized better
Chris Lattner3462cae2002-02-03 07:28:30 +000013#include "llvm/Target/TargetMachine.h"
Chris Lattnerf35f2fb2002-02-04 16:35:45 +000014#include "llvm/BasicBlock.h"
Chris Lattner455889a2002-02-12 22:39:50 +000015#include "llvm/Instruction.h"
Chris Lattner1ff63a12001-09-07 21:19:42 +000016#include <algorithm>
Chris Lattner697954c2002-01-20 22:54:45 +000017using std::cerr;
18using std::vector;
Vikram S. Advec5b46322001-09-30 23:43:34 +000019
20//************************* External Data Types *****************************/
21
Vikram S. Adve0e1158f2001-08-28 23:07:19 +000022cl::Enum<enum SchedDebugLevel_t> SchedDebugLevel("dsched", cl::NoFlags,
23 "enable instruction scheduling debugging information",
24 clEnumValN(Sched_NoDebugInfo, "n", "disable debug output"),
Vikram S. Adve802cec42002-03-24 03:44:55 +000025 clEnumValN(Sched_Disable, "off", "disable instruction scheduling"),
Vikram S. Adve0e1158f2001-08-28 23:07:19 +000026 clEnumValN(Sched_PrintMachineCode, "y", "print machine code after scheduling"),
27 clEnumValN(Sched_PrintSchedTrace, "t", "print trace of scheduling actions"),
28 clEnumValN(Sched_PrintSchedGraphs, "g", "print scheduling graphs"), 0);
29
30
Vikram S. Advec5b46322001-09-30 23:43:34 +000031//************************* Internal Data Types *****************************/
32
Vikram S. Adve0e1158f2001-08-28 23:07:19 +000033class InstrSchedule;
34class SchedulingManager;
Vikram S. Adve0e1158f2001-08-28 23:07:19 +000035
Vikram S. Adve0e1158f2001-08-28 23:07:19 +000036
37//----------------------------------------------------------------------
38// class InstrGroup:
39//
40// Represents a group of instructions scheduled to be issued
41// in a single cycle.
42//----------------------------------------------------------------------
43
44class InstrGroup: public NonCopyable {
45public:
46 inline const SchedGraphNode* operator[](unsigned int slotNum) const {
47 assert(slotNum < group.size());
48 return group[slotNum];
49 }
50
51private:
52 friend class InstrSchedule;
53
54 inline void addInstr(const SchedGraphNode* node, unsigned int slotNum) {
55 assert(slotNum < group.size());
56 group[slotNum] = node;
57 }
58
59 /*ctor*/ InstrGroup(unsigned int nslots)
60 : group(nslots, NULL) {}
61
62 /*ctor*/ InstrGroup(); // disable: DO NOT IMPLEMENT
63
64private:
65 vector<const SchedGraphNode*> group;
66};
67
68
69//----------------------------------------------------------------------
70// class ScheduleIterator:
71//
72// Iterates over the machine instructions in the for a single basic block.
73// The schedule is represented by an InstrSchedule object.
74//----------------------------------------------------------------------
75
76template<class _NodeType>
77class ScheduleIterator: public std::forward_iterator<_NodeType, ptrdiff_t> {
78private:
79 unsigned cycleNum;
80 unsigned slotNum;
81 const InstrSchedule& S;
82public:
83 typedef ScheduleIterator<_NodeType> _Self;
84
85 /*ctor*/ inline ScheduleIterator(const InstrSchedule& _schedule,
86 unsigned _cycleNum,
87 unsigned _slotNum)
88 : cycleNum(_cycleNum), slotNum(_slotNum), S(_schedule) {
89 skipToNextInstr();
90 }
91
92 /*ctor*/ inline ScheduleIterator(const _Self& x)
93 : cycleNum(x.cycleNum), slotNum(x.slotNum), S(x.S) {}
94
95 inline bool operator==(const _Self& x) const {
96 return (slotNum == x.slotNum && cycleNum== x.cycleNum && &S==&x.S);
97 }
98
99 inline bool operator!=(const _Self& x) const { return !operator==(x); }
100
101 inline _NodeType* operator*() const {
102 assert(cycleNum < S.groups.size());
103 return (*S.groups[cycleNum])[slotNum];
104 }
105 inline _NodeType* operator->() const { return operator*(); }
106
107 _Self& operator++(); // Preincrement
108 inline _Self operator++(int) { // Postincrement
109 _Self tmp(*this); ++*this; return tmp;
110 }
111
112 static _Self begin(const InstrSchedule& _schedule);
113 static _Self end( const InstrSchedule& _schedule);
114
115private:
116 inline _Self& operator=(const _Self& x); // DISABLE -- DO NOT IMPLEMENT
117 void skipToNextInstr();
118};
119
120
121//----------------------------------------------------------------------
122// class InstrSchedule:
123//
124// Represents the schedule of machine instructions for a single basic block.
125//----------------------------------------------------------------------
126
127class InstrSchedule: public NonCopyable {
128private:
129 const unsigned int nslots;
130 unsigned int numInstr;
131 vector<InstrGroup*> groups; // indexed by cycle number
132 vector<cycles_t> startTime; // indexed by node id
133
134public: // iterators
135 typedef ScheduleIterator<SchedGraphNode> iterator;
136 typedef ScheduleIterator<const SchedGraphNode> const_iterator;
137
138 iterator begin();
139 const_iterator begin() const;
140 iterator end();
141 const_iterator end() const;
142
143public: // constructors and destructor
144 /*ctor*/ InstrSchedule (unsigned int _nslots,
145 unsigned int _numNodes);
146 /*dtor*/ ~InstrSchedule ();
147
148public: // accessor functions to query chosen schedule
149 const SchedGraphNode* getInstr (unsigned int slotNum,
150 cycles_t c) const {
151 const InstrGroup* igroup = this->getIGroup(c);
152 return (igroup == NULL)? NULL : (*igroup)[slotNum];
153 }
154
155 inline InstrGroup* getIGroup (cycles_t c) {
Chris Lattnerdfb8b952002-02-24 23:01:50 +0000156 if ((unsigned)c >= groups.size())
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000157 groups.resize(c+1);
158 if (groups[c] == NULL)
159 groups[c] = new InstrGroup(nslots);
160 return groups[c];
161 }
162
163 inline const InstrGroup* getIGroup (cycles_t c) const {
Chris Lattnerdfb8b952002-02-24 23:01:50 +0000164 assert((unsigned)c < groups.size());
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000165 return groups[c];
166 }
167
168 inline cycles_t getStartTime (unsigned int nodeId) const {
169 assert(nodeId < startTime.size());
170 return startTime[nodeId];
171 }
172
173 unsigned int getNumInstructions() const {
174 return numInstr;
175 }
176
177 inline void scheduleInstr (const SchedGraphNode* node,
178 unsigned int slotNum,
179 cycles_t cycle) {
180 InstrGroup* igroup = this->getIGroup(cycle);
181 assert((*igroup)[slotNum] == NULL && "Slot already filled?");
182 igroup->addInstr(node, slotNum);
183 assert(node->getNodeId() < startTime.size());
184 startTime[node->getNodeId()] = cycle;
185 ++numInstr;
186 }
187
188private:
189 friend class iterator;
190 friend class const_iterator;
191 /*ctor*/ InstrSchedule (); // Disable: DO NOT IMPLEMENT.
192};
193
194
195/*ctor*/
196InstrSchedule::InstrSchedule(unsigned int _nslots, unsigned int _numNodes)
197 : nslots(_nslots),
198 numInstr(0),
199 groups(2 * _numNodes / _nslots), // 2 x lower-bound for #cycles
200 startTime(_numNodes, (cycles_t) -1) // set all to -1
201{
202}
203
204
205/*dtor*/
206InstrSchedule::~InstrSchedule()
207{
208 for (unsigned c=0, NC=groups.size(); c < NC; c++)
209 if (groups[c] != NULL)
210 delete groups[c]; // delete InstrGroup objects
211}
212
213
214template<class _NodeType>
215inline
216void
217ScheduleIterator<_NodeType>::skipToNextInstr()
218{
219 while(cycleNum < S.groups.size() && S.groups[cycleNum] == NULL)
220 ++cycleNum; // skip cycles with no instructions
221
222 while (cycleNum < S.groups.size() &&
223 (*S.groups[cycleNum])[slotNum] == NULL)
224 {
225 ++slotNum;
226 if (slotNum == S.nslots)
227 {
228 ++cycleNum;
229 slotNum = 0;
230 while(cycleNum < S.groups.size() && S.groups[cycleNum] == NULL)
231 ++cycleNum; // skip cycles with no instructions
232 }
233 }
234}
235
236template<class _NodeType>
237inline
238ScheduleIterator<_NodeType>&
239ScheduleIterator<_NodeType>::operator++() // Preincrement
240{
241 ++slotNum;
242 if (slotNum == S.nslots)
243 {
244 ++cycleNum;
245 slotNum = 0;
246 }
247 skipToNextInstr();
248 return *this;
249}
250
251template<class _NodeType>
252ScheduleIterator<_NodeType>
253ScheduleIterator<_NodeType>::begin(const InstrSchedule& _schedule)
254{
255 return _Self(_schedule, 0, 0);
256}
257
258template<class _NodeType>
259ScheduleIterator<_NodeType>
260ScheduleIterator<_NodeType>::end(const InstrSchedule& _schedule)
261{
262 return _Self(_schedule, _schedule.groups.size(), 0);
263}
264
265InstrSchedule::iterator
266InstrSchedule::begin()
267{
268 return iterator::begin(*this);
269}
270
271InstrSchedule::const_iterator
272InstrSchedule::begin() const
273{
274 return const_iterator::begin(*this);
275}
276
277InstrSchedule::iterator
278InstrSchedule::end()
279{
280 return iterator::end(*this);
281}
282
283InstrSchedule::const_iterator
284InstrSchedule::end() const
285{
286 return const_iterator::end( *this);
287}
288
289
290//----------------------------------------------------------------------
291// class DelaySlotInfo:
292//
293// Record information about delay slots for a single branch instruction.
294// Delay slots are simply indexed by slot number 1 ... numDelaySlots
295//----------------------------------------------------------------------
296
297class DelaySlotInfo: public NonCopyable {
298private:
299 const SchedGraphNode* brNode;
300 unsigned int ndelays;
301 vector<const SchedGraphNode*> delayNodeVec;
302 cycles_t delayedNodeCycle;
303 unsigned int delayedNodeSlotNum;
304
305public:
306 /*ctor*/ DelaySlotInfo (const SchedGraphNode* _brNode,
307 unsigned _ndelays)
308 : brNode(_brNode), ndelays(_ndelays),
309 delayedNodeCycle(0), delayedNodeSlotNum(0) {}
310
311 inline unsigned getNumDelays () {
312 return ndelays;
313 }
314
315 inline const vector<const SchedGraphNode*>& getDelayNodeVec() {
316 return delayNodeVec;
317 }
318
319 inline void addDelayNode (const SchedGraphNode* node) {
320 delayNodeVec.push_back(node);
321 assert(delayNodeVec.size() <= ndelays && "Too many delay slot instrs!");
322 }
323
324 inline void recordChosenSlot (cycles_t cycle, unsigned slotNum) {
325 delayedNodeCycle = cycle;
326 delayedNodeSlotNum = slotNum;
327 }
328
Vikram S. Advec5b46322001-09-30 23:43:34 +0000329 unsigned scheduleDelayedNode (SchedulingManager& S);
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000330};
331
332
333//----------------------------------------------------------------------
334// class SchedulingManager:
335//
336// Represents the schedule of machine instructions for a single basic block.
337//----------------------------------------------------------------------
338
339class SchedulingManager: public NonCopyable {
340public: // publicly accessible data members
341 const unsigned int nslots;
342 const MachineSchedInfo& schedInfo;
343 SchedPriorities& schedPrio;
344 InstrSchedule isched;
345
346private:
347 unsigned int totalInstrCount;
348 cycles_t curTime;
349 cycles_t nextEarliestIssueTime; // next cycle we can issue
Chris Lattner697954c2002-01-20 22:54:45 +0000350 vector<std::hash_set<const SchedGraphNode*> > choicesForSlot; // indexed by slot#
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000351 vector<const SchedGraphNode*> choiceVec; // indexed by node ptr
352 vector<int> numInClass; // indexed by sched class
353 vector<cycles_t> nextEarliestStartTime; // indexed by opCode
Chris Lattner697954c2002-01-20 22:54:45 +0000354 std::hash_map<const SchedGraphNode*, DelaySlotInfo*> delaySlotInfoForBranches;
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000355 // indexed by branch node ptr
356
357public:
Chris Lattneraf50d002002-04-09 05:45:58 +0000358 SchedulingManager(const TargetMachine& _target, const SchedGraph* graph,
359 SchedPriorities& schedPrio);
360 ~SchedulingManager() {
361 for (std::hash_map<const SchedGraphNode*,
362 DelaySlotInfo*>::iterator I = delaySlotInfoForBranches.begin(),
363 E = delaySlotInfoForBranches.end(); I != E; ++I)
364 delete I->second;
365 }
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000366
367 //----------------------------------------------------------------------
368 // Simplify access to the machine instruction info
369 //----------------------------------------------------------------------
370
371 inline const MachineInstrInfo& getInstrInfo () const {
372 return schedInfo.getInstrInfo();
373 }
374
375 //----------------------------------------------------------------------
376 // Interface for checking and updating the current time
377 //----------------------------------------------------------------------
378
379 inline cycles_t getTime () const {
380 return curTime;
381 }
382
383 inline cycles_t getEarliestIssueTime() const {
384 return nextEarliestIssueTime;
385 }
386
387 inline cycles_t getEarliestStartTimeForOp(MachineOpCode opCode) const {
388 assert(opCode < (int) nextEarliestStartTime.size());
389 return nextEarliestStartTime[opCode];
390 }
391
392 // Update current time to specified cycle
393 inline void updateTime (cycles_t c) {
394 curTime = c;
395 schedPrio.updateTime(c);
396 }
397
398 //----------------------------------------------------------------------
399 // Functions to manage the choices for the current cycle including:
400 // -- a vector of choices by priority (choiceVec)
401 // -- vectors of the choices for each instruction slot (choicesForSlot[])
402 // -- number of choices in each sched class, used to check issue conflicts
403 // between choices for a single cycle
404 //----------------------------------------------------------------------
405
406 inline unsigned int getNumChoices () const {
407 return choiceVec.size();
408 }
409
410 inline unsigned getNumChoicesInClass (const InstrSchedClass& sc) const {
411 assert(sc < (int) numInClass.size() && "Invalid op code or sched class!");
412 return numInClass[sc];
413 }
414
415 inline const SchedGraphNode* getChoice(unsigned int i) const {
416 // assert(i < choiceVec.size()); don't check here.
417 return choiceVec[i];
418 }
419
Chris Lattner697954c2002-01-20 22:54:45 +0000420 inline std::hash_set<const SchedGraphNode*>& getChoicesForSlot(unsigned slotNum) {
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000421 assert(slotNum < nslots);
422 return choicesForSlot[slotNum];
423 }
424
425 inline void addChoice (const SchedGraphNode* node) {
426 // Append the instruction to the vector of choices for current cycle.
427 // Increment numInClass[c] for the sched class to which the instr belongs.
428 choiceVec.push_back(node);
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000429 const InstrSchedClass& sc = schedInfo.getSchedClass(node->getOpCode());
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000430 assert(sc < (int) numInClass.size());
431 numInClass[sc]++;
432 }
433
434 inline void addChoiceToSlot (unsigned int slotNum,
435 const SchedGraphNode* node) {
436 // Add the instruction to the choice set for the specified slot
437 assert(slotNum < nslots);
438 choicesForSlot[slotNum].insert(node);
439 }
440
441 inline void resetChoices () {
442 choiceVec.clear();
443 for (unsigned int s=0; s < nslots; s++)
444 choicesForSlot[s].clear();
445 for (unsigned int c=0; c < numInClass.size(); c++)
446 numInClass[c] = 0;
447 }
448
449 //----------------------------------------------------------------------
450 // Code to query and manage the partial instruction schedule so far
451 //----------------------------------------------------------------------
452
453 inline unsigned int getNumScheduled () const {
454 return isched.getNumInstructions();
455 }
456
457 inline unsigned int getNumUnscheduled() const {
458 return totalInstrCount - isched.getNumInstructions();
459 }
460
461 inline bool isScheduled (const SchedGraphNode* node) const {
462 return (isched.getStartTime(node->getNodeId()) >= 0);
463 }
464
465 inline void scheduleInstr (const SchedGraphNode* node,
466 unsigned int slotNum,
467 cycles_t cycle)
468 {
469 assert(! isScheduled(node) && "Instruction already scheduled?");
470
471 // add the instruction to the schedule
472 isched.scheduleInstr(node, slotNum, cycle);
473
474 // update the earliest start times of all nodes that conflict with `node'
475 // and the next-earliest time anything can issue if `node' causes bubbles
476 updateEarliestStartTimes(node, cycle);
477
478 // remove the instruction from the choice sets for all slots
479 for (unsigned s=0; s < nslots; s++)
480 choicesForSlot[s].erase(node);
481
482 // and decrement the instr count for the sched class to which it belongs
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000483 const InstrSchedClass& sc = schedInfo.getSchedClass(node->getOpCode());
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000484 assert(sc < (int) numInClass.size());
485 numInClass[sc]--;
486 }
Chris Lattner1ff63a12001-09-07 21:19:42 +0000487
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000488 //----------------------------------------------------------------------
489 // Create and retrieve delay slot info for delayed instructions
490 //----------------------------------------------------------------------
491
492 inline DelaySlotInfo* getDelaySlotInfoForInstr(const SchedGraphNode* bn,
493 bool createIfMissing=false)
494 {
Chris Lattneraf50d002002-04-09 05:45:58 +0000495 std::hash_map<const SchedGraphNode*, DelaySlotInfo*>::const_iterator
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000496 I = delaySlotInfoForBranches.find(bn);
Chris Lattneraf50d002002-04-09 05:45:58 +0000497 if (I != delaySlotInfoForBranches.end())
498 return I->second;
499
500 if (!createIfMissing) return 0;
501
502 DelaySlotInfo *dinfo =
503 new DelaySlotInfo(bn, getInstrInfo().getNumDelaySlots(bn->getOpCode()));
504 return delaySlotInfoForBranches[bn] = dinfo;
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000505 }
506
507private:
Chris Lattneraf50d002002-04-09 05:45:58 +0000508 SchedulingManager(); // DISABLED: DO NOT IMPLEMENT
509 void updateEarliestStartTimes(const SchedGraphNode* node, cycles_t schedTime);
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000510};
511
512
513/*ctor*/
514SchedulingManager::SchedulingManager(const TargetMachine& target,
515 const SchedGraph* graph,
516 SchedPriorities& _schedPrio)
Vikram S. Advef0ba2802001-09-18 12:51:38 +0000517 : nslots(target.getSchedInfo().getMaxNumIssueTotal()),
518 schedInfo(target.getSchedInfo()),
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000519 schedPrio(_schedPrio),
520 isched(nslots, graph->getNumNodes()),
521 totalInstrCount(graph->getNumNodes() - 2),
522 nextEarliestIssueTime(0),
523 choicesForSlot(nslots),
Vikram S. Advef0ba2802001-09-18 12:51:38 +0000524 numInClass(target.getSchedInfo().getNumSchedClasses(), 0), // set all to 0
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000525 nextEarliestStartTime(target.getInstrInfo().getNumRealOpCodes(),
526 (cycles_t) 0) // set all to 0
527{
528 updateTime(0);
529
530 // Note that an upper bound on #choices for each slot is = nslots since
531 // we use this vector to hold a feasible set of instructions, and more
532 // would be infeasible. Reserve that much memory since it is probably small.
533 for (unsigned int i=0; i < nslots; i++)
534 choicesForSlot[i].resize(nslots);
535}
536
537
538void
539SchedulingManager::updateEarliestStartTimes(const SchedGraphNode* node,
540 cycles_t schedTime)
541{
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000542 if (schedInfo.numBubblesAfter(node->getOpCode()) > 0)
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000543 { // Update next earliest time before which *nothing* can issue.
Chris Lattner697954c2002-01-20 22:54:45 +0000544 nextEarliestIssueTime = std::max(nextEarliestIssueTime,
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000545 curTime + 1 + schedInfo.numBubblesAfter(node->getOpCode()));
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000546 }
547
548 const vector<MachineOpCode>*
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000549 conflictVec = schedInfo.getConflictList(node->getOpCode());
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000550
551 if (conflictVec != NULL)
552 for (unsigned i=0; i < conflictVec->size(); i++)
553 {
554 MachineOpCode toOp = (*conflictVec)[i];
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000555 cycles_t est = schedTime + schedInfo.getMinIssueGap(node->getOpCode(),
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000556 toOp);
557 assert(toOp < (int) nextEarliestStartTime.size());
558 if (nextEarliestStartTime[toOp] < est)
559 nextEarliestStartTime[toOp] = est;
560 }
561}
562
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000563//************************* Internal Functions *****************************/
564
565
566static void
Vikram S. Advec5b46322001-09-30 23:43:34 +0000567AssignInstructionsToSlots(class SchedulingManager& S, unsigned maxIssue)
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000568{
Vikram S. Advec5b46322001-09-30 23:43:34 +0000569 // find the slot to start from, in the current cycle
570 unsigned int startSlot = 0;
571 cycles_t curTime = S.getTime();
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000572
Vikram S. Advec5b46322001-09-30 23:43:34 +0000573 assert(maxIssue > 0 && maxIssue <= S.nslots - startSlot);
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000574
Vikram S. Advec5b46322001-09-30 23:43:34 +0000575 // If only one instruction can be issued, do so.
576 if (maxIssue == 1)
577 for (unsigned s=startSlot; s < S.nslots; s++)
578 if (S.getChoicesForSlot(s).size() > 0)
579 {// found the one instruction
580 S.scheduleInstr(*S.getChoicesForSlot(s).begin(), s, curTime);
581 return;
582 }
583
584 // Otherwise, choose from the choices for each slot
585 //
586 InstrGroup* igroup = S.isched.getIGroup(S.getTime());
587 assert(igroup != NULL && "Group creation failed?");
588
589 // Find a slot that has only a single choice, and take it.
590 // If all slots have 0 or multiple choices, pick the first slot with
591 // choices and use its last instruction (just to avoid shifting the vector).
592 unsigned numIssued;
593 for (numIssued = 0; numIssued < maxIssue; numIssued++)
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000594 {
Chris Lattner697954c2002-01-20 22:54:45 +0000595 int chosenSlot = -1;
Vikram S. Advec5b46322001-09-30 23:43:34 +0000596 for (unsigned s=startSlot; s < S.nslots; s++)
597 if ((*igroup)[s] == NULL && S.getChoicesForSlot(s).size() == 1)
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000598 {
Vikram S. Advec5b46322001-09-30 23:43:34 +0000599 chosenSlot = (int) s;
600 break;
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000601 }
602
Vikram S. Advec5b46322001-09-30 23:43:34 +0000603 if (chosenSlot == -1)
604 for (unsigned s=startSlot; s < S.nslots; s++)
605 if ((*igroup)[s] == NULL && S.getChoicesForSlot(s).size() > 0)
606 {
607 chosenSlot = (int) s;
608 break;
609 }
610
611 if (chosenSlot != -1)
612 { // Insert the chosen instr in the chosen slot and
613 // erase it from all slots.
614 const SchedGraphNode* node= *S.getChoicesForSlot(chosenSlot).begin();
615 S.scheduleInstr(node, chosenSlot, curTime);
616 }
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000617 }
Vikram S. Advec5b46322001-09-30 23:43:34 +0000618
619 assert(numIssued > 0 && "Should not happen when maxIssue > 0!");
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000620}
621
622
623//
624// For now, just assume we are scheduling within a single basic block.
625// Get the machine instruction vector for the basic block and clear it,
626// then append instructions in scheduled order.
627// Also, re-insert the dummy PHI instructions that were at the beginning
628// of the basic block, since they are not part of the schedule.
629//
630static void
631RecordSchedule(const BasicBlock* bb, const SchedulingManager& S)
632{
Vikram S. Advef0ba2802001-09-18 12:51:38 +0000633 MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
634 const MachineInstrInfo& mii = S.schedInfo.getInstrInfo();
635
636#ifndef NDEBUG
637 // Lets make sure we didn't lose any instructions, except possibly
638 // some NOPs from delay slots. Also, PHIs are not included in the schedule.
639 unsigned numInstr = 0;
640 for (MachineCodeForBasicBlock::iterator I=mvec.begin(); I != mvec.end(); ++I)
641 if (! mii.isNop((*I)->getOpCode()) &&
642 ! mii.isDummyPhiInstr((*I)->getOpCode()))
643 ++numInstr;
644 assert(S.isched.getNumInstructions() >= numInstr &&
645 "Lost some non-NOP instructions during scheduling!");
646#endif
647
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000648 if (S.isched.getNumInstructions() == 0)
649 return; // empty basic block!
650
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000651 // First find the dummy instructions at the start of the basic block
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000652 MachineCodeForBasicBlock::iterator I = mvec.begin();
653 for ( ; I != mvec.end(); ++I)
654 if (! mii.isDummyPhiInstr((*I)->getOpCode()))
655 break;
656
657 // Erase all except the dummy PHI instructions from mvec, and
Vikram S. Advef0ba2802001-09-18 12:51:38 +0000658 // pre-allocate create space for the ones we will put back in.
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000659 mvec.erase(I, mvec.end());
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000660
661 InstrSchedule::const_iterator NIend = S.isched.end();
662 for (InstrSchedule::const_iterator NI = S.isched.begin(); NI != NIend; ++NI)
Chris Lattner2e530932001-09-09 19:41:52 +0000663 mvec.push_back(const_cast<MachineInstr*>((*NI)->getMachineInstr()));
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000664}
665
666
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000667
668static void
669MarkSuccessorsReady(SchedulingManager& S, const SchedGraphNode* node)
670{
671 // Check if any successors are now ready that were not already marked
672 // ready before, and that have not yet been scheduled.
673 //
674 for (sg_succ_const_iterator SI = succ_begin(node); SI !=succ_end(node); ++SI)
675 if (! (*SI)->isDummyNode()
676 && ! S.isScheduled(*SI)
677 && ! S.schedPrio.nodeIsReady(*SI))
678 {// successor not scheduled and not marked ready; check *its* preds.
679
680 bool succIsReady = true;
681 for (sg_pred_const_iterator P=pred_begin(*SI); P != pred_end(*SI); ++P)
682 if (! (*P)->isDummyNode()
683 && ! S.isScheduled(*P))
684 {
685 succIsReady = false;
686 break;
687 }
688
689 if (succIsReady) // add the successor to the ready list
690 S.schedPrio.insertReady(*SI);
691 }
692}
693
694
695// Choose up to `nslots' FEASIBLE instructions and assign each
696// instruction to all possible slots that do not violate feasibility.
697// FEASIBLE means it should be guaranteed that the set
698// of chosen instructions can be issued in a single group.
699//
700// Return value:
701// maxIssue : total number of feasible instructions
702// S.choicesForSlot[i=0..nslots] : set of instructions feasible in slot i
703//
704static unsigned
705FindSlotChoices(SchedulingManager& S,
706 DelaySlotInfo*& getDelaySlotInfo)
707{
708 // initialize result vectors to empty
709 S.resetChoices();
710
711 // find the slot to start from, in the current cycle
712 unsigned int startSlot = 0;
713 InstrGroup* igroup = S.isched.getIGroup(S.getTime());
714 for (int s = S.nslots - 1; s >= 0; s--)
715 if ((*igroup)[s] != NULL)
716 {
717 startSlot = s+1;
718 break;
719 }
720
721 // Make sure we pick at most one instruction that would break the group.
722 // Also, if we do pick one, remember which it was.
723 unsigned int indexForBreakingNode = S.nslots;
724 unsigned int indexForDelayedInstr = S.nslots;
725 DelaySlotInfo* delaySlotInfo = NULL;
726
727 getDelaySlotInfo = NULL;
728
729 // Choose instructions in order of priority.
730 // Add choices to the choice vector in the SchedulingManager class as
731 // we choose them so that subsequent choices will be correctly tested
732 // for feasibility, w.r.t. higher priority choices for the same cycle.
733 //
734 while (S.getNumChoices() < S.nslots - startSlot)
735 {
736 const SchedGraphNode* nextNode=S.schedPrio.getNextHighest(S,S.getTime());
737 if (nextNode == NULL)
738 break; // no more instructions for this cycle
739
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000740 if (S.getInstrInfo().getNumDelaySlots(nextNode->getOpCode()) > 0)
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000741 {
742 delaySlotInfo = S.getDelaySlotInfoForInstr(nextNode);
743 if (delaySlotInfo != NULL)
744 {
745 if (indexForBreakingNode < S.nslots)
746 // cannot issue a delayed instr in the same cycle as one
747 // that breaks the issue group or as another delayed instr
748 nextNode = NULL;
749 else
750 indexForDelayedInstr = S.getNumChoices();
751 }
752 }
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000753 else if (S.schedInfo.breaksIssueGroup(nextNode->getOpCode()))
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000754 {
755 if (indexForBreakingNode < S.nslots)
756 // have a breaking instruction already so throw this one away
757 nextNode = NULL;
758 else
759 indexForBreakingNode = S.getNumChoices();
760 }
761
762 if (nextNode != NULL)
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000763 {
764 S.addChoice(nextNode);
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000765
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000766 if (S.schedInfo.isSingleIssue(nextNode->getOpCode()))
767 {
768 assert(S.getNumChoices() == 1 &&
769 "Prioritizer returned invalid instr for this cycle!");
770 break;
771 }
772 }
773
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000774 if (indexForDelayedInstr < S.nslots)
775 break; // leave the rest for delay slots
776 }
777
778 assert(S.getNumChoices() <= S.nslots);
779 assert(! (indexForDelayedInstr < S.nslots &&
780 indexForBreakingNode < S.nslots) && "Cannot have both in a cycle");
781
782 // Assign each chosen instruction to all possible slots for that instr.
783 // But if only one instruction was chosen, put it only in the first
784 // feasible slot; no more analysis will be needed.
785 //
786 if (indexForDelayedInstr >= S.nslots &&
787 indexForBreakingNode >= S.nslots)
788 { // No instructions that break the issue group or that have delay slots.
789 // This is the common case, so handle it separately for efficiency.
790
791 if (S.getNumChoices() == 1)
792 {
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000793 MachineOpCode opCode = S.getChoice(0)->getOpCode();
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000794 unsigned int s;
795 for (s=startSlot; s < S.nslots; s++)
796 if (S.schedInfo.instrCanUseSlot(opCode, s))
797 break;
798 assert(s < S.nslots && "No feasible slot for this opCode?");
799 S.addChoiceToSlot(s, S.getChoice(0));
800 }
801 else
802 {
803 for (unsigned i=0; i < S.getNumChoices(); i++)
804 {
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000805 MachineOpCode opCode = S.getChoice(i)->getOpCode();
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000806 for (unsigned int s=startSlot; s < S.nslots; s++)
807 if (S.schedInfo.instrCanUseSlot(opCode, s))
808 S.addChoiceToSlot(s, S.getChoice(i));
809 }
810 }
811 }
812 else if (indexForDelayedInstr < S.nslots)
813 {
814 // There is an instruction that needs delay slots.
815 // Try to assign that instruction to a higher slot than any other
816 // instructions in the group, so that its delay slots can go
817 // right after it.
818 //
819
820 assert(indexForDelayedInstr == S.getNumChoices() - 1 &&
821 "Instruction with delay slots should be last choice!");
822 assert(delaySlotInfo != NULL && "No delay slot info for instr?");
823
824 const SchedGraphNode* delayedNode = S.getChoice(indexForDelayedInstr);
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000825 MachineOpCode delayOpCode = delayedNode->getOpCode();
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000826 unsigned ndelays= S.getInstrInfo().getNumDelaySlots(delayOpCode);
827
828 unsigned delayedNodeSlot = S.nslots;
829 int highestSlotUsed;
830
831 // Find the last possible slot for the delayed instruction that leaves
832 // at least `d' slots vacant after it (d = #delay slots)
833 for (int s = S.nslots-ndelays-1; s >= (int) startSlot; s--)
834 if (S.schedInfo.instrCanUseSlot(delayOpCode, s))
835 {
836 delayedNodeSlot = s;
837 break;
838 }
839
840 highestSlotUsed = -1;
841 for (unsigned i=0; i < S.getNumChoices() - 1; i++)
842 {
843 // Try to assign every other instruction to a lower numbered
844 // slot than delayedNodeSlot.
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000845 MachineOpCode opCode =S.getChoice(i)->getOpCode();
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000846 bool noSlotFound = true;
847 unsigned int s;
848 for (s=startSlot; s < delayedNodeSlot; s++)
849 if (S.schedInfo.instrCanUseSlot(opCode, s))
850 {
851 S.addChoiceToSlot(s, S.getChoice(i));
852 noSlotFound = false;
853 }
854
855 // No slot before `delayedNodeSlot' was found for this opCode
856 // Use a later slot, and allow some delay slots to fall in
857 // the next cycle.
858 if (noSlotFound)
859 for ( ; s < S.nslots; s++)
860 if (S.schedInfo.instrCanUseSlot(opCode, s))
861 {
862 S.addChoiceToSlot(s, S.getChoice(i));
863 break;
864 }
865
866 assert(s < S.nslots && "No feasible slot for instruction?");
867
Chris Lattner697954c2002-01-20 22:54:45 +0000868 highestSlotUsed = std::max(highestSlotUsed, (int) s);
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000869 }
870
871 assert(highestSlotUsed <= (int) S.nslots-1 && "Invalid slot used?");
872
873 // We will put the delayed node in the first slot after the
874 // highest slot used. But we just mark that for now, and
875 // schedule it separately because we want to schedule the delay
876 // slots for the node at the same time.
877 cycles_t dcycle = S.getTime();
878 unsigned int dslot = highestSlotUsed + 1;
879 if (dslot == S.nslots)
880 {
881 dslot = 0;
882 ++dcycle;
883 }
884 delaySlotInfo->recordChosenSlot(dcycle, dslot);
885 getDelaySlotInfo = delaySlotInfo;
886 }
887 else
888 { // There is an instruction that breaks the issue group.
889 // For such an instruction, assign to the last possible slot in
890 // the current group, and then don't assign any other instructions
891 // to later slots.
892 assert(indexForBreakingNode < S.nslots);
893 const SchedGraphNode* breakingNode=S.getChoice(indexForBreakingNode);
894 unsigned breakingSlot = INT_MAX;
895 unsigned int nslotsToUse = S.nslots;
896
897 // Find the last possible slot for this instruction.
898 for (int s = S.nslots-1; s >= (int) startSlot; s--)
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000899 if (S.schedInfo.instrCanUseSlot(breakingNode->getOpCode(), s))
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000900 {
901 breakingSlot = s;
902 break;
903 }
904 assert(breakingSlot < S.nslots &&
905 "No feasible slot for `breakingNode'?");
906
907 // Higher priority instructions than the one that breaks the group:
908 // These can be assigned to all slots, but will be assigned only
909 // to earlier slots if possible.
910 for (unsigned i=0;
911 i < S.getNumChoices() && i < indexForBreakingNode; i++)
912 {
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000913 MachineOpCode opCode =S.getChoice(i)->getOpCode();
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000914
915 // If a higher priority instruction cannot be assigned to
916 // any earlier slots, don't schedule the breaking instruction.
917 //
918 bool foundLowerSlot = false;
919 nslotsToUse = S.nslots; // May be modified in the loop
920 for (unsigned int s=startSlot; s < nslotsToUse; s++)
921 if (S.schedInfo.instrCanUseSlot(opCode, s))
922 {
923 if (breakingSlot < S.nslots && s < breakingSlot)
924 {
925 foundLowerSlot = true;
926 nslotsToUse = breakingSlot; // RESETS LOOP UPPER BOUND!
927 }
928
929 S.addChoiceToSlot(s, S.getChoice(i));
930 }
931
932 if (!foundLowerSlot)
933 breakingSlot = INT_MAX; // disable breaking instr
934 }
935
936 // Assign the breaking instruction (if any) to a single slot
937 // Otherwise, just ignore the instruction. It will simply be
938 // scheduled in a later cycle.
939 if (breakingSlot < S.nslots)
940 {
941 S.addChoiceToSlot(breakingSlot, breakingNode);
942 nslotsToUse = breakingSlot;
943 }
944 else
945 nslotsToUse = S.nslots;
946
947 // For lower priority instructions than the one that breaks the
948 // group, only assign them to slots lower than the breaking slot.
949 // Otherwise, just ignore the instruction.
950 for (unsigned i=indexForBreakingNode+1; i < S.getNumChoices(); i++)
951 {
Vikram S. Advefb1a6c82001-11-09 02:14:20 +0000952 MachineOpCode opCode = S.getChoice(i)->getOpCode();
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000953 for (unsigned int s=startSlot; s < nslotsToUse; s++)
954 if (S.schedInfo.instrCanUseSlot(opCode, s))
955 S.addChoiceToSlot(s, S.getChoice(i));
956 }
957 } // endif (no delay slots and no breaking slots)
958
959 return S.getNumChoices();
960}
961
962
Vikram S. Advec5b46322001-09-30 23:43:34 +0000963static unsigned
964ChooseOneGroup(SchedulingManager& S)
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000965{
Vikram S. Advec5b46322001-09-30 23:43:34 +0000966 assert(S.schedPrio.getNumReady() > 0
967 && "Don't get here without ready instructions.");
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000968
Vikram S. Advec5b46322001-09-30 23:43:34 +0000969 cycles_t firstCycle = S.getTime();
970 DelaySlotInfo* getDelaySlotInfo = NULL;
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000971
Vikram S. Advec5b46322001-09-30 23:43:34 +0000972 // Choose up to `nslots' feasible instructions and their possible slots.
973 unsigned numIssued = FindSlotChoices(S, getDelaySlotInfo);
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000974
Vikram S. Advec5b46322001-09-30 23:43:34 +0000975 while (numIssued == 0)
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000976 {
Vikram S. Advec5b46322001-09-30 23:43:34 +0000977 S.updateTime(S.getTime()+1);
978 numIssued = FindSlotChoices(S, getDelaySlotInfo);
Vikram S. Adve0e1158f2001-08-28 23:07:19 +0000979 }
980
Vikram S. Advec5b46322001-09-30 23:43:34 +0000981 AssignInstructionsToSlots(S, numIssued);
982
983 if (getDelaySlotInfo != NULL)
984 numIssued += getDelaySlotInfo->scheduleDelayedNode(S);
985
986 // Print trace of scheduled instructions before newly ready ones
987 if (SchedDebugLevel >= Sched_PrintSchedTrace)
988 {
989 for (cycles_t c = firstCycle; c <= S.getTime(); c++)
990 {
Chris Lattner697954c2002-01-20 22:54:45 +0000991 cerr << " Cycle " << (long)c << " : Scheduled instructions:\n";
Vikram S. Advec5b46322001-09-30 23:43:34 +0000992 const InstrGroup* igroup = S.isched.getIGroup(c);
993 for (unsigned int s=0; s < S.nslots; s++)
994 {
Chris Lattner697954c2002-01-20 22:54:45 +0000995 cerr << " ";
Vikram S. Advec5b46322001-09-30 23:43:34 +0000996 if ((*igroup)[s] != NULL)
Chris Lattner697954c2002-01-20 22:54:45 +0000997 cerr << * ((*igroup)[s])->getMachineInstr() << "\n";
Vikram S. Advec5b46322001-09-30 23:43:34 +0000998 else
Chris Lattner697954c2002-01-20 22:54:45 +0000999 cerr << "<none>\n";
Vikram S. Advec5b46322001-09-30 23:43:34 +00001000 }
1001 }
1002 }
1003
1004 return numIssued;
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001005}
1006
1007
Vikram S. Advec5b46322001-09-30 23:43:34 +00001008static void
1009ForwardListSchedule(SchedulingManager& S)
1010{
1011 unsigned N;
1012 const SchedGraphNode* node;
1013
1014 S.schedPrio.initialize();
1015
1016 while ((N = S.schedPrio.getNumReady()) > 0)
1017 {
1018 cycles_t nextCycle = S.getTime();
1019
1020 // Choose one group of instructions for a cycle, plus any delay slot
1021 // instructions (which may overflow into successive cycles).
1022 // This will advance S.getTime() to the last cycle in which
1023 // instructions are actually issued.
1024 //
1025 unsigned numIssued = ChooseOneGroup(S);
1026 assert(numIssued > 0 && "Deadlock in list scheduling algorithm?");
1027
1028 // Notify the priority manager of scheduled instructions and mark
1029 // any successors that may now be ready
1030 //
1031 for (cycles_t c = nextCycle; c <= S.getTime(); c++)
1032 {
1033 const InstrGroup* igroup = S.isched.getIGroup(c);
1034 for (unsigned int s=0; s < S.nslots; s++)
1035 if ((node = (*igroup)[s]) != NULL)
1036 {
1037 S.schedPrio.issuedReadyNodeAt(S.getTime(), node);
1038 MarkSuccessorsReady(S, node);
1039 }
1040 }
1041
1042 // Move to the next the next earliest cycle for which
1043 // an instruction can be issued, or the next earliest in which
1044 // one will be ready, or to the next cycle, whichever is latest.
1045 //
Chris Lattner697954c2002-01-20 22:54:45 +00001046 S.updateTime(std::max(S.getTime() + 1,
1047 std::max(S.getEarliestIssueTime(),
1048 S.schedPrio.getEarliestReadyTime())));
Vikram S. Advec5b46322001-09-30 23:43:34 +00001049 }
1050}
1051
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001052
1053//---------------------------------------------------------------------
1054// Code for filling delay slots for delayed terminator instructions
1055// (e.g., BRANCH and RETURN). Delay slots for non-terminator
1056// instructions (e.g., CALL) are not handled here because they almost
1057// always can be filled with instructions from the call sequence code
1058// before a call. That's preferable because we incur many tradeoffs here
1059// when we cannot find single-cycle instructions that can be reordered.
1060//----------------------------------------------------------------------
1061
Vikram S. Advec5b46322001-09-30 23:43:34 +00001062static bool
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001063NodeCanFillDelaySlot(const SchedulingManager& S,
1064 const SchedGraphNode* node,
1065 const SchedGraphNode* brNode,
1066 bool nodeIsPredecessor)
1067{
1068 assert(! node->isDummyNode());
1069
1070 // don't put a branch in the delay slot of another branch
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001071 if (S.getInstrInfo().isBranch(node->getOpCode()))
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001072 return false;
1073
1074 // don't put a single-issue instruction in the delay slot of a branch
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001075 if (S.schedInfo.isSingleIssue(node->getOpCode()))
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001076 return false;
1077
1078 // don't put a load-use dependence in the delay slot of a branch
1079 const MachineInstrInfo& mii = S.getInstrInfo();
1080
1081 for (SchedGraphNode::const_iterator EI = node->beginInEdges();
1082 EI != node->endInEdges(); ++EI)
1083 if (! (*EI)->getSrc()->isDummyNode()
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001084 && mii.isLoad((*EI)->getSrc()->getOpCode())
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001085 && (*EI)->getDepType() == SchedGraphEdge::CtrlDep)
1086 return false;
1087
1088 // for now, don't put an instruction that does not have operand
1089 // interlocks in the delay slot of a branch
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001090 if (! S.getInstrInfo().hasOperandInterlock(node->getOpCode()))
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001091 return false;
1092
1093 // Finally, if the instruction preceeds the branch, we make sure the
1094 // instruction can be reordered relative to the branch. We simply check
1095 // if the instr. has only 1 outgoing edge, viz., a CD edge to the branch.
1096 //
1097 if (nodeIsPredecessor)
1098 {
1099 bool onlyCDEdgeToBranch = true;
1100 for (SchedGraphNode::const_iterator OEI = node->beginOutEdges();
1101 OEI != node->endOutEdges(); ++OEI)
1102 if (! (*OEI)->getSink()->isDummyNode()
1103 && ((*OEI)->getSink() != brNode
1104 || (*OEI)->getDepType() != SchedGraphEdge::CtrlDep))
1105 {
1106 onlyCDEdgeToBranch = false;
1107 break;
1108 }
1109
1110 if (!onlyCDEdgeToBranch)
1111 return false;
1112 }
1113
1114 return true;
1115}
1116
1117
Vikram S. Advec5b46322001-09-30 23:43:34 +00001118static void
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001119MarkNodeForDelaySlot(SchedulingManager& S,
Vikram S. Advef0ba2802001-09-18 12:51:38 +00001120 SchedGraph* graph,
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001121 SchedGraphNode* node,
1122 const SchedGraphNode* brNode,
1123 bool nodeIsPredecessor)
1124{
1125 if (nodeIsPredecessor)
1126 { // If node is in the same basic block (i.e., preceeds brNode),
Vikram S. Advef0ba2802001-09-18 12:51:38 +00001127 // remove it and all its incident edges from the graph. Make sure we
1128 // add dummy edges for pred/succ nodes that become entry/exit nodes.
1129 graph->eraseIncidentEdges(node, /*addDummyEdges*/ true);
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001130 }
1131 else
1132 { // If the node was from a target block, add the node to the graph
1133 // and add a CD edge from brNode to node.
1134 assert(0 && "NOT IMPLEMENTED YET");
1135 }
1136
1137 DelaySlotInfo* dinfo = S.getDelaySlotInfoForInstr(brNode, /*create*/ true);
1138 dinfo->addDelayNode(node);
1139}
1140
1141
Vikram S. Advec5b46322001-09-30 23:43:34 +00001142void
1143FindUsefulInstructionsForDelaySlots(SchedulingManager& S,
1144 SchedGraphNode* brNode,
1145 vector<SchedGraphNode*>& sdelayNodeVec)
1146{
1147 const MachineInstrInfo& mii = S.getInstrInfo();
1148 unsigned ndelays =
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001149 mii.getNumDelaySlots(brNode->getOpCode());
Vikram S. Advec5b46322001-09-30 23:43:34 +00001150
1151 if (ndelays == 0)
1152 return;
1153
1154 sdelayNodeVec.reserve(ndelays);
1155
1156 // Use a separate vector to hold the feasible multi-cycle nodes.
1157 // These will be used if not enough single-cycle nodes are found.
1158 //
1159 vector<SchedGraphNode*> mdelayNodeVec;
1160
1161 for (sg_pred_iterator P = pred_begin(brNode);
1162 P != pred_end(brNode) && sdelayNodeVec.size() < ndelays; ++P)
1163 if (! (*P)->isDummyNode() &&
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001164 ! mii.isNop((*P)->getOpCode()) &&
Vikram S. Advec5b46322001-09-30 23:43:34 +00001165 NodeCanFillDelaySlot(S, *P, brNode, /*pred*/ true))
1166 {
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001167 if (mii.maxLatency((*P)->getOpCode()) > 1)
Vikram S. Advec5b46322001-09-30 23:43:34 +00001168 mdelayNodeVec.push_back(*P);
1169 else
1170 sdelayNodeVec.push_back(*P);
1171 }
1172
1173 // If not enough single-cycle instructions were found, select the
1174 // lowest-latency multi-cycle instructions and use them.
1175 // Note that this is the most efficient code when only 1 (or even 2)
1176 // values need to be selected.
1177 //
1178 while (sdelayNodeVec.size() < ndelays && mdelayNodeVec.size() > 0)
1179 {
1180 unsigned lmin =
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001181 mii.maxLatency(mdelayNodeVec[0]->getOpCode());
Vikram S. Advec5b46322001-09-30 23:43:34 +00001182 unsigned minIndex = 0;
1183 for (unsigned i=1; i < mdelayNodeVec.size(); i++)
1184 {
1185 unsigned li =
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001186 mii.maxLatency(mdelayNodeVec[i]->getOpCode());
Vikram S. Advec5b46322001-09-30 23:43:34 +00001187 if (lmin >= li)
1188 {
1189 lmin = li;
1190 minIndex = i;
1191 }
1192 }
1193 sdelayNodeVec.push_back(mdelayNodeVec[minIndex]);
1194 if (sdelayNodeVec.size() < ndelays) // avoid the last erase!
1195 mdelayNodeVec.erase(mdelayNodeVec.begin() + minIndex);
1196 }
1197}
1198
1199
1200// Remove the NOPs currently in delay slots from the graph.
1201// Mark instructions specified in sdelayNodeVec to replace them.
1202// If not enough useful instructions were found, mark the NOPs to be used
1203// for filling delay slots, otherwise, otherwise just discard them.
1204//
1205void
1206ReplaceNopsWithUsefulInstr(SchedulingManager& S,
1207 SchedGraphNode* node,
1208 vector<SchedGraphNode*> sdelayNodeVec,
1209 SchedGraph* graph)
1210{
Vikram S. Advefb8c0532001-10-22 13:49:27 +00001211 vector<SchedGraphNode*> nopNodeVec; // this will hold unused NOPs
Vikram S. Advec5b46322001-09-30 23:43:34 +00001212 const MachineInstrInfo& mii = S.getInstrInfo();
Vikram S. Advefb8c0532001-10-22 13:49:27 +00001213 const MachineInstr* brInstr = node->getMachineInstr();
1214 unsigned ndelays= mii.getNumDelaySlots(brInstr->getOpCode());
Vikram S. Advec5b46322001-09-30 23:43:34 +00001215 assert(ndelays > 0 && "Unnecessary call to replace NOPs");
1216
1217 // Remove the NOPs currently in delay slots from the graph.
1218 // If not enough useful instructions were found, use the NOPs to
1219 // fill delay slots, otherwise, just discard them.
Vikram S. Advefb8c0532001-10-22 13:49:27 +00001220 //
Vikram S. Adveaf00d482001-11-12 14:18:01 +00001221 unsigned int firstDelaySlotIdx = node->getOrigIndexInBB() + 1;
1222 MachineCodeForBasicBlock& bbMvec = node->getBB()->getMachineInstrVec();
1223 assert(bbMvec[firstDelaySlotIdx - 1] == brInstr &&
1224 "Incorrect instr. index in basic block for brInstr");
Vikram S. Advefb8c0532001-10-22 13:49:27 +00001225
1226 // First find all useful instructions already in the delay slots
1227 // and USE THEM. We'll throw away the unused alternatives below
1228 //
1229 for (unsigned i=firstDelaySlotIdx; i < firstDelaySlotIdx + ndelays; ++i)
Vikram S. Adveaf00d482001-11-12 14:18:01 +00001230 if (! mii.isNop(bbMvec[i]->getOpCode()))
Vikram S. Advefb8c0532001-10-22 13:49:27 +00001231 sdelayNodeVec.insert(sdelayNodeVec.begin(),
Vikram S. Adveaf00d482001-11-12 14:18:01 +00001232 graph->getGraphNodeForInstr(bbMvec[i]));
Vikram S. Advefb8c0532001-10-22 13:49:27 +00001233
1234 // Then find the NOPs and keep only as many as are needed.
1235 // Put the rest in nopNodeVec to be deleted.
1236 for (unsigned i=firstDelaySlotIdx; i < firstDelaySlotIdx + ndelays; ++i)
Vikram S. Adveaf00d482001-11-12 14:18:01 +00001237 if (mii.isNop(bbMvec[i]->getOpCode()))
Vikram S. Advefb8c0532001-10-22 13:49:27 +00001238 if (sdelayNodeVec.size() < ndelays)
Vikram S. Adveaf00d482001-11-12 14:18:01 +00001239 sdelayNodeVec.push_back(graph->getGraphNodeForInstr(bbMvec[i]));
Vikram S. Advefb8c0532001-10-22 13:49:27 +00001240 else
Vikram S. Adveaf00d482001-11-12 14:18:01 +00001241 nopNodeVec.push_back(graph->getGraphNodeForInstr(bbMvec[i]));
Vikram S. Advefb8c0532001-10-22 13:49:27 +00001242
1243 assert(sdelayNodeVec.size() >= ndelays);
1244
1245 // If some delay slots were already filled, throw away that many new choices
1246 if (sdelayNodeVec.size() > ndelays)
1247 sdelayNodeVec.resize(ndelays);
Vikram S. Advec5b46322001-09-30 23:43:34 +00001248
1249 // Mark the nodes chosen for delay slots. This removes them from the graph.
1250 for (unsigned i=0; i < sdelayNodeVec.size(); i++)
1251 MarkNodeForDelaySlot(S, graph, sdelayNodeVec[i], node, true);
1252
1253 // And remove the unused NOPs from the graph.
1254 for (unsigned i=0; i < nopNodeVec.size(); i++)
1255 graph->eraseIncidentEdges(nopNodeVec[i], /*addDummyEdges*/ true);
1256}
1257
1258
1259// For all delayed instructions, choose instructions to put in the delay
1260// slots and pull those out of the graph. Mark them for the delay slots
1261// in the DelaySlotInfo object for that graph node. If no useful work
1262// is found for a delay slot, use the NOP that is currently in that slot.
1263//
1264// We try to fill the delay slots with useful work for all instructions
Vikram S. Adve6db77c52001-10-10 20:58:11 +00001265// EXCEPT CALLS AND RETURNS.
1266// For CALLs and RETURNs, it is nearly always possible to use one of the
Vikram S. Advec5b46322001-09-30 23:43:34 +00001267// call sequence instrs and putting anything else in the delay slot could be
Vikram S. Adve6db77c52001-10-10 20:58:11 +00001268// suboptimal. Also, it complicates generating the calling sequence code in
1269// regalloc.
Vikram S. Advec5b46322001-09-30 23:43:34 +00001270//
1271static void
1272ChooseInstructionsForDelaySlots(SchedulingManager& S,
Chris Lattner3462cae2002-02-03 07:28:30 +00001273 const BasicBlock *bb,
1274 SchedGraph *graph)
Vikram S. Advec5b46322001-09-30 23:43:34 +00001275{
1276 const MachineInstrInfo& mii = S.getInstrInfo();
Chris Lattner455889a2002-02-12 22:39:50 +00001277 const Instruction *termInstr = (Instruction*)bb->getTerminator();
Chris Lattner3462cae2002-02-03 07:28:30 +00001278 MachineCodeForInstruction &termMvec=MachineCodeForInstruction::get(termInstr);
Vikram S. Advec5b46322001-09-30 23:43:34 +00001279 vector<SchedGraphNode*> delayNodeVec;
Vikram S. Adve6db77c52001-10-10 20:58:11 +00001280 const MachineInstr* brInstr = NULL;
Vikram S. Advec5b46322001-09-30 23:43:34 +00001281
Vikram S. Adve6db77c52001-10-10 20:58:11 +00001282 if (termInstr->getOpcode() != Instruction::Ret)
Vikram S. Advec5b46322001-09-30 23:43:34 +00001283 {
Vikram S. Adve6db77c52001-10-10 20:58:11 +00001284 // To find instructions that need delay slots without searching the full
1285 // machine code, we assume that the only delayed instructions are CALLs
1286 // or instructions generated for the terminator inst.
1287 // Find the first branch instr in the sequence of machine instrs for term
1288 //
1289 unsigned first = 0;
1290 while (first < termMvec.size() &&
1291 ! mii.isBranch(termMvec[first]->getOpCode()))
1292 {
1293 ++first;
1294 }
1295 assert(first < termMvec.size() &&
1296 "No branch instructions for BR? Ok, but weird! Delete assertion.");
1297
1298 brInstr = (first < termMvec.size())? termMvec[first] : NULL;
1299
1300 // Compute a vector of the nodes chosen for delay slots and then
1301 // mark delay slots to replace NOPs with these useful instructions.
1302 //
1303 if (brInstr != NULL)
1304 {
1305 SchedGraphNode* brNode = graph->getGraphNodeForInstr(brInstr);
1306 FindUsefulInstructionsForDelaySlots(S, brNode, delayNodeVec);
1307 ReplaceNopsWithUsefulInstr(S, brNode, delayNodeVec, graph);
1308 }
Vikram S. Advec5b46322001-09-30 23:43:34 +00001309 }
1310
1311 // Also mark delay slots for other delayed instructions to hold NOPs.
1312 // Simply passing in an empty delayNodeVec will have this effect.
1313 //
1314 delayNodeVec.clear();
1315 const MachineCodeForBasicBlock& bbMvec = bb->getMachineInstrVec();
1316 for (unsigned i=0; i < bbMvec.size(); i++)
1317 if (bbMvec[i] != brInstr &&
1318 mii.getNumDelaySlots(bbMvec[i]->getOpCode()) > 0)
1319 {
1320 SchedGraphNode* node = graph->getGraphNodeForInstr(bbMvec[i]);
1321 ReplaceNopsWithUsefulInstr(S, node, delayNodeVec, graph);
1322 }
1323}
1324
1325
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001326//
1327// Schedule the delayed branch and its delay slots
1328//
Vikram S. Advec5b46322001-09-30 23:43:34 +00001329unsigned
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001330DelaySlotInfo::scheduleDelayedNode(SchedulingManager& S)
1331{
1332 assert(delayedNodeSlotNum < S.nslots && "Illegal slot for branch");
1333 assert(S.isched.getInstr(delayedNodeSlotNum, delayedNodeCycle) == NULL
1334 && "Slot for branch should be empty");
1335
1336 unsigned int nextSlot = delayedNodeSlotNum;
1337 cycles_t nextTime = delayedNodeCycle;
1338
1339 S.scheduleInstr(brNode, nextSlot, nextTime);
1340
1341 for (unsigned d=0; d < ndelays; d++)
1342 {
1343 ++nextSlot;
1344 if (nextSlot == S.nslots)
1345 {
1346 nextSlot = 0;
1347 nextTime++;
1348 }
1349
1350 // Find the first feasible instruction for this delay slot
1351 // Note that we only check for issue restrictions here.
1352 // We do *not* check for flow dependences but rely on pipeline
1353 // interlocks to resolve them. Machines without interlocks
1354 // will require this code to be modified.
1355 for (unsigned i=0; i < delayNodeVec.size(); i++)
1356 {
1357 const SchedGraphNode* dnode = delayNodeVec[i];
1358 if ( ! S.isScheduled(dnode)
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001359 && S.schedInfo.instrCanUseSlot(dnode->getOpCode(), nextSlot)
1360 && instrIsFeasible(S, dnode->getOpCode()))
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001361 {
Vikram S. Advefb1a6c82001-11-09 02:14:20 +00001362 assert(S.getInstrInfo().hasOperandInterlock(dnode->getOpCode())
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001363 && "Instructions without interlocks not yet supported "
1364 "when filling branch delay slots");
1365 S.scheduleInstr(dnode, nextSlot, nextTime);
1366 break;
1367 }
1368 }
1369 }
1370
1371 // Update current time if delay slots overflowed into later cycles.
1372 // Do this here because we know exactly which cycle is the last cycle
1373 // that contains delay slots. The next loop doesn't compute that.
1374 if (nextTime > S.getTime())
1375 S.updateTime(nextTime);
1376
1377 // Now put any remaining instructions in the unfilled delay slots.
1378 // This could lead to suboptimal performance but needed for correctness.
1379 nextSlot = delayedNodeSlotNum;
1380 nextTime = delayedNodeCycle;
1381 for (unsigned i=0; i < delayNodeVec.size(); i++)
1382 if (! S.isScheduled(delayNodeVec[i]))
1383 {
1384 do { // find the next empty slot
1385 ++nextSlot;
1386 if (nextSlot == S.nslots)
1387 {
1388 nextSlot = 0;
1389 nextTime++;
1390 }
1391 } while (S.isched.getInstr(nextSlot, nextTime) != NULL);
1392
1393 S.scheduleInstr(delayNodeVec[i], nextSlot, nextTime);
1394 break;
1395 }
Vikram S. Advec5b46322001-09-30 23:43:34 +00001396
1397 return 1 + ndelays;
Vikram S. Adve0e1158f2001-08-28 23:07:19 +00001398}
1399
Vikram S. Advec5b46322001-09-30 23:43:34 +00001400
1401// Check if the instruction would conflict with instructions already
1402// chosen for the current cycle
1403//
1404static inline bool
1405ConflictsWithChoices(const SchedulingManager& S,
1406 MachineOpCode opCode)
1407{
1408 // Check if the instruction must issue by itself, and some feasible
1409 // choices have already been made for this cycle
1410 if (S.getNumChoices() > 0 && S.schedInfo.isSingleIssue(opCode))
1411 return true;
1412
1413 // For each class that opCode belongs to, check if there are too many
1414 // instructions of that class.
1415 //
1416 const InstrSchedClass sc = S.schedInfo.getSchedClass(opCode);
1417 return (S.getNumChoicesInClass(sc) == S.schedInfo.getMaxIssueForClass(sc));
1418}
1419
1420
1421//************************* External Functions *****************************/
1422
1423
1424//---------------------------------------------------------------------------
1425// Function: ViolatesMinimumGap
1426//
1427// Purpose:
1428// Check minimum gap requirements relative to instructions scheduled in
1429// previous cycles.
1430// Note that we do not need to consider `nextEarliestIssueTime' here because
1431// that is also captured in the earliest start times for each opcode.
1432//---------------------------------------------------------------------------
1433
1434static inline bool
1435ViolatesMinimumGap(const SchedulingManager& S,
1436 MachineOpCode opCode,
1437 const cycles_t inCycle)
1438{
1439 return (inCycle < S.getEarliestStartTimeForOp(opCode));
1440}
1441
1442
1443//---------------------------------------------------------------------------
1444// Function: instrIsFeasible
1445//
1446// Purpose:
1447// Check if any issue restrictions would prevent the instruction from
1448// being issued in the current cycle
1449//---------------------------------------------------------------------------
1450
1451bool
1452instrIsFeasible(const SchedulingManager& S,
1453 MachineOpCode opCode)
1454{
1455 // skip the instruction if it cannot be issued due to issue restrictions
1456 // caused by previously issued instructions
1457 if (ViolatesMinimumGap(S, opCode, S.getTime()))
1458 return false;
1459
1460 // skip the instruction if it cannot be issued due to issue restrictions
1461 // caused by previously chosen instructions for the current cycle
1462 if (ConflictsWithChoices(S, opCode))
1463 return false;
1464
1465 return true;
1466}
1467
1468//---------------------------------------------------------------------------
1469// Function: ScheduleInstructionsWithSSA
1470//
1471// Purpose:
1472// Entry point for instruction scheduling on SSA form.
1473// Schedules the machine instructions generated by instruction selection.
1474// Assumes that register allocation has not been done, i.e., operands
1475// are still in SSA form.
1476//---------------------------------------------------------------------------
1477
Chris Lattner9adb7ad2002-02-04 20:02:16 +00001478namespace {
Chris Lattnerf57b8452002-04-27 06:56:12 +00001479 class InstructionSchedulingWithSSA : public FunctionPass {
Vikram S. Adve802cec42002-03-24 03:44:55 +00001480 const TargetMachine &target;
Chris Lattner9adb7ad2002-02-04 20:02:16 +00001481 public:
Vikram S. Adve802cec42002-03-24 03:44:55 +00001482 inline InstructionSchedulingWithSSA(const TargetMachine &T) : target(T) {}
Chris Lattner96c466b2002-04-29 14:57:45 +00001483
1484 const char *getPassName() const { return "Instruction Scheduling"; }
Vikram S. Adve802cec42002-03-24 03:44:55 +00001485
Chris Lattnerf57b8452002-04-27 06:56:12 +00001486 // getAnalysisUsage - We use LiveVarInfo...
1487 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
Chris Lattner483e14e2002-04-27 07:27:19 +00001488 AU.addRequired(FunctionLiveVarInfo::ID);
Vikram S. Advec5b46322001-09-30 23:43:34 +00001489 }
Vikram S. Adve802cec42002-03-24 03:44:55 +00001490
Chris Lattnerf57b8452002-04-27 06:56:12 +00001491 bool runOnFunction(Function *F);
Chris Lattner9adb7ad2002-02-04 20:02:16 +00001492 };
1493} // end anonymous namespace
1494
Vikram S. Adve802cec42002-03-24 03:44:55 +00001495
1496bool
Chris Lattnerf57b8452002-04-27 06:56:12 +00001497InstructionSchedulingWithSSA::runOnFunction(Function *M)
Vikram S. Adve802cec42002-03-24 03:44:55 +00001498{
1499 if (SchedDebugLevel == Sched_Disable)
1500 return false;
1501
1502 SchedGraphSet graphSet(M, target);
1503
1504 if (SchedDebugLevel >= Sched_PrintSchedGraphs)
1505 {
1506 cerr << "\n*** SCHEDULING GRAPHS FOR INSTRUCTION SCHEDULING\n";
1507 graphSet.dump();
1508 }
1509
1510 for (SchedGraphSet::const_iterator GI=graphSet.begin(), GE=graphSet.end();
1511 GI != GE; ++GI)
1512 {
1513 SchedGraph* graph = (*GI);
1514 const vector<const BasicBlock*> &bbvec = graph->getBasicBlocks();
1515 assert(bbvec.size() == 1 && "Cannot schedule multiple basic blocks");
1516 const BasicBlock* bb = bbvec[0];
1517
1518 if (SchedDebugLevel >= Sched_PrintSchedTrace)
1519 cerr << "\n*** TRACE OF INSTRUCTION SCHEDULING OPERATIONS\n\n";
1520
1521 // expensive!
Chris Lattner483e14e2002-04-27 07:27:19 +00001522 SchedPriorities schedPrio(M, graph,getAnalysis<FunctionLiveVarInfo>());
Vikram S. Adve802cec42002-03-24 03:44:55 +00001523 SchedulingManager S(target, graph, schedPrio);
1524
1525 ChooseInstructionsForDelaySlots(S, bb, graph); // modifies graph
1526
1527 ForwardListSchedule(S); // computes schedule in S
1528
1529 RecordSchedule(bb, S); // records schedule in BB
1530 }
1531
1532 if (SchedDebugLevel >= Sched_PrintMachineCode)
1533 {
1534 cerr << "\n*** Machine instructions after INSTRUCTION SCHEDULING\n";
1535 MachineCodeForMethod::get(M).dump();
1536 }
1537
1538 return false;
1539}
1540
1541
Chris Lattnerf57b8452002-04-27 06:56:12 +00001542Pass *createInstructionSchedulingWithSSAPass(const TargetMachine &tgt) {
Vikram S. Adve802cec42002-03-24 03:44:55 +00001543 return new InstructionSchedulingWithSSA(tgt);
Vikram S. Advec5b46322001-09-30 23:43:34 +00001544}