See Appel algorithm 19.7
Unlike the original algorithm presented in Appel, this renamer converts to a new flat (versionless) register space. The "version 0" registers, which represent the initial state of the Rop registers and should never actually be meaningfully accessed in a legal program, are represented as the first N registers in the SSA namespace. Subsequent assignments are assigned new unique names. Note that the incoming Rop representation has a concept of register widths, where 64-bit values are stored into two adjoining Rop registers. This adjoining register representation is ignored in SSA form conversion and while in SSA form, each register can be e either 32 or 64 bits wide depending on use. The adjoining-register represention is re-created later when converting back to Rop form.
But, please note, the SSA Renamer's ignoring of the adjoining-register ROP representation means that unaligned accesses to 64-bit registers are not supported. For example, you cannot do a 32-bit operation on a portion of a 64-bit register. This will never be observed to happen when coming from Java code, of course.
The implementation here, rather than keeping a single register version stack for the entire method as the dom tree is walked, instead keeps a mapping table for the current block being processed. Once the current block has been processed, this mapping table is then copied and used as the initial state for child blocks.
| Modifier and Type | Class and Description |
|---|---|
| private class | SsaRenamer.
Processes all insns in a block and renames their registers as appropriate. |
| Modifier and Type | Field and Description |
|---|---|
| private static final boolean | DEBUG
debug flag |
| private int | nextSsaReg
next available SSA register |
| private final int | ropRegCount
the number of original rop registers |
| private final SsaMethod | ssaMeth
method we're processing |
| private final ArrayList | ssaRegToLocalItems
map of SSA register number to debug (local var names) or null of n/a |
| private IntList | ssaRegToRopReg
maps SSA registers back to the original rop number. |
| private final RegisterSpec[][] | startsForBlocks
indexed by block index; register version state for each block start. |
| private int | threshold
work only on registers above this value |
| Access | Constructor and Description |
|---|---|
| public | SsaRenamer(SsaMethod
non-null; un-renamed SSA method that will
be renamed.Constructs an instance of the renamer |
| public | SsaRenamer(SsaMethod
non-null; un-renamed SSA method that will
be renamed.registers below this number are unchanged thresh)Constructs an instance of the renamer with threshold set |
| Modifier and Type | Method and Description |
|---|---|
| private static RegisterSpec[] | Returns: non-null; new instancenon-null; array to duplicateDuplicates a RegisterSpec array. |
| private static boolean | Returns: Returns true if a and b are equal or are both nullnull-ok a, Object null-ok b)Returns true if a and b are equal or are both null. |
| private LocalItem | Returns: null-ok; Local variable name or null if noneregister in SSA name space ssaReg)Gets a local variable item for a specified register. |
| private boolean | Returns: true if its register number is below the thresholdthe SSA register in question ssaReg)Returns true if this SSA register is below the specified threshold. |
| private boolean | Returns: true if it is a version 0 register.the SSA register in question ssaReg)Returns true if this SSA register is a "version 0" register. |
| public void | run()
Implements java. |
| private void | setNameForSsaReg(RegisterSpec
non-null named register spec in SSA name space ssaReg)Records a debug (local variable) name for a specified register. |
| DEBUG | back to summary |
|---|---|
| private static final boolean DEBUG debug flag | |
| nextSsaReg | back to summary |
|---|---|
| private int nextSsaReg next available SSA register | |
| ropRegCount | back to summary |
|---|---|
| private final int ropRegCount the number of original rop registers | |
| ssaMeth | back to summary |
|---|---|
| private final SsaMethod ssaMeth method we're processing | |
| ssaRegToLocalItems | back to summary |
|---|---|
| private final ArrayList<LocalItem> ssaRegToLocalItems map of SSA register number to debug (local var names) or null of n/a | |
| ssaRegToRopReg | back to summary |
|---|---|
| private IntList ssaRegToRopReg maps SSA registers back to the original rop number. Used for debug only. | |
| startsForBlocks | back to summary |
|---|---|
| private final RegisterSpec[][] startsForBlocks indexed by block index; register version state for each block start.
This list is updated by each dom parent for its children. The only
sub-arrays that exist at any one time are the start states for blocks
yet to be processed by a | |
| threshold | back to summary |
|---|---|
| private int threshold work only on registers above this value | |
| SsaRenamer | back to summary |
|---|---|
| public SsaRenamer(SsaMethod ssaMeth) Constructs an instance of the renamer
| |
| SsaRenamer | back to summary |
|---|---|
| public SsaRenamer(SsaMethod ssaMeth, int thresh) Constructs an instance of the renamer with threshold set
| |
| dupArray | back to summary |
|---|---|
| private static RegisterSpec[] dupArray(RegisterSpec[] orig) Duplicates a RegisterSpec array.
| |
| equalsHandlesNulls | back to summary |
|---|---|
| private static boolean equalsHandlesNulls(Object a, Object b) Returns true if a and b are equal or are both null. | |
| getLocalForNewReg | back to summary |
|---|---|
| private LocalItem getLocalForNewReg(int ssaReg) Gets a local variable item for a specified register.
| |
| isBelowThresholdRegister | back to summary |
|---|---|
| private boolean isBelowThresholdRegister(int ssaReg) Returns true if this SSA register is below the specified threshold. Used when most code is already in SSA form, and renaming is needed only for registers above a certain threshold.
| |
| isVersionZeroRegister | back to summary |
|---|---|
| private boolean isVersionZeroRegister(int ssaReg) Returns true if this SSA register is a "version 0" register. All version 0 registers are assigned the first N register numbers, where N is the count of original rop registers.
| |
| run | back to summary |
|---|---|
| public void run() Implements java. Performs renaming transformation, modifying the method's instructions in-place. | |
| setNameForSsaReg | back to summary |
|---|---|
| private void setNameForSsaReg(RegisterSpec ssaReg) Records a debug (local variable) name for a specified register.
| |
| Modifier and Type | Class and Description |
|---|---|
| private class | SsaRenamer.
Provides a register mapping between the old register space and the current renaming mapping. |
| Modifier and Type | Field and Description |
|---|---|
| private final SsaBasicBlock | block
|
| private final RegisterSpec[] | currentMapping
|
| private final HashMap | insnsToReplace
maps the set of insns to replace after renaming is finished on the block. |
| private final SsaRenamer. | |
| private final HashSet | movesToKeep
contains the set of moves we need to keep to preserve local var info. |
| Access | Constructor and Description |
|---|---|
| pack-priv | BlockRenamer(final SsaBasicBlock
non-null; block to processConstructs a block renamer instance. |
| Modifier and Type | Method and Description |
|---|---|
| private void | addMapping(int
>= 0; rop register numbernon-null; an SSA register that has just
been added to currentMappingEnforces a few contraints when a register mapping is added. |
| public void | |
| pack-priv void | processResultReg(SsaInsn
insn to process. insn)Renames the result register of this insn and updates the current register mapping. |
| private void | updateSuccessorPhis()
Updates the phi insns in successor blocks with operands based on the current mapping of the rop register the phis represent. |
| public void | visitMoveInsn(NormalSsaInsn
non-null; the instruction to visitImplements org. |
| public void | visitNonMoveInsn(NormalSsaInsn
non-null; the instruction to visitImplements org. |
| public void | visitPhiInsn(PhiInsn
non-null; the instruction to visitImplements org. |
| block | back to summary |
|---|---|
| private final SsaBasicBlock block
| |
| currentMapping | back to summary |
|---|---|
| private final RegisterSpec[] currentMapping
| |
| insnsToReplace | back to summary |
|---|---|
| private final HashMap<SsaInsn, SsaInsn> insnsToReplace maps the set of insns to replace after renaming is finished on the block. | |
| mapper | back to summary |
|---|---|
| private final SsaRenamer. | |
| movesToKeep | back to summary |
|---|---|
| private final HashSet<SsaInsn> movesToKeep contains the set of moves we need to keep to preserve local var info. All other moves will be deleted. | |
| BlockRenamer | back to summary |
|---|---|
| pack-priv BlockRenamer(final SsaBasicBlock block) Constructs a block renamer instance. Call
| |
| addMapping | back to summary |
|---|---|
| private void addMapping(int ropReg, RegisterSpec ssaReg) Enforces a few contraints when a register mapping is added.
| |
| process | back to summary |
|---|---|
| public void process() Renames all the variables in this block and inserts appriopriate phis in successor blocks. | |
| processResultReg | back to summary |
|---|---|
| pack-priv void processResultReg(SsaInsn insn) Renames the result register of this insn and updates the current register mapping. Does nothing if this insn has no result. Applied to all non-move insns.
| |
| updateSuccessorPhis | back to summary |
|---|---|
| private void updateSuccessorPhis() Updates the phi insns in successor blocks with operands based on the current mapping of the rop register the phis represent. | |
| visitMoveInsn | back to summary |
|---|---|
| public void visitMoveInsn(NormalSsaInsn insn) Implements org. Doc from org. Any non-phi move instruction 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.
| |
| visitNonMoveInsn | back to summary |
|---|---|
| public void visitNonMoveInsn(NormalSsaInsn insn) Implements org. Doc from org. Any insn that isn't a move or a phi (which is also a move). All insns that are not move or phi insns have their source registers mapped ot the current mapping. Their result registers are then renamed to a new SSA register which is then added to the current register mapping.
| |
| visitPhiInsn | back to summary |
|---|---|
| public void visitPhiInsn(PhiInsn phi) Implements org. Doc from org. Any phi insn Phi insns have their result registers renamed.
| |
| Access | Constructor and Description |
|---|---|
| public |
| Modifier and Type | Method and Description |
|---|---|
| public int | getNewRegisterCount()
Implements abstract org. |
| public RegisterSpec | map(RegisterSpec
old register registerSpec)Implements abstract org. |
| RenamingMapper | back to summary |
|---|---|
| public RenamingMapper() | |
| getNewRegisterCount | back to summary |
|---|---|
| public int getNewRegisterCount() Implements abstract org. Doc from org. Gets the count of registers (really, the total register width, since category width is counted) in the new namespace.
| |
| map | back to summary |
|---|---|
| public RegisterSpec map(RegisterSpec registerSpec) Implements abstract org.
| |