Search in sources :

Example 16 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

the class FirstFitLocalCombiningAllocator method handleLocalAssociatedOther.

/**
     * Maps all local-associated registers that are not parameters.
     * Tries to find an unreserved range that's wide enough for all of
     * the SSA registers, and then tries to map them all to that
     * range. If not all fit, a new range is tried until all registers
     * have been fit.
     */
private void handleLocalAssociatedOther() {
    for (ArrayList<RegisterSpec> specs : localVariables.values()) {
        int ropReg = paramRangeEnd;
        boolean done = false;
        do {
            int maxCategory = 1;
            // Compute max category for remaining unmapped registers.
            int sz = specs.size();
            for (int i = 0; i < sz; i++) {
                RegisterSpec ssaSpec = specs.get(i);
                int category = ssaSpec.getCategory();
                if (!ssaRegsMapped.get(ssaSpec.getReg()) && category > maxCategory) {
                    maxCategory = category;
                }
            }
            ropReg = findRopRegForLocal(ropReg, maxCategory);
            if (canMapRegs(specs, ropReg)) {
                done = tryMapRegs(specs, ropReg, maxCategory, true);
            }
            // Increment for next call to findRopRegForLocal.
            ropReg++;
        } while (!done);
    }
}
Also used : RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 17 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

the class FirstFitLocalCombiningAllocator method handleCheckCastResults.

/**
     * Handles check cast results to reuse the same source register.
     * Inserts a move if it can't map the same register to both and the
     * check cast is not caught.
     */
private void handleCheckCastResults() {
    for (NormalSsaInsn insn : moveResultPseudoInsns) {
        RegisterSpec moveRegSpec = insn.getResult();
        int moveReg = moveRegSpec.getReg();
        BitSet predBlocks = insn.getBlock().getPredecessors();
        // Expect one predecessor block only
        if (predBlocks.cardinality() != 1) {
            continue;
        }
        SsaBasicBlock predBlock = ssaMeth.getBlocks().get(predBlocks.nextSetBit(0));
        ArrayList<SsaInsn> insnList = predBlock.getInsns();
        /**
             * If the predecessor block has a check-cast, it will be the last
             * instruction
             */
        SsaInsn checkCastInsn = insnList.get(insnList.size() - 1);
        if (checkCastInsn.getOpcode().getOpcode() != RegOps.CHECK_CAST) {
            continue;
        }
        RegisterSpec checkRegSpec = checkCastInsn.getSources().get(0);
        int checkReg = checkRegSpec.getReg();
        /**
             * See if either register is already mapped. Most likely the move
             * result will be mapped already since the cast result is stored
             * in a local variable.
             */
        int category = checkRegSpec.getCategory();
        boolean moveMapped = ssaRegsMapped.get(moveReg);
        boolean checkMapped = ssaRegsMapped.get(checkReg);
        if (moveMapped & !checkMapped) {
            int moveRopReg = mapper.oldToNew(moveReg);
            checkMapped = tryMapReg(checkRegSpec, moveRopReg, category);
        }
        if (checkMapped & !moveMapped) {
            int checkRopReg = mapper.oldToNew(checkReg);
            moveMapped = tryMapReg(moveRegSpec, checkRopReg, category);
        }
        // Map any unmapped registers to anything available
        if (!moveMapped || !checkMapped) {
            int ropReg = findNextUnreservedRopReg(paramRangeEnd, category);
            ArrayList<RegisterSpec> ssaRegs = new ArrayList<RegisterSpec>(2);
            ssaRegs.add(moveRegSpec);
            ssaRegs.add(checkRegSpec);
            while (!tryMapRegs(ssaRegs, ropReg, category, false)) {
                ropReg = findNextUnreservedRopReg(ropReg + 1, category);
            }
        }
        /*
             * If source and result have a different mapping, insert a move so
             * they can have the same mapping. Don't do this if the check cast
             * is caught, since it will overwrite a potentially live value.
             */
        boolean hasExceptionHandlers = checkCastInsn.getOriginalRopInsn().getCatches().size() != 0;
        int moveRopReg = mapper.oldToNew(moveReg);
        int checkRopReg = mapper.oldToNew(checkReg);
        if (moveRopReg != checkRopReg && !hasExceptionHandlers) {
            ((NormalSsaInsn) checkCastInsn).changeOneSource(0, insertMoveBefore(checkCastInsn, checkRegSpec));
            addMapping(checkCastInsn.getSources().get(0), moveRopReg);
        }
    }
}
Also used : NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) SsaBasicBlock(com.android.dx.ssa.SsaBasicBlock) BitSet(java.util.BitSet) ArrayList(java.util.ArrayList) NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) SsaInsn(com.android.dx.ssa.SsaInsn) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 18 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

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 19 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

