Java Code Examples for com.android.dx.rop.code.RegisterSpecList#make()

The following examples show how to use com.android.dx.rop.code.RegisterSpecList#make() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: RopTranslator.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Gets the complete register list (result and sources) out of a
 * given rop instruction. For insns that are commutative, have
 * two register sources, and have a source equal to the result,
 * place that source first.
 *
 * @param insn {@code non-null;} instruction in question
 * @param resultReg {@code null-ok;} the real result to use (ignore the insn's)
 * @return {@code non-null;} the instruction's complete register list
 */
private static RegisterSpecList getRegs(Insn insn,
        RegisterSpec resultReg) {
    RegisterSpecList regs = insn.getSources();

    if (insn.getOpcode().isCommutative()
            && (regs.size() == 2)
            && (resultReg.getReg() == regs.get(1).getReg())) {

        /*
         * For commutative ops which have two register sources,
         * if the second source is the same register as the result,
         * swap the sources so that an opcode of form 12x can be selected
         * instead of one of form 23x
         */

        regs = RegisterSpecList.make(regs.get(1), regs.get(0));
    }

    if (resultReg == null) {
        return regs;
    }

    return regs.withFirst(resultReg);
}
 
Example 2
Source File: RopTranslator.java    From buck with Apache License 2.0 6 votes vote down vote up
/**
 * Gets the complete register list (result and sources) out of a
 * given rop instruction. For insns that are commutative, have
 * two register sources, and have a source equal to the result,
 * place that source first.
 *
 * @param insn {@code non-null;} instruction in question
 * @param resultReg {@code null-ok;} the real result to use (ignore the insn's)
 * @return {@code non-null;} the instruction's complete register list
 */
private static RegisterSpecList getRegs(Insn insn,
        RegisterSpec resultReg) {
    RegisterSpecList regs = insn.getSources();

    if (insn.getOpcode().isCommutative()
            && (regs.size() == 2)
            && (resultReg.getReg() == regs.get(1).getReg())) {

        /*
         * For commutative ops which have two register sources,
         * if the second source is the same register as the result,
         * swap the sources so that an opcode of form 12x can be selected
         * instead of one of form 23x
         */

        regs = RegisterSpecList.make(regs.get(1), regs.get(0));
    }

    if (resultReg == null) {
        return regs;
    }

    return regs.withFirst(resultReg);
}
 
Example 3
Source File: DalvInsn.java    From J2ME-Loader with Apache License 2.0 6 votes vote down vote up
/**
 * Makes a move instruction, appropriate and ideal for the given arguments.
 *
 * @param position {@code non-null;} source position information
 * @param dest {@code non-null;} destination register
 * @param src {@code non-null;} source register
 * @return {@code non-null;} an appropriately-constructed instance
 */
public static SimpleInsn makeMove(SourcePosition position,
        RegisterSpec dest, RegisterSpec src) {
    boolean category1 = dest.getCategory() == 1;
    boolean reference = dest.getType().isReference();
    int destReg = dest.getReg();
    int srcReg = src.getReg();
    Dop opcode;

    if ((srcReg | destReg) < 16) {
        opcode = reference ? Dops.MOVE_OBJECT :
            (category1 ? Dops.MOVE : Dops.MOVE_WIDE);
    } else if (destReg < 256) {
        opcode = reference ? Dops.MOVE_OBJECT_FROM16 :
            (category1 ? Dops.MOVE_FROM16 : Dops.MOVE_WIDE_FROM16);
    } else {
        opcode = reference ? Dops.MOVE_OBJECT_16 :
            (category1 ? Dops.MOVE_16 : Dops.MOVE_WIDE_16);
    }

    return new SimpleInsn(opcode, position,
                          RegisterSpecList.make(dest, src));
}
 
Example 4
Source File: RopTranslator.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Gets the complete register list (result and sources) out of a
 * given rop instruction. For insns that are commutative, have
 * two register sources, and have a source equal to the result,
 * place that source first.
 *
 * @param insn {@code non-null;} instruction in question
 * @param resultReg {@code null-ok;} the real result to use (ignore the insn's)
 * @return {@code non-null;} the instruction's complete register list
 */
private static RegisterSpecList getRegs(Insn insn,
        RegisterSpec resultReg) {
    RegisterSpecList regs = insn.getSources();

    if (insn.getOpcode().isCommutative()
            && (regs.size() == 2)
            && (resultReg.getReg() == regs.get(1).getReg())) {

        /*
         * For commutative ops which have two register sources,
         * if the second source is the same register as the result,
         * swap the sources so that an opcode of form 12x can be selected
         * instead of one of form 23x
         */

        regs = RegisterSpecList.make(regs.get(1), regs.get(0));
    }

    if (resultReg == null) {
        return regs;
    }

    return regs.withFirst(resultReg);
}
 
Example 5
Source File: DalvInsn.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Makes a move instruction, appropriate and ideal for the given arguments.
 *
 * @param position {@code non-null;} source position information
 * @param dest {@code non-null;} destination register
 * @param src {@code non-null;} source register
 * @return {@code non-null;} an appropriately-constructed instance
 */
public static SimpleInsn makeMove(SourcePosition position,
        RegisterSpec dest, RegisterSpec src) {
    boolean category1 = dest.getCategory() == 1;
    boolean reference = dest.getType().isReference();
    int destReg = dest.getReg();
    int srcReg = src.getReg();
    Dop opcode;

    if ((srcReg | destReg) < 16) {
        opcode = reference ? Dops.MOVE_OBJECT :
            (category1 ? Dops.MOVE : Dops.MOVE_WIDE);
    } else if (destReg < 256) {
        opcode = reference ? Dops.MOVE_OBJECT_FROM16 :
            (category1 ? Dops.MOVE_FROM16 : Dops.MOVE_WIDE_FROM16);
    } else {
        opcode = reference ? Dops.MOVE_OBJECT_16 :
            (category1 ? Dops.MOVE_16 : Dops.MOVE_WIDE_16);
    }

    return new SimpleInsn(opcode, position,
                          RegisterSpecList.make(dest, src));
}
 
Example 6
Source File: DalvInsn.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Makes a move instruction, appropriate and ideal for the given arguments.
 *
 * @param position {@code non-null;} source position information
 * @param dest {@code non-null;} destination register
 * @param src {@code non-null;} source register
 * @return {@code non-null;} an appropriately-constructed instance
 */
public static SimpleInsn makeMove(SourcePosition position,
        RegisterSpec dest, RegisterSpec src) {
    boolean category1 = dest.getCategory() == 1;
    boolean reference = dest.getType().isReference();
    int destReg = dest.getReg();
    int srcReg = src.getReg();
    Dop opcode;

    if ((srcReg | destReg) < 16) {
        opcode = reference ? Dops.MOVE_OBJECT :
            (category1 ? Dops.MOVE : Dops.MOVE_WIDE);
    } else if (destReg < 256) {
        opcode = reference ? Dops.MOVE_OBJECT_FROM16 :
            (category1 ? Dops.MOVE_FROM16 : Dops.MOVE_WIDE_FROM16);
    } else {
        opcode = reference ? Dops.MOVE_OBJECT_16 :
            (category1 ? Dops.MOVE_16 : Dops.MOVE_WIDE_16);
    }

    return new SimpleInsn(opcode, position,
                          RegisterSpecList.make(dest, src));
}
 
Example 7
Source File: SsaBasicBlock.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * 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++;
}
 
Example 8
Source File: RopTranslator.java    From Box with Apache License 2.0 5 votes vote down vote up
/** {@inheritDoc} */
@Override
public void visitPlainCstInsn(PlainCstInsn insn) {
    SourcePosition pos = insn.getPosition();
    Dop opcode = RopToDop.dopFor(insn);
    Rop rop = insn.getOpcode();
    int ropOpcode = rop.getOpcode();
    DalvInsn di;

    if (rop.getBranchingness() != Rop.BRANCH_NONE) {
        throw new RuntimeException("shouldn't happen");
    }

    if (ropOpcode == RegOps.MOVE_PARAM) {
        if (!paramsAreInOrder) {
            /*
             * Parameters are not in order at the top of the reg space.
             * We need to add moves.
             */

            RegisterSpec dest = insn.getResult();
            int param =
                ((CstInteger) insn.getConstant()).getValue();
            RegisterSpec source =
                RegisterSpec.make(regCount - paramSize + param,
                        dest.getType());
            di = new SimpleInsn(opcode, pos,
                                RegisterSpecList.make(dest, source));
            addOutput(di);
        }
    } else {
        // No moves required for the parameters
        RegisterSpecList regs = getRegs(insn);
        di = new CstInsn(opcode, pos, regs, insn.getConstant());
        addOutput(di);
    }
}
 
Example 9
Source File: SsaBasicBlock.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * 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++;
}
 
