|
|||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object org.jikesrvm.compilers.opt.driver.CompilerPhase org.jikesrvm.compilers.opt.ssa.EnterSSA
public class EnterSSA
This compiler phase constructs SSA form.
This module constructs SSA according to the SSA properties defined
in IR.desiredSSAOptions . See SSAOptions
for more details on supported options for SSA construction.
The SSA construction algorithm is the classic dominance frontier based algorithm from Cytron et al.'s 1991 TOPLAS paper.
See our SAS 2000 paper
Unified Analysis of Arrays and Object References in Strongly Typed
Languages for an overview of Array SSA form. More implementation
details are documented in
.
SSA.java
SSA
,
SSAOptions
,
LTDominators
Field Summary | |
---|---|
private static Constructor<CompilerPhase> |
constructor
Constructor for this compiler phase |
(package private) static boolean |
DEBUG
flag to optionally print verbose debugging messages |
private static int |
FOUND_NULL_TYPE
|
private IR |
ir
The governing IR |
private LiveAnalysis |
live
Cached results of liveness analysis |
private static int |
NO_NULL_TYPE
|
private HashSet<Register> |
nonLocalRegisters
A set of registers determined to span basic blocks |
private int[] |
numPredProcessed
For each basic block, the number of predecessors that have been processed. |
private HashSet<Instruction> |
scalarPhis
The set of scalar phi functions inserted |
Fields inherited from class org.jikesrvm.compilers.opt.driver.CompilerPhase |
---|
container |
Constructor Summary | |
---|---|
EnterSSA()
|
Method Summary | |
---|---|
private void |
computeNonLocals()
Pass through the IR and calculate which registers are not local to a basic block. |
private void |
computeSSA(IR ir,
boolean scalarsOnly,
boolean backwards,
Set<Object> heapTypes,
boolean insertUsePhis,
boolean insertPEIDeps,
boolean excludeGuards)
Calculate SSA form for an IR. |
private void |
copyHeapDefs(IR ir,
HashMap<Instruction,HeapOperand<?>[]> store)
Store a copy of the Heap variables each instruction defs. |
private TypeReference |
findParameterType(Register p)
Find a parameter type. |
Constructor<CompilerPhase> |
getClassConstructor()
Get a constructor object for this compiler phase |
private BitVector[] |
getDefSets()
Calculate the set of blocks that contain defs for each symbolic register in an IR. |
String |
getName()
Return a string identifying this compiler phase. |
private Register[] |
getSymbolicRegisters()
Set up a mapping from symbolic register number to the register. |
private void |
insertHeapPhiFunctions(IR ir)
Insert phi functions for heap array SSA heap variables. |
private void |
insertHeapVariables(IR ir,
boolean backwards)
Insert heap variables needed for Array SSA form. |
private void |
insertPhi(BasicBlock bb,
Register r)
Insert a phi function for a symbolic register at the head of a basic block. |
private void |
insertPhiFunctions(IR ir,
BitVector[] defs,
Register[] symbolics,
boolean excludeGuards)
Insert the necessary phi functions into an IR. |
private Instruction |
makePhiInstruction(Register r,
BasicBlock bb)
Create a phi-function instruction |
private static TypeReference |
meetPhiType(Instruction s)
Return the meet of the types on the rhs of a phi instruction SIDE EFFECT: bashes the Instruction scratch field. |
private void |
patchPEIgeneratedValues()
Work around some problems with PEI-generated values and handlers. |
void |
perform(IR ir)
Construct SSA form to satisfy the desired options in ir.desiredSSAOptions. |
private void |
prepare()
Perform some calculations to prepare for SSA construction. |
boolean |
printingEnabled(OptOptions options,
boolean before)
Should the IR be printed either before or after performing this phase? |
private void |
rectifyPhiTypes()
|
private void |
registerCalls(IR ir)
Register every CALL instruction in this method with the implicit heap array SSA look aside structure. |
private void |
registerExits(IR ir)
Register every instruction that can leave this method with the implicit heap array SSA look aside structure. |
private void |
registerHeapVariables(IR ir)
Register every instruction in this method with the implicit heap array SSA lookaside structure. |
private void |
registerRenamedHeapPhis(IR ir)
After performing renaming on heap phi functions, this routines notifies the SSA dictionary of the new names. |
private void |
removeAllUnreachablePhis(HashSet<Instruction> scalarPhis)
Remove all phis that are unreachable |
private void |
removePhisThatDominateAllDefs(BitVector needsPhi,
IR ir,
BitVector defs)
If node N dominates all defs of a register r, then N does not need a phi function for r; this function removes such nodes N from a Bit Set. |
private void |
removeUnreachableOperands(HashSet<Instruction> scalarPhis)
Remove all unreachable operands from scalar phi functions NOT CURRENTLY USED |
private void |
renameHeapVariables(IR ir)
Rename the implicit heap variables in the SSA form so that each heap variable has only one definition. |
private void |
renameSymbolicRegisters(Register[] symbolicRegisters)
Rename the symbolic registers so that each register has only one definition. |
private void |
search(BasicBlock X,
Stack<RegisterOperand>[] S)
This routine is the guts of the SSA construction phase for scalars. |
private void |
search2(BasicBlock X,
HashMap<Object,Stack<HeapOperand<Object>>> stacks)
This routine is the guts of the SSA construction phase for heap array SSA. |
boolean |
shouldPerform(OptOptions options)
Should this phase be performed under a guiding set of compiler options? |
Methods inherited from class org.jikesrvm.compilers.opt.driver.CompilerPhase |
---|
dumpIR, dumpIR, getCompilerPhaseConstructor, getCompilerPhaseConstructor, newExecution, performPhase, reportAdditionalStats, setContainer, verify |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
static final boolean DEBUG
private IR ir
private LiveAnalysis live
private HashSet<Register> nonLocalRegisters
private final HashSet<Instruction> scalarPhis
private int[] numPredProcessed
private static final Constructor<CompilerPhase> constructor
private static final int NO_NULL_TYPE
private static final int FOUND_NULL_TYPE
Constructor Detail |
---|
public EnterSSA()
Method Detail |
---|
public final boolean shouldPerform(OptOptions options)
shouldPerform
in class CompilerPhase
options
- the controlling compiler options
public Constructor<CompilerPhase> getClassConstructor()
getClassConstructor
in class CompilerPhase
public final String getName()
getName
in class CompilerPhase
public final boolean printingEnabled(OptOptions options, boolean before)
printingEnabled
in class CompilerPhase
options
- controlling compiler optionsbefore
- true iff querying before the phase
public final void perform(IR ir)
perform
in class CompilerPhase
ir
- the IR on which to apply the phaseprivate void prepare()
private void computeNonLocals()
nonLocalRegisters
field.
private void patchPEIgeneratedValues()
private void computeSSA(IR ir, boolean scalarsOnly, boolean backwards, Set<Object> heapTypes, boolean insertUsePhis, boolean insertPEIDeps, boolean excludeGuards)
ir
- the governing IRscalarsOnly
- should we compute SSA only for scalar variables?backwards
- If this is true, then every statement that
can leave the procedure is considered to use every heap
variable. This option is useful for backwards analyses such as dead
store elimination.heapTypes
- If this variable is non-null, then heap array SSA
form will restrict itself to this set of types. If this is null, build
heap array SSA for all types.insertUsePhis
- Should we insert uphi functions for heap array
SSA? ie., should we create a new name for each heap array at every use
of the heap array? This option is useful for some analyses, such as
our redundant load elimination algorithm.insertPEIDeps
- Should we model exceptions with an explicit
heap variable for exception state? This option is useful for global
code placement algorithms.excludeGuards
- Should we exclude guard registers from SSA?private void insertHeapVariables(IR ir, boolean backwards)
ir
- the governing IRbackwards
- if this is true, every statement that can leave the
procedure uses every heap variable.
This option is useful for backwards analysesprivate void registerExits(IR ir)
ir
- the governing IRprivate void registerCalls(IR ir)
ir
- the governing IRprivate void registerHeapVariables(IR ir)
ir
- the governing IRprivate void insertHeapPhiFunctions(IR ir)
ir
- the governing IRprivate BitVector[] getDefSets()
private void insertPhiFunctions(IR ir, BitVector[] defs, Register[] symbolics, boolean excludeGuards)
Algorithm:
For register r, let S be the set of all blocks that contain defs of r. Let D be the iterated dominance frontier of S. Each block in D needs a phi-function for r.
Special Java case: if node N dominates all defs of r, then N does not need a phi-function for r
ir
- the governing IRdefs
- defs[i] represents the basic blocks that define
symbolic register i.symbolics
- symbolics[i] is symbolic register number iprivate void removePhisThatDominateAllDefs(BitVector needsPhi, IR ir, BitVector defs)
needsPhi
- representation of set of nodes that
need phi functions for a register rir
- the governing IRdefs
- set of nodes that define register rprivate void insertPhi(BasicBlock bb, Register r)
bb
- the basic blockr
- the symbolic register that needs a phi functionprivate Instruction makePhiInstruction(Register r, BasicBlock bb)
r
- the symbolic registerbb
- the basic block holding the new phi function
private Register[] getSymbolicRegisters()
TODO: put this functionality elsewhere.
private void renameSymbolicRegisters(Register[] symbolicRegisters)
Note : call this after phi functions have been inserted.
Algorithm: from Cytron et. al 91
call search(entry) search(X): for each statement A in X do if A is not-phi for each r in RHS(A) do if !r.isSSA, replace r with TOP(S(r)) done fi for each r in LHS(A) do if !r.isSSA r2 = new temp register push r2 onto S(r) replace r in A by r2 fi done done (end of first loop) for each Y in succ(X) do j <- whichPred(Y,X) for each phi-function F in Y do replace the j-th operand (r) in RHS(F) with TOP(S(r)) done done (end of second loop) for each Y in Children(X) do call search(Y) done (end of third loop) for each assignment A in X do for each r in LHS(A) do pop(S(r)) done done (end of fourth loop) end
symbolicRegisters
- mapping from integer to symbolic registersprivate void search(BasicBlock X, Stack<RegisterOperand>[] S)
X
- basic block to search dominator tree fromS
- stack of names for each registerprivate void renameHeapVariables(IR ir)
Algorithm: Cytron et. al 91 (see renameSymbolicRegisters)
ir
- the governing IRprivate void search2(BasicBlock X, HashMap<Object,Stack<HeapOperand<Object>>> stacks)
renameSymbolicRegisters
for more details.
X
- the current basic block being traversedstacks
- a structure holding the current names for each heap
variable
used and defined by each instruction.private void registerRenamedHeapPhis(IR ir)
FIXME - this was commented out: delete it ?? RJG
ir
- the governing IRprivate void copyHeapDefs(IR ir, HashMap<Instruction,HeapOperand<?>[]> store)
ir
- governing IRstore
- place to store copiesprivate void rectifyPhiTypes()
private void removeAllUnreachablePhis(HashSet<Instruction> scalarPhis)
private void removeUnreachableOperands(HashSet<Instruction> scalarPhis)
NOT CURRENTLY USED
private static TypeReference meetPhiType(Instruction s)
SIDE EFFECT: bashes the Instruction scratch field.
s
- phi instructionprivate TypeReference findParameterType(Register p)
Given a register that holds a parameter, look at the register's use chain to find the type of the parameter
|
|||||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |