//_________________________________________________________________________________________________ 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(); #ifdef ORDER MemoryManager mm("dce_parents"); U_32 opndCount = irManager->getOpndCount(); bool * isParentOpnd = new(mm) bool [opndCount]; memset(isParentOpnd, 0, sizeof(bool) * opndCount); for (Nodes::const_iterator it = nodes.begin(),end = nodes.end(); it!=end; ++it) { Node* node = *it; for (Inst * inst=(Inst*)node->getLastInst(); inst!=NULL; inst=inst->getPrevInst()) { Opnd* load_obj = inst->getParentObjectLoad(); if (load_obj) { isParentOpnd[load_obj->getId()] = true; } Opnd* store_obj = inst->getParentObjectStore(); if (store_obj) { isParentOpnd[store_obj->getId()] = true; } } } #endif 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); #ifdef ORDER //yzm for (unsigned int i = 0 ; i < inst->getOpndCount() ; i ++) { Opnd* opnd = inst->getOpnd(i); if (isParentOpnd[opnd->getId()]) deadInst = false; } #endif 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(); }
PeepHoleOpt::Changed PeepHoleOpt::handleInst_ALU(Inst* inst) { // The normal form is 'OPERATION left opnd, right operand' // except for NOT operation. const Mnemonic mnemonic = inst->getMnemonic(); if (mnemonic == Mnemonic_NOT) { // No optimizations this time return Changed_Nothing; } // Only these mnemonics have the majestic name of ALUs. assert(mnemonic == Mnemonic_ADD || mnemonic == Mnemonic_SUB || mnemonic == Mnemonic_ADC || mnemonic == Mnemonic_SBB || mnemonic == Mnemonic_OR || mnemonic == Mnemonic_XOR || mnemonic == Mnemonic_AND || mnemonic == Mnemonic_CMP || mnemonic == Mnemonic_TEST); if (mnemonic == Mnemonic_AND) { Inst::Opnds defs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); Opnd* dst = inst->getOpnd(defs.begin()); Inst::Opnds uses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Opnd* src1= inst->getOpnd(uses.begin()); Opnd* src2= inst->getOpnd(uses.next(uses.begin())); Opnd *newopnd2; // test can work only with operands having equal sizes if (isImm(src2) && src2->getSize() != src1->getSize()) newopnd2 = irManager->newImmOpnd(src1->getType(), src2->getImmValue()); else newopnd2 = src2; if (!isMem(dst) && !isMem(src1) && !isMem(src2)) { BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount()); irManager->updateLivenessInfo(); irManager->getLiveAtExit(inst->getNode(), ls); for (Inst* i = (Inst*)inst->getNode()->getLastInst(); i!=inst; i = i->getPrevInst()) { irManager->updateLiveness(i, ls); } bool dstNotUsed = !ls.getBit(dst->getId()); if (dstNotUsed) { // what: AND opnd1, opnd2 => TEST opnd1, opnd2 // nb: applicable if opnd1 will not be used further if (inst->getForm() == Inst::Form_Extended) irManager->newInstEx(Mnemonic_TEST, 0, src1, newopnd2)->insertAfter(inst); else irManager->newInst(Mnemonic_TEST, src1, newopnd2)->insertAfter(inst); inst->unlink(); return Changed_Inst; } } } else if (mnemonic == Mnemonic_ADD) { /* Change "dst=src+0" to "MOV dst, src" if there is another ADD inst followed in the same BB. */ Inst::Opnds defs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); Opnd* dst = inst->getOpnd(defs.begin()); Inst::Opnds uses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Opnd* src1= inst->getOpnd(uses.begin()); Opnd* src2= inst->getOpnd(uses.next(uses.begin())); bool src1IsZero = false; bool src2IsZero = false; if (src1->isPlacedIn(OpndKind_Imm) && (src1->getImmValue() == 0)) src1IsZero = true; if (src2->isPlacedIn(OpndKind_Imm) && (src2->getImmValue() == 0)) src2IsZero = true; bool anotherADD = false; Inst *iter = inst->getNextInst(); while (iter != NULL) { if (iter->getMnemonic() == Mnemonic_ADC) break; if (iter->getMnemonic() == Mnemonic_ADD) { anotherADD = true; break; } iter = iter->getNextInst();; } if (anotherADD) { if (src1IsZero) { irManager->newCopyPseudoInst(Mnemonic_MOV, dst, src2)->insertAfter(inst); inst->unlink(); return Changed_Inst; } else if (src2IsZero) { irManager->newCopyPseudoInst(Mnemonic_MOV, dst, src1)->insertAfter(inst); inst->unlink(); return Changed_Inst; } } } return Changed_Nothing; }
//___________________________________________________________________________________________________ void EarlyPropagation::runImpl() { irManager->updateLoopInfo(); U_32 opndCount=irManager->getOpndCount(); MemoryManager mm("early_prop"); OpndInfo * opndInfos = new(mm) OpndInfo[opndCount]; Node * currentLoopHeader = NULL; bool anyInstHandled=false; LoopTree* lt = irManager->getFlowGraph()->getLoopTree(); const Nodes& postOrdered = irManager->getFlowGraph()->getNodesPostOrder(); for (Nodes::const_reverse_iterator it = postOrdered.rbegin(), end = postOrdered.rend(); it!=end; ++it) { Node * node=*it; if (!node->isBlockNode()) { continue; } Node * loopHeader = lt->getLoopHeader(node, false); if (currentLoopHeader != loopHeader){ currentLoopHeader = loopHeader; for (U_32 i = 0; i < opndCount; ++i) if (opndInfos[i].sourceOpndId != EmptyUint32) opndInfos[i].defCount++; } for (Inst * inst = (Inst*)node->getFirstInst(); inst != NULL; inst=inst->getNextInst()){ bool assignedOpndPropagated = false; Inst::Opnds opnds(inst, Inst::OpndRole_All); for (Inst::Opnds::iterator it = opnds.begin(); it != opnds.end(); it = opnds.next(it)){ Opnd * opnd=inst->getOpnd(it); U_32 roles=inst->getOpndRoles(it); U_32 opndId = opnd->getId(); OpndInfo& opndInfo = opndInfos[opndId]; U_32 mask = 0; if (roles & Inst::OpndRole_Def){ ++opndInfo.defCount; }else if (roles & Inst::OpndRole_Use){ if (opndInfo.sourceOpndId != EmptyUint32){ if (opndInfo.sourceOpndDefCountAtCopy < opndInfos[opndInfo.sourceOpndId].defCount) opndInfo.sourceOpndId = EmptyUint32; else{ Opnd * srcOpnd = irManager->getOpnd(opndInfo.sourceOpndId); Constraint co = srcOpnd->getConstraint(Opnd::ConstraintKind_Location); if (co.getKind() == OpndKind_Mem){ mask = (1<<it)-1; if ((roles & Inst::OpndRole_Explicit) == 0 || inst->hasKind(Inst::Kind_PseudoInst) || irManager->isGCSafePoint(inst) || opndInfo.sourceInst != inst->getPrevInst() || assignedOpndPropagated || (inst->getConstraint(it, mask, co.getSize())&co).isNull() ) opndInfo.sourceOpndId = EmptyUint32; assignedOpndPropagated = true; } } } } if (opndInfo.defCount > 1){ opndInfo.sourceOpndId = EmptyUint32; } } /* Here is the previous version to test whether the inst is copy or not. bool isCopy = inst->getMnemonic() == Mnemonic_MOV ||( (inst->getMnemonic() == Mnemonic_ADD || inst->getMnemonic() == Mnemonic_SUB) && inst->getOpnd(3)->isPlacedIn(OpndKind_Imm) && inst->getOpnd(3)->getImmValue()==0 && inst->getOpnd(3)->getRuntimeInfo()==NULL ); It considered special case of 'dst = src +/- 0' as copy. In fact there are more similar cases like 'IMUL src, 1 ; shift src, 0' etc. Such checks are obsolete now, Should as peephole takes care about such copies. Anyway, the code above had a bug: 'inst->getOpnd(3)' crashes in instructions in native form (like ADD def_use, use). */ const bool isCopy = inst->getMnemonic() == Mnemonic_MOV; if (isCopy){ // CopyPseudoInst or mov Opnd * defOpnd = inst->getOpnd(0); Opnd * srcOpnd = inst->getOpnd(1); U_32 defOpndId = defOpnd->getId(); OpndInfo * opndInfo = opndInfos + defOpndId; bool instHandled=false; bool typeConvOk = isTypeConversionAllowed(srcOpnd, defOpnd); if (typeConvOk && opndInfo->defCount == 1 && ! srcOpnd->isPlacedIn(OpndKind_Reg)){ if (!defOpnd->hasAssignedPhysicalLocation()){ opndInfo->sourceInst = inst; opndInfo->sourceOpndId = srcOpnd->getId(); instHandled=true; } } if (instHandled){ if (opndInfos[opndInfo->sourceOpndId].sourceOpndId != EmptyUint32) opndInfo->sourceOpndId = opndInfos[opndInfo->sourceOpndId].sourceOpndId; opndInfo->sourceOpndDefCountAtCopy = opndInfos[opndInfo->sourceOpndId].defCount; anyInstHandled=true; } } } } if (anyInstHandled){ Opnd ** replacements = new(mm) Opnd* [opndCount]; memset(replacements, 0, sizeof(Opnd*) * opndCount); bool hasReplacements = false; for (U_32 i = 0; i < opndCount; ++i){ if (opndInfos[i].sourceOpndId != EmptyUint32){ Inst * inst = opndInfos[i].sourceInst; if (inst !=NULL){ inst->unlink(); } if (opndInfos[i].sourceOpndId != i){ Opnd* origOpnd= irManager->getOpnd(i); Opnd* replacementOpnd = irManager->getOpnd(opndInfos[i].sourceOpndId); assert(isTypeConversionAllowed(replacementOpnd, origOpnd)); if (origOpnd->getType()->isUnmanagedPtr() && replacementOpnd->getType()->isInteger()) { replacementOpnd->setType(origOpnd->getType()); }/* else if (origOpnd->getType()->isObject() && replacementOpnd->getType()->isUnmanagedPtr()) { replacementOpnd->setType(origOpnd->getType()); }*/ replacements[i] = replacementOpnd; hasReplacements = true; } } } if (hasReplacements){ const Nodes& postOrdered = irManager->getFlowGraph()->getNodesPostOrder(); for (Nodes::const_reverse_iterator it = postOrdered.rbegin(), end = postOrdered.rend(); it!=end; ++it) { Node * node=*it; if (!node->isBlockNode()) { continue; } for (Inst * inst = (Inst*)node->getFirstInst(); inst != NULL; inst=inst->getNextInst()){ inst->replaceOpnds(replacements); } } } } }
/** * Executes lazy exception optimization pass. */ void LazyExceptionOpt::doLazyExceptionOpt() { MethodDesc &md = irManager.getMethodDesc(); BitSet excOpnds(leMemManager,irManager.getOpndManager().getNumSsaOpnds()); StlDeque<Inst*> candidateSet(leMemManager); optCandidates = new (leMemManager) OptCandidates(leMemManager); Method_Side_Effects m_sideEff = md.getSideEffect(); const Nodes& nodes = irManager.getFlowGraph().getNodes(); Nodes::const_iterator niter; #ifdef _DEBUG mtdDesc=&md; #endif #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << std::endl; for (int i=0; i<level; i++) Log::out() << " "; Log::out() << "doLE "; md.printFullName(Log::out()); Log::out() << " SideEff " << (int)m_sideEff << std::endl; } #endif level++; U_32 opndId = 0; isArgCheckNull = false; isExceptionInit = md.isInstanceInitializer() && md.getParentType()->isLikelyExceptionType(); // core api exception init if (m_sideEff == MSE_Unknown && isExceptionInit && strncmp(md.getParentType()->getName(),"java/lang/",10) == 0) { m_sideEff = MSE_False; md.setSideEffect(m_sideEff); #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << " core api exc "; md.printFullName(Log::out()); Log::out() << " SideEff " << (int)m_sideEff << std::endl; } #endif } for(niter = nodes.begin(); niter != nodes.end(); ++niter) { Node* node = *niter; Inst *headInst = (Inst*)node->getFirstInst(); for (Inst* inst=headInst->getNextInst(); inst!=NULL; inst=inst->getNextInst()) { #ifdef _DEBUG if (inst->getOpcode()==Op_DefArg && isExceptionInit) { if (Log::isEnabled()) { Log::out() << " defarg: "; inst->print(Log::out()); Log::out() << std::endl; Log::out() << " "; Log::out() << (int)(inst->getDefArgModifier()) << " " << (inst->getDefArgModifier()==DefArgNoModifier) << " " << (inst->getDefArgModifier()==NonNullThisArg) << " " << (inst->getDefArgModifier()==SpecializedToExactType) << " " << (inst->getDefArgModifier()==DefArgBothModifiers) << std::endl; } } #endif if (inst->getOpcode()==Op_Throw) { if (inst->getSrc(0)->getInst()->getOpcode()==Op_NewObj) { excOpnds.setBit(opndId=inst->getSrc(0)->getId(),true); if (!addOptCandidates(opndId,inst)) excOpnds.setBit(opndId,false); // different exc. edges #ifdef _DEBUG if (excOpnds.getBit(opndId)==1) { if (Log::isEnabled()) { Log::out() << " add opnd: "; inst->print(Log::out()); Log::out() << std::endl; Log::out() << " add obj: "; inst->getSrc(0)->getInst()->print(Log::out()); Log::out() << std::endl; } } #endif } } if (m_sideEff == MSE_Unknown) if (instHasSideEffect(inst)) { m_sideEff = MSE_True; #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << "~~~~~~inst sideEff "; inst->print(Log::out()); Log::out() << std::endl; } #endif } } } if (md.getSideEffect() == MSE_Unknown) { if (m_sideEff == MSE_Unknown) { if (isExceptionInit && isArgCheckNull) { #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << "~~~~~~init sideEff reset: " << m_sideEff << " 3 "; md.printFullName(Log::out()); Log::out() << std::endl; } #endif m_sideEff = MSE_True_Null_Param; } else m_sideEff = MSE_False; } md.setSideEffect(m_sideEff); } for(niter = nodes.begin(); niter != nodes.end(); ++niter) { Node* node = *niter; Inst *headInst = (Inst*)node->getFirstInst(); Opnd* opnd; for (Inst* inst=headInst->getNextInst(); inst!=NULL; inst=inst->getNextInst()) { U_32 nsrc = inst->getNumSrcOperands(); for (U_32 i=0; i<nsrc; i++) { if (!(opnd=inst->getSrc(i))->isSsaOpnd()) // check ssa operands continue; if (excOpnds.getBit(opndId=opnd->getId())==0) continue; if (inst->getOpcode()==Op_DirectCall) { MethodDesc* md = inst->asMethodInst()->getMethodDesc(); if (md->isInstanceInitializer() && md->getParentType()->isLikelyExceptionType()) { if (!addOptCandidates(opndId,inst)) { excOpnds.setBit(opndId,false); #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << " - rem opnd " << opnd->getId() << " "; inst->print(Log::out()); Log::out() << std::endl; } #endif } } else { excOpnds.setBit(opndId,false); #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << " -- rem opnd " << opnd->getId() << " "; inst->print(Log::out()); Log::out() << std::endl; } #endif } } else { if (inst->getOpcode()!=Op_Throw) { excOpnds.setBit(opndId,false); #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << " rem opnd " << opnd->getId() << " "; inst->print(Log::out()); Log::out() << std::endl; } #endif } } } } } if (!excOpnds.isEmpty()) { #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << "------LE: "; md.printFullName(Log::out()); Log::out() << std::endl; } #endif fixOptCandidates(&excOpnds); } level--; #ifdef _DEBUG if (Log::isEnabled()) { for (int i=0; i<level; i++) Log::out() << " "; Log::out() << "done "; md.printFullName(Log::out()); Log::out() << " SideEff " << (int)m_sideEff << std::endl; } #endif };