Search in sources :

Example 1 with SsaBasicBlock

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

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

the class SsaToRop method convertBasicBlock.

/**
     * Converts a single basic block to rop form.
     *
     * @param block SSA block to process
     * @return {@code non-null;} ROP block
     */
private BasicBlock convertBasicBlock(SsaBasicBlock block) {
    IntList successorList = block.getRopLabelSuccessorList();
    int primarySuccessorLabel = block.getPrimarySuccessorRopLabel();
    // Filter out any reference to the SSA form's exit block.
    // Exit block may be null.
    SsaBasicBlock exitBlock = ssaMeth.getExitBlock();
    int exitRopLabel = (exitBlock == null) ? -1 : exitBlock.getRopLabel();
    if (successorList.contains(exitRopLabel)) {
        if (successorList.size() > 1) {
            throw new RuntimeException("Exit predecessor must have no other successors" + Hex.u2(block.getRopLabel()));
        } else {
            successorList = IntList.EMPTY;
            primarySuccessorLabel = -1;
            verifyValidExitPredecessor(block);
        }
    }
    successorList.setImmutable();
    BasicBlock result = new BasicBlock(block.getRopLabel(), convertInsns(block.getInsns()), successorList, primarySuccessorLabel);
    return result;
}
Also used : SsaBasicBlock(com.android.dx.ssa.SsaBasicBlock) SsaBasicBlock(com.android.dx.ssa.SsaBasicBlock) BasicBlock(com.android.dx.rop.code.BasicBlock) IntList(com.android.dx.util.IntList)

Example 3 with SsaBasicBlock

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

the class SsaToRop method convertBasicBlocks.

/**
     * @return rop-form basic block list
     */
private BasicBlockList convertBasicBlocks() {
    ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
    // Exit block may be null.
    SsaBasicBlock exitBlock = ssaMeth.getExitBlock();
    ssaMeth.computeReachability();
    int ropBlockCount = ssaMeth.getCountReachableBlocks();
    // Don't count the exit block, if it exists and is reachable.
    ropBlockCount -= (exitBlock != null && exitBlock.isReachable()) ? 1 : 0;
    BasicBlockList result = new BasicBlockList(ropBlockCount);
    // Convert all the reachable blocks except the exit block.
    int ropBlockIndex = 0;
    for (SsaBasicBlock b : blocks) {
        if (b.isReachable() && b != exitBlock) {
            result.set(ropBlockIndex++, convertBasicBlock(b));
        }
    }
    // The exit block, which is discarded, must do nothing.
    if (exitBlock != null && exitBlock.getInsns().size() != 0) {
        throw new RuntimeException("Exit block must have no insns when leaving SSA form");
    }
    return result;
}
Also used : SsaBasicBlock(com.android.dx.ssa.SsaBasicBlock) BasicBlockList(com.android.dx.rop.code.BasicBlockList)

Example 4 with SsaBasicBlock

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

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

SsaBasicBlock (com.android.dx.ssa.SsaBasicBlock)15 SsaInsn (com.android.dx.ssa.SsaInsn)9 RegisterSpec (com.android.dx.rop.code.RegisterSpec)4 NormalSsaInsn (com.android.dx.ssa.NormalSsaInsn)4 IntList (com.android.dx.util.IntList)3 ArrayList (java.util.ArrayList)3 BitSet (java.util.BitSet)3 BasicBlock (com.android.dx.rop.code.BasicBlock)2 BasicBlockList (com.android.dx.rop.code.BasicBlockList)2 PlainInsn (com.android.dx.rop.code.PlainInsn)2 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)2 PhiInsn (com.android.dx.ssa.PhiInsn)2 IntIterator (com.android.dx.util.IntIterator)2 IntSet (com.android.dx.util.IntSet)2 ConcreteMethod (com.android.dx.cf.code.ConcreteMethod)1 Method (com.android.dx.cf.iface.Method)1 DexTranslationAdvice (com.android.dx.rop.code.DexTranslationAdvice)1 RopMethod (com.android.dx.rop.code.RopMethod)1 TranslationAdvice (com.android.dx.rop.code.TranslationAdvice)1 Optimizer (com.android.dx.ssa.Optimizer)1