示例#1
0
/* Debugging utility routine */
static void dumpDependentInsnPair(MipsLIR *thisLIR, MipsLIR *checkLIR,
                                  const char *optimization)
{
    LOGD("************ %s ************", optimization);
    dvmDumpLIRInsn((LIR *) thisLIR, 0);
    dvmDumpLIRInsn((LIR *) checkLIR, 0);
}
示例#2
0
__attribute__((weak)) void dumpBothLIRs(CompilationUnit *cUnit,
                                        ArmLIR *thisLIR, ArmLIR *checkLIR)
{
    if(cUnit->printMe) {
        ALOGD("thisLIR");
        dvmDumpLIRInsn((LIR*)thisLIR,0);
        ALOGD("checkLIR");
        dvmDumpLIRInsn((LIR*)checkLIR,0);
    }
}
/*
 * Perform a pass to hoist all frame pointer load instructions that
 * are independent, outside the loop.
 */
static void applyLoopLoadHoisting(CompilationUnit *cUnit)
{
    ArmLIR *thisLIR, *labelLIR, *lastLIR, *insertLIR;
    ArmLIR *loadLIR[MAX_LOAD_HOISTS];
    ArmLIR *regLIR[MAX_REGISTER_OPS];
    u8 defLoadMask = 0;
    u8 defMask = 0;
    u8 masterDefMask = ~((1ULL << kRegEnd) - 1);
    bool isValidLoop = false;
    int loadCount = 0;
    int regCount = 0;
    int loadindex;
    int hoistCount = 0;

#ifdef LOOP_LOAD_HOIST_VERBOSE
    ALOGD("GlobalOpts LoopLoadHoisting applied on '%s'", cUnit->method->name);
    cUnit->printMe = true;
#endif

    labelLIR = (ArmLIR *) cUnit->firstLIRInsn;
    lastLIR = (ArmLIR *) cUnit->lastLIRInsn;
    insertLIR = NULL;

    /* Find the insert point */
    while ((labelLIR != lastLIR) &&
           (labelLIR->flags.isNop ||
            (labelLIR->opcode != kArmPseudoNormalBlockLabel))) {
        if ((cUnit->loopAnalysis->branchesAdded) &&
            (labelLIR->opcode == kThumbBUncond) &&
            (insertLIR == NULL) && (!labelLIR->flags.isNop))
            insertLIR = labelLIR;

        labelLIR = NEXT_LIR(labelLIR);
    }

    if (labelLIR->opcode != kArmPseudoNormalBlockLabel) {
#ifdef LOOP_LOAD_HOIST_VERBOSE
        ALOGD("Can't hoist - no loop label found!");
#endif
        return;
    }

    if (insertLIR == NULL) {
        insertLIR = labelLIR;
    }
    else if ((ArmLIR *) insertLIR->generic.target != labelLIR) {
#ifdef LOOP_LOAD_HOIST_VERBOSE
        ALOGD("Can't hoist - branch target does not match!");
#endif
        return;
    }

    /* Search for eligible load instructions to hoist */
    for (thisLIR = labelLIR;
         thisLIR != lastLIR;
         thisLIR = NEXT_LIR(thisLIR)) {
        bool handled = false;
        int flags;

        /* Skip non-interesting instructions */
        if (thisLIR->flags.isNop || isPseudoOpcode(thisLIR->opcode))
            continue;

        flags = EncodingMap[thisLIR->opcode].flags;

        /* If it's a load instruction, check if it's a hoist candidate. */
        if (((flags & IS_LOAD) != 0) &&
            ((thisLIR->useMask & ENCODE_DALVIK_REG) != 0)) {
            if (regCount >= MAX_REGISTER_OPS) {
#ifdef LOOP_LOAD_HOIST_VERBOSE
                ALOGD("Out of register list space!");
#endif
                return;
            }
            regLIR[regCount++] = thisLIR;

            if ((((defLoadMask | defMask) & thisLIR->defMask) == 0) &&
                (loadCount < MAX_LOAD_HOISTS)) {
                defLoadMask |= thisLIR->defMask;
                loadLIR[loadCount++] = thisLIR;
                handled = true;
            } else {
                masterDefMask |= thisLIR->defMask;
            }
        /* If it's a store instruction, check if it matches a previous
           hoistable load instruction. If so, reset the global def-flag to
           indicate that the load is still hoistable. */
        } else if (((flags & IS_STORE) != 0) &&
                   ((thisLIR->defMask & ENCODE_DALVIK_REG) != 0)) {
            if (regCount >= MAX_REGISTER_OPS) {
#ifdef LOOP_LOAD_HOIST_VERBOSE
                ALOGD("Out of register list space!");
#endif
                return;
            }
            regLIR[regCount++] = thisLIR;

            if ((thisLIR->useMask & defLoadMask) != 0) {
                handled = true;
                for (int i = loadCount - 1; i >= 0; i--) {
                    if ((thisLIR->aliasInfo == loadLIR[i]->aliasInfo) &&
                        (thisLIR->operands[0] == loadLIR[i]->operands[0])) {
                        defMask &= ~(loadLIR[i]->defMask);
                        break;
                    }
                }
            }
        /* If it's a branch instruction, check if it's the loop branch.
           If it matches the label, mark it as a valid loop. */
        } else if ((flags & IS_BRANCH) != 0) {
            handled = true;
            if (labelLIR == (ArmLIR *) thisLIR->generic.target) {
                isValidLoop = true;
            } else if ((thisLIR->opcode >= kThumbBlx1) &&
                       (thisLIR->opcode <= kThumbBlxR))
            {
#ifdef LOOP_LOAD_HOIST_VERBOSE
                ALOGD("Trace contains branch to subroutine!");
#endif
                return;
            }
        } else if (thisLIR->opcode == kThumbUndefined) {
            break;
        }

        /* If it's not a 'special' instruction, accumulate into def-flags. */
        if (!handled)
            defMask |= thisLIR->defMask;
    }

    defLoadMask &= ~(defMask | masterDefMask);
    if (!isValidLoop || (defLoadMask == 0)) {
#ifdef LOOP_LOAD_HOIST_VERBOSE
        ALOGD("Loop not valid, or defLoadMask (0x%llx) was zero!", defLoadMask);
#endif
        return;
    }

#ifdef LOOP_LOAD_HOIST_VERBOSE
    ALOGD("Masks: masterDef: 0x%llx, def: 0x%llx, final defLoad: 0x%llx",
          masterDefMask, defMask, defLoadMask);
#endif

    /* Try to hoist the load operations */
    for (loadindex = 0; loadindex < loadCount; loadindex++) {
        thisLIR = loadLIR[loadindex];

        /* Host this load? */
        if ((thisLIR->defMask & defLoadMask) == thisLIR->defMask) {
            int i;
            bool foundAlias = false;
            for (i = 0; i < regCount; i++) {
                if ((thisLIR->aliasInfo == regLIR[i]->aliasInfo) &&
                    (thisLIR->operands[0] != regLIR[i]->operands[0])) {
                    foundAlias = true;
                    for (int k = loadindex; k < loadCount; k++) {
                        if (loadLIR[k] == regLIR[i]) {
                            loadLIR[k]->defMask = -1;
                            break;
                        }
                    }
#ifdef LOOP_LOAD_HOIST_VERBOSE
                    ALOGD("Register alias found between these two load ops:");
                    dvmDumpLIRInsn((LIR*)thisLIR, NULL);
                    dvmDumpLIRInsn((LIR*)regLIR[i], NULL);
#endif
                    break;
                }
            }

            if (!foundAlias) {
#ifdef LOOP_LOAD_HOIST_VERBOSE
                ALOGD("Hoisting this load op:");
                dvmDumpLIRInsn((LIR*)thisLIR, NULL);
#endif
                ArmLIR *newLoadLIR = (ArmLIR *) dvmCompilerNew(sizeof(ArmLIR),
                                                               true);
                *newLoadLIR = *thisLIR;
                dvmCompilerInsertLIRBefore((LIR *) insertLIR,
                                           (LIR *) newLoadLIR);
                thisLIR->flags.isNop = true;
                hoistCount++;
            }
        }
    }

    if (cUnit->printMe)
        ALOGD("GlobalOpt LoopLoadHoist hoisted %d load ops.", hoistCount);
}