void SSABuilder::deconvertSSA(ControlFlowGraph* fg,OpndManager& opndManager) { const Nodes& nodes = fg->getNodes(); Nodes::const_iterator niter; for(niter = nodes.begin(); niter != nodes.end(); ++niter) { Node* node = *niter; Inst *headInst = (Inst*)node->getFirstInst(); for (Inst *inst = headInst->getNextInst(); inst != NULL; ) { Inst *nextInst = inst->getNextInst(); if (inst->isPhi()) { inst->unlink(); } else { for (U_32 i = 0; i < inst->getNumSrcOperands(); i++) { Opnd *opnd = inst->getSrc(i); if (opnd->isSsaVarOpnd()) { SsaVarOpnd *ssa = (SsaVarOpnd *)opnd; VarOpnd *var = ssa->getVar(); inst->setSrc(i,var); } else if (opnd->isVarOpnd()) { } } Opnd *dst = inst->getDst(); if (dst->isSsaVarOpnd()) { SsaVarOpnd *ssa = (SsaVarOpnd *)dst; inst->setDst(ssa->getVar()); } } inst = nextInst; } } }
void OSR::replace(SsaOpnd* opnd, SsaOpnd* iv, SsaOpnd* rc) { Inst* inst = opnd->getInst(); SsaOpnd* dstInst = reduce(inst->getDst()->getType(), inst->getOpcode(), inst->getOperation(), iv, rc); Inst* copyInst = irManager.getInstFactory().makeCopy(opnd, dstInst); copyInst->insertBefore(inst); inst->unlink(); writeLeadingOperand(opnd, getLeadingOperand(iv)); }
void SSABuilder::checkForTrivialPhis2(Node *node, const StlVectorSet<VarOpnd *> *lookatVars, StlVector<VarOpnd *> *changedVars, StlVector<Opnd *> *removedVars) { // Check that phi insts can start from the second or third position only // and goes in a row assert(phiInstsOnRightPositionsInBB(node)); Inst* phi = (Inst*)node->getSecondInst(); if(phi && !phi->isPhi()) { // try the next one (third) phi = phi->getNextInst(); } Inst *nextphi = NULL; #ifdef DEBUG_SSA if (Log::isEnabled()) { Log::out() << "Checking node " << (int)node->getId() << " for trivial phis2" << ::std::endl; } #endif for (;phi->isPhi(); phi = nextphi) { nextphi = phi->getNextInst(); #ifdef _DEBUG PhiInst *phiInst = phi->asPhiInst(); assert(phiInst); #endif U_32 nSrcs = phi->getNumSrcOperands(); if (nSrcs <= 1) { // phi must be trivial #ifdef DEBUG_SSA ::std::ostream &cout = Log::out(); if (Log::isEnabled()) { cout << "removing trivial2 instruction "; phi->print(cout); cout << ::std::endl; } #endif Opnd *dstOp = phi->getDst(); VarOpnd *varOp = dstOp->asVarOpnd(); if (!varOp) { SsaVarOpnd *ssaOp = dstOp->asSsaVarOpnd(); assert(ssaOp); varOp = ssaOp->getVar(); } assert(!lookatVars || (lookatVars->has(varOp))); changedVars->push_back(varOp); removedVars->push_back(dstOp); phi->unlink(); } } }
//_________________________________________________________________________________________________ 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(); }
//___________________________________________________________________________________________________ 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); } } } } }
Node * JavaFlowGraphBuilder::edgesForBlock(Node* block) { // // find if this block has any region that could catch the exception // Node *dispatch = NULL; ExceptionInfo *exceptionInfo = (CatchBlock*)((LabelInst*)block->getFirstInst())->getState(); if (exceptionInfo != NULL) { dispatch = exceptionInfo->getLabelInst()->getNode(); }else{ dispatch = fg->getUnwindNode(); } assert(dispatch->isDispatchNode()); // // split the block so that // each potentially-exceptional instruction ends a block // Inst* first = (Inst*)block->getFirstInst(); Inst* last = (Inst*)block->getLastInst(); Inst* lastExceptionalInstSeen = NULL; for (Inst* inst = first->getNextInst(); inst != NULL; inst = inst->getNextInst()) { if (lastExceptionalInstSeen != NULL) { // start a new basic block LabelInst* label = irBuilder.getInstFactory()->makeLabel(); Node *newblock = createBlockNodeAfter(block, label); uint16 bcOffset = ILLEGAL_BC_MAPPING_VALUE; for (Inst *ins = lastExceptionalInstSeen->getNextInst(), *nextIns = NULL; ins!=NULL; ins = nextIns) { nextIns = ins->getNextInst(); ins->unlink(); newblock->appendInst(ins); if (bcOffset == ILLEGAL_BC_MAPPING_VALUE) { bcOffset = ins->getBCOffset(); } } label->setBCOffset(bcOffset); // now fix up the CFG, duplicating edges if (!lastExceptionalInstSeen->isThrow()) fg->addEdge(block,newblock); // // add an edge to handler entry node // assert(!block->findTargetEdge(dispatch)); fg->addEdge(block,dispatch); block = newblock; lastExceptionalInstSeen = NULL; } if (inst->getOperation().canThrow()) { lastExceptionalInstSeen = inst; } } // // examine the last instruction and create appropriate CFG edges // switch(last->getOpcode()) { case Op_Jump: { fg->addEdge(block,((BranchInst*)last)->getTargetLabel()->getNode()); last->unlink(); } break; case Op_Branch: case Op_JSR: addEdge(block, ((BranchInst*)last)->getTargetLabel()->getNode()); edgeForFallthrough(block); break; case Op_Throw: case Op_ThrowSystemException: case Op_ThrowLinkingException: // throw/rethrow creates an edge to a handler that catches the exception assert(dispatch != NULL); assert(lastExceptionalInstSeen == last); break; case Op_Return: addEdge(block, fg->getReturnNode()); break; case Op_Ret: break; // do not do anything case Op_Switch: { SwitchInst *sw = (SwitchInst*)last; U_32 num = sw->getNumTargets(); for (U_32 i = 0; i < num; i++) { Node* target = sw->getTarget(i)->getNode(); // two switch values may go to the same block if (!block->findTargetEdge(target)) { fg->addEdge(block,target); } } Node* target = sw->getDefaultTarget()->getNode(); if (!block->findTargetEdge(target)) { fg->addEdge(block,target); } } break; default:; if (block != fg->getReturnNode()) { // a fallthrough edge is needed // if the basic block does not have any outgoing edge, add one fall through edge if (block->getOutEdges().empty()) edgeForFallthrough(block); } } // // add an edge to handler entry node // if (lastExceptionalInstSeen != NULL) addEdge(block,dispatch); return block; }
void CfgCodeSelector::fixNodeInfo() { MemoryManager tmpMM("Ia32CS:fixNodeInfoMM"); ControlFlowGraph* fg = irManager.getFlowGraph(); Nodes nodes(tmpMM); fg->getNodes(nodes); //copy nodes -> loop creates new ones, so we can't use reference to cfg->getNodes() for (Nodes::const_iterator it = nodes.begin(), end = nodes.end(); it!=end; ++it) { Node* node = *it; // connect throw nodes added during inst code selection to corresponding dispatch or unwind nodes if (node->isBlockNode()){ Inst * lastInst = (Inst*)node->getLastInst(); if (lastInst) { Inst * prevInst = lastInst->getPrevInst(); if(prevInst && prevInst->getKind() == Inst::Kind_BranchInst) { Edge * ftEdge = node->getFalseEdge(); Edge * dbEdge = node->getTrueEdge(); assert(ftEdge && dbEdge); Node* newBB = fg->createBlockNode(); Node* nextFT = ftEdge->getTargetNode(); Node* nextDB = dbEdge->getTargetNode(); fg->removeEdge(ftEdge); fg->removeEdge(dbEdge); newBB->appendInst(irManager.newBranchInst(lastInst->getMnemonic(), nextDB, nextFT)); lastInst->unlink(); //now fix prev branch successors BranchInst* prevBranch = (BranchInst*)prevInst; assert(prevBranch->getTrueTarget() == NULL && prevBranch->getFalseTarget() == NULL); prevBranch->setTrueTarget(lastInst->getMnemonic() == Mnemonic_JZ? nextFT : nextDB); prevBranch->setFalseTarget(newBB); fg->addEdge(node, lastInst->getMnemonic() == Mnemonic_JZ? nextFT : nextDB, 0); fg->addEdge(node, newBB, 0); fg->addEdge(newBB, nextDB, 0); fg->addEdge(newBB, nextFT, 0); } } if (node->getOutDegree() == 0){ // throw node assert(node->getInDegree()==1); Node* bbIn = node->getInEdges().front()->getSourceNode(); assert(bbIn!=NULL); Node * target=bbIn->getExceptionEdgeTarget(); assert(target!=NULL); fg->addEdge(node, target, 1.0); } // fixup empty catch blocks otherwise respective catchEdges will be lost // There is no [catchBlock]-->[catchHandler] edge. Catch block will be removed // as an empty one and exception handling will be incorrect if (node->isCatchBlock() && node->isEmpty()) { assert(node->getInDegree()==1); Edge* catchEdge = node->getInEdges().front(); assert(catchEdge->getSourceNode()->isDispatchNode()); assert(node->getOutDegree()==1); Node* succ = node->getUnconditionalEdgeTarget(); while( succ->isEmpty() && (succ->getOutDegree() == 1) ) { succ = succ->getUnconditionalEdgeTarget(); } assert(succ && ((Inst*)succ->getFirstInst())->hasKind(Inst::Kind_CatchPseudoInst)); fg->replaceEdgeTarget(catchEdge,succ,true/*keepOldBody*/); } } } }
PeepHoleOpt::Changed PeepHoleOpt::handleInst_SETcc(Inst* inst) { if (((BasicBlock*)inst->getNode())->getLayoutSucc() == NULL) { Mnemonic mn = inst->getMnemonic(); Inst* prev = inst->getPrevInst(); Inst *next = inst->getNextInst(); Node *currNode = inst->getNode(); bool methodMarkerOccur = false; MethodMarkerPseudoInst* methodMarker = NULL; // ignoring instructions that have no effect and saving method markers to correct them during optimizations while (next == NULL || next->getKind() == Inst::Kind_MethodEndPseudoInst || next->getMnemonic() == Mnemonic_JMP) { if (next == NULL) { currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode(); if (currNode->getKind() == Node::Kind_Exit) return Changed_Nothing; next = (Inst*) currNode->getFirstInst(); } else { if (next->getKind() == Inst::Kind_MethodEndPseudoInst) { //max 1 saved method marker if (methodMarkerOccur) { return Changed_Nothing; } methodMarker = (MethodMarkerPseudoInst*)next; methodMarkerOccur = true; } next = next->getNextInst(); } } Inst *next2 = next->getNextInst(); bool step1 = true; currNode = inst->getNode(); while (currNode != next->getNode()) { currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode(); if (currNode->getInDegree()!=1) { step1 = false; break; } } // step1: // ------------------------------------------ // MOV opnd, 0 MOV opnd2, 0 // SETcc opnd -> SETcc opnd2 // MOV opnd2, opnd // ------------------------------------------ // nb: applicable if opnd will not be used further if (step1 && prev!= NULL && prev->getMnemonic() == Mnemonic_MOV && next!= NULL && next->getMnemonic() == Mnemonic_MOV) { Opnd *prevopnd1, *prevopnd2, *nextopnd1, *nextopnd2, *setopnd; if (prev->getKind() == Inst::Kind_CopyPseudoInst) { prevopnd1 = prev->getOpnd(0); prevopnd2 = prev->getOpnd(1); } else { Inst::Opnds prevuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds prevdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def); prevopnd1 = prev->getOpnd(prevdefs.begin()); prevopnd2 = prev->getOpnd(prevuses.begin()); } if (next->getKind() == Inst::Kind_CopyPseudoInst) { nextopnd1 = next->getOpnd(0); nextopnd2 = next->getOpnd(1); } else { Inst::Opnds nextuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds nextdefs(next, Inst::OpndRole_Explicit|Inst::OpndRole_Def); nextopnd1 = next->getOpnd(nextdefs.begin()); nextopnd2 = next->getOpnd(nextuses.begin()); } Inst::Opnds setdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); setopnd = inst->getOpnd(setdefs.begin()); if (isReg(nextopnd1) && prevopnd1->getId() == setopnd->getId() && setopnd->getId() == nextopnd2->getId() && isImm(prevopnd2) && prevopnd2->getImmValue() == 0 ) { BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount()); irManager->updateLivenessInfo(); irManager->getLiveAtExit(next->getNode(), ls); for (Inst* i = (Inst*)next->getNode()->getLastInst(); i!=next; i = i->getPrevInst()) { irManager->updateLiveness(i, ls); } bool opndNotUsed = !ls.getBit(setopnd->getId()); if (opndNotUsed) { if (nextopnd1->getRegName() != RegName_Null && Constraint::getAliasRegName(nextopnd1->getRegName(), OpndSize_8) == RegName_Null) { nextopnd1->assignRegName(setopnd->getRegName()); } irManager->newInst(Mnemonic_MOV, nextopnd1, prevopnd2)->insertBefore(inst); irManager->newInst(mn, nextopnd1)->insertBefore(inst); prev->unlink(); inst->unlink(); next->unlink(); return Changed_Node; } } } // step2: // -------------------------------------------------------------- // MOV opnd, 0 Jcc smwh Jcc smwh // SETcc opnd -> BB1: v BB1: // CMP opnd, 0 ... // Jcc smwh CMP opnd, 0 // BB1: Jcc smwh // -------------------------------------------------------------- // nb: applicable if opnd will not be used further // nb: conditions of new jumps are calculated from conditions of old jump and set instructions if (prev!= NULL && prev->getMnemonic() == Mnemonic_MOV && next!= NULL && (next->getMnemonic() == Mnemonic_CMP || next->getMnemonic() == Mnemonic_TEST) && next2!= NULL && (next2->getMnemonic() == Mnemonic_JG || next2->getMnemonic() == Mnemonic_JE || next2->getMnemonic() == Mnemonic_JNE) ) { Opnd* movopnd1; Opnd* movopnd2; if (prev->getKind() == Inst::Kind_CopyPseudoInst) { movopnd1 = prev->getOpnd(0); movopnd2 = prev->getOpnd(1); } else { Inst::Opnds movuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds movdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def); movopnd1 = prev->getOpnd(movdefs.begin()); movopnd2 = prev->getOpnd(movuses.begin()); } Inst::Opnds cmpuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Opnd* cmpopnd1 = next->getOpnd(cmpuses.begin()); Opnd* cmpopnd2 = next->getOpnd(cmpuses.next(cmpuses.begin())); if ( isImm(movopnd2) && movopnd2->getImmValue() == 0 && movopnd1->getId() == cmpopnd1->getId() && //case CMP: (next->getMnemonic() != Mnemonic_CMP || (isImm(cmpopnd2) && cmpopnd2->getImmValue() == 0)) && //case TEST: (next->getMnemonic() != Mnemonic_TEST || cmpopnd1->getId() == cmpopnd2->getId()) ) { BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount()); irManager->updateLivenessInfo(); irManager->getLiveAtExit(next2->getNode(), ls); bool opndNotUsed = !ls.getBit(movopnd1->getId()); if (opndNotUsed) { BranchInst* br = (BranchInst*) next2; Mnemonic newjumpmn = Mnemonic_JZ; if (next2->getMnemonic() == Mnemonic_JE) { switch (mn) { case Mnemonic_SETG: newjumpmn = Mnemonic_JLE; break; case Mnemonic_SETE: newjumpmn = Mnemonic_JNE; break; case Mnemonic_SETL: newjumpmn = Mnemonic_JGE; break; case Mnemonic_SETNE: newjumpmn = Mnemonic_JE; break; default: assert(0); break; } } else { switch (mn) { case Mnemonic_SETG: newjumpmn = Mnemonic_JG; break; case Mnemonic_SETE: newjumpmn = Mnemonic_JE; break; case Mnemonic_SETL: newjumpmn = Mnemonic_JL; break; case Mnemonic_SETNE: newjumpmn = Mnemonic_JNE; break; default: assert(0); break; } } if (inst->getNode()->getId() != next->getNode()->getId()) { ControlFlowGraph* cfg = irManager->getFlowGraph(); cfg->removeEdge(inst->getNode()->getOutEdge(Edge::Kind_Unconditional)); double trueEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_True)->getEdgeProb(); double falseEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_False)->getEdgeProb(); cfg->addEdge(inst->getNode(), br->getTrueTarget(), trueEdgeProb); cfg->addEdge(inst->getNode(), br->getFalseTarget(), falseEdgeProb); irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(inst); if (methodMarkerOccur) { inst->getNode()->appendInst(irManager->newMethodEndPseudoInst(methodMarker->getMethodDesc())); } prev->unlink(); inst->unlink(); cfg->purgeUnreachableNodes(); } else { irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(next2); prev->unlink(); inst->unlink(); next->unlink(); next2->unlink(); } return Changed_Node; }// endif opndNotUsed } } } return Changed_Nothing; }
PeepHoleOpt::Changed PeepHoleOpt::handleInst_MOV(Inst* inst) { Node* node = inst->getNode(); if (((BasicBlock*)node)->getLayoutSucc() == NULL) { Inst *next = inst->getNextInst(); Node *currNode = node; bool methodMarkerOccur = false; MethodMarkerPseudoInst* methodMarker = NULL; // ignoring instructions that have no effect and saving method markers to correct them during optimizations while (next == NULL || next->getKind() == Inst::Kind_MethodEndPseudoInst || next->getMnemonic() == Mnemonic_JMP) { if (next == NULL) { currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode(); if (currNode->getKind() == Node::Kind_Exit) return Changed_Nothing; next = (Inst*) currNode->getFirstInst(); } else { if (next->getKind() == Inst::Kind_MethodEndPseudoInst) { //max 1 saved method marker if (methodMarkerOccur) { return Changed_Nothing; } methodMarker = (MethodMarkerPseudoInst*)next; methodMarkerOccur = true; } next = next->getNextInst(); } } Inst *jump = next->getNextInst(); bool step1 = true; currNode = node; while (currNode != next->getNode()) { currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode(); if (currNode->getInDegree()!=1) { step1 = false; break; } } // step1: // --------------------------------------------- // MOV opnd, opnd2 MOV opnd3, opnd2 // MOV opnd3, opnd -> // --------------------------------------------- // nb: applicable if opnd will not be used further if (step1 && next->getMnemonic() == Mnemonic_MOV) { Opnd *movopnd1, *movopnd2, *nextmovopnd1, *nextmovopnd2; bool isInstCopyPseudo = (inst->getKind() == Inst::Kind_CopyPseudoInst); if (isInstCopyPseudo) { movopnd1 = inst->getOpnd(0); movopnd2 = inst->getOpnd(1); } else { Inst::Opnds movuses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds movdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); movopnd1 = inst->getOpnd(movdefs.begin()); movopnd2 = inst->getOpnd(movuses.begin()); } bool isNextCopyPseudo = (next->getKind() == Inst::Kind_CopyPseudoInst); if (isNextCopyPseudo) { nextmovopnd1 = next->getOpnd(0); nextmovopnd2 = next->getOpnd(1); } else { Inst::Opnds nextmovuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds nextmovdefs(next, Inst::OpndRole_Explicit|Inst::OpndRole_Def); nextmovopnd1 = next->getOpnd(nextmovdefs.begin()); nextmovopnd2 = next->getOpnd(nextmovuses.begin()); } if (movopnd1->getId() == nextmovopnd2->getId() && !isMem(movopnd2) && !isMem(nextmovopnd1) && !isMem(movopnd1) ) { BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount()); irManager->updateLivenessInfo(); irManager->getLiveAtExit(next->getNode(), ls); for (Inst* i = (Inst*)next->getNode()->getLastInst(); i!=next; i = i->getPrevInst()) { irManager->updateLiveness(i, ls); } bool dstNotUsed = !ls.getBit(movopnd1->getId()); if (dstNotUsed) { if (isInstCopyPseudo && isNextCopyPseudo) irManager->newCopyPseudoInst(Mnemonic_MOV, nextmovopnd1, movopnd2)->insertAfter(inst); else irManager->newInst(Mnemonic_MOV, nextmovopnd1, movopnd2)->insertAfter(inst); inst->unlink(); next->unlink(); return Changed_Node; } } } // step2: // -------------------------------------------------------------- // MOV opnd, 0/1 Jmp smwh/BB1 Jmp smwh/BB1 // CMP opnd, 0 -> CMP opnd, 0 v // Jcc smwh Jcc smwh // BB1: BB1: // -------------------------------------------------------------- // nb: applicable if opnd will not be used further if (next->getMnemonic() == Mnemonic_CMP && jump!= NULL && (jump->getMnemonic() == Mnemonic_JE || jump->getMnemonic() == Mnemonic_JNE)) { Opnd *movopnd1, *movopnd2; if (inst->getKind() == Inst::Kind_CopyPseudoInst) { movopnd1 = inst->getOpnd(0); movopnd2 = inst->getOpnd(1); } else { Inst::Opnds movuses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Inst::Opnds movdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def); movopnd1 = inst->getOpnd(movdefs.begin()); movopnd2 = inst->getOpnd(movuses.begin()); } Inst::Opnds cmpuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use); Opnd* cmpopnd1 = next->getOpnd(cmpuses.begin()); Opnd* cmpopnd2 = next->getOpnd(cmpuses.next(cmpuses.begin())); if (isImm(movopnd2) && (movopnd2->getImmValue() == 0 || movopnd2->getImmValue() == 1) && movopnd1->getId() == cmpopnd1->getId() && isImm(cmpopnd2) && cmpopnd2->getImmValue() == 0) { BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount()); irManager->updateLivenessInfo(); irManager->getLiveAtExit(jump->getNode(), ls); bool opndNotUsed = !ls.getBit(movopnd1->getId()); if (opndNotUsed) { ControlFlowGraph* cfg = irManager->getFlowGraph(); Node* destination = ((BranchInst*)jump)->getTrueTarget(); if ((jump->getMnemonic() == Mnemonic_JNE || movopnd2->getImmValue() == 1) && !(jump->getMnemonic() == Mnemonic_JNE && movopnd2->getImmValue() == 1)) { destination = ((BranchInst*)jump)->getFalseTarget(); } if (node->getId() != next->getNode()->getId()) { if (methodMarkerOccur) { inst->getNode()->appendInst(irManager->newMethodEndPseudoInst(methodMarker->getMethodDesc())); } inst->unlink(); Edge *outEdge = node->getOutEdge(Edge::Kind_Unconditional); cfg->replaceEdgeTarget(outEdge, destination, true); cfg->purgeUnreachableNodes(); // previous successor may become unreachable } else { cfg->removeEdge(node->getOutEdge(Edge::Kind_True)); cfg->removeEdge(node->getOutEdge(Edge::Kind_False)); cfg->addEdge(node, destination); inst->unlink(); next->unlink(); jump->unlink(); } return Changed_Node; } } } } return Changed_Nothing; }
/** * Checks that exception edges are equal for newobj instruction node and * throw instruction node. * @param bs - bit set of operands that may be optimized */ void LazyExceptionOpt::fixOptCandidates(BitSet* bs) { OptCandidates::iterator it; Inst* oinst; MethodCallInst* iinst; Inst* tinst; Inst* tlinst; U_32 opcount; Opnd **opnds = NULL; if (optCandidates == NULL) { return; } for (it = optCandidates->begin( ); it != optCandidates->end( ); it++ ) { if (bs->getBit((*it)->opndId)) { oinst = (*it)->objInst; assert(oinst != NULL); #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << " to remove "; oinst->print(Log::out()); Log::out() << std::endl; } #endif if ((*it)->initInst == NULL) { #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << " init inst is null "; Log::out() << std::endl; } #endif continue; } iinst = (*it)->initInst->asMethodCallInst(); // inline info from constructor should be propagated to lazy // exception if any #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << " to remove "; iinst->print(Log::out()); Log::out() << std::endl; } #endif assert((*it)->throwInsts != NULL); assert(iinst->getNumSrcOperands() >= 3); if (!removeInsts(oinst,iinst)) continue; // to null bitset? TypeManager& tm = irManager.getTypeManager(); Opnd* mpt = irManager.getOpndManager().createSsaTmpOpnd( tm.getMethodPtrType(iinst->getMethodDesc())); opcount = iinst->getNumSrcOperands()-2; //numSrc-3+1 if (opcount >0) { opnds = new (leMemManager) Opnd*[opcount]; //local mem should be used opnds[0] = mpt; for (U_32 i = 0; i < opcount-1; i++) opnds[i+1] = iinst->getSrc(i+3); } Inst* mptinst = irManager.getInstFactory().makeLdFunAddr(mpt,iinst->getMethodDesc()); #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << " 1st "; mptinst->print(Log::out()); Log::out() << std::endl; } #endif ThrowInsts::iterator it1; for (it1 = (*it)->throwInsts->begin(); it1 !=(*it)->throwInsts->end(); it1++) { tinst = *it1; assert(tinst != NULL); tlinst=irManager.getInstFactory().makeVMHelperCall( OpndManager::getNullOpnd(), VM_RT_THROW_LAZY, opcount, opnds); #ifdef _DEBUG if (Log::isEnabled()) { Log::out() << " 2nd "; tlinst->print(Log::out()); Log::out() << std::endl; } if (Log::isEnabled()) { Log::out() << " to change "; tinst->print(Log::out()); Log::out() << std::endl; } #endif mptinst->insertBefore(tinst); tlinst->insertBefore(tinst); tinst->unlink(); uint16 bcOffset = iinst->getBCOffset(); mptinst->setBCOffset(bcOffset); tlinst->setBCOffset(bcOffset); } } } }