Search in sources :

Example 66 with RegisterSpecList

use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.

the class SsaBasicBlock method addMoveToEnd.

/**
 * Adds a move instruction to the end of this basic block, just
 * before the last instruction. If the result of the final instruction
 * is the source in question, then the move is placed at the beginning of
 * the primary successor block. This is for unversioned registers.
 *
 * @param result move destination
 * @param source move source
 */
public void addMoveToEnd(RegisterSpec result, RegisterSpec source) {
    if (result.getReg() == source.getReg()) {
        // Sometimes we end up with no-op moves. Ignore them here.
        return;
    }
    /*
         * The last Insn has to be a normal SSA insn: a phi can't branch
         * or return or cause an exception, etc.
         */
    NormalSsaInsn lastInsn;
    lastInsn = (NormalSsaInsn) insns.get(insns.size() - 1);
    if (lastInsn.getResult() != null || lastInsn.getSources().size() > 0) {
        for (int i = successors.nextSetBit(0); i >= 0; i = successors.nextSetBit(i + 1)) {
            SsaBasicBlock succ;
            succ = parent.getBlocks().get(i);
            succ.addMoveToBeginning(result, source);
        }
    } else {
        /*
             * We can safely add a move to the end of the block just
             * before the last instruction, because the final insn does
             * not assign to anything.
             */
        RegisterSpecList sources = RegisterSpecList.make(source);
        NormalSsaInsn toAdd = new NormalSsaInsn(new PlainInsn(Rops.opMove(result.getType()), SourcePosition.NO_INFO, result, sources), this);
        insns.add(insns.size() - 1, toAdd);
        movesFromPhisAtEnd++;
    }
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList)

Example 67 with RegisterSpecList

use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.

the class SsaMethod method onSourcesChanged.

/**
 * Updates the use list for a source list change.
 *
 * @param insn {@code insn non-null;} insn being changed.
 * {@code insn.getSources()} must return the new source list.
 * @param oldSources {@code null-ok;} list of sources that were
 * previously used
 */
/*package*/
void onSourcesChanged(SsaInsn insn, RegisterSpecList oldSources) {
    if (useList == null)
        return;
    if (oldSources != null) {
        removeFromUseList(insn, oldSources);
    }
    RegisterSpecList sources = insn.getSources();
    int szNew = sources.size();
    for (int i = 0; i < szNew; i++) {
        int reg = sources.get(i).getReg();
        useList[reg].add(insn);
    }
}
Also used : RegisterSpecList(com.android.dx.rop.code.RegisterSpecList)

Example 68 with RegisterSpecList

use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.

the class FirstFitLocalCombiningAllocator method findRangeAndAdjust.

/**
 * Find a contiguous rop register range that fits the specified
 * instruction's sources. First, try to center the range around
 * sources that have already been mapped to rop registers. If that fails,
 * just find a new contiguous range that doesn't interfere.
 *
 * @param insn {@code non-null;} the insn whose sources need to
 * fit. Must be last insn in basic block.
 * @return {@code >= 0;} rop register of start of range
 */
