Add new optional getPassName() virtual function that a Pass can override
[oota-llvm.git] / lib / Target / SparcV9 / InstrSched / InstrScheduling.cpp
index 7a9a801715db860c1fa3ebe0d52eb4ff18d8b0ad..b0422797475193f48454333b4e5fb23dbe22d28e 100644 (file)
@@ -1,37 +1,32 @@
-// $Id$
-//***************************************************************************
-// File:
-//     InstrScheduling.cpp
-// 
-// Purpose:
-//     
-// History:
-//     7/23/01  -  Vikram Adve  -  Created
-//**************************************************************************/
-
-
-//************************* User Include Files *****************************/
+//===- InstrScheduling.cpp - Generic Instruction Scheduling support -------===//
+//
+// This file implements the llvm/CodeGen/InstrScheduling.h interface, along with
+// generic support routines for instruction scheduling.
+//
+//===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/InstrScheduling.h"
-#include "SchedPriorities.h"
-#include "llvm/Analysis/LiveVar/BBLiveVar.h"
 #include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Support/CommandLine.h"
+#include "llvm/CodeGen/MachineCodeForInstruction.h"
+#include "llvm/CodeGen/MachineCodeForMethod.h"
+#include "llvm/Analysis/LiveVar/FunctionLiveVarInfo.h" // FIXME: Remove when modularized better
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/BasicBlock.h"
 #include "llvm/Instruction.h"
-
-
-//************************ System Include Files *****************************/
-
-#include <hash_set>
+#include "SchedPriorities.h"
+#include <ext/hash_set>
 #include <algorithm>
 #include <iterator>
-
+#include <iostream>
+using std::cerr;
+using std::vector;
 
 //************************* External Data Types *****************************/
 
 cl::Enum<enum SchedDebugLevel_t> SchedDebugLevel("dsched", cl::NoFlags,
   "enable instruction scheduling debugging information",
   clEnumValN(Sched_NoDebugInfo,      "n", "disable debug output"),
+  clEnumValN(Sched_Disable,        "off", "disable instruction scheduling"),
   clEnumValN(Sched_PrintMachineCode, "y", "print machine code after scheduling"),
   clEnumValN(Sched_PrintSchedTrace,  "t", "print trace of scheduling actions"),
   clEnumValN(Sched_PrintSchedGraphs, "g", "print scheduling graphs"), 0);
@@ -41,7 +36,6 @@ cl::Enum<enum SchedDebugLevel_t> SchedDebugLevel("dsched", cl::NoFlags,
 
 class InstrSchedule;
 class SchedulingManager;
-class DelaySlotInfo;
 
 
 //----------------------------------------------------------------------
@@ -163,7 +157,7 @@ public: // accessor functions to query chosen schedule
   }
   
   inline InstrGroup*   getIGroup       (cycles_t c) {
-    if (c >= groups.size())
+    if ((unsigned)c >= groups.size())
       groups.resize(c+1);
     if (groups[c] == NULL)
       groups[c] = new InstrGroup(nslots);
@@ -171,7 +165,7 @@ public: // accessor functions to query chosen schedule
   }
   
   inline const InstrGroup* getIGroup   (cycles_t c) const {
-    assert(c < groups.size());
+    assert((unsigned)c < groups.size());
     return groups[c];
   }
   
@@ -357,18 +351,22 @@ private:
   unsigned int totalInstrCount;
   cycles_t curTime;
   cycles_t nextEarliestIssueTime;              // next cycle we can issue
-  vector<hash_set<const SchedGraphNode*> > choicesForSlot; // indexed by slot#
+  vector<std::hash_set<const SchedGraphNode*> > choicesForSlot; // indexed by slot#
   vector<const SchedGraphNode*> choiceVec;     // indexed by node ptr
   vector<int> numInClass;                      // indexed by sched class
   vector<cycles_t> nextEarliestStartTime;      // indexed by opCode
-  hash_map<const SchedGraphNode*, DelaySlotInfo*> delaySlotInfoForBranches;
+  std::hash_map<const SchedGraphNode*, DelaySlotInfo*> delaySlotInfoForBranches;
                                                // indexed by branch node ptr 
   
 public:
-  /*ctor*/     SchedulingManager       (const TargetMachine& _target,
-                                        const SchedGraph* graph,
-                                        SchedPriorities& schedPrio);
-  /*dtor*/     ~SchedulingManager      () {}
+  SchedulingManager(const TargetMachine& _target, const SchedGraph* graph,
+                    SchedPriorities& schedPrio);
+  ~SchedulingManager() {
+    for (std::hash_map<const SchedGraphNode*,
+           DelaySlotInfo*>::iterator I = delaySlotInfoForBranches.begin(),
+           E = delaySlotInfoForBranches.end(); I != E; ++I)
+      delete I->second;
+  }
   
   //----------------------------------------------------------------------
   // Simplify access to the machine instruction info
