Search in sources :

Example 1 with IntSet

use of com.android.dx.util.IntSet in project buck by facebook.

the class RegisterAllocator method insertMoveBefore.

/**
     * Inserts a move instruction for a specified SSA register before a
     * specified instruction, creating a new SSA register and adjusting the
     * interference graph in the process. The insn currently must be the
     * last insn in a block.
     *
     * @param insn {@code non-null;} insn to insert move before, must
     * be last insn in block
     * @param reg {@code non-null;} SSA register to duplicate
     * @return {@code non-null;} spec of new SSA register created by move
     */
protected final RegisterSpec insertMoveBefore(SsaInsn insn, RegisterSpec reg) {
    SsaBasicBlock block = insn.getBlock();
    ArrayList<SsaInsn> insns = block.getInsns();
    int insnIndex = insns.indexOf(insn);
    if (insnIndex < 0) {
        throw new IllegalArgumentException("specified insn is not in this block");
    }
    if (insnIndex != insns.size() - 1) {
        /*
             * Presently, the interference updater only works when
             * adding before the last insn, and the last insn must have no
             * result
             */
        throw new IllegalArgumentException("Adding move here not supported:" + insn.toHuman());
    }
    /*
         * Get new register and make new move instruction.
         */
    // The new result must not have an associated local variable.
    RegisterSpec newRegSpec = RegisterSpec.make(ssaMeth.makeNewSsaReg(), reg.getTypeBearer());
    SsaInsn toAdd = SsaInsn.makeFromRop(new PlainInsn(Rops.opMove(newRegSpec.getType()), SourcePosition.NO_INFO, newRegSpec, RegisterSpecList.make(reg)), block);
    insns.add(insnIndex, toAdd);
    int newReg = newRegSpec.getReg();
    /*
         * Adjust interference graph based on what's live out of the current
         * block and what's used by the final instruction.
         */
    IntSet liveOut = block.getLiveOutRegs();
    IntIterator liveOutIter = liveOut.iterator();
    while (liveOutIter.hasNext()) {
        interference.add(newReg, liveOutIter.next());
    }
    // Everything that's a source in the last insn interferes.
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    for (int i = 0; i < szSources; i++) {
        interference.add(newReg, sources.get(i).getReg());
    }
    ssaMeth.onInsnsChanged();
    return newRegSpec;
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) IntIterator(com.android.dx.util.IntIterator) IntSet(com.android.dx.util.IntSet) SsaBasicBlock(com.android.dx.ssa.SsaBasicBlock) NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) SsaInsn(com.android.dx.ssa.SsaInsn) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 2 with IntSet

use of com.android.dx.util.IntSet in project buck by facebook.

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)

Example 3 with IntSet

use of com.android.dx.util.IntSet in project buck by facebook.

the class FirstFitAllocator method allocateRegisters.

/** {@inheritDoc} */
@Override
public RegisterMapper allocateRegisters() {
    int oldRegCount = ssaMeth.getRegCount();
    BasicRegisterMapper mapper = new BasicRegisterMapper(oldRegCount);
    int nextNewRegister = 0;
    if (PRESLOT_PARAMS) {
        /*
             * Reserve space for the params at the bottom of the register
             * space. Later, we'll flip the params to the end of the register
             * space.
             */
        nextNewRegister = ssaMeth.getParamWidth();
    }
    for (int i = 0; i < oldRegCount; i++) {
        if (mapped.get(i)) {
            // we already got this one
            continue;
        }
        int maxCategory = getCategoryForSsaReg(i);
        IntSet current = new BitIntSet(oldRegCount);
        interference.mergeInterferenceSet(i, current);
        boolean isPreslotted = false;
        int newReg = 0;
        if (PRESLOT_PARAMS && isDefinitionMoveParam(i)) {
            // Any move-param definition must be a NormalSsaInsn
            NormalSsaInsn defInsn = (NormalSsaInsn) ssaMeth.getDefinitionForRegister(i);
            newReg = paramNumberFromMoveParam(defInsn);
            mapper.addMapping(i, newReg, maxCategory);
            isPreslotted = true;
        } else {
            mapper.addMapping(i, nextNewRegister, maxCategory);
            newReg = nextNewRegister;
        }
        for (int j = i + 1; j < oldRegCount; j++) {
            if (mapped.get(j) || isDefinitionMoveParam(j)) {
                continue;
            }
            /*
                 * If reg j doesn't interfere with the current mapping.
                 * Also, if this is a pre-slotted method parameter, we
                 * can't use more than the original param width.
                 */
            if (!current.has(j) && !(isPreslotted && (maxCategory < getCategoryForSsaReg(j)))) {
                interference.mergeInterferenceSet(j, current);
                maxCategory = Math.max(maxCategory, getCategoryForSsaReg(j));
                mapper.addMapping(j, newReg, maxCategory);
                mapped.set(j);
            }
        }
        mapped.set(i);
        if (!isPreslotted) {
            nextNewRegister += maxCategory;
        }
    }
    return mapper;
}
Also used : NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) BasicRegisterMapper(com.android.dx.ssa.BasicRegisterMapper) IntSet(com.android.dx.util.IntSet) BitIntSet(com.android.dx.util.BitIntSet) BitIntSet(com.android.dx.util.BitIntSet)

Aggregations

IntSet (com.android.dx.util.IntSet)3 RegisterSpec (com.android.dx.rop.code.RegisterSpec)2 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)2 NormalSsaInsn (com.android.dx.ssa.NormalSsaInsn)2 PlainInsn (com.android.dx.rop.code.PlainInsn)1 BasicRegisterMapper (com.android.dx.ssa.BasicRegisterMapper)1 SsaBasicBlock (com.android.dx.ssa.SsaBasicBlock)1 SsaInsn (com.android.dx.ssa.SsaInsn)1 BitIntSet (com.android.dx.util.BitIntSet)1 IntIterator (com.android.dx.util.IntIterator)1 BitSet (java.util.BitSet)1