FileDocCategorySizeDatePackage
RegisterAllocator.javaAPI DocAndroid 5.1 API6543Thu Mar 12 22:18:30 GMT 2015com.android.dx.ssa.back

RegisterAllocator

public abstract class RegisterAllocator extends Object
Base class of all register allocators.

Fields Summary
protected final com.android.dx.ssa.SsaMethod
ssaMeth
method being processed
protected final InterferenceGraph
interference
interference graph, indexed by register in both dimensions
Constructors Summary
public RegisterAllocator(com.android.dx.ssa.SsaMethod ssaMeth, InterferenceGraph interference)
Creates an instance. Call {@code allocateRegisters} to run.

param
ssaMeth method to process.
param
interference Interference graph, indexed by register in both dimensions.

        this.ssaMeth = ssaMeth;
        this.interference = interference;
    
Methods Summary
public abstract com.android.dx.ssa.RegisterMapperallocateRegisters()
Runs the algorithm.

return
a register mapper to apply to the {@code SsaMethod}

protected final intgetCategoryForSsaReg(int reg)
Returns the category (width) of the definition site of the register. Returns {@code 1} for undefined registers.

param
reg register
return
{@code 1..2}

        SsaInsn definition = ssaMeth.getDefinitionForRegister(reg);

        if (definition == null) {
            // an undefined reg
            return 1;
        } else {
            return definition.getResult().getCategory();
        }
    
protected final com.android.dx.rop.code.RegisterSpecgetDefinitionSpecForSsaReg(int reg)
Returns the RegisterSpec of the definition of the register.

param
reg {@code >= 0;} SSA register
return
definition spec of the register or null if it is never defined (for the case of "version 0" SSA registers)

        SsaInsn definition = ssaMeth.getDefinitionForRegister(reg);

        return definition == null ? null : definition.getResult();
    
protected final com.android.dx.rop.code.RegisterSpecinsertMoveBefore(com.android.dx.ssa.SsaInsn insn, com.android.dx.rop.code.RegisterSpec reg)
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

        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;
    
protected booleanisDefinitionMoveParam(int reg)
Returns true if the definition site of this register is a move-param (ie, this is a method parameter).

param
reg register in question
return
{@code true} if this is a method parameter

        SsaInsn defInsn = ssaMeth.getDefinitionForRegister(reg);

        if (defInsn instanceof NormalSsaInsn) {
            NormalSsaInsn ndefInsn = (NormalSsaInsn) defInsn;

            return ndefInsn.getOpcode().getOpcode() == RegOps.MOVE_PARAM;
        }

        return false;
    
public abstract booleanwantsParamsMovedHigh()
Indicates whether the method params were allocated at the bottom of the namespace, and thus should be moved up to the top of the namespace after phi removal.

return
{@code true} if params should be moved from low to high