Exemplo n.º 1
0
/*
 * Dump the liveness bits to the log.
 *
 * "curIdx" is for display only.
 */
static void dumpLiveState(const VerifierData* vdata, u4 curIdx,
    const BitVector* workBits)
{
    u4 insnRegCount = vdata->insnRegCount;
    size_t regCharSize = insnRegCount + (insnRegCount-1)/4 + 2 +1;
#ifndef __GNUC__
    char* regChars = (char*)alloca(regCharSize +1);
#else
    char regChars[regCharSize +1];
#endif
    unsigned int idx;

    memset(regChars, ' ', regCharSize);
    regChars[0] = '[';
    if (insnRegCount == 0)
        regChars[1] = ']';
    else
        regChars[1 + (insnRegCount-1) + (insnRegCount-1)/4 +1] = ']';
    regChars[regCharSize] = '\0';

    for (idx = 0; idx < insnRegCount; idx++) {
        char ch = dvmIsBitSet(workBits, idx) ? '+' : '-';
        regChars[1 + idx + (idx/4)] = ch;
    }

    ALOGI("0x%04x %s", curIdx, regChars);
}
Exemplo n.º 2
0
static BasicBlock *findPredecessorBlock(const CompilationUnit *cUnit,
                                        const BasicBlock *bb)
{
    int numPred = dvmCountSetBits(bb->predecessors);
    BitVectorIterator bvIterator;
    dvmBitVectorIteratorInit(bb->predecessors, &bvIterator);

    if (numPred == 1) {
        int predIdx = dvmBitVectorIteratorNext(&bvIterator);
        return (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList,
                                                        predIdx);
    /* First loop block */
    } else if ((numPred == 2) &&
               dvmIsBitSet(bb->predecessors, cUnit->entryBlock->id)) {
        while (true) {
            int predIdx = dvmBitVectorIteratorNext(&bvIterator);
            if (predIdx == cUnit->entryBlock->id) continue;
            return (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList,
                                                            predIdx);
        }
    /* Doesn't support other shape of control flow yet */
    } else {
        return NULL;
    }
}
Exemplo n.º 3
0
/*
 * Perform null-check on a register. sReg is the ssa register being checked,
 * and mReg is the machine register holding the actual value. If internal state
 * indicates that sReg has been checked before the check request is ignored.
 */
