/**
 * Checks if there is a side effect between throw_inst and init_inst instructions.
 * @param throw_inst - the exception object throw instruction
 * @param init_inst - the exception object constructor call instruction
 * @return <code>true</code> if there is side effect;
 *         <code>false<code> if there is no side effect.
 */
bool
LazyExceptionOpt::checkInSideEff(Inst* throw_inst, Inst* init_inst) {
    Node* node = throw_inst->getNode();
    Inst* instfirst = (Inst*)node->getFirstInst();;
    Inst* instlast = throw_inst;
    Inst* inst;
    bool dofind = true;
    bool inSE = false;
    if (throw_inst!=instfirst)
        instlast=throw_inst->getPrevInst();
    else {
        node = node->getInEdges().front()->getSourceNode();
        instlast = (Inst*)node->getLastInst();
    }
    while (dofind && node!=NULL) {
        instfirst = (Inst*)node->getFirstInst();
        for (inst = instlast; inst!=instfirst; inst=inst->getPrevInst()) {
#ifdef _DEBUG
            if (Log::isEnabled()) {
                Log::out() << "      checkInSE: see ";
                inst->print(Log::out());
                Log::out() << std::endl;
            }
#endif
            if (inst==init_inst) {
                dofind=false;
                break;
            }
            if (!inSE) {
                if (instHasSideEffect(inst)) {
                    inSE=true;
#ifdef _DEBUG
                    if (Log::isEnabled()) {
                        Log::out() << "      checkInSE: sideEff ";
                        inst->print(Log::out());
                        Log::out() << std::endl;
                    }
#endif
                    break;
                }
            }
        }
        if (dofind) {
            node = node->getInEdges().front()->getSourceNode();
            instlast = (Inst*)node->getLastInst();
        }
    }
    if (dofind)
        return true; // call init wasn't found
    return inSE;
}
Ejemplo n.º 2
0
SsaOpnd* OSR::reduce(Type* type, Opcode opcode, Operation op,
                     SsaOpnd* iv, SsaOpnd* rc) {
    if (Log::isEnabled()) {
        Log::out() << "Reducing: ";
        iv->print(Log::out());
        Log::out() << std::endl;
        rc->print(Log::out());
        Log::out() << std::endl;
    }
    Inst* newinst = hashTable->lookup(op.encodeForHashing(), iv->getId(), rc->getId());
    if (!newinst) {
        Inst* newDef = insertNewDef(type, iv, rc);
        if (Log::isEnabled()) {
            Log::out() << "NewDef" << std::endl;
            newDef->print(Log::out());
            Log::out() << std::endl;
        }

        SsaOpnd* result = newDef->getDst()->asSsaOpnd();
        writeLeadingOperand(result, getLeadingOperand(iv));
        hashTable->insert(op.encodeForHashing(), iv->getId(),
                          rc->getId(), newDef);
        writeLFTR(iv, op, rc, newDef->getDst()->asSsaOpnd());
        replaceOperands(type, newDef, iv, rc, opcode, op);
        return result;

    } else {
        SsaOpnd* result = newinst->getDst()->asSsaOpnd();
        return result;
    }
}
/**
 * Checks if Op_TauStInd (stind) instruction has a side effect.
 * @param inst - checked instruction
 * @return <code>true</code> if an instruction has side effect;
 *         <code>false<code> if an instruction has no side effect.
 */
bool
LazyExceptionOpt::fieldUsageHasSideEffect(Inst* inst) {
    Opnd* insOp = inst->getSrc(0);
    Inst* instDef = insOp->getInst();
    if (instDef->getOpcode() == Op_DefArg) {
#ifdef _DEBUG
        if (Log::isEnabled()) {
            Log::out() << "    fieldUsageHasSideEffect: ";
            inst->print(Log::out());
            Log::out()  << std::endl;
            Log::out() << "    fieldUsageHasSideEffect: ";
            instDef->print(Log::out());
            Log::out()  << std::endl;
            Log::out() << "    fieldUsageHasSideEffect: ";
            Log::out() << (int)(instDef->getDefArgModifier()) << " " <<
                       (instDef->getDefArgModifier()==DefArgNoModifier) << " " <<
                       (instDef->getDefArgModifier()==NonNullThisArg) << " " <<
                       (instDef->getDefArgModifier()==DefArgBothModifiers) << std::endl;
        }
#endif
        if (instDef->getDefArgModifier()==NonNullThisArg && isExceptionInit)
            return false;
    }
    return true;
}
/**
 * Prints information about optimization candidates.
 * @param os - output stream
 */
