Search in sources :

Example 36 with Instruction

use of org.jikesrvm.compilers.opt.ir.Instruction 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 37 with Instruction

use of org.jikesrvm.compilers.opt.ir.Instruction 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 38 with Instruction

use of org.jikesrvm.compilers.opt.ir.Instruction 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)

Example 39 with Instruction

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

the class LoopVersioning method generateNullCheckBranchBlocks.

/**
 * Generate null check branch blocks
 *
 * @param loop the current loop where checks are being eliminated
 * @param checksToEliminate all of the checks that are being eliminated in the pass
 * @param optimalRegMap a map from original register to the register used in the optimal loop
 * @param block the block to generate code into
 * @param unoptimizedLoopEntry entry to the unoptimized loop for if the check fails
 * @return the new block to generate code into
 */
private BasicBlock generateNullCheckBranchBlocks(AnnotatedLSTNode loop, ArrayList<Instruction> checksToEliminate, HashMap<Register, Register> optimalRegMap, BasicBlock block, BasicBlock unoptimizedLoopEntry) {
    // Map of already generated null check references to their
    // corresponding guard result
    HashMap<Register, Operand> refToGuardMap = new HashMap<Register, Operand>();
    // Iterate over checks
    for (Instruction instr : checksToEliminate) {
        // Is this a null check
        if (NullCheck.conforms(instr)) {
            // the generated branch instruction
            Instruction branch;
            // the reference to compare
            Operand ref = AnnotatedLSTNode.follow(NullCheck.getRef(instr));
            // the guard result to define
            RegisterOperand guardResult = NullCheck.getGuardResult(instr).copyRO();
            guardResult.setRegister(optimalRegMap.get(guardResult.getRegister()));
            // check if we've generated this test already
            if (ref.isRegister() && refToGuardMap.containsKey(ref.asRegister().getRegister())) {
                // yes - generate just a guard move
                branch = Move.create(GUARD_MOVE, guardResult, refToGuardMap.get(ref.asRegister().getRegister()).copy());
                branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
                block.appendInstruction(branch);
            } else {
                // check if we can just move a guard from the loop predecessors
                RegisterOperand guard = nullCheckPerformedInLoopPredecessors(loop.header, instr);
                if (guard != null) {
                    // yes - generate just a guard move
                    branch = Move.create(GUARD_MOVE, guardResult, guard.copyRO());
                    branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
                    block.appendInstruction(branch);
                } else {
                    // generate explicit null test
                    branch = IfCmp.create(REF_IFCMP, guardResult, ref.copy(), new NullConstantOperand(), ConditionOperand.EQUAL(), unoptimizedLoopEntry.makeJumpTarget(), BranchProfileOperand.unlikely());
                    if (ref.isRegister()) {
                        refToGuardMap.put(ref.asRegister().getRegister(), guardResult);
                    }
                    branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
                    block.appendInstruction(branch);
                    // Adjust block
                    block.insertOut(unoptimizedLoopEntry);
                    BasicBlock new_block = block.createSubBlock(SYNTH_LOOP_VERSIONING_BCI, ir);
                    BasicBlock temp = (BasicBlock) block.next;
                    ir.cfg.breakCodeOrder(block, temp);
                    ir.cfg.linkInCodeOrder(block, new_block);
                    ir.cfg.linkInCodeOrder(new_block, temp);
                    block.insertOut(new_block);
                    block = new_block;
                }
            }
        }
    }
    return block;
}
Also used : NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) 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)

Example 40 with Instruction

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

the class LoopVersioning method getListOfChecksToEliminate.

/**
 * Create a list of instructions to be eliminated
 * @param loop the loop to examine
 * @param instrToEliminate the instructions to remove
 */
private void getListOfChecksToEliminate(AnnotatedLSTNode loop, ArrayList<Instruction> instrToEliminate) {
    ArrayList<Instruction> nullChecks = new ArrayList<Instruction>();
    ArrayList<Instruction> oddBoundChecks = new ArrayList<Instruction>();
    Enumeration<BasicBlock> blocks = loop.getBasicBlocks();
    while (blocks.hasMoreElements()) {
        BasicBlock block = blocks.nextElement();
        IREnumeration.AllInstructionsEnum instructions = new IREnumeration.AllInstructionsEnum(ir, block);
        while (instructions.hasMoreElements()) {
            Instruction instruction = instructions.nextElement();
            if (NullCheck.conforms(instruction)) {
                if (loop.isInvariant(NullCheck.getRef(instruction))) {
                    instrToEliminate.add(instruction);
                    nullChecks.add(instruction);
                }
            } else if (loop.isMonotonic() && BoundsCheck.conforms(instruction)) {
                if (loop.isInvariant(BoundsCheck.getRef(instruction))) {
                    if (loop.isRelatedToIterator(BoundsCheck.getIndex(instruction))) {
                        if (loop.isInvariant(BoundsCheck.getGuard(instruction))) {
                            instrToEliminate.add(instruction);
                        } else {
                            // Null check isn't invariant but reference was, check
                            // null check will be eliminated at end of loop
                            oddBoundChecks.add(instruction);
                        }
                    }
                }
            }
        }
    }
    // it will be in the optimized loop as we'll have eliminated it
    for (Instruction oddBoundCheck : oddBoundChecks) {
        Operand guard = BoundsCheck.getGuard(oddBoundCheck);
        for (Instruction nullCheck : nullChecks) {
            if (guard.similar(NullCheck.getGuardResult(nullCheck))) {
                instrToEliminate.add(oddBoundCheck);
                break;
            }
        }
    }
}
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) ArrayList(java.util.ArrayList) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Aggregations

Instruction (org.jikesrvm.compilers.opt.ir.Instruction)356 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)204 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)144 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)117 Register (org.jikesrvm.compilers.opt.ir.Register)106 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)72 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)61 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)61 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)54 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)53 Test (org.junit.Test)49 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)46 TypeReference (org.jikesrvm.classloader.TypeReference)38 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)38 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)35 BasicBlockOperand (org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand)33 HeapOperand (org.jikesrvm.compilers.opt.ir.operand.HeapOperand)33 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)31 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)28 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)27