blob: 1680d6cc75da877817b4ecb402fcc76729573789 [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 Vyacheslav P. Shakin
*/
#include "Ia32IRManager.h"
#include "CodeGenerator_arch.h"
namespace Jitrino
{
namespace Ia32{
/**
class DCE performs Dead code elimination
*/
class DCE : public SessionAction {
public:
void runImpl();
U_32 getSideEffects() const {return 0;}
U_32 getNeedInfo()const {return 0;}
};
static ActionFactory<DCE> _dce("cg_dce");
//========================================================================================
// class DCE
//========================================================================================
//_________________________________________________________________________________________________
void DCE::runImpl()
{
bool early = false;
getArg("early", early);
if (early && !irManager->getCGFlags()->earlyDCEOn) {
return;
}
irManager->updateLivenessInfo();
irManager->calculateOpndStatistics();
BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
const Nodes& nodes = irManager->getFlowGraph()->getNodesPostOrder();
for (Nodes::const_iterator it = nodes.begin(),end = nodes.end();it!=end; ++it) {
Node* node = *it;
if (node->isBlockNode()){
//Here we'll try to remove redundant branches that could appear after
//branch translations. All such branches are supposed to be conditional.
Inst * inst = (Inst *)node->getLastInst();
if(inst && node->getOutEdges().size() > 1) {
Edges edges = node->getOutEdges();
for (Edges::const_iterator ite1 = ++edges.begin(), end = edges.end(); ite1 != end; ++ite1) {
for (Edges::const_iterator ite2 = edges.begin(); ite1 != ite2; ++ite2) {
Edge *edge1 = *ite1;
Edge *edge2 = *ite2;
assert(edge1 != edge2);
//If this condition is satisfied then there are at least two branches with
//the same destination
if (edge1->getTargetNode() == edge2->getTargetNode()) {
//Check that edges are conditional and the last instruction is branch,
//the other situations are not permitted at the moment
assert(inst->hasKind(Inst::Kind_BranchInst));
assert(edge1->getKind() == Edge::Kind_True ||
edge1->getKind() == Edge::Kind_False);
assert(edge2->getKind() == Edge::Kind_True ||
edge2->getKind() == Edge::Kind_False);
//Remove last instruction if it is a branch
inst->unlink();
irManager->getFlowGraph()->removeEdge(edge2);
}
}
}
}
irManager->getLiveAtExit(node, ls);
for (Inst * inst=(Inst*)node->getLastInst(), * prevInst=NULL; inst!=NULL; inst=prevInst){
prevInst=inst->getPrevInst();
// Prevent debug traps or instructions with side effects
// like (MOVS) from being removed.
bool deadInst=!inst->hasSideEffect() && (inst->getMnemonic() != Mnemonic_INT3);
if (deadInst){
if (inst->hasKind(Inst::Kind_CopyPseudoInst)){
Opnd * opnd=inst->getOpnd(1);
if (opnd->getType()->isFP() && opnd->getDefiningInst()!=NULL && opnd->getDefiningInst()->getMnemonic()==Mnemonic_CALL){
deadInst=false;
}
}
if (deadInst){
Inst::Opnds opnds(inst, Inst::OpndRole_All);
for (Inst::Opnds::iterator ito = opnds.begin(); ito != opnds.end(); ito = opnds.next(ito)){
Opnd * opnd = inst->getOpnd(ito);
if ((ls.getBit(opnd->getId()) && (inst->getOpndRoles(ito) & Inst::OpndRole_Def)) ||
(((opnd->getMemOpndKind()&(MemOpndKind_Heap|MemOpndKind_StackManualLayout))!=0) && (inst->getMnemonic() != Mnemonic_LEA))) {
deadInst=false;
break;
}
}
}
}
if (deadInst) {
inst->unlink();
} else {
irManager->updateLiveness(inst, ls);
}
}
irManager->getLiveAtEntry(node)->copyFrom(ls);
}
}
irManager->eliminateSameOpndMoves();
irManager->getFlowGraph()->purgeEmptyNodes();
irManager->getFlowGraph()->mergeAdjacentNodes(true, false);
irManager->getFlowGraph()->purgeUnreachableNodes();
irManager->packOpnds();
irManager->invalidateLivenessInfo();
}
}}; //namespace Ia32