Search in sources :

Example 46 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.

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.taobao.android.dx.rop.code.PlainInsn) IntIterator(com.taobao.android.dx.util.IntIterator) IntSet(com.taobao.android.dx.util.IntSet) SsaBasicBlock(com.taobao.android.dx.ssa.SsaBasicBlock) SsaInsn(com.taobao.android.dx.ssa.SsaInsn) NormalSsaInsn(com.taobao.android.dx.ssa.NormalSsaInsn) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 47 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.

the class FirstFitLocalCombiningAllocator method handleNormalUnassociated.

/**
     * Maps all non-parameter, non-local variable registers.
     */
private void handleNormalUnassociated() {
    int szSsaRegs = ssaMeth.getRegCount();
    for (int ssaReg = 0; ssaReg < szSsaRegs; ssaReg++) {
        if (ssaRegsMapped.get(ssaReg)) {
            // We already did this one
            continue;
        }
        RegisterSpec ssaSpec = getDefinitionSpecForSsaReg(ssaReg);
        if (ssaSpec == null)
            continue;
        int category = ssaSpec.getCategory();
        // Find a rop reg that does not interfere
        int ropReg = findNextUnreservedRopReg(paramRangeEnd, category);
        while (!canMapReg(ssaSpec, ropReg)) {
            ropReg = findNextUnreservedRopReg(ropReg + 1, category);
        }
        addMapping(ssaSpec, ropReg);
    }
}
Also used : RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 48 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.

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.taobao.android.dx.rop.code.RegisterSpecList) SsaInsn(com.taobao.android.dx.ssa.SsaInsn) NormalSsaInsn(com.taobao.android.dx.ssa.NormalSsaInsn) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 49 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.

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.taobao.android.dx.ssa.NormalSsaInsn) SsaBasicBlock(com.taobao.android.dx.ssa.SsaBasicBlock) BitSet(java.util.BitSet) ArrayList(java.util.ArrayList) SsaInsn(com.taobao.android.dx.ssa.SsaInsn) NormalSsaInsn(com.taobao.android.dx.ssa.NormalSsaInsn) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 50 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.

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.taobao.android.dx.rop.code.RegisterSpec)

Aggregations

RegisterSpec (com.taobao.android.dx.rop.code.RegisterSpec)66 RegisterSpecList (com.taobao.android.dx.rop.code.RegisterSpecList)24 PlainInsn (com.taobao.android.dx.rop.code.PlainInsn)12 Constant (com.taobao.android.dx.rop.cst.Constant)10 TypedConstant (com.taobao.android.dx.rop.cst.TypedConstant)8 ArrayList (java.util.ArrayList)8 Insn (com.taobao.android.dx.rop.code.Insn)7 PlainCstInsn (com.taobao.android.dx.rop.code.PlainCstInsn)7 Rop (com.taobao.android.dx.rop.code.Rop)7 ThrowingCstInsn (com.taobao.android.dx.rop.code.ThrowingCstInsn)7 CstType (com.taobao.android.dx.rop.cst.CstType)7 TypeBearer (com.taobao.android.dx.rop.type.TypeBearer)7 LocalItem (com.taobao.android.dx.rop.code.LocalItem)5 RegisterSpecSet (com.taobao.android.dx.rop.code.RegisterSpecSet)5 ThrowingInsn (com.taobao.android.dx.rop.code.ThrowingInsn)5 CstString (com.taobao.android.dx.rop.cst.CstString)5 BitSet (java.util.BitSet)5 HashSet (java.util.HashSet)5 SourcePosition (com.taobao.android.dx.rop.code.SourcePosition)4 CstFieldRef (com.taobao.android.dx.rop.cst.CstFieldRef)4