Made the code readable:

* Lines must be wrapped at 80 chars. This is a hard limit.
* Consistent style on functions, braces, if, for, etc. Code must be readable.

No functional changes have been made, even though I added a new typedef.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@5768 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Misha Brukman
2003-04-09 21:51:34 +00:00
parent 4bd8b24470
commit 8baa01c1d7
8 changed files with 3924 additions and 3738 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
//===- ModuloSchedGraph.h - Represent a collection of data structures ----*- C++ -*-===//
//===- ModuloSchedGraph.h - Modulo Scheduling Graph and Set -*- C++ -*-----===//
//
// This header defines the primative classes that make up a data structure
// graph.
@@ -8,14 +8,13 @@
#ifndef LLVM_CODEGEN_MODULO_SCHED_GRAPH_H
#define LLVM_CODEGEN_MODULO_SCHED_GRAPH_H
#include "Support/HashExtras.h"
#include "Support/GraphTraits.h"
#include "../InstrSched/SchedGraphCommon.h"
#include "llvm/Instruction.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "Support/HashExtras.h"
#include "Support/GraphTraits.h"
#include "../InstrSched/SchedGraphCommon.h"
#include <iostream>
using std::pair;
//for debug information selecton
enum ModuloSchedDebugLevel_t {
@@ -25,10 +24,11 @@ enum ModuloSchedDebugLevel_t{
ModuloSched_PrintScheduleProcess,
};
//===============------------------------------------------------------------------------
///ModuloSchedGraphNode - Implement a data structure based on the SchedGraphNodeCommon
///this class stores informtion needed later to order the nodes in modulo scheduling
///
//===----------------------------------------------------------------------===//
// ModuloSchedGraphNode - Implement a data structure based on the
// SchedGraphNodeCommon this class stores informtion needed later to order the
// nodes in modulo scheduling
//
class ModuloSchedGraphNode:public SchedGraphNodeCommon {
private:
// the corresponding instruction
@@ -52,35 +52,64 @@ private:
public:
//get the instruction
const Instruction* getInst() const { return inst;}
const Instruction *getInst() const {
return inst;
}
//get the instruction op-code name
const char* getInstOpcodeName() const{ return inst->getOpcodeName();}
const char *getInstOpcodeName() const {
return inst->getOpcodeName();
}
//get the instruction op-code
const unsigned getInstOpcode() const { return inst->getOpcode();}
const unsigned getInstOpcode() const {
return inst->getOpcode();
}
//return whether the node is NULL
bool isNullNode() const{ return(inst== NULL);}
bool isNullNode() const {
return (inst == NULL);
}
//return whether the property of the node has been computed
bool getPropertyComputed() {return propertyComputed;}
bool getPropertyComputed() {
return propertyComputed;
}
//set the propertyComputed
void setPropertyComputed(bool _propertyComputed) {propertyComputed = _propertyComputed;}
void setPropertyComputed(bool _propertyComputed) {
propertyComputed = _propertyComputed;
}
//get the corresponding property
int getASAP(){ return ASAP;}
int getALAP(){ return ALAP;}
int getMov() { return mov;}
int getDepth(){return depth;}
int getHeight(){return height;}
int getSchTime(){return schTime;}
int getEarlyStart(){return earlyStart;}
int getLateStart() { return lateStart;}
void setEarlyStart(int _earlyStart) {earlyStart= _earlyStart;}
void setLateStart(int _lateStart) {lateStart= _lateStart;}
void setSchTime(int _time){schTime=_time;}
int getASAP() {
return ASAP;
}
int getALAP() {
return ALAP;
}
int getMov() {
return mov;
}
int getDepth() {
return depth;
}
int getHeight() {
return height;
}
int getSchTime() {
return schTime;
}
int getEarlyStart() {
return earlyStart;
}
int getLateStart() {
return lateStart;
}
void setEarlyStart(int _earlyStart) {
earlyStart = _earlyStart;
}
void setLateStart(int _lateStart) {
lateStart = _lateStart;
}
void setSchTime(int _time) {
schTime = _time;
}
private:
friend class ModuloSchedGraph;
@@ -95,34 +124,25 @@ public:
ModuloSchedGraphNode(unsigned int _nodeId,
const BasicBlock * _bb,
const Instruction * _inst,
int indexInBB,
const TargetMachine& target);
int indexInBB, const TargetMachine &target);
friend std::ostream& operator<<(std::ostream& os,const ModuloSchedGraphNode& edge);
friend std::ostream & operator<<(std::ostream & os,
const ModuloSchedGraphNode & edge);
};
//FIXME: these two value should not be used
#define MAXNODE 100
#define MAXCC 100
//===----------------------------------------------------------------------===//
/// ModuloSchedGraph- the data structure to store dependence between nodes
/// it catches data dependence and constrol dependence
///
///
class ModuloSchedGraph :
public SchedGraphCommon,
protected hash_map<const Instruction*, ModuloSchedGraphNode*>
{
protected hash_map<const Instruction*,ModuloSchedGraphNode*> {
private:
//iteration Interval
@@ -196,6 +216,7 @@ private:
NodeVec vectorSub(NodeVec set1, NodeVec set2);
typedef hash_map<const Instruction*,ModuloSchedGraphNode*> map_base;
public:
using map_base::iterator;
using map_base::const_iterator;
@@ -203,18 +224,24 @@ public:
public:
//get target machine
const TargetMachine& getTarget(){return target;}
const TargetMachine & getTarget() {
return target;
}
//get the iteration interval
const int getMII(){return MII;}
const int getMII() {
return MII;
}
//get the ordered nodes
const NodeVec& getONodes(){return oNodes;}
const NodeVec & getONodes() {
return oNodes;
}
//get the number of nodes (including the root and leaf)
//note: actually root and leaf is not used
const unsigned int getNumNodes() const {return size()+2;}
const unsigned int getNumNodes() const {
return size() + 2;
}
//return wether the BasicBlock 'bb' contains a loop
bool isLoop(const BasicBlock * bb);
@@ -227,10 +254,7 @@ public:
const_iterator onePair = this->find(inst);
return (onePair != this->end()) ? (*onePair).second : NULL;
}
//Debugging support
//dump the graph
void dump() const;
//Debugging support//dump the graph void dump() const;
//dump the basicBlock
void dump(const BasicBlock * bb);
//dump the basicBlock into 'os' stream
@@ -242,13 +266,11 @@ public:
friend class ModuloSchedGraphSet; //give access to ctor
public:
/*ctr*/
ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &_target)
:SchedGraphCommon(bb), target(_target) {
buildGraph(target);
}
/*dtr*/
~ModuloSchedGraph() {
for (const_iterator I = begin(); I != end(); ++I)
delete I->second;
@@ -259,9 +281,7 @@ public:
using map_base::begin;
using map_base::end;
inline void noteModuloSchedGraphNodeForInst(const Instruction* inst,
void noteModuloSchedGraphNodeForInst(const Instruction *inst,
ModuloSchedGraphNode *node)
{
assert((*this)[inst] == NULL);
@@ -308,12 +328,10 @@ public:
int computeRecII(const BasicBlock *bb);
};
///==================================-
//gragh set
//==================================-
// Graph set
class ModuloSchedGraphSet:
public std::vector<ModuloSchedGraph*>
{
class ModuloSchedGraphSet : public std::vector<ModuloSchedGraph*> {
private:
const Function *method;
@@ -323,26 +341,25 @@ public:
using baseVector::const_iterator;
public:
/*ctor*/ ModuloSchedGraphSet (const Function* function, const TargetMachine& target);
ModuloSchedGraphSet(const Function *function, const TargetMachine &target);
~ModuloSchedGraphSet();
/*dtor*/ ~ModuloSchedGraphSet ();
//iterators
// Iterators
using baseVector::begin;
using baseVector::end;
// Debugging support
void dump() const;
private:
inline void addGraph(ModuloSchedGraph* graph){
void addGraph(ModuloSchedGraph *graph) {
assert(graph != NULL);
this->push_back(graph);
}
// Graph builder
void buildGraphsForMethod (const Function *F, const TargetMachine& target);
};
void buildGraphsForMethod(const Function *F,
const TargetMachine &target);
}
#endif

View File

@@ -1,46 +1,36 @@
//===- SPLInstrScheduling.cpp - Modulo Software Pipelining Instruction Scheduling support -------===//
//
// this file implements the llvm/CodeGen/ModuloScheduling.h interface
//===- ModuloScheduling.cpp - Modulo Software Pipelining ------------------===//
//
// Implements the llvm/CodeGen/ModuloScheduling.h interface
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
//#include "llvm/CodeGen/MachineCodeForBasicBlock.h"
//#include "llvm/CodeGen/MachineCodeForMethod.h"
#include "llvm/CodeGen/MachineFunction.h"
//#include "llvm/Analysis/LiveVar/FunctionLiveVarInfo.h" // FIXME: Remove when modularized better
#include "llvm/Target/TargetMachine.h"
#include "llvm/BasicBlock.h"
#include "llvm/Constants.h"
#include "llvm/Instruction.h"
#include "Support/CommandLine.h"
#include <algorithm>
#include "ModuloSchedGraph.h"
#include "ModuloScheduling.h"
#include "llvm/Target/TargetSchedInfo.h"
#include "llvm/BasicBlock.h"
#include "llvm/iTerminators.h"
#include "llvm/iPHINode.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/Target/TargetSchedInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "Support/CommandLine.h"
#include "ModuloSchedGraph.h"
#include "ModuloScheduling.h"
#include <algorithm>
#include <fstream>
#include <iostream>
//#include <swig.h>
#include <fstream>
#include "llvm/CodeGen/InstrSelection.h"
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
using std::cerr;
using std::cout;
using std::ostream;
using std::ios;
using std::filebuf;
//************************************************************
// printing Debug information
// ModuloSchedDebugLevel stores the value of debug level
// modsched_os is the ostream to dump debug information, which is written into the file 'moduloSchedDebugInfo.output'
// modsched_os is the ostream to dump debug information, which is written into
// the file 'moduloSchedDebugInfo.output'
// see ModuloSchedulingPass::runOnFunction()
//************************************************************
@@ -48,37 +38,34 @@ ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
static cl::opt<ModuloSchedDebugLevel_t,true>
SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel),
cl::desc("enable modulo scheduling debugging information"),
cl::values(
clEnumValN(ModuloSched_NoDebugInfo, "n", "disable debug output"),
clEnumValN(ModuloSched_Disable, "off", "disable modulo scheduling"),
clEnumValN(ModuloSched_PrintSchedule, "psched", "print original and new schedule"),
clEnumValN(ModuloSched_PrintScheduleProcess,"pschedproc", "print how the new schdule is produced"),
0));
cl::values(clEnumValN
(ModuloSched_NoDebugInfo, "n", "disable debug output"),
clEnumValN(ModuloSched_Disable, "off",
"disable modulo scheduling"),
clEnumValN(ModuloSched_PrintSchedule, "psched",
"print original and new schedule"),
clEnumValN(ModuloSched_PrintScheduleProcess, "pschedproc",
"print how the new schdule is produced"), 0));
filebuf modSched_fb;
ostream modSched_os(&modSched_fb);
std::filebuf modSched_fb;
std::ostream modSched_os(&modSched_fb);
//************************************************************
///the method to compute schedule and instert epilogue and prologue
void ModuloScheduling::instrScheduling(){
// Computes the schedule and inserts epilogue and prologue
//
void ModuloScheduling::instrScheduling()
{
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
modSched_os<<"*************************computing modulo schedule ************************\n";
modSched_os << "*************** computing modulo schedule **************\n";
const TargetSchedInfo & msi = target.getSchedInfo();
//number of issue slots in the in each cycle
int numIssueSlots = msi.maxNumIssueTotal;
//compute the schedule
bool success = false;
while(!success)
{
while (!success) {
//clear memory from the last round and initialize if necessary
clearInitMem(msi);
@@ -96,7 +83,6 @@ void ModuloScheduling::instrScheduling(){
if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule)
dumpScheduling();
//the schedule has been computed
//create epilogue, prologue and kernel BasicBlock
@@ -108,23 +94,20 @@ void ModuloScheduling::instrScheduling(){
modSched_os << "dumping the orginal block\n";
graph.dump(bb);
}
//construction of prologue, kernel and epilogue
BasicBlock *kernel = bb->splitBasicBlock(bb->begin());
BasicBlock *prologue = bb;
BasicBlock *epilogue = kernel->splitBasicBlock(kernel->begin());
//construct prologue
// Construct prologue
constructPrologue(prologue);
//construct kernel
// Construct kernel
constructKernel(prologue, kernel, epilogue);
//construct epilogue
// Construct epilogue
constructEpilogue(epilogue, succ_bb);
//print the BasicBlocks if necessary
if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) {
modSched_os << "dumping the prologue block:\n";
@@ -134,28 +117,27 @@ void ModuloScheduling::instrScheduling(){
modSched_os << "dumping the epilogue block\n";
graph.dump(epilogue);
}
}
//clear memory from the last round and initialize if necessary
void ModuloScheduling::clearInitMem(const TargetSchedInfo& msi){
// Clear memory from the last round and initialize if necessary
//
void ModuloScheduling::clearInitMem(const TargetSchedInfo & msi)
{
unsigned numIssueSlots = msi.maxNumIssueTotal;
// clear nodeScheduled from the last round
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) {
modSched_os<< "***** new round with II= "<<II<<" *******************"<<"\n";
modSched_os<< " **************clear the vector nodeScheduled**************** \n";
modSched_os << "***** new round with II= " << II <<
" *******************\n";
modSched_os <<
" ************clear the vector nodeScheduled*************\n";
}
nodeScheduled.clear();
// clear resourceTable from the last round and reset it
resourceTable.clear();
for(unsigned i=0;i< II;i++)
for (unsigned i = 0; i < II; ++i)
resourceTable.push_back(msi.resourceNumVector);
// clear the schdule and coreSchedule from the last round
schedule.clear();
coreSchedule.clear();
@@ -163,32 +145,33 @@ void ModuloScheduling::clearInitMem(const TargetSchedInfo& msi){
// create a coreSchedule of size II*numIssueSlots
// each entry is NULL
while (coreSchedule.size() < II) {
std::vector<ModuloSchedGraphNode*>* newCycle=new std::vector<ModuloSchedGraphNode*>();
for(unsigned k=0;k<numIssueSlots;k++)
std::vector < ModuloSchedGraphNode * >*newCycle =
new std::vector < ModuloSchedGraphNode * >();
for (unsigned k = 0; k < numIssueSlots; ++k)
newCycle->push_back(NULL);
coreSchedule.push_back(*newCycle);
}
}
//compute schedule and coreSchedule with the current II
bool ModuloScheduling::computeSchedule(){
// Compute schedule and coreSchedule with the current II
//
bool ModuloScheduling::computeSchedule()
{
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
modSched_os << "start to compute schedule\n";
//loop over the ordered nodes
for(NodeVec::const_iterator I=oNodes.begin();I!=oNodes.end();I++)
{
//try to schedule for node I
// Loop over the ordered nodes
for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) {
// Try to schedule for node I
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
dumpScheduling();
ModuloSchedGraphNode *node = *I;
//compute whether this node has successor(s)
// Compute whether this node has successor(s)
bool succ = true;
//compute whether this node has predessor(s)
// Compute whether this node has predessor(s)
bool pred = true;
NodeVec schSucc = graph.vectorConj(nodeScheduled, graph.succSet(node));
@@ -207,78 +190,90 @@ bool ModuloScheduling::computeSchedule(){
node->setEarlyStart(-1);
node->setLateStart(9999);
//this node has predessor but no successor
if (!succ && pred) {
//this node's earlyStart is it's predessor's schedule time + the edge delay
// - the iteration difference* II
// This node's earlyStart is it's predessor's schedule time + the edge
// delay - the iteration difference* II
for (unsigned i = 0; i < schPred.size(); i++) {
ModuloSchedGraphNode *predNode = schPred[i];
SchedGraphEdge* edge=graph.getMaxDelayEdge(predNode->getNodeId(),node->getNodeId());
int temp=predNode->getSchTime()+edge->getMinDelay() - edge->getIteDiff()*II;
node->setEarlyStart( max(node->getEarlyStart(),temp));
SchedGraphEdge *edge =
graph.getMaxDelayEdge(predNode->getNodeId(),
node->getNodeId());
int temp =
predNode->getSchTime() + edge->getMinDelay() -
edge->getIteDiff() * II;
node->setEarlyStart(std::max(node->getEarlyStart(), temp));
}
startTime = node->getEarlyStart();
endTime = node->getEarlyStart() + II - 1;
}
//this node has successor but no predessor
// This node has a successor but no predecessor
if (succ && !pred) {
for(unsigned i=0;i<schSucc.size();i++){
for (unsigned i = 0; i < schSucc.size(); ++i) {
ModuloSchedGraphNode *succNode = schSucc[i];
SchedGraphEdge* edge=graph.getMaxDelayEdge(succNode->getNodeId(),node->getNodeId());
int temp=succNode->getSchTime() - edge->getMinDelay() + edge->getIteDiff()*II;
node->setLateStart(min(node->getEarlyStart(),temp));
SchedGraphEdge *edge =
graph.getMaxDelayEdge(succNode->getNodeId(),
node->getNodeId());
int temp =
succNode->getSchTime() - edge->getMinDelay() +
edge->getIteDiff() * II;
node->setLateStart(std::min(node->getEarlyStart(), temp));
}
startTime = node->getLateStart() - II + 1;
endTime = node->getLateStart();
}
//this node has both successors and predessors
if(succ && pred)
{
for(unsigned i=0;i<schPred.size();i++){
// This node has both successors and predecessors
if (succ && pred) {
for (unsigned i = 0; i < schPred.size(); ++i) {
ModuloSchedGraphNode *predNode = schPred[i];
SchedGraphEdge* edge=graph.getMaxDelayEdge(predNode->getNodeId(),node->getNodeId());
int temp=predNode->getSchTime()+edge->getMinDelay() - edge->getIteDiff()*II;
node->setEarlyStart(max(node->getEarlyStart(),temp));
SchedGraphEdge *edge =
graph.getMaxDelayEdge(predNode->getNodeId(),
node->getNodeId());
int temp =
predNode->getSchTime() + edge->getMinDelay() -
edge->getIteDiff() * II;
node->setEarlyStart(std::max(node->getEarlyStart(), temp));
}
for(unsigned i=0;i<schSucc.size();i++){
for (unsigned i = 0; i < schSucc.size(); ++i) {
ModuloSchedGraphNode *succNode = schSucc[i];
SchedGraphEdge* edge=graph.getMaxDelayEdge(succNode->getNodeId(),node->getNodeId());
int temp=succNode->getSchTime() - edge->getMinDelay() + edge->getIteDiff()*II;
node->setLateStart(min(node->getEarlyStart(),temp));
SchedGraphEdge *edge =
graph.getMaxDelayEdge(succNode->getNodeId(),
node->getNodeId());
int temp =
succNode->getSchTime() - edge->getMinDelay() +
edge->getIteDiff() * II;
node->setLateStart(std::min(node->getEarlyStart(), temp));
}
startTime = node->getEarlyStart();
endTime=min(node->getLateStart(),node->getEarlyStart()+((int)II)-1);
endTime = std::min(node->getLateStart(),
node->getEarlyStart() + ((int) II) - 1);
}
//this node has no successor or predessor
if (!succ && !pred) {
node->setEarlyStart(node->getASAP());
startTime = node->getEarlyStart();
endTime = node->getEarlyStart() + II - 1;
}
//try to schedule this node based on the startTime and endTime
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
modSched_os << "scheduling the node " << (*I)->getNodeId() << "\n";
bool success= this->ScheduleNode(node,startTime, endTime,nodeScheduled);
if(!success)return false;
bool success =
this->ScheduleNode(node, startTime, endTime, nodeScheduled);
if (!success)
return false;
}
return true;
}
//get the successor of the BasicBlock
BasicBlock* ModuloScheduling::getSuccBB(BasicBlock* bb){
// Get the successor of the BasicBlock
//
BasicBlock *ModuloScheduling::getSuccBB(BasicBlock *bb)
{
BasicBlock *succ_bb;
for(unsigned i=0;i < II; i++)
for(unsigned j=0;j< coreSchedule[i].size();j++)
for (unsigned i = 0; i < II; ++i)
for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
if (coreSchedule[i][j]) {
const Instruction *ist = coreSchedule[i][j]->getInst();
@@ -286,13 +281,18 @@ BasicBlock* ModuloScheduling::getSuccBB(BasicBlock* bb){
//assume we only have one successor (besides itself) here
if (BranchInst::classof(ist)) {
BranchInst *bi = (BranchInst *) ist;
assert(bi->isConditional()&&"the branchInst is not a conditional one");
assert(bi->getNumSuccessors() ==2&&" more than two successors?");
assert(bi->isConditional() &&
"the branchInst is not a conditional one");
assert(bi->getNumSuccessors() == 2
&& " more than two successors?");
BasicBlock *bb1 = bi->getSuccessor(0);
BasicBlock *bb2 = bi->getSuccessor(1);
assert( (bb1 == bb|| bb2 == bb) && " None of its successor is itself?");
if(bb1 == bb) succ_bb=bb2;
else succ_bb=bb1;
assert((bb1 == bb || bb2 == bb) &&
" None of its successors is itself?");
if (bb1 == bb)
succ_bb = bb2;
else
succ_bb = bb1;
return succ_bb;
}
}
@@ -301,13 +301,13 @@ BasicBlock* ModuloScheduling::getSuccBB(BasicBlock* bb){
}
//get the predecessor of the BasicBlock
BasicBlock* ModuloScheduling::getPredBB(BasicBlock* bb){
// Get the predecessor of the BasicBlock
//
BasicBlock *ModuloScheduling::getPredBB(BasicBlock *bb)
{
BasicBlock *pred_bb;
for(unsigned i=0;i < II; i++)
for(unsigned j=0;j< coreSchedule[i].size();j++)
for (unsigned i = 0; i < II; ++i)
for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
if (coreSchedule[i][j]) {
const Instruction *ist = coreSchedule[i][j]->getInst();
@@ -315,12 +315,16 @@ BasicBlock* ModuloScheduling::getPredBB(BasicBlock* bb){
//assume we only have one predecessor (besides itself) here
if (PHINode::classof(ist)) {
PHINode *phi = (PHINode *) ist;
assert(phi->getNumIncomingValues() == 2 &&" the number of incoming value is not equal to two? ");
assert(phi->getNumIncomingValues() == 2 &&
" the number of incoming value is not equal to two? ");
BasicBlock *bb1 = phi->getIncomingBlock(0);
BasicBlock *bb2 = phi->getIncomingBlock(1);
assert( (bb1 == bb || bb2 == bb) && " None of its predecessor is itself?");
if(bb1 == bb) pred_bb=bb2;
else pred_bb=bb1;
assert((bb1 == bb || bb2 == bb) &&
" None of its predecessor is itself?");
if (bb1 == bb)
pred_bb = bb2;
else
pred_bb = bb1;
return pred_bb;
}
}
@@ -329,39 +333,45 @@ BasicBlock* ModuloScheduling::getPredBB(BasicBlock* bb){
}
//construct the prologue
void ModuloScheduling::constructPrologue(BasicBlock* prologue){
// Construct the prologue
//
void ModuloScheduling::constructPrologue(BasicBlock *prologue)
{
InstListType & prologue_ist = prologue->getInstList();
vvNodeType& tempSchedule_prologue= *(new vector< std::vector<ModuloSchedGraphNode*> >(schedule));
vvNodeType & tempSchedule_prologue =
*(new vector < std::vector < ModuloSchedGraphNode * >>(schedule));
//compute the schedule for prologue
unsigned round = 0;
unsigned scheduleSize = schedule.size();
while (round < scheduleSize / II) {
round++;
for(unsigned i=0;i < scheduleSize ;i++){
if(round*II + i >= scheduleSize) break;
for(unsigned j=0;j < schedule[i].size(); j++)
for (unsigned i = 0; i < scheduleSize; ++i) {
if (round * II + i >= scheduleSize)
break;
for (unsigned j = 0; j < schedule[i].size(); ++j) {
if (schedule[i][j]) {
assert( tempSchedule_prologue[round*II +i ][j] == NULL && "table not consitant with core table");
//move the schedule one iteration ahead and overlap with the original one
assert(tempSchedule_prologue[round * II + i][j] == NULL &&
"table not consitent with core table");
// move the schedule one iteration ahead and overlap with the original
tempSchedule_prologue[round * II + i][j] = schedule[i][j];
}
}
}
}
//clear the clone memory in the core schedule instructions
// Clear the clone memory in the core schedule instructions
clearCloneMemory();
//fill in the prologue
for(unsigned i=0;i < ceil(1.0*scheduleSize/II -1)*II ;i++)
for(unsigned j=0;j < tempSchedule_prologue[i].size();j++)
// Fill in the prologue
for (unsigned i = 0; i < ceil(1.0 * scheduleSize / II - 1) * II; ++i)
for (unsigned j = 0; j < tempSchedule_prologue[i].size(); ++j)
if (tempSchedule_prologue[i][j]) {
//get the instruction
Instruction* orn=(Instruction*)tempSchedule_prologue[i][j]->getInst();
Instruction *orn =
(Instruction *) tempSchedule_prologue[i][j]->getInst();
//made a clone of it
Instruction *cln = cloneInstSetMemory(orn);
@@ -369,8 +379,8 @@ void ModuloScheduling::constructPrologue(BasicBlock* prologue){
//insert the instruction
prologue_ist.insert(prologue_ist.back(), cln);
//if there is PHINode in the prologue, the incoming value from itself should be removed
//because it is not a loop any longer
//if there is PHINode in the prologue, the incoming value from itself
//should be removed because it is not a loop any longer
if (PHINode::classof(cln)) {
PHINode *phi = (PHINode *) cln;
phi->removeIncomingValue(phi->getParent());
@@ -379,25 +389,28 @@ void ModuloScheduling::constructPrologue(BasicBlock* prologue){
}
//construct the kernel BasicBlock
void ModuloScheduling::constructKernel(BasicBlock* prologue,BasicBlock* kernel,BasicBlock* epilogue){
// Construct the kernel BasicBlock
//
void ModuloScheduling::constructKernel(BasicBlock *prologue,
BasicBlock *kernel,
BasicBlock *epilogue)
{
//*************fill instructions in the kernel****************
InstListType & kernel_ist = kernel->getInstList();
BranchInst *brchInst;
PHINode *phiInst, *phiCln;
for(unsigned i=0;i<coreSchedule.size();i++)
for(unsigned j=0;j<coreSchedule[i].size();j++)
for (unsigned i = 0; i < coreSchedule.size(); ++i)
for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
if (coreSchedule[i][j]) {
//we should take care of branch instruction differently with normal instructions
// Take care of branch instruction differently with normal instructions
if (BranchInst::classof(coreSchedule[i][j]->getInst())) {
brchInst = (BranchInst *) coreSchedule[i][j]->getInst();
continue;
}
//we should take care of PHINode instruction differently with normal instructions
// Take care of PHINode instruction differently with normal instructions
if (PHINode::classof(coreSchedule[i][j]->getInst())) {
phiInst = (PHINode *) coreSchedule[i][j]->getInst();
Instruction *cln = cloneInstSetMemory(phiInst);
@@ -405,26 +418,28 @@ void ModuloScheduling::constructKernel(BasicBlock* prologue,BasicBlock* kernel,B
phiCln = (PHINode *) cln;
continue;
}
//for normal instructions: made a clone and insert it in the kernel_ist
Instruction* cln=cloneInstSetMemory( (Instruction*)coreSchedule[i][j]->getInst());
Instruction *cln =
cloneInstSetMemory((Instruction *) coreSchedule[i][j]->
getInst());
kernel_ist.insert(kernel_ist.back(), cln);
}
//the two incoming BasicBlock for PHINode is the prologue and the kernel (itself)
// The two incoming BasicBlock for PHINode is the prologue and the kernel
// (itself)
phiCln->setIncomingBlock(0, prologue);
phiCln->setIncomingBlock(1, kernel);
//the incoming value for the kernel (itself) is the new value which is computed in the kernel
// The incoming value for the kernel (itself) is the new value which is
// computed in the kernel
Instruction *originalVal = (Instruction *) phiInst->getIncomingValue(1);
phiCln->setIncomingValue(1, originalVal->getClone());
//make a clone of the branch instruction and insert it in the end
// Make a clone of the branch instruction and insert it in the end
BranchInst *cln = (BranchInst *) cloneInstSetMemory(brchInst);
kernel_ist.insert(kernel_ist.back(), cln);
//delete the unconditional branch instruction, which is generated when splitting the basicBlock
// delete the unconditional branch instruction, which is generated when
// splitting the basicBlock
kernel_ist.erase(--kernel_ist.end());
// set the first successor to itself
@@ -442,29 +457,34 @@ void ModuloScheduling::constructKernel(BasicBlock* prologue,BasicBlock* kernel,B
assert(ConstantSInt::classof(operand));
//change the constant in the condtion instruction
ConstantSInt* iteTimes=ConstantSInt::get(operand->getType(),((ConstantSInt*)operand)->getValue()-II+1);
ConstantSInt *iteTimes =
ConstantSInt::get(operand->getType(),
((ConstantSInt *) operand)->getValue() - II + 1);
cond->setOperand(1, iteTimes);
}
//construct the epilogue
void ModuloScheduling::constructEpilogue(BasicBlock* epilogue, BasicBlock* succ_bb){
// Construct the epilogue
//
void ModuloScheduling::constructEpilogue(BasicBlock *epilogue,
BasicBlock *succ_bb)
{
//compute the schedule for epilogue
vvNodeType& tempSchedule_epilogue= *(new vector< std::vector<ModuloSchedGraphNode*> >(schedule));
vvNodeType & tempSchedule_epilogue =
*(new vector < std::vector < ModuloSchedGraphNode * >>(schedule));
unsigned scheduleSize = schedule.size();
int round = 0;
while (round < ceil(1.0 * scheduleSize / II) - 1) {
round++;
for (unsigned i = 0; i < scheduleSize; i++) {
if(i + round *II >= scheduleSize) break;
if (i + round * II >= scheduleSize)
break;
for (unsigned j = 0; j < schedule[i].size(); j++)
if (schedule[i + round * II][j]) {
assert( tempSchedule_epilogue[i][j] == NULL && "table not consitant with core table");
assert(tempSchedule_epilogue[i][j] == NULL
&& "table not consitant with core table");
//move the schdule one iteration behind and overlap
tempSchedule_epilogue[i][j] = schedule[i + round * II][j];
@@ -477,7 +497,8 @@ void ModuloScheduling::constructEpilogue(BasicBlock* epilogue, BasicBlock* succ_
for (unsigned i = II; i < scheduleSize; i++)
for (unsigned j = 0; j < tempSchedule_epilogue[i].size(); j++)
if (tempSchedule_epilogue[i][j]) {
Instruction* inst=(Instruction*)tempSchedule_epilogue[i][j]->getInst();
Instruction *inst =
(Instruction *) tempSchedule_epilogue[i][j]->getInst();
//BranchInst and PHINode should be treated differently
//BranchInst:unecessary, simly omitted
@@ -489,7 +510,6 @@ void ModuloScheduling::constructEpilogue(BasicBlock* epilogue, BasicBlock* succ_
}
}
//*************delete the original instructions****************//
//to delete the original instructions, we have to make sure their use is zero
@@ -516,11 +536,13 @@ void ModuloScheduling::constructEpilogue(BasicBlock* epilogue, BasicBlock* succ_
}
//----------------------------------------------------------------------------------------------
//this function replace the value(instruction) ist in other instructions with its latest clone
//i.e. after this function is called, the ist is not used anywhere and it can be erased.
//----------------------------------------------------------------------------------------------
void ModuloScheduling::updateUseWithClone(Instruction* ist){
//------------------------------------------------------------------------------
//this function replace the value(instruction) ist in other instructions with
//its latest clone i.e. after this function is called, the ist is not used
//anywhere and it can be erased.
//------------------------------------------------------------------------------
void ModuloScheduling::updateUseWithClone(Instruction * ist)
{
while (ist->use_size() > 0) {
bool destroyed = false;
@@ -531,16 +553,14 @@ void ModuloScheduling::updateUseWithClone(Instruction* ist){
for (unsigned i = 0; i < inst->getNumOperands(); i++)
if (inst->getOperand(i) == ist && ist->getClone()) {
//if the instruction is TmpInstruction, simly delete it because it has no parent
// and it does not belongs to any BasicBlock
// if the instruction is TmpInstruction, simly delete it because it has
// no parent and it does not belongs to any BasicBlock
if (TmpInstruction::classof(inst)) {
delete inst;
destroyed = true;
break;
}
//otherwise, set the instruction's operand to the value's clone
inst->setOperand(i, ist->getClone());
@@ -548,8 +568,7 @@ void ModuloScheduling::updateUseWithClone(Instruction* ist){
destroyed = true;
break;
}
if( !destroyed)
{
if (!destroyed) {
//if the use can not be destroyed , something is wrong
inst->dump();
assert(0 && "this use can not be destroyed");
@@ -563,27 +582,27 @@ void ModuloScheduling::updateUseWithClone(Instruction* ist){
//this function clear all clone mememoy
//i.e. set all instruction's clone memory to NULL
//*****************************************************
void ModuloScheduling::clearCloneMemory(){
void ModuloScheduling::clearCloneMemory()
{
for (unsigned i = 0; i < coreSchedule.size(); i++)
for (unsigned j = 0; j < coreSchedule[i].size(); j++)
if(coreSchedule[i][j]) ((Instruction*)coreSchedule[i][j]->getInst())->clearClone();
if (coreSchedule[i][j])
((Instruction *) coreSchedule[i][j]->getInst())->clearClone();
}
//********************************************************************************
//this function make a clone of the instruction orn
//the cloned instruction will use the orn's operands' latest clone as its operands
//it is done this way because LLVM is in SSA form and we should use the correct value
//
//******************************************************************************
// this function make a clone of the instruction orn the cloned instruction will
// use the orn's operands' latest clone as its operands it is done this way
// because LLVM is in SSA form and we should use the correct value
//this fuction also update the instruction orn's latest clone memory
//**********************************************************************************
Instruction* ModuloScheduling::cloneInstSetMemory(Instruction* orn) {
//******************************************************************************
Instruction *ModuloScheduling::cloneInstSetMemory(Instruction * orn)
{
// make a clone instruction
Instruction *cln = orn->clone();
// update the operands
for (unsigned k = 0; k < orn->getNumOperands(); k++) {
const Value *op = orn->getOperand(k);
@@ -600,9 +619,10 @@ Instruction* ModuloScheduling::cloneInstSetMemory(Instruction* orn) {
bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, unsigned end, NodeVec& nodeScheduled)
bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode * node,
unsigned start, unsigned end,
NodeVec & nodeScheduled)
{
const TargetSchedInfo & msi = target.getSchedInfo();
unsigned int numIssueSlots = msi.maxNumIssueTotal;
@@ -619,21 +639,22 @@ bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, u
modSched_os << "\t Trying slot " << j << "...........";
//check the resouce table, make sure there is no resource conflicts
const Instruction *instr = node->getInst();
MachineCodeForInstruction& tempMvec= MachineCodeForInstruction::get(instr);
MachineCodeForInstruction & tempMvec =
MachineCodeForInstruction::get(instr);
bool resourceConflict = false;
const TargetInstrInfo & mii = msi.getInstrInfo();
if(coreSchedule.size() < core_i+1 || !coreSchedule[core_i][core_j]){
if (coreSchedule.size() < core_i + 1
|| !coreSchedule[core_i][core_j]) {
//this->dumpResourceUsageTable();
int latency = 0;
for(unsigned k=0;k< tempMvec.size();k++)
{
for (unsigned k = 0; k < tempMvec.size(); k++) {
MachineInstr *minstr = tempMvec[k];
InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
std::vector < std::vector < resourceId_t > >resources
= rUsage.resourcesByCycle;
updateResourceTable(resources, i + latency);
latency +=max(mii.minLatency(minstr->getOpCode()),1) ;
latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
}
//this->dumpResourceUsageTable();
@@ -648,7 +669,7 @@ bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, u
std::vector < std::vector < resourceId_t > >resources
= rUsage.resourcesByCycle;
undoUpdateResourceTable(resources, i + latency);
latency +=max(mii.minLatency(minstr->getOpCode()),1) ;
latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
}
resourceConflict = true;
}
@@ -656,11 +677,13 @@ bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, u
if (!resourceConflict && !coreSchedule[core_i][core_j]) {
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) {
modSched_os << " OK!" << "\n";
modSched_os<<"Node "<<node->getNodeId()<< " is scheduleed."<<"\n";
modSched_os << "Node " << node->
getNodeId() << " is scheduleed." << "\n";
}
//schedule[i][j]=node;
while (schedule.size() <= i) {
std::vector<ModuloSchedGraphNode*>* newCycle=new std::vector<ModuloSchedGraphNode*>();
std::vector < ModuloSchedGraphNode * >*newCycle =
new std::vector < ModuloSchedGraphNode * >();
for (unsigned k = 0; k < numIssueSlots; k++)
newCycle->push_back(NULL);
schedule.push_back(*newCycle);
@@ -674,7 +697,8 @@ bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, u
//update coreSchedule
//coreSchedule[core_i][core_j]=node;
while (coreSchedule.size() <= core_i) {
std::vector<ModuloSchedGraphNode*>* newCycle=new std::vector<ModuloSchedGraphNode*>();
std::vector < ModuloSchedGraphNode * >*newCycle =
new std::vector < ModuloSchedGraphNode * >();
for (unsigned k = 0; k < numIssueSlots; k++)
newCycle->push_back(NULL);
coreSchedule.push_back(*newCycle);
@@ -690,27 +714,30 @@ bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, u
nodeScheduled.push_back(node);
break;
}
else if( coreSchedule[core_i][core_j]) {
} else if (coreSchedule[core_i][core_j]) {
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
modSched_os << " Slot not available " << "\n";
}
else{
} else {
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
modSched_os << " Resource conflicts" << "\n";
}
}
if(isScheduled) break;
if (isScheduled)
break;
}
//assert(nodeScheduled &&"this node can not be scheduled?");
return isScheduled;
}
void ModuloScheduling::updateResourceTable(std::vector<std::vector<unsigned int> > useResources, int startCycle){
void ModuloScheduling::updateResourceTable(Resources useResources,
int startCycle)
{
for (unsigned i = 0; i < useResources.size(); i++) {
int absCycle = startCycle + i;
int coreCycle = absCycle % II;
std::vector<pair<int,int> >& resourceRemained=resourceTable[coreCycle];
std::vector<std::pair<int,int> > &resourceRemained =
resourceTable[coreCycle];
std::vector < unsigned int >&resourceUsed = useResources[i];
for (unsigned j = 0; j < resourceUsed.size(); j++) {
for (unsigned k = 0; k < resourceRemained.size(); k++)
@@ -721,11 +748,14 @@ void ModuloScheduling::updateResourceTable(std::vector<std::vector<unsigned int>
}
}
void ModuloScheduling::undoUpdateResourceTable(std::vector<std::vector<unsigned int> > useResources, int startCycle){
void ModuloScheduling::undoUpdateResourceTable(Resources useResources,
int startCycle)
{
for (unsigned i = 0; i < useResources.size(); i++) {
int absCycle = startCycle + i;
int coreCycle = absCycle % II;
std::vector<pair<int,int> >& resourceRemained=resourceTable[coreCycle];
std::vector<std::pair<int,int> > &resourceRemained =
resourceTable[coreCycle];
std::vector < unsigned int >&resourceUsed = useResources[i];
for (unsigned j = 0; j < resourceUsed.size(); j++) {
for (unsigned k = 0; k < resourceRemained.size(); k++)
@@ -738,16 +768,21 @@ void ModuloScheduling::undoUpdateResourceTable(std::vector<std::vector<unsigned
//-----------------------------------------------------------------------
//Function: resouceTableNegative
// Function: resourceTableNegative
// return value:
// return false if any element in the resouceTable is negative
// otherwise return true
// Purpose:
// this function is used to determine if an instruction is eligible for schedule at certain cycle
//---------------------------------------------------------------------------------------
bool ModuloScheduling::resourceTableNegative(){
assert(resourceTable.size() == (unsigned)II&& "resouceTable size must be equal to II");
// this function is used to determine if an instruction is eligible for
// schedule at certain cycle
//-----------------------------------------------------------------------
bool ModuloScheduling::resourceTableNegative()
{
assert(resourceTable.size() == (unsigned) II
&& "resouceTable size must be equal to II");
bool isNegative = false;
for (unsigned i = 0; i < resourceTable.size(); i++)
for (unsigned j = 0; j < resourceTable[i].size(); j++) {
@@ -767,11 +802,13 @@ bool ModuloScheduling::resourceTableNegative(){
//
//------------------------------------------------------------------------
void ModuloScheduling::dumpResourceUsageTable(){
void ModuloScheduling::dumpResourceUsageTable()
{
modSched_os << "dumping resource usage table" << "\n";
for (unsigned i = 0; i < resourceTable.size(); i++) {
for (unsigned j = 0; j < resourceTable[i].size(); j++)
modSched_os <<resourceTable[i][j].first<<":"<< resourceTable[i][j].second<<" ";
modSched_os << resourceTable[i][j].
first << ":" << resourceTable[i][j].second << " ";
modSched_os << "\n";
}
@@ -783,15 +820,14 @@ void ModuloScheduling::dumpResourceUsageTable(){
// print out thisSchedule for debug
//
//-----------------------------------------------------------------------
void ModuloScheduling::dumpSchedule(std::vector< std::vector<ModuloSchedGraphNode*> > thisSchedule){
void ModuloScheduling::dumpSchedule(vvNodeType thisSchedule)
{
const TargetSchedInfo & msi = target.getSchedInfo();
unsigned numIssueSlots = msi.maxNumIssueTotal;
for (unsigned i = 0; i < numIssueSlots; i++)
modSched_os << "\t#";
modSched_os << "\n";
for(unsigned i=0;i < thisSchedule.size();i++)
{
for (unsigned i = 0; i < thisSchedule.size(); i++) {
modSched_os << "cycle" << i << ": ";
for (unsigned j = 0; j < thisSchedule[i].size(); j++)
if (thisSchedule[i][j] != NULL)
@@ -811,15 +847,15 @@ void ModuloScheduling::dumpSchedule(std::vector< std::vector<ModuloSchedGraphNod
//
//-------------------------------------------------------
void ModuloScheduling::dumpScheduling(){
void ModuloScheduling::dumpScheduling()
{
modSched_os << "dump schedule:" << "\n";
const TargetSchedInfo & msi = target.getSchedInfo();
unsigned numIssueSlots = msi.maxNumIssueTotal;
for (unsigned i = 0; i < numIssueSlots; i++)
modSched_os << "\t#";
modSched_os << "\n";
for(unsigned i=0;i < schedule.size();i++)
{
for (unsigned i = 0; i < schedule.size(); i++) {
modSched_os << "cycle" << i << ": ";
for (unsigned j = 0; j < schedule[i].size(); j++)
if (schedule[i][j] != NULL)
@@ -859,19 +895,18 @@ namespace {
class ModuloSchedulingPass:public FunctionPass {
const TargetMachine & target;
public:
ModuloSchedulingPass(const TargetMachine &T) : target(T) {}
const char *getPassName() const { return "Modulo Scheduling"; }
ModuloSchedulingPass(const TargetMachine &T):target(T) {
} const char *getPassName() const {
return "Modulo Scheduling";
}
// getAnalysisUsage - We use LiveVarInfo...
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
//AU.addRequired(FunctionLiveVarInfo::ID);
}
bool runOnFunction(Function &F);
} bool runOnFunction(Function & F);
};
} // end anonymous namespace
bool ModuloSchedulingPass::runOnFunction(Function &F)
{
@@ -880,8 +915,10 @@ bool ModuloSchedulingPass::runOnFunction(Function &F)
return false;
if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) {
modSched_fb.open("moduloSchedDebugInfo.output", ios::out);
modSched_os<<"******************Modula Scheduling debug information*************************"<<"\n ";
modSched_fb.open("moduloSchedDebugInfo.output", std::ios::out);
modSched_os <<
"******************Modula Scheduling debug information****************"
<< "\n ";
}
ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target);
@@ -894,7 +931,7 @@ bool ModuloSchedulingPass::runOnFunction(Function &F)
}
Pass *createModuloSchedulingPass(const TargetMachine &tgt) {
Pass *createModuloSchedulingPass(const TargetMachine & tgt)
{
return new ModuloSchedulingPass(tgt);
}

View File

@@ -1,7 +1,7 @@
//// - head file for the classes ModuloScheduling and ModuloScheduling ----*- C++ -*-===//
//
// This header defines the the classes ModuloScheduling and ModuloSchedulingSet 's structure
// ModuloScheduling.h -------------------------------------------*- C++ -*-===//
//
// This header defines the the classes ModuloScheduling and
// ModuloSchedulingSet's structure
//
//===----------------------------------------------------------------------===//
@@ -13,31 +13,31 @@
#include <iostream>
#include <vector>
using std::vector;
class ModuloScheduling: NonCopyable {
private:
typedef std::vector<ModuloSchedGraphNode*> NodeVec;
/// the graph to feed in
typedef std::vector<ModuloSchedGraphNode*> NodeVec;
typedef std::vector<std::vector<unsigned> > Resources;
// The graph to feed in
ModuloSchedGraph &graph;
const TargetMachine &target;
//the BasicBlock to be scheduled
// The BasicBlock to be scheduled
BasicBlock *bb;
///Iteration Intervel
///FIXME: II may be a better name for its meaning
// Iteration Interval
// FIXME: II may be a better name for its meaning
unsigned II;
//the vector containing the nodes which have been scheduled
// The vector containing the nodes which have been scheduled
NodeVec nodeScheduled;
///the remaining unscheduled nodes
// The remaining unscheduled nodes
const NodeVec &oNodes;
///the machine resource table
std::vector< std::vector<pair<int,int> > > resourceTable ;
// The machine resource table
std::vector<std::vector<std::pair<int,int> > > resourceTable;
///the schedule( with many schedule stage)
std::vector<std::vector<ModuloSchedGraphNode*> > schedule;
@@ -48,23 +48,16 @@ class ModuloScheduling:NonCopyable {
typedef BasicBlock::InstListType InstListType;
typedef std::vector<std::vector<ModuloSchedGraphNode*> > vvNodeType;
public:
///constructor
ModuloScheduling(ModuloSchedGraph & _graph):
graph(_graph),
target(graph.getTarget()),
oNodes(graph.getONodes())
graph(_graph), target(graph.getTarget()), oNodes(graph.getONodes())
{
II = graph.getMII();
bb = (BasicBlock *) graph.getBasicBlocks()[0];
instrScheduling();
};
///destructor
~ModuloScheduling() {};
///the method to compute schedule and instert epilogue and prologue
@@ -72,7 +65,8 @@ public:
///debug functions:
///dump the schedule and core schedule
void dumpScheduling();
void
dumpScheduling();
///dump the input vector of nodes
//sch: the input vector of nodes
@@ -81,8 +75,7 @@ public:
///dump the resource usage table
void dumpResourceUsageTable();
//*******************internel functions*******************************
//*******************internal functions*******************************
private:
//clear memory from the last round and initialize if necessary
void clearInitMem(const TargetSchedInfo&);
@@ -93,39 +86,45 @@ private:
BasicBlock *getSuccBB(BasicBlock *);
BasicBlock *getPredBB(BasicBlock *);
void constructPrologue(BasicBlock *prologue);
void constructKernel(BasicBlock* prologue,BasicBlock* kernel,BasicBlock* epilogue);
void constructKernel(BasicBlock *prologue,
BasicBlock *kernel,
BasicBlock *epilogue);
void constructEpilogue(BasicBlock *epilogue, BasicBlock *succ_bb);
///update the resource table at the startCycle
// update the resource table at the startCycle
// vec: the resouce usage
// startCycle: the start cycle the resouce usage is
void updateResourceTable(std::vector<vector<unsigned int> > vec,int startCycle);
void updateResourceTable(std::vector<std::vector<unsigned int>> vec,
int startCycle);
///un-do the update in the resource table in the startCycle
// un-do the update in the resource table in the startCycle
// vec: the resouce usage
// startCycle: the start cycle the resouce usage is
void undoUpdateResourceTable(std::vector<vector<unsigned int> > vec,int startCycle);
void undoUpdateResourceTable(std::vector<vector<unsigned int>> vec,
int startCycle);
///return whether the resourcetable has negative element
///this function is called after updateResouceTable() to determine whether a node can
/// be scheduled at certain cycle
// return whether the resourcetable has negative element
// this function is called after updateResouceTable() to determine whether a
// node can be scheduled at certain cycle
bool resourceTableNegative();
///try to Schedule the node starting from start to end cycle(inclusive)
// try to Schedule the node starting from start to end cycle(inclusive)
// if it can be scheduled, put it in the schedule and update nodeScheduled
// node: the node to be scheduled
// start: start cycle
// end : end cycle
// nodeScheduled: a vector storing nodes which has been scheduled
bool ScheduleNode(ModuloSchedGraphNode* node,unsigned start, unsigned end, NodeVec& nodeScheduled);
bool ScheduleNode(ModuloSchedGraphNode * node, unsigned start,
unsigned end, NodeVec &nodeScheduled);
//each instruction has a memory of the latest clone instruction
//the clone instruction can be get using getClone()
//this function clears the memory, i.e. getClone() after calling this function returns null
//this function clears the memory, i.e. getClone() after calling this function
//returns null
void clearCloneMemory();
//this fuction make a clone of this input Instruction and update the clone memory
//this fuction make a clone of this input Instruction and update the clone
//memory
//inst: the instrution to be cloned
Instruction *cloneInstSetMemory(Instruction *inst);
@@ -136,11 +135,13 @@ private:
};
class ModuloSchedulingSet:NonCopyable{
class ModuloSchedulingSet:
NonCopyable {
private:
//the graphSet to feed in
ModuloSchedGraphSet & graphSet;
public:
//constructor
@@ -148,16 +149,12 @@ class ModuloSchedulingSet:NonCopyable{
ModuloSchedulingSet(ModuloSchedGraphSet _graphSet): graphSet(_graphSet) {
for (unsigned i = 0; i < graphSet.size(); i++) {
ModuloSchedGraph & graph = *(graphSet[i]);
if(graph.isLoop())ModuloScheduling ModuloScheduling(graph);
if (graph.isLoop())
ModuloScheduling ModuloScheduling(graph);
}
};
//destructor
~ModuloSchedulingSet() {};
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
//===- ModuloSchedGraph.h - Represent a collection of data structures ----*- C++ -*-===//
//===- ModuloSchedGraph.h - Modulo Scheduling Graph and Set -*- C++ -*-----===//
//
// This header defines the primative classes that make up a data structure
// graph.
@@ -8,14 +8,13 @@
#ifndef LLVM_CODEGEN_MODULO_SCHED_GRAPH_H
#define LLVM_CODEGEN_MODULO_SCHED_GRAPH_H
#include "Support/HashExtras.h"
#include "Support/GraphTraits.h"
#include "../InstrSched/SchedGraphCommon.h"
#include "llvm/Instruction.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "Support/HashExtras.h"
#include "Support/GraphTraits.h"
#include "../InstrSched/SchedGraphCommon.h"
#include <iostream>
using std::pair;
//for debug information selecton
enum ModuloSchedDebugLevel_t {
@@ -25,10 +24,11 @@ enum ModuloSchedDebugLevel_t{
ModuloSched_PrintScheduleProcess,
};
//===============------------------------------------------------------------------------
///ModuloSchedGraphNode - Implement a data structure based on the SchedGraphNodeCommon
///this class stores informtion needed later to order the nodes in modulo scheduling
///
//===----------------------------------------------------------------------===//
// ModuloSchedGraphNode - Implement a data structure based on the
// SchedGraphNodeCommon this class stores informtion needed later to order the
// nodes in modulo scheduling
//
class ModuloSchedGraphNode:public SchedGraphNodeCommon {
private:
// the corresponding instruction
@@ -52,35 +52,64 @@ private:
public:
//get the instruction
const Instruction* getInst() const { return inst;}
const Instruction *getInst() const {
return inst;
}
//get the instruction op-code name
const char* getInstOpcodeName() const{ return inst->getOpcodeName();}
const char *getInstOpcodeName() const {
return inst->getOpcodeName();
}
//get the instruction op-code
const unsigned getInstOpcode() const { return inst->getOpcode();}
const unsigned getInstOpcode() const {
return inst->getOpcode();
}
//return whether the node is NULL
bool isNullNode() const{ return(inst== NULL);}
bool isNullNode() const {
return (inst == NULL);
}
//return whether the property of the node has been computed
bool getPropertyComputed() {return propertyComputed;}
bool getPropertyComputed() {
return propertyComputed;
}
//set the propertyComputed
void setPropertyComputed(bool _propertyComputed) {propertyComputed = _propertyComputed;}
void setPropertyComputed(bool _propertyComputed) {
propertyComputed = _propertyComputed;
}
//get the corresponding property
int getASAP(){ return ASAP;}
int getALAP(){ return ALAP;}
int getMov() { return mov;}
int getDepth(){return depth;}
int getHeight(){return height;}
int getSchTime(){return schTime;}
int getEarlyStart(){return earlyStart;}
int getLateStart() { return lateStart;}
void setEarlyStart(int _earlyStart) {earlyStart= _earlyStart;}
void setLateStart(int _lateStart) {lateStart= _lateStart;}
void setSchTime(int _time){schTime=_time;}
int getASAP() {
return ASAP;
}
int getALAP() {
return ALAP;
}
int getMov() {
return mov;
}
int getDepth() {
return depth;
}
int getHeight() {
return height;
}
int getSchTime() {
return schTime;
}
int getEarlyStart() {
return earlyStart;
}
int getLateStart() {
return lateStart;
}
void setEarlyStart(int _earlyStart) {
earlyStart = _earlyStart;
}
void setLateStart(int _lateStart) {
lateStart = _lateStart;
}
void setSchTime(int _time) {
schTime = _time;
}
private:
friend class ModuloSchedGraph;
@@ -95,34 +124,25 @@ public:
ModuloSchedGraphNode(unsigned int _nodeId,
const BasicBlock * _bb,
const Instruction * _inst,
int indexInBB,
const TargetMachine& target);
int indexInBB, const TargetMachine &target);
friend std::ostream& operator<<(std::ostream& os,const ModuloSchedGraphNode& edge);
friend std::ostream & operator<<(std::ostream & os,
const ModuloSchedGraphNode & edge);
};
//FIXME: these two value should not be used
#define MAXNODE 100
#define MAXCC 100
//===----------------------------------------------------------------------===//
/// ModuloSchedGraph- the data structure to store dependence between nodes
/// it catches data dependence and constrol dependence
///
///
class ModuloSchedGraph :
public SchedGraphCommon,
protected hash_map<const Instruction*, ModuloSchedGraphNode*>
{
protected hash_map<const Instruction*,ModuloSchedGraphNode*> {
private:
//iteration Interval
@@ -196,6 +216,7 @@ private:
NodeVec vectorSub(NodeVec set1, NodeVec set2);
typedef hash_map<const Instruction*,ModuloSchedGraphNode*> map_base;
public:
using map_base::iterator;
using map_base::const_iterator;
@@ -203,18 +224,24 @@ public:
public:
//get target machine
const TargetMachine& getTarget(){return target;}
const TargetMachine & getTarget() {
return target;
}
//get the iteration interval
const int getMII(){return MII;}
const int getMII() {
return MII;
}
//get the ordered nodes
const NodeVec& getONodes(){return oNodes;}
const NodeVec & getONodes() {
return oNodes;
}
//get the number of nodes (including the root and leaf)
//note: actually root and leaf is not used
const unsigned int getNumNodes() const {return size()+2;}
const unsigned int getNumNodes() const {
return size() + 2;
}
//return wether the BasicBlock 'bb' contains a loop
bool isLoop(const BasicBlock * bb);
@@ -227,10 +254,7 @@ public:
const_iterator onePair = this->find(inst);
return (onePair != this->end()) ? (*onePair).second : NULL;
}
//Debugging support
//dump the graph
void dump() const;
//Debugging support//dump the graph void dump() const;
//dump the basicBlock
void dump(const BasicBlock * bb);
//dump the basicBlock into 'os' stream
@@ -242,13 +266,11 @@ public:
friend class ModuloSchedGraphSet; //give access to ctor
public:
/*ctr*/
ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &_target)
:SchedGraphCommon(bb), target(_target) {
buildGraph(target);
}
/*dtr*/
~ModuloSchedGraph() {
for (const_iterator I = begin(); I != end(); ++I)
delete I->second;
@@ -259,9 +281,7 @@ public:
using map_base::begin;
using map_base::end;
inline void noteModuloSchedGraphNodeForInst(const Instruction* inst,
void noteModuloSchedGraphNodeForInst(const Instruction *inst,
ModuloSchedGraphNode *node)
{
assert((*this)[inst] == NULL);
@@ -308,12 +328,10 @@ public:
int computeRecII(const BasicBlock *bb);
};
///==================================-
//gragh set
//==================================-
// Graph set
class ModuloSchedGraphSet:
public std::vector<ModuloSchedGraph*>
{
class ModuloSchedGraphSet : public std::vector<ModuloSchedGraph*> {
private:
const Function *method;
@@ -323,26 +341,25 @@ public:
using baseVector::const_iterator;
public:
/*ctor*/ ModuloSchedGraphSet (const Function* function, const TargetMachine& target);
ModuloSchedGraphSet(const Function *function, const TargetMachine &target);
~ModuloSchedGraphSet();
/*dtor*/ ~ModuloSchedGraphSet ();
//iterators
// Iterators
using baseVector::begin;
using baseVector::end;
// Debugging support
void dump() const;
private:
inline void addGraph(ModuloSchedGraph* graph){
void addGraph(ModuloSchedGraph *graph) {
assert(graph != NULL);
this->push_back(graph);
}
// Graph builder
void buildGraphsForMethod (const Function *F, const TargetMachine& target);
};
void buildGraphsForMethod(const Function *F,
const TargetMachine &target);
}
#endif

View File

@@ -1,46 +1,36 @@
//===- SPLInstrScheduling.cpp - Modulo Software Pipelining Instruction Scheduling support -------===//
//
// this file implements the llvm/CodeGen/ModuloScheduling.h interface
//===- ModuloScheduling.cpp - Modulo Software Pipelining ------------------===//
//
// Implements the llvm/CodeGen/ModuloScheduling.h interface
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
//#include "llvm/CodeGen/MachineCodeForBasicBlock.h"
//#include "llvm/CodeGen/MachineCodeForMethod.h"
#include "llvm/CodeGen/MachineFunction.h"
//#include "llvm/Analysis/LiveVar/FunctionLiveVarInfo.h" // FIXME: Remove when modularized better
#include "llvm/Target/TargetMachine.h"
#include "llvm/BasicBlock.h"
#include "llvm/Constants.h"
#include "llvm/Instruction.h"
#include "Support/CommandLine.h"
#include <algorithm>
#include "ModuloSchedGraph.h"
#include "ModuloScheduling.h"
#include "llvm/Target/TargetSchedInfo.h"
#include "llvm/BasicBlock.h"
#include "llvm/iTerminators.h"
#include "llvm/iPHINode.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineCodeForInstruction.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/InstrSelection.h"
#include "llvm/Target/TargetSchedInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "Support/CommandLine.h"
#include "ModuloSchedGraph.h"
#include "ModuloScheduling.h"
#include <algorithm>
#include <fstream>
#include <iostream>
//#include <swig.h>
#include <fstream>
#include "llvm/CodeGen/InstrSelection.h"
#define max(x,y) (x>y?x:y)
#define min(x,y) (x<y?x:y)
using std::cerr;
using std::cout;
using std::ostream;
using std::ios;
using std::filebuf;
//************************************************************
// printing Debug information
// ModuloSchedDebugLevel stores the value of debug level
// modsched_os is the ostream to dump debug information, which is written into the file 'moduloSchedDebugInfo.output'
// modsched_os is the ostream to dump debug information, which is written into
// the file 'moduloSchedDebugInfo.output'
// see ModuloSchedulingPass::runOnFunction()
//************************************************************
@@ -48,37 +38,34 @@ ModuloSchedDebugLevel_t ModuloSchedDebugLevel;
static cl::opt<ModuloSchedDebugLevel_t,true>
SDL_opt("modsched", cl::Hidden, cl::location(ModuloSchedDebugLevel),
cl::desc("enable modulo scheduling debugging information"),
cl::values(
clEnumValN(ModuloSched_NoDebugInfo, "n", "disable debug output"),
clEnumValN(ModuloSched_Disable, "off", "disable modulo scheduling"),
clEnumValN(ModuloSched_PrintSchedule, "psched", "print original and new schedule"),
clEnumValN(ModuloSched_PrintScheduleProcess,"pschedproc", "print how the new schdule is produced"),
0));
cl::values(clEnumValN
(ModuloSched_NoDebugInfo, "n", "disable debug output"),
clEnumValN(ModuloSched_Disable, "off",
"disable modulo scheduling"),
clEnumValN(ModuloSched_PrintSchedule, "psched",
"print original and new schedule"),
clEnumValN(ModuloSched_PrintScheduleProcess, "pschedproc",
"print how the new schdule is produced"), 0));
filebuf modSched_fb;
ostream modSched_os(&modSched_fb);
std::filebuf modSched_fb;
std::ostream modSched_os(&modSched_fb);
//************************************************************
///the method to compute schedule and instert epilogue and prologue
void ModuloScheduling::instrScheduling(){
// Computes the schedule and inserts epilogue and prologue
//
void ModuloScheduling::instrScheduling()
{
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
modSched_os<<"*************************computing modulo schedule ************************\n";
modSched_os << "*************** computing modulo schedule **************\n";
const TargetSchedInfo & msi = target.getSchedInfo();
//number of issue slots in the in each cycle
int numIssueSlots = msi.maxNumIssueTotal;
//compute the schedule
bool success = false;
while(!success)
{
while (!success) {
//clear memory from the last round and initialize if necessary
clearInitMem(msi);
@@ -96,7 +83,6 @@ void ModuloScheduling::instrScheduling(){
if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule)
dumpScheduling();
//the schedule has been computed
//create epilogue, prologue and kernel BasicBlock
@@ -108,23 +94,20 @@ void ModuloScheduling::instrScheduling(){
modSched_os << "dumping the orginal block\n";
graph.dump(bb);
}
//construction of prologue, kernel and epilogue
BasicBlock *kernel = bb->splitBasicBlock(bb->begin());
BasicBlock *prologue = bb;
BasicBlock *epilogue = kernel->splitBasicBlock(kernel->begin());
//construct prologue
// Construct prologue
constructPrologue(prologue);
//construct kernel
// Construct kernel
constructKernel(prologue, kernel, epilogue);
//construct epilogue
// Construct epilogue
constructEpilogue(epilogue, succ_bb);
//print the BasicBlocks if necessary
if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) {
modSched_os << "dumping the prologue block:\n";
@@ -134,28 +117,27 @@ void ModuloScheduling::instrScheduling(){
modSched_os << "dumping the epilogue block\n";
graph.dump(epilogue);
}
}
//clear memory from the last round and initialize if necessary
void ModuloScheduling::clearInitMem(const TargetSchedInfo& msi){
// Clear memory from the last round and initialize if necessary
//
void ModuloScheduling::clearInitMem(const TargetSchedInfo & msi)
{
unsigned numIssueSlots = msi.maxNumIssueTotal;
// clear nodeScheduled from the last round
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) {
modSched_os<< "***** new round with II= "<<II<<" *******************"<<"\n";
modSched_os<< " **************clear the vector nodeScheduled**************** \n";
modSched_os << "***** new round with II= " << II <<
" *******************\n";
modSched_os <<
" ************clear the vector nodeScheduled*************\n";
}
nodeScheduled.clear();
// clear resourceTable from the last round and reset it
resourceTable.clear();
for(unsigned i=0;i< II;i++)
for (unsigned i = 0; i < II; ++i)
resourceTable.push_back(msi.resourceNumVector);
// clear the schdule and coreSchedule from the last round
schedule.clear();
coreSchedule.clear();
@@ -163,32 +145,33 @@ void ModuloScheduling::clearInitMem(const TargetSchedInfo& msi){
// create a coreSchedule of size II*numIssueSlots
// each entry is NULL
while (coreSchedule.size() < II) {
std::vector<ModuloSchedGraphNode*>* newCycle=new std::vector<ModuloSchedGraphNode*>();
for(unsigned k=0;k<numIssueSlots;k++)
std::vector < ModuloSchedGraphNode * >*newCycle =
new std::vector < ModuloSchedGraphNode * >();
for (unsigned k = 0; k < numIssueSlots; ++k)
newCycle->push_back(NULL);
coreSchedule.push_back(*newCycle);
}
}
//compute schedule and coreSchedule with the current II
bool ModuloScheduling::computeSchedule(){
// Compute schedule and coreSchedule with the current II
//
bool ModuloScheduling::computeSchedule()
{
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
modSched_os << "start to compute schedule\n";
//loop over the ordered nodes
for(NodeVec::const_iterator I=oNodes.begin();I!=oNodes.end();I++)
{
//try to schedule for node I
// Loop over the ordered nodes
for (NodeVec::const_iterator I = oNodes.begin(); I != oNodes.end(); ++I) {
// Try to schedule for node I
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
dumpScheduling();
ModuloSchedGraphNode *node = *I;
//compute whether this node has successor(s)
// Compute whether this node has successor(s)
bool succ = true;
//compute whether this node has predessor(s)
// Compute whether this node has predessor(s)
bool pred = true;
NodeVec schSucc = graph.vectorConj(nodeScheduled, graph.succSet(node));
@@ -207,78 +190,90 @@ bool ModuloScheduling::computeSchedule(){
node->setEarlyStart(-1);
node->setLateStart(9999);
//this node has predessor but no successor
if (!succ && pred) {
//this node's earlyStart is it's predessor's schedule time + the edge delay
// - the iteration difference* II
// This node's earlyStart is it's predessor's schedule time + the edge
// delay - the iteration difference* II
for (unsigned i = 0; i < schPred.size(); i++) {
ModuloSchedGraphNode *predNode = schPred[i];
SchedGraphEdge* edge=graph.getMaxDelayEdge(predNode->getNodeId(),node->getNodeId());
int temp=predNode->getSchTime()+edge->getMinDelay() - edge->getIteDiff()*II;
node->setEarlyStart( max(node->getEarlyStart(),temp));
SchedGraphEdge *edge =
graph.getMaxDelayEdge(predNode->getNodeId(),
node->getNodeId());
int temp =
predNode->getSchTime() + edge->getMinDelay() -
edge->getIteDiff() * II;
node->setEarlyStart(std::max(node->getEarlyStart(), temp));
}
startTime = node->getEarlyStart();
endTime = node->getEarlyStart() + II - 1;
}
//this node has successor but no predessor
// This node has a successor but no predecessor
if (succ && !pred) {
for(unsigned i=0;i<schSucc.size();i++){
for (unsigned i = 0; i < schSucc.size(); ++i) {
ModuloSchedGraphNode *succNode = schSucc[i];
SchedGraphEdge* edge=graph.getMaxDelayEdge(succNode->getNodeId(),node->getNodeId());
int temp=succNode->getSchTime() - edge->getMinDelay() + edge->getIteDiff()*II;
node->setLateStart(min(node->getEarlyStart(),temp));
SchedGraphEdge *edge =
graph.getMaxDelayEdge(succNode->getNodeId(),
node->getNodeId());
int temp =
succNode->getSchTime() - edge->getMinDelay() +
edge->getIteDiff() * II;
node->setLateStart(std::min(node->getEarlyStart(), temp));
}
startTime = node->getLateStart() - II + 1;
endTime = node->getLateStart();
}
//this node has both successors and predessors
if(succ && pred)
{
for(unsigned i=0;i<schPred.size();i++){
// This node has both successors and predecessors
if (succ && pred) {
for (unsigned i = 0; i < schPred.size(); ++i) {
ModuloSchedGraphNode *predNode = schPred[i];
SchedGraphEdge* edge=graph.getMaxDelayEdge(predNode->getNodeId(),node->getNodeId());
int temp=predNode->getSchTime()+edge->getMinDelay() - edge->getIteDiff()*II;
node->setEarlyStart(max(node->getEarlyStart(),temp));
SchedGraphEdge *edge =
graph.getMaxDelayEdge(predNode->getNodeId(),
node->getNodeId());
int temp =
predNode->getSchTime() + edge->getMinDelay() -
edge->getIteDiff() * II;
node->setEarlyStart(std::max(node->getEarlyStart(), temp));
}
for(unsigned i=0;i<schSucc.size();i++){
for (unsigned i = 0; i < schSucc.size(); ++i) {
ModuloSchedGraphNode *succNode = schSucc[i];
SchedGraphEdge* edge=graph.getMaxDelayEdge(succNode->getNodeId(),node->getNodeId());
int temp=succNode->getSchTime() - edge->getMinDelay() + edge->getIteDiff()*II;
node->setLateStart(min(node->getEarlyStart(),temp));
SchedGraphEdge *edge =
graph.getMaxDelayEdge(succNode->getNodeId(),
node->getNodeId());
int temp =
succNode->getSchTime() - edge->getMinDelay() +
edge->getIteDiff() * II;
node->setLateStart(std::min(node->getEarlyStart(), temp));
}
startTime = node->getEarlyStart();
endTime=min(node->getLateStart(),node->getEarlyStart()+((int)II)-1);
endTime = std::min(node->getLateStart(),
node->getEarlyStart() + ((int) II) - 1);
}
//this node has no successor or predessor
if (!succ && !pred) {
node->setEarlyStart(node->getASAP());
startTime = node->getEarlyStart();
endTime = node->getEarlyStart() + II - 1;
}
//try to schedule this node based on the startTime and endTime
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
modSched_os << "scheduling the node " << (*I)->getNodeId() << "\n";
bool success= this->ScheduleNode(node,startTime, endTime,nodeScheduled);
if(!success)return false;
bool success =
this->ScheduleNode(node, startTime, endTime, nodeScheduled);
if (!success)
return false;
}
return true;
}
//get the successor of the BasicBlock
BasicBlock* ModuloScheduling::getSuccBB(BasicBlock* bb){
// Get the successor of the BasicBlock
//
BasicBlock *ModuloScheduling::getSuccBB(BasicBlock *bb)
{
BasicBlock *succ_bb;
for(unsigned i=0;i < II; i++)
for(unsigned j=0;j< coreSchedule[i].size();j++)
for (unsigned i = 0; i < II; ++i)
for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
if (coreSchedule[i][j]) {
const Instruction *ist = coreSchedule[i][j]->getInst();
@@ -286,13 +281,18 @@ BasicBlock* ModuloScheduling::getSuccBB(BasicBlock* bb){
//assume we only have one successor (besides itself) here
if (BranchInst::classof(ist)) {
BranchInst *bi = (BranchInst *) ist;
assert(bi->isConditional()&&"the branchInst is not a conditional one");
assert(bi->getNumSuccessors() ==2&&" more than two successors?");
assert(bi->isConditional() &&
"the branchInst is not a conditional one");
assert(bi->getNumSuccessors() == 2
&& " more than two successors?");
BasicBlock *bb1 = bi->getSuccessor(0);
BasicBlock *bb2 = bi->getSuccessor(1);
assert( (bb1 == bb|| bb2 == bb) && " None of its successor is itself?");
if(bb1 == bb) succ_bb=bb2;
else succ_bb=bb1;
assert((bb1 == bb || bb2 == bb) &&
" None of its successors is itself?");
if (bb1 == bb)
succ_bb = bb2;
else
succ_bb = bb1;
return succ_bb;
}
}
@@ -301,13 +301,13 @@ BasicBlock* ModuloScheduling::getSuccBB(BasicBlock* bb){
}
//get the predecessor of the BasicBlock
BasicBlock* ModuloScheduling::getPredBB(BasicBlock* bb){
// Get the predecessor of the BasicBlock
//
BasicBlock *ModuloScheduling::getPredBB(BasicBlock *bb)
{
BasicBlock *pred_bb;
for(unsigned i=0;i < II; i++)
for(unsigned j=0;j< coreSchedule[i].size();j++)
for (unsigned i = 0; i < II; ++i)
for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
if (coreSchedule[i][j]) {
const Instruction *ist = coreSchedule[i][j]->getInst();
@@ -315,12 +315,16 @@ BasicBlock* ModuloScheduling::getPredBB(BasicBlock* bb){
//assume we only have one predecessor (besides itself) here
if (PHINode::classof(ist)) {
PHINode *phi = (PHINode *) ist;
assert(phi->getNumIncomingValues() == 2 &&" the number of incoming value is not equal to two? ");
assert(phi->getNumIncomingValues() == 2 &&
" the number of incoming value is not equal to two? ");
BasicBlock *bb1 = phi->getIncomingBlock(0);
BasicBlock *bb2 = phi->getIncomingBlock(1);
assert( (bb1 == bb || bb2 == bb) && " None of its predecessor is itself?");
if(bb1 == bb) pred_bb=bb2;
else pred_bb=bb1;
assert((bb1 == bb || bb2 == bb) &&
" None of its predecessor is itself?");
if (bb1 == bb)
pred_bb = bb2;
else
pred_bb = bb1;
return pred_bb;
}
}
@@ -329,39 +333,45 @@ BasicBlock* ModuloScheduling::getPredBB(BasicBlock* bb){
}
//construct the prologue
void ModuloScheduling::constructPrologue(BasicBlock* prologue){
// Construct the prologue
//
void ModuloScheduling::constructPrologue(BasicBlock *prologue)
{
InstListType & prologue_ist = prologue->getInstList();
vvNodeType& tempSchedule_prologue= *(new vector< std::vector<ModuloSchedGraphNode*> >(schedule));
vvNodeType & tempSchedule_prologue =
*(new vector < std::vector < ModuloSchedGraphNode * >>(schedule));
//compute the schedule for prologue
unsigned round = 0;
unsigned scheduleSize = schedule.size();
while (round < scheduleSize / II) {
round++;
for(unsigned i=0;i < scheduleSize ;i++){
if(round*II + i >= scheduleSize) break;
for(unsigned j=0;j < schedule[i].size(); j++)
for (unsigned i = 0; i < scheduleSize; ++i) {
if (round * II + i >= scheduleSize)
break;
for (unsigned j = 0; j < schedule[i].size(); ++j) {
if (schedule[i][j]) {
assert( tempSchedule_prologue[round*II +i ][j] == NULL && "table not consitant with core table");
//move the schedule one iteration ahead and overlap with the original one
assert(tempSchedule_prologue[round * II + i][j] == NULL &&
"table not consitent with core table");
// move the schedule one iteration ahead and overlap with the original
tempSchedule_prologue[round * II + i][j] = schedule[i][j];
}
}
}
}
//clear the clone memory in the core schedule instructions
// Clear the clone memory in the core schedule instructions
clearCloneMemory();
//fill in the prologue
for(unsigned i=0;i < ceil(1.0*scheduleSize/II -1)*II ;i++)
for(unsigned j=0;j < tempSchedule_prologue[i].size();j++)
// Fill in the prologue
for (unsigned i = 0; i < ceil(1.0 * scheduleSize / II - 1) * II; ++i)
for (unsigned j = 0; j < tempSchedule_prologue[i].size(); ++j)
if (tempSchedule_prologue[i][j]) {
//get the instruction
Instruction* orn=(Instruction*)tempSchedule_prologue[i][j]->getInst();
Instruction *orn =
(Instruction *) tempSchedule_prologue[i][j]->getInst();
//made a clone of it
Instruction *cln = cloneInstSetMemory(orn);
@@ -369,8 +379,8 @@ void ModuloScheduling::constructPrologue(BasicBlock* prologue){
//insert the instruction
prologue_ist.insert(prologue_ist.back(), cln);
//if there is PHINode in the prologue, the incoming value from itself should be removed
//because it is not a loop any longer
//if there is PHINode in the prologue, the incoming value from itself
//should be removed because it is not a loop any longer
if (PHINode::classof(cln)) {
PHINode *phi = (PHINode *) cln;
phi->removeIncomingValue(phi->getParent());
@@ -379,25 +389,28 @@ void ModuloScheduling::constructPrologue(BasicBlock* prologue){
}
//construct the kernel BasicBlock
void ModuloScheduling::constructKernel(BasicBlock* prologue,BasicBlock* kernel,BasicBlock* epilogue){
// Construct the kernel BasicBlock
//
void ModuloScheduling::constructKernel(BasicBlock *prologue,
BasicBlock *kernel,
BasicBlock *epilogue)
{
//*************fill instructions in the kernel****************
InstListType & kernel_ist = kernel->getInstList();
BranchInst *brchInst;
PHINode *phiInst, *phiCln;
for(unsigned i=0;i<coreSchedule.size();i++)
for(unsigned j=0;j<coreSchedule[i].size();j++)
for (unsigned i = 0; i < coreSchedule.size(); ++i)
for (unsigned j = 0; j < coreSchedule[i].size(); ++j)
if (coreSchedule[i][j]) {
//we should take care of branch instruction differently with normal instructions
// Take care of branch instruction differently with normal instructions
if (BranchInst::classof(coreSchedule[i][j]->getInst())) {
brchInst = (BranchInst *) coreSchedule[i][j]->getInst();
continue;
}
//we should take care of PHINode instruction differently with normal instructions
// Take care of PHINode instruction differently with normal instructions
if (PHINode::classof(coreSchedule[i][j]->getInst())) {
phiInst = (PHINode *) coreSchedule[i][j]->getInst();
Instruction *cln = cloneInstSetMemory(phiInst);
@@ -405,26 +418,28 @@ void ModuloScheduling::constructKernel(BasicBlock* prologue,BasicBlock* kernel,B
phiCln = (PHINode *) cln;
continue;
}
//for normal instructions: made a clone and insert it in the kernel_ist
Instruction* cln=cloneInstSetMemory( (Instruction*)coreSchedule[i][j]->getInst());
Instruction *cln =
cloneInstSetMemory((Instruction *) coreSchedule[i][j]->
getInst());
kernel_ist.insert(kernel_ist.back(), cln);
}
//the two incoming BasicBlock for PHINode is the prologue and the kernel (itself)
// The two incoming BasicBlock for PHINode is the prologue and the kernel
// (itself)
phiCln->setIncomingBlock(0, prologue);
phiCln->setIncomingBlock(1, kernel);
//the incoming value for the kernel (itself) is the new value which is computed in the kernel
// The incoming value for the kernel (itself) is the new value which is
// computed in the kernel
Instruction *originalVal = (Instruction *) phiInst->getIncomingValue(1);
phiCln->setIncomingValue(1, originalVal->getClone());
//make a clone of the branch instruction and insert it in the end
// Make a clone of the branch instruction and insert it in the end
BranchInst *cln = (BranchInst *) cloneInstSetMemory(brchInst);
kernel_ist.insert(kernel_ist.back(), cln);
//delete the unconditional branch instruction, which is generated when splitting the basicBlock
// delete the unconditional branch instruction, which is generated when
// splitting the basicBlock
kernel_ist.erase(--kernel_ist.end());
// set the first successor to itself
@@ -442,29 +457,34 @@ void ModuloScheduling::constructKernel(BasicBlock* prologue,BasicBlock* kernel,B
assert(ConstantSInt::classof(operand));
//change the constant in the condtion instruction
ConstantSInt* iteTimes=ConstantSInt::get(operand->getType(),((ConstantSInt*)operand)->getValue()-II+1);
ConstantSInt *iteTimes =
ConstantSInt::get(operand->getType(),
((ConstantSInt *) operand)->getValue() - II + 1);
cond->setOperand(1, iteTimes);
}
//construct the epilogue
void ModuloScheduling::constructEpilogue(BasicBlock* epilogue, BasicBlock* succ_bb){
// Construct the epilogue
//
void ModuloScheduling::constructEpilogue(BasicBlock *epilogue,
BasicBlock *succ_bb)
{
//compute the schedule for epilogue
vvNodeType& tempSchedule_epilogue= *(new vector< std::vector<ModuloSchedGraphNode*> >(schedule));
vvNodeType & tempSchedule_epilogue =
*(new vector < std::vector < ModuloSchedGraphNode * >>(schedule));
unsigned scheduleSize = schedule.size();
int round = 0;
while (round < ceil(1.0 * scheduleSize / II) - 1) {
round++;
for (unsigned i = 0; i < scheduleSize; i++) {
if(i + round *II >= scheduleSize) break;
if (i + round * II >= scheduleSize)
break;
for (unsigned j = 0; j < schedule[i].size(); j++)
if (schedule[i + round * II][j]) {
assert( tempSchedule_epilogue[i][j] == NULL && "table not consitant with core table");
assert(tempSchedule_epilogue[i][j] == NULL
&& "table not consitant with core table");
//move the schdule one iteration behind and overlap
tempSchedule_epilogue[i][j] = schedule[i + round * II][j];
@@ -477,7 +497,8 @@ void ModuloScheduling::constructEpilogue(BasicBlock* epilogue, BasicBlock* succ_
for (unsigned i = II; i < scheduleSize; i++)
for (unsigned j = 0; j < tempSchedule_epilogue[i].size(); j++)
if (tempSchedule_epilogue[i][j]) {
Instruction* inst=(Instruction*)tempSchedule_epilogue[i][j]->getInst();
Instruction *inst =
(Instruction *) tempSchedule_epilogue[i][j]->getInst();
//BranchInst and PHINode should be treated differently
//BranchInst:unecessary, simly omitted
@@ -489,7 +510,6 @@ void ModuloScheduling::constructEpilogue(BasicBlock* epilogue, BasicBlock* succ_
}
}
//*************delete the original instructions****************//
//to delete the original instructions, we have to make sure their use is zero
@@ -516,11 +536,13 @@ void ModuloScheduling::constructEpilogue(BasicBlock* epilogue, BasicBlock* succ_
}
//----------------------------------------------------------------------------------------------
//this function replace the value(instruction) ist in other instructions with its latest clone
//i.e. after this function is called, the ist is not used anywhere and it can be erased.
//----------------------------------------------------------------------------------------------
void ModuloScheduling::updateUseWithClone(Instruction* ist){
//------------------------------------------------------------------------------
//this function replace the value(instruction) ist in other instructions with
//its latest clone i.e. after this function is called, the ist is not used
//anywhere and it can be erased.
//------------------------------------------------------------------------------
void ModuloScheduling::updateUseWithClone(Instruction * ist)
{
while (ist->use_size() > 0) {
bool destroyed = false;
@@ -531,16 +553,14 @@ void ModuloScheduling::updateUseWithClone(Instruction* ist){
for (unsigned i = 0; i < inst->getNumOperands(); i++)
if (inst->getOperand(i) == ist && ist->getClone()) {
//if the instruction is TmpInstruction, simly delete it because it has no parent
// and it does not belongs to any BasicBlock
// if the instruction is TmpInstruction, simly delete it because it has
// no parent and it does not belongs to any BasicBlock
if (TmpInstruction::classof(inst)) {
delete inst;
destroyed = true;
break;
}
//otherwise, set the instruction's operand to the value's clone
inst->setOperand(i, ist->getClone());
@@ -548,8 +568,7 @@ void ModuloScheduling::updateUseWithClone(Instruction* ist){
destroyed = true;
break;
}
if( !destroyed)
{
if (!destroyed) {
//if the use can not be destroyed , something is wrong
inst->dump();
assert(0 && "this use can not be destroyed");
@@ -563,27 +582,27 @@ void ModuloScheduling::updateUseWithClone(Instruction* ist){
//this function clear all clone mememoy
//i.e. set all instruction's clone memory to NULL
//*****************************************************
void ModuloScheduling::clearCloneMemory(){
void ModuloScheduling::clearCloneMemory()
{
for (unsigned i = 0; i < coreSchedule.size(); i++)
for (unsigned j = 0; j < coreSchedule[i].size(); j++)
if(coreSchedule[i][j]) ((Instruction*)coreSchedule[i][j]->getInst())->clearClone();
if (coreSchedule[i][j])
((Instruction *) coreSchedule[i][j]->getInst())->clearClone();
}
//********************************************************************************
//this function make a clone of the instruction orn
//the cloned instruction will use the orn's operands' latest clone as its operands
//it is done this way because LLVM is in SSA form and we should use the correct value
//
//******************************************************************************
// this function make a clone of the instruction orn the cloned instruction will
// use the orn's operands' latest clone as its operands it is done this way
// because LLVM is in SSA form and we should use the correct value
//this fuction also update the instruction orn's latest clone memory
//**********************************************************************************
Instruction* ModuloScheduling::cloneInstSetMemory(Instruction* orn) {
//******************************************************************************
Instruction *ModuloScheduling::cloneInstSetMemory(Instruction * orn)
{
// make a clone instruction
Instruction *cln = orn->clone();
// update the operands
for (unsigned k = 0; k < orn->getNumOperands(); k++) {
const Value *op = orn->getOperand(k);
@@ -600,9 +619,10 @@ Instruction* ModuloScheduling::cloneInstSetMemory(Instruction* orn) {
bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, unsigned end, NodeVec& nodeScheduled)
bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode * node,
unsigned start, unsigned end,
NodeVec & nodeScheduled)
{
const TargetSchedInfo & msi = target.getSchedInfo();
unsigned int numIssueSlots = msi.maxNumIssueTotal;
@@ -619,21 +639,22 @@ bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, u
modSched_os << "\t Trying slot " << j << "...........";
//check the resouce table, make sure there is no resource conflicts
const Instruction *instr = node->getInst();
MachineCodeForInstruction& tempMvec= MachineCodeForInstruction::get(instr);
MachineCodeForInstruction & tempMvec =
MachineCodeForInstruction::get(instr);
bool resourceConflict = false;
const TargetInstrInfo & mii = msi.getInstrInfo();
if(coreSchedule.size() < core_i+1 || !coreSchedule[core_i][core_j]){
if (coreSchedule.size() < core_i + 1
|| !coreSchedule[core_i][core_j]) {
//this->dumpResourceUsageTable();
int latency = 0;
for(unsigned k=0;k< tempMvec.size();k++)
{
for (unsigned k = 0; k < tempMvec.size(); k++) {
MachineInstr *minstr = tempMvec[k];
InstrRUsage rUsage = msi.getInstrRUsage(minstr->getOpCode());
std::vector < std::vector < resourceId_t > >resources
= rUsage.resourcesByCycle;
updateResourceTable(resources, i + latency);
latency +=max(mii.minLatency(minstr->getOpCode()),1) ;
latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
}
//this->dumpResourceUsageTable();
@@ -648,7 +669,7 @@ bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, u
std::vector < std::vector < resourceId_t > >resources
= rUsage.resourcesByCycle;
undoUpdateResourceTable(resources, i + latency);
latency +=max(mii.minLatency(minstr->getOpCode()),1) ;
latency += std::max(mii.minLatency(minstr->getOpCode()), 1);
}
resourceConflict = true;
}
@@ -656,11 +677,13 @@ bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, u
if (!resourceConflict && !coreSchedule[core_i][core_j]) {
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess) {
modSched_os << " OK!" << "\n";
modSched_os<<"Node "<<node->getNodeId()<< " is scheduleed."<<"\n";
modSched_os << "Node " << node->
getNodeId() << " is scheduleed." << "\n";
}
//schedule[i][j]=node;
while (schedule.size() <= i) {
std::vector<ModuloSchedGraphNode*>* newCycle=new std::vector<ModuloSchedGraphNode*>();
std::vector < ModuloSchedGraphNode * >*newCycle =
new std::vector < ModuloSchedGraphNode * >();
for (unsigned k = 0; k < numIssueSlots; k++)
newCycle->push_back(NULL);
schedule.push_back(*newCycle);
@@ -674,7 +697,8 @@ bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, u
//update coreSchedule
//coreSchedule[core_i][core_j]=node;
while (coreSchedule.size() <= core_i) {
std::vector<ModuloSchedGraphNode*>* newCycle=new std::vector<ModuloSchedGraphNode*>();
std::vector < ModuloSchedGraphNode * >*newCycle =
new std::vector < ModuloSchedGraphNode * >();
for (unsigned k = 0; k < numIssueSlots; k++)
newCycle->push_back(NULL);
coreSchedule.push_back(*newCycle);
@@ -690,27 +714,30 @@ bool ModuloScheduling::ScheduleNode(ModuloSchedGraphNode* node,unsigned start, u
nodeScheduled.push_back(node);
break;
}
else if( coreSchedule[core_i][core_j]) {
} else if (coreSchedule[core_i][core_j]) {
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
modSched_os << " Slot not available " << "\n";
}
else{
} else {
if (ModuloSchedDebugLevel >= ModuloSched_PrintScheduleProcess)
modSched_os << " Resource conflicts" << "\n";
}
}
if(isScheduled) break;
if (isScheduled)
break;
}
//assert(nodeScheduled &&"this node can not be scheduled?");
return isScheduled;
}
void ModuloScheduling::updateResourceTable(std::vector<std::vector<unsigned int> > useResources, int startCycle){
void ModuloScheduling::updateResourceTable(Resources useResources,
int startCycle)
{
for (unsigned i = 0; i < useResources.size(); i++) {
int absCycle = startCycle + i;
int coreCycle = absCycle % II;
std::vector<pair<int,int> >& resourceRemained=resourceTable[coreCycle];
std::vector<std::pair<int,int> > &resourceRemained =
resourceTable[coreCycle];
std::vector < unsigned int >&resourceUsed = useResources[i];
for (unsigned j = 0; j < resourceUsed.size(); j++) {
for (unsigned k = 0; k < resourceRemained.size(); k++)
@@ -721,11 +748,14 @@ void ModuloScheduling::updateResourceTable(std::vector<std::vector<unsigned int>
}
}
void ModuloScheduling::undoUpdateResourceTable(std::vector<std::vector<unsigned int> > useResources, int startCycle){
void ModuloScheduling::undoUpdateResourceTable(Resources useResources,
int startCycle)
{
for (unsigned i = 0; i < useResources.size(); i++) {
int absCycle = startCycle + i;
int coreCycle = absCycle % II;
std::vector<pair<int,int> >& resourceRemained=resourceTable[coreCycle];
std::vector<std::pair<int,int> > &resourceRemained =
resourceTable[coreCycle];
std::vector < unsigned int >&resourceUsed = useResources[i];
for (unsigned j = 0; j < resourceUsed.size(); j++) {
for (unsigned k = 0; k < resourceRemained.size(); k++)
@@ -738,16 +768,21 @@ void ModuloScheduling::undoUpdateResourceTable(std::vector<std::vector<unsigned
//-----------------------------------------------------------------------
//Function: resouceTableNegative
// Function: resourceTableNegative
// return value:
// return false if any element in the resouceTable is negative
// otherwise return true
// Purpose:
// this function is used to determine if an instruction is eligible for schedule at certain cycle
//---------------------------------------------------------------------------------------
bool ModuloScheduling::resourceTableNegative(){
assert(resourceTable.size() == (unsigned)II&& "resouceTable size must be equal to II");
// this function is used to determine if an instruction is eligible for
// schedule at certain cycle
//-----------------------------------------------------------------------
bool ModuloScheduling::resourceTableNegative()
{
assert(resourceTable.size() == (unsigned) II
&& "resouceTable size must be equal to II");
bool isNegative = false;
for (unsigned i = 0; i < resourceTable.size(); i++)
for (unsigned j = 0; j < resourceTable[i].size(); j++) {
@@ -767,11 +802,13 @@ bool ModuloScheduling::resourceTableNegative(){
//
//------------------------------------------------------------------------
void ModuloScheduling::dumpResourceUsageTable(){
void ModuloScheduling::dumpResourceUsageTable()
{
modSched_os << "dumping resource usage table" << "\n";
for (unsigned i = 0; i < resourceTable.size(); i++) {
for (unsigned j = 0; j < resourceTable[i].size(); j++)
modSched_os <<resourceTable[i][j].first<<":"<< resourceTable[i][j].second<<" ";
modSched_os << resourceTable[i][j].
first << ":" << resourceTable[i][j].second << " ";
modSched_os << "\n";
}
@@ -783,15 +820,14 @@ void ModuloScheduling::dumpResourceUsageTable(){
// print out thisSchedule for debug
//
//-----------------------------------------------------------------------
void ModuloScheduling::dumpSchedule(std::vector< std::vector<ModuloSchedGraphNode*> > thisSchedule){
void ModuloScheduling::dumpSchedule(vvNodeType thisSchedule)
{
const TargetSchedInfo & msi = target.getSchedInfo();
unsigned numIssueSlots = msi.maxNumIssueTotal;
for (unsigned i = 0; i < numIssueSlots; i++)
modSched_os << "\t#";
modSched_os << "\n";
for(unsigned i=0;i < thisSchedule.size();i++)
{
for (unsigned i = 0; i < thisSchedule.size(); i++) {
modSched_os << "cycle" << i << ": ";
for (unsigned j = 0; j < thisSchedule[i].size(); j++)
if (thisSchedule[i][j] != NULL)
@@ -811,15 +847,15 @@ void ModuloScheduling::dumpSchedule(std::vector< std::vector<ModuloSchedGraphNod
//
//-------------------------------------------------------
void ModuloScheduling::dumpScheduling(){
void ModuloScheduling::dumpScheduling()
{
modSched_os << "dump schedule:" << "\n";
const TargetSchedInfo & msi = target.getSchedInfo();
unsigned numIssueSlots = msi.maxNumIssueTotal;
for (unsigned i = 0; i < numIssueSlots; i++)
modSched_os << "\t#";
modSched_os << "\n";
for(unsigned i=0;i < schedule.size();i++)
{
for (unsigned i = 0; i < schedule.size(); i++) {
modSched_os << "cycle" << i << ": ";
for (unsigned j = 0; j < schedule[i].size(); j++)
if (schedule[i][j] != NULL)
@@ -859,19 +895,18 @@ namespace {
class ModuloSchedulingPass:public FunctionPass {
const TargetMachine & target;
public:
ModuloSchedulingPass(const TargetMachine &T) : target(T) {}
const char *getPassName() const { return "Modulo Scheduling"; }
ModuloSchedulingPass(const TargetMachine &T):target(T) {
} const char *getPassName() const {
return "Modulo Scheduling";
}
// getAnalysisUsage - We use LiveVarInfo...
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
//AU.addRequired(FunctionLiveVarInfo::ID);
}
bool runOnFunction(Function &F);
} bool runOnFunction(Function & F);
};
} // end anonymous namespace
bool ModuloSchedulingPass::runOnFunction(Function &F)
{
@@ -880,8 +915,10 @@ bool ModuloSchedulingPass::runOnFunction(Function &F)
return false;
if (ModuloSchedDebugLevel >= ModuloSched_PrintSchedule) {
modSched_fb.open("moduloSchedDebugInfo.output", ios::out);
modSched_os<<"******************Modula Scheduling debug information*************************"<<"\n ";
modSched_fb.open("moduloSchedDebugInfo.output", std::ios::out);
modSched_os <<
"******************Modula Scheduling debug information****************"
<< "\n ";
}
ModuloSchedGraphSet *graphSet = new ModuloSchedGraphSet(&F, target);
@@ -894,7 +931,7 @@ bool ModuloSchedulingPass::runOnFunction(Function &F)
}
Pass *createModuloSchedulingPass(const TargetMachine &tgt) {
Pass *createModuloSchedulingPass(const TargetMachine & tgt)
{
return new ModuloSchedulingPass(tgt);
}

View File

@@ -1,7 +1,7 @@
//// - head file for the classes ModuloScheduling and ModuloScheduling ----*- C++ -*-===//
//
// This header defines the the classes ModuloScheduling and ModuloSchedulingSet 's structure
// ModuloScheduling.h -------------------------------------------*- C++ -*-===//
//
// This header defines the the classes ModuloScheduling and
// ModuloSchedulingSet's structure
//
//===----------------------------------------------------------------------===//
@@ -13,31 +13,31 @@
#include <iostream>
#include <vector>
using std::vector;
class ModuloScheduling: NonCopyable {
private:
typedef std::vector<ModuloSchedGraphNode*> NodeVec;
/// the graph to feed in
typedef std::vector<ModuloSchedGraphNode*> NodeVec;
typedef std::vector<std::vector<unsigned> > Resources;
// The graph to feed in
ModuloSchedGraph &graph;
const TargetMachine &target;
//the BasicBlock to be scheduled
// The BasicBlock to be scheduled
BasicBlock *bb;
///Iteration Intervel
///FIXME: II may be a better name for its meaning
// Iteration Interval
// FIXME: II may be a better name for its meaning
unsigned II;
//the vector containing the nodes which have been scheduled
// The vector containing the nodes which have been scheduled
NodeVec nodeScheduled;
///the remaining unscheduled nodes
// The remaining unscheduled nodes
const NodeVec &oNodes;
///the machine resource table
std::vector< std::vector<pair<int,int> > > resourceTable ;
// The machine resource table
std::vector<std::vector<std::pair<int,int> > > resourceTable;
///the schedule( with many schedule stage)
std::vector<std::vector<ModuloSchedGraphNode*> > schedule;
@@ -48,23 +48,16 @@ class ModuloScheduling:NonCopyable {
typedef BasicBlock::InstListType InstListType;
typedef std::vector<std::vector<ModuloSchedGraphNode*> > vvNodeType;
public:
///constructor
ModuloScheduling(ModuloSchedGraph & _graph):
graph(_graph),
target(graph.getTarget()),
oNodes(graph.getONodes())
graph(_graph), target(graph.getTarget()), oNodes(graph.getONodes())
{
II = graph.getMII();
bb = (BasicBlock *) graph.getBasicBlocks()[0];
instrScheduling();
};
///destructor
~ModuloScheduling() {};
///the method to compute schedule and instert epilogue and prologue
@@ -72,7 +65,8 @@ public:
///debug functions:
///dump the schedule and core schedule
void dumpScheduling();
void
dumpScheduling();
///dump the input vector of nodes
//sch: the input vector of nodes
@@ -81,8 +75,7 @@ public:
///dump the resource usage table
void dumpResourceUsageTable();
//*******************internel functions*******************************
//*******************internal functions*******************************
private:
//clear memory from the last round and initialize if necessary
void clearInitMem(const TargetSchedInfo&);
@@ -93,39 +86,45 @@ private:
BasicBlock *getSuccBB(BasicBlock *);
BasicBlock *getPredBB(BasicBlock *);
void constructPrologue(BasicBlock *prologue);
void constructKernel(BasicBlock* prologue,BasicBlock* kernel,BasicBlock* epilogue);
void constructKernel(BasicBlock *prologue,
BasicBlock *kernel,
BasicBlock *epilogue);
void constructEpilogue(BasicBlock *epilogue, BasicBlock *succ_bb);
///update the resource table at the startCycle
// update the resource table at the startCycle
// vec: the resouce usage
// startCycle: the start cycle the resouce usage is
void updateResourceTable(std::vector<vector<unsigned int> > vec,int startCycle);
void updateResourceTable(std::vector<std::vector<unsigned int>> vec,
int startCycle);
///un-do the update in the resource table in the startCycle
// un-do the update in the resource table in the startCycle
// vec: the resouce usage
// startCycle: the start cycle the resouce usage is
void undoUpdateResourceTable(std::vector<vector<unsigned int> > vec,int startCycle);
void undoUpdateResourceTable(std::vector<vector<unsigned int>> vec,
int startCycle);
///return whether the resourcetable has negative element
///this function is called after updateResouceTable() to determine whether a node can
/// be scheduled at certain cycle
// return whether the resourcetable has negative element
// this function is called after updateResouceTable() to determine whether a
// node can be scheduled at certain cycle
bool resourceTableNegative();
///try to Schedule the node starting from start to end cycle(inclusive)
// try to Schedule the node starting from start to end cycle(inclusive)
// if it can be scheduled, put it in the schedule and update nodeScheduled
// node: the node to be scheduled
// start: start cycle
// end : end cycle
// nodeScheduled: a vector storing nodes which has been scheduled
bool ScheduleNode(ModuloSchedGraphNode* node,unsigned start, unsigned end, NodeVec& nodeScheduled);
bool ScheduleNode(ModuloSchedGraphNode * node, unsigned start,
unsigned end, NodeVec &nodeScheduled);
//each instruction has a memory of the latest clone instruction
//the clone instruction can be get using getClone()
//this function clears the memory, i.e. getClone() after calling this function returns null
//this function clears the memory, i.e. getClone() after calling this function
//returns null
void clearCloneMemory();
//this fuction make a clone of this input Instruction and update the clone memory
//this fuction make a clone of this input Instruction and update the clone
//memory
//inst: the instrution to be cloned
Instruction *cloneInstSetMemory(Instruction *inst);
@@ -136,11 +135,13 @@ private:
};
class ModuloSchedulingSet:NonCopyable{
class ModuloSchedulingSet:
NonCopyable {
private:
//the graphSet to feed in
ModuloSchedGraphSet & graphSet;
public:
//constructor
@@ -148,16 +149,12 @@ class ModuloSchedulingSet:NonCopyable{
ModuloSchedulingSet(ModuloSchedGraphSet _graphSet): graphSet(_graphSet) {
for (unsigned i = 0; i < graphSet.size(); i++) {
ModuloSchedGraph & graph = *(graphSet[i]);
if(graph.isLoop())ModuloScheduling ModuloScheduling(graph);
if (graph.isLoop())
ModuloScheduling ModuloScheduling(graph);
}
};
//destructor
~ModuloSchedulingSet() {};
};
#endif