Search in sources :

Example 6 with TypeBearer

use of com.taobao.android.dx.rop.type.TypeBearer in project atlas by alibaba.

the class ConstCollector method updateConstUses.

/**
     * Updates all uses of various consts to use the values in the newly
     * assigned registers.
     *
     * @param newRegs {@code non-null;} mapping between constant and new reg
     * @param origRegCount {@code >=0;} original SSA reg count, not including
     * newly added constant regs
     */
private void updateConstUses(HashMap<TypedConstant, RegisterSpec> newRegs, int origRegCount) {
    /*
         * set of constants associated with a local variable; used
         * only if COLLECT_ONE_LOCAL is true.
         */
    final HashSet<TypedConstant> usedByLocal = new HashSet<TypedConstant>();
    final ArrayList<SsaInsn>[] useList = ssaMeth.getUseListCopy();
    for (int i = 0; i < origRegCount; i++) {
        SsaInsn insn = ssaMeth.getDefinitionForRegister(i);
        if (insn == null) {
            continue;
        }
        final RegisterSpec origReg = insn.getResult();
        TypeBearer typeBearer = insn.getResult().getTypeBearer();
        if (!typeBearer.isConstant())
            continue;
        TypedConstant cst = (TypedConstant) typeBearer;
        final RegisterSpec newReg = newRegs.get(cst);
        if (newReg == null) {
            continue;
        }
        if (ssaMeth.isRegALocal(origReg)) {
            if (!COLLECT_ONE_LOCAL) {
                continue;
            } else {
                /*
                     * TODO: If the same local gets the same cst
                     * multiple times, it would be nice to reuse the
                     * register.
                     */
                if (usedByLocal.contains(cst)) {
                    continue;
                } else {
                    usedByLocal.add(cst);
                    fixLocalAssignment(origReg, newRegs.get(cst));
                }
            }
        }
        // maps an original const register to the new collected register
        RegisterMapper mapper = new RegisterMapper() {

            @Override
            public int getNewRegisterCount() {
                return ssaMeth.getRegCount();
            }

            @Override
            public RegisterSpec map(RegisterSpec registerSpec) {
                if (registerSpec.getReg() == origReg.getReg()) {
                    return newReg.withLocalItem(registerSpec.getLocalItem());
                }
                return registerSpec;
            }
        };
        for (SsaInsn use : useList[origReg.getReg()]) {
            if (use.canThrow() && use.getBlock().getSuccessors().cardinality() > 1) {
                continue;
            }
            use.mapSourceRegisters(mapper);
        }
    }
}
Also used : TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) ArrayList(java.util.ArrayList) TypeBearer(com.taobao.android.dx.rop.type.TypeBearer) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec) HashSet(java.util.HashSet)

Example 7 with TypeBearer

use of com.taobao.android.dx.rop.type.TypeBearer in project atlas by alibaba.

the class EscapeAnalysis method scalarReplacement.

/**
     * Performs scalar replacement on all eligible arrays.
     */
private void scalarReplacement() {
    // Iterate through lattice, looking for non-escaping replaceable arrays
    for (EscapeSet escSet : latticeValues) {
        if (!escSet.replaceableArray || escSet.escape != EscapeState.NONE) {
            continue;
        }
        // Get the instructions for the definition and move of the array
        int e = escSet.regSet.nextSetBit(0);
        SsaInsn def = ssaMeth.getDefinitionForRegister(e);
        SsaInsn prev = getInsnForMove(def);
        // Create a map for the new registers that will be created
        TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
        int length = ((CstLiteralBits) lengthReg).getIntBits();
        ArrayList<RegisterSpec> newRegs = new ArrayList<RegisterSpec>(length);
        HashSet<SsaInsn> deletedInsns = new HashSet<SsaInsn>();
        // Replace the definition of the array with registers
        replaceDef(def, prev, length, newRegs);
        // Mark definition instructions for deletion
        deletedInsns.add(prev);
        deletedInsns.add(def);
        // Go through all uses of the array
        List<SsaInsn> useList = ssaMeth.getUseListForRegister(e);
        for (SsaInsn use : useList) {
            // Replace the use with scalars and then mark it for deletion
            replaceUse(use, prev, newRegs, deletedInsns);
            deletedInsns.add(use);
        }
        // Delete all marked instructions
        ssaMeth.deleteInsns(deletedInsns);
        ssaMeth.onInsnsChanged();
        // Convert the method back to SSA form
        SsaConverter.updateSsaMethod(optimizer, ssaMeth, regCount);
        // Propagate and remove extra moves added by scalar replacement
        movePropagate();
    }
}
Also used : CstLiteralBits(com.taobao.android.dx.rop.cst.CstLiteralBits) ArrayList(java.util.ArrayList) TypeBearer(com.taobao.android.dx.rop.type.TypeBearer) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec) HashSet(java.util.HashSet)

Example 8 with TypeBearer

