Search in sources :

Example 1 with HeapOperand

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);
}
Also used : BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) 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) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) Register(org.jikesrvm.compilers.opt.ir.Register) IREnumeration(org.jikesrvm.compilers.opt.ir.IREnumeration)

Example 2 with HeapOperand

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);
}
Also used : HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 3 with HeapOperand

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);
}
Also used : BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) DominatorTreeNode(org.jikesrvm.compilers.opt.controlflow.DominatorTreeNode) TreeNode(org.jikesrvm.compilers.opt.util.TreeNode) DominatorTreeNode(org.jikesrvm.compilers.opt.controlflow.DominatorTreeNode)

Example 4 with HeapOperand

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);
}
Also used : HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) DF_LatticeCell(org.jikesrvm.compilers.opt.dfsolver.DF_LatticeCell) HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand)

Example 5 with HeapOperand

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);
    }
}
Also used : HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException)

Aggregations

HeapOperand (org.jikesrvm.compilers.opt.ir.operand.HeapOperand)20 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)13 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)8 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)7 BasicBlockOperand (org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand)5 OptimizingCompilerException (org.jikesrvm.compilers.opt.OptimizingCompilerException)4 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)4 Register (org.jikesrvm.compilers.opt.ir.Register)3 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)3 HashSet (java.util.HashSet)2 RVMField (org.jikesrvm.classloader.RVMField)2 TypeReference (org.jikesrvm.classloader.TypeReference)2 HashMap (java.util.HashMap)1 Iterator (java.util.Iterator)1 Stack (java.util.Stack)1 DominatorTreeNode (org.jikesrvm.compilers.opt.controlflow.DominatorTreeNode)1 DF_LatticeCell (org.jikesrvm.compilers.opt.dfsolver.DF_LatticeCell)1 ExceptionHandlerBasicBlock (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)1 IREnumeration (org.jikesrvm.compilers.opt.ir.IREnumeration)1 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)1