use of org.jikesrvm.compilers.opt.controlflow.AnnotatedLSTNode 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;
}
}
Aggregations