the class FirstFitLocalCombiningAllocator method adjustAndMapSourceRangeRange.

/**
     * Maps the source registers of the specified instruction such that they
     * will fall in a contiguous range in rop form. Moves are inserted as
     * necessary to allow the range to be allocated.
     *
     * @param insn {@code non-null;} insn whos sources to process
     */
private void adjustAndMapSourceRangeRange(NormalSsaInsn insn) {
    int newRegStart = findRangeAndAdjust(insn);
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    int nextRopReg = newRegStart;
    for (int i = 0; i < szSources; i++) {
        RegisterSpec source = sources.get(i);
        int sourceReg = source.getReg();
        int category = source.getCategory();
        int curRopReg = nextRopReg;
        nextRopReg += category;
        if (ssaRegsMapped.get(sourceReg)) {
            continue;
        }
        LocalItem localItem = getLocalItemForReg(sourceReg);
        addMapping(source, curRopReg);
        if (localItem != null) {
            markReserved(curRopReg, category);
            ArrayList<RegisterSpec> similarRegisters = localVariables.get(localItem);
            int szSimilar = similarRegisters.size();
            /*
                 * Try to map all SSA registers also associated with
                 * this local.
                 */
            for (int j = 0; j < szSimilar; j++) {
                RegisterSpec similarSpec = similarRegisters.get(j);
                int similarReg = similarSpec.getReg();
                // Don't map anything that's also a source.
                if (-1 != sources.indexOfRegister(similarReg)) {
                    continue;
                }
                // Registers left unmapped will get handled later.
                tryMapReg(similarSpec, curRopReg, category);
            }
        }
    }
}
Also used : LocalItem(com.android.dx.rop.code.LocalItem) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 20 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.

the class FirstFitLocalCombiningAllocator method handleUnassociatedParameters.

/**
     * Maps any parameter that isn't local-associated, which can happen
     * in the case where there is no java debug info.
     */
private void handleUnassociatedParameters() {
    int szSsaRegs = ssaMeth.getRegCount();
    for (int ssaReg = 0; ssaReg < szSsaRegs; ssaReg++) {
        if (ssaRegsMapped.get(ssaReg)) {
            // We already did this one above
            continue;
        }
        int paramIndex = getParameterIndexForReg(ssaReg);
        RegisterSpec ssaSpec = getDefinitionSpecForSsaReg(ssaReg);
        if (paramIndex >= 0) {
            addMapping(ssaSpec, paramIndex);
        }
    }
}
Also used : RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Aggregations

RegisterSpec (com.android.dx.rop.code.RegisterSpec)135 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)50 PlainInsn (com.android.dx.rop.code.PlainInsn)24 Constant (com.android.dx.rop.cst.Constant)20 TypedConstant (com.android.dx.rop.cst.TypedConstant)16 TypeBearer (com.android.dx.rop.type.TypeBearer)16 ArrayList (java.util.ArrayList)16 Insn (com.android.dx.rop.code.Insn)14 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)14 Rop (com.android.dx.rop.code.Rop)14 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)14 CstType (com.android.dx.rop.cst.CstType)14 BitSet (java.util.BitSet)11 LocalItem (com.android.dx.rop.code.LocalItem)10 RegisterSpecSet (com.android.dx.rop.code.RegisterSpecSet)10 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)10 CstString (com.android.dx.rop.cst.CstString)10 HashSet (java.util.HashSet)10 SourcePosition (com.android.dx.rop.code.SourcePosition)8 CstFieldRef (com.android.dx.rop.cst.CstFieldRef)8