in vm/jitrino/src/optimizer/FlowGraph.cpp [878:1082]
void FlowGraph::doTranslatorCleanupPhase(IRManager& irm) {
U_32 id = irm.getCompilationContext()->getCurrentSessionNum();
const char* stage = "trans_cleanup";
if (Log::isLogEnabled(LogStream::IRDUMP)) {
LogStream& irdump = Log::log(LogStream::IRDUMP);
Log::printStageBegin(irdump.out(), id, "TRANS", stage, stage);
irdump << OptPass::indent(irm) << "Trans: Running " << "cleanup" << ::std::endl;
Log::printIRDumpBegin(irdump.out(), id, stage, "before");
printHIR(irdump.out(), irm.getFlowGraph(), irm.getMethodDesc());
Log::printIRDumpEnd(irdump.out(), id, stage, "before");
}
ControlFlowGraph& fg = irm.getFlowGraph();
InstFactory& instFactory = irm.getInstFactory();
OpndManager& opndManager = irm.getOpndManager();
static CountTime cleanupPhaseTimer("ptra::fg::cleanupPhase");
AutoTimer tm(cleanupPhaseTimer);
fg.purgeUnreachableNodes();
#ifdef _DEBUG
//check if loop structure is valid after translator
OptPass::computeLoops(irm, false);
#endif
inlineJSRs(&irm);
fg.purgeUnreachableNodes();
checkBCMapping(irm);
{
static CountTime cleanupPhaseInternalTimer("ptra::fg::cleanupPhase::in");
AutoTimer tm(cleanupPhaseInternalTimer);
// Cleanup optimizations
for (Nodes::const_iterator niter = fg.getNodes().begin(), end = fg.getNodes().end(); niter!=end; ++niter) {
Node* node = *niter;
if (node->isDispatchNode() || node == fg.getReturnNode() || node == fg.getExitNode()) {
continue;
}
Inst *last = (Inst*)node->getLastInst();
if (last->isBranch()) {
if (last->isConditionalBranch()) { // loop peeling for conditional branches
Node *target = ((BranchInst*)last)->getTargetLabel()->getNode();
if (((LabelInst*)target->getFirstInst())->getLabelId() > ((LabelInst*)node->getFirstInst())->getLabelId())
{
LabelInst *targetLabel = ((BranchInst*)last)->getTargetLabel();
Node *fthru = NULL, *taken = NULL;
const Edges& outEdges = node->getOutEdges();
Edges::const_iterator eIter;
for(eIter = outEdges.begin(); eIter != outEdges.end(); ++eIter) {
Edge* edge = *eIter;
Node * tar = edge->getTargetNode();
if (!tar->isDispatchNode()) {
if (tar->getFirstInst() == targetLabel) {
taken = tar;
} else {
fthru = tar;
}
}
}
Inst *takenLdConst = (Inst*)taken->getSecondInst();
Inst *fthruLdConst = (Inst*)fthru->getSecondInst();
Inst *takenStVar = (takenLdConst!=NULL) ? takenLdConst->getNextInst() : NULL;
Inst *fthruStVar = (fthruLdConst!=NULL) ? fthruLdConst->getNextInst() : NULL;
if (takenStVar!=NULL && fthruStVar!=NULL &&
taken->hasOnlyOneSuccEdge() &&
taken->hasOnlyOnePredEdge() &&
fthru->hasOnlyOneSuccEdge() &&
fthru->hasOnlyOnePredEdge() &&
(taken->getOutEdges().front()->getTargetNode() ==
fthru->getOutEdges().front()->getTargetNode()) &&
takenLdConst->getOpcode() == Op_LdConstant &&
fthruLdConst->getOpcode() == Op_LdConstant &&
takenLdConst->getType() == Type::Int32 &&
fthruLdConst->getType() == Type::Int32 &&
takenStVar->getOpcode() == Op_StVar &&
fthruStVar->getOpcode() == Op_StVar &&
takenStVar->getDst() == fthruStVar->getDst() &&
takenStVar->getNextInst() == taken->getLastInst() &&
fthruStVar->getNextInst() == fthru->getLastInst())
{
int takenint32 = ((ConstInst*)takenLdConst)->getValue().i4;
int fthruint32 = ((ConstInst*)fthruLdConst)->getValue().i4;
Node *meet = taken->getOutEdges().front()->getTargetNode();
// find the ldVar for the variable, if any
Inst *meetLdVar = (Inst*)meet->getSecondInst();
while (meetLdVar->getOpcode()==Op_LdVar) {
if (meetLdVar->getSrc(0) == takenStVar->getDst())
break;
meetLdVar = meetLdVar->getNextInst();
}
if ((((takenint32==0) && (fthruint32==1)) ||
((takenint32==1) && (fthruint32==0))) &&
meetLdVar->getOpcode()==Op_LdVar &&
last->getNumSrcOperands()==2) {
// change the instruction to reflect the compare instruction
fg.removeEdge(node,taken);
fg.removeEdge(node,fthru);
fg.addEdge(node,meet);
Opnd* dst = opndManager.createSsaTmpOpnd(meetLdVar->getDst()->getType());
BranchInst *lastBranch = (BranchInst*)last;
if (takenint32==0)
lastBranch->swapTargets(NULL);
Inst *cmp = instFactory.makeCmp(
lastBranch->getComparisonModifier(),
lastBranch->getType(), dst,
lastBranch->getSrc(0),
lastBranch->getSrc(1));
cmp->insertBefore(lastBranch);
Inst* newStVar = instFactory.makeStVar(meetLdVar->getSrc(0)->asVarOpnd(),dst);
newStVar->insertBefore(lastBranch);
lastBranch->unlink();
}
}
}
}
}
// remove trivial basic blocks
if (node->hasOnlyOnePredEdge()) {
Node *pred = node->getInEdges().front()->getSourceNode();
if (!pred->isDispatchNode() && !((Inst*)pred->getLastInst())->isSwitch() &&
(pred->hasOnlyOneSuccEdge() || (node->isEmpty() && node->hasOnlyOneSuccEdge())))
{
// don't merge if the node has an exception edge
Edge *edge = NULL;
Edges::const_iterator eiter;
for(eiter = node->getOutEdges().begin(); eiter != node->getOutEdges().end(); ++eiter) {
edge = *eiter;
if ((edge->getTargetNode())->isDispatchNode()) {
break;
}
}
// If the node has an exception edge, then merging is potentially illegal, so
// skip.
if (edge == NULL) {
if (Log::isEnabled()) {
Log::out()<<" MERGE ";FlowGraph::printLabel(Log::out(), pred);FlowGraph::printLabel(Log::out(), node);Log::out()<<"\n";
Log::out().flush();
}
BranchInst *branch = NULL;
if (!pred->hasOnlyOneSuccEdge() && node->isEmpty()) {
Inst* lastPred = (Inst*)pred->getLastInst();
Node* nodeSucc = node->getOutEdges().front()->getTargetNode();
if (lastPred->isBranch()) {
branch = (BranchInst*)lastPred;
if (branch->getTargetLabel() == node->getFirstInst()) {
branch->replaceTargetLabel((LabelInst*)nodeSucc->getFirstInst());
}
}
}
fg.mergeBlocks(pred,node);
// remove useless branches
if (branch != NULL) {
Node *target = NULL;
for(eiter=pred->getOutEdges().begin(); eiter!=pred->getOutEdges().end();) {
Edge* edge = *eiter;
++eiter;
Node *succ = edge->getTargetNode();
if (! succ->isDispatchNode()) {
if (target == succ) {
fg.removeEdge(pred,succ);
branch->unlink();
break;
}
target = succ;
}
}
}
}
}
}
}
}
// Remove extra PseudoThrow insts
DeadCodeEliminator dce(irm);
dce.removeExtraPseudoThrow();
//process all methods marked with @Inline pragma
if (Log::isLogEnabled(LogStream::IRDUMP)) {
LogStream& irdump = Log::log(LogStream::IRDUMP);
Log::printIRDumpBegin(irdump.out(), id, stage, "before_pragma_inline");
printHIR(irdump.out(), irm.getFlowGraph(), irm.getMethodDesc());
Log::printIRDumpEnd(irdump.out(), id, stage, "before_pragma_inline");
}
Inliner::processInlinePragmas(irm);
//
// a quick cleanup of unreachable and empty basic blocks
//
fg.purgeUnreachableNodes();
fg.purgeEmptyNodes(false);
if (Log::isLogEnabled(LogStream::IRDUMP)) {
LogStream& irdump = Log::log(LogStream::IRDUMP);
Log::printStageEnd(irdump.out(), id, "TRANS", stage, stage);
}
}