private int findRangeAndAdjust(NormalSsaInsn insn) {
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    // the category for each source index
    int[] categoriesForIndex = new int[szSources];
    int rangeLength = 0;
    // Compute rangeLength and categoriesForIndex
    for (int i = 0; i < szSources; i++) {
        int category = sources.get(i).getCategory();
        categoriesForIndex[i] = category;
        rangeLength += categoriesForIndex[i];
    }
    // the highest score of fits tried so far
    int maxScore = Integer.MIN_VALUE;
    // the high scoring range's start
    int resultRangeStart = -1;
    // by source index: set of sources needing moves in high scoring plan
    BitSet resultMovesRequired = null;
    /*
         * First, go through each source that's already been mapped. Try
         * to center the range around the rop register this source is mapped
         * to.
         */
    int rangeStartOffset = 0;
    for (int i = 0; i < szSources; i++) {
        int ssaCenterReg = sources.get(i).getReg();
        if (i != 0) {
            rangeStartOffset -= categoriesForIndex[i - 1];
        }
        if (!ssaRegsMapped.get(ssaCenterReg)) {
            continue;
        }
        int rangeStart = mapper.oldToNew(ssaCenterReg) + rangeStartOffset;
        if (rangeStart < 0 || spansParamRange(rangeStart, rangeLength)) {
            continue;
        }
        BitSet curMovesRequired = new BitSet(szSources);
        int fitWidth = fitPlanForRange(rangeStart, insn, categoriesForIndex, curMovesRequired);
        if (fitWidth < 0) {
            continue;
        }
        int score = fitWidth - curMovesRequired.cardinality();
        if (score > maxScore) {
            maxScore = score;
            resultRangeStart = rangeStart;
            resultMovesRequired = curMovesRequired;
        }
        if (fitWidth == rangeLength) {
            // We can't do any better than this, so stop here
            break;
        }
    }
    if (resultRangeStart == -1) {
        resultMovesRequired = new BitSet(szSources);
        resultRangeStart = findAnyFittingRange(insn, rangeLength, categoriesForIndex, resultMovesRequired);
    }
    for (int i = resultMovesRequired.nextSetBit(0); i >= 0; i = resultMovesRequired.nextSetBit(i + 1)) {
        insn.changeOneSource(i, insertMoveBefore(insn, sources.get(i)));
    }
    return resultRangeStart;
}
Also used : BitSet(java.util.BitSet) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList)

Example 69 with RegisterSpecList

use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.

the class FirstFitLocalCombiningAllocator method processPhiInsn.

/**
 * Attempts to map the sources and result of a phi to a common register.
 * Will try existing mappings first, from most to least common. If none
 * of the registers have mappings yet, a new mapping is created.
 */
private void processPhiInsn(PhiInsn insn) {
    RegisterSpec result = insn.getResult();
    int resultReg = result.getReg();
    int category = result.getCategory();
    RegisterSpecList sources = insn.getSources();
    int sourcesSize = sources.size();
    // List of phi sources / result that need mapping
    ArrayList<RegisterSpec> ssaRegs = new ArrayList<RegisterSpec>();
    // Track how many times a particular mapping is found
    Multiset mapSet = new Multiset(sourcesSize + 1);
    /*
         * If the result of the phi has an existing mapping, get it.
         * Otherwise, add it to the list of regs that need mapping.
         */
    if (ssaRegsMapped.get(resultReg)) {
        mapSet.add(mapper.oldToNew(resultReg));
    } else {
        ssaRegs.add(result);
    }
    for (int i = 0; i < sourcesSize; i++) {
        RegisterSpec source = sources.get(i);
        SsaInsn def = ssaMeth.getDefinitionForRegister(source.getReg());
        RegisterSpec sourceDef = def.getResult();
        int sourceReg = sourceDef.getReg();
        /*
             * If a source of the phi has an existing mapping, get it.
             * Otherwise, add it to the list of regs that need mapping.
             */
        if (ssaRegsMapped.get(sourceReg)) {
            mapSet.add(mapper.oldToNew(sourceReg));
        } else {
            ssaRegs.add(sourceDef);
        }
    }
    // Try all existing mappings, with the most common ones first
    for (int i = 0; i < mapSet.getSize(); i++) {
        int maxReg = mapSet.getAndRemoveHighestCount();
        tryMapRegs(ssaRegs, maxReg, category, false);
    }
    // Map any remaining unmapped regs with whatever fits
    int mapReg = findNextUnreservedRopReg(paramRangeEnd, category);
    while (!tryMapRegs(ssaRegs, mapReg, category, false)) {
        mapReg = findNextUnreservedRopReg(mapReg + 1, category);
    }
}
Also used : ArrayList(java.util.ArrayList) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) SsaInsn(com.android.dx.ssa.SsaInsn) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 70 with RegisterSpecList

