Search in sources :

Example 1 with LiveAnalysis

use of org.jikesrvm.compilers.opt.liveness.LiveAnalysis in project JikesRVM by JikesRVM.

the class DepGraphStats method printBasicBlockStatistics.

/**
 * Print the dependence graph stats for all basic blocks in an IR.
 * @param ir the IR
 */
public static void printBasicBlockStatistics(IR ir) {
    final boolean DEBUG = false;
    System.out.println();
    System.out.println("**** START OF printBasicBlockStatistics() for method " + ir.method + " ****");
    if (DEBUG) {
        ir.printInstructions();
    }
    // Performing live analysis may reduce dependences between PEIs and stores
    if (ir.options.L2M_HANDLER_LIVENESS) {
        new LiveAnalysis(false, false, true).perform(ir);
    }
    for (BasicBlock bb = ir.firstBasicBlockInCodeOrder(); bb != null; bb = bb.nextBasicBlockInCodeOrder()) {
        // DepGraph dg =
        new DepGraph(ir, bb.firstRealInstruction(), bb.lastRealInstruction(), bb);
    }
    System.out.println("**** END OF printBasicBlockStatistics() ****");
}
Also used : LiveAnalysis(org.jikesrvm.compilers.opt.liveness.LiveAnalysis) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock)

Example 2 with LiveAnalysis

use of org.jikesrvm.compilers.opt.liveness.LiveAnalysis in project JikesRVM by JikesRVM.

the class LeaveSSA method translateFromSSA.

/**
 * Main driver to translate an IR out of SSA form.
 *
 * @param ir the IR in SSA form
 */
public void translateFromSSA(IR ir) {
    // 0. Deal with guards (validation registers)
    unSSAGuards(ir);
    // 1. re-compute dominator tree in case of control flow changes
    LTDominators.perform(ir, true, true);
    DominatorTree dom = new DominatorTree(ir, true);
    // 1.5 Perform Sreedhar's naive translation from TSSA to CSSA
    // if (ir.options.UNROLL_LOG == 0) normalizeSSA(ir);
    // 2. compute liveness
    LiveAnalysis live = new // don't create GC maps
    LiveAnalysis(// don't create GC maps
    false, // skip (final) local propagation step
    true, // don't store information at handlers
    false, // don't skip guards
    false);
    live.perform(ir);
    // 3. initialization
    VariableStacks s = new VariableStacks();
    // 4. convert phi nodes into copies
    BasicBlock b = ((DominatorTreeNode) dom.getRoot()).getBlock();
    insertCopies(b, dom, live);
    // 5. If necessary, recompute dominators to account for new control flow.
    if (splitSomeBlock) {
        LTDominators.perform(ir, true, true);
        dom = new DominatorTree(ir, true);
    }
    // 6. compensate for copies required by simultaneous liveness
    performRename(b, dom, s);
    // 7. phis are now redundant
    removeAllPhis(ir);
}
Also used : DominatorTree(org.jikesrvm.compilers.opt.controlflow.DominatorTree) DominatorTreeNode(org.jikesrvm.compilers.opt.controlflow.DominatorTreeNode) LiveAnalysis(org.jikesrvm.compilers.opt.liveness.LiveAnalysis) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock)

Example 3 with LiveAnalysis

use of org.jikesrvm.compilers.opt.liveness.LiveAnalysis in project JikesRVM by JikesRVM.

the class LICM method perform.

/**
 * Execute loop invariant code motion on the given IR.
 */