@@ -423,7 +421,7 @@ public:
     return choiceVec[i];
   }
   
-  inline hash_set<const SchedGraphNode*>& getChoicesForSlot(unsigned slotNum) {
+  inline std::hash_set<const SchedGraphNode*>& getChoicesForSlot(unsigned slotNum) {
     assert(slotNum < nslots);
     return choicesForSlot[slotNum];
   }
@@ -498,30 +496,21 @@ public:
   inline DelaySlotInfo* getDelaySlotInfoForInstr(const SchedGraphNode* bn,
                                                 bool createIfMissing=false)
   {
-    DelaySlotInfo* dinfo;
-    hash_map<const SchedGraphNode*, DelaySlotInfo* >::const_iterator
+    std::hash_map<const SchedGraphNode*, DelaySlotInfo*>::const_iterator
       I = delaySlotInfoForBranches.find(bn);
-    if (I == delaySlotInfoForBranches.end())
-      {
-       if (createIfMissing)
-         {
-           dinfo = new DelaySlotInfo(bn,
-                          getInstrInfo().getNumDelaySlots(bn->getOpCode()));
-           delaySlotInfoForBranches[bn] = dinfo;
-         }
-       else
-         dinfo = NULL;
-      }
-    else
-      dinfo = (*I).second;
-    
-    return dinfo;
+    if (I != delaySlotInfoForBranches.end())
+      return I->second;
+
+    if (!createIfMissing) return 0;
+
+    DelaySlotInfo *dinfo =
+      new DelaySlotInfo(bn, getInstrInfo().getNumDelaySlots(bn->getOpCode()));
+    return delaySlotInfoForBranches[bn] = dinfo;
   }
   
 private:
-  /*ctor*/     SchedulingManager       ();     // Disable: DO NOT IMPLEMENT.
-  void         updateEarliestStartTimes(const SchedGraphNode* node,
-                                        cycles_t schedTime);
+  SchedulingManager();     // DISABLED: DO NOT IMPLEMENT
+  void updateEarliestStartTimes(const SchedGraphNode* node, cycles_t schedTime);
 };
 
 
