Search in sources :

Example 21 with Operand

use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.

the class LiveAnalysis method collectOsrInfo.

/* collect osr info according to live information */
private void collectOsrInfo(Instruction inst, LiveSet lives) {
    // create an entry to the OSRIRMap, order: callee => caller
    LinkedList<MethodVariables> mvarList = new LinkedList<MethodVariables>();
    // get the type info for locals and stacks
    InlinedOsrTypeInfoOperand typeInfo = OsrPoint.getInlinedTypeInfo(inst);
    /* iterator over type info and create LocalRegTuple
    * for each variable.
    * NOTE: we do not process LONG type register operand here,
    * which was splitted in BURS.
    */
    byte[][] ltypes = typeInfo.localTypeCodes;
    byte[][] stypes = typeInfo.stackTypeCodes;
    int nummeth = typeInfo.methodids.length;
    int elm_idx = 0;
    int snd_long_idx = typeInfo.validOps;
    for (int midx = 0; midx < nummeth; midx++) {
        LinkedList<LocalRegPair> tupleList = new LinkedList<LocalRegPair>();
        byte[] ls = ltypes[midx];
        byte[] ss = stypes[midx];
        /* record maps for local variables, skip dead ones */
        for (int i = 0, n = ls.length; i < n; i++) {
            if (ls[i] != VoidTypeCode) {
                // check liveness
                Operand op = OsrPoint.getElement(inst, elm_idx++);
                LocalRegPair tuple = new LocalRegPair(LOCAL, i, ls[i], op);
                // put it in the list
                tupleList.add(tuple);
                // get another half of a long type operand
                if (VM.BuildFor32Addr && (ls[i] == LongTypeCode)) {
                    Operand other_op = OsrPoint.getElement(inst, snd_long_idx++);
                    tuple._otherHalf = new LocalRegPair(LOCAL, i, ls[i], other_op);
                }
            }
        }
        /* record maps for stack slots */
        for (int i = 0, n = ss.length; i < n; i++) {
            if (ss[i] != VoidTypeCode) {
                LocalRegPair tuple = new LocalRegPair(STACK, i, ss[i], OsrPoint.getElement(inst, elm_idx++));
                tupleList.add(tuple);
                if (VM.BuildFor32Addr && (ss[i] == LongTypeCode)) {
                    tuple._otherHalf = new LocalRegPair(STACK, i, ss[i], OsrPoint.getElement(inst, snd_long_idx++));
                }
            }
        }
        // create MethodVariables
        MethodVariables mvar = new MethodVariables(typeInfo.methodids[midx], typeInfo.bcindexes[midx], tupleList);
        mvarList.add(mvar);
    }
    // put the method variables for this OSR in the osrMap, encoding later.
    osrMap.insertFirst(inst, mvarList);
}
Also used : InlinedOsrTypeInfoOperand(org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand) BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) InlinedOsrTypeInfoOperand(org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand) LocalRegPair(org.jikesrvm.osr.LocalRegPair) MethodVariables(org.jikesrvm.osr.MethodVariables) LinkedList(java.util.LinkedList) OsrPoint(org.jikesrvm.compilers.opt.ir.OsrPoint)

Example 22 with Operand

use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.

the class LiveAnalysis method computeBlockGenAndKill.

/**
 * Compute summary (local) live variable analysis for a basic block, which
 * is basically Gen and Kill information.<p>
 *
 * For more details, see the paper "Efficient and Precise Modeling of
 * Exceptions for the Analysis of Java Programs" by Choi, Grove, Hind
 * and Sarkar in ACM PASTE99 workshop.
 *
 * @param bblock the basic block
 * @param ir the governing IR
 */
