use of org.jikesrvm.compilers.opt.util.GraphNode in project JikesRVM by JikesRVM.
the class LoopVersioning method findLoopToOptimise.
// -oO Optimisation routines Oo-
/**
* Find an outermost loop to optimise and optimise it. Focus on
* annotated regular loops, LICM should handle possible
* optimisation for the non-regular loops
*
* @param loop Loop to search
* @return was optimisation performed
*/
private boolean findLoopToOptimise(AnnotatedLSTNode loop) {
// Has this loop already been optimised?
Operand carriedLoopIterator = loop.getCarriedLoopIterator();
if ((carriedLoopIterator instanceof RegisterOperand) && (isOptimizedLoop(carriedLoopIterator.asRegister().getRegister()))) {
return false;
}
// Process inner loops first
Enumeration<GraphNode> innerLoops = loop.outNodes();
// Iterate over loops
while (innerLoops.hasMoreElements()) {
AnnotatedLSTNode nestedLoop = (AnnotatedLSTNode) innerLoops.nextElement();
// Try to optimise inner loops first
if (findLoopToOptimise(nestedLoop)) {
// Exit early if inner loop optimisation succeeded
return true;
}
}
// Don't try to optimise irregular loops
if (loop.isNonRegularLoop()) {
return false;
}
if (DEBUG) {
report("LoopFissionOfArrayGuards: found loop in " + ir.getMethod());
VM.sysWriteln("dominator tree:");
VM.sysWriteln(ir.HIRInfo.dominatorTree.toString());
}
// 1) Determine the bound and null checks to be eliminated. The
// bound checks are the ones that operate on the loop iterator. If
// no checks can be eliminated, stop optimising this loop.
ArrayList<Instruction> checksToEliminate = new ArrayList<Instruction>();
getListOfChecksToEliminate(loop, checksToEliminate);
if (checksToEliminate.isEmpty()) {
return false;
} else {
// We found instructions to eliminate
if (DEBUG) {
VM.sysWriteln("Loop being optimised:");
VM.sysWriteln(loop.toString());
VM.sysWriteln("Checks to eliminate:");
for (Instruction instruction : checksToEliminate) {
VM.sysWriteln(instruction.toString());
}
}
// 2) Determine the registers defined in the loop.
ArrayList<Register> registersDefinedInOriginalLoop = new ArrayList<Register>();
ArrayList<TypeReference> typesOfRegistersDefinedInOriginalLoop = new ArrayList<TypeReference>();
ArrayList<Instruction> definingInstructionsInOriginalLoop = new ArrayList<Instruction>();
getRegistersDefinedInLoop(loop, registersDefinedInOriginalLoop, typesOfRegistersDefinedInOriginalLoop, definingInstructionsInOriginalLoop);
if (DEBUG) {
VM.sysWrite("Registers in original loop:\n{");
for (int i = 0; i < registersDefinedInOriginalLoop.size(); i++) {
VM.sysWrite(registersDefinedInOriginalLoop.get(i).toString());
if (definingInstructionsInOriginalLoop.get(i) != null) {
VM.sysWrite("(escapes),");
} else {
VM.sysWrite(",");
}
}
VM.sysWriteln("}");
}
// 3) Generate phi nodes that define the original register
// defined by the loop and use two newly created registers.
ArrayList<Instruction> phiInstructions = new ArrayList<Instruction>();
HashMap<Register, Register> subOptimalRegMap = new HashMap<Register, Register>();
HashMap<Register, Register> optimalRegMap = new HashMap<Register, Register>();
generatePhiNodes(loop, registersDefinedInOriginalLoop, typesOfRegistersDefinedInOriginalLoop, phiInstructions, subOptimalRegMap, optimalRegMap);
if (DEBUG) {
VM.sysWriteln("subOptimalRegMap");
VM.sysWriteln(subOptimalRegMap.toString());
VM.sysWriteln("optimalRegMap");
VM.sysWriteln(optimalRegMap.toString());
}
// 4) Create a version of the original loop that uses the first of
// the newly created registers instead of the original
// registers.
HashMap<Register, BasicBlock> regToUnoptimizedBlockMap = new HashMap<Register, BasicBlock>();
HashMap<BasicBlock, BasicBlock> unoptimizedLoopMap = createCloneLoop(loop, subOptimalRegMap, regToUnoptimizedBlockMap);
if (DEBUG) {
VM.sysWriteln("subOptimalLoopMap");
VM.sysWriteln(unoptimizedLoopMap.toString());
}
// 5) Create a second version, this time with the result of the
// eliminated checks set to explicit test guards.
HashMap<Register, BasicBlock> regToOptimizedBlockMap = new HashMap<Register, BasicBlock>();
HashMap<BasicBlock, BasicBlock> optimizedLoopMap = createOptimizedLoop(loop, optimalRegMap, checksToEliminate, regToOptimizedBlockMap);
if (DEBUG) {
VM.sysWriteln("optimalLoopMap");
VM.sysWriteln(optimizedLoopMap.toString());
}
// 6) Work out what the maximum value for all the bounds checks
// are and create branches to optimal or suboptimal loops - with
// the unoptimized loop possibly being unreachable
BasicBlock firstBranchBlock = loop.header.createSubBlock(SYNTH_LOOP_VERSIONING_BCI, ir);
BasicBlock temp = (BasicBlock) loop.header.prev;
ir.cfg.breakCodeOrder(temp, loop.header);
ir.cfg.linkInCodeOrder(temp, firstBranchBlock);
ir.cfg.linkInCodeOrder(firstBranchBlock, loop.header);
temp.redirectOuts(loop.header, firstBranchBlock, ir);
boolean isUnoptimizedLoopReachable = createBranchBlocks(loop, firstBranchBlock, checksToEliminate, unoptimizedLoopMap.get(loop.predecessor), optimizedLoopMap.get(loop.predecessor), optimalRegMap);
// 7) Fix up the phi node predecessors
fixUpPhiPredecessors(phiInstructions, isUnoptimizedLoopReachable ? unoptimizedLoopMap.get(loop.exit) : null, optimizedLoopMap.get(loop.exit));
// 8) Remove the unoptimized loop if its redundant
if (!isUnoptimizedLoopReachable) {
removeUnoptimizedLoop(loop, unoptimizedLoopMap);
}
// 9) Replace register definitions in the original
// loop with phi instructions
modifyOriginalLoop(loop, phiInstructions, definingInstructionsInOriginalLoop, subOptimalRegMap, optimalRegMap);
// 10) Compact node numbering so that CFG number of nodes
// reflects that some basic blocks may have been deleted
ir.cfg.compactNodeNumbering();
return true;
}
}
use of org.jikesrvm.compilers.opt.util.GraphNode in project JikesRVM by JikesRVM.
the class DF_Equation method outNodes.
/**
* Return an enumeration of the equations which use the result of this
* equation.
* @return an enumeration of the equations which use the result of this
* equation.
*/
@Override
public Enumeration<GraphNode> outNodes() {
return new Enumeration<GraphNode>() {
private GraphNode elt = getLHS();
@Override
public boolean hasMoreElements() {
return elt != null;
}
@Override
public GraphNode nextElement() {
GraphNode x = elt;
elt = null;
return x;
}
};
}
use of org.jikesrvm.compilers.opt.util.GraphNode in project JikesRVM by JikesRVM.
the class DF_System method showGraphStats.
/**
* Debugging aid: print statistics about the dataflow system.
*/
void showGraphStats() {
System.out.println("graph has " + equations.numberOfNodes() + " nodes");
int count = 0;
for (Enumeration<GraphNode> e = equations.enumerateNodes(); e.hasMoreElements(); ) {
GraphNode eq = e.nextElement();
Enumeration<GraphNode> outs = eq.outNodes();
while (outs.hasMoreElements()) {
count++;
outs.nextElement();
}
}
System.out.println("graph has " + count + " edges");
}
use of org.jikesrvm.compilers.opt.util.GraphNode in project JikesRVM by JikesRVM.
the class DF_System method numberEquationsTopological.
/**
* Number the equations in topological order.
*
* <p> PRECONDITION: Already called addGraphEdges()
*
* <p>Algorithm:
* <ul>
* <li> 1. create a DAG of SCCs
* <li> 2. number this DAG topologically
* <li> 3. walk through the DAG and number nodes as they are
* encountered
* </ul>
*/
private void numberEquationsTopological() {
Enumeration<GraphNode> topOrder = GraphUtilities.enumerateTopSort(equations);
Enumeration<GraphNode> rev = new ReverseDFSenumerateByFinish(equations, topOrder);
int number = 0;
while (rev.hasMoreElements()) {
GraphNode elt = rev.nextElement();
if (elt instanceof DF_Equation) {
DF_Equation eq = (DF_Equation) elt;
eq.setTopologicalNumber(number++);
}
}
}
Aggregations