use of org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand in project JikesRVM by JikesRVM.
the class LeaveSSA method normalizeSSA.
/**
* Avoid potential lost copy and other associated problems by
* Sreedhar's naive translation from TSSA to CSSA. Guards are rather
* trivial to un-SSA so they have already been removed from the IR.
* This algorithm is very wasteful of registers so needs good
* coalescing.
* @param ir the IR to work upon
*/
// NB this was an aborted attempt to fix a bug in leave SSA
@SuppressWarnings("unused")
private static void normalizeSSA(IR ir) {
for (Instruction s = ir.firstInstructionInCodeOrder(), sentinel = ir.lastInstructionInCodeOrder(), nextInstr = null; s != sentinel; s = nextInstr) {
// cache so we don't process inserted instructions
nextInstr = s.nextInstructionInCodeOrder();
if (Phi.conforms(s) && !s.getBasicBlock().isExceptionHandlerBasicBlock()) {
// We ignore exception handler BBs as they cause problems when inserting copies
if (DEBUG)
VM.sysWriteln("Processing " + s + " of basic block " + s.getBasicBlock());
// Does the phi instruction have an unreachable operand?
boolean hasUnreachable = false;
// 1. Naively copy source operands into predecessor blocks
for (int index = 0; index < Phi.getNumberOfPreds(s); index++) {
Operand op = Phi.getValue(s, index);
if (op.isRegister()) {
// Get rval
Register rval = op.asRegister().getRegister();
if (rval.isValidation()) {
// ignore guards
continue;
} else {
// Make rval'
Register rvalPrime = ir.regpool.getReg(rval);
// Make copy instruction
Instruction copy = SSA.makeMoveInstruction(ir, rvalPrime, rval, op.getType());
// Insert a copy of rval to rval' in predBlock
BasicBlock pred = Phi.getPred(s, index).block;
pred.appendInstructionRespectingTerminalBranch(copy);
if (DEBUG)
VM.sysWriteln("Inserted rval copy of " + copy + " into basic block " + pred);
// Rename rval to rval' in phi instruction
op.asRegister().setRegister(rvalPrime);
}
} else if (op instanceof UnreachableOperand) {
hasUnreachable = true;
}
}
// 2. Naively copy the result if there were no unreachable operands
if (!hasUnreachable) {
Operand op = Phi.getResult(s);
if (!op.isRegister()) {
// ignore heap operands
} else {
// Get lval
Register lval = op.asRegister().getRegister();
// Make lval'
Register lvalPrime = ir.regpool.getReg(lval);
// Make copy instruction
Instruction copy = SSA.makeMoveInstruction(ir, lval, lvalPrime, op.getType());
// Insert a copy of lval' to lval after phi instruction
s.insertAfter(copy);
// Rename lval to lval' in phi instruction
op.asRegister().setRegister(lvalPrime);
if (DEBUG)
VM.sysWriteln("Inserted lval copy of " + copy + " after " + s);
}
}
}
}
}
use of org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand 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.ir.operand.UnreachableOperand in project JikesRVM by JikesRVM.
the class LeaveSSA method unSSAGuardsInit.
/**
* Initialization for removal of guard phis.
*
* @param ir the governing IR, currently in SSA form
*/
private void unSSAGuardsInit(IR ir) {
guardPhis = null;
Enumeration<Instruction> e = ir.forwardInstrEnumerator();
// visit all instructions, looking for guard phis
inst2guardPhi = new HashMap<Instruction, Instruction>();
while (e.hasMoreElements()) {
Instruction inst = e.nextElement();
if (!Phi.conforms(inst))
continue;
Operand res = Phi.getResult(inst);
if (!(res instanceof RegisterOperand))
continue;
Register r = res.asRegister().getRegister();
if (!r.isValidation())
continue;
// force all operands of Phis into registers.
inst2guardPhi.put(inst, guardPhis);
guardPhis = inst;
int values = Phi.getNumberOfValues(inst);
for (int i = 0; i < values; ++i) {
Operand op = Phi.getValue(inst, i);
if (!(op instanceof RegisterOperand)) {
if (op instanceof TrueGuardOperand) {
BasicBlock bb = Phi.getPred(inst, i).block;
Instruction move = Move.create(GUARD_MOVE, res.asRegister().copyD2D(), new TrueGuardOperand());
move.setSourcePosition(SSA_SYNTH_BCI, ir.getGc().getInlineSequence());
bb.appendInstructionRespectingTerminalBranchOrPEI(move);
} else if (op instanceof UnreachableOperand) {
// do nothing
} else {
if (VM.VerifyAssertions)
VM._assert(VM.NOT_REACHED);
}
}
}
}
guardRegUnion = new HashMap<Register, Integer>();
associatedRegisters = new HashMap<Register, Register>();
// visit all guard registers, init union/find
for (Register r = ir.regpool.getFirstSymbolicRegister(); r != null; r = r.getNext()) {
if (!r.isValidation())
continue;
guardRegUnion.put(r, Integer.valueOf(1));
associatedRegisters.put(r, r);
}
}
use of org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand in project JikesRVM by JikesRVM.
the class EnterSSA method search.
/**
* This routine is the guts of the SSA construction phase for scalars. See
* renameSymbolicRegisters for more details.
*
* @param X basic block to search dominator tree from
* @param S stack of names for each register
*/
private void search(BasicBlock X, Stack<RegisterOperand>[] S) {
if (DEBUG)
System.out.println("SEARCH " + X);
HashMap<Register, Register> pushedRegs = new HashMap<Register, Register>();
for (Enumeration<Instruction> ie = X.forwardInstrEnumerator(); ie.hasMoreElements(); ) {
Instruction A = ie.nextElement();
if (A.operator() != PHI) {
// replace each use
for (int u = A.getNumberOfDefs(); u < A.getNumberOfOperands(); u++) {
Operand op = A.getOperand(u);
if (op instanceof RegisterOperand) {
RegisterOperand rop = (RegisterOperand) op;
Register r1 = rop.getRegister();
if (r1.isSSA())
continue;
if (r1.isPhysical())
continue;
RegisterOperand r2 = S[r1.getNumber()].peek();
if (DEBUG)
System.out.println("REPLACE NORMAL USE " + r1 + " with " + r2);
if (r2 != null) {
rop.setRegister(r2.getRegister());
DefUse.recordUse(rop);
}
}
}
}
// replace each def
for (int d = 0; d < A.getNumberOfDefs(); d++) {
Operand op = A.getOperand(d);
if (op instanceof RegisterOperand) {
RegisterOperand rop = (RegisterOperand) op;
Register r1 = rop.getRegister();
if (r1.isSSA())
continue;
if (r1.isPhysical())
continue;
Register r2 = ir.regpool.getReg(r1);
if (DEBUG)
System.out.println("PUSH " + r2 + " FOR " + r1 + " BECAUSE " + A);
S[r1.getNumber()].push(new RegisterOperand(r2, rop.getType()));
rop.setRegister(r2);
pushedRegs.put(r2, r1);
}
}
}
if (DEBUG)
System.out.println("SEARCH (second loop) " + X);
for (Enumeration<BasicBlock> y = X.getOut(); y.hasMoreElements(); ) {
BasicBlock Y = y.nextElement();
if (DEBUG)
System.out.println(" Successor: " + Y);
int j = numPredProcessed[Y.getNumber()]++;
if (Y.isExit())
continue;
Instruction s = Y.firstRealInstruction();
if (s == null)
continue;
// replace use USE in each PHI instruction
if (DEBUG)
System.out.println(" Predecessor: " + j);
while (s.operator() == PHI) {
Operand val = Phi.getValue(s, j);
if (val.isRegister()) {
Register r1 = ((RegisterOperand) Phi.getValue(s, j)).getRegister();
// ignore registers already marked SSA by a previous pass
if (!r1.isSSA()) {
RegisterOperand r2 = S[r1.getNumber()].peek();
if (r2 == null) {
// in this case, the register is never defined along
// this particular control flow path into the basic
// block.
Phi.setValue(s, j, new UnreachableOperand());
} else {
RegisterOperand rop = r2.copyRO();
Phi.setValue(s, j, rop);
DefUse.recordUse(rop);
}
Phi.setPred(s, j, new BasicBlockOperand(X));
}
}
s = s.nextInstructionInCodeOrder();
}
}
if (DEBUG)
System.out.println("SEARCH (third loop) " + X);
for (Enumeration<TreeNode> c = ir.HIRInfo.dominatorTree.getChildren(X); c.hasMoreElements(); ) {
DominatorTreeNode v = (DominatorTreeNode) c.nextElement();
search(v.getBlock(), S);
}
if (DEBUG)
System.out.println("SEARCH (fourth loop) " + X);
for (Enumeration<Instruction> a = X.forwardInstrEnumerator(); a.hasMoreElements(); ) {
Instruction A = a.nextElement();
// loop over each def
for (int d = 0; d < A.getNumberOfDefs(); d++) {
Operand newOp = A.getOperand(d);
if (newOp == null)
continue;
if (!newOp.isRegister())
continue;
Register newReg = newOp.asRegister().getRegister();
if (newReg.isSSA())
continue;
if (newReg.isPhysical())
continue;
Register r1 = pushedRegs.get(newReg);
S[r1.getNumber()].pop();
if (DEBUG)
System.out.println("POP " + r1);
}
}
// end of fourth loop
if (DEBUG)
System.out.println("FINISHED SEARCH " + X);
}
use of org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand in project JikesRVM by JikesRVM.
the class Simplifier method getObjTib.
private static DefUseEffect getObjTib(Instruction s, OptOptions opts) {
if (opts.SIMPLIFY_TIB_OPS) {
Operand op = GuardedUnary.getVal(s);
if (op.isNullConstant()) {
// Simplify to an unreachable operand, this instruction is dead code
// guarded by a nullcheck that should already have been simplified
RegisterOperand result = GetField.getClearResult(s);
Move.mutate(s, IRTools.getMoveOp(result.getType()), result, new UnreachableOperand());
return DefUseEffect.MOVE_FOLDED;
} else if (op.isConstant()) {
final TypeReference typeRef = op.getType();
if (typeRef.isResolved()) {
Move.mutate(s, REF_MOVE, GuardedUnary.getClearResult(s), new TIBConstantOperand(op.getType().peekType()));
return DefUseEffect.MOVE_FOLDED;
}
} else {
RegisterOperand rop = op.asRegister();
TypeReference typeRef = rop.getType();
// Is the type of this register only one possible type?
if (typeRef.isResolved() && rop.isPreciseType() && typeRef.resolve().isInstantiated()) {
// before simplifying ensure that the type is instantiated, this stops
// constant propagation potentially moving the TIB constant before the
// runtime call that instantiates it
Move.mutate(s, REF_MOVE, GuardedUnary.getClearResult(s), new TIBConstantOperand(typeRef.peekType()));
return DefUseEffect.MOVE_FOLDED;
}
}
}
return DefUseEffect.UNCHANGED;
}
Aggregations