Create a new #include "Support/..." directory structure to move things
[oota-llvm.git] / lib / Target / SparcV9 / InstrSched / InstrScheduling.cpp
1 // $Id$
2 //***************************************************************************
3 // File:
4 //      InstrScheduling.cpp
5 // 
6 // Purpose:
7 //      
8 // History:
9 //      7/23/01  -  Vikram Adve  -  Created
10 //**************************************************************************/
11
12
13 //************************* User Include Files *****************************/
14
15 #include "llvm/CodeGen/InstrScheduling.h"
16 #include "llvm/Analysis/LiveVar/BBLiveVar.h"
17 #include "llvm/CodeGen/MachineInstr.h"
18 #include "llvm/Instruction.h"
19 #include "Support/CommandLine.h"
20 #include "SchedPriorities.h"
21 #include <hash_set>
22 #include <algorithm>
23 #include <iterator>
24
25
26 //************************* External Data Types *****************************/
27
28 cl::Enum<enum SchedDebugLevel_t> SchedDebugLevel("dsched", cl::NoFlags,
29   "enable instruction scheduling debugging information",
30   clEnumValN(Sched_NoDebugInfo,      "n", "disable debug output"),
31   clEnumValN(Sched_PrintMachineCode, "y", "print machine code after scheduling"),
32   clEnumValN(Sched_PrintSchedTrace,  "t", "print trace of scheduling actions"),
33   clEnumValN(Sched_PrintSchedGraphs, "g", "print scheduling graphs"), 0);
34
35
36 //************************* Internal Data Types *****************************/
37
38 class InstrSchedule;
39 class SchedulingManager;
40 class DelaySlotInfo;
41
42
43 //----------------------------------------------------------------------
44 // class InstrGroup:
45 // 
46 // Represents a group of instructions scheduled to be issued
47 // in a single cycle.
48 //----------------------------------------------------------------------
49
50 class InstrGroup: public NonCopyable {
51 public:
52   inline const SchedGraphNode* operator[](unsigned int slotNum) const {
53     assert(slotNum  < group.size());
54     return group[slotNum];
55   }
56   
57 private:
58   friend class InstrSchedule;
59   
60   inline void   addInstr(const SchedGraphNode* node, unsigned int slotNum) {
61     assert(slotNum < group.size());
62     group[slotNum] = node;
63   }
64   
65   /*ctor*/      InstrGroup(unsigned int nslots)
66     : group(nslots, NULL) {}
67   
68   /*ctor*/      InstrGroup();           // disable: DO NOT IMPLEMENT
69   
70 private:
71   vector<const SchedGraphNode*> group;
72 };
73
74
75 //----------------------------------------------------------------------
76 // class ScheduleIterator:
77 // 
78 // Iterates over the machine instructions in the for a single basic block.
79 // The schedule is represented by an InstrSchedule object.
80 //----------------------------------------------------------------------
81
82 template<class _NodeType>
83 class ScheduleIterator: public std::forward_iterator<_NodeType, ptrdiff_t> {
84 private:
85   unsigned cycleNum;
86   unsigned slotNum;
87   const InstrSchedule& S;
88 public:
89   typedef ScheduleIterator<_NodeType> _Self;
90   
91   /*ctor*/ inline ScheduleIterator(const InstrSchedule& _schedule,
92                                    unsigned _cycleNum,
93                                    unsigned _slotNum)
94     : cycleNum(_cycleNum), slotNum(_slotNum), S(_schedule) {
95     skipToNextInstr(); 
96   }
97   
98   /*ctor*/ inline ScheduleIterator(const _Self& x)
99     : cycleNum(x.cycleNum), slotNum(x.slotNum), S(x.S) {}
100   
101   inline bool operator==(const _Self& x) const {
102     return (slotNum == x.slotNum && cycleNum== x.cycleNum && &S==&x.S);
103   }
104   
105   inline bool operator!=(const _Self& x) const { return !operator==(x); }
106   
107   inline _NodeType* operator*() const {
108     assert(cycleNum < S.groups.size());
109     return (*S.groups[cycleNum])[slotNum];
110   }
111   inline _NodeType* operator->() const { return operator*(); }
112   
113          _Self& operator++();                           // Preincrement
114   inline _Self operator++(int) {                        // Postincrement
115     _Self tmp(*this); ++*this; return tmp; 
116   }
117   
118   static _Self begin(const InstrSchedule& _schedule);
119   static _Self end(  const InstrSchedule& _schedule);
120   
121 private:
122   inline _Self& operator=(const _Self& x); // DISABLE -- DO NOT IMPLEMENT
123   void  skipToNextInstr();
124 };
125
126
127 //----------------------------------------------------------------------
128 // class InstrSchedule:
129 // 
130 // Represents the schedule of machine instructions for a single basic block.
131 //----------------------------------------------------------------------
132
133 class InstrSchedule: public NonCopyable {
134 private:
135   const unsigned int nslots;
136   unsigned int numInstr;
137   vector<InstrGroup*> groups;           // indexed by cycle number
138   vector<cycles_t> startTime;           // indexed by node id
139   
140 public: // iterators
141   typedef ScheduleIterator<SchedGraphNode> iterator;
142   typedef ScheduleIterator<const SchedGraphNode> const_iterator;
143   
144         iterator begin();
145   const_iterator begin() const;
146         iterator end();
147   const_iterator end()   const;
148   
149 public: // constructors and destructor
150   /*ctor*/              InstrSchedule   (unsigned int _nslots,
151                                          unsigned int _numNodes);
152   /*dtor*/              ~InstrSchedule  ();
153   
154 public: // accessor functions to query chosen schedule
155   const SchedGraphNode* getInstr        (unsigned int slotNum,
156                                          cycles_t c) const {
157     const InstrGroup* igroup = this->getIGroup(c);
158     return (igroup == NULL)? NULL : (*igroup)[slotNum];
159   }
160   
161   inline InstrGroup*    getIGroup       (cycles_t c) {
162     if (c >= groups.size())
163       groups.resize(c+1);
164     if (groups[c] == NULL)
165       groups[c] = new InstrGroup(nslots);
166     return groups[c];
167   }
168   
169   inline const InstrGroup* getIGroup    (cycles_t c) const {
170     assert(c < groups.size());
171     return groups[c];
172   }
173   
174   inline cycles_t       getStartTime    (unsigned int nodeId) const {
175     assert(nodeId < startTime.size());
176     return startTime[nodeId];
177   }
178   
179   unsigned int          getNumInstructions() const {
180     return numInstr;
181   }
182   
183   inline void           scheduleInstr   (const SchedGraphNode* node,
184                                          unsigned int slotNum,
185                                          cycles_t cycle) {
186     InstrGroup* igroup = this->getIGroup(cycle);
187     assert((*igroup)[slotNum] == NULL &&  "Slot already filled?");
188     igroup->addInstr(node, slotNum);
189     assert(node->getNodeId() < startTime.size());
190     startTime[node->getNodeId()] = cycle;
191     ++numInstr;
192   }
193   
194 private:
195   friend class iterator;
196   friend class const_iterator;
197   /*ctor*/      InstrSchedule   ();     // Disable: DO NOT IMPLEMENT.
198 };
199
200
201 /*ctor*/
202 InstrSchedule::InstrSchedule(unsigned int _nslots, unsigned int _numNodes)
203   : nslots(_nslots),
204     numInstr(0),
205     groups(2 * _numNodes / _nslots),            // 2 x lower-bound for #cycles
206     startTime(_numNodes, (cycles_t) -1)         // set all to -1
207 {
208 }
209
210
211 /*dtor*/
212 InstrSchedule::~InstrSchedule()
213 {
214   for (unsigned c=0, NC=groups.size(); c < NC; c++)
215     if (groups[c] != NULL)
216       delete groups[c];                 // delete InstrGroup objects
217 }
218
219
220 template<class _NodeType>
221 inline 
222 void
223 ScheduleIterator<_NodeType>::skipToNextInstr()
224 {
225   while(cycleNum < S.groups.size() && S.groups[cycleNum] == NULL)
226     ++cycleNum;                 // skip cycles with no instructions
227   
228   while (cycleNum < S.groups.size() &&
229          (*S.groups[cycleNum])[slotNum] == NULL)
230     {
231       ++slotNum;
232       if (slotNum == S.nslots)
233         {
234           ++cycleNum;
235           slotNum = 0;
236           while(cycleNum < S.groups.size() && S.groups[cycleNum] == NULL)
237             ++cycleNum;                 // skip cycles with no instructions
238         }
239     }
240 }
241
242 template<class _NodeType>
243 inline 
244 ScheduleIterator<_NodeType>&
245 ScheduleIterator<_NodeType>::operator++()       // Preincrement
246 {
247   ++slotNum;
248   if (slotNum == S.nslots)
249     {
250       ++cycleNum;
251       slotNum = 0;
252     }
253   skipToNextInstr(); 
254   return *this;
255 }
256
257 template<class _NodeType>
258 ScheduleIterator<_NodeType>
259 ScheduleIterator<_NodeType>::begin(const InstrSchedule& _schedule)
260 {
261   return _Self(_schedule, 0, 0);
262 }
263
264 template<class _NodeType>
265 ScheduleIterator<_NodeType>
266 ScheduleIterator<_NodeType>::end(const InstrSchedule& _schedule)
267 {
268   return _Self(_schedule, _schedule.groups.size(), 0);
269 }
270
271 InstrSchedule::iterator
272 InstrSchedule::begin()
273 {
274   return iterator::begin(*this);
275 }
276
277 InstrSchedule::const_iterator
278 InstrSchedule::begin() const
279 {
280   return const_iterator::begin(*this);
281 }
282
283 InstrSchedule::iterator
284 InstrSchedule::end()
285 {
286   return iterator::end(*this);
287 }
288
289 InstrSchedule::const_iterator
290 InstrSchedule::end() const
291 {
292   return const_iterator::end(  *this);
293 }
294
295
296 //----------------------------------------------------------------------
297 // class DelaySlotInfo:
298 // 
299 // Record information about delay slots for a single branch instruction.
300 // Delay slots are simply indexed by slot number 1 ... numDelaySlots
301 //----------------------------------------------------------------------
302
303 class DelaySlotInfo: public NonCopyable {
304 private:
305   const SchedGraphNode* brNode;
306   unsigned int ndelays;
307   vector<const SchedGraphNode*> delayNodeVec;
308   cycles_t delayedNodeCycle;
309   unsigned int delayedNodeSlotNum;
310   
311 public:
312   /*ctor*/      DelaySlotInfo           (const SchedGraphNode* _brNode,
313                                          unsigned _ndelays)
314     : brNode(_brNode), ndelays(_ndelays),
315       delayedNodeCycle(0), delayedNodeSlotNum(0) {}
316   
317   inline unsigned getNumDelays  () {
318     return ndelays;
319   }
320   
321   inline const vector<const SchedGraphNode*>& getDelayNodeVec() {
322     return delayNodeVec;
323   }
324   
325   inline void   addDelayNode            (const SchedGraphNode* node) {
326     delayNodeVec.push_back(node);
327     assert(delayNodeVec.size() <= ndelays && "Too many delay slot instrs!");
328   }
329   
330   inline void   recordChosenSlot        (cycles_t cycle, unsigned slotNum) {
331     delayedNodeCycle = cycle;
332     delayedNodeSlotNum = slotNum;
333   }
334   
335   unsigned      scheduleDelayedNode     (SchedulingManager& S);
336 };
337
338
339 //----------------------------------------------------------------------
340 // class SchedulingManager:
341 // 
342 // Represents the schedule of machine instructions for a single basic block.
343 //----------------------------------------------------------------------
344
345 class SchedulingManager: public NonCopyable {
346 public: // publicly accessible data members
347   const unsigned int nslots;
348   const MachineSchedInfo& schedInfo;
349   SchedPriorities& schedPrio;
350   InstrSchedule isched;
351   
352 private:
353   unsigned int totalInstrCount;
354   cycles_t curTime;
355   cycles_t nextEarliestIssueTime;               // next cycle we can issue
356   vector<hash_set<const SchedGraphNode*> > choicesForSlot; // indexed by slot#
357   vector<const SchedGraphNode*> choiceVec;      // indexed by node ptr
358   vector<int> numInClass;                       // indexed by sched class
359   vector<cycles_t> nextEarliestStartTime;       // indexed by opCode
360   hash_map<const SchedGraphNode*, DelaySlotInfo*> delaySlotInfoForBranches;
361                                                 // indexed by branch node ptr 
362   
363 public:
364   /*ctor*/      SchedulingManager       (const TargetMachine& _target,
365                                          const SchedGraph* graph,
366                                          SchedPriorities& schedPrio);
367   /*dtor*/      ~SchedulingManager      () {}
368   
369   //----------------------------------------------------------------------
370   // Simplify access to the machine instruction info
371   //----------------------------------------------------------------------
372   
373   inline const MachineInstrInfo& getInstrInfo   () const {
374     return schedInfo.getInstrInfo();
375   }
376   
377   //----------------------------------------------------------------------
378   // Interface for checking and updating the current time
379   //----------------------------------------------------------------------
380   
381   inline cycles_t       getTime                 () const {
382     return curTime;
383   }
384   
385   inline cycles_t       getEarliestIssueTime() const {
386     return nextEarliestIssueTime;
387   }
388   
389   inline cycles_t       getEarliestStartTimeForOp(MachineOpCode opCode) const {
390     assert(opCode < (int) nextEarliestStartTime.size());
391     return nextEarliestStartTime[opCode];
392   }
393   
394   // Update current time to specified cycle
395   inline void   updateTime              (cycles_t c) {
396     curTime = c;
397     schedPrio.updateTime(c);
398   }
399   
400   //----------------------------------------------------------------------
401   // Functions to manage the choices for the current cycle including:
402   // -- a vector of choices by priority (choiceVec)
403   // -- vectors of the choices for each instruction slot (choicesForSlot[])
404   // -- number of choices in each sched class, used to check issue conflicts
405   //    between choices for a single cycle
406   //----------------------------------------------------------------------
407   
408   inline unsigned int getNumChoices     () const {
409     return choiceVec.size();
410   }
411   
412   inline unsigned getNumChoicesInClass  (const InstrSchedClass& sc) const {
413     assert(sc < (int) numInClass.size() && "Invalid op code or sched class!");
414     return numInClass[sc];
415   }
416   
417   inline const SchedGraphNode* getChoice(unsigned int i) const {
418     // assert(i < choiceVec.size());    don't check here.
419     return choiceVec[i];
420   }
421   
422   inline hash_set<const SchedGraphNode*>& getChoicesForSlot(unsigned slotNum) {
423     assert(slotNum < nslots);
424     return choicesForSlot[slotNum];
425   }
426   
427   inline void   addChoice               (const SchedGraphNode* node) {
428     // Append the instruction to the vector of choices for current cycle.
429     // Increment numInClass[c] for the sched class to which the instr belongs.
430     choiceVec.push_back(node);
431     const InstrSchedClass& sc = schedInfo.getSchedClass(node->getOpCode());
432     assert(sc < (int) numInClass.size());
433     numInClass[sc]++;
434   }
435   
436   inline void   addChoiceToSlot         (unsigned int slotNum,
437                                          const SchedGraphNode* node) {
438     // Add the instruction to the choice set for the specified slot
439     assert(slotNum < nslots);
440     choicesForSlot[slotNum].insert(node);
441   }
442   
443   inline void   resetChoices            () {
444     choiceVec.clear();
445     for (unsigned int s=0; s < nslots; s++)
446       choicesForSlot[s].clear();
447     for (unsigned int c=0; c < numInClass.size(); c++)
448       numInClass[c] = 0;
449   }
450   
451   //----------------------------------------------------------------------
452   // Code to query and manage the partial instruction schedule so far
453   //----------------------------------------------------------------------
454   
455   inline unsigned int   getNumScheduled () const {
456     return isched.getNumInstructions();
457   }
458   
459   inline unsigned int   getNumUnscheduled() const {
460     return totalInstrCount - isched.getNumInstructions();
461   }
462   
463   inline bool           isScheduled     (const SchedGraphNode* node) const {
464     return (isched.getStartTime(node->getNodeId()) >= 0);
465   }
466   
467   inline void   scheduleInstr           (const SchedGraphNode* node,
468                                          unsigned int slotNum,
469                                          cycles_t cycle)
470   {
471     assert(! isScheduled(node) && "Instruction already scheduled?");
472     
473     // add the instruction to the schedule
474     isched.scheduleInstr(node, slotNum, cycle);
475     
476     // update the earliest start times of all nodes that conflict with `node'
477     // and the next-earliest time anything can issue if `node' causes bubbles
478     updateEarliestStartTimes(node, cycle);
479     
480     // remove the instruction from the choice sets for all slots
481     for (unsigned s=0; s < nslots; s++)
482       choicesForSlot[s].erase(node);
483     
484     // and decrement the instr count for the sched class to which it belongs
485     const InstrSchedClass& sc = schedInfo.getSchedClass(node->getOpCode());
486     assert(sc < (int) numInClass.size());
487     numInClass[sc]--;
488   }
489
490   //----------------------------------------------------------------------
491   // Create and retrieve delay slot info for delayed instructions
492   //----------------------------------------------------------------------
493   
494   inline DelaySlotInfo* getDelaySlotInfoForInstr(const SchedGraphNode* bn,
495                                                  bool createIfMissing=false)
496   {
497     DelaySlotInfo* dinfo;
498     hash_map<const SchedGraphNode*, DelaySlotInfo* >::const_iterator
499       I = delaySlotInfoForBranches.find(bn);
500     if (I == delaySlotInfoForBranches.end())
501       {
502         if (createIfMissing)
503           {
504             dinfo = new DelaySlotInfo(bn,
505                           getInstrInfo().getNumDelaySlots(bn->getOpCode()));
506             delaySlotInfoForBranches[bn] = dinfo;
507           }
508         else
509           dinfo = NULL;
510       }
511     else
512       dinfo = (*I).second;
513     
514     return dinfo;
515   }
516   
517 private:
518   /*ctor*/      SchedulingManager       ();     // Disable: DO NOT IMPLEMENT.
519   void          updateEarliestStartTimes(const SchedGraphNode* node,
520                                          cycles_t schedTime);
521 };
522
523
524 /*ctor*/
525 SchedulingManager::SchedulingManager(const TargetMachine& target,
526                                      const SchedGraph* graph,
527                                      SchedPriorities& _schedPrio)
528   : nslots(target.getSchedInfo().getMaxNumIssueTotal()),
529     schedInfo(target.getSchedInfo()),
530     schedPrio(_schedPrio),
531     isched(nslots, graph->getNumNodes()),
532     totalInstrCount(graph->getNumNodes() - 2),
533     nextEarliestIssueTime(0),
534     choicesForSlot(nslots),
535     numInClass(target.getSchedInfo().getNumSchedClasses(), 0),  // set all to 0
536     nextEarliestStartTime(target.getInstrInfo().getNumRealOpCodes(),
537                           (cycles_t) 0)                         // set all to 0
538 {
539   updateTime(0);
540   
541   // Note that an upper bound on #choices for each slot is = nslots since
542   // we use this vector to hold a feasible set of instructions, and more
543   // would be infeasible. Reserve that much memory since it is probably small.
544   for (unsigned int i=0; i < nslots; i++)
545     choicesForSlot[i].resize(nslots);
546 }
547
548
549 void
550 SchedulingManager::updateEarliestStartTimes(const SchedGraphNode* node,
551                                             cycles_t schedTime)
552 {
553   if (schedInfo.numBubblesAfter(node->getOpCode()) > 0)
554     { // Update next earliest time before which *nothing* can issue.
555       nextEarliestIssueTime = max(nextEarliestIssueTime,
556                   curTime + 1 + schedInfo.numBubblesAfter(node->getOpCode()));
557     }
558   
559   const vector<MachineOpCode>*
560     conflictVec = schedInfo.getConflictList(node->getOpCode());
561   
562   if (conflictVec != NULL)
563     for (unsigned i=0; i < conflictVec->size(); i++)
564       {
565         MachineOpCode toOp = (*conflictVec)[i];
566         cycles_t est = schedTime + schedInfo.getMinIssueGap(node->getOpCode(),
567                                                             toOp);
568         assert(toOp < (int) nextEarliestStartTime.size());
569         if (nextEarliestStartTime[toOp] < est)
570           nextEarliestStartTime[toOp] = est;
571       }
572 }
573
574 //************************* Internal Functions *****************************/
575
576
577 static void
578 AssignInstructionsToSlots(class SchedulingManager& S, unsigned maxIssue)
579 {
580   // find the slot to start from, in the current cycle
581   unsigned int startSlot = 0;
582   cycles_t curTime = S.getTime();
583   
584   assert(maxIssue > 0 && maxIssue <= S.nslots - startSlot);
585   
586   // If only one instruction can be issued, do so.
587   if (maxIssue == 1)
588     for (unsigned s=startSlot; s < S.nslots; s++)
589       if (S.getChoicesForSlot(s).size() > 0)
590         {// found the one instruction
591           S.scheduleInstr(*S.getChoicesForSlot(s).begin(), s, curTime);
592           return;
593         }
594   
595   // Otherwise, choose from the choices for each slot
596   // 
597   InstrGroup* igroup = S.isched.getIGroup(S.getTime());
598   assert(igroup != NULL && "Group creation failed?");
599   
600   // Find a slot that has only a single choice, and take it.
601   // If all slots have 0 or multiple choices, pick the first slot with
602   // choices and use its last instruction (just to avoid shifting the vector).
603   unsigned numIssued;
604   for (numIssued = 0; numIssued < maxIssue; numIssued++)
605     {
606       int chosenSlot = -1, chosenNodeIndex = -1;
607       for (unsigned s=startSlot; s < S.nslots; s++)
608         if ((*igroup)[s] == NULL && S.getChoicesForSlot(s).size() == 1)
609           {
610             chosenSlot = (int) s;
611             break;
612           }
613       
614       if (chosenSlot == -1)
615         for (unsigned s=startSlot; s < S.nslots; s++)
616           if ((*igroup)[s] == NULL && S.getChoicesForSlot(s).size() > 0)
617             {
618               chosenSlot = (int) s;
619               break;
620             }
621       
622       if (chosenSlot != -1)
623         { // Insert the chosen instr in the chosen slot and
624           // erase it from all slots.
625           const SchedGraphNode* node= *S.getChoicesForSlot(chosenSlot).begin();
626           S.scheduleInstr(node, chosenSlot, curTime);
627         }
628     }
629   
630   assert(numIssued > 0 && "Should not happen when maxIssue > 0!");
631 }
632
633
634 // 
635 // For now, just assume we are scheduling within a single basic block.
636 // Get the machine instruction vector for the basic block and clear it,
637 // then append instructions in scheduled order.
638 // Also, re-insert the dummy PHI instructions that were at the beginning
639 // of the basic block, since they are not part of the schedule.
640 //   
641 static void
642 RecordSchedule(const BasicBlock* bb, const SchedulingManager& S)
643 {
644   MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
645   const MachineInstrInfo& mii = S.schedInfo.getInstrInfo();
646   
647 #ifndef NDEBUG
648   // Lets make sure we didn't lose any instructions, except possibly
649   // some NOPs from delay slots.  Also, PHIs are not included in the schedule.
650   unsigned numInstr = 0;
651   for (MachineCodeForBasicBlock::iterator I=mvec.begin(); I != mvec.end(); ++I)
652     if (! mii.isNop((*I)->getOpCode()) &&
653         ! mii.isDummyPhiInstr((*I)->getOpCode()))
654       ++numInstr;
655   assert(S.isched.getNumInstructions() >= numInstr &&
656          "Lost some non-NOP instructions during scheduling!");
657 #endif
658   
659   if (S.isched.getNumInstructions() == 0)
660     return;                             // empty basic block!
661   
662   // First find the dummy instructions at the start of the basic block
663   MachineCodeForBasicBlock::iterator I = mvec.begin();
664   for ( ; I != mvec.end(); ++I)
665     if (! mii.isDummyPhiInstr((*I)->getOpCode()))
666       break;
667   
668   // Erase all except the dummy PHI instructions from mvec, and
669   // pre-allocate create space for the ones we will put back in.
670   mvec.erase(I, mvec.end());
671   mvec.reserve(mvec.size() + S.isched.getNumInstructions());
672   
673   InstrSchedule::const_iterator NIend = S.isched.end();
674   for (InstrSchedule::const_iterator NI = S.isched.begin(); NI != NIend; ++NI)
675     mvec.push_back(const_cast<MachineInstr*>((*NI)->getMachineInstr()));
676 }
677
678
679
680 static void
681 MarkSuccessorsReady(SchedulingManager& S, const SchedGraphNode* node)
682 {
683   // Check if any successors are now ready that were not already marked
684   // ready before, and that have not yet been scheduled.
685   // 
686   for (sg_succ_const_iterator SI = succ_begin(node); SI !=succ_end(node); ++SI)
687     if (! (*SI)->isDummyNode()
688         && ! S.isScheduled(*SI)
689         && ! S.schedPrio.nodeIsReady(*SI))
690       {// successor not scheduled and not marked ready; check *its* preds.
691         
692         bool succIsReady = true;
693         for (sg_pred_const_iterator P=pred_begin(*SI); P != pred_end(*SI); ++P)
694           if (! (*P)->isDummyNode()
695               && ! S.isScheduled(*P))
696             {
697               succIsReady = false;
698               break;
699             }
700         
701         if (succIsReady)        // add the successor to the ready list
702           S.schedPrio.insertReady(*SI);
703       }
704 }
705
706
707 // Choose up to `nslots' FEASIBLE instructions and assign each
708 // instruction to all possible slots that do not violate feasibility.
709 // FEASIBLE means it should be guaranteed that the set
710 // of chosen instructions can be issued in a single group.
711 // 
712 // Return value:
713 //      maxIssue : total number of feasible instructions
714 //      S.choicesForSlot[i=0..nslots] : set of instructions feasible in slot i
715 // 
716 static unsigned
717 FindSlotChoices(SchedulingManager& S,
718                 DelaySlotInfo*& getDelaySlotInfo)
719 {
720   // initialize result vectors to empty
721   S.resetChoices();
722   
723   // find the slot to start from, in the current cycle
724   unsigned int startSlot = 0;
725   InstrGroup* igroup = S.isched.getIGroup(S.getTime());
726   for (int s = S.nslots - 1; s >= 0; s--)
727     if ((*igroup)[s] != NULL)
728       {
729         startSlot = s+1;
730         break;
731       }
732   
733   // Make sure we pick at most one instruction that would break the group.
734   // Also, if we do pick one, remember which it was.
735   unsigned int indexForBreakingNode = S.nslots;
736   unsigned int indexForDelayedInstr = S.nslots;
737   DelaySlotInfo* delaySlotInfo = NULL;
738
739   getDelaySlotInfo = NULL;
740   
741   // Choose instructions in order of priority.
742   // Add choices to the choice vector in the SchedulingManager class as
743   // we choose them so that subsequent choices will be correctly tested
744   // for feasibility, w.r.t. higher priority choices for the same cycle.
745   // 
746   while (S.getNumChoices() < S.nslots - startSlot)
747     {
748       const SchedGraphNode* nextNode=S.schedPrio.getNextHighest(S,S.getTime());
749       if (nextNode == NULL)
750         break;                  // no more instructions for this cycle
751       
752       if (S.getInstrInfo().getNumDelaySlots(nextNode->getOpCode()) > 0)
753         {
754           delaySlotInfo = S.getDelaySlotInfoForInstr(nextNode);
755           if (delaySlotInfo != NULL)
756             {
757               if (indexForBreakingNode < S.nslots)
758                 // cannot issue a delayed instr in the same cycle as one
759                 // that breaks the issue group or as another delayed instr
760                 nextNode = NULL;
761               else
762                 indexForDelayedInstr = S.getNumChoices();
763             }
764         }
765       else if (S.schedInfo.breaksIssueGroup(nextNode->getOpCode()))
766         {
767           if (indexForBreakingNode < S.nslots)
768             // have a breaking instruction already so throw this one away
769             nextNode = NULL;
770           else
771             indexForBreakingNode = S.getNumChoices();
772         }
773       
774       if (nextNode != NULL)
775         {
776           S.addChoice(nextNode);
777       
778           if (S.schedInfo.isSingleIssue(nextNode->getOpCode()))
779             {
780               assert(S.getNumChoices() == 1 &&
781                      "Prioritizer returned invalid instr for this cycle!");
782               break;
783             }
784         }
785           
786       if (indexForDelayedInstr < S.nslots)
787         break;                  // leave the rest for delay slots
788     }
789   
790   assert(S.getNumChoices() <= S.nslots);
791   assert(! (indexForDelayedInstr < S.nslots &&
792             indexForBreakingNode < S.nslots) && "Cannot have both in a cycle");
793   
794   // Assign each chosen instruction to all possible slots for that instr.
795   // But if only one instruction was chosen, put it only in the first
796   // feasible slot; no more analysis will be needed.
797   // 
798   if (indexForDelayedInstr >= S.nslots && 
799       indexForBreakingNode >= S.nslots)
800     { // No instructions that break the issue group or that have delay slots.
801       // This is the common case, so handle it separately for efficiency.
802       
803       if (S.getNumChoices() == 1)
804         {
805           MachineOpCode opCode = S.getChoice(0)->getOpCode();
806           unsigned int s;
807           for (s=startSlot; s < S.nslots; s++)
808             if (S.schedInfo.instrCanUseSlot(opCode, s))
809               break;
810           assert(s < S.nslots && "No feasible slot for this opCode?");
811           S.addChoiceToSlot(s, S.getChoice(0));
812         }
813       else
814         {
815           for (unsigned i=0; i < S.getNumChoices(); i++)
816             {
817               MachineOpCode opCode = S.getChoice(i)->getOpCode();
818               for (unsigned int s=startSlot; s < S.nslots; s++)
819                 if (S.schedInfo.instrCanUseSlot(opCode, s))
820                   S.addChoiceToSlot(s, S.getChoice(i));
821             }
822         }
823     }
824   else if (indexForDelayedInstr < S.nslots)
825     {
826       // There is an instruction that needs delay slots.
827       // Try to assign that instruction to a higher slot than any other
828       // instructions in the group, so that its delay slots can go
829       // right after it.
830       //  
831
832       assert(indexForDelayedInstr == S.getNumChoices() - 1 &&
833              "Instruction with delay slots should be last choice!");
834       assert(delaySlotInfo != NULL && "No delay slot info for instr?");
835       
836       const SchedGraphNode* delayedNode = S.getChoice(indexForDelayedInstr);
837       MachineOpCode delayOpCode = delayedNode->getOpCode();
838       unsigned ndelays= S.getInstrInfo().getNumDelaySlots(delayOpCode);
839       
840       unsigned delayedNodeSlot = S.nslots;
841       int highestSlotUsed;
842       
843       // Find the last possible slot for the delayed instruction that leaves
844       // at least `d' slots vacant after it (d = #delay slots)
845       for (int s = S.nslots-ndelays-1; s >= (int) startSlot; s--)
846         if (S.schedInfo.instrCanUseSlot(delayOpCode, s))
847           {
848             delayedNodeSlot = s;
849             break;
850           }
851       
852       highestSlotUsed = -1;
853       for (unsigned i=0; i < S.getNumChoices() - 1; i++)
854         {
855           // Try to assign every other instruction to a lower numbered
856           // slot than delayedNodeSlot.
857           MachineOpCode opCode =S.getChoice(i)->getOpCode();
858           bool noSlotFound = true;
859           unsigned int s;
860           for (s=startSlot; s < delayedNodeSlot; s++)
861             if (S.schedInfo.instrCanUseSlot(opCode, s))
862               {
863                 S.addChoiceToSlot(s, S.getChoice(i));
864                 noSlotFound = false;
865               }
866           
867           // No slot before `delayedNodeSlot' was found for this opCode
868           // Use a later slot, and allow some delay slots to fall in
869           // the next cycle.
870           if (noSlotFound)
871             for ( ; s < S.nslots; s++)
872               if (S.schedInfo.instrCanUseSlot(opCode, s))
873                 {
874                   S.addChoiceToSlot(s, S.getChoice(i));
875                   break;
876                 }
877           
878           assert(s < S.nslots && "No feasible slot for instruction?");
879           
880           highestSlotUsed = max(highestSlotUsed, (int) s);
881         }
882       
883       assert(highestSlotUsed <= (int) S.nslots-1 && "Invalid slot used?");
884       
885       // We will put the delayed node in the first slot after the
886       // highest slot used.  But we just mark that for now, and
887       // schedule it separately because we want to schedule the delay
888       // slots for the node at the same time.
889       cycles_t dcycle = S.getTime();
890       unsigned int dslot = highestSlotUsed + 1;
891       if (dslot == S.nslots)
892         {
893           dslot = 0;
894           ++dcycle;
895         }
896       delaySlotInfo->recordChosenSlot(dcycle, dslot);
897       getDelaySlotInfo = delaySlotInfo;
898     }
899   else
900     { // There is an instruction that breaks the issue group.
901       // For such an instruction, assign to the last possible slot in
902       // the current group, and then don't assign any other instructions
903       // to later slots.
904       assert(indexForBreakingNode < S.nslots);
905       const SchedGraphNode* breakingNode=S.getChoice(indexForBreakingNode);
906       unsigned breakingSlot = INT_MAX;
907       unsigned int nslotsToUse = S.nslots;
908           
909       // Find the last possible slot for this instruction.
910       for (int s = S.nslots-1; s >= (int) startSlot; s--)
911         if (S.schedInfo.instrCanUseSlot(breakingNode->getOpCode(), s))
912           {
913             breakingSlot = s;
914             break;
915           }
916       assert(breakingSlot < S.nslots &&
917              "No feasible slot for `breakingNode'?");
918       
919       // Higher priority instructions than the one that breaks the group:
920       // These can be assigned to all slots, but will be assigned only
921       // to earlier slots if possible.
922       for (unsigned i=0;
923            i < S.getNumChoices() && i < indexForBreakingNode; i++)
924         {
925           MachineOpCode opCode =S.getChoice(i)->getOpCode();
926           
927           // If a higher priority instruction cannot be assigned to
928           // any earlier slots, don't schedule the breaking instruction.
929           // 
930           bool foundLowerSlot = false;
931           nslotsToUse = S.nslots;           // May be modified in the loop
932           for (unsigned int s=startSlot; s < nslotsToUse; s++)
933             if (S.schedInfo.instrCanUseSlot(opCode, s))
934               {
935                 if (breakingSlot < S.nslots && s < breakingSlot)
936                   {
937                     foundLowerSlot = true;
938                     nslotsToUse = breakingSlot; // RESETS LOOP UPPER BOUND!
939                   }
940                     
941                 S.addChoiceToSlot(s, S.getChoice(i));
942               }
943               
944           if (!foundLowerSlot)
945             breakingSlot = INT_MAX;             // disable breaking instr
946         }
947       
948       // Assign the breaking instruction (if any) to a single slot
949       // Otherwise, just ignore the instruction.  It will simply be
950       // scheduled in a later cycle.
951       if (breakingSlot < S.nslots)
952         {
953           S.addChoiceToSlot(breakingSlot, breakingNode);
954           nslotsToUse = breakingSlot;
955         }
956       else
957         nslotsToUse = S.nslots;
958           
959       // For lower priority instructions than the one that breaks the
960       // group, only assign them to slots lower than the breaking slot.
961       // Otherwise, just ignore the instruction.
962       for (unsigned i=indexForBreakingNode+1; i < S.getNumChoices(); i++)
963         {
964           bool foundLowerSlot = false;
965           MachineOpCode opCode = S.getChoice(i)->getOpCode();
966           for (unsigned int s=startSlot; s < nslotsToUse; s++)
967             if (S.schedInfo.instrCanUseSlot(opCode, s))
968               S.addChoiceToSlot(s, S.getChoice(i));
969         }
970     } // endif (no delay slots and no breaking slots)
971   
972   return S.getNumChoices();
973 }
974
975
976 static unsigned
977 ChooseOneGroup(SchedulingManager& S)
978 {
979   assert(S.schedPrio.getNumReady() > 0
980          && "Don't get here without ready instructions.");
981   
982   cycles_t firstCycle = S.getTime();
983   DelaySlotInfo* getDelaySlotInfo = NULL;
984   
985   // Choose up to `nslots' feasible instructions and their possible slots.
986   unsigned numIssued = FindSlotChoices(S, getDelaySlotInfo);
987   
988   while (numIssued == 0)
989     {
990       S.updateTime(S.getTime()+1);
991       numIssued = FindSlotChoices(S, getDelaySlotInfo);
992     }
993   
994   AssignInstructionsToSlots(S, numIssued);
995   
996   if (getDelaySlotInfo != NULL)
997     numIssued += getDelaySlotInfo->scheduleDelayedNode(S); 
998   
999   // Print trace of scheduled instructions before newly ready ones
1000   if (SchedDebugLevel >= Sched_PrintSchedTrace)
1001     {
1002       for (cycles_t c = firstCycle; c <= S.getTime(); c++)
1003         {
1004           cout << "    Cycle " << c << " : Scheduled instructions:\n";
1005           const InstrGroup* igroup = S.isched.getIGroup(c);
1006           for (unsigned int s=0; s < S.nslots; s++)
1007             {
1008               cout << "        ";
1009               if ((*igroup)[s] != NULL)
1010                 cout << * ((*igroup)[s])->getMachineInstr() << endl;
1011               else
1012                 cout << "<none>" << endl;
1013             }
1014         }
1015     }
1016   
1017   return numIssued;
1018 }
1019
1020
1021 static void
1022 ForwardListSchedule(SchedulingManager& S)
1023 {
1024   unsigned N;
1025   const SchedGraphNode* node;
1026   
1027   S.schedPrio.initialize();
1028   
1029   while ((N = S.schedPrio.getNumReady()) > 0)
1030     {
1031       cycles_t nextCycle = S.getTime();
1032       
1033       // Choose one group of instructions for a cycle, plus any delay slot
1034       // instructions (which may overflow into successive cycles).
1035       // This will advance S.getTime() to the last cycle in which
1036       // instructions are actually issued.
1037       // 
1038       unsigned numIssued = ChooseOneGroup(S);
1039       assert(numIssued > 0 && "Deadlock in list scheduling algorithm?");
1040       
1041       // Notify the priority manager of scheduled instructions and mark
1042       // any successors that may now be ready
1043       // 
1044       for (cycles_t c = nextCycle; c <= S.getTime(); c++)
1045         {
1046           const InstrGroup* igroup = S.isched.getIGroup(c);
1047           for (unsigned int s=0; s < S.nslots; s++)
1048             if ((node = (*igroup)[s]) != NULL)
1049               {
1050                 S.schedPrio.issuedReadyNodeAt(S.getTime(), node);
1051                 MarkSuccessorsReady(S, node);
1052               }
1053         }
1054       
1055       // Move to the next the next earliest cycle for which
1056       // an instruction can be issued, or the next earliest in which
1057       // one will be ready, or to the next cycle, whichever is latest.
1058       // 
1059       S.updateTime(max(S.getTime() + 1,
1060                        max(S.getEarliestIssueTime(),
1061                            S.schedPrio.getEarliestReadyTime())));
1062     }
1063 }
1064
1065
1066 //---------------------------------------------------------------------
1067 // Code for filling delay slots for delayed terminator instructions
1068 // (e.g., BRANCH and RETURN).  Delay slots for non-terminator
1069 // instructions (e.g., CALL) are not handled here because they almost
1070 // always can be filled with instructions from the call sequence code
1071 // before a call.  That's preferable because we incur many tradeoffs here
1072 // when we cannot find single-cycle instructions that can be reordered.
1073 //----------------------------------------------------------------------
1074
1075 static bool
1076 NodeCanFillDelaySlot(const SchedulingManager& S,
1077                      const SchedGraphNode* node,
1078                      const SchedGraphNode* brNode,
1079                      bool nodeIsPredecessor)
1080 {
1081   assert(! node->isDummyNode());
1082   
1083   // don't put a branch in the delay slot of another branch
1084   if (S.getInstrInfo().isBranch(node->getOpCode()))
1085     return false;
1086   
1087   // don't put a single-issue instruction in the delay slot of a branch
1088   if (S.schedInfo.isSingleIssue(node->getOpCode()))
1089     return false;
1090   
1091   // don't put a load-use dependence in the delay slot of a branch
1092   const MachineInstrInfo& mii = S.getInstrInfo();
1093   
1094   for (SchedGraphNode::const_iterator EI = node->beginInEdges();
1095        EI != node->endInEdges(); ++EI)
1096     if (! (*EI)->getSrc()->isDummyNode()
1097         && mii.isLoad((*EI)->getSrc()->getOpCode())
1098         && (*EI)->getDepType() == SchedGraphEdge::CtrlDep)
1099       return false;
1100   
1101   // for now, don't put an instruction that does not have operand
1102   // interlocks in the delay slot of a branch
1103   if (! S.getInstrInfo().hasOperandInterlock(node->getOpCode()))
1104     return false;
1105   
1106   // Finally, if the instruction preceeds the branch, we make sure the
1107   // instruction can be reordered relative to the branch.  We simply check
1108   // if the instr. has only 1 outgoing edge, viz., a CD edge to the branch.
1109   // 
1110   if (nodeIsPredecessor)
1111     {
1112       bool onlyCDEdgeToBranch = true;
1113       for (SchedGraphNode::const_iterator OEI = node->beginOutEdges();
1114            OEI != node->endOutEdges(); ++OEI)
1115         if (! (*OEI)->getSink()->isDummyNode()
1116             && ((*OEI)->getSink() != brNode
1117                 || (*OEI)->getDepType() != SchedGraphEdge::CtrlDep))
1118           {
1119             onlyCDEdgeToBranch = false;
1120             break;
1121           }
1122       
1123       if (!onlyCDEdgeToBranch)
1124         return false;
1125     }
1126   
1127   return true;
1128 }
1129
1130
1131 static void
1132 MarkNodeForDelaySlot(SchedulingManager& S,
1133                      SchedGraph* graph,
1134                      SchedGraphNode* node,
1135                      const SchedGraphNode* brNode,
1136                      bool nodeIsPredecessor)
1137 {
1138   if (nodeIsPredecessor)
1139     { // If node is in the same basic block (i.e., preceeds brNode),
1140       // remove it and all its incident edges from the graph.  Make sure we
1141       // add dummy edges for pred/succ nodes that become entry/exit nodes.
1142       graph->eraseIncidentEdges(node, /*addDummyEdges*/ true);
1143     }
1144   else
1145     { // If the node was from a target block, add the node to the graph
1146       // and add a CD edge from brNode to node.
1147       assert(0 && "NOT IMPLEMENTED YET");
1148     }
1149   
1150   DelaySlotInfo* dinfo = S.getDelaySlotInfoForInstr(brNode, /*create*/ true);
1151   dinfo->addDelayNode(node);
1152 }
1153
1154
1155 void
1156 FindUsefulInstructionsForDelaySlots(SchedulingManager& S,
1157                                     SchedGraphNode* brNode,
1158                                     vector<SchedGraphNode*>& sdelayNodeVec)
1159 {
1160   const MachineInstrInfo& mii = S.getInstrInfo();
1161   unsigned ndelays =
1162     mii.getNumDelaySlots(brNode->getOpCode());
1163   
1164   if (ndelays == 0)
1165     return;
1166   
1167   sdelayNodeVec.reserve(ndelays);
1168   
1169   // Use a separate vector to hold the feasible multi-cycle nodes.
1170   // These will be used if not enough single-cycle nodes are found.
1171   // 
1172   vector<SchedGraphNode*> mdelayNodeVec;
1173   
1174   for (sg_pred_iterator P = pred_begin(brNode);
1175        P != pred_end(brNode) && sdelayNodeVec.size() < ndelays; ++P)
1176     if (! (*P)->isDummyNode() &&
1177         ! mii.isNop((*P)->getOpCode()) &&
1178         NodeCanFillDelaySlot(S, *P, brNode, /*pred*/ true))
1179       {
1180         if (mii.maxLatency((*P)->getOpCode()) > 1)
1181           mdelayNodeVec.push_back(*P);
1182         else
1183           sdelayNodeVec.push_back(*P);
1184       }
1185   
1186   // If not enough single-cycle instructions were found, select the
1187   // lowest-latency multi-cycle instructions and use them.
1188   // Note that this is the most efficient code when only 1 (or even 2)
1189   // values need to be selected.
1190   // 
1191   while (sdelayNodeVec.size() < ndelays && mdelayNodeVec.size() > 0)
1192     {
1193       unsigned lmin =
1194         mii.maxLatency(mdelayNodeVec[0]->getOpCode());
1195       unsigned minIndex   = 0;
1196       for (unsigned i=1; i < mdelayNodeVec.size(); i++)
1197         {
1198           unsigned li = 
1199             mii.maxLatency(mdelayNodeVec[i]->getOpCode());
1200           if (lmin >= li)
1201             {
1202               lmin = li;
1203               minIndex = i;
1204             }
1205         }
1206       sdelayNodeVec.push_back(mdelayNodeVec[minIndex]);
1207       if (sdelayNodeVec.size() < ndelays) // avoid the last erase!
1208         mdelayNodeVec.erase(mdelayNodeVec.begin() + minIndex);
1209     }
1210 }
1211
1212
1213 // Remove the NOPs currently in delay slots from the graph.
1214 // Mark instructions specified in sdelayNodeVec to replace them.
1215 // If not enough useful instructions were found, mark the NOPs to be used
1216 // for filling delay slots, otherwise, otherwise just discard them.
1217 // 
1218 void
1219 ReplaceNopsWithUsefulInstr(SchedulingManager& S,
1220                            SchedGraphNode* node,
1221                            vector<SchedGraphNode*> sdelayNodeVec,
1222                            SchedGraph* graph)
1223 {
1224   vector<SchedGraphNode*> nopNodeVec;   // this will hold unused NOPs
1225   const MachineInstrInfo& mii = S.getInstrInfo();
1226   const MachineInstr* brInstr = node->getMachineInstr();
1227   unsigned ndelays= mii.getNumDelaySlots(brInstr->getOpCode());
1228   assert(ndelays > 0 && "Unnecessary call to replace NOPs");
1229   
1230   // Remove the NOPs currently in delay slots from the graph.
1231   // If not enough useful instructions were found, use the NOPs to
1232   // fill delay slots, otherwise, just discard them.
1233   //  
1234   unsigned int firstDelaySlotIdx = node->getOrigIndexInBB() + 1;
1235   MachineCodeForBasicBlock& bbMvec  = node->getBB()->getMachineInstrVec();
1236   assert(bbMvec[firstDelaySlotIdx - 1] == brInstr &&
1237          "Incorrect instr. index in basic block for brInstr");
1238   
1239   // First find all useful instructions already in the delay slots
1240   // and USE THEM.  We'll throw away the unused alternatives below
1241   // 
1242   for (unsigned i=firstDelaySlotIdx; i < firstDelaySlotIdx + ndelays; ++i)
1243     if (! mii.isNop(bbMvec[i]->getOpCode()))
1244       sdelayNodeVec.insert(sdelayNodeVec.begin(),
1245                            graph->getGraphNodeForInstr(bbMvec[i]));
1246   
1247   // Then find the NOPs and keep only as many as are needed.
1248   // Put the rest in nopNodeVec to be deleted.
1249   for (unsigned i=firstDelaySlotIdx; i < firstDelaySlotIdx + ndelays; ++i)
1250     if (mii.isNop(bbMvec[i]->getOpCode()))
1251       if (sdelayNodeVec.size() < ndelays)
1252         sdelayNodeVec.push_back(graph->getGraphNodeForInstr(bbMvec[i]));
1253       else
1254         nopNodeVec.push_back(graph->getGraphNodeForInstr(bbMvec[i]));
1255   
1256   assert(sdelayNodeVec.size() >= ndelays);
1257   
1258   // If some delay slots were already filled, throw away that many new choices
1259   if (sdelayNodeVec.size() > ndelays)
1260     sdelayNodeVec.resize(ndelays);
1261   
1262   // Mark the nodes chosen for delay slots.  This removes them from the graph.
1263   for (unsigned i=0; i < sdelayNodeVec.size(); i++)
1264     MarkNodeForDelaySlot(S, graph, sdelayNodeVec[i], node, true);
1265   
1266   // And remove the unused NOPs from the graph.
1267   for (unsigned i=0; i < nopNodeVec.size(); i++)
1268     graph->eraseIncidentEdges(nopNodeVec[i], /*addDummyEdges*/ true);
1269 }
1270
1271
1272 // For all delayed instructions, choose instructions to put in the delay
1273 // slots and pull those out of the graph.  Mark them for the delay slots
1274 // in the DelaySlotInfo object for that graph node.  If no useful work
1275 // is found for a delay slot, use the NOP that is currently in that slot.
1276 // 
1277 // We try to fill the delay slots with useful work for all instructions
1278 // EXCEPT CALLS AND RETURNS.
1279 // For CALLs and RETURNs, it is nearly always possible to use one of the
1280 // call sequence instrs and putting anything else in the delay slot could be
1281 // suboptimal.  Also, it complicates generating the calling sequence code in
1282 // regalloc.
1283 // 
1284 static void
1285 ChooseInstructionsForDelaySlots(SchedulingManager& S,
1286                                 const BasicBlock* bb,
1287                                 SchedGraph* graph)
1288 {
1289   const MachineInstrInfo& mii = S.getInstrInfo();
1290   const TerminatorInst* termInstr = bb->getTerminator();
1291   MachineCodeForVMInstr& termMvec = termInstr->getMachineInstrVec();
1292   vector<SchedGraphNode*> delayNodeVec;
1293   const MachineInstr* brInstr = NULL;
1294   
1295   assert(termInstr->getOpcode() != Instruction::Call
1296          && "Call used as terminator?");
1297   
1298   if (termInstr->getOpcode() != Instruction::Ret)
1299     {
1300       // To find instructions that need delay slots without searching the full
1301       // machine code, we assume that the only delayed instructions are CALLs
1302       // or instructions generated for the terminator inst.
1303       // Find the first branch instr in the sequence of machine instrs for term
1304       // 
1305       unsigned first = 0;
1306       while (first < termMvec.size() &&
1307              ! mii.isBranch(termMvec[first]->getOpCode()))
1308         {
1309           ++first;
1310         }
1311       assert(first < termMvec.size() &&
1312          "No branch instructions for BR?  Ok, but weird!  Delete assertion.");
1313       
1314       brInstr = (first < termMvec.size())? termMvec[first] : NULL;
1315       
1316       // Compute a vector of the nodes chosen for delay slots and then
1317       // mark delay slots to replace NOPs with these useful instructions.
1318       // 
1319       if (brInstr != NULL)
1320         {
1321           SchedGraphNode* brNode = graph->getGraphNodeForInstr(brInstr);
1322           FindUsefulInstructionsForDelaySlots(S, brNode, delayNodeVec);
1323           ReplaceNopsWithUsefulInstr(S, brNode, delayNodeVec, graph);
1324         }
1325     }
1326   
1327   // Also mark delay slots for other delayed instructions to hold NOPs. 
1328   // Simply passing in an empty delayNodeVec will have this effect.
1329   // 
1330   delayNodeVec.clear();
1331   const MachineCodeForBasicBlock& bbMvec = bb->getMachineInstrVec();
1332   for (unsigned i=0; i < bbMvec.size(); i++)
1333     if (bbMvec[i] != brInstr &&
1334         mii.getNumDelaySlots(bbMvec[i]->getOpCode()) > 0)
1335       {
1336         SchedGraphNode* node = graph->getGraphNodeForInstr(bbMvec[i]);
1337         ReplaceNopsWithUsefulInstr(S, node, delayNodeVec, graph);
1338       }
1339 }
1340
1341
1342 // 
1343 // Schedule the delayed branch and its delay slots
1344 // 
1345 unsigned
1346 DelaySlotInfo::scheduleDelayedNode(SchedulingManager& S)
1347 {
1348   assert(delayedNodeSlotNum < S.nslots && "Illegal slot for branch");
1349   assert(S.isched.getInstr(delayedNodeSlotNum, delayedNodeCycle) == NULL
1350          && "Slot for branch should be empty");
1351   
1352   unsigned int nextSlot = delayedNodeSlotNum;
1353   cycles_t nextTime = delayedNodeCycle;
1354   
1355   S.scheduleInstr(brNode, nextSlot, nextTime);
1356   
1357   for (unsigned d=0; d < ndelays; d++)
1358     {
1359       ++nextSlot;
1360       if (nextSlot == S.nslots)
1361         {
1362           nextSlot = 0;
1363           nextTime++;
1364         }
1365       
1366       // Find the first feasible instruction for this delay slot
1367       // Note that we only check for issue restrictions here.
1368       // We do *not* check for flow dependences but rely on pipeline
1369       // interlocks to resolve them.  Machines without interlocks
1370       // will require this code to be modified.
1371       for (unsigned i=0; i < delayNodeVec.size(); i++)
1372         {
1373           const SchedGraphNode* dnode = delayNodeVec[i];
1374           if ( ! S.isScheduled(dnode)
1375                && S.schedInfo.instrCanUseSlot(dnode->getOpCode(), nextSlot)
1376                && instrIsFeasible(S, dnode->getOpCode()))
1377             {
1378               assert(S.getInstrInfo().hasOperandInterlock(dnode->getOpCode())
1379                      && "Instructions without interlocks not yet supported "
1380                      "when filling branch delay slots");
1381               S.scheduleInstr(dnode, nextSlot, nextTime);
1382               break;
1383             }
1384         }
1385     }
1386   
1387   // Update current time if delay slots overflowed into later cycles.
1388   // Do this here because we know exactly which cycle is the last cycle
1389   // that contains delay slots.  The next loop doesn't compute that.
1390   if (nextTime > S.getTime())
1391     S.updateTime(nextTime);
1392   
1393   // Now put any remaining instructions in the unfilled delay slots.
1394   // This could lead to suboptimal performance but needed for correctness.
1395   nextSlot = delayedNodeSlotNum;
1396   nextTime = delayedNodeCycle;
1397   for (unsigned i=0; i < delayNodeVec.size(); i++)
1398     if (! S.isScheduled(delayNodeVec[i]))
1399       {
1400         do { // find the next empty slot
1401           ++nextSlot;
1402           if (nextSlot == S.nslots)
1403             {
1404               nextSlot = 0;
1405               nextTime++;
1406             }
1407         } while (S.isched.getInstr(nextSlot, nextTime) != NULL);
1408         
1409         S.scheduleInstr(delayNodeVec[i], nextSlot, nextTime);
1410         break;
1411       }
1412
1413   return 1 + ndelays;
1414 }
1415
1416
1417 // Check if the instruction would conflict with instructions already
1418 // chosen for the current cycle
1419 // 
1420 static inline bool
1421 ConflictsWithChoices(const SchedulingManager& S,
1422                      MachineOpCode opCode)
1423 {
1424   // Check if the instruction must issue by itself, and some feasible
1425   // choices have already been made for this cycle
1426   if (S.getNumChoices() > 0 && S.schedInfo.isSingleIssue(opCode))
1427     return true;
1428   
1429   // For each class that opCode belongs to, check if there are too many
1430   // instructions of that class.
1431   // 
1432   const InstrSchedClass sc = S.schedInfo.getSchedClass(opCode);
1433   return (S.getNumChoicesInClass(sc) == S.schedInfo.getMaxIssueForClass(sc));
1434 }
1435
1436
1437 //************************* External Functions *****************************/
1438
1439
1440 //---------------------------------------------------------------------------
1441 // Function: ViolatesMinimumGap
1442 // 
1443 // Purpose:
1444 //   Check minimum gap requirements relative to instructions scheduled in
1445 //   previous cycles.
1446 //   Note that we do not need to consider `nextEarliestIssueTime' here because
1447 //   that is also captured in the earliest start times for each opcode.
1448 //---------------------------------------------------------------------------
1449
1450 static inline bool
1451 ViolatesMinimumGap(const SchedulingManager& S,
1452                    MachineOpCode opCode,
1453                    const cycles_t inCycle)
1454 {
1455   return (inCycle < S.getEarliestStartTimeForOp(opCode));
1456 }
1457
1458
1459 //---------------------------------------------------------------------------
1460 // Function: instrIsFeasible
1461 // 
1462 // Purpose:
1463 //   Check if any issue restrictions would prevent the instruction from
1464 //   being issued in the current cycle
1465 //---------------------------------------------------------------------------
1466
1467 bool
1468 instrIsFeasible(const SchedulingManager& S,
1469                 MachineOpCode opCode)
1470 {
1471   // skip the instruction if it cannot be issued due to issue restrictions
1472   // caused by previously issued instructions
1473   if (ViolatesMinimumGap(S, opCode, S.getTime()))
1474     return false;
1475   
1476   // skip the instruction if it cannot be issued due to issue restrictions
1477   // caused by previously chosen instructions for the current cycle
1478   if (ConflictsWithChoices(S, opCode))
1479     return false;
1480   
1481   return true;
1482 }
1483
1484 //---------------------------------------------------------------------------
1485 // Function: ScheduleInstructionsWithSSA
1486 // 
1487 // Purpose:
1488 //   Entry point for instruction scheduling on SSA form.
1489 //   Schedules the machine instructions generated by instruction selection.
1490 //   Assumes that register allocation has not been done, i.e., operands
1491 //   are still in SSA form.
1492 //---------------------------------------------------------------------------
1493
1494 bool
1495 ScheduleInstructionsWithSSA(Method* method,
1496                             const TargetMachine &target)
1497 {
1498   SchedGraphSet graphSet(method, target);       
1499   
1500   if (SchedDebugLevel >= Sched_PrintSchedGraphs)
1501     {
1502       cout << endl << "*** SCHEDULING GRAPHS FOR INSTRUCTION SCHEDULING"
1503            << endl;
1504       graphSet.dump();
1505     }
1506   
1507   for (SchedGraphSet::const_iterator GI=graphSet.begin();
1508        GI != graphSet.end(); ++GI)
1509     {
1510       SchedGraph* graph = (*GI).second;
1511       const vector<const BasicBlock*>& bbvec = graph->getBasicBlocks();
1512       assert(bbvec.size() == 1 && "Cannot schedule multiple basic blocks");
1513       const BasicBlock* bb = bbvec[0];
1514       
1515       if (SchedDebugLevel >= Sched_PrintSchedTrace)
1516         cout << endl << "*** TRACE OF INSTRUCTION SCHEDULING OPERATIONS\n\n";
1517       
1518       SchedPriorities schedPrio(method, graph);      // expensive!
1519       SchedulingManager S(target, graph, schedPrio);
1520       
1521       ChooseInstructionsForDelaySlots(S, bb, graph); // modifies graph
1522       
1523       ForwardListSchedule(S);                        // computes schedule in S
1524       
1525       RecordSchedule((*GI).first, S);                // records schedule in BB
1526     }
1527   
1528   if (SchedDebugLevel >= Sched_PrintMachineCode)
1529     {
1530       cout << endl
1531            << "*** Machine instructions after INSTRUCTION SCHEDULING" << endl;
1532       MachineCodeForMethod::get(method).dump();
1533     }
1534   
1535   return false;                                  // no reason to fail yet
1536 }
1537
1538