@Override
public void perform(IR ir) {
    this.ir = ir;
    if (DEBUG && ir.hasReachableExceptionHandlers()) {
        VM.sysWriteln("] " + ir.method);
        (new LiveAnalysis(false, false, true, false)).perform(ir);
        Enumeration<BasicBlock> e = ir.getBasicBlocks();
        while (e.hasMoreElements()) {
            BasicBlock b = e.nextElement();
            if (b instanceof ExceptionHandlerBasicBlock) {
                VM.sysWriteln("] " + b + ": " + ((ExceptionHandlerBasicBlock) b).getLiveSet());
            }
        }
    }
    if (ir.hasReachableExceptionHandlers() || GCP.tooBig(ir)) {
        resetLandingPads();
        return;
    }
    VERBOSE = ir.options.DEBUG_GCP;
    if (VERBOSE && ir.options.hasMETHOD_TO_PRINT()) {
        VERBOSE = ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString());
        if (!VERBOSE) {
            resetLandingPads();
            return;
        }
    }
    if (VERBOSE)
        VM.sysWriteln("] " + ir.method);
    initialize(ir);
    if (VERBOSE)
        SSA.printInstructions(ir);
    Instruction inst = ir.firstInstructionInCodeOrder();
    while (inst != null) {
        Instruction next = inst.nextInstructionInCodeOrder();
        if (DEBUG)
            System.out.println("scheduleEarly: " + inst);
        scheduleEarly(inst);
        inst = next;
    }
    inst = ir.lastInstructionInCodeOrder();
    while (inst != null) {
        Instruction next = inst.prevInstructionInCodeOrder();
        scheduleLate(inst);
        inst = next;
    }
    resetLandingPads();
    if (DEBUG)
        SSA.printInstructions(ir);
    ir.actualSSAOptions.setScalarValid(false);
}
Also used : LiveAnalysis(org.jikesrvm.compilers.opt.liveness.LiveAnalysis) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 4 with LiveAnalysis

use of org.jikesrvm.compilers.opt.liveness.LiveAnalysis in project JikesRVM by JikesRVM.

the class LeaveSSA method scheduleCopies.

/**
 * Record pending copy operations needed to insert at the end of a basic
 * block.<p>
 *
 * TODO: this procedure is getting long and ugly.  Rewrite or refactor
 * it.
 * @param bb the basic block to process
 * @param live valid liveness information for the IR
 */