Example 10
Source File: RopTranslator.java    From Box with Apache License 2.0 5 votes vote down vote up
/** {@inheritDoc} */
@Override
public void visitPlainCstInsn(PlainCstInsn insn) {
    SourcePosition pos = insn.getPosition();
    Dop opcode = RopToDop.dopFor(insn);
    Rop rop = insn.getOpcode();
    int ropOpcode = rop.getOpcode();
    DalvInsn di;

    if (rop.getBranchingness() != Rop.BRANCH_NONE) {
        throw new RuntimeException("shouldn't happen");
    }

    if (ropOpcode == RegOps.MOVE_PARAM) {
        if (!paramsAreInOrder) {
            /*
             * Parameters are not in order at the top of the reg space.
             * We need to add moves.
             */

            RegisterSpec dest = insn.getResult();
            int param =
                ((CstInteger) insn.getConstant()).getValue();
            RegisterSpec source =
                RegisterSpec.make(regCount - paramSize + param,
                        dest.getType());
            di = new SimpleInsn(opcode, pos,
                                RegisterSpecList.make(dest, source));
            addOutput(di);
        }
    } else {
        // No moves required for the parameters
        RegisterSpecList regs = getRegs(insn);
        di = new CstInsn(opcode, pos, regs, insn.getConstant());
        addOutput(di);
    }
}
 