static ArmLIR *genNullCheck(CompilationUnit *cUnit, int sReg, int mReg,
                                int dOffset, ArmLIR *pcrLabel)
{
    /* This particular Dalvik register has been null-checked */
    if (dvmIsBitSet(cUnit->regPool->nullCheckedRegs, sReg)) {
        return pcrLabel;
    }
    dvmSetBit(cUnit->regPool->nullCheckedRegs, sReg);
    return genRegImmCheck(cUnit, kArmCondEq, mReg, 0, dOffset, pcrLabel);
}
Exemplo n.º 4
0
/* Debugging routines */
static void dumpConstants(CompilationUnit *cUnit)
{
    int i;
    LOGE("LOOP starting offset: %x", cUnit->entryBlock->startOffset);
    for (i = 0; i < cUnit->numSSARegs; i++) {
        if (dvmIsBitSet(cUnit->isConstantV, i)) {
            int subNReg = dvmConvertSSARegToDalvik(cUnit, i);
            LOGE("CONST: s%d(v%d_%d) has %d", i,
                 DECODE_REG(subNReg), DECODE_SUB(subNReg),
                 cUnit->constantValues[i]);
        }
    }
}
Exemplo n.º 5
0
/* Worker function to compute the idom */
static bool computeImmediateDominator(CompilationUnit *cUnit, BasicBlock *bb) {
    GrowableList *blockList = &cUnit->blockList;
    BitVector *tempBlockV = cUnit->tempBlockV;
    BitVectorIterator bvIterator;
    BasicBlock *iDom;

    if (bb == cUnit->entryBlock) return false;

    dvmCopyBitVector(tempBlockV, bb->dominators);
    dvmClearBit(tempBlockV, bb->id);
    dvmBitVectorIteratorInit(tempBlockV, &bvIterator);

    /* Should not see any dead block */
    assert(dvmCountSetBits(tempBlockV) != 0);
    if (dvmCountSetBits(tempBlockV) == 1) {
        iDom = (BasicBlock *) dvmGrowableListGetElement(
                blockList, dvmBitVectorIteratorNext(&bvIterator));
        bb->iDom = iDom;
    } else {
        int iDomIdx = dvmBitVectorIteratorNext(&bvIterator);
        assert(iDomIdx != -1);
        while (true) {
            int nextDom = dvmBitVectorIteratorNext(&bvIterator);
            if (nextDom == -1) break;
            BasicBlock *nextDomBB = (BasicBlock *)
                    dvmGrowableListGetElement(blockList, nextDom);
            /* iDom dominates nextDom - set new iDom */
            if (dvmIsBitSet(nextDomBB->dominators, iDomIdx)) {
                iDomIdx = nextDom;
            }

        }
        iDom = (BasicBlock *) dvmGrowableListGetElement(blockList, iDomIdx);
        /* Set the immediate dominator block for bb */
        bb->iDom = iDom;
    }
    /* Add bb to the iDominated set of the immediate dominator block */
    dvmCompilerSetBit(iDom->iDominated, bb->id);
    return true;
}
Exemplo n.º 6
0
/* Compute the post-order traversal of the CFG */
static void computeDomPostOrderTraversal(CompilationUnit *cUnit, BasicBlock *bb) {
    BitVectorIterator bvIterator;
    dvmBitVectorIteratorInit(bb->iDominated, &bvIterator);
    GrowableList *blockList = &cUnit->blockList;

    /* Iterate through the dominated blocks first */
    while (true) {
        int bbIdx = dvmBitVectorIteratorNext(&bvIterator);
        if (bbIdx == -1) break;
        BasicBlock *dominatedBB =
                (BasicBlock *) dvmGrowableListGetElement(blockList, bbIdx);
        computeDomPostOrderTraversal(cUnit, dominatedBB);
    }

    /* Enter the current block id */
    dvmInsertGrowableList(&cUnit->domPostOrderTraversal, bb->id);

    /* hacky loop detection */
    if (bb->taken && dvmIsBitSet(bb->dominators, bb->taken->id)) {
        cUnit->hasLoop = true;
    }
}
Exemplo n.º 7
0
/*
 * A loop is considered optimizable if:
 * 1) It has one basic induction variable.
 * 2) The loop back branch compares the BIV with a constant.
 * 3) We need to normalize the loop exit condition so that the loop is exited
 *    via the taken path.
 * 4) If it is a count-up loop, the condition is GE/GT. Otherwise it is
 *    LE/LT/LEZ/LTZ for a count-down loop.
 *
 * Return false for loops that fail the above tests.
 */
