#include "SchedPriorities.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
-#include "llvm/CodeGen/MachineCodeForMethod.h"
+#include "llvm/CodeGen/MachineFunction.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"
+#include "Support/CommandLine.h"
#include <algorithm>
using std::cerr;
using std::vector;
-//************************* External Data Types *****************************/
+SchedDebugLevel_t SchedDebugLevel;
-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);
+static cl::opt<SchedDebugLevel_t, true>
+SDL_opt("dsched", cl::Hidden, cl::location(SchedDebugLevel),
+ cl::desc("enable instruction scheduling debugging information"),
+ cl::values(
+ clEnumValN(Sched_NoDebugInfo, "n", "disable debug output"),
+ 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));
//************************* Internal Data Types *****************************/
//----------------------------------------------------------------------
template<class _NodeType>
-class ScheduleIterator: public std::forward_iterator<_NodeType, ptrdiff_t> {
+class ScheduleIterator : public forward_iterator<_NodeType, ptrdiff_t> {
private:
unsigned cycleNum;
unsigned slotNum;
class SchedulingManager: public NonCopyable {
public: // publicly accessible data members
- const unsigned int nslots;
- const MachineSchedInfo& schedInfo;
+ const unsigned nslots;
+ const TargetSchedInfo& schedInfo;
SchedPriorities& schedPrio;
InstrSchedule isched;
unsigned int totalInstrCount;
cycles_t curTime;
cycles_t nextEarliestIssueTime; // next cycle we can issue
- vector<std::hash_set<const SchedGraphNode*> > choicesForSlot; // indexed by slot#
+ vector<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
- std::hash_map<const SchedGraphNode*, DelaySlotInfo*> delaySlotInfoForBranches;
+ hash_map<const SchedGraphNode*, DelaySlotInfo*> delaySlotInfoForBranches;
// indexed by branch node ptr
public:
SchedulingManager(const TargetMachine& _target, const SchedGraph* graph,
SchedPriorities& schedPrio);
~SchedulingManager() {
- for (std::hash_map<const SchedGraphNode*,
+ for (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
//----------------------------------------------------------------------
- inline const MachineInstrInfo& getInstrInfo () const {
+ inline const TargetInstrInfo& getInstrInfo () const {
return schedInfo.getInstrInfo();
}
}
inline unsigned getNumChoicesInClass (const InstrSchedClass& sc) const {
- assert(sc < (int) numInClass.size() && "Invalid op code or sched class!");
+ assert(sc < numInClass.size() && "Invalid op code or sched class!");
return numInClass[sc];
}
return choiceVec[i];
}
- inline std::hash_set<const SchedGraphNode*>& getChoicesForSlot(unsigned slotNum) {
+ inline hash_set<const SchedGraphNode*>& getChoicesForSlot(unsigned slotNum) {
assert(slotNum < nslots);
return choicesForSlot[slotNum];
}
// Increment numInClass[c] for the sched class to which the instr belongs.
choiceVec.push_back(node);
const InstrSchedClass& sc = schedInfo.getSchedClass(node->getOpCode());
- assert(sc < (int) numInClass.size());
+ assert(sc < numInClass.size());
numInClass[sc]++;
}
// and decrement the instr count for the sched class to which it belongs
const InstrSchedClass& sc = schedInfo.getSchedClass(node->getOpCode());
- assert(sc < (int) numInClass.size());
+ assert(sc < numInClass.size());
numInClass[sc]--;
}
inline DelaySlotInfo* getDelaySlotInfoForInstr(const SchedGraphNode* bn,
bool createIfMissing=false)
{
- std::hash_map<const SchedGraphNode*, DelaySlotInfo*>::const_iterator
+ hash_map<const SchedGraphNode*, DelaySlotInfo*>::const_iterator
I = delaySlotInfoForBranches.find(bn);
if (I != delaySlotInfoForBranches.end())
return I->second;
curTime + 1 + schedInfo.numBubblesAfter(node->getOpCode()));
}
- const vector<MachineOpCode>*
+ const std::vector<MachineOpCode>&
conflictVec = schedInfo.getConflictList(node->getOpCode());
- if (conflictVec != NULL)
- for (unsigned i=0; i < conflictVec->size(); i++)
- {
- MachineOpCode toOp = (*conflictVec)[i];
- cycles_t est = schedTime + schedInfo.getMinIssueGap(node->getOpCode(),
- toOp);
- assert(toOp < (int) nextEarliestStartTime.size());
- if (nextEarliestStartTime[toOp] < est)
- nextEarliestStartTime[toOp] = est;
- }
+ for (unsigned i=0; i < conflictVec.size(); i++)
+ {
+ MachineOpCode toOp = conflictVec[i];
+ cycles_t est=schedTime + schedInfo.getMinIssueGap(node->getOpCode(),toOp);
+ assert(toOp < (int) nextEarliestStartTime.size());
+ if (nextEarliestStartTime[toOp] < est)
+ nextEarliestStartTime[toOp] = est;
+ }
}
//************************* Internal Functions *****************************/
// of the basic block, since they are not part of the schedule.
//
static void
-RecordSchedule(const BasicBlock* bb, const SchedulingManager& S)
+RecordSchedule(MachineBasicBlock &MBB, const SchedulingManager& S)
{
- MachineCodeForBasicBlock& mvec = bb->getMachineInstrVec();
- const MachineInstrInfo& mii = S.schedInfo.getInstrInfo();
+ const TargetInstrInfo& mii = S.schedInfo.getInstrInfo();
#ifndef NDEBUG
// Lets make sure we didn't lose any instructions, except possibly
// some NOPs from delay slots. Also, PHIs are not included in the schedule.
unsigned numInstr = 0;
- for (MachineCodeForBasicBlock::iterator I=mvec.begin(); I != mvec.end(); ++I)
+ for (MachineBasicBlock::iterator I=MBB.begin(); I != MBB.end(); ++I)
if (! mii.isNop((*I)->getOpCode()) &&
! mii.isDummyPhiInstr((*I)->getOpCode()))
++numInstr;
return; // empty basic block!
// First find the dummy instructions at the start of the basic block
- MachineCodeForBasicBlock::iterator I = mvec.begin();
- for ( ; I != mvec.end(); ++I)
+ MachineBasicBlock::iterator I = MBB.begin();
+ for ( ; I != MBB.end(); ++I)
if (! mii.isDummyPhiInstr((*I)->getOpCode()))
break;
- // Erase all except the dummy PHI instructions from mvec, and
+ // Erase all except the dummy PHI instructions from MBB, and
// pre-allocate create space for the ones we will put back in.
- mvec.erase(I, mvec.end());
+ MBB.erase(I, MBB.end());
InstrSchedule::const_iterator NIend = S.isched.end();
for (InstrSchedule::const_iterator NI = S.isched.begin(); NI != NIend; ++NI)
- mvec.push_back(const_cast<MachineInstr*>((*NI)->getMachineInstr()));
+ MBB.push_back(const_cast<MachineInstr*>((*NI)->getMachineInstr()));
}
return false;
// don't put a load-use dependence in the delay slot of a branch
- const MachineInstrInfo& mii = S.getInstrInfo();
+ const TargetInstrInfo& mii = S.getInstrInfo();
for (SchedGraphNode::const_iterator EI = node->beginInEdges();
EI != node->endInEdges(); ++EI)
SchedGraphNode* brNode,
vector<SchedGraphNode*>& sdelayNodeVec)
{
- const MachineInstrInfo& mii = S.getInstrInfo();
+ const TargetInstrInfo& mii = S.getInstrInfo();
unsigned ndelays =
mii.getNumDelaySlots(brNode->getOpCode());
// If not enough useful instructions were found, mark the NOPs to be used
// for filling delay slots, otherwise, otherwise just discard them.
//
-void
-ReplaceNopsWithUsefulInstr(SchedulingManager& S,
- SchedGraphNode* node,
- vector<SchedGraphNode*> sdelayNodeVec,
- SchedGraph* graph)
+static void ReplaceNopsWithUsefulInstr(SchedulingManager& S,
+ SchedGraphNode* node,
+ vector<SchedGraphNode*> sdelayNodeVec,
+ SchedGraph* graph)
{
vector<SchedGraphNode*> nopNodeVec; // this will hold unused NOPs
- const MachineInstrInfo& mii = S.getInstrInfo();
+ const TargetInstrInfo& mii = S.getInstrInfo();
const MachineInstr* brInstr = node->getMachineInstr();
unsigned ndelays= mii.getNumDelaySlots(brInstr->getOpCode());
assert(ndelays > 0 && "Unnecessary call to replace NOPs");
// fill delay slots, otherwise, just discard them.
//
unsigned int firstDelaySlotIdx = node->getOrigIndexInBB() + 1;
- MachineCodeForBasicBlock& bbMvec = node->getBB()->getMachineInstrVec();
- assert(bbMvec[firstDelaySlotIdx - 1] == brInstr &&
+ MachineBasicBlock& MBB = node->getMachineBasicBlock();
+ assert(MBB[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(bbMvec[i]->getOpCode()))
+ if (! mii.isNop(MBB[i]->getOpCode()))
sdelayNodeVec.insert(sdelayNodeVec.begin(),
- graph->getGraphNodeForInstr(bbMvec[i]));
+ graph->getGraphNodeForInstr(MBB[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(bbMvec[i]->getOpCode()))
+ if (mii.isNop(MBB[i]->getOpCode()))
if (sdelayNodeVec.size() < ndelays)
- sdelayNodeVec.push_back(graph->getGraphNodeForInstr(bbMvec[i]));
+ sdelayNodeVec.push_back(graph->getGraphNodeForInstr(MBB[i]));
else
- nopNodeVec.push_back(graph->getGraphNodeForInstr(bbMvec[i]));
-
+ {
+ nopNodeVec.push_back(graph->getGraphNodeForInstr(MBB[i]));
+
+ //remove the MI from the Machine Code For Instruction
+ TerminatorInst *TI = MBB.getBasicBlock()->getTerminator();
+ MachineCodeForInstruction& llvmMvec =
+ MachineCodeForInstruction::get((Instruction *)TI);
+
+ for(MachineCodeForInstruction::iterator mciI=llvmMvec.begin(),
+ mciE=llvmMvec.end(); mciI!=mciE; ++mciI){
+ if (*mciI==MBB[i])
+ llvmMvec.erase(mciI);
+ }
+ }
+
assert(sdelayNodeVec.size() >= ndelays);
// If some delay slots were already filled, throw away that many new choices
// regalloc.
//
static void
-ChooseInstructionsForDelaySlots(SchedulingManager& S,
- const BasicBlock *bb,
+ChooseInstructionsForDelaySlots(SchedulingManager& S, MachineBasicBlock &MBB,
SchedGraph *graph)
{
- const MachineInstrInfo& mii = S.getInstrInfo();
- const Instruction *termInstr = (Instruction*)bb->getTerminator();
+ const TargetInstrInfo& mii = S.getInstrInfo();
+
+ Instruction *termInstr = (Instruction*)MBB.getBasicBlock()->getTerminator();
MachineCodeForInstruction &termMvec=MachineCodeForInstruction::get(termInstr);
vector<SchedGraphNode*> delayNodeVec;
const MachineInstr* brInstr = NULL;
// Simply passing in an empty delayNodeVec will have this effect.
//
delayNodeVec.clear();
- const MachineCodeForBasicBlock& bbMvec = bb->getMachineInstrVec();
- for (unsigned i=0; i < bbMvec.size(); i++)
- if (bbMvec[i] != brInstr &&
- mii.getNumDelaySlots(bbMvec[i]->getOpCode()) > 0)
+ for (unsigned i=0; i < MBB.size(); ++i)
+ if (MBB[i] != brInstr &&
+ mii.getNumDelaySlots(MBB[i]->getOpCode()) > 0)
{
- SchedGraphNode* node = graph->getGraphNodeForInstr(bbMvec[i]);
+ SchedGraphNode* node = graph->getGraphNodeForInstr(MBB[i]);
ReplaceNopsWithUsefulInstr(S, node, delayNodeVec, graph);
}
}
// getAnalysisUsage - We use LiveVarInfo...
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired(FunctionLiveVarInfo::ID);
+ AU.addRequired<FunctionLiveVarInfo>();
+ AU.setPreservesCFG();
}
- bool runOnFunction(Function *F);
+ bool runOnFunction(Function &F);
};
} // end anonymous namespace
-bool
-InstructionSchedulingWithSSA::runOnFunction(Function *M)
+bool InstructionSchedulingWithSSA::runOnFunction(Function &F)
{
- if (SchedDebugLevel == Sched_Disable)
- return false;
-
- SchedGraphSet graphSet(M, target);
+ SchedGraphSet graphSet(&F, target);
if (SchedDebugLevel >= Sched_PrintSchedGraphs)
{
GI != GE; ++GI)
{
SchedGraph* graph = (*GI);
- const vector<const BasicBlock*> &bbvec = graph->getBasicBlocks();
- assert(bbvec.size() == 1 && "Cannot schedule multiple basic blocks");
- const BasicBlock* bb = bbvec[0];
+ MachineBasicBlock &MBB = graph->getBasicBlock();
if (SchedDebugLevel >= Sched_PrintSchedTrace)
cerr << "\n*** TRACE OF INSTRUCTION SCHEDULING OPERATIONS\n\n";
// expensive!
- SchedPriorities schedPrio(M, graph,getAnalysis<FunctionLiveVarInfo>());
+ SchedPriorities schedPrio(&F, graph,getAnalysis<FunctionLiveVarInfo>());
SchedulingManager S(target, graph, schedPrio);
- ChooseInstructionsForDelaySlots(S, bb, graph); // modifies graph
-
+ ChooseInstructionsForDelaySlots(S, MBB, graph); // modifies graph
ForwardListSchedule(S); // computes schedule in S
-
- RecordSchedule(bb, S); // records schedule in BB
+ RecordSchedule(MBB, S); // records schedule in BB
}
if (SchedDebugLevel >= Sched_PrintMachineCode)
{
cerr << "\n*** Machine instructions after INSTRUCTION SCHEDULING\n";
- MachineCodeForMethod::get(M).dump();
+ MachineFunction::get(&F).dump();
}
return false;