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