diff --git a/lib/CodeGen/ModuloScheduling/MSchedGraph.cpp b/lib/CodeGen/ModuloScheduling/MSchedGraph.cpp index 6db099488e7..4898da8e495 100644 --- a/lib/CodeGen/ModuloScheduling/MSchedGraph.cpp +++ b/lib/CodeGen/ModuloScheduling/MSchedGraph.cpp @@ -1,4 +1,4 @@ -//===-- MSchedGraph.h - Scheduling Graph ------------------------*- C++ -*-===// +//===-- MSchedGraph.cpp - Scheduling Graph ------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,6 +13,7 @@ #define DEBUG_TYPE "ModuloSched" #include "MSchedGraph.h" +#include "../../Target/SparcV9/SparcV9RegisterInfo.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/Target/TargetInstrInfo.h" #include "Support/Debug.h" @@ -21,8 +22,8 @@ using namespace llvm; MSchedGraphNode::MSchedGraphNode(const MachineInstr* inst, MSchedGraph *graph, - unsigned late) - : Inst(inst), Parent(graph), latency(late) { + unsigned late, bool isBranch) + : Inst(inst), Parent(graph), latency(late), isBranchInstr(isBranch) { //Add to the graph graph->addNode(inst, this); @@ -118,7 +119,7 @@ void MSchedGraph::buildNodesAndEdges() { //using the op code, create a new node for it, and add to the //graph. - MachineOpCode MIopCode = MI->getOpcode(); + MachineOpCode opCode = MI->getOpcode(); int delay; #if 0 // FIXME: LOOK INTO THIS @@ -128,26 +129,30 @@ void MSchedGraph::buildNodesAndEdges() { delay = MTI.minLatency(MIopCode); else #endif - /// FIxME: get this from the sched class. - delay = 7; //MTI.maxLatency(MIopCode); + //Get delay + delay = MTI.maxLatency(opCode); //Create new node for this machine instruction and add to the graph. //Create only if not a nop - if(MTI.isNop(MIopCode)) + if(MTI.isNop(opCode)) continue; //Add PHI to phi instruction list to be processed later - if (MIopCode == TargetInstrInfo::PHI) + if (opCode == TargetInstrInfo::PHI) phiInstrs.push_back(MI); + bool isBranch = false; + + //We want to flag the branch node to treat it special + if(MTI.isBranch(opCode)) + isBranch = true; + //Node is created and added to the graph automatically - MSchedGraphNode *node = new MSchedGraphNode(MI, this, delay); + MSchedGraphNode *node = new MSchedGraphNode(MI, this, delay, isBranch); DEBUG(std::cerr << "Created Node: " << *node << "\n"); - - //Check OpCode to keep track of memory operations to add memory dependencies later. - MachineOpCode opCode = MI->getOpcode(); + //Check OpCode to keep track of memory operations to add memory dependencies later. if(MTI.isLoad(opCode) || MTI.isStore(opCode)) memInstructions.push_back(node); @@ -158,14 +163,14 @@ void MSchedGraph::buildNodesAndEdges() { //Get Operand const MachineOperand &mOp = MI->getOperand(i); - //Check if it has an allocated register (Note: this means it - //is greater then zero because zero is a special register for - //Sparc that holds the constant zero + //Check if it has an allocated register if(mOp.hasAllocatedReg()) { int regNum = mOp.getReg(); - + + if(regNum != SparcV9::g0) { //Put into our map regNumtoNodeMap[regNum].push_back(std::make_pair(i, node)); + } continue; } @@ -179,7 +184,7 @@ void MSchedGraph::buildNodesAndEdges() { assert((mOp.getVRegValue() != NULL) && "Null value is defined"); //Check if this is a read operation in a phi node, if so DO NOT PROCESS - if(mOp.isUse() && (MIopCode == TargetInstrInfo::PHI)) + if(mOp.isUse() && (opCode == TargetInstrInfo::PHI)) continue; @@ -334,24 +339,24 @@ void MSchedGraph::addMachRegEdges(std::map >& //Src only uses the register (read) if(srcIsUse) srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister, - MSchedGraphEdge::AntiDep, 1); + MSchedGraphEdge::AntiDep, 1); else if(srcIsUseandDef) { srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister, - MSchedGraphEdge::AntiDep, 1); + MSchedGraphEdge::AntiDep, 1); srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister, - MSchedGraphEdge::OutputDep, 1); + MSchedGraphEdge::OutputDep, 1); } else srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister, - MSchedGraphEdge::OutputDep, 1); + MSchedGraphEdge::OutputDep, 1); } //Dest node is a read else { if(!srcIsUse || srcIsUseandDef) srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister, - MSchedGraphEdge::TrueDep,1 ); + MSchedGraphEdge::TrueDep,1 ); } diff --git a/lib/CodeGen/ModuloScheduling/MSchedGraph.h b/lib/CodeGen/ModuloScheduling/MSchedGraph.h index 9680fc09944..0dcbb496f19 100644 --- a/lib/CodeGen/ModuloScheduling/MSchedGraph.h +++ b/lib/CodeGen/ModuloScheduling/MSchedGraph.h @@ -58,13 +58,14 @@ namespace llvm { const MachineInstr* Inst; //Machine Instruction MSchedGraph* Parent; //Graph this node belongs to unsigned latency; //Latency of Instruction - + bool isBranchInstr; //Is this node the branch instr or not + std::vector Predecessors; //Predecessor Nodes std::vector Successors; public: MSchedGraphNode(const MachineInstr *inst, MSchedGraph *graph, - unsigned late=0); + unsigned late=0, bool isBranch=false); //Iterators typedef std::vector::iterator pred_iterator; @@ -85,6 +86,7 @@ namespace llvm { MSchedGraphNode> succ_iterator; succ_iterator succ_begin(); succ_iterator succ_end(); + void addOutEdge(MSchedGraphNode *destination, @@ -103,7 +105,7 @@ namespace llvm { bool isSuccessor(MSchedGraphNode *); bool isPredecessor(MSchedGraphNode *); - + bool isBranch() { return isBranchInstr; } //Debug support void print(std::ostream &os) const; @@ -200,7 +202,7 @@ namespace llvm { iterator begin() { return GraphMap.begin(); } reverse_iterator rbegin() { return GraphMap.rbegin(); } reverse_iterator rend() { return GraphMap.rend(); } - + const TargetMachine* getTarget() { return &Target; } }; diff --git a/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp b/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp index 508467eb976..cab600e1157 100644 --- a/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp +++ b/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp @@ -135,7 +135,8 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) { II = std::max(RecMII, ResMII); - DEBUG(std::cerr << "II starts out as " << II << "\n"); + + DEBUG(std::cerr << "II starts out as " << II << " ( RecMII=" << RecMII << "and ResMII=" << ResMII << "\n"); //Calculate Node Properties calculateNodeAttributes(MSG, ResMII); @@ -165,20 +166,9 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) { //Finally schedule nodes computeSchedule(); - - //Dump out final schedule - //std::cerr << "FINALSCHEDULE\n"; - //Dump out current schedule - /*for(std::map > >::iterator J = schedule.begin(), - JE = schedule.end(); J != JE; ++J) { - std::cerr << "Cycle " << J->first << ":\n"; - for(std::vector >::iterator VI = J->second.begin(), VE = J->second.end(); VI != VE; ++VI) - std::cerr << "Resource ID: " << VI->first << " by node " << *(VI->second) << "\n"; - } - std::cerr << "END FINAL SCHEDULE\n"; - - DEBUG(std::cerr << "II ends up as " << II << "\n"); - */ + DEBUG(schedule.print(std::cerr)); + + reconstructLoop(BI); nodeToAttributesMap.clear(); @@ -265,11 +255,12 @@ int ModuloSchedulingPass::calculateResMII(const MachineBasicBlock *BI) { //Find maximum usage count //Get max number of instructions that can be issued at once. (FIXME) - int issueSlots = 1; // msi.maxNumIssueTotal; + int issueSlots = msi.maxNumIssueTotal; for(std::map::iterator RB = resourceUsageCount.begin(), RE = resourceUsageCount.end(); RB != RE; ++RB) { + //Get the total number of the resources in our cpu - //int resourceNum = msi.getCPUResourceNum(RB->first); + int resourceNum = CPUResource::getCPUResource(RB->first)->maxNumUsers; //Get total usage count for this resources unsigned usageCount = RB->second; @@ -277,9 +268,9 @@ int ModuloSchedulingPass::calculateResMII(const MachineBasicBlock *BI) { //Divide the usage count by either the max number we can issue or the number of //resources (whichever is its upper bound) double finalUsageCount; - //if( resourceNum <= issueSlots) - //finalUsageCount = ceil(1.0 * usageCount / resourceNum); - //else + if( resourceNum <= issueSlots) + finalUsageCount = ceil(1.0 * usageCount / resourceNum); + else finalUsageCount = ceil(1.0 * usageCount / issueSlots); @@ -363,7 +354,7 @@ bool ModuloSchedulingPass::ignoreEdge(MSchedGraphNode *srcNode, MSchedGraphNode return false; bool findEdge = edgesToIgnore.count(std::make_pair(srcNode, destNode->getInEdgeNum(srcNode))); - DEBUG(std::cerr << "Ignore Edge from " << *srcNode << " to " << *destNode << "? " << findEdge << "\n"); + return findEdge; } @@ -561,10 +552,23 @@ void ModuloSchedulingPass::addReccurrence(std::vector &recurre } if(!same) { - //if(srcBENode == 0 || destBENode == 0) { - srcBENode = recurrence.back(); - destBENode = recurrence.front(); - //} + srcBENode = recurrence.back(); + destBENode = recurrence.front(); + + //FIXME + if(destBENode->getInEdge(srcBENode).getIteDiff() == 0) { + //DEBUG(std::cerr << "NOT A BACKEDGE\n"); + //find actual backedge HACK HACK + for(unsigned i=0; i< recurrence.size()-1; ++i) { + if(recurrence[i+1]->getInEdge(recurrence[i]).getIteDiff() == 1) { + srcBENode = recurrence[i]; + destBENode = recurrence[i+1]; + break; + } + + } + + } DEBUG(std::cerr << "Back Edge to Remove: " << *srcBENode << " to " << *destBENode << "\n"); edgesToIgnore.insert(std::make_pair(srcBENode, destBENode->getInEdgeNum(srcBENode))); recurrenceList.insert(std::make_pair(II, recurrence)); @@ -996,42 +1000,47 @@ void ModuloSchedulingPass::computeSchedule() { int LateStart = 99999; //Set to something higher then we would ever expect (FIXME) bool hasSucc = false; bool hasPred = false; - std::set seenNodes; - - for(std::map > > >::iterator J = schedule.begin(), - JE = schedule.end(); J != JE; ++J) { - - //For each resource with nodes scheduled, loop over the nodes and see if they - //are a predecessor or successor of this current node we are trying - //to schedule. - for(std::vector > >::iterator schedNodeVec = J->second.begin(), SNE = J->second.end(); schedNodeVec != SNE; ++schedNodeVec) { + + if(!(*I)->isBranch()) { + //Loop over nodes in the schedule and determine if they are predecessors + //or successors of the node we are trying to schedule + for(MSSchedule::schedule_iterator nodesByCycle = schedule.begin(), nodesByCycleEnd = schedule.end(); + nodesByCycle != nodesByCycleEnd; ++nodesByCycle) { - for(std::vector::iterator schedNode = schedNodeVec->second.begin(), schedNodeEnd = schedNodeVec->second.end(); schedNode != schedNodeEnd; ++schedNode) { - if((*I)->isPredecessor(*schedNode) && !seenNodes.count(*schedNode)) { + //For this cycle, get the vector of nodes schedule and loop over it + for(std::vector::iterator schedNode = nodesByCycle->second.begin(), SNE = nodesByCycle->second.end(); schedNode != SNE; ++schedNode) { + + if((*I)->isPredecessor(*schedNode)) { if(!ignoreEdge(*schedNode, *I)) { int diff = (*I)->getInEdge(*schedNode).getIteDiff(); - int ES_Temp = J->first + (*schedNode)->getLatency() - diff * II; - DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << J->first << "\n"); + int ES_Temp = nodesByCycle->first + (*schedNode)->getLatency() - diff * II; + DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << nodesByCycle->first << "\n"); DEBUG(std::cerr << "Temp EarlyStart: " << ES_Temp << " Prev EarlyStart: " << EarlyStart << "\n"); EarlyStart = std::max(EarlyStart, ES_Temp); hasPred = true; } } - if((*I)->isSuccessor(*schedNode) && !seenNodes.count(*schedNode)) { + if((*I)->isSuccessor(*schedNode)) { if(!ignoreEdge(*I,*schedNode)) { int diff = (*schedNode)->getInEdge(*I).getIteDiff(); - int LS_Temp = J->first - (*I)->getLatency() + diff * II; - DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << J->first << "\n"); + int LS_Temp = nodesByCycle->first - (*I)->getLatency() + diff * II; + DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << nodesByCycle->first << "\n"); DEBUG(std::cerr << "Temp LateStart: " << LS_Temp << " Prev LateStart: " << LateStart << "\n"); LateStart = std::min(LateStart, LS_Temp); hasSucc = true; } } - seenNodes.insert(*schedNode); } } } - seenNodes.clear(); + else { + //WARNING: HACK! FIXME!!!! + EarlyStart = II-1; + LateStart = II-1; + hasPred = 1; + hasSucc = 1; + } + DEBUG(std::cerr << "Has Successors: " << hasSucc << ", Has Pred: " << hasPred << "\n"); DEBUG(std::cerr << "EarlyStart: " << EarlyStart << ", LateStart: " << LateStart << "\n"); @@ -1058,6 +1067,13 @@ void ModuloSchedulingPass::computeSchedule() { } } + + DEBUG(std::cerr << "Constructing Kernel\n"); + success = schedule.constructKernel(II); + if(!success) { + ++II; + schedule.clear(); + } } } @@ -1068,17 +1084,6 @@ bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node, DEBUG(std::cerr << *node << " (Start Cycle: " << start << ", End Cycle: " << end << ")\n"); - /*std::cerr << "CURRENT SCHEDULE\n"; - //Dump out current schedule - for(std::map > >::iterator J = schedule.begin(), - JE = schedule.end(); J != JE; ++J) { - std::cerr << "Cycle " << J->first << ":\n"; - for(std::vector >::iterator VI = J->second.begin(), VE = J->second.end(); VI != VE; ++VI) - std::cerr << "Resource ID: " << VI->first << " by node " << *(VI->second) << "\n"; - } - std::cerr << "END CURRENT SCHEDULE\n"; - */ - //Make sure start and end are not negative if(start < 0) start = 0; @@ -1089,10 +1094,7 @@ bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node, if(start > end) forward = false; - const TargetSchedInfo & msi = target.getSchedInfo(); - bool increaseSC = true; - int cycle = start ; @@ -1100,79 +1102,8 @@ bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node, increaseSC = false; - //Get the resource used by this instruction - //Get resource usage for this instruction - InstrRUsage rUsage = msi.getInstrRUsage(node->getInst()->getOpcode()); - std::vector > resources = rUsage.resourcesByCycle; - - //Loop over each resource and see if we can put it into the schedule - for(unsigned r=0; r < resources.size(); ++r) { - unsigned intermediateCycle = cycle + r; - - for(unsigned j=0; j < resources[r].size(); ++j) { - //Put it into the schedule - DEBUG(std::cerr << "Attempting to put resource " << resources[r][j] << " in schedule at cycle: " << intermediateCycle << "\n"); - - //Check if resource is free at this cycle - std::vector > > resourceForCycle = schedule[intermediateCycle]; - - //Vector of nodes using this resource - std::vector *nodesUsingResource; - - for(std::vector > >::iterator I = resourceForCycle.begin(), E= resourceForCycle.end(); I != E; ++I) { - - if(I->first == resources[r][j]) { - //Get the number of available for this resource - unsigned numResource = CPUResource::getCPUResource(resources[r][j])->maxNumUsers; - nodesUsingResource = &(I->second); - - //Check that there are enough of this resource, otherwise - //we need to increase/decrease the cycle - if(I->second.size() >= numResource) { - DEBUG(std::cerr << "No open spot for this resource in this cycle\n"); - increaseSC = true; - } - break; - - } - //safe to put into schedule - } - - if(increaseSC) - break; - - else { - DEBUG(std::cerr << "Found spot in schedule\n"); - //Add node to resource vector - if(nodesUsingResource == 0) { - nodesUsingResource = new std::vector; - resourceForCycle.push_back(std::make_pair(resources[r][j], *nodesUsingResource)); - } - - nodesUsingResource->push_back(node); - - schedule[intermediateCycle] = resourceForCycle; - } - } - if(increaseSC) { - /*for(unsigned x = 0; x < r; ++x) { - unsigned removeCycle = x + start; - for(unsigned j=0; j < resources[x].size(); ++j) { - std::vector > resourceForCycle = schedule[removeCycle]; - for(std::vector >::iterator I = resourceForCycle.begin(), E= resourceForCycle.end(); I != E; ++I) { - if(I->first == resources[x][j]) { - //remove it - resourceForCycle.erase(I); - } - } - //Put vector back - schedule[removeCycle] = resourceForCycle; - } - }*/ - - break; - } - } + increaseSC = schedule.insert(node, cycle); + if(!increaseSC) return true; @@ -1190,5 +1121,202 @@ bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node, return false; } } + return success; } + +/*void ModuloSchedulingPass::saveValue(const MachineInstr *inst, std::set &valuestoSave, std::vector *valuesForNode) { + int numFound = 0; + Instruction *tmp; + + //For each value* in this inst that is a def, we want to save a copy + //Target info + const TargetInstrInfo & mii = target.getInstrInfo(); + for(unsigned i=0; i < inst->getNumOperands(); ++i) { + //get machine operand + const MachineOperand &mOp = inst->getOperand(i); + if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) { + //Save copy in tmpInstruction + numFound++; + tmp = TmpInstruction(mii.getMachineCodeFor(mOp.getVRegValue()), + mOp.getVRegValue()); + valuesForNode->push_back(tmp); + } + } + + assert(numFound == 1 && "We should have only found one def to this virtual register!"); +}*/ + +void ModuloSchedulingPass::writePrologue(std::vector &prologues, MachineBasicBlock *origBB, std::vector &llvm_prologues) { + std::map > inKernel; + int maxStageCount = 0; + + for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) { + maxStageCount = std::max(maxStageCount, I->second); + + //Ignore the branch, we will handle this separately + if(I->first->isBranch()) + continue; + + //Put int the map so we know what instructions in each stage are in the kernel + if(I->second > 0) + inKernel[I->second].insert(I->first->getInst()); + } + + //Now write the prologues + for(std::map >::iterator I = inKernel.begin(), E = inKernel.end(); + I != E; ++I) { + BasicBlock *llvmBB = new BasicBlock(); + MachineBasicBlock *machineBB = new MachineBasicBlock(llvmBB); + + //Loop over original machine basic block. If we see an instruction from this + //stage that is NOT in the kernel, then it needs to be added into the prologue + //We go in order to preserve dependencies + for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) { + if(I->second.count(&*MI)) + continue; + else + machineBB->push_back(MI->clone()); + } + + prologues.push_back(machineBB); + llvm_prologues.push_back(llvmBB); + } +} + + +void ModuloSchedulingPass::reconstructLoop(const MachineBasicBlock *BB) { + + //The new loop will consist of an prologue, the kernel, and one or more epilogues. + + std::vector prologues; + std::vector llvm_prologues; + + + + //create a vector of epilogues corresponding to each stage + /*std::vector epilogues; + + //Create kernel + MachineBasicBlock *kernel = new MachineBasicBlock(); + + //keep track of stage count + int stageCount = 0; + + //Target info + const TargetInstrInfo & mii = target.getInstrInfo(); + + //Map for creating MachinePhis + std::map > nodeAndValueMap; + + + //Loop through the kernel and clone instructions that need to be put into the prologue + for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) { + //For each pair see if the stage is greater then 0 + //if so, then ALL instructions before this in the original loop, need to be + //copied into the prologue + MachineBasicBlock::const_iterator actualInst; + + + //ignore branch + if(I->first->isBranch()) + continue; + + if(I->second > 0) { + + assert(I->second >= stageCount && "Visiting instruction from previous stage count.\n"); + + + //Make a set that has all the Value*'s that we read + std::set valuesToSave; + + //For this instruction, get the Value*'s that it reads and put them into the set. + //Assert if there is an operand of another type that we need to save + const MachineInstr *inst = I->first->getInst(); + for(unsigned i=0; i < inst->getNumOperands(); ++i) { + //get machine operand + const MachineOperand &mOp = inst->getOperand(i); + + if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) { + //find the value in the map + if (const Value* srcI = mOp.getVRegValue()) + valuesToSave.insert(srcI); + } + + if(mOp.getType() != MachineOperand::MO_VirtualRegister && mOp.isUse()) { + assert("Our assumption is wrong. We have another type of register that needs to be saved\n"); + } + } + + //Check if we skipped a stage count, we need to add that stuff here + if(I->second - stageCount > 1) { + int temp = stageCount; + while(I->second - temp > 1) { + for(MachineBasicBlock::const_iterator MI = BB->begin(), ME = BB->end(); ME != MI; ++MI) { + //Check that MI is not a branch before adding, we add branches separately + if(!mii.isBranch(MI->getOpcode()) && !mii.isNop(MI->getOpcode())) { + prologue->push_back(MI->clone()); + saveValue(&*MI, valuesToSave); + } + } + ++temp; + } + } + + if(I->second == stageCount) + continue; + + stageCount = I->second; + DEBUG(std::cerr << "Found Instruction from Stage > 0\n"); + //Loop over instructions in original basic block and clone them. Add to the prologue + for (MachineBasicBlock::const_iterator MI = BB->begin(), e = BB->end(); MI != e; ++MI) { + if(&*MI == I->first->getInst()) { + actualInst = MI; + break; + } + else { + //Check that MI is not a branch before adding, we add branches separately + if(!mii.isBranch(MI->getOpcode()) && !mii.isNop(MI->getOpcode())) + prologue->push_back(MI->clone()); + } + } + + //Now add in all instructions from this one on to its corresponding epilogue + MachineBasicBlock *epi = new MachineBasicBlock(); + epilogues.push_back(epi); + + for(MachineBasicBlock::const_iterator MI = actualInst, ME = BB->end(); ME != MI; ++MI) { + //Check that MI is not a branch before adding, we add branches separately + if(!mii.isBranch(MI->getOpcode()) && !mii.isNop(MI->getOpcode())) + epi->push_back(MI->clone()); + } + } + } + + //Create kernel + for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), + E = schedule.kernel_end(); I != E; ++I) { + kernel->push_back(I->first->getInst()->clone()); + + } + + //Debug stuff + ((MachineBasicBlock*)BB)->getParent()->getBasicBlockList().push_back(prologue); + std::cerr << "PROLOGUE:\n"; + prologue->print(std::cerr); + + ((MachineBasicBlock*)BB)->getParent()->getBasicBlockList().push_back(kernel); + std::cerr << "KERNEL: \n"; + kernel->print(std::cerr); + + for(std::vector::iterator MBB = epilogues.begin(), ME = epilogues.end(); + MBB != ME; ++MBB) { + std::cerr << "EPILOGUE:\n"; + ((MachineBasicBlock*)BB)->getParent()->getBasicBlockList().push_back(*MBB); + (*MBB)->print(std::cerr); + }*/ + + + +} + diff --git a/lib/CodeGen/ModuloScheduling/ModuloScheduling.h b/lib/CodeGen/ModuloScheduling/ModuloScheduling.h index b573b104868..62abc7c5286 100644 --- a/lib/CodeGen/ModuloScheduling/ModuloScheduling.h +++ b/lib/CodeGen/ModuloScheduling/ModuloScheduling.h @@ -14,6 +14,7 @@ #define LLVM_MODULOSCHEDULING_H #include "MSchedGraph.h" +#include "MSSchedule.h" #include "llvm/Function.h" #include "llvm/Pass.h" #include @@ -54,7 +55,7 @@ namespace llvm { std::vector FinalNodeOrder; //Schedule table, key is the cycle number and the vector is resource, node pairs - std::map > > > schedule; + MSSchedule schedule; //Current initiation interval int II; @@ -87,6 +88,12 @@ namespace llvm { void predIntersect(std::vector &CurrentSet, std::vector &IntersectResult); void succIntersect(std::vector &CurrentSet, std::vector &IntersectResult); + + void reconstructLoop(const MachineBasicBlock*); + + //void saveValue(const MachineInstr*, const std::set&, std::vector*); + + void writePrologue(std::vector &prologues, MachineBasicBlock *origBB, std::vector &llvm_prologues); public: ModuloSchedulingPass(TargetMachine &targ) : target(targ) {} diff --git a/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp b/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp index 6db099488e7..4898da8e495 100644 --- a/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp +++ b/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.cpp @@ -1,4 +1,4 @@ -//===-- MSchedGraph.h - Scheduling Graph ------------------------*- C++ -*-===// +//===-- MSchedGraph.cpp - Scheduling Graph ------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,6 +13,7 @@ #define DEBUG_TYPE "ModuloSched" #include "MSchedGraph.h" +#include "../../Target/SparcV9/SparcV9RegisterInfo.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/Target/TargetInstrInfo.h" #include "Support/Debug.h" @@ -21,8 +22,8 @@ using namespace llvm; MSchedGraphNode::MSchedGraphNode(const MachineInstr* inst, MSchedGraph *graph, - unsigned late) - : Inst(inst), Parent(graph), latency(late) { + unsigned late, bool isBranch) + : Inst(inst), Parent(graph), latency(late), isBranchInstr(isBranch) { //Add to the graph graph->addNode(inst, this); @@ -118,7 +119,7 @@ void MSchedGraph::buildNodesAndEdges() { //using the op code, create a new node for it, and add to the //graph. - MachineOpCode MIopCode = MI->getOpcode(); + MachineOpCode opCode = MI->getOpcode(); int delay; #if 0 // FIXME: LOOK INTO THIS @@ -128,26 +129,30 @@ void MSchedGraph::buildNodesAndEdges() { delay = MTI.minLatency(MIopCode); else #endif - /// FIxME: get this from the sched class. - delay = 7; //MTI.maxLatency(MIopCode); + //Get delay + delay = MTI.maxLatency(opCode); //Create new node for this machine instruction and add to the graph. //Create only if not a nop - if(MTI.isNop(MIopCode)) + if(MTI.isNop(opCode)) continue; //Add PHI to phi instruction list to be processed later - if (MIopCode == TargetInstrInfo::PHI) + if (opCode == TargetInstrInfo::PHI) phiInstrs.push_back(MI); + bool isBranch = false; + + //We want to flag the branch node to treat it special + if(MTI.isBranch(opCode)) + isBranch = true; + //Node is created and added to the graph automatically - MSchedGraphNode *node = new MSchedGraphNode(MI, this, delay); + MSchedGraphNode *node = new MSchedGraphNode(MI, this, delay, isBranch); DEBUG(std::cerr << "Created Node: " << *node << "\n"); - - //Check OpCode to keep track of memory operations to add memory dependencies later. - MachineOpCode opCode = MI->getOpcode(); + //Check OpCode to keep track of memory operations to add memory dependencies later. if(MTI.isLoad(opCode) || MTI.isStore(opCode)) memInstructions.push_back(node); @@ -158,14 +163,14 @@ void MSchedGraph::buildNodesAndEdges() { //Get Operand const MachineOperand &mOp = MI->getOperand(i); - //Check if it has an allocated register (Note: this means it - //is greater then zero because zero is a special register for - //Sparc that holds the constant zero + //Check if it has an allocated register if(mOp.hasAllocatedReg()) { int regNum = mOp.getReg(); - + + if(regNum != SparcV9::g0) { //Put into our map regNumtoNodeMap[regNum].push_back(std::make_pair(i, node)); + } continue; } @@ -179,7 +184,7 @@ void MSchedGraph::buildNodesAndEdges() { assert((mOp.getVRegValue() != NULL) && "Null value is defined"); //Check if this is a read operation in a phi node, if so DO NOT PROCESS - if(mOp.isUse() && (MIopCode == TargetInstrInfo::PHI)) + if(mOp.isUse() && (opCode == TargetInstrInfo::PHI)) continue; @@ -334,24 +339,24 @@ void MSchedGraph::addMachRegEdges(std::map >& //Src only uses the register (read) if(srcIsUse) srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister, - MSchedGraphEdge::AntiDep, 1); + MSchedGraphEdge::AntiDep, 1); else if(srcIsUseandDef) { srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister, - MSchedGraphEdge::AntiDep, 1); + MSchedGraphEdge::AntiDep, 1); srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister, - MSchedGraphEdge::OutputDep, 1); + MSchedGraphEdge::OutputDep, 1); } else srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister, - MSchedGraphEdge::OutputDep, 1); + MSchedGraphEdge::OutputDep, 1); } //Dest node is a read else { if(!srcIsUse || srcIsUseandDef) srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister, - MSchedGraphEdge::TrueDep,1 ); + MSchedGraphEdge::TrueDep,1 ); } diff --git a/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h b/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h index 9680fc09944..0dcbb496f19 100644 --- a/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h +++ b/lib/Target/SparcV9/ModuloScheduling/MSchedGraph.h @@ -58,13 +58,14 @@ namespace llvm { const MachineInstr* Inst; //Machine Instruction MSchedGraph* Parent; //Graph this node belongs to unsigned latency; //Latency of Instruction - + bool isBranchInstr; //Is this node the branch instr or not + std::vector Predecessors; //Predecessor Nodes std::vector Successors; public: MSchedGraphNode(const MachineInstr *inst, MSchedGraph *graph, - unsigned late=0); + unsigned late=0, bool isBranch=false); //Iterators typedef std::vector::iterator pred_iterator; @@ -85,6 +86,7 @@ namespace llvm { MSchedGraphNode> succ_iterator; succ_iterator succ_begin(); succ_iterator succ_end(); + void addOutEdge(MSchedGraphNode *destination, @@ -103,7 +105,7 @@ namespace llvm { bool isSuccessor(MSchedGraphNode *); bool isPredecessor(MSchedGraphNode *); - + bool isBranch() { return isBranchInstr; } //Debug support void print(std::ostream &os) const; @@ -200,7 +202,7 @@ namespace llvm { iterator begin() { return GraphMap.begin(); } reverse_iterator rbegin() { return GraphMap.rbegin(); } reverse_iterator rend() { return GraphMap.rend(); } - + const TargetMachine* getTarget() { return &Target; } }; diff --git a/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.cpp b/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.cpp index 508467eb976..cab600e1157 100644 --- a/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.cpp +++ b/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.cpp @@ -135,7 +135,8 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) { II = std::max(RecMII, ResMII); - DEBUG(std::cerr << "II starts out as " << II << "\n"); + + DEBUG(std::cerr << "II starts out as " << II << " ( RecMII=" << RecMII << "and ResMII=" << ResMII << "\n"); //Calculate Node Properties calculateNodeAttributes(MSG, ResMII); @@ -165,20 +166,9 @@ bool ModuloSchedulingPass::runOnFunction(Function &F) { //Finally schedule nodes computeSchedule(); - - //Dump out final schedule - //std::cerr << "FINALSCHEDULE\n"; - //Dump out current schedule - /*for(std::map > >::iterator J = schedule.begin(), - JE = schedule.end(); J != JE; ++J) { - std::cerr << "Cycle " << J->first << ":\n"; - for(std::vector >::iterator VI = J->second.begin(), VE = J->second.end(); VI != VE; ++VI) - std::cerr << "Resource ID: " << VI->first << " by node " << *(VI->second) << "\n"; - } - std::cerr << "END FINAL SCHEDULE\n"; - - DEBUG(std::cerr << "II ends up as " << II << "\n"); - */ + DEBUG(schedule.print(std::cerr)); + + reconstructLoop(BI); nodeToAttributesMap.clear(); @@ -265,11 +255,12 @@ int ModuloSchedulingPass::calculateResMII(const MachineBasicBlock *BI) { //Find maximum usage count //Get max number of instructions that can be issued at once. (FIXME) - int issueSlots = 1; // msi.maxNumIssueTotal; + int issueSlots = msi.maxNumIssueTotal; for(std::map::iterator RB = resourceUsageCount.begin(), RE = resourceUsageCount.end(); RB != RE; ++RB) { + //Get the total number of the resources in our cpu - //int resourceNum = msi.getCPUResourceNum(RB->first); + int resourceNum = CPUResource::getCPUResource(RB->first)->maxNumUsers; //Get total usage count for this resources unsigned usageCount = RB->second; @@ -277,9 +268,9 @@ int ModuloSchedulingPass::calculateResMII(const MachineBasicBlock *BI) { //Divide the usage count by either the max number we can issue or the number of //resources (whichever is its upper bound) double finalUsageCount; - //if( resourceNum <= issueSlots) - //finalUsageCount = ceil(1.0 * usageCount / resourceNum); - //else + if( resourceNum <= issueSlots) + finalUsageCount = ceil(1.0 * usageCount / resourceNum); + else finalUsageCount = ceil(1.0 * usageCount / issueSlots); @@ -363,7 +354,7 @@ bool ModuloSchedulingPass::ignoreEdge(MSchedGraphNode *srcNode, MSchedGraphNode return false; bool findEdge = edgesToIgnore.count(std::make_pair(srcNode, destNode->getInEdgeNum(srcNode))); - DEBUG(std::cerr << "Ignore Edge from " << *srcNode << " to " << *destNode << "? " << findEdge << "\n"); + return findEdge; } @@ -561,10 +552,23 @@ void ModuloSchedulingPass::addReccurrence(std::vector &recurre } if(!same) { - //if(srcBENode == 0 || destBENode == 0) { - srcBENode = recurrence.back(); - destBENode = recurrence.front(); - //} + srcBENode = recurrence.back(); + destBENode = recurrence.front(); + + //FIXME + if(destBENode->getInEdge(srcBENode).getIteDiff() == 0) { + //DEBUG(std::cerr << "NOT A BACKEDGE\n"); + //find actual backedge HACK HACK + for(unsigned i=0; i< recurrence.size()-1; ++i) { + if(recurrence[i+1]->getInEdge(recurrence[i]).getIteDiff() == 1) { + srcBENode = recurrence[i]; + destBENode = recurrence[i+1]; + break; + } + + } + + } DEBUG(std::cerr << "Back Edge to Remove: " << *srcBENode << " to " << *destBENode << "\n"); edgesToIgnore.insert(std::make_pair(srcBENode, destBENode->getInEdgeNum(srcBENode))); recurrenceList.insert(std::make_pair(II, recurrence)); @@ -996,42 +1000,47 @@ void ModuloSchedulingPass::computeSchedule() { int LateStart = 99999; //Set to something higher then we would ever expect (FIXME) bool hasSucc = false; bool hasPred = false; - std::set seenNodes; - - for(std::map > > >::iterator J = schedule.begin(), - JE = schedule.end(); J != JE; ++J) { - - //For each resource with nodes scheduled, loop over the nodes and see if they - //are a predecessor or successor of this current node we are trying - //to schedule. - for(std::vector > >::iterator schedNodeVec = J->second.begin(), SNE = J->second.end(); schedNodeVec != SNE; ++schedNodeVec) { + + if(!(*I)->isBranch()) { + //Loop over nodes in the schedule and determine if they are predecessors + //or successors of the node we are trying to schedule + for(MSSchedule::schedule_iterator nodesByCycle = schedule.begin(), nodesByCycleEnd = schedule.end(); + nodesByCycle != nodesByCycleEnd; ++nodesByCycle) { - for(std::vector::iterator schedNode = schedNodeVec->second.begin(), schedNodeEnd = schedNodeVec->second.end(); schedNode != schedNodeEnd; ++schedNode) { - if((*I)->isPredecessor(*schedNode) && !seenNodes.count(*schedNode)) { + //For this cycle, get the vector of nodes schedule and loop over it + for(std::vector::iterator schedNode = nodesByCycle->second.begin(), SNE = nodesByCycle->second.end(); schedNode != SNE; ++schedNode) { + + if((*I)->isPredecessor(*schedNode)) { if(!ignoreEdge(*schedNode, *I)) { int diff = (*I)->getInEdge(*schedNode).getIteDiff(); - int ES_Temp = J->first + (*schedNode)->getLatency() - diff * II; - DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << J->first << "\n"); + int ES_Temp = nodesByCycle->first + (*schedNode)->getLatency() - diff * II; + DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << nodesByCycle->first << "\n"); DEBUG(std::cerr << "Temp EarlyStart: " << ES_Temp << " Prev EarlyStart: " << EarlyStart << "\n"); EarlyStart = std::max(EarlyStart, ES_Temp); hasPred = true; } } - if((*I)->isSuccessor(*schedNode) && !seenNodes.count(*schedNode)) { + if((*I)->isSuccessor(*schedNode)) { if(!ignoreEdge(*I,*schedNode)) { int diff = (*schedNode)->getInEdge(*I).getIteDiff(); - int LS_Temp = J->first - (*I)->getLatency() + diff * II; - DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << J->first << "\n"); + int LS_Temp = nodesByCycle->first - (*I)->getLatency() + diff * II; + DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << nodesByCycle->first << "\n"); DEBUG(std::cerr << "Temp LateStart: " << LS_Temp << " Prev LateStart: " << LateStart << "\n"); LateStart = std::min(LateStart, LS_Temp); hasSucc = true; } } - seenNodes.insert(*schedNode); } } } - seenNodes.clear(); + else { + //WARNING: HACK! FIXME!!!! + EarlyStart = II-1; + LateStart = II-1; + hasPred = 1; + hasSucc = 1; + } + DEBUG(std::cerr << "Has Successors: " << hasSucc << ", Has Pred: " << hasPred << "\n"); DEBUG(std::cerr << "EarlyStart: " << EarlyStart << ", LateStart: " << LateStart << "\n"); @@ -1058,6 +1067,13 @@ void ModuloSchedulingPass::computeSchedule() { } } + + DEBUG(std::cerr << "Constructing Kernel\n"); + success = schedule.constructKernel(II); + if(!success) { + ++II; + schedule.clear(); + } } } @@ -1068,17 +1084,6 @@ bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node, DEBUG(std::cerr << *node << " (Start Cycle: " << start << ", End Cycle: " << end << ")\n"); - /*std::cerr << "CURRENT SCHEDULE\n"; - //Dump out current schedule - for(std::map > >::iterator J = schedule.begin(), - JE = schedule.end(); J != JE; ++J) { - std::cerr << "Cycle " << J->first << ":\n"; - for(std::vector >::iterator VI = J->second.begin(), VE = J->second.end(); VI != VE; ++VI) - std::cerr << "Resource ID: " << VI->first << " by node " << *(VI->second) << "\n"; - } - std::cerr << "END CURRENT SCHEDULE\n"; - */ - //Make sure start and end are not negative if(start < 0) start = 0; @@ -1089,10 +1094,7 @@ bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node, if(start > end) forward = false; - const TargetSchedInfo & msi = target.getSchedInfo(); - bool increaseSC = true; - int cycle = start ; @@ -1100,79 +1102,8 @@ bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node, increaseSC = false; - //Get the resource used by this instruction - //Get resource usage for this instruction - InstrRUsage rUsage = msi.getInstrRUsage(node->getInst()->getOpcode()); - std::vector > resources = rUsage.resourcesByCycle; - - //Loop over each resource and see if we can put it into the schedule - for(unsigned r=0; r < resources.size(); ++r) { - unsigned intermediateCycle = cycle + r; - - for(unsigned j=0; j < resources[r].size(); ++j) { - //Put it into the schedule - DEBUG(std::cerr << "Attempting to put resource " << resources[r][j] << " in schedule at cycle: " << intermediateCycle << "\n"); - - //Check if resource is free at this cycle - std::vector > > resourceForCycle = schedule[intermediateCycle]; - - //Vector of nodes using this resource - std::vector *nodesUsingResource; - - for(std::vector > >::iterator I = resourceForCycle.begin(), E= resourceForCycle.end(); I != E; ++I) { - - if(I->first == resources[r][j]) { - //Get the number of available for this resource - unsigned numResource = CPUResource::getCPUResource(resources[r][j])->maxNumUsers; - nodesUsingResource = &(I->second); - - //Check that there are enough of this resource, otherwise - //we need to increase/decrease the cycle - if(I->second.size() >= numResource) { - DEBUG(std::cerr << "No open spot for this resource in this cycle\n"); - increaseSC = true; - } - break; - - } - //safe to put into schedule - } - - if(increaseSC) - break; - - else { - DEBUG(std::cerr << "Found spot in schedule\n"); - //Add node to resource vector - if(nodesUsingResource == 0) { - nodesUsingResource = new std::vector; - resourceForCycle.push_back(std::make_pair(resources[r][j], *nodesUsingResource)); - } - - nodesUsingResource->push_back(node); - - schedule[intermediateCycle] = resourceForCycle; - } - } - if(increaseSC) { - /*for(unsigned x = 0; x < r; ++x) { - unsigned removeCycle = x + start; - for(unsigned j=0; j < resources[x].size(); ++j) { - std::vector > resourceForCycle = schedule[removeCycle]; - for(std::vector >::iterator I = resourceForCycle.begin(), E= resourceForCycle.end(); I != E; ++I) { - if(I->first == resources[x][j]) { - //remove it - resourceForCycle.erase(I); - } - } - //Put vector back - schedule[removeCycle] = resourceForCycle; - } - }*/ - - break; - } - } + increaseSC = schedule.insert(node, cycle); + if(!increaseSC) return true; @@ -1190,5 +1121,202 @@ bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node, return false; } } + return success; } + +/*void ModuloSchedulingPass::saveValue(const MachineInstr *inst, std::set &valuestoSave, std::vector *valuesForNode) { + int numFound = 0; + Instruction *tmp; + + //For each value* in this inst that is a def, we want to save a copy + //Target info + const TargetInstrInfo & mii = target.getInstrInfo(); + for(unsigned i=0; i < inst->getNumOperands(); ++i) { + //get machine operand + const MachineOperand &mOp = inst->getOperand(i); + if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) { + //Save copy in tmpInstruction + numFound++; + tmp = TmpInstruction(mii.getMachineCodeFor(mOp.getVRegValue()), + mOp.getVRegValue()); + valuesForNode->push_back(tmp); + } + } + + assert(numFound == 1 && "We should have only found one def to this virtual register!"); +}*/ + +void ModuloSchedulingPass::writePrologue(std::vector &prologues, MachineBasicBlock *origBB, std::vector &llvm_prologues) { + std::map > inKernel; + int maxStageCount = 0; + + for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) { + maxStageCount = std::max(maxStageCount, I->second); + + //Ignore the branch, we will handle this separately + if(I->first->isBranch()) + continue; + + //Put int the map so we know what instructions in each stage are in the kernel + if(I->second > 0) + inKernel[I->second].insert(I->first->getInst()); + } + + //Now write the prologues + for(std::map >::iterator I = inKernel.begin(), E = inKernel.end(); + I != E; ++I) { + BasicBlock *llvmBB = new BasicBlock(); + MachineBasicBlock *machineBB = new MachineBasicBlock(llvmBB); + + //Loop over original machine basic block. If we see an instruction from this + //stage that is NOT in the kernel, then it needs to be added into the prologue + //We go in order to preserve dependencies + for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) { + if(I->second.count(&*MI)) + continue; + else + machineBB->push_back(MI->clone()); + } + + prologues.push_back(machineBB); + llvm_prologues.push_back(llvmBB); + } +} + + +void ModuloSchedulingPass::reconstructLoop(const MachineBasicBlock *BB) { + + //The new loop will consist of an prologue, the kernel, and one or more epilogues. + + std::vector prologues; + std::vector llvm_prologues; + + + + //create a vector of epilogues corresponding to each stage + /*std::vector epilogues; + + //Create kernel + MachineBasicBlock *kernel = new MachineBasicBlock(); + + //keep track of stage count + int stageCount = 0; + + //Target info + const TargetInstrInfo & mii = target.getInstrInfo(); + + //Map for creating MachinePhis + std::map > nodeAndValueMap; + + + //Loop through the kernel and clone instructions that need to be put into the prologue + for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) { + //For each pair see if the stage is greater then 0 + //if so, then ALL instructions before this in the original loop, need to be + //copied into the prologue + MachineBasicBlock::const_iterator actualInst; + + + //ignore branch + if(I->first->isBranch()) + continue; + + if(I->second > 0) { + + assert(I->second >= stageCount && "Visiting instruction from previous stage count.\n"); + + + //Make a set that has all the Value*'s that we read + std::set valuesToSave; + + //For this instruction, get the Value*'s that it reads and put them into the set. + //Assert if there is an operand of another type that we need to save + const MachineInstr *inst = I->first->getInst(); + for(unsigned i=0; i < inst->getNumOperands(); ++i) { + //get machine operand + const MachineOperand &mOp = inst->getOperand(i); + + if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) { + //find the value in the map + if (const Value* srcI = mOp.getVRegValue()) + valuesToSave.insert(srcI); + } + + if(mOp.getType() != MachineOperand::MO_VirtualRegister && mOp.isUse()) { + assert("Our assumption is wrong. We have another type of register that needs to be saved\n"); + } + } + + //Check if we skipped a stage count, we need to add that stuff here + if(I->second - stageCount > 1) { + int temp = stageCount; + while(I->second - temp > 1) { + for(MachineBasicBlock::const_iterator MI = BB->begin(), ME = BB->end(); ME != MI; ++MI) { + //Check that MI is not a branch before adding, we add branches separately + if(!mii.isBranch(MI->getOpcode()) && !mii.isNop(MI->getOpcode())) { + prologue->push_back(MI->clone()); + saveValue(&*MI, valuesToSave); + } + } + ++temp; + } + } + + if(I->second == stageCount) + continue; + + stageCount = I->second; + DEBUG(std::cerr << "Found Instruction from Stage > 0\n"); + //Loop over instructions in original basic block and clone them. Add to the prologue + for (MachineBasicBlock::const_iterator MI = BB->begin(), e = BB->end(); MI != e; ++MI) { + if(&*MI == I->first->getInst()) { + actualInst = MI; + break; + } + else { + //Check that MI is not a branch before adding, we add branches separately + if(!mii.isBranch(MI->getOpcode()) && !mii.isNop(MI->getOpcode())) + prologue->push_back(MI->clone()); + } + } + + //Now add in all instructions from this one on to its corresponding epilogue + MachineBasicBlock *epi = new MachineBasicBlock(); + epilogues.push_back(epi); + + for(MachineBasicBlock::const_iterator MI = actualInst, ME = BB->end(); ME != MI; ++MI) { + //Check that MI is not a branch before adding, we add branches separately + if(!mii.isBranch(MI->getOpcode()) && !mii.isNop(MI->getOpcode())) + epi->push_back(MI->clone()); + } + } + } + + //Create kernel + for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), + E = schedule.kernel_end(); I != E; ++I) { + kernel->push_back(I->first->getInst()->clone()); + + } + + //Debug stuff + ((MachineBasicBlock*)BB)->getParent()->getBasicBlockList().push_back(prologue); + std::cerr << "PROLOGUE:\n"; + prologue->print(std::cerr); + + ((MachineBasicBlock*)BB)->getParent()->getBasicBlockList().push_back(kernel); + std::cerr << "KERNEL: \n"; + kernel->print(std::cerr); + + for(std::vector::iterator MBB = epilogues.begin(), ME = epilogues.end(); + MBB != ME; ++MBB) { + std::cerr << "EPILOGUE:\n"; + ((MachineBasicBlock*)BB)->getParent()->getBasicBlockList().push_back(*MBB); + (*MBB)->print(std::cerr); + }*/ + + + +} + diff --git a/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.h b/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.h index b573b104868..62abc7c5286 100644 --- a/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.h +++ b/lib/Target/SparcV9/ModuloScheduling/ModuloScheduling.h @@ -14,6 +14,7 @@ #define LLVM_MODULOSCHEDULING_H #include "MSchedGraph.h" +#include "MSSchedule.h" #include "llvm/Function.h" #include "llvm/Pass.h" #include @@ -54,7 +55,7 @@ namespace llvm { std::vector FinalNodeOrder; //Schedule table, key is the cycle number and the vector is resource, node pairs - std::map > > > schedule; + MSSchedule schedule; //Current initiation interval int II; @@ -87,6 +88,12 @@ namespace llvm { void predIntersect(std::vector &CurrentSet, std::vector &IntersectResult); void succIntersect(std::vector &CurrentSet, std::vector &IntersectResult); + + void reconstructLoop(const MachineBasicBlock*); + + //void saveValue(const MachineInstr*, const std::set&, std::vector*); + + void writePrologue(std::vector &prologues, MachineBasicBlock *origBB, std::vector &llvm_prologues); public: ModuloSchedulingPass(TargetMachine &targ) : target(targ) {}