Search in sources :

Example 6 with SsaBasicBlock

use of com.android.dx.ssa.SsaBasicBlock in project J2ME-Loader by nikita36078.

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 7 with SsaBasicBlock

use of com.android.dx.ssa.SsaBasicBlock in project J2ME-Loader by nikita36078.

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 8 with SsaBasicBlock

use of com.android.dx.ssa.SsaBasicBlock in project J2ME-Loader by nikita36078.

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 9 with SsaBasicBlock

use of com.android.dx.ssa.SsaBasicBlock in project J2ME-Loader by nikita36078.

the class SsaToRop method removePhiFunctions.

/**
 * See Appel 19.6. To remove the phi instructions in an edge-split
 * SSA representation we know we can always insert a move in a
 * predecessor block.
 */
private void removePhiFunctions() {
    ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
    for (SsaBasicBlock block : blocks) {
        // Add moves in all the pred blocks for each phi insn.
        block.forEachPhiInsn(new PhiVisitor(blocks));
        // Delete the phi insns.
        block.removeAllPhiInsns();
    }
    /*
         * After all move insns have been added, sort them so they don't
         * destructively interfere.
         */
    for (SsaBasicBlock block : blocks) {
        block.scheduleMovesFromPhis();
    }
}
Also used : SsaBasicBlock(com.android.dx.ssa.SsaBasicBlock)

Example 10 with SsaBasicBlock

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

the class LivenessAnalyzer method coInterferePhis.

/**
     * Ensures that all the phi result registers for all the phis in the
     * same basic block interfere with each other. This is needed since
     * the dead code remover has allowed through "dead-end phis" whose
     * results are not used except as local assignments. Without this step,
     * a the result of a dead-end phi might be assigned the same register
     * as the result of another phi, and the phi removal move scheduler may
     * generate moves that over-write the live result.
     *
     * @param ssaMeth {@code non-null;} method to pricess
     * @param interference {@code non-null;} interference graph
     */
private static void coInterferePhis(SsaMethod ssaMeth, InterferenceGraph interference) {
    for (SsaBasicBlock b : ssaMeth.getBlocks()) {
        List<SsaInsn> phis = b.getPhiInsns();
        int szPhis = phis.size();
        for (int i = 0; i < szPhis; i++) {
            for (int j = 0; j < szPhis; j++) {
                if (i == j) {
                    continue;
                }
                interference.add(phis.get(i).getResult().getReg(), phis.get(j).getResult().getReg());
            }
        }
    }
}
Also used : 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