Search in sources :

Example 1 with AnnotatedLSTNode

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;
    }
}
Also used : HashMap(java.util.HashMap) BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AnnotatedLSTNode(org.jikesrvm.compilers.opt.controlflow.AnnotatedLSTNode) ArrayList(java.util.ArrayList) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) GraphNode(org.jikesrvm.compilers.opt.util.GraphNode) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) TypeReference(org.jikesrvm.classloader.TypeReference)

Aggregations

ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 TypeReference (org.jikesrvm.classloader.TypeReference)1 AnnotatedLSTNode (org.jikesrvm.compilers.opt.controlflow.AnnotatedLSTNode)1 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)1 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)1 Register (org.jikesrvm.compilers.opt.ir.Register)1 BasicBlockOperand (org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand)1 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)1 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)1 HeapOperand (org.jikesrvm.compilers.opt.ir.operand.HeapOperand)1 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)1 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)1 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)1 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)1 GraphNode (org.jikesrvm.compilers.opt.util.GraphNode)1