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() ****");
}
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);
}
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);
}
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);
}
}
}
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);
}
}
Aggregations