Search in sources :

Example 1 with SsaInsn

use of com.android.dx.ssa.SsaInsn 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 SsaInsn

use of com.android.dx.ssa.SsaInsn 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 3 with SsaInsn

use of com.android.dx.ssa.SsaInsn 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 4 with SsaInsn

use of com.android.dx.ssa.SsaInsn in project buck by facebook.

the class FirstFitLocalCombiningAllocator method getParameterIndexForReg.

/**
     * Gets the parameter index for SSA registers that are method parameters.
     * {@code -1} is returned for non-parameter registers.
     *
     * @param ssaReg {@code >=0;} SSA register to look up
     * @return parameter index or {@code -1} if not a parameter
     */
private int getParameterIndexForReg(int ssaReg) {
    SsaInsn defInsn = ssaMeth.getDefinitionForRegister(ssaReg);
    if (defInsn == null) {
        return -1;
    }
    Rop opcode = defInsn.getOpcode();
    // opcode == null for phi insns.
    if (opcode != null && opcode.getOpcode() == RegOps.MOVE_PARAM) {
        CstInsn origInsn = (CstInsn) defInsn.getOriginalRopInsn();
        return ((CstInteger) origInsn.getConstant()).getValue();
    }
    return -1;
}
Also used : CstInsn(com.android.dx.rop.code.CstInsn) Rop(com.android.dx.rop.code.Rop) CstInteger(com.android.dx.rop.cst.CstInteger) NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) SsaInsn(com.android.dx.ssa.SsaInsn)

Example 5 with SsaInsn

use of com.android.dx.ssa.SsaInsn in project buck by facebook.

the class LivenessAnalyzer method run.

/**
     * From Appel algorithm 19.17.
     */
public void run() {
    List<SsaInsn> useList = ssaMeth.getUseListForRegister(regV);
    for (SsaInsn insn : useList) {
        nextFunction = NextFunction.DONE;
        if (insn instanceof PhiInsn) {
            // If s is a phi-function with V as it's ith argument.
            PhiInsn phi = (PhiInsn) insn;
            for (SsaBasicBlock pred : phi.predBlocksForReg(regV, ssaMeth)) {
                blockN = pred;
                nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
                handleTailRecursion();
            }
        } else {
            blockN = insn.getBlock();
            statementIndex = blockN.getInsns().indexOf(insn);
            if (statementIndex < 0) {
                throw new RuntimeException("insn not found in it's own block");
            }
            nextFunction = NextFunction.LIVE_IN_AT_STATEMENT;
            handleTailRecursion();
        }
    }
    int nextLiveOutBlock;
    while ((nextLiveOutBlock = liveOutBlocks.nextSetBit(0)) >= 0) {
        blockN = ssaMeth.getBlocks().get(nextLiveOutBlock);
        liveOutBlocks.clear(nextLiveOutBlock);
        nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
        handleTailRecursion();
    }
}
Also used : PhiInsn(com.android.dx.ssa.PhiInsn) SsaBasicBlock(com.android.dx.ssa.SsaBasicBlock) SsaInsn(com.android.dx.ssa.SsaInsn)

Aggregations

SsaInsn (com.android.dx.ssa.SsaInsn)9 SsaBasicBlock (com.android.dx.ssa.SsaBasicBlock)5 RegisterSpec (com.android.dx.rop.code.RegisterSpec)4 NormalSsaInsn (com.android.dx.ssa.NormalSsaInsn)4 ArrayList (java.util.ArrayList)3 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)2 Rop (com.android.dx.rop.code.Rop)2 BitSet (java.util.BitSet)2 ConcreteMethod (com.android.dx.cf.code.ConcreteMethod)1 Method (com.android.dx.cf.iface.Method)1 CstInsn (com.android.dx.rop.code.CstInsn)1 DexTranslationAdvice (com.android.dx.rop.code.DexTranslationAdvice)1 PlainInsn (com.android.dx.rop.code.PlainInsn)1 RopMethod (com.android.dx.rop.code.RopMethod)1 TranslationAdvice (com.android.dx.rop.code.TranslationAdvice)1 CstInteger (com.android.dx.rop.cst.CstInteger)1 Optimizer (com.android.dx.ssa.Optimizer)1 PhiInsn (com.android.dx.ssa.PhiInsn)1 SsaMethod (com.android.dx.ssa.SsaMethod)1 IntIterator (com.android.dx.util.IntIterator)1