use of com.android.dx.rop.code.RegisterSpecList in project J2ME-Loader by nikita36078.

the class FirstFitLocalCombiningAllocator method fitPlanForRange.

/**
 * Attempts to build a plan for fitting a range of sources into rop
 * registers.
 *
 * @param ropReg {@code >= 0;} rop reg that begins range
 * @param insn {@code non-null;} insn to plan range for
 * @param categoriesForIndex {@code non-null;} indexed by source index;
 * the category for each source
 * @param outMovesRequired {@code non-null;} an output parameter indexed by
 * source index that will contain the set of sources which need
 * moves inserted
 * @return the width of the fit that that does not involve added moves or
 * {@code -1} if "no fit possible"
 */
private int fitPlanForRange(int ropReg, NormalSsaInsn insn, int[] categoriesForIndex, BitSet outMovesRequired) {
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    int fitWidth = 0;
    IntSet liveOut = insn.getBlock().getLiveOutRegs();
    RegisterSpecList liveOutSpecs = ssaSetToSpecs(liveOut);
    // An SSA reg may only be mapped into a range once.
    BitSet seen = new BitSet(ssaMeth.getRegCount());
    for (int i = 0; i < szSources; i++) {
        RegisterSpec ssaSpec = sources.get(i);
        int ssaReg = ssaSpec.getReg();
        int category = categoriesForIndex[i];
        if (i != 0) {
            ropReg += categoriesForIndex[i - 1];
        }
        if (ssaRegsMapped.get(ssaReg) && mapper.oldToNew(ssaReg) == ropReg) {
            // This is a register that is already mapped appropriately.
            fitWidth += category;
        } else if (rangeContainsReserved(ropReg, category)) {
            fitWidth = -1;
            break;
        } else if (!ssaRegsMapped.get(ssaReg) && canMapReg(ssaSpec, ropReg) && !seen.get(ssaReg)) {
            // This is a register that can be mapped appropriately.
            fitWidth += category;
        } else if (!mapper.areAnyPinned(liveOutSpecs, ropReg, category) && !mapper.areAnyPinned(sources, ropReg, category)) {
            /*
                 * This is a source that can be moved. We can insert a
                 * move as long as:
                 *
                 *   * no SSA register pinned to the desired rop reg
                 *     is live out on the block
                 *
                 *   * no SSA register pinned to desired rop reg is
                 *     a source of this insn (since this may require
                 *     overlapping moves, which we can't presently handle)
                 */
            outMovesRequired.set(i);
        } else {
            fitWidth = -1;
            break;
        }
        seen.set(ssaReg);
    }
    return fitWidth;
}
Also used : IntSet(com.android.dx.util.IntSet) BitSet(java.util.BitSet) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Aggregations

RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)202 RegisterSpec (com.android.dx.rop.code.RegisterSpec)50 BitSet (java.util.BitSet)45 CstLiteralBits (com.android.dx.rop.cst.CstLiteralBits)42 Constant (com.android.dx.rop.cst.Constant)36 CstInsn (com.android.dx.dex.code.CstInsn)34 PlainInsn (com.android.dx.rop.code.PlainInsn)18 CstType (com.android.dx.rop.cst.CstType)12 TargetInsn (com.android.dx.dex.code.TargetInsn)10 Insn (com.android.dx.rop.code.Insn)10 TypedConstant (com.android.dx.rop.cst.TypedConstant)10 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)8 Rop (com.android.dx.rop.code.Rop)8 CstFieldRef (com.android.dx.rop.cst.CstFieldRef)8 CstMethodRef (com.android.dx.rop.cst.CstMethodRef)8 TypeBearer (com.android.dx.rop.type.TypeBearer)8 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)6 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)6 CstInteger (com.android.dx.rop.cst.CstInteger)6 MultiCstInsn (com.android.dx.dex.code.MultiCstInsn)4