FileDocCategorySizeDatePackage
RegisterAllocator.javaAPI DocAndroid 1.5 API6681Wed May 06 22:41:02 BST 2009com.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 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 SsaMethod

protected intgetCategoryForSsaReg(int reg)
Returns the category (width) of the definition site of the register. Returns 1 for undefined registers.

param
reg register
return
1 or 2

        SsaInsn definition;
        definition = ssaMeth.getDefinitionForRegister(reg);

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

param
reg >= 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;
        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 non-null; insn to insert move before, must be last insn in block.
param
reg non-null; SSA register to duplicate
return
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
         */

        // new result must not have associated local variable
        RegisterSpec newRegSpec = RegisterSpec.make(ssaMeth.makeNewSsaReg(),
                reg.getTypeBearer());

        SsaInsn toAdd;

        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();

        RegisterSpec result = insn.getResult();
        int resultReg = (result == null) ? -1 : result.getReg();

        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
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
true if params should be moved from low to high.