Search in sources :

Example 11 with PlainInsn

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

the class ConstCollector method run.

/**
     * Applies the optimization.
     */
private void run() {
    int regSz = ssaMeth.getRegCount();
    ArrayList<TypedConstant> constantList = getConstsSortedByCountUse();
    int toCollect = Math.min(constantList.size(), MAX_COLLECTED_CONSTANTS);
    SsaBasicBlock start = ssaMeth.getEntryBlock();
    // Constant to new register containing the constant
    HashMap<TypedConstant, RegisterSpec> newRegs = new HashMap<TypedConstant, RegisterSpec>(toCollect);
    for (int i = 0; i < toCollect; i++) {
        TypedConstant cst = constantList.get(i);
        RegisterSpec result = RegisterSpec.make(ssaMeth.makeNewSsaReg(), cst);
        Rop constRop = Rops.opConst(cst);
        if (constRop.getBranchingness() == Rop.BRANCH_NONE) {
            start.addInsnToHead(new PlainCstInsn(Rops.opConst(cst), SourcePosition.NO_INFO, result, RegisterSpecList.EMPTY, cst));
        } else {
            // We need two new basic blocks along with the new insn
            SsaBasicBlock entryBlock = ssaMeth.getEntryBlock();
            SsaBasicBlock successorBlock = entryBlock.getPrimarySuccessor();
            // Insert a block containing the const insn.
            SsaBasicBlock constBlock = entryBlock.insertNewSuccessor(successorBlock);
            constBlock.replaceLastInsn(new ThrowingCstInsn(constRop, SourcePosition.NO_INFO, RegisterSpecList.EMPTY, StdTypeList.EMPTY, cst));
            // Insert a block containing the move-result-pseudo insn.
            SsaBasicBlock resultBlock = constBlock.insertNewSuccessor(successorBlock);
            PlainInsn insn = new PlainInsn(Rops.opMoveResultPseudo(result.getTypeBearer()), SourcePosition.NO_INFO, result, RegisterSpecList.EMPTY);
            resultBlock.addInsnToHead(insn);
        }
        newRegs.put(cst, result);
    }
    updateConstUses(newRegs, regSz);
}
Also used : PlainCstInsn(com.android.dx.rop.code.PlainCstInsn) PlainInsn(com.android.dx.rop.code.PlainInsn) Rop(com.android.dx.rop.code.Rop) ThrowingCstInsn(com.android.dx.rop.code.ThrowingCstInsn) TypedConstant(com.android.dx.rop.cst.TypedConstant) HashMap(java.util.HashMap) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 12 with PlainInsn

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

the class SCCP method replaceBranches.

/**
     * Replaces branches that have constant conditions with gotos
     */
private void replaceBranches() {
    for (SsaInsn insn : branchWorklist) {
        // Find if a successor block is never executed
        int oldSuccessor = -1;
        SsaBasicBlock block = insn.getBlock();
        int successorSize = block.getSuccessorList().size();
        for (int i = 0; i < successorSize; i++) {
            int successorBlock = block.getSuccessorList().get(i);
            if (!executableBlocks.get(successorBlock)) {
                oldSuccessor = successorBlock;
            }
        }
        /*
             * Prune branches that have already been handled and ones that no
             * longer have constant conditions (no nonexecutable successors)
             */
        if (successorSize != 2 || oldSuccessor == -1)
            continue;
        // Replace branch with goto
        Insn originalRopInsn = insn.getOriginalRopInsn();
        block.replaceLastInsn(new PlainInsn(Rops.GOTO, originalRopInsn.getPosition(), null, RegisterSpecList.EMPTY));
        block.removeSuccessor(oldSuccessor);
    }
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) Insn(com.android.dx.rop.code.Insn) PlainInsn(com.android.dx.rop.code.PlainInsn) CstInsn(com.android.dx.rop.code.CstInsn)

Example 13 with PlainInsn

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

the class SsaBasicBlock method addMoveToBeginning.

/**
     * Adds a move instruction after the phi insn block.
     *
     * @param result move destination
     * @param source move source
     */
public void addMoveToBeginning(RegisterSpec result, RegisterSpec source) {
    if (result.getReg() == source.getReg()) {
        // Sometimes we end up with no-op moves. Ignore them here.
        return;
    }
    RegisterSpecList sources = RegisterSpecList.make(source);
    NormalSsaInsn toAdd = new NormalSsaInsn(new PlainInsn(Rops.opMove(result.getType()), SourcePosition.NO_INFO, result, sources), this);
    insns.add(getCountPhiInsns(), toAdd);
    movesFromPhisAtBeginning++;
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList)

Example 14 with PlainInsn

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

the class SsaBasicBlock method addMoveToEnd.

/**
     * Adds a move instruction to the end of this basic block, just
     * before the last instruction. If the result of the final instruction
     * is the source in question, then the move is placed at the beginning of
     * the primary successor block. This is for unversioned registers.
     *
     * @param result move destination
     * @param source move source
     */
