[llvm-commits] [parallel] CVS: llvm/lib/CodeGen/ModuloScheduling/MSchedGraph.cpp MSchedGraph.h ModuloScheduling.h ModuloScheduling.cpp ModuloSchedGraph.cpp ModuloSchedGraph.h

Misha Brukman brukman at cs.uiuc.edu
Mon Mar 1 18:04:33 PST 2004


Changes in directory llvm/lib/CodeGen/ModuloScheduling:

MSchedGraph.cpp added (r1.1.2.1)
MSchedGraph.h added (r1.1.2.1)
ModuloScheduling.h added (r1.11.2.1)
ModuloScheduling.cpp updated: 1.15 -> 1.15.4.1
ModuloSchedGraph.cpp (r1.14) removed
ModuloSchedGraph.h (r1.12) removed

---
Log message:

Merge from trunk

---
Diffs of the changes:  (+1451 -24)

Index: llvm/lib/CodeGen/ModuloScheduling/MSchedGraph.cpp
diff -c /dev/null llvm/lib/CodeGen/ModuloScheduling/MSchedGraph.cpp:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:27 2004
--- llvm/lib/CodeGen/ModuloScheduling/MSchedGraph.cpp	Mon Mar  1 17:58:13 2004
***************
*** 0 ****
--- 1,391 ----
+ //===-- MSchedGraph.h - Scheduling Graph ------------------------*- 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.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // A graph class for dependencies
+ //
+ //===----------------------------------------------------------------------===//
+ #define DEBUG_TYPE "ModuloSched"
+ 
+ #include "MSchedGraph.h"
+ #include "llvm/CodeGen/MachineBasicBlock.h"
+ #include "llvm/Target/TargetInstrInfo.h"
+ #include "Support/Debug.h"
+ #include <iostream>
+ using namespace llvm;
+ 
+ MSchedGraphNode::MSchedGraphNode(const MachineInstr* inst, 
+ 				 MSchedGraph *graph, 
+ 				 unsigned late) 
+   : Inst(inst), Parent(graph), latency(late) {
+ 
+   //Add to the graph
+   graph->addNode(inst, this);
+ }
+ 
+ void MSchedGraphNode::print(std::ostream &os) const {
+   os << "MSehedGraphNode: Inst=" << *Inst << ", latency= " << latency << "\n"; 
+ }
+ 
+ MSchedGraphEdge MSchedGraphNode::getInEdge(MSchedGraphNode *pred) {
+   //Loop over all the successors of our predecessor
+   //return the edge the corresponds to this in edge
+   for(MSchedGraphNode::succ_iterator I = pred->succ_begin(), E = pred->succ_end();
+       I != E; ++I) {
+     if(*I == this)
+       return I.getEdge();
+   }
+   assert(0 && "Should have found edge between this node and its predecessor!");
+   
+ }
+ 
+ void MSchedGraph::addNode(const MachineInstr *MI,
+ 			  MSchedGraphNode *node) {
+   
+   //Make sure node does not already exist  
+   assert(GraphMap.find(MI) == GraphMap.end() 
+ 	 && "New MSchedGraphNode already exists for this instruction");
+   
+   GraphMap[MI] = node;
+ }
+ 
+ MSchedGraph::MSchedGraph(const MachineBasicBlock *bb, const TargetMachine &targ)
+   : BB(bb), Target(targ) {
+   
+   //Make sure BB is not null, 
+   assert(BB != NULL && "Basic Block is null");
+   
+   DEBUG(std::cerr << "Constructing graph for " << bb << "\n");
+ 
+   //Create nodes and edges for this BB
+   buildNodesAndEdges();
+ }
+ 
+ MSchedGraph::~MSchedGraph () {
+   for(MSchedGraph::iterator I = GraphMap.begin(), E = GraphMap.end(); I != E; ++I)
+     delete I->second;
+ }
+ 
+ void MSchedGraph::buildNodesAndEdges() {
+   
+   //Get Machine target information for calculating latency
+   const TargetInstrInfo &MTI = Target.getInstrInfo();
+ 
+   std::vector<MSchedGraphNode*> memInstructions;
+   std::map<int, std::vector<OpIndexNodePair> > regNumtoNodeMap;
+   std::map<const Value*, std::vector<OpIndexNodePair> > valuetoNodeMap;
+ 
+   //Save PHI instructions to deal with later
+   std::vector<const MachineInstr*> phiInstrs;
+ 
+   //Loop over instructions in MBB and add nodes and edges
+   for (MachineBasicBlock::const_iterator MI = BB->begin(), e = BB->end(); MI != e; ++MI) {
+     //Get each instruction of machine basic block, get the delay
+     //using the op code, create a new node for it, and add to the
+     //graph.
+     
+     MachineOpCode MIopCode = MI->getOpcode();
+     int delay;
+ 
+     //Check if subsequent instructions can be issued before
+     //the result is ready, if so use min delay.
+     if(MTI.hasResultInterlock(MIopCode))
+       delay = MTI.minLatency(MIopCode);
+     else
+       delay = MTI.maxLatency(MIopCode);
+     
+     //Create new node for this machine instruction and add to the graph.
+     //Create only if not a nop
+     if(MTI.isNop(MIopCode))
+       continue;
+     
+     //Add PHI to phi instruction list to be processed later
+     if (MIopCode == TargetInstrInfo::PHI)
+       phiInstrs.push_back(MI);
+ 
+     //Node is created and added to the graph automatically
+     MSchedGraphNode *node =  new MSchedGraphNode(MI, this, delay);
+ 
+     DEBUG(std::cerr << "Created Node: " << *node << "\n"); 
+     
+     //Check OpCode to keep track of memory operations to add memory dependencies later.
+     MachineOpCode opCode = MI->getOpcode();
+ 
+     if(MTI.isLoad(opCode) || MTI.isStore(opCode))
+       memInstructions.push_back(node);
+ 
+     //Loop over all operands, and put them into the register number to
+     //graph node map for determining dependencies
+     //If an operands is a use/def, we have an anti dependence to itself
+     for(unsigned i=0; i < MI->getNumOperands(); ++i) {
+       //Get Operand
+       const MachineOperand &mOp = MI->getOperand(i);
+       
+       //Check if it has an allocated register (Note: this means it
+       //is greater then zero because zero is a special register for
+       //Sparc that holds the constant zero
+       if(mOp.hasAllocatedReg()) {
+ 	int regNum = mOp.getReg();
+ 	
+ 	//Put into our map
+ 	regNumtoNodeMap[regNum].push_back(std::make_pair(i, node));
+ 	continue;
+       }
+       
+       
+       //Add virtual registers dependencies
+       //Check if any exist in the value map already and create dependencies
+       //between them.
+       if(mOp.getType() == MachineOperand::MO_VirtualRegister ||  mOp.getType() == MachineOperand::MO_CCRegister) {
+ 
+ 	//Make sure virtual register value is not null
+ 	assert((mOp.getVRegValue() != NULL) && "Null value is defined");
+ 
+ 	//Check if this is a read operation in a phi node, if so DO NOT PROCESS
+ 	if(mOp.isUse() && (MIopCode == TargetInstrInfo::PHI))
+ 	  continue;
+ 
+       
+ 	if (const Value* srcI = mOp.getVRegValue()) {
+ 	  
+ 	  //Find value in the map
+ 	  std::map<const Value*, std::vector<OpIndexNodePair> >::iterator V 
+ 	    = valuetoNodeMap.find(srcI);
+ 	  
+ 	  //If there is something in the map already, add edges from
+ 	  //those instructions
+ 	  //to this one we are processing
+ 	  if(V != valuetoNodeMap.end()) {
+ 	    addValueEdges(V->second, node, mOp.isUse(), mOp.isDef());
+ 	    
+ 	    //Add to value map
+ 	    V->second.push_back(std::make_pair(i,node));
+ 	  }
+ 	  //Otherwise put it in the map
+ 	  else
+ 	    //Put into value map
+ 	  valuetoNodeMap[mOp.getVRegValue()].push_back(std::make_pair(i, node));
+ 	}
+       } 
+     }
+   }
+   addMemEdges(memInstructions);
+   addMachRegEdges(regNumtoNodeMap);
+ 
+   //Finally deal with PHI Nodes and Value*
+   for(std::vector<const MachineInstr*>::iterator I = phiInstrs.begin(), E = phiInstrs.end(); I != E;  ++I) {
+     //Get Node for this instruction
+     MSchedGraphNode *node = find(*I)->second;
+   
+     //Loop over operands for this instruction and add value edges
+     for(unsigned i=0; i < (*I)->getNumOperands(); ++i) {
+       //Get Operand
+       const MachineOperand &mOp = (*I)->getOperand(i);
+       if((mOp.getType() == MachineOperand::MO_VirtualRegister ||  mOp.getType() == MachineOperand::MO_CCRegister) && mOp.isUse()) {
+ 	//find the value in the map
+ 	if (const Value* srcI = mOp.getVRegValue()) {
+ 	  
+ 	  //Find value in the map
+ 	  std::map<const Value*, std::vector<OpIndexNodePair> >::iterator V 
+ 	    = valuetoNodeMap.find(srcI);
+ 	  
+ 	  //If there is something in the map already, add edges from
+ 	  //those instructions
+ 	  //to this one we are processing
+ 	  if(V != valuetoNodeMap.end()) {
+ 	    addValueEdges(V->second, node, mOp.isUse(), mOp.isDef(), 1);
+ 	  }
+ 	}
+       }
+     }
+   }
+ } 
+ 
+ void MSchedGraph::addValueEdges(std::vector<OpIndexNodePair> &NodesInMap,
+ 				MSchedGraphNode *destNode, bool nodeIsUse, 
+ 				bool nodeIsDef, int diff) {
+ 
+   for(std::vector<OpIndexNodePair>::iterator I = NodesInMap.begin(), 
+ 	E = NodesInMap.end(); I != E; ++I) {
+     
+     //Get node in vectors machine operand that is the same value as node
+     MSchedGraphNode *srcNode = I->second;
+     MachineOperand mOp = srcNode->getInst()->getOperand(I->first);
+ 
+     //Node is a Def, so add output dep.
+     if(nodeIsDef) {
+       if(mOp.isUse())
+ 	srcNode->addOutEdge(destNode, MSchedGraphEdge::ValueDep, 
+ 			    MSchedGraphEdge::AntiDep, diff);
+       if(mOp.isDef())
+ 	srcNode->addOutEdge(destNode, MSchedGraphEdge::ValueDep, 
+ 			    MSchedGraphEdge::OutputDep, diff);
+       
+     }
+     if(nodeIsUse) {
+       if(mOp.isDef())
+ 	srcNode->addOutEdge(destNode, MSchedGraphEdge::ValueDep, 
+ 			    MSchedGraphEdge::TrueDep, diff);
+     }
+   } 
+ }
+ 
+ 
+ void MSchedGraph::addMachRegEdges(std::map<int, std::vector<OpIndexNodePair> >& regNumtoNodeMap) {
+   //Loop over all machine registers in the map, and add dependencies
+   //between the instructions that use it
+   typedef std::map<int, std::vector<OpIndexNodePair> > regNodeMap;
+   for(regNodeMap::iterator I = regNumtoNodeMap.begin(); I != regNumtoNodeMap.end(); ++I) {
+     //Get the register number
+     int regNum = (*I).first;
+ 
+     //Get Vector of nodes that use this register
+     std::vector<OpIndexNodePair> Nodes = (*I).second;
+     
+     //Loop over nodes and determine the dependence between the other
+     //nodes in the vector
+     for(unsigned i =0; i < Nodes.size(); ++i) {
+       
+       //Get src node operator index that uses this machine register
+       int srcOpIndex = Nodes[i].first;
+       
+       //Get the actual src Node
+       MSchedGraphNode *srcNode = Nodes[i].second;
+       
+       //Get Operand
+       const MachineOperand &srcMOp = srcNode->getInst()->getOperand(srcOpIndex);
+       
+       bool srcIsUseandDef = srcMOp.isDef() && srcMOp.isUse();
+       bool srcIsUse = srcMOp.isUse() && !srcMOp.isDef();
+       
+       
+       //Look at all instructions after this in execution order
+       for(unsigned j=i+1; j < Nodes.size(); ++j) {
+ 	
+ 	//Sink node is a write
+ 	if(Nodes[j].second->getInst()->getOperand(Nodes[j].first).isDef()) {
+ 	              //Src only uses the register (read)
+             if(srcIsUse)
+ 	      srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
+ 				  MSchedGraphEdge::AntiDep);
+ 	    
+             else if(srcIsUseandDef) {
+ 	      srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
+ 				  MSchedGraphEdge::AntiDep);
+ 	      
+ 	      srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
+ 				  MSchedGraphEdge::OutputDep);
+ 	    }
+             else
+ 	      srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
+ 				  MSchedGraphEdge::OutputDep);
+ 	}
+ 	//Dest node is a read
+ 	else {
+ 	  if(!srcIsUse || srcIsUseandDef)
+ 	    srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
+ 				MSchedGraphEdge::TrueDep);
+ 	}
+         
+       }
+       
+       //Look at all the instructions before this one since machine registers
+       //could live across iterations.
+       for(unsigned j = 0; j < i; ++j) {
+ 		//Sink node is a write
+ 	if(Nodes[j].second->getInst()->getOperand(Nodes[j].first).isDef()) {
+ 	              //Src only uses the register (read)
+             if(srcIsUse)
+ 	      srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
+ 				  MSchedGraphEdge::AntiDep, 1);
+ 	    
+             else if(srcIsUseandDef) {
+ 	      srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
+ 				  MSchedGraphEdge::AntiDep, 1);
+ 	      
+ 	      srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
+ 				  MSchedGraphEdge::OutputDep, 1);
+ 	    }
+             else
+ 	      srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
+ 				  MSchedGraphEdge::OutputDep, 1);
+ 	}
+ 	//Dest node is a read
+ 	else {
+ 	  if(!srcIsUse || srcIsUseandDef)
+ 	    srcNode->addOutEdge(Nodes[j].second, MSchedGraphEdge::MachineRegister,
+ 				MSchedGraphEdge::TrueDep,1 );
+ 	}
+ 	
+ 
+       }
+ 
+     }
+     
+   }
+   
+ }
+ 
+ void MSchedGraph::addMemEdges(const std::vector<MSchedGraphNode*>& memInst) {
+ 
+   //Get Target machine instruction info
+   const TargetInstrInfo& TMI = Target.getInstrInfo();
+   
+   //Loop over all memory instructions in the vector
+   //Knowing that they are in execution, add true, anti, and output dependencies
+   for (unsigned srcIndex = 0; srcIndex < memInst.size(); ++srcIndex) {
+ 
+     //Get the machine opCode to determine type of memory instruction
+     MachineOpCode srcNodeOpCode = memInst[srcIndex]->getInst()->getOpcode();
+       
+     //All instructions after this one in execution order have an iteration delay of 0
+     for(unsigned destIndex = srcIndex + 1; destIndex < memInst.size(); ++destIndex) {
+        
+       //source is a Load, so add anti-dependencies (store after load)
+       if(TMI.isLoad(srcNodeOpCode))
+ 	if(TMI.isStore(memInst[destIndex]->getInst()->getOpcode()))
+ 	  memInst[srcIndex]->addOutEdge(memInst[destIndex], 
+ 			      MSchedGraphEdge::MemoryDep, 
+ 			      MSchedGraphEdge::AntiDep);
+       
+       //If source is a store, add output and true dependencies
+       if(TMI.isStore(srcNodeOpCode)) {
+ 	if(TMI.isStore(memInst[destIndex]->getInst()->getOpcode()))
+ 	   memInst[srcIndex]->addOutEdge(memInst[destIndex], 
+ 			      MSchedGraphEdge::MemoryDep, 
+ 			      MSchedGraphEdge::OutputDep);
+ 	else
+ 	  memInst[srcIndex]->addOutEdge(memInst[destIndex], 
+ 			      MSchedGraphEdge::MemoryDep, 
+ 			      MSchedGraphEdge::TrueDep);
+       }
+     }
+     
+     //All instructions before the src in execution order have an iteration delay of 1
+     for(unsigned destIndex = 0; destIndex < srcIndex; ++destIndex) {
+       //source is a Load, so add anti-dependencies (store after load)
+       if(TMI.isLoad(srcNodeOpCode))
+ 	if(TMI.isStore(memInst[destIndex]->getInst()->getOpcode()))
+ 	  memInst[srcIndex]->addOutEdge(memInst[destIndex], 
+ 			      MSchedGraphEdge::MemoryDep, 
+ 			      MSchedGraphEdge::AntiDep, 1);
+       if(TMI.isStore(srcNodeOpCode)) {
+ 	if(TMI.isStore(memInst[destIndex]->getInst()->getOpcode()))
+ 	  memInst[srcIndex]->addOutEdge(memInst[destIndex], 
+ 			      MSchedGraphEdge::MemoryDep, 
+ 			      MSchedGraphEdge::OutputDep, 1);
+ 	else
+ 	  memInst[srcIndex]->addOutEdge(memInst[destIndex], 
+ 			      MSchedGraphEdge::MemoryDep, 
+ 			      MSchedGraphEdge::TrueDep, 1);
+       }
+ 	  
+     }
+     
+   }
+ }