use of com.taobao.android.dx.rop.type.TypeBearer in project atlas by alibaba.

the class LiteralOpUpgrader method tryReplacingWithConstant.

/**
     * Tries to replace an instruction with a const instruction. The given
     * instruction must have a constant result for it to be replaced.
     *
     * @param insn {@code non-null;} instruction to try to replace
     * @return true if the instruction was replaced
     */
private boolean tryReplacingWithConstant(NormalSsaInsn insn) {
    Insn originalRopInsn = insn.getOriginalRopInsn();
    Rop opcode = originalRopInsn.getOpcode();
    RegisterSpec result = insn.getResult();
    if (result != null && !ssaMeth.isRegALocal(result) && opcode.getOpcode() != RegOps.CONST) {
        TypeBearer type = insn.getResult().getTypeBearer();
        if (type.isConstant() && type.getBasicType() == Type.BT_INT) {
            // Replace the instruction with a constant
            replacePlainInsn(insn, RegisterSpecList.EMPTY, RegOps.CONST, (Constant) type);
            // Remove the source as well if this is a move-result-pseudo
            if (opcode.getOpcode() == RegOps.MOVE_RESULT_PSEUDO) {
                int pred = insn.getBlock().getPredecessors().nextSetBit(0);
                ArrayList<SsaInsn> predInsns = ssaMeth.getBlocks().get(pred).getInsns();
                NormalSsaInsn sourceInsn = (NormalSsaInsn) predInsns.get(predInsns.size() - 1);
                replacePlainInsn(sourceInsn, RegisterSpecList.EMPTY, RegOps.GOTO, null);
            }
            return true;
        }
    }
    return false;
}
Also used : Insn(com.taobao.android.dx.rop.code.Insn) PlainCstInsn(com.taobao.android.dx.rop.code.PlainCstInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) Rop(com.taobao.android.dx.rop.code.Rop) TypeBearer(com.taobao.android.dx.rop.type.TypeBearer) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 9 with TypeBearer

use of com.taobao.android.dx.rop.type.TypeBearer in project atlas by alibaba.

the class EscapeAnalysis method replaceUse.

/**
     * Replaces the use for a scalar replaceable array. Gets and puts become
     * move instructions, and array lengths and fills are handled. Can also
     * identify ArrayIndexOutOfBounds exceptions and throw them if detected.
     *
     * @param use {@code non-null;} move result instruction for array
     * @param prev {@code non-null;} instruction for instantiating new array
     * @param newRegs {@code non-null;} mapping of array indices to new
     * registers
     * @param deletedInsns {@code non-null;} set of instructions marked for
     * deletion
     */
private void replaceUse(SsaInsn use, SsaInsn prev, ArrayList<RegisterSpec> newRegs, HashSet<SsaInsn> deletedInsns) {
    int index;
    int length = newRegs.size();
    SsaInsn next;
    RegisterSpecList sources;
    RegisterSpec source, result;
    CstLiteralBits indexReg;
    switch(use.getOpcode().getOpcode()) {
        case RegOps.AGET:
            // Replace array gets with moves
            next = getMoveForInsn(use);
            sources = use.getSources();
            indexReg = ((CstLiteralBits) sources.get(1).getTypeBearer());
            index = indexReg.getIntBits();
            if (index < length) {
                source = newRegs.get(index);
                result = source.withReg(next.getResult().getReg());
                insertPlainInsnBefore(next, RegisterSpecList.make(source), result, RegOps.MOVE, null);
            } else {
                // Throw an exception if the index is out of bounds
                insertExceptionThrow(next, sources.get(1), deletedInsns);
                deletedInsns.add(next.getBlock().getInsns().get(2));
            }
            deletedInsns.add(next);
            break;
        case RegOps.APUT:
            // Replace array puts with moves
            sources = use.getSources();
            indexReg = ((CstLiteralBits) sources.get(2).getTypeBearer());
            index = indexReg.getIntBits();
            if (index < length) {
                source = sources.get(0);
                result = source.withReg(newRegs.get(index).getReg());
                insertPlainInsnBefore(use, RegisterSpecList.make(source), result, RegOps.MOVE, null);
                // Update the newReg entry to mark value as unknown now
                newRegs.set(index, result.withSimpleType());
            } else {
                // Throw an exception if the index is out of bounds
                insertExceptionThrow(use, sources.get(2), deletedInsns);
            }
            break;
        case RegOps.ARRAY_LENGTH:
            // Replace array lengths with const instructions
            TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
            //CstInteger lengthReg = CstInteger.make(length);
            next = getMoveForInsn(use);
            insertPlainInsnBefore(next, RegisterSpecList.EMPTY, next.getResult(), RegOps.CONST, (Constant) lengthReg);
            deletedInsns.add(next);
            break;
        case RegOps.MARK_LOCAL:
            // Remove mark local instructions
            break;
        case RegOps.FILL_ARRAY_DATA:
            // Create const instructions for each fill value
            Insn ropUse = use.getOriginalRopInsn();
            FillArrayDataInsn fill = (FillArrayDataInsn) ropUse;
            ArrayList<Constant> constList = fill.getInitValues();
            for (int i = 0; i < length; i++) {
                RegisterSpec newFill = RegisterSpec.make(newRegs.get(i).getReg(), (TypeBearer) constList.get(i));
                insertPlainInsnBefore(use, RegisterSpecList.EMPTY, newFill, RegOps.CONST, constList.get(i));
                // Update the newRegs to hold the new const value
                newRegs.set(i, newFill);
            }
            break;
        default:
    }
}
Also used : Insn(com.taobao.android.dx.rop.code.Insn) PlainCstInsn(com.taobao.android.dx.rop.code.PlainCstInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) ThrowingInsn(com.taobao.android.dx.rop.code.ThrowingInsn) ThrowingCstInsn(com.taobao.android.dx.rop.code.ThrowingCstInsn) FillArrayDataInsn(com.taobao.android.dx.rop.code.FillArrayDataInsn) CstLiteralBits(com.taobao.android.dx.rop.cst.CstLiteralBits) FillArrayDataInsn(com.taobao.android.dx.rop.code.FillArrayDataInsn) Constant(com.taobao.android.dx.rop.cst.Constant) TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) TypeBearer(com.taobao.android.dx.rop.type.TypeBearer) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 10 with TypeBearer