public void addMoveToEnd(RegisterSpec result, RegisterSpec source) {
    if (result.getReg() == source.getReg()) {
        // Sometimes we end up with no-op moves. Ignore them here.
        return;
    }
    /*
         * The last Insn has to be a normal SSA insn: a phi can't branch
         * or return or cause an exception, etc.
         */
    NormalSsaInsn lastInsn;
    lastInsn = (NormalSsaInsn) insns.get(insns.size() - 1);
    if (lastInsn.getResult() != null || lastInsn.getSources().size() > 0) {
        for (int i = successors.nextSetBit(0); i >= 0; i = successors.nextSetBit(i + 1)) {
            SsaBasicBlock succ;
            succ = parent.getBlocks().get(i);
            succ.addMoveToBeginning(result, source);
        }
    } else {
        /*
             * We can safely add a move to the end of the block just
             * before the last instruction, because the final insn does
             * not assign to anything.
             */
        RegisterSpecList sources = RegisterSpecList.make(source);
        NormalSsaInsn toAdd = new NormalSsaInsn(new PlainInsn(Rops.opMove(result.getType()), SourcePosition.NO_INFO, result, sources), this);
        insns.add(insns.size() - 1, toAdd);
        movesFromPhisAtEnd++;
    }
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList)

Example 15 with PlainInsn

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

the class SsaBasicBlock method scheduleUseBeforeAssigned.

/**
     * Ensures that all move operations in this block occur such that
     * reads of any register happen before writes to that register.
     * NOTE: caller is expected to returnSpareRegisters()!
     *
     * TODO: See Briggs, et al "Practical Improvements to the Construction and
     * Destruction of Static Single Assignment Form" section 5. a) This can
     * be done in three passes.
     *
     * @param toSchedule List of instructions. Must consist only of moves.
     */
private void scheduleUseBeforeAssigned(List<SsaInsn> toSchedule) {
    BitSet regsUsedAsSources = new BitSet(parent.getRegCount());
    // TODO: Get rid of this.
    BitSet regsUsedAsResults = new BitSet(parent.getRegCount());
    int sz = toSchedule.size();
    int insertPlace = 0;
    while (insertPlace < sz) {
        int oldInsertPlace = insertPlace;
        // Record all registers used as sources in this block.
        for (int i = insertPlace; i < sz; i++) {
            setRegsUsed(regsUsedAsSources, toSchedule.get(i).getSources().get(0));
            setRegsUsed(regsUsedAsResults, toSchedule.get(i).getResult());
        }
        /*
             * If there are no circular dependencies, then there exists
             * n instructions where n > 1 whose result is not used as a source.
             */
        for (int i = insertPlace; i < sz; i++) {
            SsaInsn insn = toSchedule.get(i);
            /*
                 * Move these n registers to the front, since they overwrite
                 * nothing.
                 */
            if (!checkRegUsed(regsUsedAsSources, insn.getResult())) {
                Collections.swap(toSchedule, i, insertPlace++);
            }
        }
        /*
             * If we've made no progress in this iteration, there's a
             * circular dependency. Split it using the temp reg.
             */
        if (oldInsertPlace == insertPlace) {
            SsaInsn insnToSplit = null;
            // Find an insn whose result is used as a source.
            for (int i = insertPlace; i < sz; i++) {
                SsaInsn insn = toSchedule.get(i);
                if (checkRegUsed(regsUsedAsSources, insn.getResult()) && checkRegUsed(regsUsedAsResults, insn.getSources().get(0))) {
                    insnToSplit = insn;
                    /*
                         * We're going to split this insn; move it to the
                         * front.
                         */
                    Collections.swap(toSchedule, insertPlace, i);
                    break;
                }
            }
            // At least one insn will be set above.
            RegisterSpec result = insnToSplit.getResult();
            RegisterSpec tempSpec = result.withReg(parent.borrowSpareRegister(result.getCategory()));
            NormalSsaInsn toAdd = new NormalSsaInsn(new PlainInsn(Rops.opMove(result.getType()), SourcePosition.NO_INFO, tempSpec, insnToSplit.getSources()), this);
            toSchedule.add(insertPlace++, toAdd);
            RegisterSpecList newSources = RegisterSpecList.make(tempSpec);
            NormalSsaInsn toReplace = new NormalSsaInsn(new PlainInsn(Rops.opMove(result.getType()), SourcePosition.NO_INFO, result, newSources), this);
            toSchedule.set(insertPlace, toReplace);
            // The size changed.
            sz = toSchedule.size();
        }
        regsUsedAsSources.clear();
        regsUsedAsResults.clear();
    }
}
Also used : PlainInsn(com.android.dx.rop.code.PlainInsn) BitSet(java.util.BitSet) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Aggregations

PlainInsn (com.android.dx.rop.code.PlainInsn)17 Insn (com.android.dx.rop.code.Insn)10 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)9 RegisterSpec (com.android.dx.rop.code.RegisterSpec)9 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)8 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)7 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)6 SourcePosition (com.android.dx.rop.code.SourcePosition)6 BasicBlock (com.android.dx.rop.code.BasicBlock)5 InsnList (com.android.dx.rop.code.InsnList)5 Rop (com.android.dx.rop.code.Rop)5 CstType (com.android.dx.rop.cst.CstType)3 FillArrayDataInsn (com.android.dx.rop.code.FillArrayDataInsn)2 StdTypeList (com.android.dx.rop.type.StdTypeList)2 Type (com.android.dx.rop.type.Type)2 IntList (com.android.dx.util.IntList)2 BitSet (java.util.BitSet)2 CstInsn (com.android.dx.rop.code.CstInsn)1 LocalItem (com.android.dx.rop.code.LocalItem)1 SwitchInsn (com.android.dx.rop.code.SwitchInsn)1