static bool isSimpleCountedLoop(CompilationUnit *cUnit)
{
    unsigned int i;
    BasicBlock *loopBackBlock = cUnit->entryBlock->fallThrough;
    LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;

    if (loopAnalysis->numBasicIV != 1) return false;
    for (i = 0; i < loopAnalysis->ivList->numUsed; i++) {
        InductionVariableInfo *ivInfo;

        ivInfo = GET_ELEM_N(loopAnalysis->ivList, InductionVariableInfo*, i);
        /* Count up or down loop? */
        if (ivInfo->ssaReg == ivInfo->basicSSAReg) {
            /* Infinite loop */
            if (ivInfo->inc == 0) {
                return false;
            }
            loopAnalysis->isCountUpLoop = ivInfo->inc > 0;
            break;
        }
    }

    /* Find the block that ends with a branch to exit the loop */
    while (true) {
        loopBackBlock = findPredecessorBlock(cUnit, loopBackBlock);
        /* Loop structure not recognized as counted blocks */
        if (loopBackBlock == NULL) {
            return false;
        }
        /* Unconditional goto - continue to trace up the predecessor chain */
        if (loopBackBlock->taken == NULL) {
            continue;
        }
        break;
    }

    MIR *branch = loopBackBlock->lastMIRInsn;
    Opcode opcode = branch->dalvikInsn.opcode;

    /* Last instruction is not a conditional branch - bail */
    if (dexGetFlagsFromOpcode(opcode) != (kInstrCanContinue|kInstrCanBranch)) {
        return false;
    }

    int endSSAReg;
    int endDalvikReg;

    /* reg/reg comparison */
    if (branch->ssaRep->numUses == 2) {
        if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) {
            endSSAReg = branch->ssaRep->uses[1];
        } else if (branch->ssaRep->uses[1] == loopAnalysis->ssaBIV) {
            endSSAReg = branch->ssaRep->uses[0];
            opcode = negateOpcode(opcode);
        } else {
            return false;
        }
        endDalvikReg = dvmConvertSSARegToDalvik(cUnit, endSSAReg);
        /*
         * If the comparison is not between the BIV and a loop invariant,
         * return false. endDalvikReg is loop invariant if one of the
         * following is true:
         * - It is not defined in the loop (ie DECODE_SUB returns 0)
         * - It is reloaded with a constant
         */
        if ((DECODE_SUB(endDalvikReg) != 0) &&
            !dvmIsBitSet(cUnit->isConstantV, endSSAReg)) {
            return false;
        }
    /* Compare against zero */
    } else if (branch->ssaRep->numUses == 1) {
        if (branch->ssaRep->uses[0] == loopAnalysis->ssaBIV) {
            /* Keep the compiler happy */
            endDalvikReg = -1;
        } else {
            return false;
        }
    } else {
        return false;
    }

    /* Normalize the loop exit check as "if (iv op end) exit;" */
    if (loopBackBlock->taken->blockType == kDalvikByteCode) {
        opcode = negateOpcode(opcode);
    }

    if (loopAnalysis->isCountUpLoop) {
        /*
         * If the normalized condition op is not > or >=, this is not an
         * optimization candidate.
         */
        switch (opcode) {
            case OP_IF_GT:
            case OP_IF_GE:
                break;
            default:
                return false;
        }
        loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg);
    } else  {
        /*
         * If the normalized condition op is not < or <=, this is not an
         * optimization candidate.
         */
        switch (opcode) {
            case OP_IF_LT:
            case OP_IF_LE:
                loopAnalysis->endConditionReg = DECODE_REG(endDalvikReg);
                break;
            case OP_IF_LTZ:
            case OP_IF_LEZ:
                break;
            default:
                return false;
        }
    }
    /*
     * Remember the normalized opcode, which will be used to determine the end
     * value used for the yanked range checks.
     */
    loopAnalysis->loopBranchOpcode = opcode;
    return true;
}
Exemplo n.º 8
0
/* Insert phi nodes to for each variable to the dominance frontiers */
static void insertPhiNodes(CompilationUnit *cUnit) {
    int dalvikReg;
    const GrowableList *blockList = &cUnit->blockList;
    BitVector *phiBlocks =
            dvmCompilerAllocBitVector(cUnit->numBlocks, false);
    BitVector *tmpBlocks =
            dvmCompilerAllocBitVector(cUnit->numBlocks, false);
    BitVector *inputBlocks =
            dvmCompilerAllocBitVector(cUnit->numBlocks, false);

    cUnit->tempDalvikRegisterV =
            dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);

    dvmCompilerDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
                                          kPostOrderDFSTraversal,
                                          true /* isIterative */);

    /* Iterate through each Dalvik register */
    for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
        bool change;
        BitVectorIterator iterator;

        dvmCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
        dvmClearAllBits(phiBlocks);

        /* Calculate the phi blocks for each Dalvik register */
        do {
            change = false;
            dvmClearAllBits(tmpBlocks);
            dvmBitVectorIteratorInit(inputBlocks, &iterator);

            while (true) {
                int idx = dvmBitVectorIteratorNext(&iterator);
                if (idx == -1) break;
                BasicBlock *defBB =
                        (BasicBlock *) dvmGrowableListGetElement(blockList, idx);

                /* Merge the dominance frontier to tmpBlocks */
                dvmUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
            }
            if (dvmCompareBitVectors(phiBlocks, tmpBlocks)) {
                change = true;
                dvmCopyBitVector(phiBlocks, tmpBlocks);

                /*
                 * Iterate through the original blocks plus the new ones in
                 * the dominance frontier.
                 */
                dvmCopyBitVector(inputBlocks, phiBlocks);
                dvmUnifyBitVectors(inputBlocks, inputBlocks,
                                   cUnit->defBlockMatrix[dalvikReg]);
            }
        } while (change);

        /*
         * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
         * register is in the live-in set.
         */
        dvmBitVectorIteratorInit(phiBlocks, &iterator);
        while (true) {
            int idx = dvmBitVectorIteratorNext(&iterator);
            if (idx == -1) break;
            BasicBlock *phiBB =
                    (BasicBlock *) dvmGrowableListGetElement(blockList, idx);
            /* Variable will be clobbered before being used - no need for phi */
            if (!dvmIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
            MIR *phi = (MIR *) dvmCompilerNew(sizeof(MIR), true);
            phi->dalvikInsn.opcode = (Opcode) kMirOpPhi;
            phi->dalvikInsn.vA = dalvikReg;
            phi->offset = phiBB->startOffset;
            dvmCompilerPrependMIR(phiBB, phi);
        }
    }
}