use of com.taobao.android.dx.rop.type.TypeBearer in project atlas by alibaba.

the class SCCP method replaceConstants.

/**
     * Replaces TypeBearers in source register specs with constant type
     * bearers if possible. These are then referenced in later optimization
     * steps.
     */
private void replaceConstants() {
    for (int reg = 0; reg < regCount; reg++) {
        if (latticeValues[reg] != CONSTANT) {
            continue;
        }
        if (!(latticeConstants[reg] instanceof TypedConstant)) {
            // We can't do much with these
            continue;
        }
        SsaInsn defn = ssaMeth.getDefinitionForRegister(reg);
        TypeBearer typeBearer = defn.getResult().getTypeBearer();
        if (typeBearer.isConstant()) {
            /*
                 * The definition was a constant already.
                 * The uses should be as well.
                 */
            continue;
        }
        // Update the destination RegisterSpec with the constant value
        RegisterSpec dest = defn.getResult();
        RegisterSpec newDest = dest.withType((TypedConstant) latticeConstants[reg]);
        defn.setResult(newDest);
        /*
             * Update the sources RegisterSpec's of all non-move uses.
             * These will be used in later steps.
             */
        for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) {
            if (insn.isPhiOrMove()) {
                continue;
            }
            NormalSsaInsn nInsn = (NormalSsaInsn) insn;
            RegisterSpecList sources = insn.getSources();
            int index = sources.indexOfRegister(reg);
            RegisterSpec spec = sources.get(index);
            RegisterSpec newSpec = spec.withType((TypedConstant) latticeConstants[reg]);
            nInsn.changeOneSource(index, newSpec);
        }
    }
}
Also used : TypedConstant(com.taobao.android.dx.rop.cst.TypedConstant) TypeBearer(com.taobao.android.dx.rop.type.TypeBearer) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Aggregations

TypeBearer (com.taobao.android.dx.rop.type.TypeBearer)19 RegisterSpec (com.taobao.android.dx.rop.code.RegisterSpec)7 Type (com.taobao.android.dx.rop.type.Type)5 Constant (com.taobao.android.dx.rop.cst.Constant)4 TypedConstant (com.taobao.android.dx.rop.cst.TypedConstant)4 Insn (com.taobao.android.dx.rop.code.Insn)3 PlainCstInsn (com.taobao.android.dx.rop.code.PlainCstInsn)3 PlainInsn (com.taobao.android.dx.rop.code.PlainInsn)3 RegisterSpecList (com.taobao.android.dx.rop.code.RegisterSpecList)3 ArrayList (java.util.ArrayList)3 HashSet (java.util.HashSet)3 FillArrayDataInsn (com.taobao.android.dx.rop.code.FillArrayDataInsn)2 Rop (com.taobao.android.dx.rop.code.Rop)2 ThrowingCstInsn (com.taobao.android.dx.rop.code.ThrowingCstInsn)2 ThrowingInsn (com.taobao.android.dx.rop.code.ThrowingInsn)2 CstInteger (com.taobao.android.dx.rop.cst.CstInteger)2 CstLiteralBits (com.taobao.android.dx.rop.cst.CstLiteralBits)2 SourcePosition (com.taobao.android.dx.rop.code.SourcePosition)1 SwitchInsn (com.taobao.android.dx.rop.code.SwitchInsn)1 CstFieldRef (com.taobao.android.dx.rop.cst.CstFieldRef)1