//===-- MSchedGraph.cpp - 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 "../../Target/SparcV9/SparcV9RegisterInfo.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "Support/Debug.h"
#include <cstdlib>
using namespace llvm;

MSchedGraphNode::MSchedGraphNode(const MachineInstr* inst, 
				 MSchedGraph *graph, 
				 unsigned late, bool isBranch) 
  : Inst(inst), Parent(graph), latency(late), isBranchInstr(isBranch) {

  //Add to the graph
  graph->addNode(inst, this);
}

void MSchedGraphNode::print(std::ostream &os) const {
  os << "MSchedGraphNode: 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!");
  abort();
}

unsigned MSchedGraphNode::getInEdgeNum(MSchedGraphNode *pred) {
  //Loop over all the successors of our predecessor
  //return the edge the corresponds to this in edge
  int count = 0;
  for(MSchedGraphNode::succ_iterator I = pred->succ_begin(), E = pred->succ_end();
      I != E; ++I) {
    if(*I == this)
      return count;
    count++;
  }
  assert(0 && "Should have found edge between this node and its predecessor!");
  abort();
}
bool MSchedGraphNode::isSuccessor(MSchedGraphNode *succ) {
  for(succ_iterator I = succ_begin(), E = succ_end(); I != E; ++I)
    if(*I == succ)
      return true;
  return false;
}


bool MSchedGraphNode::isPredecessor(MSchedGraphNode *pred) {
  if(find( Predecessors.begin(),  Predecessors.end(), pred) !=   Predecessors.end())
    return true;
  else
    return false;
}


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 opCode = MI->getOpcode();
    int delay;

#if 0  // FIXME: LOOK INTO THIS
    //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
#endif
      //Get delay
      delay = MTI->maxLatency(opCode);
    
    //Create new node for this machine instruction and add to the graph.
    //Create only if not a nop
    if(MTI->isNop(opCode))
      continue;
    
    //Add PHI to phi instruction list to be processed later
    if (opCode == TargetInstrInfo::PHI)
      phiInstrs.push_back(MI);

    bool isBranch = false;

    //We want to flag the branch node to treat it special
    if(MTI->isBranch(opCode))
      isBranch = true;

    //Node is created and added to the graph automatically
    MSchedGraphNode *node =  new MSchedGraphNode(MI, this, delay, isBranch);

    DEBUG(std::cerr << "Created Node: " << *node << "\n"); 

    //Check OpCode to keep track of memory operations to add memory dependencies later.    
    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 
      if(mOp.hasAllocatedReg()) {
	int regNum = mOp.getReg();

	if(regNum != SparcV9::g0) {
	//Put into our map
	regNumtoNodeMap[regNum].push_back(std::make_pair(i, node));
	}
	continue;
      }
      
      
      //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() && (opCode == 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);
      }
	  
    }
    
  }
}