Index: llvm/lib/CodeGen/ModuloScheduling/MSchedGraph.h
diff -c /dev/null llvm/lib/CodeGen/ModuloScheduling/MSchedGraph.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:58:28 2004
--- llvm/lib/CodeGen/ModuloScheduling/MSchedGraph.h	Mon Mar  1 17:58:13 2004
***************
*** 0 ****
--- 1,310 ----
+ //===-- MSchedGraph.h - Scheduling Graph ------------------------*- 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.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // A graph class for dependencies
+ //
+ //===----------------------------------------------------------------------===//
+ 
+ #ifndef LLVM_MSCHEDGRAPH_H
+ #define LLVM_MSCHEDGRAPH_H
+ 
+ #include "llvm/CodeGen/MachineInstr.h"
+ #include "llvm/Target/TargetMachine.h"
+ #include "Support/GraphTraits.h"
+ #include "Support/STLExtras.h"
+ #include "Support/iterator"
+ #include <vector>
+ 
+ namespace llvm {
+   class MSchedGraph;
+   class MSchedGraphNode;
+   template<class IteratorType, class NodeType>
+   class MSchedGraphNodeIterator;
+ 
+ 
+   struct MSchedGraphEdge {
+     enum DataDepOrderType {
+       TrueDep, AntiDep, OutputDep, NonDataDep
+     };
+     
+     enum MSchedGraphEdgeType {
+       MemoryDep, ValueDep, MachineRegister
+     };
+ 
+     MSchedGraphNode *getDest() const { return dest; }
+     unsigned getIteDiff() { return iteDiff; }
+     unsigned getDepOrderType() { return depOrderType; }
+ 
+   private:
+     friend class MSchedGraphNode;
+     MSchedGraphEdge(MSchedGraphNode *destination, MSchedGraphEdgeType type, 
+ 		    unsigned deptype, unsigned diff) 
+       : dest(destination), depType(type), depOrderType(deptype), iteDiff(diff) {}
+     
+     MSchedGraphNode *dest;
+     MSchedGraphEdgeType depType;
+     unsigned depOrderType;
+     unsigned iteDiff;
+   };
+ 
+   class MSchedGraphNode {
+    
+     const MachineInstr* Inst; //Machine Instruction
+     MSchedGraph* Parent; //Graph this node belongs to
+     unsigned latency; //Latency of Instruction
+     
+     std::vector<MSchedGraphNode*> Predecessors; //Predecessor Nodes
+     std::vector<MSchedGraphEdge> Successors;
+ 
+   public:
+     MSchedGraphNode(const MachineInstr *inst, MSchedGraph *graph, 
+ 		    unsigned late=0);
+ 
+     //Iterators
+     typedef std::vector<MSchedGraphNode*>::iterator pred_iterator;
+     pred_iterator pred_begin() { return Predecessors.begin(); }
+     pred_iterator pred_end() { return Predecessors.end(); }
+     
+     typedef std::vector<MSchedGraphNode*>::const_iterator pred_const_iterator;
+     pred_const_iterator pred_begin() const { return Predecessors.begin(); }
+     pred_const_iterator pred_end() const { return Predecessors.end(); }
+ 
+     // Successor iterators.
+     typedef MSchedGraphNodeIterator<std::vector<MSchedGraphEdge>::const_iterator,
+ 				    const MSchedGraphNode> succ_const_iterator;
+     succ_const_iterator succ_begin() const;
+     succ_const_iterator succ_end() const;
+ 
+     typedef MSchedGraphNodeIterator<std::vector<MSchedGraphEdge>::iterator,
+ 				    MSchedGraphNode> succ_iterator;
+     succ_iterator succ_begin();
+     succ_iterator succ_end();
+     
+ 
+     void addOutEdge(MSchedGraphNode *destination, 
+ 		    MSchedGraphEdge::MSchedGraphEdgeType type, 
+ 		    unsigned deptype, unsigned diff=0) {
+       Successors.push_back(MSchedGraphEdge(destination, type, deptype,diff));
+       destination->Predecessors.push_back(this);
+     }
+     const MachineInstr* getInst() { return Inst; }
+     MSchedGraph* getParent() { return Parent; }
+     bool hasPredecessors() { return (Predecessors.size() > 0); }
+     bool hasSuccessors() { return (Successors.size() > 0); }
+     int getLatency() { return latency; }
+     MSchedGraphEdge getInEdge(MSchedGraphNode *pred);
+ 
+     //Debug support
+     void print(std::ostream &os) const;
+ 
+   };
+ 
+   template<class IteratorType, class NodeType>
+   class MSchedGraphNodeIterator : public forward_iterator<NodeType*, ptrdiff_t> {
+     IteratorType I;   // std::vector<MSchedGraphEdge>::iterator or const_iterator
+   public:
+     MSchedGraphNodeIterator(IteratorType i) : I(i) {}
+ 
+     bool operator==(const MSchedGraphNodeIterator RHS) const { return I == RHS.I; }
+     bool operator!=(const MSchedGraphNodeIterator RHS) const { return I != RHS.I; }
+ 
+     const MSchedGraphNodeIterator &operator=(const MSchedGraphNodeIterator &RHS) {
+       I = RHS.I;
+       return *this;
+     }
+ 
+     NodeType* operator*() const {
+       return I->getDest();
+     }
+     NodeType* operator->() const { return operator*(); }
+     
+     MSchedGraphNodeIterator& operator++() {                // Preincrement
+       ++I;
+       return *this;
+     }
+     MSchedGraphNodeIterator operator++(int) { // Postincrement
+       MSchedGraphNodeIterator tmp = *this; ++*this; return tmp; 
+     }
+ 
+     MSchedGraphEdge &getEdge() {
+       return *I;
+     }
+     const MSchedGraphEdge &getEdge() const {
+       return *I;
+     }
+   };
+ 
+   inline MSchedGraphNode::succ_const_iterator MSchedGraphNode::succ_begin() const {
+     return succ_const_iterator(Successors.begin());
+   }
+   inline MSchedGraphNode::succ_const_iterator MSchedGraphNode::succ_end() const {
+     return succ_const_iterator(Successors.end());
+   }
+   inline MSchedGraphNode::succ_iterator MSchedGraphNode::succ_begin() {
+     return succ_iterator(Successors.begin());
+   }
+   inline MSchedGraphNode::succ_iterator MSchedGraphNode::succ_end() {
+     return succ_iterator(Successors.end());
+   }
+ 
+   // ostream << operator for MSGraphNode class
+   inline std::ostream &operator<<(std::ostream &os, 
+ 				  const MSchedGraphNode &node) {
+     node.print(os);
+     return os;
+   }
+ 
+ 
+ 
+   class MSchedGraph {
+     
+     const MachineBasicBlock *BB; //Machine basic block
+     const TargetMachine &Target; //Target Machine
+         
+     //Nodes
+     std::map<const MachineInstr*, MSchedGraphNode*> GraphMap;
+ 
+     //Add Nodes and Edges to this graph for our BB
+     typedef std::pair<int, MSchedGraphNode*> OpIndexNodePair;
+     void buildNodesAndEdges();
+     void addValueEdges(std::vector<OpIndexNodePair> &NodesInMap, 
+ 		       MSchedGraphNode *node,
+ 		       bool nodeIsUse, bool nodeIsDef, int diff=0);
+     void addMachRegEdges(std::map<int, 
+ 			 std::vector<OpIndexNodePair> >& regNumtoNodeMap);
+     void addMemEdges(const std::vector<MSchedGraphNode*>& memInst);
+ 
+   public:
+     MSchedGraph(const MachineBasicBlock *bb, const TargetMachine &targ);
+     ~MSchedGraph();
+     
+     //Add Nodes to the Graph
+     void addNode(const MachineInstr* MI, MSchedGraphNode *node);
+     
+     //iterators 
+     typedef std::map<const MachineInstr*, MSchedGraphNode*>::iterator iterator;
+     typedef std::map<const MachineInstr*, MSchedGraphNode*>::const_iterator const_iterator;
+     typedef std::map<const MachineInstr*, MSchedGraphNode*>::reverse_iterator reverse_iterator;
+     iterator find(const MachineInstr* I) { return GraphMap.find(I); }
+     iterator end() { return GraphMap.end(); }
+     iterator begin() { return GraphMap.begin(); }
+     reverse_iterator rbegin() { return GraphMap.rbegin(); }
+     reverse_iterator rend() { return GraphMap.rend(); }
+     
+   };
+ 
+   
+   static MSchedGraphNode& getSecond(std::pair<const MachineInstr* const,
+ 					 MSchedGraphNode*> &Pair) {
+     return *Pair.second;
+   }
+ 
+ 
+ 
+   // Provide specializations of GraphTraits to be able to use graph
+   // iterators on the scheduling graph!
+   //
+   template <> struct GraphTraits<MSchedGraph*> {
+     typedef MSchedGraphNode NodeType;
+     typedef MSchedGraphNode::succ_iterator ChildIteratorType;
+     
+     static inline ChildIteratorType child_begin(NodeType *N) { 
+       return N->succ_begin(); 
+     }
+     static inline ChildIteratorType child_end(NodeType *N) { 
+       return N->succ_end();
+     }
+ 
+     typedef std::pointer_to_unary_function<std::pair<const MachineInstr* const,
+            MSchedGraphNode*>&, MSchedGraphNode&> DerefFun;
+ 
+     typedef mapped_iterator<MSchedGraph::iterator, DerefFun> nodes_iterator;
+     static nodes_iterator nodes_begin(MSchedGraph *G) {
+       return map_iterator(((MSchedGraph*)G)->begin(), DerefFun(getSecond));
+     }
+     static nodes_iterator nodes_end(MSchedGraph *G) {
+       return map_iterator(((MSchedGraph*)G)->end(), DerefFun(getSecond));
+     }
+     
+ 
+   };
+   
+   template <> struct GraphTraits<const MSchedGraph*> {
+     typedef const MSchedGraphNode NodeType;
+     typedef MSchedGraphNode::succ_const_iterator ChildIteratorType;
+     
+     static inline ChildIteratorType child_begin(NodeType *N) { 
+       return N->succ_begin(); 
+     }
+     static inline ChildIteratorType child_end(NodeType *N) { 
+       return N->succ_end();
+     }
+     typedef std::pointer_to_unary_function<std::pair<const MachineInstr* const,
+ 						     MSchedGraphNode*>&, MSchedGraphNode&> DerefFun;
+     
+     typedef mapped_iterator<MSchedGraph::iterator, DerefFun> nodes_iterator;
+     static nodes_iterator nodes_begin(MSchedGraph *G) {
+       return map_iterator(((MSchedGraph*)G)->begin(), DerefFun(getSecond));
+     }
+     static nodes_iterator nodes_end(MSchedGraph *G) {
+       return map_iterator(((MSchedGraph*)G)->end(), DerefFun(getSecond));
+     }
+   };
+   
+   template <> struct GraphTraits<Inverse<MSchedGraph*> > {
+     typedef MSchedGraphNode NodeType;
+     typedef MSchedGraphNode::pred_iterator ChildIteratorType;
+     
+     static inline ChildIteratorType child_begin(NodeType *N) { 
+       return N->pred_begin();
+     }
+     static inline ChildIteratorType child_end(NodeType *N) { 
+       return N->pred_end();
+     }
+     typedef std::pointer_to_unary_function<std::pair<const MachineInstr* const,
+            MSchedGraphNode*>&, MSchedGraphNode&> DerefFun;
+ 
+     typedef mapped_iterator<MSchedGraph::iterator, DerefFun> nodes_iterator;
+     static nodes_iterator nodes_begin(MSchedGraph *G) {
+       return map_iterator(((MSchedGraph*)G)->begin(), DerefFun(getSecond));
+     }
+     static nodes_iterator nodes_end(MSchedGraph *G) {
+       return map_iterator(((MSchedGraph*)G)->end(), DerefFun(getSecond));
+     }
+   };
+   
+   template <> struct GraphTraits<Inverse<const MSchedGraph*> > {
+     typedef const MSchedGraphNode NodeType;
+     typedef MSchedGraphNode::pred_const_iterator ChildIteratorType;
+     
+     static inline ChildIteratorType child_begin(NodeType *N) { 
+       return N->pred_begin();
+     }
+     static inline ChildIteratorType child_end(NodeType *N) { 
+       return N->pred_end();
+     }
+ 
+     typedef std::pointer_to_unary_function<std::pair<const MachineInstr* const,
+ 						     MSchedGraphNode*>&, MSchedGraphNode&> DerefFun;
+     
+     typedef mapped_iterator<MSchedGraph::iterator, DerefFun> nodes_iterator;
+     static nodes_iterator nodes_begin(MSchedGraph *G) {
+       return map_iterator(((MSchedGraph*)G)->begin(), DerefFun(getSecond));
+     }
+     static nodes_iterator nodes_end(MSchedGraph *G) {
+       return map_iterator(((MSchedGraph*)G)->end(), DerefFun(getSecond));
+     }
+   };
+ 
+ 
+ 
+ 
+ }
+ 
+ #endif


