//===- SchedGraphCommon.cpp - Scheduling Graphs Base Class- ---------------===//
// 
//                     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.
// 
//===----------------------------------------------------------------------===//
//
// Scheduling graph base class that contains common information for SchedGraph
// and ModuloSchedGraph scheduling graphs.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/SchedGraphCommon.h"
#include "Support/STLExtras.h"
#include <iostream>

namespace llvm {

class SchedGraphCommon;

//
// class SchedGraphEdge
// 
SchedGraphEdge::SchedGraphEdge(SchedGraphNodeCommon* _src,
			       SchedGraphNodeCommon* _sink,
			       SchedGraphEdgeDepType _depType,
			       unsigned int     _depOrderType,
			       int _minDelay)
  : src(_src), sink(_sink), depType(_depType), depOrderType(_depOrderType),
    minDelay((_minDelay >= 0)? _minDelay : _src->getLatency()), val(NULL) {
  
  iteDiff=0;
  assert(src != sink && "Self-loop in scheduling graph!");
  src->addOutEdge(this);
  sink->addInEdge(this);
}

SchedGraphEdge::SchedGraphEdge(SchedGraphNodeCommon*  _src,
			       SchedGraphNodeCommon*  _sink,
			       const Value*     _val,
			       unsigned int     _depOrderType,
			       int              _minDelay)
  : src(_src), sink(_sink), depType(ValueDep), depOrderType(_depOrderType),
    minDelay((_minDelay >= 0)? _minDelay : _src->getLatency()), val(_val) {
  iteDiff=0;
  assert(src != sink && "Self-loop in scheduling graph!");
  src->addOutEdge(this);
  sink->addInEdge(this);
}

SchedGraphEdge::SchedGraphEdge(SchedGraphNodeCommon*  _src,
			       SchedGraphNodeCommon*  _sink,
			       unsigned int     _regNum,
			       unsigned int     _depOrderType,
			       int             _minDelay)
  : src(_src), sink(_sink), depType(MachineRegister),
    depOrderType(_depOrderType),
    minDelay((_minDelay >= 0)? _minDelay : _src->getLatency()),
    machineRegNum(_regNum) {
  iteDiff=0;
  assert(src != sink && "Self-loop in scheduling graph!");
  src->addOutEdge(this);
  sink->addInEdge(this);
}

SchedGraphEdge::SchedGraphEdge(SchedGraphNodeCommon* _src,
			       SchedGraphNodeCommon* _sink,
			       ResourceId      _resourceId,
			       int             _minDelay)
  : src(_src), sink(_sink), depType(MachineResource), depOrderType(NonDataDep),
    minDelay((_minDelay >= 0)? _minDelay : _src->getLatency()),
    resourceId(_resourceId) {
  iteDiff=0;
  assert(src != sink && "Self-loop in scheduling graph!");
  src->addOutEdge(this);
  sink->addInEdge(this);
}


void SchedGraphEdge::dump(int indent) const {
  std::cerr << std::string(indent*2, ' ') << *this; 
}

/*dtor*/
SchedGraphNodeCommon::~SchedGraphNodeCommon()
{
  // for each node, delete its out-edges
  std::for_each(beginOutEdges(), endOutEdges(),
                deleter<SchedGraphEdge>);
}

void SchedGraphNodeCommon::removeInEdge(const SchedGraphEdge* edge) {
  assert(edge->getSink() == this);
  
  for (iterator I = beginInEdges(); I != endInEdges(); ++I)
    if ((*I) == edge) {
      inEdges.erase(I);
      break;
    }
}

void SchedGraphNodeCommon::removeOutEdge(const SchedGraphEdge* edge) {
  assert(edge->getSrc() == this);
  
  for (iterator I = beginOutEdges(); I != endOutEdges(); ++I)
    if ((*I) == edge) {
      outEdges.erase(I);
      break;
    }
}

void SchedGraphNodeCommon::dump(int indent) const {
  std::cerr << std::string(indent*2, ' ') << *this; 
}

//class SchedGraphCommon

SchedGraphCommon::~SchedGraphCommon() {
  delete graphRoot;
  delete graphLeaf;
}


void SchedGraphCommon::eraseIncomingEdges(SchedGraphNodeCommon* node, 
					  bool addDummyEdges) {
  // Delete and disconnect all in-edges for the node
  for (SchedGraphNodeCommon::iterator I = node->beginInEdges();
       I != node->endInEdges(); ++I) {
    SchedGraphNodeCommon* srcNode = (*I)->getSrc();
    srcNode->removeOutEdge(*I);
    delete *I;
    
    if (addDummyEdges && srcNode != getRoot() &&
	srcNode->beginOutEdges() == srcNode->endOutEdges()) { 
      
      // srcNode has no more out edges, so add an edge to dummy EXIT node
      assert(node != getLeaf() && "Adding edge that was just removed?");
      (void) new SchedGraphEdge(srcNode, getLeaf(),
				SchedGraphEdge::CtrlDep, 
				SchedGraphEdge::NonDataDep, 0);
    }
  }
  
  node->inEdges.clear();
}

void SchedGraphCommon::eraseOutgoingEdges(SchedGraphNodeCommon* node, 
					  bool addDummyEdges) {
  // Delete and disconnect all out-edges for the node
  for (SchedGraphNodeCommon::iterator I = node->beginOutEdges();
       I != node->endOutEdges(); ++I) {
    SchedGraphNodeCommon* sinkNode = (*I)->getSink();
    sinkNode->removeInEdge(*I);
    delete *I;
    
    if (addDummyEdges &&
	sinkNode != getLeaf() &&
	sinkNode->beginInEdges() == sinkNode->endInEdges()) {
      
      //sinkNode has no more in edges, so add an edge from dummy ENTRY node
      assert(node != getRoot() && "Adding edge that was just removed?");
      (void) new SchedGraphEdge(getRoot(), sinkNode,
				SchedGraphEdge::CtrlDep, 
				SchedGraphEdge::NonDataDep, 0);
    }
  }
  
  node->outEdges.clear();
}

void SchedGraphCommon::eraseIncidentEdges(SchedGraphNodeCommon* node, 
					  bool addDummyEdges) {
  this->eraseIncomingEdges(node, addDummyEdges);	
  this->eraseOutgoingEdges(node, addDummyEdges);	
}

} // End llvm namespace