Example 11
Source File: SsaBasicBlock.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * 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++;
}
 
Example 12
Source File: SsaBasicBlock.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * 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++;
}
 
Example 13
Source File: RopTranslator.java    From buck with Apache License 2.0 5 votes vote down vote up
/** {@inheritDoc} */
public void visitPlainCstInsn(PlainCstInsn insn) {
    SourcePosition pos = insn.getPosition();
    Dop opcode = RopToDop.dopFor(insn);
    Rop rop = insn.getOpcode();
    int ropOpcode = rop.getOpcode();
    DalvInsn di;

    if (rop.getBranchingness() != Rop.BRANCH_NONE) {
        throw new RuntimeException("shouldn't happen");
    }

    if (ropOpcode == RegOps.MOVE_PARAM) {
        if (!paramsAreInOrder) {
            /*
             * Parameters are not in order at the top of the reg space.
             * We need to add moves.
             */

            RegisterSpec dest = insn.getResult();
            int param =
                ((CstInteger) insn.getConstant()).getValue();
            RegisterSpec source =
                RegisterSpec.make(regCount - paramSize + param,
                        dest.getType());
            di = new SimpleInsn(opcode, pos,
                                RegisterSpecList.make(dest, source));
            addOutput(di);
        }
    } else {
        // No moves required for the parameters
        RegisterSpecList regs = getRegs(insn);
        di = new CstInsn(opcode, pos, regs, insn.getConstant());
        addOutput(di);
    }
}
 
Example 14
Source File: SsaBasicBlock.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * 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) {
    /*
     * Check that there are no other successors otherwise we may
     * insert a move that affects those (b/69128828).
     */
    if (successors.cardinality() > 1) {
        throw new IllegalStateException("Inserting a move to a block with multiple successors");
    }

    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) {
        /*
         * The final insn in this block has a source or result
         * register, and the moves we may need to place and
         * schedule may interfere. We need to insert this
         * instruction at the beginning of the primary successor
         * block instead. We know this is safe, because when we
         * edge-split earlier, we ensured that each successor has
         * only us as a predecessor.
         */

        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++;
    }
}
 
Example 15
Source File: SsaRenamer.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * {@inheritDoc}
 *
 * Move insns are treated as a simple mapping operation, and
 * will later be removed unless they represent a local variable
 * assignment. If they represent a local variable assignement, they
 * are preserved.
 */