Index: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h
diff -c /dev/null llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h:1.11.2.1
*** /dev/null	Mon Mar  1 17:58:28 2004
--- llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.h	Mon Mar  1 17:58:13 2004
***************
*** 0 ****
--- 1,68 ----
+ //===-- ModuloScheduling.h - Swing Modulo Scheduling------------*- 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.
+ //
+ //===----------------------------------------------------------------------===//
+ // 
+ // 
+ //===----------------------------------------------------------------------===//
+ 
+ #ifndef LLVM_MODULOSCHEDULING_H
+ #define LLVM_MODULOSCHEDULING_H
+ 
+ #include "MSchedGraph.h"
+ #include "llvm/Function.h"
+ #include "llvm/Pass.h"
+ #include <set>
+ 
+ namespace llvm {
+   
+ 
+   //Struct to contain ModuloScheduling Specific Information for each node
+   struct MSNodeAttributes {
+     int ASAP; //Earliest time at which the opreation can be scheduled
+     int ALAP; //Latest time at which the operation can be scheduled.
+     int MOB;
+     int depth;
+     int height;
+     MSNodeAttributes(int asap=-1, int alap=-1, int mob=-1, 
+ 			     int d=-1, int h=-1) : ASAP(asap), ALAP(alap), 
+ 						   MOB(mob), depth(d), 
+ 						   height(h) {}
+   };
+ 
+ 
+   class ModuloSchedulingPass : public FunctionPass {
+     const TargetMachine ⌖
+ 
+     //Map that holds node to node attribute information
+     std::map<MSchedGraphNode*, MSNodeAttributes> nodeToAttributesMap;
+ 
+     //Internal functions
+     bool MachineBBisValid(const MachineBasicBlock *BI);
+     int calculateResMII(const MachineBasicBlock *BI);
+     void calculateNodeAttributes(MSchedGraph *graph, int MII);
+     void calculateASAP(MSchedGraphNode *node, MSNodeAttributes &attributes, 
+ 		       int MII,std::set<MSchedGraphNode*> &visitedNodes);
+     void calculateALAP(MSchedGraphNode *node, MSNodeAttributes &attributes, int MII, 
+ 		       int maxASAP, std::set<MSchedGraphNode*> &visitedNodes);
+     void calculateHeight(MSchedGraphNode *node, 
+ 			 MSNodeAttributes &attributes, std::set<MSchedGraphNode*> &visitedNodes);
+     void calculateDepth(MSchedGraphNode *node, MSNodeAttributes &attributes, 
+ 			std::set<MSchedGraphNode*> &visitedNodes);
+ 
+     int findMaxASAP();
+     void ModuloSchedulingPass::orderNodes();
+     void findAllReccurrences(MSchedGraphNode *node, std::vector<MSchedGraphNode*> &visitedNodes);
+   public:
+     ModuloSchedulingPass(TargetMachine &targ) : target(targ) {}
+     virtual bool runOnFunction(Function &F);
+   };
+ 
+ }
+ 
+ 
+ #endif


Index: llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp
diff -u llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.15 llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.15.4.1
--- llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp:1.15	Tue Nov 11 16:41:33 2003
+++ llvm/lib/CodeGen/ModuloScheduling/ModuloScheduling.cpp	Mon Mar  1 17:58:13 2004
@@ -1,46 +1,704 @@
-//===-- 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 &GT) {
+  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;
+}





More information about the llvm-commits mailing list