private void scheduleCopies(BasicBlock bb, LiveAnalysis live) {
    if (DEBUG)
        VM.sysWriteln("scheduleCopies: " + bb);
    // compute out liveness from information in LiveAnalysis
    LiveSet out = new LiveSet();
    for (Enumeration<BasicBlock> outBlocks = bb.getOut(); outBlocks.hasMoreElements(); ) {
        BasicBlock ob = outBlocks.nextElement();
        LiveAnalysis.BBLiveElement le = live.getLiveInfo(ob);
        out.add(le.getIn());
    }
    // usedByAnother represents the set of registers that appear on the
    // left-hand side of subsequent phi nodes.  This is important, since
    // we be careful to order copies if the same register appears as the
    // source and dest of copies in the same basic block.
    HashSet<Register> usedByAnother = new HashSet<Register>(4);
    // for each basic block successor b of bb, if we make a block on the
    // critical edge bb->b, then store this critical block.
    HashMap<BasicBlock, BasicBlock> criticalBlocks = new HashMap<BasicBlock, BasicBlock>(4);
    // For each critical basic block b in which we are inserting copies: return the
    // mapping of registers to names implied by the copies that have
    // already been inserted into b.
    HashMap<BasicBlock, HashMap<Register, Register>> currentNames = new HashMap<BasicBlock, HashMap<Register, Register>>(4);
    // Additionally store the current names for the current basic block bb.
    HashMap<Register, Register> bbNames = new HashMap<Register, Register>(4);
    // copySet is a linked-list of copies we need to insert in this block.
    final LinkedList<Copy> copySet = new LinkedList<Copy>();
    /* Worklist is actually used like a stack - should we make this an Stack ?? */
    final LinkedList<Copy> workList = new LinkedList<Copy>();
    // collect copies required in this block.  These copies move
    // the appropriate rval into the lval of each phi node in
    // control children of the current block.
    Enumeration<BasicBlock> e = bb.getOut();
    while (e.hasMoreElements()) {
        BasicBlock bbs = e.nextElement();
        if (bbs.isExit())
            continue;
        for (Instruction phi = bbs.firstInstruction(); phi != bbs.lastInstruction(); phi = phi.nextInstructionInCodeOrder()) {
            if (phi.operator() != PHI)
                continue;
            for (int index = 0; index < Phi.getNumberOfPreds(phi); index++) {
                if (Phi.getPred(phi, index).block != bb)
                    continue;
                Operand rval = Phi.getValue(phi, index);
                if (rval.isRegister() && Phi.getResult(phi).asRegister().getRegister() == rval.asRegister().getRegister()) {
                    continue;
                }
                Copy c = new Copy(phi, index);
                copySet.add(0, c);
                if (c.source instanceof RegisterOperand) {
                    Register r = c.source.asRegister().getRegister();
                    usedByAnother.add(r);
                }
            }
        }
    }
    // the set of needed copies.
    for (Iterator<Copy> copySetIter = copySet.iterator(); copySetIter.hasNext(); ) {
        Copy c = copySetIter.next();
        if (!usedByAnother.contains(c.destination.getRegister())) {
            workList.add(0, c);
            copySetIter.remove();
        }
    }
    // while there is any more work to do.
    while (!workList.isEmpty() || !copySet.isEmpty()) {
        // while there are copies that can be correctly inserted.
        while (!workList.isEmpty()) {
            Copy c = workList.remove(0);
            Register r = c.destination.getRegister();
            TypeReference tt = c.destination.getType();
            if (VM.VerifyAssertions && tt == null) {
                tt = TypeReference.Int;
                VM.sysWriteln("SSA, warning: null type in " + c.destination);
            }
            Register rr = null;
            if (c.source.isRegister())
                rr = c.source.asRegister().getRegister();
            boolean shouldSplitBlock = !c.phi.getBasicBlock().isExceptionHandlerBasicBlock() && ((ir.options.SSA_SPLITBLOCK_TO_AVOID_RENAME && out.contains(r)) || (rr != null && ir.options.SSA_SPLITBLOCK_FOR_LOCAL_LIVE && usedBelowCopy(bb, rr)));
            if (ir.options.SSA_SPLITBLOCK_INTO_INFREQUENT) {
                if (!bb.getInfrequent() && c.phi.getBasicBlock().getInfrequent() && !c.phi.getBasicBlock().isExceptionHandlerBasicBlock()) {
                    shouldSplitBlock = true;
                }
            }
            // new name.
            if (out.contains(r) && !shouldSplitBlock) {
                if (!globalRenamePhis.contains(r)) {
                    Register t = ir.regpool.getReg(r);
                    Instruction save = SSA.makeMoveInstruction(ir, t, r, tt);
                    if (DEBUG) {
                        VM.sysWriteln("Inserting " + save + " before " + c.phi + " in " + c.phi.getBasicBlock());
                    }
                    c.phi.insertAfter(save);
                    globalRenamePhis.add(r);
                    globalRenameTable.add(save);
                }
            }
            Instruction ci = null;
            // insert copy operation required to remove phi
            if (c.source instanceof ConstantOperand) {
                if (c.source instanceof UnreachableOperand) {
                    ci = null;
                } else {
                    ci = SSA.makeMoveInstruction(ir, r, (ConstantOperand) c.source);
                }
            } else if (c.source instanceof RegisterOperand) {
                if (shouldSplitBlock) {
                    if (DEBUG)
                        VM.sysWriteln("splitting edge: " + bb + "->" + c.phi.getBasicBlock());
                    BasicBlock criticalBlock = criticalBlocks.get(c.phi.getBasicBlock());
                    if (criticalBlock == null) {
                        criticalBlock = IRTools.makeBlockOnEdge(bb, c.phi.getBasicBlock(), ir);
                        if (c.phi.getBasicBlock().getInfrequent()) {
                            criticalBlock.setInfrequent();
                        }
                        splitSomeBlock = true;
                        criticalBlocks.put(c.phi.getBasicBlock(), criticalBlock);
                        HashMap<Register, Register> newNames = new HashMap<Register, Register>(4);
                        currentNames.put(criticalBlock, newNames);
                    }
                    Register sr = c.source.asRegister().getRegister();
                    HashMap<Register, Register> criticalBlockNames = currentNames.get(criticalBlock);
                    Register nameForSR = criticalBlockNames.get(sr);
                    if (nameForSR == null) {
                        nameForSR = bbNames.get(sr);
                        if (nameForSR == null)
                            nameForSR = sr;
                    }
                    if (DEBUG)
                        VM.sysWriteln("dest(r): " + r);
                    if (DEBUG)
                        VM.sysWriteln("sr: " + sr + ", nameForSR: " + nameForSR);
                    ci = SSA.makeMoveInstruction(ir, r, nameForSR, tt);
                    criticalBlockNames.put(sr, r);
                    criticalBlock.appendInstructionRespectingTerminalBranch(ci);
                } else {
                    Register sr = c.source.asRegister().getRegister();
                    Register nameForSR = bbNames.get(sr);
                    if (nameForSR == null)
                        nameForSR = sr;
                    if (DEBUG)
                        VM.sysWriteln("not splitting edge: " + bb + "->" + c.phi.getBasicBlock());
                    if (DEBUG)
                        VM.sysWriteln("dest(r): " + r);
                    if (DEBUG)
                        VM.sysWriteln("sr: " + sr + ", nameForSR: " + nameForSR);
                    ci = SSA.makeMoveInstruction(ir, r, nameForSR, tt);
                    bbNames.put(sr, r);
                    SSA.addAtEnd(ir, bb, ci, c.phi.getBasicBlock().isExceptionHandlerBasicBlock());
                }
                // ugly hack: having already added ci; set ci to null to skip remaining code;
                ci = null;
            } else {
                throw new OptimizingCompilerException("Unexpected phi operand " + c.source + " encountered during SSA teardown", true);
            }
            if (ci != null) {
                if (shouldSplitBlock) {
                    if (DEBUG)
                        VM.sysWriteln("splitting edge: " + bb + "->" + c.phi.getBasicBlock());
                    BasicBlock criticalBlock = criticalBlocks.get(c.phi.getBasicBlock());
                    if (criticalBlock == null) {
                        criticalBlock = IRTools.makeBlockOnEdge(bb, c.phi.getBasicBlock(), ir);
                        if (c.phi.getBasicBlock().getInfrequent()) {
                            criticalBlock.setInfrequent();
                        }
                        splitSomeBlock = true;
                        criticalBlocks.put(c.phi.getBasicBlock(), criticalBlock);
                        HashMap<Register, Register> newNames = new HashMap<Register, Register>(4);
                        currentNames.put(criticalBlock, newNames);
                    }
                    criticalBlock.appendInstructionRespectingTerminalBranch(ci);
                } else {
                    SSA.addAtEnd(ir, bb, ci, c.phi.getBasicBlock().isExceptionHandlerBasicBlock());
                }
            }
            // current copy to the work list.
            if (c.source instanceof RegisterOperand) {
                Register saved = c.source.asRegister().getRegister();
                Iterator<Copy> copySetIter = copySet.iterator();
                while (copySetIter.hasNext()) {
                    Copy cc = copySetIter.next();
                    if (cc.destination.asRegister().getRegister() == saved) {
                        workList.add(0, cc);
                        copySetIter.remove();
                    }
                }
            }
        }
        // safely overwritten.  so, add that copy to the work list.
        if (!copySet.isEmpty()) {
            Copy c = copySet.remove(0);
            Register tt = ir.regpool.getReg(c.destination.getRegister());
            SSA.addAtEnd(ir, bb, SSA.makeMoveInstruction(ir, tt, c.destination.getRegister(), c.destination.getType()), c.phi.getBasicBlock().isExceptionHandlerBasicBlock());
            bbNames.put(c.destination.getRegister(), tt);
            workList.add(0, c);
        }
    }
}
Also used : LiveSet(org.jikesrvm.compilers.opt.liveness.LiveSet) HashMap(java.util.HashMap) UnreachableOperand(org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) UnreachableOperand(org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TypeReference(org.jikesrvm.classloader.TypeReference) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) HashSet(java.util.HashSet) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) LiveAnalysis(org.jikesrvm.compilers.opt.liveness.LiveAnalysis) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) LinkedList(java.util.LinkedList) Register(org.jikesrvm.compilers.opt.ir.Register)