private void computeBlockGenAndKill(BasicBlock bblock, IR ir) {
    if (VERBOSE) {
        System.out.println(" --> Computing Gen/Kill for block " + bblock);
    }
    // Tells whether we've seen the first PEI
    boolean seenFirstPEI = false;
    // Because control flow may emanate from a potentially excepting
    // instruction (PEI) out of the basic block, care must be taken
    // when computing what can be killed by a basic block.
    // 
    // S1:  y =
    // S2:  <exception-raising inst>
    // S3:  x =
    // For example in the block above, live variables coming from
    // the normal exit of the block (i.e., after S3) can be killed
    // by S1 or S3 (depending on the variable).  However, live variables
    // coming from the PEI edge (at S2) can only be killed by S1.
    // Thus, when a block contains PEIs, we need to distinguish the
    // kill sets.  Namely, we need
    // Kill_tot  -  what can be killed anywhere in the block
    // Kill_n    -  what can be killed from PEI_n on up
    // Kill_n-1  -  what can be killed from PEI_n-1 on up
    // ...
    // Kill_1    -  what can be killed from PEI_1 on up
    // We would then compute In as follows
    // 
    // In = Out_norm - Kill_tot   (all vars entering from bottom are eligible
    // to be killed)
    // U Out_n - Kill_n
    // U Out_n-1 - Kill_n-1
    // ...
    // U Out_1 - Kill_1
    // U Gen
    // where Out_n is the out information at PEI i, i.e., the IN information
    // for whatever handlers may catch PEI i
    // ...
    // PEI 1
    // ...
    // PEI n-1
    // ...
    // PEI n
    // ...
    // If we conservatively assume all handlers for the block of interest
    // can be reached by all PEIs in this block then the equation becomes
    // In = (Out_norm - Kill_tot)
    // U (Out_hand - Kill_n)
    // U (Out_hand - Kill_n-1)
    // ...
    // U (Out_hand - Kill_1)
    // U Gen
    // where "Out_hand" is the union of the in sets for all handlers.
    // Since Kill_i is a subset of Kill_j, for i < j, we can simplify to
    // In = (Out_norm - Kill_tot)
    // U (Out_hand - Kill_1)    (1)
    // U Gen
    // Since kill_1 is a subset of kill_tot, we don't need the
    // the parenthesis (and the intermediate set)
    // If there are no handlers than (1) is empty and we don't need
    // to compute Kill_1.  We will take this approach for now.
    // So for each block we will have at most 2 kill sets: Kill_tot and Kill_1
    // This code finds the first PEI in the block
    Instruction firstPEI = null;
    if (bblock.canThrowExceptions()) {
        for (Instruction inst = bblock.firstInstruction(); inst != bblock.lastInstruction(); inst = inst.nextInstructionInCodeOrder()) {
            if (inst.isPEI() && bblock.getApplicableExceptionalOut(inst).hasMoreElements()) {
                firstPEI = inst;
                // remember that this block has a PEI with a handler for use
                // later in "processBlock"
                bbLiveInfo[bblock.getNumber()].setContainsPEIWithHandler(true);
                break;
            }
        }
    }
    // Get any uses from PHIs, which are in the successor blocks
    getUsesFromPhis(bblock);
    // Traverse instructions in reverse order within the basic block.
    for (Instruction inst = bblock.lastInstruction(); inst != bblock.firstInstruction(); inst = inst.prevInstructionInCodeOrder()) {
        // traverse from defs to uses becauses uses happen after
        // (in a backward sense) defs
        Enumeration<Operand> defs = inst.getPureDefs();
        while (defs.hasMoreElements()) {
            Operand def = defs.nextElement();
            if (def instanceof RegisterOperand) {
                RegisterOperand regOp = (RegisterOperand) def;
                // Do we care about this reg?
                if (isSkippableReg(regOp, ir)) {
                    continue;
                }
                TypeReference regType = regOp.getType();
                // include it.  It will be picked up later by local propagation phase.
                if (regOp.getRegister().spansBasicBlock() && regType != null) {
                    // if it is a DEF we place it is the BBKillSet and remove it from
                    // the GEN set, (GEN should only contain upward-exposed uses,
                    // i.e., uses that are NOT dominated by a DEF).
                    // We don't need to worry about PEIs here because
                    // later instructions (traversing backwards like we are)
                    // will always dominate earlier instructions *of this block*
                    bbLiveInfo[bblock.getNumber()].BBKillSet().add(regOp);
                    bbLiveInfo[bblock.getNumber()].getGen().remove(regOp);
                    // If there are no PEIs in this block we don't bother to add
                    if (seenFirstPEI) {
                        bbLiveInfo[bblock.getNumber()].firstPEIKillSet().add(regOp);
                    }
                }
            }
        }
        // Now process the uses, unless this is a PHI operator
        if (inst.operator() != PHI) {
            for (Enumeration<Operand> uses = inst.getUses(); uses.hasMoreElements(); ) {
                Operand use = uses.nextElement();
                if (use instanceof RegisterOperand) {
                    RegisterOperand regOp = (RegisterOperand) use;
                    // Do we care about this reg?
                    if (isSkippableReg(regOp, ir)) {
                        continue;
                    }
                    TypeReference regType = regOp.getType();
                    // later by local propagation phase.
                    if (regOp.getRegister().spansBasicBlock() && regType != null) {
                        bbLiveInfo[bblock.getNumber()].getGen().add(regOp);
                    }
                }
            // is RegOp
            }
        // foreach use
        }
        // If so, set the flag so we can start killing.
        if (firstPEI == inst) {
            seenFirstPEI = true;
        }
    }
    // foreach instruction in block
    if (VERBOSE) {
        System.out.println("  Gen: " + bbLiveInfo[bblock.getNumber()].getGen());
        System.out.println("  Kill: " + bbLiveInfo[bblock.getNumber()].BBKillSet());
        System.out.println("  1st PEI Kill: " + bbLiveInfo[bblock.getNumber()].firstPEIKillSet());
        System.out.println(" ---> Done computing Gen/Kill for block");
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) InlinedOsrTypeInfoOperand(org.jikesrvm.compilers.opt.ir.operand.InlinedOsrTypeInfoOperand) BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 23 with Operand

use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.

the class LoopVersioning method createOptimizedLoop.

/**
 * Create a clone of the loop replacing definitions in the cloned
 * loop with those found in the register map and eliminate
 * unnecessary bound checks
 * @param loop - loop to clone
 * @param regMap - mapping of original definition to new
 * definition
 * @param instrToEliminate - instructions to eliminate
 * @param regToBlockMap - mapping of a register to its defining BB
 * @return a mapping from original BBs to created BBs
 */
private HashMap<BasicBlock, BasicBlock> createOptimizedLoop(AnnotatedLSTNode loop, HashMap<Register, Register> regMap, ArrayList<Instruction> instrToEliminate, HashMap<Register, BasicBlock> regToBlockMap) {
    HashMap<BasicBlock, BasicBlock> originalToCloneBBMap = new HashMap<BasicBlock, BasicBlock>();
    // After the newly created loop goto the old loop header
    originalToCloneBBMap.put(loop.successor, loop.header);
    // Create an empty block to be the loop predecessor
    BasicBlock new_pred = loop.header.createSubBlock(SYNTH_LOOP_VERSIONING_BCI, ir);
    ir.cfg.linkInCodeOrder(ir.cfg.lastInCodeOrder(), new_pred);
    originalToCloneBBMap.put(loop.predecessor, new_pred);
    // Create copy blocks
    Enumeration<BasicBlock> blocks = loop.getBasicBlocks();
    while (blocks.hasMoreElements()) {
        BasicBlock block = blocks.nextElement();
        // N.B. fall through will have been killed by unoptimized loop
        // Create copy and register mapping
        BasicBlock copy = block.copyWithoutLinks(ir);
        originalToCloneBBMap.put(block, copy);
        // Link into code order
        ir.cfg.linkInCodeOrder(ir.cfg.lastInCodeOrder(), copy);
        // Alter register definitions in copy
        IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, copy);
        loop_over_created_instructions: while (instructions.hasMoreElements()) {
            Instruction instruction = instructions.nextElement();
            if (BoundsCheck.conforms(instruction)) {
                for (Instruction anInstrToEliminate : instrToEliminate) {
                    if (instruction.similar(anInstrToEliminate)) {
                        instruction.remove();
                        continue loop_over_created_instructions;
                    }
                }
            } else if (NullCheck.conforms(instruction)) {
                for (Instruction anInstrToEliminate : instrToEliminate) {
                    if (instruction.similar(anInstrToEliminate)) {
                        instruction.remove();
                        continue loop_over_created_instructions;
                    }
                }
            }
            Enumeration<Operand> operands = instruction.getDefs();
            while (operands.hasMoreElements()) {
                Operand operand = operands.nextElement();
                if (operand instanceof RegisterOperand) {
                    Register register = operand.asRegister().getRegister();
                    if (regMap.containsKey(register)) {
                        instruction.replaceRegister(register, regMap.get(register));
                        regToBlockMap.put(regMap.get(register), copy);
                    }
                }
            }
            operands = instruction.getUses();
            while (operands.hasMoreElements()) {
                Operand operand = operands.nextElement();
                if (operand.isRegister()) {
                    Register register = operand.asRegister().getRegister();
                    if (regMap.containsKey(register)) {
                        instruction.replaceRegister(register, regMap.get(register));
                    }
                }
            }
        }
    }
    // Fix up outs
    // loop predecessor
    new_pred.redirectOuts(loop.header, originalToCloneBBMap.get(loop.header), ir);
    blocks = loop.getBasicBlocks();
    while (blocks.hasMoreElements()) {
        BasicBlock block = blocks.nextElement();
        BasicBlock copy = originalToCloneBBMap.get(block);
        Enumeration<BasicBlock> outs = block.getOutNodes();
        while (outs.hasMoreElements()) {
            BasicBlock out = outs.nextElement();
            if (originalToCloneBBMap.containsKey(out)) {
                copy.redirectOuts(out, originalToCloneBBMap.get(out), ir);
            }
        }
    }
    // Fix up phis
    blocks = loop.getBasicBlocks();
    while (blocks.hasMoreElements()) {
        BasicBlock block = blocks.nextElement();
        BasicBlock copy = originalToCloneBBMap.get(block);
        IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, copy);
        while (instructions.hasMoreElements()) {
            Instruction instruction = instructions.nextElement();
            if (Phi.conforms(instruction)) {
                for (int i = 0; i < Phi.getNumberOfValues(instruction); i++) {
                    BasicBlock phi_predecessor = Phi.getPred(instruction, i).block;
                    if (originalToCloneBBMap.containsKey(phi_predecessor)) {
                        Phi.setPred(instruction, i, new BasicBlockOperand(originalToCloneBBMap.get(phi_predecessor)));
                    } else {
                        throw new Error("There's > 1 route to this phi node from outside the loop: " + phi_predecessor);
                    }
                }
            }
        }
    }
    return originalToCloneBBMap;
}
Also used : BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) Enumeration(java.util.Enumeration) IREnumeration(org.jikesrvm.compilers.opt.ir.IREnumeration) HashMap(java.util.HashMap) 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) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) IREnumeration(org.jikesrvm.compilers.opt.ir.IREnumeration)

