use of org.jikesrvm.compilers.opt.ir.operand.HeapOperand in project JikesRVM by JikesRVM.
the class LoopVersioning method modifyOriginalLoop.
/*
* TODO Convert to JavaDoc and add missing tags.
* <p>
* Remove loop and replace register definitions in the original loop
* with phi instructions
*/
private void modifyOriginalLoop(AnnotatedLSTNode loop, ArrayList<Instruction> phiInstructions, ArrayList<Instruction> definingInstrInOriginalLoop, HashMap<Register, Register> subOptimalRegMap, HashMap<Register, Register> optimalRegMap) {
// Remove instructions from loop header and exit, remove other
// loop body blocks
Enumeration<BasicBlock> blocks = loop.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
if ((block == loop.header) || (block == loop.exit)) {
IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, block);
while (instructions.hasMoreElements()) {
Instruction instruction = instructions.nextElement();
if (!BBend.conforms(instruction) && !Label.conforms(instruction)) {
instruction.remove();
}
}
} else {
ir.cfg.removeFromCFGAndCodeOrder(block);
}
}
// Place phi instructions in loop header
for (int i = 0; i < phiInstructions.size(); i++) {
Instruction origInstr = definingInstrInOriginalLoop.get(i);
// Did the original instructions value escape the loop?
if (origInstr != null) {
// Was this a phi of a phi?
if (Phi.conforms(origInstr)) {
Instruction phi = phiInstructions.get(i);
boolean phiHasUnoptimizedArg = Phi.getNumberOfValues(phi) == 2;
// Phi of a phi - so make sure that we get the value to escape the loop, not the value at the loop header
boolean fixed = false;
for (int index = 0; index < Phi.getNumberOfPreds(origInstr); index++) {
BasicBlockOperand predOp = Phi.getPred(origInstr, index);
// Only worry about values who are on the backward branch
if (predOp.block == loop.exit) {
if (fixed) {
// We've tried to do 2 replaces => something wrong
SSA.printInstructions(ir);
OptimizingCompilerException.UNREACHABLE("LoopVersioning", "Phi node in loop header with multiple in loop predecessors");
}
Operand rval = Phi.getValue(origInstr, index);
if (rval.isRegister()) {
// Sort out registers
Register origRegPhiRval = rval.asRegister().getRegister();
Register subOptRegPhiRval;
Register optRegPhiRval;
if (!subOptimalRegMap.containsKey(origRegPhiRval)) {
// Register comes from loop exit but it wasn't defined in the loop
subOptRegPhiRval = origRegPhiRval;
optRegPhiRval = origRegPhiRval;
} else {
subOptRegPhiRval = subOptimalRegMap.get(origRegPhiRval);
optRegPhiRval = optimalRegMap.get(origRegPhiRval);
}
if (phiHasUnoptimizedArg) {
Phi.getValue(phi, UNOPTIMIZED_LOOP_OPERAND).asRegister().setRegister(subOptRegPhiRval);
}
Phi.getValue(phi, OPTIMIZED_LOOP_OPERAND).asRegister().setRegister(optRegPhiRval);
} else if (rval.isConstant()) {
// Sort out constants
if (phiHasUnoptimizedArg) {
Phi.setValue(phi, UNOPTIMIZED_LOOP_OPERAND, rval.copy());
}
Phi.setValue(phi, OPTIMIZED_LOOP_OPERAND, rval.copy());
} else if (rval instanceof HeapOperand) {
// Sort out heap variables
// Cast to generic type
@SuppressWarnings("unchecked") HeapVariable<Object> origPhiRval = ((HeapOperand) rval).value;
HeapVariable<Object> subOptPhiRval;
HeapVariable<Object> optPhiRval;
if (true) /*subOptimalRegMap.containsKey(origPhiRval) == false*/
{
// currently we only expect to optimise scalar SSA
// form
subOptPhiRval = origPhiRval;
optPhiRval = origPhiRval;
} else {
/*
subOptPhiRval = (HeapVariable)subOptimalRegMap.get(origPhiRval);
optPhiRval = (HeapVariable)optimalRegMap.get(origPhiRval);
*/
}
if (phiHasUnoptimizedArg) {
Phi.setValue(phi, UNOPTIMIZED_LOOP_OPERAND, new HeapOperand<Object>(subOptPhiRval));
}
Phi.setValue(phi, OPTIMIZED_LOOP_OPERAND, new HeapOperand<Object>(optPhiRval));
} else {
OptimizingCompilerException.UNREACHABLE("LoopVersioning", "Unknown operand type", rval.toString());
}
fixed = true;
}
}
}
// Add back to loop
loop.header.appendInstruction(phiInstructions.get(i));
}
}
// Remove original loop and branch to loop successor
Instruction tempInstr;
if (loop.header != loop.exit) {
tempInstr = Goto.create(GOTO, loop.exit.makeJumpTarget());
tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
loop.header.appendInstruction(tempInstr);
loop.header.deleteNormalOut();
loop.header.insertOut(loop.exit);
}
tempInstr = Goto.create(GOTO, loop.successor.makeJumpTarget());
tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
loop.exit.appendInstruction(tempInstr);
loop.exit.deleteNormalOut();
loop.exit.insertOut(loop.successor);
}
use of org.jikesrvm.compilers.opt.ir.operand.HeapOperand in project JikesRVM by JikesRVM.
the class SSA method printInstructions.
/**
* Print the instructions in SSA form.
*
* @param ir the IR, assumed to be in SSA form
*/
public static void printInstructions(IR ir) {
SSADictionary dictionary = ir.HIRInfo.dictionary;
System.out.println("********* START OF IR DUMP in SSA FOR " + ir.method);
for (Enumeration<BasicBlock> be = ir.forwardBlockEnumerator(); be.hasMoreElements(); ) {
BasicBlock bb = be.nextElement();
// print the explicit instructions for basic block bb
for (Enumeration<Instruction> e = dictionary.getAllInstructions(bb); e.hasMoreElements(); ) {
Instruction s = e.nextElement();
System.out.print(s.getBytecodeIndex() + "\t" + s);
if (dictionary.defsHeapVariable(s) && s.operator() != PHI) {
System.out.print(" (Implicit Defs: ");
HeapOperand<?>[] defs = dictionary.getHeapDefs(s);
if (defs != null) {
for (HeapOperand<?> def : defs) System.out.print(def + " ");
}
System.out.print(" )");
}
if (dictionary.usesHeapVariable(s) && s.operator() != PHI) {
System.out.print(" (Implicit Uses: ");
HeapOperand<?>[] uses = dictionary.getHeapUses(s);
if (uses != null) {
for (HeapOperand<?> use : uses) System.out.print(use + " ");
}
System.out.print(" )");
}
System.out.println();
}
}
System.out.println("********* END OF IR DUMP in SSA FOR " + ir.method);
}
use of org.jikesrvm.compilers.opt.ir.operand.HeapOperand in project JikesRVM by JikesRVM.
the class EnterSSA method search2.
/**
* This routine is the guts of the SSA construction phase for heap array
* SSA. The renaming algorithm is analagous to the algorithm for
* scalars See <code> renameSymbolicRegisters </code> for more details.
*
* @param X the current basic block being traversed
* @param stacks a structure holding the current names for each heap
* variable
* used and defined by each instruction.
*/
private void search2(BasicBlock X, HashMap<Object, Stack<HeapOperand<Object>>> stacks) {
if (DEBUG)
System.out.println("SEARCH2 " + X);
SSADictionary dictionary = ir.HIRInfo.dictionary;
for (Enumeration<Instruction> ie = dictionary.getAllInstructions(X); ie.hasMoreElements(); ) {
Instruction A = ie.nextElement();
if (!dictionary.usesHeapVariable(A) && !dictionary.defsHeapVariable(A))
continue;
if (A.operator() != PHI) {
// replace the Heap variables USED by this instruction
HeapOperand<Object>[] uses = dictionary.getHeapUses(A);
if (uses != null) {
// Generic array problem
@SuppressWarnings("unchecked") HeapOperand<Object>[] newUses = new HeapOperand[uses.length];
for (int i = 0; i < uses.length; i++) {
Stack<HeapOperand<Object>> S = stacks.get(uses[i].getHeapType());
newUses[i] = S.peek().copy();
if (DEBUG) {
System.out.println("NORMAL USE PEEK " + newUses[i]);
}
}
dictionary.replaceUses(A, newUses);
}
}
// replace any Heap variable DEF
if (A.operator() != PHI) {
HeapOperand<Object>[] defs = dictionary.getHeapDefs(A);
if (defs != null) {
for (HeapOperand<Object> operand : dictionary.replaceDefs(A, X)) {
Stack<HeapOperand<Object>> S = stacks.get(operand.getHeapType());
S.push(operand);
if (DEBUG)
System.out.println("PUSH " + operand + " FOR " + operand.getHeapType());
}
}
} else {
HeapOperand<Object>[] r = dictionary.replaceDefs(A, X);
Stack<HeapOperand<Object>> S = stacks.get(r[0].getHeapType());
S.push(r[0]);
if (DEBUG)
System.out.println("PUSH " + r[0] + " FOR " + r[0].getHeapType());
}
}
for (Enumeration<BasicBlock> y = X.getOut(); y.hasMoreElements(); ) {
BasicBlock Y = y.nextElement();
if (Y.isExit())
continue;
int j = numPredProcessed[Y.getNumber()]++;
// replace each USE in each HEAP-PHI function for Y
for (Iterator<Instruction> hp = dictionary.getHeapPhiInstructions(Y); hp.hasNext(); ) {
Instruction s = hp.next();
// Down-cast to a generic type
@SuppressWarnings("unchecked") HeapOperand<Object> H1 = (HeapOperand) Phi.getResult(s);
Stack<HeapOperand<Object>> S = stacks.get(H1.getHeapType());
HeapOperand<Object> H2 = S.peek();
Phi.setValue(s, j, new HeapOperand<Object>(H2.getHeapVariable()));
Phi.setPred(s, j, new BasicBlockOperand(X));
}
}
for (Enumeration<TreeNode> c = ir.HIRInfo.dominatorTree.getChildren(X); c.hasMoreElements(); ) {
DominatorTreeNode v = (DominatorTreeNode) c.nextElement();
search2(v.getBlock(), stacks);
}
for (Enumeration<Instruction> a = dictionary.getAllInstructions(X); a.hasMoreElements(); ) {
Instruction A = a.nextElement();
if (!dictionary.usesHeapVariable(A) && !dictionary.defsHeapVariable(A))
continue;
// retrieve the Heap Variables defined by A
if (A.operator() != PHI) {
HeapOperand<Object>[] defs = dictionary.getHeapDefs(A);
if (defs != null) {
for (HeapOperand<Object> def : defs) {
Stack<HeapOperand<Object>> S = stacks.get(def.getHeapType());
S.pop();
if (DEBUG)
System.out.println("POP " + def.getHeapType());
}
}
} else {
// Down-cast to a generic type
@SuppressWarnings("unchecked") HeapOperand<Object> H = (HeapOperand) Phi.getResult(A);
Stack<HeapOperand<Object>> S = stacks.get(H.getHeapType());
S.pop();
if (DEBUG)
System.out.println("POP " + H.getHeapType());
}
}
// end of fourth loop
if (DEBUG)
System.out.println("END SEARCH2 " + X);
}
use of org.jikesrvm.compilers.opt.ir.operand.HeapOperand in project JikesRVM by JikesRVM.
the class IndexPropagationSystem method processPhi.
/**
* Update the set of dataflow equations to account for the actions
* of Phi instruction.
*
* <p> The instruction has the form A1 = PHI (A2, A3, A4);
* We add the dataflow equation
* L(A1) = MEET(L(A2), L(A3), L(A4))
*
* @param s the Phi instruction
*/
void processPhi(Instruction s) {
Operand result = Phi.getResult(s);
if (!(result instanceof HeapOperand)) {
return;
}
HeapVariable<?> lhs = ((HeapOperand<?>) result).value;
DF_LatticeCell A1 = findOrCreateCell(lhs);
DF_LatticeCell[] rhs = new DF_LatticeCell[Phi.getNumberOfValues(s)];
for (int i = 0; i < rhs.length; i++) {
HeapOperand<?> op = (HeapOperand<?>) Phi.getValue(s, i);
rhs[i] = findOrCreateCell(op.value);
}
newEquation(A1, MEET, rhs);
}
use of org.jikesrvm.compilers.opt.ir.operand.HeapOperand in project JikesRVM by JikesRVM.
the class IndexPropagationSystem method processALoad.
/**
* Update the set of dataflow equations to account for the actions
* of ALoad instruction s
*
* <p> The load is of the form x = A[k]. let A_1 be the array SSA
* variable before the load, and A_2 the array SSA variable after
* the load. Then we add the dataflow equation
* L(A_2) = updateUse(L(A_1), VALNUM(k))
*
* <p> Intuitively, this equation represents the fact that A[k] is available
* after the store
*
* @param s the Aload instruction
*/
void processALoad(Instruction s) {
HeapOperand<?>[] A1 = ssa.getHeapUses(s);
HeapOperand<?>[] A2 = ssa.getHeapDefs(s);
if ((A1.length != 1) || (A2.length != 1)) {
throw new OptimizingCompilerException("IndexPropagation.processALoad: aload instruction defs or uses multiple heap variables?");
}
Operand array = ALoad.getArray(s);
Operand index = ALoad.getIndex(s);
if (IRTools.mayBeVolatileFieldLoad(s) || ir.options.READS_KILL) {
// to obey JMM strictly, we must treat every load as a
// DEF
addUpdateArrayDefEquation(A2[0].getHeapVariable(), A1[0].getHeapVariable(), array, index);
} else {
// otherwise, don't have to treat every load as a DEF
addUpdateArrayUseEquation(A2[0].getHeapVariable(), A1[0].getHeapVariable(), array, index);
}
}
Aggregations