@Override
public void visitMoveInsn(NormalSsaInsn insn) {
    /*
     * For moves: copy propogate the move if we can, but don't
     * if we need to preserve local variable info and the
     * result has a different name than the source.
     */

    RegisterSpec ropResult = insn.getResult();
    int ropResultReg = ropResult.getReg();
    int ropSourceReg = insn.getSources().get(0).getReg();

    insn.mapSourceRegisters(mapper);
    int ssaSourceReg = insn.getSources().get(0).getReg();

    LocalItem sourceLocal
        = currentMapping[ropSourceReg].getLocalItem();
    LocalItem resultLocal = ropResult.getLocalItem();

    /*
     * A move from a register that's currently associated with a local
     * to one that will not be associated with a local does not need
     * to be preserved, but the local association should remain.
     * Hence, we inherit the sourceLocal where the resultLocal is null.
     */

    LocalItem newLocal
        = (resultLocal == null) ? sourceLocal : resultLocal;
    LocalItem associatedLocal = getLocalForNewReg(ssaSourceReg);

    /*
     * If we take the new local, will only one local have ever
     * been associated with this SSA reg?
     */
    boolean onlyOneAssociatedLocal
            = associatedLocal == null || newLocal == null
            || newLocal.equals(associatedLocal);

    /*
     * If we're going to copy-propogate, then the ssa register
     * spec that's going to go into the mapping is made up of
     * the source register number mapped from above, the type
     * of the result, and the name either from the result (if
     * specified) or inherited from the existing mapping.
     *
     * The move source has incomplete type information in null
     * object cases, so the result type is used.
     */
    RegisterSpec ssaReg
            = RegisterSpec.makeLocalOptional(
                ssaSourceReg, ropResult.getType(), newLocal);

    if (!Optimizer.getPreserveLocals() || (onlyOneAssociatedLocal
            && equalsHandlesNulls(newLocal, sourceLocal)) &&
            threshold == 0) {
        /*
         * We don't have to keep this move to preserve local
         * information. Either the name is the same, or the result
         * register spec is unnamed.
         */

        addMapping(ropResultReg, ssaReg);
    } else if (onlyOneAssociatedLocal && sourceLocal == null &&
            threshold == 0) {
        /*
         * The register was previously unnamed. This means that a
         * local starts after it's first assignment in SSA form
         */

        RegisterSpecList ssaSources = RegisterSpecList.make(
                RegisterSpec.make(ssaReg.getReg(),
                        ssaReg.getType(), newLocal));

        SsaInsn newInsn
                = SsaInsn.makeFromRop(
                    new PlainInsn(Rops.opMarkLocal(ssaReg),
                    SourcePosition.NO_INFO, null, ssaSources),block);

        insnsToReplace.put(insn, newInsn);

        // Just map as above.
        addMapping(ropResultReg, ssaReg);
    } else {
        /*
         * Do not copy-propogate, since the two registers have
         * two different local-variable names.
         */
        processResultReg(insn);

        movesToKeep.add(insn);
    }
}
 
Example 16
Source File: SsaRenamer.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * {@inheritDoc}
 *
 * Move insns are treated as a simple mapping operation, and
 * will later be removed unless they represent a local variable
 * assignment. If they represent a local variable assignement, they
 * are preserved.
 */
@Override
public void visitMoveInsn(NormalSsaInsn insn) {
    /*
     * For moves: copy propogate the move if we can, but don't
     * if we need to preserve local variable info and the
     * result has a different name than the source.
     */

    RegisterSpec ropResult = insn.getResult();
    int ropResultReg = ropResult.getReg();
    int ropSourceReg = insn.getSources().get(0).getReg();

    insn.mapSourceRegisters(mapper);
    int ssaSourceReg = insn.getSources().get(0).getReg();

    LocalItem sourceLocal
        = currentMapping[ropSourceReg].getLocalItem();
    LocalItem resultLocal = ropResult.getLocalItem();

    /*
     * A move from a register that's currently associated with a local
     * to one that will not be associated with a local does not need
     * to be preserved, but the local association should remain.
     * Hence, we inherit the sourceLocal where the resultLocal is null.
     */

    LocalItem newLocal
        = (resultLocal == null) ? sourceLocal : resultLocal;
    LocalItem associatedLocal = getLocalForNewReg(ssaSourceReg);

    /*
     * If we take the new local, will only one local have ever
     * been associated with this SSA reg?
     */
    boolean onlyOneAssociatedLocal
            = associatedLocal == null || newLocal == null
            || newLocal.equals(associatedLocal);

    /*
     * If we're going to copy-propogate, then the ssa register
     * spec that's going to go into the mapping is made up of
     * the source register number mapped from above, the type
     * of the result, and the name either from the result (if
     * specified) or inherited from the existing mapping.
     *
     * The move source has incomplete type information in null
     * object cases, so the result type is used.
     */
    RegisterSpec ssaReg
            = RegisterSpec.makeLocalOptional(
                ssaSourceReg, ropResult.getType(), newLocal);

    if (!Optimizer.getPreserveLocals() || (onlyOneAssociatedLocal
            && equalsHandlesNulls(newLocal, sourceLocal)) &&
            threshold == 0) {
        /*
         * We don't have to keep this move to preserve local
         * information. Either the name is the same, or the result
         * register spec is unnamed.
         */

        addMapping(ropResultReg, ssaReg);
    } else if (onlyOneAssociatedLocal && sourceLocal == null &&
            threshold == 0) {
        /*
         * The register was previously unnamed. This means that a
         * local starts after it's first assignment in SSA form
         */

        RegisterSpecList ssaSources = RegisterSpecList.make(
                RegisterSpec.make(ssaReg.getReg(),
                        ssaReg.getType(), newLocal));

        SsaInsn newInsn
                = SsaInsn.makeFromRop(
                    new PlainInsn(Rops.opMarkLocal(ssaReg),
                    SourcePosition.NO_INFO, null, ssaSources),block);

        insnsToReplace.put(insn, newInsn);

        // Just map as above.
        addMapping(ropResultReg, ssaReg);
    } else {
        /*
         * Do not copy-propogate, since the two registers have
         * two different local-variable names.
         */
        processResultReg(insn);

        movesToKeep.add(insn);
    }
}
 