@@ -556,7 +545,7 @@ SchedulingManager::updateEarliestStartTimes(const SchedGraphNode* node,
 {
   if (schedInfo.numBubblesAfter(node->getOpCode()) > 0)
     { // Update next earliest time before which *nothing* can issue.
-      nextEarliestIssueTime = max(nextEarliestIssueTime,
+      nextEarliestIssueTime = std::max(nextEarliestIssueTime,
                  curTime + 1 + schedInfo.numBubblesAfter(node->getOpCode()));
     }
   
@@ -607,7 +596,7 @@ AssignInstructionsToSlots(class SchedulingManager& S, unsigned maxIssue)
   unsigned numIssued;
   for (numIssued = 0; numIssued < maxIssue; numIssued++)
     {
-      int chosenSlot = -1, chosenNodeIndex = -1;
+      int chosenSlot = -1;
       for (unsigned s=startSlot; s < S.nslots; s++)
        if ((*igroup)[s] == NULL && S.getChoicesForSlot(s).size() == 1)
          {
@@ -672,7 +661,6 @@ RecordSchedule(const BasicBlock* bb, const SchedulingManager& S)
   // Erase all except the dummy PHI instructions from mvec, and
   // pre-allocate create space for the ones we will put back in.
   mvec.erase(I, mvec.end());
-  mvec.reserve(mvec.size() + S.isched.getNumInstructions());
   
   InstrSchedule::const_iterator NIend = S.isched.end();
   for (InstrSchedule::const_iterator NI = S.isched.begin(); NI != NIend; ++NI)
@@ -881,7 +869,7 @@ FindSlotChoices(SchedulingManager& S,
          
          assert(s < S.nslots && "No feasible slot for instruction?");
          
-         highestSlotUsed = max(highestSlotUsed, (int) s);
+         highestSlotUsed = std::max(highestSlotUsed, (int) s);
        }
       
       assert(highestSlotUsed <= (int) S.nslots-1 && "Invalid slot used?");
@@ -965,7 +953,6 @@ FindSlotChoices(SchedulingManager& S,
       // Otherwise, just ignore the instruction.
       for (unsigned i=indexForBreakingNode+1; i < S.getNumChoices(); i++)
        {
-         bool foundLowerSlot = false;
          MachineOpCode opCode = S.getChoice(i)->getOpCode();
          for (unsigned int s=startSlot; s < nslotsToUse; s++)
            if (S.schedInfo.instrCanUseSlot(opCode, s))
@@ -1005,15 +992,15 @@ ChooseOneGroup(SchedulingManager& S)
     {
       for (cycles_t c = firstCycle; c <= S.getTime(); c++)
         {
-          cout << "    Cycle " << c << " : Scheduled instructions:\n";
+          cerr << "    Cycle " << (long)c << " : Scheduled instructions:\n";
           const InstrGroup* igroup = S.isched.getIGroup(c);
           for (unsigned int s=0; s < S.nslots; s++)
             {
-              cout << "        ";
+              cerr << "        ";
               if ((*igroup)[s] != NULL)
-                cout << * ((*igroup)[s])->getMachineInstr() << endl;
+                cerr << * ((*igroup)[s])->getMachineInstr() << "\n";
               else
-                cout << "<none>" << endl;
+                cerr << "<none>\n";
             }
         }
     }
@@ -1060,9 +1047,9 @@ ForwardListSchedule(SchedulingManager& S)
       // an instruction can be issued, or the next earliest in which
       // one will be ready, or to the next cycle, whichever is latest.
       // 
-      S.updateTime(max(S.getTime() + 1,
-                      max(S.getEarliestIssueTime(),
-                          S.schedPrio.getEarliestReadyTime())));
+      S.updateTime(std::max(S.getTime() + 1,
+                            std::max(S.getEarliestIssueTime(),
+                                     S.schedPrio.getEarliestReadyTime())));
     }
 }
 
@@ -1235,33 +1222,27 @@ ReplaceNopsWithUsefulInstr(SchedulingManager& S,
   // If not enough useful instructions were found, use the NOPs to
   // fill delay slots, otherwise, just discard them.
   //  
-  MachineCodeForVMInstr& termMvec = node->getInstr()->getMachineInstrVec();
-  unsigned int firstDelaySlotIdx;
-  for (unsigned i=0; i < termMvec.size(); ++i)
-    if (termMvec[i] == brInstr)
-      {
-        firstDelaySlotIdx = i+1;
-        break;
-      }
-  assert(firstDelaySlotIdx <= termMvec.size()-1 &&
-         "This sucks! Where's that delay slot instruction?");
+  unsigned int firstDelaySlotIdx = node->getOrigIndexInBB() + 1;
+  MachineCodeForBasicBlock& bbMvec  = node->getBB()->getMachineInstrVec();
+  assert(bbMvec[firstDelaySlotIdx - 1] == brInstr &&
+         "Incorrect instr. index in basic block for brInstr");
   
   // First find all useful instructions already in the delay slots
   // and USE THEM.  We'll throw away the unused alternatives below
   // 
   for (unsigned i=firstDelaySlotIdx; i < firstDelaySlotIdx + ndelays; ++i)
-    if (! mii.isNop(termMvec[i]->getOpCode()))
+    if (! mii.isNop(bbMvec[i]->getOpCode()))
       sdelayNodeVec.insert(sdelayNodeVec.begin(),
-                           graph->getGraphNodeForInstr(termMvec[i]));
+                           graph->getGraphNodeForInstr(bbMvec[i]));
   
   // Then find the NOPs and keep only as many as are needed.
   // Put the rest in nopNodeVec to be deleted.
   for (unsigned i=firstDelaySlotIdx; i < firstDelaySlotIdx + ndelays; ++i)
-    if (mii.isNop(termMvec[i]->getOpCode()))
+    if (mii.isNop(bbMvec[i]->getOpCode()))
       if (sdelayNodeVec.size() < ndelays)
-        sdelayNodeVec.push_back(graph->getGraphNodeForInstr(termMvec[i]));
+        sdelayNodeVec.push_back(graph->getGraphNodeForInstr(bbMvec[i]));
       else
-        nopNodeVec.push_back(graph->getGraphNodeForInstr(termMvec[i]));
+        nopNodeVec.push_back(graph->getGraphNodeForInstr(bbMvec[i]));
   
   assert(sdelayNodeVec.size() >= ndelays);
   
@@ -1293,18 +1274,15 @@ ReplaceNopsWithUsefulInstr(SchedulingManager& S,
 // 
 static void
 ChooseInstructionsForDelaySlots(SchedulingManager& S,
-                               const BasicBlockbb,
-                               SchedGraphgraph)
+                               const BasicBlock *bb,
+                               SchedGraph *graph)
 {
   const MachineInstrInfo& mii = S.getInstrInfo();
-  const TerminatorInst* termInstr = bb->getTerminator();
-  MachineCodeForVMInstr& termMvec = termInstr->getMachineInstrVec();
+  const Instruction *termInstr = (Instruction*)bb->getTerminator();
+  MachineCodeForInstruction &termMvec=MachineCodeForInstruction::get(termInstr);
   vector<SchedGraphNode*> delayNodeVec;
   const MachineInstr* brInstr = NULL;
   
-  assert(termInstr->getOpcode() != Instruction::Call
-         && "Call used as terminator?");
-  
   if (termInstr->getOpcode() != Instruction::Ret)
     {
       // To find instructions that need delay slots without searching the full
@@ -1501,48 +1479,70 @@ instrIsFeasible(const SchedulingManager& S,
 //   are still in SSA form.
 //---------------------------------------------------------------------------
 
+namespace {
+  class InstructionSchedulingWithSSA : public FunctionPass {
+    const TargetMachine &target;
+  public:
+    inline InstructionSchedulingWithSSA(const TargetMachine &T) : target(T) {}
+
+    const char *getPassName() const { return "Instruction Scheduling"; }
+  
+    // getAnalysisUsage - We use LiveVarInfo...
+    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+      AU.addRequired(FunctionLiveVarInfo::ID);
+    }
+    
+    bool runOnFunction(Function *F);
+  };
+} // end anonymous namespace
+
+
 bool
-ScheduleInstructionsWithSSA(Method* method,
-                           const TargetMachine &target)
+InstructionSchedulingWithSSA::runOnFunction(Function *M)
 {
-  SchedGraphSet graphSet(method, target);      
+  if (SchedDebugLevel == Sched_Disable)
+    return false;
+  
+  SchedGraphSet graphSet(M, target);   
   
   if (SchedDebugLevel >= Sched_PrintSchedGraphs)
     {
-      cout << endl << "*** SCHEDULING GRAPHS FOR INSTRUCTION SCHEDULING"
-          << endl;
+      cerr << "\n*** SCHEDULING GRAPHS FOR INSTRUCTION SCHEDULING\n";
       graphSet.dump();
     }
   
-  for (SchedGraphSet::const_iterator GI=graphSet.begin();
-       GI != graphSet.end(); ++GI)
+  for (SchedGraphSet::const_iterator GI=graphSet.begin(), GE=graphSet.end();
+       GI != GE; ++GI)
     {
-      SchedGraph* graph = (*GI).second;
-      const vector<const BasicBlock*>bbvec = graph->getBasicBlocks();
+      SchedGraph* graph = (*GI);
+      const vector<const BasicBlock*> &bbvec = graph->getBasicBlocks();
       assert(bbvec.size() == 1 && "Cannot schedule multiple basic blocks");
       const BasicBlock* bb = bbvec[0];
       
       if (SchedDebugLevel >= Sched_PrintSchedTrace)
-       cout << endl << "*** TRACE OF INSTRUCTION SCHEDULING OPERATIONS\n\n";
+        cerr << "\n*** TRACE OF INSTRUCTION SCHEDULING OPERATIONS\n\n";
       
-      SchedPriorities schedPrio(method, graph);             // expensive!
+      // expensive!
+      SchedPriorities schedPrio(M, graph,getAnalysis<FunctionLiveVarInfo>());
       SchedulingManager S(target, graph, schedPrio);
-      
+          
       ChooseInstructionsForDelaySlots(S, bb, graph); // modifies graph
       
-      ForwardListSchedule(S);                       // computes schedule in S
+      ForwardListSchedule(S);               // computes schedule in S
       
-      RecordSchedule((*GI).first, S);               // records schedule in BB
+      RecordSchedule(bb, S);                // records schedule in BB
     }
   
   if (SchedDebugLevel >= Sched_PrintMachineCode)
     {
-      cout << endl
-          << "*** Machine instructions after INSTRUCTION SCHEDULING" << endl;
-      MachineCodeForMethod::get(method).dump();
+      cerr << "\n*** Machine instructions after INSTRUCTION SCHEDULING\n";
+      MachineCodeForMethod::get(M).dump();
     }
   
-  return false;                                         // no reason to fail yet
+  return false;
 }
 
 
+Pass *createInstructionSchedulingWithSSAPass(const TargetMachine &tgt) {
+  return new InstructionSchedulingWithSSA(tgt);
+}