blob: b62bbb6cf4fc83a64a3fa2769d7fcc22431822d2 [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 "IpfCodeSelector.h"
#include "IpfOpndManager.h"
#include "IpfIrPrinter.h"
namespace Jitrino {
namespace IPF {
//========================================================================================//
// IpfMethodCodeSelector
//========================================================================================//
IpfMethodCodeSelector::IpfMethodCodeSelector(Cfg &cfg,
CompilationInterface &compilationInterface) :
mm(cfg.getMM()),
cfg(cfg),
compilationInterface(compilationInterface),
methodDesc(NULL),
opnds(mm),
nodes(mm) {
}
//----------------------------------------------------------------------------------------//
void IpfMethodCodeSelector::genVars(U_32 numVars, VarCodeSelector &varCodeSelector) {
IPF_LOG << endl << " Select variables" << endl;
IpfVarCodeSelector ipfVarCodeSelector(cfg, opnds);
varCodeSelector.genCode(ipfVarCodeSelector);
}
//----------------------------------------------------------------------------------------//
void IpfMethodCodeSelector::setMethodDesc(MethodDesc *methodDesc_) {
methodDesc = methodDesc_;
}
//----------------------------------------------------------------------------------------//
void IpfMethodCodeSelector::genCFG(U_32 numNodes,
CFGCodeSelector &codeSelector,
bool useProfile) {
IPF_LOG << endl << " Select CFG" << endl;
IpfCfgCodeSelector cfgCodeSelector(cfg, nodes, opnds, compilationInterface);
codeSelector.genCode(cfgCodeSelector);
}
//----------------------------------------------------------------------------------------//
MethodDesc *IpfMethodCodeSelector::getMethodDesc() { return methodDesc; }
//========================================================================================//
// IpfVarCodeSelector
//========================================================================================//
IpfVarCodeSelector::IpfVarCodeSelector(Cfg &cfg, OpndVector &opnds) :
mm(cfg.getMM()),
cfg(cfg),
opnds(opnds) {
opndManager = cfg.getOpndManager();
}
//----------------------------------------------------------------------------------------//
U_32 IpfVarCodeSelector::defVar(Type *varType, bool isAddressTaken, bool isPinned) {
OpndKind opndKind = IpfInstCodeSelector::toOpndKind(varType->tag);
DataKind dataKind = IpfInstCodeSelector::toDataKind(varType->tag);
RegOpnd *var = NULL;
if (Type::isTau(varType->tag)) var = opndManager->getTau();
else var = opndManager->newRegOpnd(opndKind, dataKind);
opnds.push_back(var);
IPF_LOG << " Define local variable"
<< "; varType=" << Type::tag2str(varType->tag)
<< ", isPinned=" << isPinned
<< "; var='" << IrPrinter::toString(var) << "'" << endl;
return opnds.size()-1; // It is going to be varId
}
//----------------------------------------------------------------------------------------//
void IpfVarCodeSelector::setManagedPointerBase(U_32 managedPtrVarNum, U_32 baseVarNum) {}
//========================================================================================//
// IpfCfgCodeSelector
//========================================================================================//
IpfCfgCodeSelector::IpfCfgCodeSelector(Cfg &cfg,
NodeVector &nodes,
OpndVector &opnds,
CompilationInterface &compilationInterface) :
mm(cfg.getMM()),
cfg(cfg),
nodes(nodes),
opnds(opnds),
compilationInterface(compilationInterface),
opndManager(cfg.getOpndManager()) {
}
//----------------------------------------------------------------------------------------//
U_32 IpfCfgCodeSelector::genDispatchNode(U_32 numInEdges,
U_32 numOutEdges,
const StlVector<MethodDesc*>& inlineInfo,
double cnt) {
Node *node = new(mm) Node(mm, opndManager->getNextNodeId(), (U_32) cnt, NODE_DISPATCH);
nodes.push_back(node);
IPF_LOG << endl << " Generate Dispatch node" << node->getId() << endl;
return nodes.size()-1;
}
//----------------------------------------------------------------------------------------//
U_32 IpfCfgCodeSelector::genBlock(U_32 numInEdges,
U_32 numOutEdges,
BlockKind blockKind,
BlockCodeSelector &codeSelector,
double cnt) {
BbNode *node = new(mm) BbNode(mm, opndManager->getNextNodeId(), (U_32)cnt);
nodes.push_back(node);
if(blockKind == Prolog) cfg.setEnterNode(node);
IPF_LOG << endl << " Generate BB node" << node->getId() << endl;
IpfInstCodeSelector ipfInstCodeSelector(cfg, *node, opnds, compilationInterface);
codeSelector.genCode(ipfInstCodeSelector);
return nodes.size()-1;
}
//----------------------------------------------------------------------------------------//
U_32 IpfCfgCodeSelector::genUnwindNode(U_32 numInEdges,
U_32 numOutEdges,
double cnt) {
Node *node = new(mm) Node(mm, opndManager->getNextNodeId(), (U_32) cnt, NODE_UNWIND);
nodes.push_back(node);
IPF_LOG << endl << " Generate Unwind node" << node->getId() << endl;
return nodes.size()-1;
}
//----------------------------------------------------------------------------------------//
U_32 IpfCfgCodeSelector::genExitNode(U_32 numInEdges, double cnt) {
BbNode *node = new(mm) BbNode(mm, opndManager->getNextNodeId(), (U_32) cnt);
nodes.push_back(node);
cfg.setExitNode(node);
IPF_LOG << endl << " Generate Exit node" << node->getId() << endl << endl;
return nodes.size()-1;
}
//----------------------------------------------------------------------------------------//
void IpfCfgCodeSelector::genUnconditionalEdge(U_32 tailNodeId,
U_32 headNodeId,
double prob) {
IPF_LOG << " Generate Unconditional edge node" << nodes[tailNodeId]->getId();
IPF_LOG << " -> node" << nodes[headNodeId]->getId() << endl;
Edge *edge = new(mm) Edge(nodes[tailNodeId], nodes[headNodeId], prob, EDGE_THROUGH);
edge->insert();
}
//----------------------------------------------------------------------------------------//
void IpfCfgCodeSelector::genTrueEdge(U_32 tailNodeId, U_32 headNodeId, double prob) {
IPF_LOG << " Generate True edge node" << nodes[tailNodeId]->getId();
IPF_LOG << " -> node" << nodes[headNodeId]->getId() << endl;
Edge *edge = new(mm) Edge(nodes[tailNodeId], nodes[headNodeId], prob, EDGE_BRANCH);
edge->insert();
}
//----------------------------------------------------------------------------------------//
void IpfCfgCodeSelector::genFalseEdge(U_32 tailNodeId, U_32 headNodeId, double prob) {
IPF_LOG << " Generate False edge node" << nodes[tailNodeId]->getId();
IPF_LOG << " -> node" << nodes[headNodeId]->getId() << endl;
Edge *edge = new(mm) Edge(nodes[tailNodeId], nodes[headNodeId], prob, EDGE_THROUGH);
edge->insert();
}
//----------------------------------------------------------------------------------------//
void IpfCfgCodeSelector::genSwitchEdges(U_32 tailNodeId,
U_32 numTargets,
U_32 *targets,
double *probs,
U_32 defaultTarget) {
BbNode *tailNode = (BbNode *)nodes[tailNodeId];
InstVector &insts = tailNode->getInsts();
Inst *switchInst = insts.back();
Opnd *defTargetImm = switchInst->getOpnd(POS_SWITCH_DEFAULT);
ConstantRef *constantRef = (ConstantRef *) switchInst->getOpnd(POS_SWITCH_TABLE);
SwitchConstant *switchConstant = (SwitchConstant *)constantRef->getConstant();
Edge *defedge = NULL;
Edge *edge = NULL;
bool defadded = false;
U_32 i = 0;
IPF_LOG << " Generate Switch tailNodeId=" << tailNodeId
<< "; defaultTarget=" << defaultTarget << endl;
defedge = new(mm) Edge(nodes[tailNodeId], nodes[defaultTarget], probs[defaultTarget], EDGE_BRANCH);
defedge->insert();
for(i=0; i<numTargets; i++) {
if(targets[i] == defaultTarget) {
defTargetImm->setValue(i);
switchConstant->addEdge(defedge);
defadded = true;
IPF_LOG << " default: " << i << endl;
continue;
}
IPF_LOG << " case " << i << ": " << targets[i] << endl;
edge = new(mm) Edge(nodes[tailNodeId], nodes[targets[i]], probs[i], EDGE_BRANCH);
edge->insert();
switchConstant->addEdge(edge);
}
if (!defadded) {
defTargetImm->setValue(i);
switchConstant->addEdge(defedge);
defadded = true;
IPF_LOG << " default: " << i << endl;
}
}
//--------------------------------------------------------------------------------//
// edge from try region to dispatch node
void IpfCfgCodeSelector::genExceptionEdge(U_32 tailNodeId,
U_32 headNodeId,
double prob) {
Node *tailNode = nodes[tailNodeId];
Node *headNode = nodes[headNodeId];
IPF_LOG << " Generate Exception edge node" << tailNode->getId();
IPF_LOG << " -> node" << headNode->getId() << endl;
Edge *edge = new(mm) Edge(tailNode, headNode, prob, EDGE_DISPATCH);
edge->insert();
}
//----------------------------------------------------------------------------------------//
// edge from dispatch node to exception handler
void IpfCfgCodeSelector::genCatchEdge(U_32 tailNodeId,
U_32 headNodeId,
U_32 priority,
Type *exceptionType,
double prob) {
Node *tailNode = nodes[tailNodeId];
Node *headNode = nodes[headNodeId];
IPF_LOG << " Generate Catch edge node" << tailNode->getId();
IPF_LOG << " -> node" << headNode->getId() << endl;
ExceptionEdge *edge = new(mm) ExceptionEdge(tailNode, headNode, prob, exceptionType, priority);
edge->insert();
}
//----------------------------------------------------------------------------------------//
void IpfCfgCodeSelector::genExitEdge(U_32 tailNodeId,
U_32 headNodeId,
double prob) {
Node *tailNode=nodes[tailNodeId];
Node *headNode=nodes[headNodeId];
IPF_LOG << " Generate Exit edge node" << tailNode->getId();
IPF_LOG << " -> node" << headNode->getId() << endl;
Edge *edge = new(mm) Edge(tailNode, headNode, prob, EDGE_THROUGH);
edge->insert();
}
//----------------------------------------------------------------------------------------//
void IpfCfgCodeSelector::setLoopInfo(U_32 nodeId,
bool isLoopHeader,
bool hasContainingLoopHeader,
U_32 headerId) {
if (hasContainingLoopHeader == false) return;
Node *node = nodes[nodeId];
Node *header = nodes[headerId];
node->setLoopHeader(header);
}
//----------------------------------------------------------------------------------------//
void IpfCfgCodeSelector::setPersistentId(U_32 nodeId, U_32 persistentId) {}
} //namespace IPF
} //namespace Jitrino