Example 17
Source File: SsaBasicBlock.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * 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) {
    /*
     * Check that there are no other successors otherwise we may
     * insert a move that affects those (b/69128828).
     */
    if (successors.cardinality() > 1) {
        throw new IllegalStateException("Inserting a move to a block with multiple successors");
    }

    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) {
        /*
         * The final insn in this block has a source or result
         * register, and the moves we may need to place and
         * schedule may interfere. We need to insert this
         * instruction at the beginning of the primary successor
         * block instead. We know this is safe, because when we
         * edge-split earlier, we ensured that each successor has
         * only us as a predecessor.
         */

        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++;
    }
}
 
Example 18
Source File: SsaRenamer.java    From buck with Apache License 2.0 4 votes vote down vote up
/**
 * {@inheritDoc}
 *
 * Move insns are treated as a simple mapping operation, and
 * will later be removed unless they represent a local variable
 * assignment. If they represent a local variable assignement, they
 * are preserved.
 */
public void visitMoveInsn(NormalSsaInsn insn) {
    /*
     * For moves: copy propogate the move if we can, but don't
     * if we need to preserve local variable info and the
     * result has a different name than the source.
     */

    RegisterSpec ropResult = insn.getResult();
    int ropResultReg = ropResult.getReg();
    int ropSourceReg = insn.getSources().get(0).getReg();

    insn.mapSourceRegisters(mapper);
    int ssaSourceReg = insn.getSources().get(0).getReg();

    LocalItem sourceLocal
        = currentMapping[ropSourceReg].getLocalItem();
    LocalItem resultLocal = ropResult.getLocalItem();

    /*
     * A move from a register that's currently associated with a local
     * to one that will not be associated with a local does not need
     * to be preserved, but the local association should remain.
     * Hence, we inherit the sourceLocal where the resultLocal is null.
     */

    LocalItem newLocal
        = (resultLocal == null) ? sourceLocal : resultLocal;
    LocalItem associatedLocal = getLocalForNewReg(ssaSourceReg);

    /*
     * If we take the new local, will only one local have ever
     * been associated with this SSA reg?
     */
    boolean onlyOneAssociatedLocal
            = associatedLocal == null || newLocal == null
            || newLocal.equals(associatedLocal);

    /*
     * If we're going to copy-propogate, then the ssa register
     * spec that's going to go into the mapping is made up of
     * the source register number mapped from above, the type
     * of the result, and the name either from the result (if
     * specified) or inherited from the existing mapping.
     *
     * The move source has incomplete type information in null
     * object cases, so the result type is used.
     */
    RegisterSpec ssaReg
            = RegisterSpec.makeLocalOptional(
                ssaSourceReg, ropResult.getType(), newLocal);

    if (!Optimizer.getPreserveLocals() || (onlyOneAssociatedLocal
            && equalsHandlesNulls(newLocal, sourceLocal)) &&
            threshold == 0) {
        /*
         * We don't have to keep this move to preserve local
         * information. Either the name is the same, or the result
         * register spec is unnamed.
         */

        addMapping(ropResultReg, ssaReg);
    } else if (onlyOneAssociatedLocal && sourceLocal == null &&
            threshold == 0) {
        /*
         * The register was previously unnamed. This means that a
         * local starts after it's first assignment in SSA form
         */

        RegisterSpecList ssaSources = RegisterSpecList.make(
                RegisterSpec.make(ssaReg.getReg(),
                        ssaReg.getType(), newLocal));

        SsaInsn newInsn
                = SsaInsn.makeFromRop(
                    new PlainInsn(Rops.opMarkLocal(ssaReg),
                    SourcePosition.NO_INFO, null, ssaSources),block);

        insnsToReplace.put(insn, newInsn);

        // Just map as above.
        addMapping(ropResultReg, ssaReg);
    } else {
        /*
         * Do not copy-propogate, since the two registers have
         * two different local-variable names.
         */
        processResultReg(insn);

        movesToKeep.add(insn);
    }
}
 