void
LazyExceptionOpt::printOptCandidates(::std::ostream& os) {
    OptCandidates::iterator it;
    Inst* oinst;
    Inst* iinst;
    Inst* tinst;

    if (optCandidates == NULL) {
        return;
    }
    for (it = optCandidates->begin( ); it != optCandidates->end( ); it++ ) {
        os << "~~  opndId " << (*it)->opndId << std::endl;
        oinst = (*it)->objInst;
        os << "  obj       ";
        if (oinst != NULL)
            oinst->print(os);
        else
            os << "newobj NULL";
        os << std::endl;
        iinst = (*it)->initInst;
        os << "  init      ";
        if (iinst != NULL)
            iinst->print(os);
        else
            os << "call init NULL";
        os << std::endl;
        if ((*it)->throwInsts == NULL) {
            os << "  thr        throw NULL";
            os << std::endl;
            continue;
        }
        ThrowInsts::iterator it1;
        for (it1 = (*it)->throwInsts->begin(); it1 !=(*it)->throwInsts->end(); it1++) {
            tinst = *it1;
            assert(tinst != NULL);
            os << "  thr       ";
            tinst->print(os);
            os << std::endl;
        }
    }
    os << "end~~" << std::endl;
}
Ejemplo n.º 5
0
Inst*    CSEHashTable::lookupKeyBase(CSEHashKey* key) {
    Inst* inst = (Inst*)hashTable.lookup(key);
    if (inst != NULL) {
        numCSE++;
        if(Log::isEnabled()) {
            Log::out() << "***** CSEHashTable::Lookup succeeded: ";
            inst->print(Log::out());
            Log::out() << ::std::endl;
        }
    }
    return inst;
}
Ejemplo n.º 6
0
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();
        }
    }
}
Ejemplo n.º 7
0
static OpndLoopInfo processOpnd(LoopNode* loopHead, LoopTree* lt, InstStack& defStack, Opnd* opnd) {
    OpndLoopInfo result;
    Inst* defInst = opnd->getInst();
    if (Log::isEnabled()) {
        log_ident(defStack.size()); defInst->print(Log::out()); Log::out()<<"]"<<std::endl;
    }
    if (std::find(defStack.begin(), defStack.end(), defInst)!=defStack.end()) {
        result.setType(OpndLoopInfo::COUNTER);
        result.setIncrement(0);
        if (Log::isEnabled()) {
            log_ident(defStack.size()); 
            Log::out()<<"Found duplicate in def stack -> stopping recursion. ";result.print(Log::out()); Log::out()<<std::endl;
        }
        return result;
    }
    Node* defNode = defInst->getNode();
    Opcode opcode = defInst->getOpcode();

    if (opcode == Op_LdConstant) {
        result.setType(OpndLoopInfo::LD_CONST);
        result.setConst(defInst->asConstInst()->getValue().i4);
        if (Log::isEnabled()) {
            log_ident(defStack.size()); 
            Log::out()<<"assigning to const -> stopping recursion. ";result.print(Log::out());Log::out()<<std::endl;
        }
        return result;
    }
    if (!loopHead->inLoop(defNode)) {
        if (Log::isEnabled()) {
            log_ident(defStack.size());
            Log::out()<<"Inst out of the loop -> stopping recursion. ";result.print(Log::out()); Log::out()<<std::endl;
        }
        return result;
    }

    defStack.push_back(defInst);
    if (opcode == Op_Phi) {
        OpndLoopInfo info1 = processOpnd(loopHead, lt, defStack, defInst->getSrc(0));
        OpndLoopInfo info2 = processOpnd(loopHead, lt, defStack, defInst->getSrc(1));
        if (Log::isEnabled()) {
            log_ident(defStack.size());
            Log::out()<<"PHI(";info1.print(Log::out());Log::out()<<",";info2.print(Log::out());Log::out()<<")"<<std::endl;
        }
        if ( ((info1.isCounter() && !info1.isPhiSplit()) && (info2.isDOL() || info2.isLDConst()))
             || ((info2.isCounter() && !info2.isPhiSplit()) && (info1.isDOL() || info1.isLDConst())) )
        {
            result.setType(OpndLoopInfo::COUNTER);
            result.setIncrement(info1.isCounter() ? info1.getIncrement() : info2.getIncrement());
            result.markPhiSplit();
        } else {
            result.setType(OpndLoopInfo::UNDEF);
        }
    } else if (opcode == Op_Add || opcode == Op_Sub) { //todo: LADD 
        Opnd *op1 = defInst->getSrc(0);
        Opnd *op2 = defInst->getSrc(1);
        OpndLoopInfo info1 = processOpnd(loopHead, lt, defStack, op1);
        OpndLoopInfo info2 = processOpnd(loopHead, lt, defStack, op2);
        if ((info1.isLDConst() || info1.isDOL()) && (info2.isLDConst() || info2.isDOL())) {
            if (info1.isLDConst() && info2.isLDConst() && info1.getConst() == info2.getConst()) {
                result.setType(OpndLoopInfo::LD_CONST);
                result.setConst(info1.getConst());
            } else {
                //result is DOL (default type)
            }
        } else if ((info1.isCounter() && info2.isLDConst()) || (info2.isCounter() && info1.isLDConst())) {
            int increment = info1.isCounter()? info1.getIncrement(): info2.getIncrement();
            int diff = info1.isLDConst()? info1.getConst(): info2.getConst(); 

            //we use SSA form to analyze how opnd changes in loop and we do not analyze actual control flow, 
            // so we can unroll loops with monotonically changing 'counters' only.
            //Example: when 'counter' changes not monotonically and we can't unroll:
            //idx=0; loop {idx+=100; if(idx>=100) break; idx-=99;} ->'increment'=1 but not monotonicaly.
            bool monotonousFlag = increment == 0 || diff == 0 
                || (opcode == Op_Add && signof(diff) == signof(increment)) 
                || (opcode == Op_Sub && signof(diff) != signof(increment));
            if (monotonousFlag) {
                result.setType(OpndLoopInfo::COUNTER);
                if ((info1.isCounter() && info1.isPhiSplit()) || (info2.isCounter() && info2.isPhiSplit())) {
                    result.markPhiSplit();
                }
                //TO IMPROVE: for loops like: for (; length-1>=0;length--){...}
                //we have 2 SUBs by -1 => "-2", but real counter is changed by "-1".
                //Loop unroll will use "-2". It's ok, because this value is used in a guard inst
                //and ABS(increment_in_unroll) >= ABS(real_increment). This work only for monotonous loops.
                //To make increment_in_unroll == real_increment we must track modifications (SUB,ADD) that affects vars only.
                if (opcode == Op_Add) {
                    result.setIncrement(increment + diff);
                } else {
                    result.setIncrement(increment - diff);
                }
            } else {
                result.setType(OpndLoopInfo::UNDEF);
            }
        } else {
            result.setType(OpndLoopInfo::UNDEF);
        }
    } else if (opcode == Op_StVar  || opcode == Op_LdVar) {
        Opnd* newOpnd = defInst->getSrc(0);
        result  = processOpnd(loopHead, lt, defStack, newOpnd);
    } else if (opcode == Op_TauArrayLen) {
        Opnd* arrayOpnd  = defInst->getSrc(0);
        result  = processOpnd(loopHead, lt, defStack, arrayOpnd);
    } else { //unsupported op
        result.setType(OpndLoopInfo::UNDEF);
        if (Log::isEnabled()) {
            log_ident(defStack.size()); Log::out()<<"unknown op -> stopping recursion. ";
        }
    }
    defStack.pop_back();
    if (Log::isEnabled()) {
        log_ident(defStack.size());
        result.print(Log::out());Log::out()<<std::endl;
    }
    return result;
}
/**
 * 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);
            }
        }
    }
}
Ejemplo n.º 9
0
//
// traverse dominator tree and rename variables
//
void SSABuilder::renameNode(RenameStack *renameStack, DominatorNode* dt,
                            const StlVectorSet<VarOpnd *> *whatVars)
{
    if (dt == NULL) return;
    Node* node = dt->getNode();

    Inst* head = (Inst*)node->getFirstInst();
#ifdef DEBUG_SSA
    std::ostream &cout = Log::out();
    if (Log::isEnabled()) {
        cout << "renameNode "; FlowGraph::printLabel(cout, node); cout << std::endl;
    }
#endif
    for (Inst* i = head->getNextInst(); i != NULL; i = i->getNextInst()) {
        if (!i->isPhi()) {
            // replace src with ssa opnd
            U_32 nSrcs = i->getNumSrcOperands();
            for (U_32 j = 0; j < nSrcs; j++) {
                Opnd *srcj = i->getSrc(j);
                VarOpnd *srcjVar = (srcj->isSsaVarOpnd()
                                    ? srcj->asSsaVarOpnd()->getVar()
                                    : srcj->asVarOpnd());
                if (!(srcjVar && !srcjVar->isAddrTaken()))
                    continue;
                if (whatVars && !whatVars->has(srcjVar)) continue;
                SsaVarOpnd* ssa = renameStack->lookup(srcjVar);
                assert(ssa);
                i->setSrc(j,ssa);
            }
        }

        // for both Phi and non-Phi
        // we replace any non-ssa dst with a new ssa opnd
        // and record it in the RenameStack map
        Opnd* dst = i->getDst();
        VarOpnd *theVar = dst->asVarOpnd();

        if (theVar && (!theVar->isAddrTaken())
            && !(whatVars && !whatVars->has(theVar))) {

            SsaVarOpnd* ssaDst = opndManager.createSsaVarOpnd((VarOpnd*)dst);
#ifdef DEBUG_SSA
            if (Log::isEnabled()) {
                cout << "SSA "; ssaDst->print(cout); cout << ::std::endl;
            }
#endif
            renameStack->insert((VarOpnd*)dst, ssaDst);
            i->setDst(ssaDst);
#ifdef DEBUG_SSA
            if (Log::isEnabled()) {
                i->print(cout); cout << ::std::endl;
            }
#endif
            // record stVar inst
        } else if (dst->isSsaVarOpnd()) {
            SsaVarOpnd* ssaDst = dst->asSsaVarOpnd();
            theVar = ssaDst->getVar();
            if (whatVars && !whatVars->has(theVar))
                continue;
#ifdef DEBUG_SSA
            if (Log::isEnabled()) {
                cout << "SSA "; ssaDst->print(cout); cout << ::std::endl;
            }
#endif
            renameStack->insert(ssaDst->getVar(), ssaDst);
#ifdef DEBUG_SSA
            if (Log::isEnabled()) {
                i->print(cout); cout << ::std::endl;
            }
#endif
        }
    }

    // add var sources to following phi instructions
    const Edges& edges = node->getOutEdges();
    Edges::const_iterator 
        eiter = edges.begin(),
        eend = edges.end();
    for(eiter = edges.begin(); eiter != eend; ++eiter) {
        Edge* e = *eiter;
        Node* succ = e->getTargetNode();
        // Phi insts are inserted to the beginning of the block
        // if succ does not have phi insts, then we can skip  it
        Inst *phi = (Inst*)succ->getSecondInst();
        if (phi==NULL || !phi->isPhi()) continue;

        // node is jth predecessor for succ
        
        
        // replace jth var of phi insts
        Inst* nextphi = phi->getNextInst();
        for (;phi!=NULL && phi->isPhi(); phi = nextphi) {
            nextphi = phi->getNextInst();
            // get var 
            Opnd *theopnd = phi->getDst();
            VarOpnd *thevar = theopnd->asVarOpnd();

            if (!thevar) {
                SsaVarOpnd *theSsaVar = theopnd->asSsaVarOpnd();
                assert(theSsaVar);

#ifdef DEBUG_SSA
                if (Log::isEnabled()) {
                    Log::out() << "case 2" << ::std::endl;
                }
#endif
                thevar = theSsaVar->getVar();
            }

            if (whatVars && !whatVars->has(thevar)) continue;

            SsaVarOpnd* ssa = renameStack->lookup((VarOpnd*)thevar);

            if (ssa != NULL) {
#ifdef DEBUG_SSA
                if (Log::isEnabled()) {
                    cout << "redge";
//                    cout << (I_32)j;
                    cout << " with ssa "; ssa->print(cout); cout << ::std::endl;
                }
#endif
                addPhiSrc((PhiInst*)phi,ssa);
            } else {
#ifdef DEBUG_SSA
                if (Log::isEnabled()) {
                    cout << "no source for phi of var ";
                    thevar->print(cout);
                    cout << ::std::endl;
                }
#endif
                // if ssa is NULL, then the phi must be a dead phi inst
                // (no more use of var afterwards). it will be removed.
            }
        }
    }
}