Search in sources :

Example 31 with Operand

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

the class LoopVersioning method createBranchBlocks.

/*
   * TODO better JavaDoc comment.
   * <p>
   * Create the block containing explict branches to either the
   * optimized or unoptimized loops
   * @param optimalRegMap - mapping used to map eliminated bound and
   * null check guards to
   */
private boolean createBranchBlocks(AnnotatedLSTNode loop, BasicBlock block, ArrayList<Instruction> checksToEliminate, BasicBlock unoptimizedLoopEntry, BasicBlock optimizedLoopEntry, HashMap<Register, Register> optimalRegMap) {
    BasicBlock blockOnEntry = block;
    // 1) generate null check guards
    block = generateNullCheckBranchBlocks(loop, checksToEliminate, optimalRegMap, block, unoptimizedLoopEntry);
    // 2) generate bound check guards
    if (loop.isMonotonic()) {
        // create new operands for values beyond initial and terminal iterator values
        Operand terminal;
        Operand terminalLessStrideOnce;
        Operand terminalPlusStrideOnce;
        // it does create dead code though
        if (loop.terminalIteratorValue.isIntConstant()) {
            terminal = loop.terminalIteratorValue;
            int terminalAsInt = terminal.asIntConstant().value;
            int stride = loop.strideValue.asIntConstant().value;
            terminalLessStrideOnce = new IntConstantOperand(terminalAsInt - stride);
            terminalPlusStrideOnce = new IntConstantOperand(terminalAsInt + stride);
        } else {
            Instruction tempInstr;
            terminal = loop.generateLoopInvariantOperand(block, loop.terminalIteratorValue);
            terminalLessStrideOnce = ir.regpool.makeTempInt();
            terminalPlusStrideOnce = ir.regpool.makeTempInt();
            tempInstr = Binary.create(INT_SUB, terminalLessStrideOnce.asRegister(), terminal.copy(), loop.strideValue.copy());
            tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
            block.appendInstruction(tempInstr);
            DefUse.updateDUForNewInstruction(tempInstr);
            tempInstr = Binary.create(INT_ADD, terminalPlusStrideOnce.asRegister(), terminal.copy(), loop.strideValue.copy());
            tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
            block.appendInstruction(tempInstr);
            DefUse.updateDUForNewInstruction(tempInstr);
        }
        // Determine maximum and minimum index values for different loop types
        Operand phiMinIndexValue;
        Operand phiMaxIndexValue;
        if (loop.isMonotonicIncreasing()) {
            phiMinIndexValue = loop.initialIteratorValue;
            if ((loop.condition.isLESS() || loop.condition.isLOWER() || loop.condition.isNOT_EQUAL())) {
                phiMaxIndexValue = terminal;
            } else if ((loop.condition.isLESS_EQUAL() || loop.condition.isLOWER_EQUAL() || loop.condition.isEQUAL())) {
                phiMaxIndexValue = terminalPlusStrideOnce;
            } else {
                throw new Error("Unrecognised loop for fission " + loop);
            }
        } else if (loop.isMonotonicDecreasing()) {
            phiMaxIndexValue = loop.initialIteratorValue;
            if ((loop.condition.isGREATER() || loop.condition.isHIGHER() || loop.condition.isNOT_EQUAL())) {
                phiMinIndexValue = terminalPlusStrideOnce;
            } else if ((loop.condition.isGREATER_EQUAL() || loop.condition.isHIGHER_EQUAL() || loop.condition.isEQUAL())) {
                phiMinIndexValue = terminalLessStrideOnce;
            } else {
                throw new Error("Unrecognised loop for fission " + loop);
            }
        } else {
            throw new Error("Unrecognised loop for fission " + loop);
        }
        // Generate tests
        for (int i = 0; i < checksToEliminate.size(); i++) {
            Instruction instr = checksToEliminate.get(i);
            if (BoundsCheck.conforms(instr)) {
                // Have we already generated these tests?
                boolean alreadyChecked = false;
                for (int j = 0; j < i; j++) {
                    Instruction old_instr = checksToEliminate.get(j);
                    if (BoundsCheck.conforms(old_instr) && (BoundsCheck.getRef(old_instr).similar(BoundsCheck.getRef(instr))) && (BoundsCheck.getIndex(old_instr).similar(BoundsCheck.getIndex(instr)))) {
                        // yes - just create a guard move
                        alreadyChecked = true;
                        RegisterOperand guardResult = BoundsCheck.getGuardResult(instr).copyRO();
                        guardResult.setRegister(optimalRegMap.get(guardResult.getRegister()));
                        RegisterOperand guardSource = BoundsCheck.getGuardResult(old_instr).copyRO();
                        guardSource.setRegister(optimalRegMap.get(guardSource.getRegister()));
                        Instruction tempInstr = Move.create(GUARD_MOVE, guardResult, guardSource);
                        tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
                        block.appendInstruction(tempInstr);
                        break;
                    }
                }
                if (!alreadyChecked) {
                    // no - generate tests
                    Operand index = BoundsCheck.getIndex(instr);
                    int distance = loop.getFixedDistanceFromPhiIterator(index);
                    if (distance == 0) {
                        block = generateExplicitBoundCheck(instr, phiMinIndexValue, phiMaxIndexValue, optimalRegMap, block, unoptimizedLoopEntry);
                    } else {
                        Instruction tempInstr;
                        RegisterOperand minIndex = ir.regpool.makeTempInt();
                        RegisterOperand maxIndex = ir.regpool.makeTempInt();
                        tempInstr = Binary.create(INT_ADD, minIndex, phiMinIndexValue.copy(), new IntConstantOperand(distance));
                        tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
                        block.appendInstruction(tempInstr);
                        DefUse.updateDUForNewInstruction(tempInstr);
                        tempInstr = Binary.create(INT_ADD, maxIndex, phiMaxIndexValue.copy(), new IntConstantOperand(distance));
                        tempInstr.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
                        block.appendInstruction(tempInstr);
                        DefUse.updateDUForNewInstruction(tempInstr);
                        block = generateExplicitBoundCheck(instr, minIndex, maxIndex, optimalRegMap, block, unoptimizedLoopEntry);
                    }
                }
            }
        }
    }
    // Have we had to create a new basic block since entry => we
    // generated a branch to the unoptimized loop
    boolean isUnoptimizedLoopReachable = (blockOnEntry != block);
    // 3) Finish up with goto and generate true guard value
    {
        // the generated branch instruction
        Instruction branch;
        branch = Goto.create(GOTO, optimizedLoopEntry.makeJumpTarget());
        branch.setBytecodeIndex(SYNTH_LOOP_VERSIONING_BCI);
        block.appendInstruction(branch);
        block.deleteNormalOut();
        block.insertOut(optimizedLoopEntry);
    }
    return isUnoptimizedLoopReachable;
}
Also used : IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) 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 32 with Operand

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

