blob: b27597056b2a47649d5aff4cc1daebc1067062fa [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, Pavel A. Ozhdikhin
*
*/
#include "Log.h"
#include "optpass.h"
#include "irmanager.h"
#include "Dominator.h"
#include "Loop.h"
#include "./ssa/SSA.h"
#include "EMInterface.h"
#include "optimizer.h"
#include "FlowGraph.h"
#include "StaticProfiler.h"
#include "deadcodeeliminator.h"
#ifdef _WIN32
#define snprintf _snprintf
#endif
namespace Jitrino {
void
OptPass::run()
{
IRManager& irm = *getCompilationContext()->getHIRManager();
id = Log::getStageId();
LogStream& irdump = log(LogStream::IRDUMP);
LogStream& dotdump = log(LogStream::DOTDUMP);
if (irdump.isEnabled()) {
Log::printStageBegin(irdump.out(), id, "HLO", getName(), getTagName());
irdump << indent(irm) << "Opt: Running " << getName() << ::std::endl;
printHIR(irm, "before");
}
if (dotdump.isEnabled()) {
printDotFile(irm, id, getTagName(), "before");
}
_run(irm);
if (dotdump.isEnabled()) {
printDotFile(irm, id, getTagName(), "after");
}
if (irdump.isEnabled()) {
printHIR(irm, "after");
Log::printStageEnd(irdump.out(), id, "HLO", getName(), getTagName());
}
}
void
OptPass::computeDominators(IRManager& irm) {
DominatorTree* dominatorTree = irm.getDominatorTree();
if(dominatorTree != NULL && dominatorTree->isValid()) {
// Already valid.
return;
}
Log::out() << indent(irm) << "Opt: Compute Dominators" << ::std::endl;
static CountTime computeDominatorsTimer("opt::helper::computeDominators");
AutoTimer tm(computeDominatorsTimer);
DominatorBuilder db;
dominatorTree = db.computeDominators(irm.getNestedMemoryManager(), &(irm.getFlowGraph()),false,true);
irm.setDominatorTree(dominatorTree);
}
void
OptPass::computeLoops(IRManager& irm, bool normalize) {
LoopTree* lt = irm.getLoopTree();
if (lt!=NULL && lt->isValid() && (lt->isNormalized() || !normalize)) {
return;
}
Log::out() << indent(irm) << "Opt: Compute Loop Tree" << ::std::endl;
static CountTime computeLoopsTimer("opt::helper::computeLoops");
AutoTimer tm(computeLoopsTimer);
LoopBuilder lb(irm.getNestedMemoryManager(), irm, *(irm.getDominatorTree()),false);
lb.computeLoops(normalize);
if (lb.needSsaFixup()) {
fixupSsa(irm);
}
}
void
OptPass::computeDominatorsAndLoops(IRManager& irm, bool normalizeLoops) {
computeDominators(irm);
computeLoops(irm, normalizeLoops);
computeDominators(irm);
}
void
OptPass::dce(IRManager& irm) {
DeadCodeEliminator dce(irm);
dce.eliminateDeadCode(false);
}
void
OptPass::uce(IRManager& irm, bool fixup_ssa) {
DeadCodeEliminator dce(irm);
dce.eliminateUnreachableCode();
if (irm.getInSsa() && fixup_ssa) {
OptPass::fixupSsa(irm);
}
}
void
OptPass::fixupSsa(IRManager& irm) {
static CountTime fixupSsaTimer("opt::helper::fixupSsa");
static U_32 globalSsaFixupCounter = 0;
if(!irm.isSsaUpdated()) {
AutoTimer tm(fixupSsaTimer);
Log::out() << indent(irm) << "Opt: SSA Fixup" << ::std::endl;
computeDominators(irm);
DominatorTree* dominatorTree = irm.getDominatorTree();
ControlFlowGraph& flowGraph = irm.getFlowGraph();
MemoryManager& memoryManager = irm.getNestedMemoryManager();
DomFrontier frontier(memoryManager,*dominatorTree,&flowGraph);
SSABuilder ssaBuilder(irm.getOpndManager(),irm.getInstFactory(),frontier,&flowGraph, irm.getOptimizerFlags());
bool better_ssa_fixup = irm.getOptimizerFlags().better_ssa_fixup;
ssaBuilder.fixupSSA(irm.getMethodDesc(), better_ssa_fixup);
globalSsaFixupCounter += 1;
irm.setSsaUpdated();
}
}
void
OptPass::splitCriticalEdges(IRManager& irm) {
if(!irm.areCriticalEdgesSplit()) {
Nodes newNodes(irm.getMemoryManager());
irm.getFlowGraph().splitCriticalEdges(false, &newNodes);
for (Nodes::const_iterator it = newNodes.begin(), end = newNodes.end(); it!=end; ++it) {
Node* node = *it;
if(node->isEmpty(false)) {
assert(node->isBlockNode() && !node->isCatchBlock());
node->appendInst(irm.getInstFactory().makeLabel());
}
}
irm.setCriticalEdgesSplit();
}
}
void
OptPass::initialize() {
}
bool
OptPass::isProfileConsistent(IRManager& irm) {
return irm.getFlowGraph().isEdgeProfileConsistent();
}
void
OptPass::smoothProfile(IRManager& irm) {
if (isProfileConsistent(irm) == false) {
StaticProfiler::fixEdgeProbs(irm);
irm.getFlowGraph().smoothEdgeProfile();
}
}
void
OptPass::printHIR(IRManager& irm) {
FlowGraph::printHIR(Log::log(LogStream::IRDUMP).out(), irm.getFlowGraph(), irm.getMethodDesc());
}
void
OptPass::printHIR(IRManager& irm, const char* when) {
std::ostream& out = Log::log(LogStream::IRDUMP).out();
Log::printIRDumpBegin(out, id, getName(), when);
printHIR(irm);
Log::printIRDumpEnd(out, id, getName(), when);
}
void
OptPass::printDotFile(IRManager& irm, int id, const char* name, const char* suffix) {
char temp[128];
snprintf(temp, sizeof(temp), "%.2i.%s.%s", id, name, suffix);
printDotFile(irm, temp);
}
void
OptPass::printDotFile(IRManager& irm, const char* name) {
ControlFlowGraph& flowGraph = irm.getFlowGraph();
FlowGraph::printDotFile(flowGraph, irm.getMethodDesc(), name);
}
const char*
OptPass::indent(IRManager& irm) {
return irm.getParent() == NULL ? "" : " ";
}
} //namespace Jitrino