Example 24 with Operand

use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.

the class LoopVersioning method getRegistersDefinedInLoop.

/**
 * Get registers defined in the given loop. As we're in SSA form
 * all register definitions must be unique.
 * @param loop - the loop to examine
 * @param registers - vector to which defined registers are added
 * @param types list to which the register's types are added
 * @param definingInstructions list to which the defining instructions for
 *  the registers are added
 */
private void getRegistersDefinedInLoop(AnnotatedLSTNode loop, ArrayList<Register> registers, ArrayList<TypeReference> types, ArrayList<Instruction> definingInstructions) {
    Enumeration<BasicBlock> blocks = loop.getBasicBlocks();
    while (blocks.hasMoreElements()) {
        BasicBlock block = blocks.nextElement();
        // can value escape
        final boolean escapes = (block == loop.exit) || (ir.HIRInfo.dominatorTree.dominates(block, loop.exit));
        IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, block);
        while (instructions.hasMoreElements()) {
            Instruction instruction = instructions.nextElement();
            Enumeration<Operand> operands = instruction.getDefs();
            while (operands.hasMoreElements()) {
                Operand operand = operands.nextElement();
                if (operand.isRegister()) {
                    registers.add(operand.asRegister().getRegister());
                    types.add(operand.asRegister().getType());
                    if (escapes) {
                        definingInstructions.add(instruction);
                    } else {
                        definingInstructions.add(null);
                    }
                }
            }
        }
    }
}
Also used : IREnumeration(org.jikesrvm.compilers.opt.ir.IREnumeration) 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)

