+++ /dev/null
-//===- ModuloSchedGraph.cpp - Modulo Scheduling Graph and Set -*- C++ -*---===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Description here
-//===----------------------------------------------------------------------===//
-
-#include "ModuloSchedGraph.h"
-#include "llvm/Type.h"
-
-namespace llvm {
-
-ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned id, int index,
- const Instruction *inst,
- const TargetMachine &targ)
- : SchedGraphNodeCommon(id, index), Inst(inst), Target(targ) {
-}
-
-void ModuloSchedGraphNode::print(std::ostream &os) const {
- os << "Modulo Scheduling Node\n";
-}
-
-ModuloSchedGraph::ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &targ)
- : SchedGraphCommon(), BB(bb), Target(targ) {
-
- assert(BB != NULL && "Basic Block is null");
-
- //Builds nodes from each instruction in the basic block
- buildNodesForBB();
-
-}
-
-void ModuloSchedGraph::buildNodesForBB() {
- int count = 0;
- for (BasicBlock::const_iterator i = BB->begin(), e = BB->end(); i != e; ++i) {
- addNode(i,new ModuloSchedGraphNode(size(), count, i, Target));
- count++;
- }
-
- //Get machine instruction(s) for the llvm instruction
- //MachineCodeForInstruction &MC = MachineCodeForInstruction::get(Node->first);
-
-
-}
-
-void ModuloSchedGraph::addNode(const Instruction *I,
- ModuloSchedGraphNode *node) {
- assert(node!= NULL && "New ModuloSchedGraphNode is null");
- GraphMap[I] = node;
-}
-
-void ModuloSchedGraph::addDepEdges() {
-
- //Get Machine target information for calculating delay
- const TargetInstrInfo &MTI = Target.getInstrInfo();
-
- //Loop over instruction in BB and gather dependencies
- for(BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
-
- //Ignore instructions of the void type
- if(I->getType() != Type::VoidTy) {
-
- //Iterate over def-use chain and add true dependencies
- for (Value::use_const_iterator U = I->use_begin(), e = I->use_end(); U != e;
- ++U) {
- if (Instruction *Inst = dyn_cast<Instruction>(*U)) {
- //Check if a node already exists for this instruction
- ModuloSchedGraph::iterator Sink = find(Inst);
-
- //If the instruction is in our graph, add appropriate edges
- if(Sink->second != NULL) {
- //assert if self loop
- assert(&*I == Sink->first && "Use edge to itself!");
-
- //Create edge and set delay equal to node latency
- //FIXME: Is it safe to do this?
- ModuloSchedGraph::iterator Src = find(I);
- SchedGraphEdge *trueDep = new SchedGraphEdge(&*Src->second ,&*Sink->second,
- &*I, SchedGraphEdge::TrueDep,
- Src->second->getLatency());
- //Determine the iteration difference
- //FIXME: Will this ever happen?
- }
- }
- }
- }
-
- }
-
-
-}
-
-void ModuloSchedGraph::ASAP() {
-
-
-}
-
-void ModuloSchedGraph::ALAP() {
-
-
-}
-
-void ModuloSchedGraph::MOB() {
-
-}
-
-void ModuloSchedGraph::ComputeDepth() {
-
-}
-
-void ModuloSchedGraph::ComputeHeight() {
-
-}
-
-void ModuloSchedGraphSet::addGraph(ModuloSchedGraph *graph) {
- assert(graph!=NULL && "Graph for BasicBlock is null");
- Graphs.push_back(graph);
-}
-
-
-ModuloSchedGraphSet::ModuloSchedGraphSet(const Function *F,
- const TargetMachine &targ)
- : function(F) {
-
- //Create graph for each BB in this function
- for (Function::const_iterator BI = F->begin(); BI != F->end(); ++BI)
- addGraph(new ModuloSchedGraph(BI, targ));
-}
-
-ModuloSchedGraphSet::~ModuloSchedGraphSet(){
-
- //delete all the graphs
-}
-
-} // End llvm namespace
+++ /dev/null
-//===- ModuloSchedGraph.h - Modulo Scheduling Graph and Set -*- C++ -*-----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// TODO: Need a description here.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_MODULO_SCHED_GRAPH_H
-#define LLVM_MODULO_SCHED_GRAPH_H
-
-#include "llvm/Instruction.h"
-#include "llvm/CodeGen/SchedGraphCommon.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/BasicBlock.h"
-#include "llvm/Function.h"
-#include "Support/hash_map"
-#include <vector>
-
-namespace llvm {
-
-class ModuloSchedGraphNode : public SchedGraphNodeCommon {
-
- const Instruction *Inst; //Node's Instruction
- unsigned Earliest; //ASAP, or earliest time to be scheduled
- unsigned Latest; //ALAP, or latested time to be scheduled
- unsigned Depth; //Max Distance from node to the root
- unsigned Height; //Max Distance from node to leaf
- unsigned Mobility; //MOB, number of time slots it can be scheduled
- const TargetMachine &Target; //Target information.
-
-public:
- ModuloSchedGraphNode(unsigned ID, int index, const Instruction *inst,
- const TargetMachine &target);
-
- void print(std::ostream &os) const;
- const Instruction* getInst() { return Inst; }
- unsigned getEarliest() { return Earliest; }
- unsigned getLatest() { return Latest; }
- unsigned getDepth() { return Depth; }
- unsigned getHeight() { return Height; }
- unsigned getMobility() { return Mobility; }
-
- void setEarliest(unsigned early) { Earliest = early; }
- void setLatest(unsigned late) { Latest = late; }
- void setDepth(unsigned depth) { Depth = depth; }
- void setHeight(unsigned height) { Height = height; }
- void setMobility(unsigned mob) { Mobility = mob; }
-
-
-};
-
-class ModuloSchedGraph : public SchedGraphCommon {
-
- const BasicBlock *BB; //The Basic block this graph represents
- const TargetMachine &Target;
- hash_map<const Instruction*, ModuloSchedGraphNode*> GraphMap;
-
- void buildNodesForBB();
-
-public:
- typedef hash_map<const Instruction*,
- ModuloSchedGraphNode*>::iterator iterator;
- typedef hash_map<const Instruction*,
- ModuloSchedGraphNode*>::const_iterator const_iterator;
-
-
- ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &targ);
-
- const BasicBlock* getBB() { return BB; }
- void setBB(BasicBlock *bb) { BB = bb; }
- unsigned size() { return GraphMap.size(); }
- void addNode(const Instruction *I, ModuloSchedGraphNode *node);
- void ASAP(); //Calculate earliest schedule time for all nodes in graph.
- void ALAP(); //Calculate latest schedule time for all nodes in graph.
- void MOB(); //Calculate mobility for all nodes in the graph.
- void ComputeDepth(); //Compute depth of each node in graph
- void ComputeHeight(); //Computer height of each node in graph
- void addDepEdges(); //Add Dependencies
- iterator find(const Instruction *I) { return GraphMap.find(I); }
-};
-
-
-class ModuloSchedGraphSet {
-
- const Function *function; //Function this set of graphs represent.
- std::vector<ModuloSchedGraph*> Graphs;
-
-public:
- typedef std::vector<ModuloSchedGraph*>::iterator iterator;
- typedef std::vector<ModuloSchedGraph*>::const_iterator const_iterator;
-
- iterator begin() { return Graphs.begin(); }
- iterator end() { return Graphs.end(); }
-
- ModuloSchedGraphSet(const Function *func, const TargetMachine &target);
- ~ModuloSchedGraphSet();
-
- void addGraph(ModuloSchedGraph *graph);
- void dump() const;
-
-
-};
-
-} // End llvm namespace
-
-#endif
-//===-- ModuloScheduling.cpp - Software Pipeling Approach - SMS -----------===//
-//
+//===-- ModuloScheduling.cpp - ModuloScheduling ----------------*- C++ -*-===//
+//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
-// The is a software pipelining pass based on the Swing Modulo Scheduling
-// algorithm (SMS).
+//
//
//===----------------------------------------------------------------------===//
-#include "ModuloSchedGraph.h"
-#include "llvm/Function.h"
-#include "llvm/Pass.h"
+#define DEBUG_TYPE "ModuloSched"
-namespace llvm {
+#include "ModuloScheduling.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Target/TargetSchedInfo.h"
+#include "Support/Debug.h"
+#include "Support/GraphWriter.h"
+#include <vector>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+using namespace llvm;
+
+/// Create ModuloSchedulingPass
+///
+FunctionPass *llvm::createModuloSchedulingPass(TargetMachine & targ) {
+ DEBUG(std::cerr << "Created ModuloSchedulingPass\n");
+ return new ModuloSchedulingPass(targ);
+}
-namespace {
+template<typename GraphType>
+static void WriteGraphToFile(std::ostream &O, const std::string &GraphName,
+ const GraphType >) {
+ std::string Filename = GraphName + ".dot";
+ O << "Writing '" << Filename << "'...";
+ std::ofstream F(Filename.c_str());
- class ModuloScheduling : public FunctionPass {
+ if (F.good())
+ WriteGraph(F, GT);
+ else
+ O << " error opening file for writing!";
+ O << "\n";
+};
+
+namespace llvm {
+
+ template<>
+ struct DOTGraphTraits<MSchedGraph*> : public DefaultDOTGraphTraits {
+ static std::string getGraphName(MSchedGraph *F) {
+ return "Dependence Graph";
+ }
- public:
- virtual bool runOnFunction(Function &F);
- };
+ static std::string getNodeLabel(MSchedGraphNode *Node, MSchedGraph *Graph) {
+ if (Node->getInst()) {
+ std::stringstream ss;
+ ss << *(Node->getInst());
+ return ss.str(); //((MachineInstr*)Node->getInst());
+ }
+ else
+ return "No Inst";
+ }
+ static std::string getEdgeSourceLabel(MSchedGraphNode *Node,
+ MSchedGraphNode::succ_iterator I) {
+ //Label each edge with the type of dependence
+ std::string edgelabel = "";
+ switch (I.getEdge().getDepOrderType()) {
+
+ case MSchedGraphEdge::TrueDep:
+ edgelabel = "True";
+ break;
+
+ case MSchedGraphEdge::AntiDep:
+ edgelabel = "Anti";
+ break;
+
+ case MSchedGraphEdge::OutputDep:
+ edgelabel = "Output";
+ break;
+
+ default:
+ edgelabel = "Unknown";
+ break;
+ }
+ if(I.getEdge().getIteDiff() > 0)
+ edgelabel += I.getEdge().getIteDiff();
+
+ return edgelabel;
+ }
- RegisterOpt<ModuloScheduling> X("modulo-sched",
- "Modulo Scheduling/Software Pipelining");
-}
-/// Create Modulo Scheduling Pass
-///
-Pass *createModuloSchedPass() {
- return new ModuloScheduling();
+
+ };
}
/// ModuloScheduling::runOnFunction - main transformation entry point
-///
-bool ModuloScheduling::runOnFunction(Function &F) {
+bool ModuloSchedulingPass::runOnFunction(Function &F) {
bool Changed = false;
+
+ DEBUG(std::cerr << "Creating ModuloSchedGraph for each BasicBlock in" + F.getName() + "\n");
+
+ //Get MachineFunction
+ MachineFunction &MF = MachineFunction::get(&F);
+
+ //Iterate over BasicBlocks and do ModuloScheduling if they are valid
+ for (MachineFunction::const_iterator BI = MF.begin(); BI != MF.end(); ++BI) {
+ if(MachineBBisValid(BI)) {
+ MSchedGraph *MSG = new MSchedGraph(BI, target);
+
+ //Write Graph out to file
+ DEBUG(WriteGraphToFile(std::cerr, "dependgraph", MSG));
+
+ //Print out BB for debugging
+ DEBUG(BI->print(std::cerr));
+
+ //Calculate Resource II
+ int ResMII = calculateResMII(BI);
+
+ calculateNodeAttributes(MSG, ResMII);
+
+ }
+ }
+
+
return Changed;
}
-} // End llvm namespace
+
+bool ModuloSchedulingPass::MachineBBisValid(const MachineBasicBlock *BI) {
+
+ //Valid basic blocks must be loops and can not have if/else statements or calls.
+ bool isLoop = false;
+
+ //Check first if its a valid loop
+ for(succ_const_iterator I = succ_begin(BI->getBasicBlock()),
+ E = succ_end(BI->getBasicBlock()); I != E; ++I) {
+ if (*I == BI->getBasicBlock()) // has single block loop
+ isLoop = true;
+ }
+
+ if(!isLoop) {
+ DEBUG(std::cerr << "Basic Block is not a loop\n");
+ return false;
+ }
+ else
+ DEBUG(std::cerr << "Basic Block is a loop\n");
+
+ //Get Target machine instruction info
+ /*const TargetInstrInfo& TMI = targ.getInstrInfo();
+
+ //Check each instruction and look for calls or if/else statements
+ unsigned count = 0;
+ for(MachineBasicBlock::const_iterator I = BI->begin(), E = BI->end(); I != E; ++I) {
+ //Get opcode to check instruction type
+ MachineOpCode OC = I->getOpcode();
+ if(TMI.isControlFlow(OC) && (count+1 < BI->size()))
+ return false;
+ count++;
+ }*/
+ return true;
+
+}
+
+//ResMII is calculated by determining the usage count for each resource
+//and using the maximum.
+//FIXME: In future there should be a way to get alternative resources
+//for each instruction
+int ModuloSchedulingPass::calculateResMII(const MachineBasicBlock *BI) {
+
+ const TargetInstrInfo & mii = target.getInstrInfo();
+ const TargetSchedInfo & msi = target.getSchedInfo();
+
+ int ResMII = 0;
+
+ //Map to keep track of usage count of each resource
+ std::map<unsigned, unsigned> resourceUsageCount;
+
+ for(MachineBasicBlock::const_iterator I = BI->begin(), E = BI->end(); I != E; ++I) {
+
+ //Get resource usage for this instruction
+ InstrRUsage rUsage = msi.getInstrRUsage(I->getOpcode());
+ std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle;
+
+ //Loop over resources in each cycle and increments their usage count
+ for(unsigned i=0; i < resources.size(); ++i)
+ for(unsigned j=0; j < resources[i].size(); ++j) {
+ if( resourceUsageCount.find(resources[i][j]) == resourceUsageCount.end()) {
+ resourceUsageCount[resources[i][j]] = 1;
+ }
+ else {
+ resourceUsageCount[resources[i][j]] = resourceUsageCount[resources[i][j]] + 1;
+ }
+ }
+ }
+
+ //Find maximum usage count
+
+ //Get max number of instructions that can be issued at once.
+ int issueSlots = msi.maxNumIssueTotal;
+
+ for(std::map<unsigned,unsigned>::iterator RB = resourceUsageCount.begin(), RE = resourceUsageCount.end(); RB != RE; ++RB) {
+ //Get the total number of the resources in our cpu
+ //int resourceNum = msi.getCPUResourceNum(RB->first);
+
+ //Get total usage count for this resources
+ unsigned usageCount = RB->second;
+
+ //Divide the usage count by either the max number we can issue or the number of
+ //resources (whichever is its upper bound)
+ double finalUsageCount;
+ //if( resourceNum <= issueSlots)
+ //finalUsageCount = ceil(1.0 * usageCount / resourceNum);
+ //else
+ finalUsageCount = ceil(1.0 * usageCount / issueSlots);
+
+
+ DEBUG(std::cerr << "Resource ID: " << RB->first << " (usage=" << usageCount << ", resourceNum=X" << ", issueSlots=" << issueSlots << ", finalUsage=" << finalUsageCount << ")\n");
+
+ //Only keep track of the max
+ ResMII = std::max( (int) finalUsageCount, ResMII);
+
+ }
+
+ DEBUG(std::cerr << "Final Resource MII: " << ResMII << "\n");
+ return ResMII;
+
+}
+
+void ModuloSchedulingPass::calculateNodeAttributes(MSchedGraph *graph, int MII) {
+
+ //Loop over the nodes and add them to the map
+ for(MSchedGraph::iterator I = graph->begin(), E = graph->end(); I != E; ++I) {
+ //Assert if its already in the map
+ assert(nodeToAttributesMap.find(I->second) == nodeToAttributesMap.end() && "Node attributes are already in the map");
+
+ //Put into the map with default attribute values
+ nodeToAttributesMap[I->second] = MSNodeAttributes();
+ }
+
+ //Create set to deal with reccurrences
+ std::set<MSchedGraphNode*> visitedNodes;
+ std::vector<MSchedGraphNode*> vNodes;
+ //Now Loop over map and calculate the node attributes
+ for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(), E = nodeToAttributesMap.end(); I != E; ++I) {
+ // calculateASAP(I->first, (I->second), MII, visitedNodes);
+ findAllReccurrences(I->first, vNodes);
+ vNodes.clear();
+ visitedNodes.clear();
+ }
+
+ //Calculate ALAP which depends on ASAP being totally calculated
+ /*for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(), E = nodeToAttributesMap.end(); I != E; ++I) {
+ calculateALAP(I->first, (I->second), MII, MII, visitedNodes);
+ visitedNodes.clear();
+ }*/
+
+ //Calculate MOB which depends on ASAP being totally calculated, also do depth and height
+ /*for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(), E = nodeToAttributesMap.end(); I != E; ++I) {
+ (I->second).MOB = (I->second).ALAP - (I->second).ASAP;
+ DEBUG(std::cerr << "MOB: " << (I->second).MOB << " (" << *(I->first) << ")\n");
+ calculateDepth(I->first, (I->second), visitedNodes);
+ visitedNodes.clear();
+ calculateHeight(I->first, (I->second), visitedNodes);
+ visitedNodes.clear();
+ }*/
+
+
+}
+
+void ModuloSchedulingPass::calculateASAP(MSchedGraphNode *node, MSNodeAttributes &attributes,
+ int MII, std::set<MSchedGraphNode*> &visitedNodes) {
+
+ DEBUG(std::cerr << "Calculating ASAP for " << *node << "\n");
+
+ if(attributes.ASAP != -1 || (visitedNodes.find(node) != visitedNodes.end())) {
+ visitedNodes.erase(node);
+ return;
+ }
+ if(node->hasPredecessors()) {
+ int maxPredValue = 0;
+
+ //Iterate over all of the predecessors and fine max
+ for(MSchedGraphNode::pred_iterator P = node->pred_begin(), E = node->pred_end(); P != E; ++P) {
+
+ //Get that nodes ASAP
+ MSNodeAttributes predAttributes = nodeToAttributesMap.find(*P)->second;
+ if(predAttributes.ASAP == -1) {
+ //Put into set before you recurse
+ visitedNodes.insert(node);
+ calculateASAP(*P, predAttributes, MII, visitedNodes);
+ predAttributes = nodeToAttributesMap.find(*P)->second;
+ }
+ int iteDiff = node->getInEdge(*P).getIteDiff();
+
+ int currentPredValue = predAttributes.ASAP + node->getLatency() - iteDiff * MII;
+ DEBUG(std::cerr << "Current ASAP pred: " << currentPredValue << "\n");
+ maxPredValue = std::max(maxPredValue, currentPredValue);
+ }
+ visitedNodes.erase(node);
+ attributes.ASAP = maxPredValue;
+ }
+ else {
+ visitedNodes.erase(node);
+ attributes.ASAP = 0;
+ }
+
+ DEBUG(std::cerr << "ASAP: " << attributes.ASAP << " (" << *node << ")\n");
+}
+
+
+void ModuloSchedulingPass::calculateALAP(MSchedGraphNode *node, MSNodeAttributes &attributes,
+ int MII, int maxASAP,
+ std::set<MSchedGraphNode*> &visitedNodes) {
+
+ DEBUG(std::cerr << "Calculating AlAP for " << *node << "\n");
+
+ if(attributes.ALAP != -1|| (visitedNodes.find(node) != visitedNodes.end())) {
+ visitedNodes.erase(node);
+ return;
+ }
+ if(node->hasSuccessors()) {
+ int minSuccValue = 0;
+
+ //Iterate over all of the predecessors and fine max
+ for(MSchedGraphNode::succ_iterator P = node->succ_begin(),
+ E = node->succ_end(); P != E; ++P) {
+
+ MSNodeAttributes succAttributes = nodeToAttributesMap.find(*P)->second;
+ if(succAttributes.ASAP == -1) {
+
+ //Put into set before recursing
+ visitedNodes.insert(node);
+
+ calculateALAP(*P, succAttributes, MII, maxASAP, visitedNodes);
+ succAttributes = nodeToAttributesMap.find(*P)->second;
+ assert(succAttributes.ASAP == -1 && "Successors ALAP should have been caclulated");
+ }
+ int iteDiff = P.getEdge().getIteDiff();
+ int currentSuccValue = succAttributes.ALAP + node->getLatency() + iteDiff * MII;
+ minSuccValue = std::min(minSuccValue, currentSuccValue);
+ }
+ visitedNodes.erase(node);
+ attributes.ALAP = minSuccValue;
+ }
+ else {
+ visitedNodes.erase(node);
+ attributes.ALAP = maxASAP;
+ }
+ DEBUG(std::cerr << "ALAP: " << attributes.ALAP << " (" << *node << ")\n");
+}
+
+int ModuloSchedulingPass::findMaxASAP() {
+ int maxASAP = 0;
+
+ for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(),
+ E = nodeToAttributesMap.end(); I != E; ++I)
+ maxASAP = std::max(maxASAP, I->second.ASAP);
+ return maxASAP;
+}
+
+
+void ModuloSchedulingPass::calculateHeight(MSchedGraphNode *node,
+ MSNodeAttributes &attributes,
+ std::set<MSchedGraphNode*> &visitedNodes) {
+
+ if(attributes.depth != -1 || (visitedNodes.find(node) != visitedNodes.end())) {
+ //Remove from map before returning
+ visitedNodes.erase(node);
+ return;
+ }
+
+ if(node->hasSuccessors()) {
+ int maxHeight = 0;
+
+ //Iterate over all of the predecessors and fine max
+ for(MSchedGraphNode::succ_iterator P = node->succ_begin(),
+ E = node->succ_end(); P != E; ++P) {
+
+ MSNodeAttributes succAttributes = nodeToAttributesMap.find(*P)->second;
+ if(succAttributes.height == -1) {
+
+ //Put into map before recursing
+ visitedNodes.insert(node);
+
+ calculateHeight(*P, succAttributes, visitedNodes);
+ succAttributes = nodeToAttributesMap.find(*P)->second;
+ assert(succAttributes.height == -1 && "Successors Height should have been caclulated");
+ }
+ int currentHeight = succAttributes.height + node->getLatency();
+ maxHeight = std::max(maxHeight, currentHeight);
+ }
+ visitedNodes.erase(node);
+ attributes.height = maxHeight;
+ }
+ else {
+ visitedNodes.erase(node);
+ attributes.height = 0;
+ }
+
+ DEBUG(std::cerr << "Height: " << attributes.height << " (" << *node << ")\n");
+}
+
+
+void ModuloSchedulingPass::calculateDepth(MSchedGraphNode *node,
+ MSNodeAttributes &attributes,
+ std::set<MSchedGraphNode*> &visitedNodes) {
+
+ if(attributes.depth != -1 || (visitedNodes.find(node) != visitedNodes.end())) {
+ //Remove from map before returning
+ visitedNodes.erase(node);
+ return;
+ }
+
+ if(node->hasPredecessors()) {
+ int maxDepth = 0;
+
+ //Iterate over all of the predecessors and fine max
+ for(MSchedGraphNode::pred_iterator P = node->pred_begin(), E = node->pred_end(); P != E; ++P) {
+
+ //Get that nodes depth
+ MSNodeAttributes predAttributes = nodeToAttributesMap.find(*P)->second;
+ if(predAttributes.depth == -1) {
+
+ //Put into set before recursing
+ visitedNodes.insert(node);
+
+ calculateDepth(*P, predAttributes, visitedNodes);
+ predAttributes = nodeToAttributesMap.find(*P)->second;
+ assert(predAttributes.depth == -1 && "Predecessors ASAP should have been caclulated");
+ }
+ int currentDepth = predAttributes.depth + node->getLatency();
+ maxDepth = std::max(maxDepth, currentDepth);
+ }
+
+ //Remove from map before returning
+ visitedNodes.erase(node);
+
+ attributes.height = maxDepth;
+ }
+ else {
+ //Remove from map before returning
+ visitedNodes.erase(node);
+ attributes.depth = 0;
+ }
+
+ DEBUG(std::cerr << "Depth: " << attributes.depth << " (" << *node << "*)\n");
+
+}
+
+
+void ModuloSchedulingPass::findAllReccurrences(MSchedGraphNode *node,
+ std::vector<MSchedGraphNode*> &visitedNodes) {
+
+ if(find(visitedNodes.begin(), visitedNodes.end(), node) != visitedNodes.end()) {
+ //DUMP out recurrence
+ DEBUG(std::cerr << "Reccurrence:\n");
+ bool first = true;
+ for(std::vector<MSchedGraphNode*>::iterator I = visitedNodes.begin(), E = visitedNodes.end();
+ I !=E; ++I) {
+ if(*I == node)
+ first = false;
+ if(first)
+ continue;
+ DEBUG(std::cerr << **I << "\n");
+ }
+ DEBUG(std::cerr << "End Reccurrence:\n");
+ return;
+ }
+
+ for(MSchedGraphNode::succ_iterator I = node->succ_begin(), E = node->succ_end(); I != E; ++I) {
+ visitedNodes.push_back(node);
+ findAllReccurrences(*I, visitedNodes);
+ visitedNodes.pop_back();
+ }
+
+}
+
+
+
+
+
+
+
+
+
+void ModuloSchedulingPass::orderNodes() {
+
+ int BOTTOM_UP = 0;
+ int TOP_DOWN = 1;
+
+ //FIXME: Group nodes into sets and order all the sets based on RecMII
+ typedef std::vector<MSchedGraphNode*> NodeVector;
+ typedef std::pair<int, NodeVector> NodeSet;
+
+ std::vector<NodeSet> NodeSetsToOrder;
+
+ //Order the resulting sets
+ NodeVector FinalNodeOrder;
+
+ //Loop over all the sets and place them in the final node order
+ for(unsigned i=0; i < NodeSetsToOrder.size(); ++i) {
+
+ //Set default order
+ int order = BOTTOM_UP;
+
+ //Get Nodes in Current set
+ NodeVector CurrentSet = NodeSetsToOrder[i].second;
+
+ //Loop through the predecessors for each node in the final order
+ //and only keeps nodes both in the pred_set and currentset
+ NodeVector IntersectCurrent;
+
+ //Sort CurrentSet so we can use lowerbound
+ sort(CurrentSet.begin(), CurrentSet.end());
+
+ for(unsigned j=0; j < FinalNodeOrder.size(); ++j) {
+ for(MSchedGraphNode::pred_iterator P = FinalNodeOrder[j]->pred_begin(),
+ E = FinalNodeOrder[j]->pred_end(); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end())
+ IntersectCurrent.push_back(*P);
+ }
+ }
+
+ //If the intersection of predecessor and current set is not empty
+ //sort nodes bottom up
+ if(IntersectCurrent.size() != 0)
+ order = BOTTOM_UP;
+
+ //If empty, use successors
+ else {
+
+ for(unsigned j=0; j < FinalNodeOrder.size(); ++j) {
+ for(MSchedGraphNode::succ_iterator P = FinalNodeOrder[j]->succ_begin(),
+ E = FinalNodeOrder[j]->succ_end(); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end())
+ IntersectCurrent.push_back(*P);
+ }
+ }
+
+ //sort top-down
+ if(IntersectCurrent.size() != 0)
+ order = TOP_DOWN;
+
+ else {
+ //Find node with max ASAP in current Set
+ MSchedGraphNode *node;
+ int maxASAP = 0;
+ for(unsigned j=0; j < CurrentSet.size(); ++j) {
+ //Get node attributes
+ MSNodeAttributes nodeAttr= nodeToAttributesMap.find(CurrentSet[j])->second;
+ //assert(nodeAttr != nodeToAttributesMap.end() && "Node not in attributes map!");
+
+ if(maxASAP < nodeAttr.ASAP) {
+ maxASAP = nodeAttr.ASAP;
+ node = CurrentSet[j];
+ }
+ }
+ order = BOTTOM_UP;
+ }
+ }
+
+ //Repeat until all nodes are put into the final order from current set
+ /*while(IntersectCurrent.size() > 0) {
+
+ if(order == TOP_DOWN) {
+ while(IntersectCurrent.size() > 0) {
+
+ //FIXME
+ //Get node attributes
+ MSNodeAttributes nodeAttr= nodeToAttributesMap.find(IntersectCurrent[0])->second;
+ assert(nodeAttr != nodeToAttributesMap.end() && "Node not in attributes map!");
+
+ //Get node with highest height, if a tie, use one with lowest
+ //MOB
+ int MOB = nodeAttr.MBO;
+ int height = nodeAttr.height;
+ ModuloSchedGraphNode *V = IntersectCurrent[0];
+
+ for(unsigned j=0; j < IntersectCurrent.size(); ++j) {
+ int temp = IntersectCurrent[j]->getHeight();
+ if(height < temp) {
+ V = IntersectCurrent[j];
+ height = temp;
+ MOB = V->getMobility();
+ }
+ else if(height == temp) {
+ if(MOB > IntersectCurrent[j]->getMobility()) {
+ V = IntersectCurrent[j];
+ height = temp;
+ MOB = V->getMobility();
+ }
+ }
+ }
+
+ //Append V to the NodeOrder
+ NodeOrder.push_back(V);
+
+ //Remove V from IntersectOrder
+ IntersectCurrent.erase(find(IntersectCurrent.begin(),
+ IntersectCurrent.end(), V));
+
+ //Intersect V's successors with CurrentSet
+ for(mod_succ_iterator P = succ_begin(V),
+ E = succ_end(V); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end()) {
+ //If not already in Intersect, add
+ if(find(IntersectCurrent.begin(), IntersectCurrent.end(), *P) == IntersectCurrent.end())
+ IntersectCurrent.push_back(*P);
+ }
+ }
+ } //End while loop over Intersect Size
+
+ //Change direction
+ order = BOTTOM_UP;
+
+ //Reset Intersect to reflect changes in OrderNodes
+ IntersectCurrent.clear();
+ for(unsigned j=0; j < NodeOrder.size(); ++j) {
+ for(mod_pred_iterator P = pred_begin(NodeOrder[j]),
+ E = pred_end(NodeOrder[j]); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end())
+ IntersectCurrent.push_back(*P);
+ }
+ }
+ } //End If TOP_DOWN
+
+ //Begin if BOTTOM_UP
+ else {
+ while(IntersectCurrent.size() > 0) {
+ //Get node with highest depth, if a tie, use one with lowest
+ //MOB
+ int MOB = IntersectCurrent[0]->getMobility();
+ int depth = IntersectCurrent[0]->getDepth();
+ ModuloSchedGraphNode *V = IntersectCurrent[0];
+
+ for(unsigned j=0; j < IntersectCurrent.size(); ++j) {
+ int temp = IntersectCurrent[j]->getDepth();
+ if(depth < temp) {
+ V = IntersectCurrent[j];
+ depth = temp;
+ MOB = V->getMobility();
+ }
+ else if(depth == temp) {
+ if(MOB > IntersectCurrent[j]->getMobility()) {
+ V = IntersectCurrent[j];
+ depth = temp;
+ MOB = V->getMobility();
+ }
+ }
+ }
+
+ //Append V to the NodeOrder
+ NodeOrder.push_back(V);
+
+ //Remove V from IntersectOrder
+ IntersectCurrent.erase(find(IntersectCurrent.begin(),
+ IntersectCurrent.end(),V));
+
+ //Intersect V's pred with CurrentSet
+ for(mod_pred_iterator P = pred_begin(V),
+ E = pred_end(V); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end()) {
+ //If not already in Intersect, add
+ if(find(IntersectCurrent.begin(), IntersectCurrent.end(), *P) == IntersectCurrent.end())
+ IntersectCurrent.push_back(*P);
+ }
+ }
+ } //End while loop over Intersect Size
+
+ //Change order
+ order = TOP_DOWN;
+
+ //Reset IntersectCurrent to reflect changes in OrderNodes
+ IntersectCurrent.clear();
+ for(unsigned j=0; j < NodeOrder.size(); ++j) {
+ for(mod_succ_iterator P = succ_begin(NodeOrder[j]),
+ E = succ_end(NodeOrder[j]); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end())
+ IntersectCurrent.push_back(*P);
+ }
+
+ }
+ } //End if BOTTOM_DOWN
+
+ }*/
+//End Wrapping while loop
+
+ }//End for over all sets of nodes
+
+ //Return final Order
+ //return FinalNodeOrder;
+}
+++ /dev/null
-//===- ModuloSchedGraph.cpp - Modulo Scheduling Graph and Set -*- C++ -*---===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Description here
-//===----------------------------------------------------------------------===//
-
-#include "ModuloSchedGraph.h"
-#include "llvm/Type.h"
-
-namespace llvm {
-
-ModuloSchedGraphNode::ModuloSchedGraphNode(unsigned id, int index,
- const Instruction *inst,
- const TargetMachine &targ)
- : SchedGraphNodeCommon(id, index), Inst(inst), Target(targ) {
-}
-
-void ModuloSchedGraphNode::print(std::ostream &os) const {
- os << "Modulo Scheduling Node\n";
-}
-
-ModuloSchedGraph::ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &targ)
- : SchedGraphCommon(), BB(bb), Target(targ) {
-
- assert(BB != NULL && "Basic Block is null");
-
- //Builds nodes from each instruction in the basic block
- buildNodesForBB();
-
-}
-
-void ModuloSchedGraph::buildNodesForBB() {
- int count = 0;
- for (BasicBlock::const_iterator i = BB->begin(), e = BB->end(); i != e; ++i) {
- addNode(i,new ModuloSchedGraphNode(size(), count, i, Target));
- count++;
- }
-
- //Get machine instruction(s) for the llvm instruction
- //MachineCodeForInstruction &MC = MachineCodeForInstruction::get(Node->first);
-
-
-}
-
-void ModuloSchedGraph::addNode(const Instruction *I,
- ModuloSchedGraphNode *node) {
- assert(node!= NULL && "New ModuloSchedGraphNode is null");
- GraphMap[I] = node;
-}
-
-void ModuloSchedGraph::addDepEdges() {
-
- //Get Machine target information for calculating delay
- const TargetInstrInfo &MTI = Target.getInstrInfo();
-
- //Loop over instruction in BB and gather dependencies
- for(BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
-
- //Ignore instructions of the void type
- if(I->getType() != Type::VoidTy) {
-
- //Iterate over def-use chain and add true dependencies
- for (Value::use_const_iterator U = I->use_begin(), e = I->use_end(); U != e;
- ++U) {
- if (Instruction *Inst = dyn_cast<Instruction>(*U)) {
- //Check if a node already exists for this instruction
- ModuloSchedGraph::iterator Sink = find(Inst);
-
- //If the instruction is in our graph, add appropriate edges
- if(Sink->second != NULL) {
- //assert if self loop
- assert(&*I == Sink->first && "Use edge to itself!");
-
- //Create edge and set delay equal to node latency
- //FIXME: Is it safe to do this?
- ModuloSchedGraph::iterator Src = find(I);
- SchedGraphEdge *trueDep = new SchedGraphEdge(&*Src->second ,&*Sink->second,
- &*I, SchedGraphEdge::TrueDep,
- Src->second->getLatency());
- //Determine the iteration difference
- //FIXME: Will this ever happen?
- }
- }
- }
- }
-
- }
-
-
-}
-
-void ModuloSchedGraph::ASAP() {
-
-
-}
-
-void ModuloSchedGraph::ALAP() {
-
-
-}
-
-void ModuloSchedGraph::MOB() {
-
-}
-
-void ModuloSchedGraph::ComputeDepth() {
-
-}
-
-void ModuloSchedGraph::ComputeHeight() {
-
-}
-
-void ModuloSchedGraphSet::addGraph(ModuloSchedGraph *graph) {
- assert(graph!=NULL && "Graph for BasicBlock is null");
- Graphs.push_back(graph);
-}
-
-
-ModuloSchedGraphSet::ModuloSchedGraphSet(const Function *F,
- const TargetMachine &targ)
- : function(F) {
-
- //Create graph for each BB in this function
- for (Function::const_iterator BI = F->begin(); BI != F->end(); ++BI)
- addGraph(new ModuloSchedGraph(BI, targ));
-}
-
-ModuloSchedGraphSet::~ModuloSchedGraphSet(){
-
- //delete all the graphs
-}
-
-} // End llvm namespace
+++ /dev/null
-//===- ModuloSchedGraph.h - Modulo Scheduling Graph and Set -*- C++ -*-----===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// TODO: Need a description here.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_MODULO_SCHED_GRAPH_H
-#define LLVM_MODULO_SCHED_GRAPH_H
-
-#include "llvm/Instruction.h"
-#include "llvm/CodeGen/SchedGraphCommon.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/BasicBlock.h"
-#include "llvm/Function.h"
-#include "Support/hash_map"
-#include <vector>
-
-namespace llvm {
-
-class ModuloSchedGraphNode : public SchedGraphNodeCommon {
-
- const Instruction *Inst; //Node's Instruction
- unsigned Earliest; //ASAP, or earliest time to be scheduled
- unsigned Latest; //ALAP, or latested time to be scheduled
- unsigned Depth; //Max Distance from node to the root
- unsigned Height; //Max Distance from node to leaf
- unsigned Mobility; //MOB, number of time slots it can be scheduled
- const TargetMachine &Target; //Target information.
-
-public:
- ModuloSchedGraphNode(unsigned ID, int index, const Instruction *inst,
- const TargetMachine &target);
-
- void print(std::ostream &os) const;
- const Instruction* getInst() { return Inst; }
- unsigned getEarliest() { return Earliest; }
- unsigned getLatest() { return Latest; }
- unsigned getDepth() { return Depth; }
- unsigned getHeight() { return Height; }
- unsigned getMobility() { return Mobility; }
-
- void setEarliest(unsigned early) { Earliest = early; }
- void setLatest(unsigned late) { Latest = late; }
- void setDepth(unsigned depth) { Depth = depth; }
- void setHeight(unsigned height) { Height = height; }
- void setMobility(unsigned mob) { Mobility = mob; }
-
-
-};
-
-class ModuloSchedGraph : public SchedGraphCommon {
-
- const BasicBlock *BB; //The Basic block this graph represents
- const TargetMachine &Target;
- hash_map<const Instruction*, ModuloSchedGraphNode*> GraphMap;
-
- void buildNodesForBB();
-
-public:
- typedef hash_map<const Instruction*,
- ModuloSchedGraphNode*>::iterator iterator;
- typedef hash_map<const Instruction*,
- ModuloSchedGraphNode*>::const_iterator const_iterator;
-
-
- ModuloSchedGraph(const BasicBlock *bb, const TargetMachine &targ);
-
- const BasicBlock* getBB() { return BB; }
- void setBB(BasicBlock *bb) { BB = bb; }
- unsigned size() { return GraphMap.size(); }
- void addNode(const Instruction *I, ModuloSchedGraphNode *node);
- void ASAP(); //Calculate earliest schedule time for all nodes in graph.
- void ALAP(); //Calculate latest schedule time for all nodes in graph.
- void MOB(); //Calculate mobility for all nodes in the graph.
- void ComputeDepth(); //Compute depth of each node in graph
- void ComputeHeight(); //Computer height of each node in graph
- void addDepEdges(); //Add Dependencies
- iterator find(const Instruction *I) { return GraphMap.find(I); }
-};
-
-
-class ModuloSchedGraphSet {
-
- const Function *function; //Function this set of graphs represent.
- std::vector<ModuloSchedGraph*> Graphs;
-
-public:
- typedef std::vector<ModuloSchedGraph*>::iterator iterator;
- typedef std::vector<ModuloSchedGraph*>::const_iterator const_iterator;
-
- iterator begin() { return Graphs.begin(); }
- iterator end() { return Graphs.end(); }
-
- ModuloSchedGraphSet(const Function *func, const TargetMachine &target);
- ~ModuloSchedGraphSet();
-
- void addGraph(ModuloSchedGraph *graph);
- void dump() const;
-
-
-};
-
-} // End llvm namespace
-
-#endif
-//===-- ModuloScheduling.cpp - Software Pipeling Approach - SMS -----------===//
-//
+//===-- ModuloScheduling.cpp - ModuloScheduling ----------------*- C++ -*-===//
+//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
-// The is a software pipelining pass based on the Swing Modulo Scheduling
-// algorithm (SMS).
+//
//
//===----------------------------------------------------------------------===//
-#include "ModuloSchedGraph.h"
-#include "llvm/Function.h"
-#include "llvm/Pass.h"
+#define DEBUG_TYPE "ModuloSched"
-namespace llvm {
+#include "ModuloScheduling.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Support/CFG.h"
+#include "llvm/Target/TargetSchedInfo.h"
+#include "Support/Debug.h"
+#include "Support/GraphWriter.h"
+#include <vector>
+#include <utility>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+
+using namespace llvm;
+
+/// Create ModuloSchedulingPass
+///
+FunctionPass *llvm::createModuloSchedulingPass(TargetMachine & targ) {
+ DEBUG(std::cerr << "Created ModuloSchedulingPass\n");
+ return new ModuloSchedulingPass(targ);
+}
-namespace {
+template<typename GraphType>
+static void WriteGraphToFile(std::ostream &O, const std::string &GraphName,
+ const GraphType >) {
+ std::string Filename = GraphName + ".dot";
+ O << "Writing '" << Filename << "'...";
+ std::ofstream F(Filename.c_str());
- class ModuloScheduling : public FunctionPass {
+ if (F.good())
+ WriteGraph(F, GT);
+ else
+ O << " error opening file for writing!";
+ O << "\n";
+};
+
+namespace llvm {
+
+ template<>
+ struct DOTGraphTraits<MSchedGraph*> : public DefaultDOTGraphTraits {
+ static std::string getGraphName(MSchedGraph *F) {
+ return "Dependence Graph";
+ }
- public:
- virtual bool runOnFunction(Function &F);
- };
+ static std::string getNodeLabel(MSchedGraphNode *Node, MSchedGraph *Graph) {
+ if (Node->getInst()) {
+ std::stringstream ss;
+ ss << *(Node->getInst());
+ return ss.str(); //((MachineInstr*)Node->getInst());
+ }
+ else
+ return "No Inst";
+ }
+ static std::string getEdgeSourceLabel(MSchedGraphNode *Node,
+ MSchedGraphNode::succ_iterator I) {
+ //Label each edge with the type of dependence
+ std::string edgelabel = "";
+ switch (I.getEdge().getDepOrderType()) {
+
+ case MSchedGraphEdge::TrueDep:
+ edgelabel = "True";
+ break;
+
+ case MSchedGraphEdge::AntiDep:
+ edgelabel = "Anti";
+ break;
+
+ case MSchedGraphEdge::OutputDep:
+ edgelabel = "Output";
+ break;
+
+ default:
+ edgelabel = "Unknown";
+ break;
+ }
+ if(I.getEdge().getIteDiff() > 0)
+ edgelabel += I.getEdge().getIteDiff();
+
+ return edgelabel;
+ }
- RegisterOpt<ModuloScheduling> X("modulo-sched",
- "Modulo Scheduling/Software Pipelining");
-}
-/// Create Modulo Scheduling Pass
-///
-Pass *createModuloSchedPass() {
- return new ModuloScheduling();
+
+ };
}
/// ModuloScheduling::runOnFunction - main transformation entry point
-///
-bool ModuloScheduling::runOnFunction(Function &F) {
+bool ModuloSchedulingPass::runOnFunction(Function &F) {
bool Changed = false;
+
+ DEBUG(std::cerr << "Creating ModuloSchedGraph for each BasicBlock in" + F.getName() + "\n");
+
+ //Get MachineFunction
+ MachineFunction &MF = MachineFunction::get(&F);
+
+ //Iterate over BasicBlocks and do ModuloScheduling if they are valid
+ for (MachineFunction::const_iterator BI = MF.begin(); BI != MF.end(); ++BI) {
+ if(MachineBBisValid(BI)) {
+ MSchedGraph *MSG = new MSchedGraph(BI, target);
+
+ //Write Graph out to file
+ DEBUG(WriteGraphToFile(std::cerr, "dependgraph", MSG));
+
+ //Print out BB for debugging
+ DEBUG(BI->print(std::cerr));
+
+ //Calculate Resource II
+ int ResMII = calculateResMII(BI);
+
+ calculateNodeAttributes(MSG, ResMII);
+
+ }
+ }
+
+
return Changed;
}
-} // End llvm namespace
+
+bool ModuloSchedulingPass::MachineBBisValid(const MachineBasicBlock *BI) {
+
+ //Valid basic blocks must be loops and can not have if/else statements or calls.
+ bool isLoop = false;
+
+ //Check first if its a valid loop
+ for(succ_const_iterator I = succ_begin(BI->getBasicBlock()),
+ E = succ_end(BI->getBasicBlock()); I != E; ++I) {
+ if (*I == BI->getBasicBlock()) // has single block loop
+ isLoop = true;
+ }
+
+ if(!isLoop) {
+ DEBUG(std::cerr << "Basic Block is not a loop\n");
+ return false;
+ }
+ else
+ DEBUG(std::cerr << "Basic Block is a loop\n");
+
+ //Get Target machine instruction info
+ /*const TargetInstrInfo& TMI = targ.getInstrInfo();
+
+ //Check each instruction and look for calls or if/else statements
+ unsigned count = 0;
+ for(MachineBasicBlock::const_iterator I = BI->begin(), E = BI->end(); I != E; ++I) {
+ //Get opcode to check instruction type
+ MachineOpCode OC = I->getOpcode();
+ if(TMI.isControlFlow(OC) && (count+1 < BI->size()))
+ return false;
+ count++;
+ }*/
+ return true;
+
+}
+
+//ResMII is calculated by determining the usage count for each resource
+//and using the maximum.
+//FIXME: In future there should be a way to get alternative resources
+//for each instruction
+int ModuloSchedulingPass::calculateResMII(const MachineBasicBlock *BI) {
+
+ const TargetInstrInfo & mii = target.getInstrInfo();
+ const TargetSchedInfo & msi = target.getSchedInfo();
+
+ int ResMII = 0;
+
+ //Map to keep track of usage count of each resource
+ std::map<unsigned, unsigned> resourceUsageCount;
+
+ for(MachineBasicBlock::const_iterator I = BI->begin(), E = BI->end(); I != E; ++I) {
+
+ //Get resource usage for this instruction
+ InstrRUsage rUsage = msi.getInstrRUsage(I->getOpcode());
+ std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle;
+
+ //Loop over resources in each cycle and increments their usage count
+ for(unsigned i=0; i < resources.size(); ++i)
+ for(unsigned j=0; j < resources[i].size(); ++j) {
+ if( resourceUsageCount.find(resources[i][j]) == resourceUsageCount.end()) {
+ resourceUsageCount[resources[i][j]] = 1;
+ }
+ else {
+ resourceUsageCount[resources[i][j]] = resourceUsageCount[resources[i][j]] + 1;
+ }
+ }
+ }
+
+ //Find maximum usage count
+
+ //Get max number of instructions that can be issued at once.
+ int issueSlots = msi.maxNumIssueTotal;
+
+ for(std::map<unsigned,unsigned>::iterator RB = resourceUsageCount.begin(), RE = resourceUsageCount.end(); RB != RE; ++RB) {
+ //Get the total number of the resources in our cpu
+ //int resourceNum = msi.getCPUResourceNum(RB->first);
+
+ //Get total usage count for this resources
+ unsigned usageCount = RB->second;
+
+ //Divide the usage count by either the max number we can issue or the number of
+ //resources (whichever is its upper bound)
+ double finalUsageCount;
+ //if( resourceNum <= issueSlots)
+ //finalUsageCount = ceil(1.0 * usageCount / resourceNum);
+ //else
+ finalUsageCount = ceil(1.0 * usageCount / issueSlots);
+
+
+ DEBUG(std::cerr << "Resource ID: " << RB->first << " (usage=" << usageCount << ", resourceNum=X" << ", issueSlots=" << issueSlots << ", finalUsage=" << finalUsageCount << ")\n");
+
+ //Only keep track of the max
+ ResMII = std::max( (int) finalUsageCount, ResMII);
+
+ }
+
+ DEBUG(std::cerr << "Final Resource MII: " << ResMII << "\n");
+ return ResMII;
+
+}
+
+void ModuloSchedulingPass::calculateNodeAttributes(MSchedGraph *graph, int MII) {
+
+ //Loop over the nodes and add them to the map
+ for(MSchedGraph::iterator I = graph->begin(), E = graph->end(); I != E; ++I) {
+ //Assert if its already in the map
+ assert(nodeToAttributesMap.find(I->second) == nodeToAttributesMap.end() && "Node attributes are already in the map");
+
+ //Put into the map with default attribute values
+ nodeToAttributesMap[I->second] = MSNodeAttributes();
+ }
+
+ //Create set to deal with reccurrences
+ std::set<MSchedGraphNode*> visitedNodes;
+ std::vector<MSchedGraphNode*> vNodes;
+ //Now Loop over map and calculate the node attributes
+ for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(), E = nodeToAttributesMap.end(); I != E; ++I) {
+ // calculateASAP(I->first, (I->second), MII, visitedNodes);
+ findAllReccurrences(I->first, vNodes);
+ vNodes.clear();
+ visitedNodes.clear();
+ }
+
+ //Calculate ALAP which depends on ASAP being totally calculated
+ /*for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(), E = nodeToAttributesMap.end(); I != E; ++I) {
+ calculateALAP(I->first, (I->second), MII, MII, visitedNodes);
+ visitedNodes.clear();
+ }*/
+
+ //Calculate MOB which depends on ASAP being totally calculated, also do depth and height
+ /*for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(), E = nodeToAttributesMap.end(); I != E; ++I) {
+ (I->second).MOB = (I->second).ALAP - (I->second).ASAP;
+ DEBUG(std::cerr << "MOB: " << (I->second).MOB << " (" << *(I->first) << ")\n");
+ calculateDepth(I->first, (I->second), visitedNodes);
+ visitedNodes.clear();
+ calculateHeight(I->first, (I->second), visitedNodes);
+ visitedNodes.clear();
+ }*/
+
+
+}
+
+void ModuloSchedulingPass::calculateASAP(MSchedGraphNode *node, MSNodeAttributes &attributes,
+ int MII, std::set<MSchedGraphNode*> &visitedNodes) {
+
+ DEBUG(std::cerr << "Calculating ASAP for " << *node << "\n");
+
+ if(attributes.ASAP != -1 || (visitedNodes.find(node) != visitedNodes.end())) {
+ visitedNodes.erase(node);
+ return;
+ }
+ if(node->hasPredecessors()) {
+ int maxPredValue = 0;
+
+ //Iterate over all of the predecessors and fine max
+ for(MSchedGraphNode::pred_iterator P = node->pred_begin(), E = node->pred_end(); P != E; ++P) {
+
+ //Get that nodes ASAP
+ MSNodeAttributes predAttributes = nodeToAttributesMap.find(*P)->second;
+ if(predAttributes.ASAP == -1) {
+ //Put into set before you recurse
+ visitedNodes.insert(node);
+ calculateASAP(*P, predAttributes, MII, visitedNodes);
+ predAttributes = nodeToAttributesMap.find(*P)->second;
+ }
+ int iteDiff = node->getInEdge(*P).getIteDiff();
+
+ int currentPredValue = predAttributes.ASAP + node->getLatency() - iteDiff * MII;
+ DEBUG(std::cerr << "Current ASAP pred: " << currentPredValue << "\n");
+ maxPredValue = std::max(maxPredValue, currentPredValue);
+ }
+ visitedNodes.erase(node);
+ attributes.ASAP = maxPredValue;
+ }
+ else {
+ visitedNodes.erase(node);
+ attributes.ASAP = 0;
+ }
+
+ DEBUG(std::cerr << "ASAP: " << attributes.ASAP << " (" << *node << ")\n");
+}
+
+
+void ModuloSchedulingPass::calculateALAP(MSchedGraphNode *node, MSNodeAttributes &attributes,
+ int MII, int maxASAP,
+ std::set<MSchedGraphNode*> &visitedNodes) {
+
+ DEBUG(std::cerr << "Calculating AlAP for " << *node << "\n");
+
+ if(attributes.ALAP != -1|| (visitedNodes.find(node) != visitedNodes.end())) {
+ visitedNodes.erase(node);
+ return;
+ }
+ if(node->hasSuccessors()) {
+ int minSuccValue = 0;
+
+ //Iterate over all of the predecessors and fine max
+ for(MSchedGraphNode::succ_iterator P = node->succ_begin(),
+ E = node->succ_end(); P != E; ++P) {
+
+ MSNodeAttributes succAttributes = nodeToAttributesMap.find(*P)->second;
+ if(succAttributes.ASAP == -1) {
+
+ //Put into set before recursing
+ visitedNodes.insert(node);
+
+ calculateALAP(*P, succAttributes, MII, maxASAP, visitedNodes);
+ succAttributes = nodeToAttributesMap.find(*P)->second;
+ assert(succAttributes.ASAP == -1 && "Successors ALAP should have been caclulated");
+ }
+ int iteDiff = P.getEdge().getIteDiff();
+ int currentSuccValue = succAttributes.ALAP + node->getLatency() + iteDiff * MII;
+ minSuccValue = std::min(minSuccValue, currentSuccValue);
+ }
+ visitedNodes.erase(node);
+ attributes.ALAP = minSuccValue;
+ }
+ else {
+ visitedNodes.erase(node);
+ attributes.ALAP = maxASAP;
+ }
+ DEBUG(std::cerr << "ALAP: " << attributes.ALAP << " (" << *node << ")\n");
+}
+
+int ModuloSchedulingPass::findMaxASAP() {
+ int maxASAP = 0;
+
+ for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(),
+ E = nodeToAttributesMap.end(); I != E; ++I)
+ maxASAP = std::max(maxASAP, I->second.ASAP);
+ return maxASAP;
+}
+
+
+void ModuloSchedulingPass::calculateHeight(MSchedGraphNode *node,
+ MSNodeAttributes &attributes,
+ std::set<MSchedGraphNode*> &visitedNodes) {
+
+ if(attributes.depth != -1 || (visitedNodes.find(node) != visitedNodes.end())) {
+ //Remove from map before returning
+ visitedNodes.erase(node);
+ return;
+ }
+
+ if(node->hasSuccessors()) {
+ int maxHeight = 0;
+
+ //Iterate over all of the predecessors and fine max
+ for(MSchedGraphNode::succ_iterator P = node->succ_begin(),
+ E = node->succ_end(); P != E; ++P) {
+
+ MSNodeAttributes succAttributes = nodeToAttributesMap.find(*P)->second;
+ if(succAttributes.height == -1) {
+
+ //Put into map before recursing
+ visitedNodes.insert(node);
+
+ calculateHeight(*P, succAttributes, visitedNodes);
+ succAttributes = nodeToAttributesMap.find(*P)->second;
+ assert(succAttributes.height == -1 && "Successors Height should have been caclulated");
+ }
+ int currentHeight = succAttributes.height + node->getLatency();
+ maxHeight = std::max(maxHeight, currentHeight);
+ }
+ visitedNodes.erase(node);
+ attributes.height = maxHeight;
+ }
+ else {
+ visitedNodes.erase(node);
+ attributes.height = 0;
+ }
+
+ DEBUG(std::cerr << "Height: " << attributes.height << " (" << *node << ")\n");
+}
+
+
+void ModuloSchedulingPass::calculateDepth(MSchedGraphNode *node,
+ MSNodeAttributes &attributes,
+ std::set<MSchedGraphNode*> &visitedNodes) {
+
+ if(attributes.depth != -1 || (visitedNodes.find(node) != visitedNodes.end())) {
+ //Remove from map before returning
+ visitedNodes.erase(node);
+ return;
+ }
+
+ if(node->hasPredecessors()) {
+ int maxDepth = 0;
+
+ //Iterate over all of the predecessors and fine max
+ for(MSchedGraphNode::pred_iterator P = node->pred_begin(), E = node->pred_end(); P != E; ++P) {
+
+ //Get that nodes depth
+ MSNodeAttributes predAttributes = nodeToAttributesMap.find(*P)->second;
+ if(predAttributes.depth == -1) {
+
+ //Put into set before recursing
+ visitedNodes.insert(node);
+
+ calculateDepth(*P, predAttributes, visitedNodes);
+ predAttributes = nodeToAttributesMap.find(*P)->second;
+ assert(predAttributes.depth == -1 && "Predecessors ASAP should have been caclulated");
+ }
+ int currentDepth = predAttributes.depth + node->getLatency();
+ maxDepth = std::max(maxDepth, currentDepth);
+ }
+
+ //Remove from map before returning
+ visitedNodes.erase(node);
+
+ attributes.height = maxDepth;
+ }
+ else {
+ //Remove from map before returning
+ visitedNodes.erase(node);
+ attributes.depth = 0;
+ }
+
+ DEBUG(std::cerr << "Depth: " << attributes.depth << " (" << *node << "*)\n");
+
+}
+
+
+void ModuloSchedulingPass::findAllReccurrences(MSchedGraphNode *node,
+ std::vector<MSchedGraphNode*> &visitedNodes) {
+
+ if(find(visitedNodes.begin(), visitedNodes.end(), node) != visitedNodes.end()) {
+ //DUMP out recurrence
+ DEBUG(std::cerr << "Reccurrence:\n");
+ bool first = true;
+ for(std::vector<MSchedGraphNode*>::iterator I = visitedNodes.begin(), E = visitedNodes.end();
+ I !=E; ++I) {
+ if(*I == node)
+ first = false;
+ if(first)
+ continue;
+ DEBUG(std::cerr << **I << "\n");
+ }
+ DEBUG(std::cerr << "End Reccurrence:\n");
+ return;
+ }
+
+ for(MSchedGraphNode::succ_iterator I = node->succ_begin(), E = node->succ_end(); I != E; ++I) {
+ visitedNodes.push_back(node);
+ findAllReccurrences(*I, visitedNodes);
+ visitedNodes.pop_back();
+ }
+
+}
+
+
+
+
+
+
+
+
+
+void ModuloSchedulingPass::orderNodes() {
+
+ int BOTTOM_UP = 0;
+ int TOP_DOWN = 1;
+
+ //FIXME: Group nodes into sets and order all the sets based on RecMII
+ typedef std::vector<MSchedGraphNode*> NodeVector;
+ typedef std::pair<int, NodeVector> NodeSet;
+
+ std::vector<NodeSet> NodeSetsToOrder;
+
+ //Order the resulting sets
+ NodeVector FinalNodeOrder;
+
+ //Loop over all the sets and place them in the final node order
+ for(unsigned i=0; i < NodeSetsToOrder.size(); ++i) {
+
+ //Set default order
+ int order = BOTTOM_UP;
+
+ //Get Nodes in Current set
+ NodeVector CurrentSet = NodeSetsToOrder[i].second;
+
+ //Loop through the predecessors for each node in the final order
+ //and only keeps nodes both in the pred_set and currentset
+ NodeVector IntersectCurrent;
+
+ //Sort CurrentSet so we can use lowerbound
+ sort(CurrentSet.begin(), CurrentSet.end());
+
+ for(unsigned j=0; j < FinalNodeOrder.size(); ++j) {
+ for(MSchedGraphNode::pred_iterator P = FinalNodeOrder[j]->pred_begin(),
+ E = FinalNodeOrder[j]->pred_end(); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end())
+ IntersectCurrent.push_back(*P);
+ }
+ }
+
+ //If the intersection of predecessor and current set is not empty
+ //sort nodes bottom up
+ if(IntersectCurrent.size() != 0)
+ order = BOTTOM_UP;
+
+ //If empty, use successors
+ else {
+
+ for(unsigned j=0; j < FinalNodeOrder.size(); ++j) {
+ for(MSchedGraphNode::succ_iterator P = FinalNodeOrder[j]->succ_begin(),
+ E = FinalNodeOrder[j]->succ_end(); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end())
+ IntersectCurrent.push_back(*P);
+ }
+ }
+
+ //sort top-down
+ if(IntersectCurrent.size() != 0)
+ order = TOP_DOWN;
+
+ else {
+ //Find node with max ASAP in current Set
+ MSchedGraphNode *node;
+ int maxASAP = 0;
+ for(unsigned j=0; j < CurrentSet.size(); ++j) {
+ //Get node attributes
+ MSNodeAttributes nodeAttr= nodeToAttributesMap.find(CurrentSet[j])->second;
+ //assert(nodeAttr != nodeToAttributesMap.end() && "Node not in attributes map!");
+
+ if(maxASAP < nodeAttr.ASAP) {
+ maxASAP = nodeAttr.ASAP;
+ node = CurrentSet[j];
+ }
+ }
+ order = BOTTOM_UP;
+ }
+ }
+
+ //Repeat until all nodes are put into the final order from current set
+ /*while(IntersectCurrent.size() > 0) {
+
+ if(order == TOP_DOWN) {
+ while(IntersectCurrent.size() > 0) {
+
+ //FIXME
+ //Get node attributes
+ MSNodeAttributes nodeAttr= nodeToAttributesMap.find(IntersectCurrent[0])->second;
+ assert(nodeAttr != nodeToAttributesMap.end() && "Node not in attributes map!");
+
+ //Get node with highest height, if a tie, use one with lowest
+ //MOB
+ int MOB = nodeAttr.MBO;
+ int height = nodeAttr.height;
+ ModuloSchedGraphNode *V = IntersectCurrent[0];
+
+ for(unsigned j=0; j < IntersectCurrent.size(); ++j) {
+ int temp = IntersectCurrent[j]->getHeight();
+ if(height < temp) {
+ V = IntersectCurrent[j];
+ height = temp;
+ MOB = V->getMobility();
+ }
+ else if(height == temp) {
+ if(MOB > IntersectCurrent[j]->getMobility()) {
+ V = IntersectCurrent[j];
+ height = temp;
+ MOB = V->getMobility();
+ }
+ }
+ }
+
+ //Append V to the NodeOrder
+ NodeOrder.push_back(V);
+
+ //Remove V from IntersectOrder
+ IntersectCurrent.erase(find(IntersectCurrent.begin(),
+ IntersectCurrent.end(), V));
+
+ //Intersect V's successors with CurrentSet
+ for(mod_succ_iterator P = succ_begin(V),
+ E = succ_end(V); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end()) {
+ //If not already in Intersect, add
+ if(find(IntersectCurrent.begin(), IntersectCurrent.end(), *P) == IntersectCurrent.end())
+ IntersectCurrent.push_back(*P);
+ }
+ }
+ } //End while loop over Intersect Size
+
+ //Change direction
+ order = BOTTOM_UP;
+
+ //Reset Intersect to reflect changes in OrderNodes
+ IntersectCurrent.clear();
+ for(unsigned j=0; j < NodeOrder.size(); ++j) {
+ for(mod_pred_iterator P = pred_begin(NodeOrder[j]),
+ E = pred_end(NodeOrder[j]); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end())
+ IntersectCurrent.push_back(*P);
+ }
+ }
+ } //End If TOP_DOWN
+
+ //Begin if BOTTOM_UP
+ else {
+ while(IntersectCurrent.size() > 0) {
+ //Get node with highest depth, if a tie, use one with lowest
+ //MOB
+ int MOB = IntersectCurrent[0]->getMobility();
+ int depth = IntersectCurrent[0]->getDepth();
+ ModuloSchedGraphNode *V = IntersectCurrent[0];
+
+ for(unsigned j=0; j < IntersectCurrent.size(); ++j) {
+ int temp = IntersectCurrent[j]->getDepth();
+ if(depth < temp) {
+ V = IntersectCurrent[j];
+ depth = temp;
+ MOB = V->getMobility();
+ }
+ else if(depth == temp) {
+ if(MOB > IntersectCurrent[j]->getMobility()) {
+ V = IntersectCurrent[j];
+ depth = temp;
+ MOB = V->getMobility();
+ }
+ }
+ }
+
+ //Append V to the NodeOrder
+ NodeOrder.push_back(V);
+
+ //Remove V from IntersectOrder
+ IntersectCurrent.erase(find(IntersectCurrent.begin(),
+ IntersectCurrent.end(),V));
+
+ //Intersect V's pred with CurrentSet
+ for(mod_pred_iterator P = pred_begin(V),
+ E = pred_end(V); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end()) {
+ //If not already in Intersect, add
+ if(find(IntersectCurrent.begin(), IntersectCurrent.end(), *P) == IntersectCurrent.end())
+ IntersectCurrent.push_back(*P);
+ }
+ }
+ } //End while loop over Intersect Size
+
+ //Change order
+ order = TOP_DOWN;
+
+ //Reset IntersectCurrent to reflect changes in OrderNodes
+ IntersectCurrent.clear();
+ for(unsigned j=0; j < NodeOrder.size(); ++j) {
+ for(mod_succ_iterator P = succ_begin(NodeOrder[j]),
+ E = succ_end(NodeOrder[j]); P != E; ++P) {
+ if(lower_bound(CurrentSet.begin(),
+ CurrentSet.end(), *P) != CurrentSet.end())
+ IntersectCurrent.push_back(*P);
+ }
+
+ }
+ } //End if BOTTOM_DOWN
+
+ }*/
+//End Wrapping while loop
+
+ }//End for over all sets of nodes
+
+ //Return final Order
+ //return FinalNodeOrder;
+}