Updating my cvs versions. THis is still in progress and much will be changed.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@13782 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Tanya Lattner 2004-05-26 06:27:18 +00:00
parent 1812268126
commit 4cffb588f5
8 changed files with 598 additions and 314 deletions

View File

@ -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<int, std::vector<OpIndexNodePair> >&
//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 );
}

View File

@ -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<MSchedGraphNode*> Predecessors; //Predecessor Nodes
std::vector<MSchedGraphEdge> Successors;
public:
MSchedGraphNode(const MachineInstr *inst, MSchedGraph *graph,
unsigned late=0);
unsigned late=0, bool isBranch=false);
//Iterators
typedef std::vector<MSchedGraphNode*>::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; }
};

View File

@ -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<unsigned, std::vector<std::pair<unsigned, MSchedGraphNode*> > >::iterator J = schedule.begin(),
JE = schedule.end(); J != JE; ++J) {
std::cerr << "Cycle " << J->first << ":\n";
for(std::vector<std::pair<unsigned, MSchedGraphNode*> >::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<unsigned,unsigned>::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<MSchedGraphNode*> &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<MSchedGraphNode*> seenNodes;
for(std::map<unsigned, std::vector<std::pair<unsigned, std::vector<MSchedGraphNode*> > > >::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<std::pair<unsigned, std::vector<MSchedGraphNode*> > >::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<MSchedGraphNode*>::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<MSchedGraphNode*>::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<unsigned, std::vector<std::pair<unsigned, MSchedGraphNode*> > >::iterator J = schedule.begin(),
JE = schedule.end(); J != JE; ++J) {
std::cerr << "Cycle " << J->first << ":\n";
for(std::vector<std::pair<unsigned, MSchedGraphNode*> >::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<std::vector<resourceId_t> > 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<std::pair<unsigned, std::vector<MSchedGraphNode*> > > resourceForCycle = schedule[intermediateCycle];
//Vector of nodes using this resource
std::vector<MSchedGraphNode*> *nodesUsingResource;
for(std::vector<std::pair<unsigned, std::vector<MSchedGraphNode*> > >::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<MSchedGraphNode*>;
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<std::pair<unsigned, MSchedGraphNode*> > resourceForCycle = schedule[removeCycle];
for(std::vector<std::pair<unsigned,MSchedGraphNode*> >::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<const Value*> &valuestoSave, std::vector<Value*> *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<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues) {
std::map<int, std::set<const MachineInstr*> > 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<int, std::set<const MachineInstr*> >::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<MachineBasicBlock*> prologues;
std::vector<BasicBlock*> llvm_prologues;
//create a vector of epilogues corresponding to each stage
/*std::vector<MachineBasicBlock*> 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<MSchedGraphNode *, std::vector<Value*> > 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<const Value*> 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<MachineBasicBlock*>::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);
}*/
}

View File

@ -14,6 +14,7 @@
#define LLVM_MODULOSCHEDULING_H
#include "MSchedGraph.h"
#include "MSSchedule.h"
#include "llvm/Function.h"
#include "llvm/Pass.h"
#include <set>
@ -54,7 +55,7 @@ namespace llvm {
std::vector<MSchedGraphNode*> FinalNodeOrder;
//Schedule table, key is the cycle number and the vector is resource, node pairs
std::map<unsigned, std::vector<std::pair<unsigned, std::vector<MSchedGraphNode*> > > > schedule;
MSSchedule schedule;
//Current initiation interval
int II;
@ -87,6 +88,12 @@ namespace llvm {
void predIntersect(std::vector<MSchedGraphNode*> &CurrentSet, std::vector<MSchedGraphNode*> &IntersectResult);
void succIntersect(std::vector<MSchedGraphNode*> &CurrentSet, std::vector<MSchedGraphNode*> &IntersectResult);
void reconstructLoop(const MachineBasicBlock*);
//void saveValue(const MachineInstr*, const std::set<Value*>&, std::vector<Value*>*);
void writePrologue(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues);
public:
ModuloSchedulingPass(TargetMachine &targ) : target(targ) {}

View File

@ -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<int, std::vector<OpIndexNodePair> >&
//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 );
}

View File

@ -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<MSchedGraphNode*> Predecessors; //Predecessor Nodes
std::vector<MSchedGraphEdge> Successors;
public:
MSchedGraphNode(const MachineInstr *inst, MSchedGraph *graph,
unsigned late=0);
unsigned late=0, bool isBranch=false);
//Iterators
typedef std::vector<MSchedGraphNode*>::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; }
};

View File

@ -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<unsigned, std::vector<std::pair<unsigned, MSchedGraphNode*> > >::iterator J = schedule.begin(),
JE = schedule.end(); J != JE; ++J) {
std::cerr << "Cycle " << J->first << ":\n";
for(std::vector<std::pair<unsigned, MSchedGraphNode*> >::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<unsigned,unsigned>::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<MSchedGraphNode*> &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<MSchedGraphNode*> seenNodes;
for(std::map<unsigned, std::vector<std::pair<unsigned, std::vector<MSchedGraphNode*> > > >::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<std::pair<unsigned, std::vector<MSchedGraphNode*> > >::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<MSchedGraphNode*>::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<MSchedGraphNode*>::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<unsigned, std::vector<std::pair<unsigned, MSchedGraphNode*> > >::iterator J = schedule.begin(),
JE = schedule.end(); J != JE; ++J) {
std::cerr << "Cycle " << J->first << ":\n";
for(std::vector<std::pair<unsigned, MSchedGraphNode*> >::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<std::vector<resourceId_t> > 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<std::pair<unsigned, std::vector<MSchedGraphNode*> > > resourceForCycle = schedule[intermediateCycle];
//Vector of nodes using this resource
std::vector<MSchedGraphNode*> *nodesUsingResource;
for(std::vector<std::pair<unsigned, std::vector<MSchedGraphNode*> > >::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<MSchedGraphNode*>;
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<std::pair<unsigned, MSchedGraphNode*> > resourceForCycle = schedule[removeCycle];
for(std::vector<std::pair<unsigned,MSchedGraphNode*> >::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<const Value*> &valuestoSave, std::vector<Value*> *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<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues) {
std::map<int, std::set<const MachineInstr*> > 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<int, std::set<const MachineInstr*> >::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<MachineBasicBlock*> prologues;
std::vector<BasicBlock*> llvm_prologues;
//create a vector of epilogues corresponding to each stage
/*std::vector<MachineBasicBlock*> 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<MSchedGraphNode *, std::vector<Value*> > 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<const Value*> 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<MachineBasicBlock*>::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);
}*/
}

View File

@ -14,6 +14,7 @@
#define LLVM_MODULOSCHEDULING_H
#include "MSchedGraph.h"
#include "MSSchedule.h"
#include "llvm/Function.h"
#include "llvm/Pass.h"
#include <set>
@ -54,7 +55,7 @@ namespace llvm {
std::vector<MSchedGraphNode*> FinalNodeOrder;
//Schedule table, key is the cycle number and the vector is resource, node pairs
std::map<unsigned, std::vector<std::pair<unsigned, std::vector<MSchedGraphNode*> > > > schedule;
MSSchedule schedule;
//Current initiation interval
int II;
@ -87,6 +88,12 @@ namespace llvm {
void predIntersect(std::vector<MSchedGraphNode*> &CurrentSet, std::vector<MSchedGraphNode*> &IntersectResult);
void succIntersect(std::vector<MSchedGraphNode*> &CurrentSet, std::vector<MSchedGraphNode*> &IntersectResult);
void reconstructLoop(const MachineBasicBlock*);
//void saveValue(const MachineInstr*, const std::set<Value*>&, std::vector<Value*>*);
void writePrologue(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues);
public:
ModuloSchedulingPass(TargetMachine &targ) : target(targ) {}