Example 5 with LiveAnalysis

use of org.jikesrvm.compilers.opt.liveness.LiveAnalysis in project JikesRVM by JikesRVM.

the class CoalesceMoves method perform.

@Override
public final void perform(IR ir) {
    // Compute liveness.
    LiveAnalysis live = new LiveAnalysis(false, /* GC Maps */
    false);
    live.perform(ir);
    // TODO: As of August 2014, we're  saving the live analysis results in the
    // LiveAnalysis instances. This means that we need to retain the compiler
    // phase object even if we're only interested in the analysis results.
    // We ought to save the results via the IR object so that we can throw away
    // the phase object once it has performed its work.
    // Compute def-use information.
    DefUse.computeDU(ir);
    Map<Instruction, Integer> instNumbers = ir.numberInstructionsViaMap();
    Coalesce coalesce = new Coalesce(instNumbers);
    // Maintain a set of dead move instructions.
    HashSet<Instruction> dead = new HashSet<Instruction>(5);
    // for each Move instruction ...
    for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements(); ) {
        Instruction s = e.nextElement();
        if (s.operator().isMove()) {
            Register r = Move.getResult(s).asRegister().getRegister();
            if (r.isSymbolic()) {
                Operand val = Move.getVal(s);
                if (val != null && val.isRegister()) {
                    Register r2 = val.asRegister().getRegister();
                    if (r2.isSymbolic()) {
                        if (coalesce.attempt(live, r, r2)) {
                            if (DEBUG)
                                System.out.println("COALESCED " + r + " " + r2);
                            dead.add(s);
                        }
                    }
                }
            }
        }
    }
    // Now remove all dead Move instructions.
    for (Instruction s : dead) {
        DefUse.removeInstructionAndUpdateDU(s);
    }
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) LiveAnalysis(org.jikesrvm.compilers.opt.liveness.LiveAnalysis) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) HashSet(java.util.HashSet)

Aggregations

LiveAnalysis (org.jikesrvm.compilers.opt.liveness.LiveAnalysis)7 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)4 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)3 HashSet (java.util.HashSet)2 MIRBranchOptimizations (org.jikesrvm.compilers.opt.controlflow.MIRBranchOptimizations)2 Register (org.jikesrvm.compilers.opt.ir.Register)2 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)2 ExpandCallingConvention (org.jikesrvm.compilers.opt.regalloc.ExpandCallingConvention)2 PrologueEpilogueCreator (org.jikesrvm.compilers.opt.regalloc.PrologueEpilogueCreator)2 RegisterAllocator (org.jikesrvm.compilers.opt.regalloc.RegisterAllocator)2 HashMap (java.util.HashMap)1 LinkedList (java.util.LinkedList)1 TypeReference (org.jikesrvm.classloader.TypeReference)1 OptimizingCompilerException (org.jikesrvm.compilers.opt.OptimizingCompilerException)1 DominatorTree (org.jikesrvm.compilers.opt.controlflow.DominatorTree)1 DominatorTreeNode (org.jikesrvm.compilers.opt.controlflow.DominatorTreeNode)1 ExceptionHandlerBasicBlock (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)1 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)1 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)1 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)1