mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-07 12:28:24 +00:00
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:
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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 ⌖
|
||||
|
||||
//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
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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 ⌖
|
||||
|
||||
//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
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user