mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-04 17:58:22 +00:00
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:
parent
1812268126
commit
4cffb588f5
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -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; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -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) {}
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -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; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -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) {}
|
||||
|
Loading…
Reference in New Issue
Block a user