Example 25 with Operand

use of org.jikesrvm.compilers.opt.ir.operand.Operand in project JikesRVM by JikesRVM.

the class LoopVersioning method getConstantAdjustedArrayLengthDistance.

/**
 * Get the distance from an array length by addding up instructions
 * that adjust the array length result by a constant amount
 *
 * @param op operand to chase arraylength opcode to
 * @return the array length as defined above
 */
private int getConstantAdjustedArrayLengthDistance(Operand op) {
    Instruction opInstr = AnnotatedLSTNode.definingInstruction(op);
    if (opInstr.getOpcode() == ARRAYLENGTH_opcode) {
        return 0;
    } else if (opInstr.getOpcode() == INT_ADD_opcode) {
        Operand val1 = Binary.getVal1(opInstr);
        Operand val2 = Binary.getVal2(opInstr);
        if (val1.isConstant()) {
            return val1.asIntConstant().value + getConstantAdjustedArrayLengthDistance(val2);
        } else {
            if (VM.VerifyAssertions)
                VM._assert(val2.isConstant());
            return getConstantAdjustedArrayLengthDistance(val1) + val2.asIntConstant().value;
        }
    } else if (opInstr.getOpcode() == INT_SUB_opcode) {
        Operand val1 = Binary.getVal1(opInstr);
        Operand val2 = Binary.getVal2(opInstr);
        if (val1.isConstant()) {
            return val1.asIntConstant().value - getConstantAdjustedArrayLengthDistance(val2);
        } else {
            if (VM.VerifyAssertions)
                VM._assert(val2.isConstant());
            return getConstantAdjustedArrayLengthDistance(val1) - val2.asIntConstant().value;
        }
    } else {
        throw new Error("Unexpected opcode when computing distance " + op);
    }
}
Also used : 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) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Aggregations

Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)355 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)328 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)242 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)217 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)212 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)210 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)207 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)185 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)174 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)165 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)153 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)144 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)143 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)141 ObjectConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ObjectConstantOperand)128 TIBConstantOperand (org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand)121 UnreachableOperand (org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand)117 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)102 CodeConstantOperand (org.jikesrvm.compilers.opt.ir.operand.CodeConstantOperand)98 Register (org.jikesrvm.compilers.opt.ir.Register)82