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