blob: 0e2b09f6c991b77c1e371b91705bb063bbb79279 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Intel, Konstantin M. Anisimov, Igor V. Chebykin
*
*/
#include "IpfCfg.h"
#include "IpfOpndManager.h"
#include "IpfIrPrinter.h"
namespace Jitrino {
namespace IPF {
//========================================================================================//
// Edge
//========================================================================================//
Edge::Edge(Node *source, Node *target, double prob, EdgeKind edgeKind) :
edgeKind(edgeKind),
source(source),
target(target),
prob(prob) {
}
//----------------------------------------------------------------------------------------//
void Edge::remove() {
source->removeEdge(this);
target->removeEdge(this);
}
//----------------------------------------------------------------------------------------//
void Edge::insert() {
source->addEdge(this);
target->addEdge(this);
}
//----------------------------------------------------------------------------------------//
void Edge::changeSource(Node *source_) {
source->removeEdge(this);
source = source_;
source->addEdge(this);
}
//----------------------------------------------------------------------------------------//
void Edge::changeTarget(Node *target_) {
target->removeEdge(this);
target = target_;
target->addEdge(this);
}
//----------------------------------------------------------------------------------------//
bool Edge::isBackEdge() {
if(source->getLoopHeader() == target) return true;
return false;
}
//========================================================================================//
// ExceptionEdge
//========================================================================================//
ExceptionEdge::ExceptionEdge(Node *source,
Node *target,
double prob,
Type *exceptionType,
U_32 priority) :
Edge(source, target, prob, EDGE_EXCEPTION),
exceptionType(exceptionType),
priority(priority) {
}
//========================================================================================//
// Node
//========================================================================================//
Node::Node(MemoryManager &mm, U_32 id, U_32 execCounter, NodeKind kind) :
id(id),
execCounter(execCounter),
nodeKind(kind),
inEdges(mm),
outEdges(mm),
loopHeader(NULL),
liveSet(mm) {
}
//----------------------------------------------------------------------------------------//
void Node::addEdge(Edge *edge) {
if (edge->getSource() == this) outEdges.push_back(edge);
if (edge->getTarget() == this) inEdges.push_back(edge);
}
//----------------------------------------------------------------------------------------//
void Node::removeEdge(Edge *edge) {
if (edge->getSource() == this) {
EdgeIterator it = find(outEdges.begin(), outEdges.end(), edge);
if (it != outEdges.end()) outEdges.erase(it);
}
if (edge->getTarget() == this) {
EdgeIterator it = find(inEdges.begin(), inEdges.end(), edge);
if (it != inEdges.end()) inEdges.erase(it);
}
}
//----------------------------------------------------------------------------------------//
Edge *Node::getOutEdge(EdgeKind edgeKind) {
for(uint16 i=0; i<outEdges.size(); i++) {
if(outEdges[i]->getEdgeKind() == edgeKind) return outEdges[i];
}
return NULL;
}
//----------------------------------------------------------------------------------------//
Edge *Node::getInEdge(EdgeKind edgeKind) {
for(uint16 i=0; i<inEdges.size(); i++) {
if(inEdges[i]->getEdgeKind() == edgeKind) return inEdges[i];
}
return NULL;
}
//----------------------------------------------------------------------------------------//
Edge *Node::getOutEdge(Node *targetNode) {
for(uint16 i=0; i<outEdges.size(); i++) {
if(outEdges[i]->getTarget() == targetNode) return outEdges[i];
}
return NULL;
}
//----------------------------------------------------------------------------------------//
Edge *Node::getInEdge(Node *sourceNode) {
for(uint16 i=0; i<inEdges.size(); i++) {
if(inEdges[i]->getSource() == sourceNode) return inEdges[i];
}
return NULL;
}
//----------------------------------------------------------------------------------------//
Node *Node::getDispatchNode() {
Edge *dispatchEdge = getOutEdge(EDGE_DISPATCH);
if(dispatchEdge == NULL) return NULL;
return dispatchEdge->getTarget();
}
//----------------------------------------------------------------------------------------//
void Node::mergeOutLiveSets(RegOpndSet &resultSet) {
for(uint16 i=0; i<outEdges.size(); i++) {
RegOpndSet &outLiveSet = outEdges[i]->getTarget()->getLiveSet();
resultSet.insert(outLiveSet.begin(), outLiveSet.end());
}
}
//----------------------------------------------------------------------------------------//
void Node::remove() {
for (int16 i=outEdges.size()-1; i>=0; i--) outEdges[i]->remove(); // remove out edges
for (int16 i=inEdges.size()-1; i>=0; i--) inEdges[i]->remove(); // remove in edges
}
//========================================================================================//
// BbNode
//========================================================================================//
BbNode::BbNode(MemoryManager &mm, U_32 id, U_32 execCounter) :
Node(mm, id, execCounter, NODE_BB),
insts(mm),
layoutSucc(NULL),
address(0) {
}
//========================================================================================//
// Cfg
//========================================================================================//
Cfg::Cfg(MemoryManager &mm, CompilationInterface &compilationInterface):
mm(mm),
compilationInterface(compilationInterface),
enterNode(NULL),
exitNode(NULL),
searchResult(mm),
lastSearchKind(SEARCH_UNDEF_ORDER) {
opndManager = new(mm) OpndManager(mm, compilationInterface);
}
//----------------------------------------------------------------------------------------//
NodeVector& Cfg::search(SearchKind searchKind) {
if (lastSearchKind == searchKind) return searchResult;
lastSearchKind = searchKind;
NodeSet visitedNodes(mm);
searchResult.clear();
switch (searchKind) {
case SEARCH_DIRECT_ORDER : makeDirectOrdered(exitNode, visitedNodes); break;
case SEARCH_POST_ORDER : makePostOrdered(enterNode, visitedNodes); break;
case SEARCH_LAYOUT_ORDER : makeLayoutOrdered(); break;
case SEARCH_UNDEF_ORDER : break;
default : IPF_ERR << endl; break;
}
return searchResult;
}
//----------------------------------------------------------------------------------------//
// All predecessors of current node have already been visited
void Cfg::makeDirectOrdered(Node *node, NodeSet &visitedNodes) {
visitedNodes.insert(node); // mark node visited
EdgeVector& inEdges = node->getInEdges(); // get inEdges
for (U_32 i=0; i<inEdges.size(); i++) { // iterate through inEdges
Node *pred = inEdges[i]->getSource(); // get pred node
if (visitedNodes.count(pred) == 1) continue; // if it is already visited - ignore
makeDirectOrdered(pred, visitedNodes); // we have found unvisited pred - reenter
}
searchResult.push_back(node); // all preds have been visited - place node in searchResult vector
}
//----------------------------------------------------------------------------------------//
// All successors of current node have already been visited
void Cfg::makePostOrdered(Node *node, NodeSet &visitedNodes) {
visitedNodes.insert(node); // mark node visited
EdgeVector& outEdges = node->getOutEdges(); // get outEdges
for (U_32 i=0; i<outEdges.size(); i++) { // iterate through outEdges
Node *succ = outEdges[i]->getTarget(); // get succ node
if (visitedNodes.count(succ) == 1) continue; // if it is already visited - ignore
makePostOrdered(succ, visitedNodes); // we have found unvisited succ - reenter
}
searchResult.push_back(node); // all succs have been visited - place node in searchResult vector
}
//----------------------------------------------------------------------------------------//
void Cfg::makeLayoutOrdered() {
BbNode *node = getEnterNode();
while (node != NULL) {
searchResult.push_back(node);
node = node->getLayoutSucc();
}
}
} // IPF
} // Jitrino