Example 19
Source File: SsaRenamer.java    From J2ME-Loader with Apache License 2.0 4 votes vote down vote up
/**
       * {@inheritDoc}
       *
       * Move insns are treated as a simple mapping operation, and
       * will later be removed unless they represent a local variable
       * assignment. If they represent a local variable assignement, they
       * are preserved.
       */
      @Override
public void visitMoveInsn(NormalSsaInsn insn) {
          /*
           * For moves: copy propogate the move if we can, but don't
           * if we need to preserve local variable info and the
           * result has a different name than the source.
           */

          RegisterSpec ropResult = insn.getResult();
          int ropResultReg = ropResult.getReg();
          int ropSourceReg = insn.getSources().get(0).getReg();

          insn.mapSourceRegisters(mapper);
          int ssaSourceReg = insn.getSources().get(0).getReg();

          LocalItem sourceLocal
              = currentMapping[ropSourceReg].getLocalItem();
          LocalItem resultLocal = ropResult.getLocalItem();

          /*
           * A move from a register that's currently associated with a local
           * to one that will not be associated with a local does not need
           * to be preserved, but the local association should remain.
           * Hence, we inherit the sourceLocal where the resultLocal is null.
           */

          LocalItem newLocal
              = (resultLocal == null) ? sourceLocal : resultLocal;
          LocalItem associatedLocal = getLocalForNewReg(ssaSourceReg);

          /*
           * If we take the new local, will only one local have ever
           * been associated with this SSA reg?
           */
          boolean onlyOneAssociatedLocal
                  = associatedLocal == null || newLocal == null
                  || newLocal.equals(associatedLocal);

          /*
           * If we're going to copy-propogate, then the ssa register
           * spec that's going to go into the mapping is made up of
           * the source register number mapped from above, the type
           * of the result, and the name either from the result (if
           * specified) or inherited from the existing mapping.
           *
           * The move source has incomplete type information in null
           * object cases, so the result type is used.
           */
          RegisterSpec ssaReg
                  = RegisterSpec.makeLocalOptional(
                      ssaSourceReg, ropResult.getType(), newLocal);

          if (!Optimizer.getPreserveLocals() || (onlyOneAssociatedLocal
                  && equalsHandlesNulls(newLocal, sourceLocal)) &&
                  threshold == 0) {
              /*
               * We don't have to keep this move to preserve local
               * information. Either the name is the same, or the result
               * register spec is unnamed.
               */

              addMapping(ropResultReg, ssaReg);
          } else if (onlyOneAssociatedLocal && sourceLocal == null &&
                  threshold == 0) {
              /*
               * The register was previously unnamed. This means that a
               * local starts after it's first assignment in SSA form
               */

              RegisterSpecList ssaSources = RegisterSpecList.make(
                      RegisterSpec.make(ssaReg.getReg(),
                              ssaReg.getType(), newLocal));

              SsaInsn newInsn
                      = SsaInsn.makeFromRop(
                          new PlainInsn(Rops.opMarkLocal(ssaReg),
                          SourcePosition.NO_INFO, null, ssaSources),block);

              insnsToReplace.put(insn, newInsn);

              // Just map as above.
              addMapping(ropResultReg, ssaReg);
          } else {
              /*
               * Do not copy-propogate, since the two registers have
               * two different local-variable names.
               */
              processResultReg(insn);

              movesToKeep.add(insn);
          }
      }
 
Example 20
Source File: SsaBasicBlock.java    From J2ME-Loader with Apache License 2.0 4 votes vote down vote up
/**
 * 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) {
        /*
         * The final insn in this block has a source or result
         * register, and the moves we may need to place and
         * schedule may interfere. We need to insert this
         * instruction at the beginning of the primary successor
         * block instead. We know this is safe, because when we
         * edge-split earlier, we ensured that each successor has
         * only us as a predecessor.
         */

        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++;
    }
}