the class PiNodes method insertPiNullCheckNodes.

/**
 * Insert Pi nodes for null check operations.
 *
 * <p>Each checkcast obj will be followed by
 * <pre> PI obj, obj </pre>
 *
 * @param ir the governing IR
 */
private void insertPiNullCheckNodes(IR ir) {
    if (!CHECK_REF_PI)
        return;
    Instruction nextInst = null;
    // for each instruction in the IR
    for (Instruction instr = ir.firstInstructionInCodeOrder(); instr != null; instr = nextInst) {
        // can't use iterator, since we modify instruction stream
        nextInst = instr.nextInstructionInCodeOrder();
        if (NullCheck.conforms(instr)) {
            // get compared variables
            Operand obj = NullCheck.getRef(instr);
            // create the instruction and insert it
            if (obj.isRegister()) {
                RegisterOperand lval = (RegisterOperand) obj.copy();
                Instruction s = GuardedUnary.create(PI, lval, obj.copy(), null);
                RegisterOperand sGuard = (RegisterOperand) NullCheck.getGuardResult(instr).copy();
                sGuard.setNullCheck();
                GuardedUnary.setGuard(s, sGuard);
                instr.insertAfter(s);
            }
        }
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 33 with Operand

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

the class PiNodes method insertPiCheckCastNodes.

/**
 * Insert Pi nodes for checkcast operations.
 *
 * <p>Each checkcast obj will be followed by
 * <pre> ref_move obj, obj </pre>
 *
 * @param ir the governing IR
 */
private void insertPiCheckCastNodes(IR ir) {
    Instruction nextInst = null;
    // for each instruction in the IR
    for (Instruction instr = ir.firstInstructionInCodeOrder(); instr != null; instr = nextInst) {
        // can't use iterator, since we modify instruction stream
        nextInst = instr.nextInstructionInCodeOrder();
        if (TypeCheck.conforms(instr)) {
            // get compared variables
            Operand obj = TypeCheck.getRef(instr);
            // create the instruction and insert it
            if (obj.isRegister()) {
                RegisterOperand lval = (RegisterOperand) obj.copy();
                lval.clearDeclaredType();
                if (lval.getType().isLoaded() && lval.getType().isClassType() && lval.getType().peekType().asClass().isFinal()) {
                    lval.setPreciseType(TypeCheck.getType(instr).getTypeRef());
                } else {
                    lval.clearPreciseType();
                    lval.setType(TypeCheck.getType(instr).getTypeRef());
                }
                Instruction s = GuardedUnary.create(PI, lval, obj.copy(), null);
                s.copyPosition(instr);
                Operand iGuard = TypeCheck.getGuard(instr);
                if (iGuard != null) {
                    Operand sGuard = iGuard.copy();
                    GuardedUnary.setGuard(s, sGuard);
                }
                instr.insertAfter(s);
            }
        }
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 34 with Operand

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

the class PiNodes method cleanUp.

/**
 * Change all PI nodes to INT_MOVE instructions
 * <p> Side effect: invalidates SSA state
 *
 * @param ir the governing IR
 */
static void cleanUp(IR ir) {
    for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements(); ) {
        Instruction s = e.nextElement();
        if (s.operator() == PI) {
            RegisterOperand result = GuardedUnary.getResult(s);
            Operator mv = IRTools.getMoveOp(result.getType());
            Operand val = GuardedUnary.getVal(s);
            Move.mutate(s, mv, result, val);
        }
    }
    // invalidate SSA state
    ir.actualSSAOptions = null;
}
Also used : Operator(org.jikesrvm.compilers.opt.ir.Operator) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 35 with Operand

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

the class PiNodes method insertPiIfNodes.

/**
 *  Insert PI nodes corresponding to compare operations.
 *  Pi-nodes are represented as dummy assignments with a single
 *  argument inserted along each outedge of the conditional.
 *
 *  @param ir the governing IR
 */
private void insertPiIfNodes(IR ir) {
    Enumeration<Instruction> e = ir.forwardInstrEnumerator();
    while (e.hasMoreElements()) {
        Instruction instr = e.nextElement();
        // TODO: what other compareops generate useful assertions?
        if (IfCmp.conforms(instr) || InlineGuard.conforms(instr)) {
            BasicBlock thisbb = instr.getBasicBlock();
            // only handle the "normal" case
            if (thisbb.getNumberOfNormalOut() != 2) {
                continue;
            }
            // insert new basic blocks on each edge out of thisbb
            Enumeration<BasicBlock> outBB = thisbb.getNormalOut();
            BasicBlock out1 = outBB.nextElement();
            BasicBlock new1 = IRTools.makeBlockOnEdge(thisbb, out1, ir);
            BasicBlock out2 = outBB.nextElement();
            BasicBlock new2 = IRTools.makeBlockOnEdge(thisbb, out2, ir);
            // blocks made on the outgoing edges.
            if (InlineGuard.conforms(instr))
                continue;
            RegisterOperand ifGuard = IfCmp.getGuardResult(instr);
            if (VM.VerifyAssertions) {
                VM._assert(ifGuard != null);
            }
            // get compared variables
            Operand a = IfCmp.getVal1(instr);
            Operand b = IfCmp.getVal2(instr);
            // determine which block is "taken" on the branch
            BasicBlock takenBlock = IfCmp.getTarget(instr).target.getBasicBlock();
            boolean new1IsTaken = false;
            if (takenBlock == new1) {
                new1IsTaken = true;
            }
            // insert the PI-node instructions for a and b
            if (a.isRegister() && !a.asRegister().getRegister().isPhysical() && (a.asRegister().getRegister().isInteger() || a.asRegister().getRegister().isAddress())) {
                // insert pi-nodes only for variables, not constants
                Instruction s = GuardedUnary.create(PI, (RegisterOperand) a.copy(), a.copy(), null);
                RegisterOperand sGuard = (RegisterOperand) ifGuard.copy();
                if (new1IsTaken) {
                    sGuard.setTaken();
                } else {
                    sGuard.setNotTaken();
                }
                GuardedUnary.setGuard(s, sGuard);
                new1.prependInstruction(s);
                s = s.copyWithoutLinks();
                sGuard = (RegisterOperand) ifGuard.copy();
                if (new1IsTaken) {
                    sGuard.setNotTaken();
                } else {
                    sGuard.setTaken();
                }
                GuardedUnary.setGuard(s, sGuard);
                new2.prependInstruction(s);
            }
            if (b.isRegister() && !b.asRegister().getRegister().isPhysical() && (b.asRegister().getRegister().isInteger() || b.asRegister().getRegister().isAddress())) {
                Instruction s = GuardedUnary.create(PI, (RegisterOperand) b.copy(), b.copy(), null);
                RegisterOperand sGuard = (RegisterOperand) ifGuard.copy();
                if (new1IsTaken) {
                    sGuard.setTaken();
                } else {
                    sGuard.setNotTaken();
                }
                GuardedUnary.setGuard(s, sGuard);
                new1.prependInstruction(s);
                s = s.copyWithoutLinks();
                sGuard = (RegisterOperand) ifGuard.copy();
                if (new1IsTaken) {
                    sGuard.setNotTaken();
                } else {
                    sGuard.setTaken();
                }
                GuardedUnary.setGuard(s, sGuard);
                new2.prependInstruction(s);
            }
        }
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) 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