Search in sources :

Example 1 with ConditionOperand

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

the class LoopUnrolling method unrollLeaf.

boolean unrollLeaf(LSTNode t, IR ir) {
    int instructionsInLoop = 0;
    BasicBlock exitBlock = null, backEdgeBlock = null, succBlock = null, predBlock = null;
    BitVector nloop = t.getLoop();
    BasicBlock header = t.header;
    Instruction tmp;
    if (ir.hasReachableExceptionHandlers()) {
        report("0 IR may have exception handlers");
        return false;
    }
    // determine loop structure by looking at its blocks
    Enumeration<BasicBlock> loopBlocks = ir.getBasicBlocks(nloop);
    int blocks = 0;
    while (loopBlocks.hasMoreElements()) {
        BasicBlock b = loopBlocks.nextElement();
        blocks++;
        // check for size
        instructionsInLoop += b.getNumberOfRealInstructions();
        if (instructionsInLoop > MaxInstructions) {
            report("1 is too big");
            return false;
        }
        // look at the in edges. We want the header to be the only
        // block with out of loop incoming edges.
        Enumeration<BasicBlock> e = b.getIn();
        if (b != header) {
            while (e.hasMoreElements()) {
                BasicBlock o = e.nextElement();
                if (!CFGTransformations.inLoop(o, nloop)) {
                    report("2 interior pointers.");
                    return true;
                }
            }
        } else {
            // check the headers predecessors: there should be
            // one out of loop input and one backedge.
            // We can extend this for loops with several backedges,
            // if they all have the same conditions.
            int inEdges = 0;
            while (e.hasMoreElements()) {
                inEdges++;
                BasicBlock o = e.nextElement();
                if (!CFGTransformations.inLoop(o, nloop)) {
                    if (predBlock == null) {
                        predBlock = o;
                    } else {
                        report("3 multi entry header.");
                        return true;
                    }
                } else {
                    if (backEdgeBlock == null) {
                        backEdgeBlock = o;
                    } else {
                        report("4 multiple back edges.");
                        return true;
                    }
                }
            }
        }
        // look at the out edges to find loop exits
        e = b.getOut();
        while (e.hasMoreElements()) {
            BasicBlock out = e.nextElement();
            if (!CFGTransformations.inLoop(out, nloop)) {
                if (exitBlock == null) {
                    exitBlock = b;
                } else {
                    report("5 multiple exit blocks.");
                    return true;
                }
            }
        }
    }
    // exitBlock must equal backEdgeBlock
    if (exitBlock == null) {
        report("6 no exit block found...infinite loop?");
        return true;
    }
    if (exitBlock != backEdgeBlock) {
        report("7 exit block is not immediate predecessor of loop head");
        return true;
    }
    // exitBlock must exit (skip over pads in critical edges)
    while (exitBlock.getNumberOfOut() == 1 && exitBlock.getNumberOfIn() == 1) {
        exitBlock = exitBlock.getIn().nextElement();
    }
    if (exitBlock == header && blocks > 1) {
        report("6 while loop? (" + blocks + ")");
        return true;
    }
    // So far, so good. Examine the exit test.
    Instruction origBranch = exitBlock.firstBranchInstruction();
    if (origBranch != exitBlock.lastRealInstruction()) {
        Instruction aGoto = origBranch.nextInstructionInCodeOrder();
        if (aGoto.getOpcode() != GOTO_opcode) {
            report("7 too complex exit");
            return true;
        }
        succBlock = Label.getBlock(Goto.getTarget(aGoto).target).block;
        if (VM.VerifyAssertions) {
            VM._assert(aGoto == exitBlock.lastRealInstruction());
        }
    } else {
        succBlock = exitBlock.getFallThroughBlock();
    }
    if (origBranch.getOpcode() != INT_IFCMP_opcode) {
        report("8 branch isn't int_ifcmp: " + origBranch.operator() + ".");
        return true;
    }
    // examine operands:
    Operand op1 = follow(IfCmp.getVal1(origBranch));
    Operand op2 = follow(IfCmp.getVal2(origBranch));
    ConditionOperand cond = (ConditionOperand) IfCmp.getCond(origBranch).copy();
    RegisterOperand ifcmpGuard = IfCmp.getGuardResult(origBranch);
    float backBranchProbability = IfCmp.getBranchProfile(origBranch).takenProbability;
    if (!loopInvariant(op2, nloop, 4)) {
        if (loopInvariant(op1, nloop, 4)) {
            Operand op = op1;
            op1 = op2;
            op2 = op;
            cond.flipOperands();
        } else {
            if (DEBUG) {
                printDefs(op1, nloop, 4);
                printDefs(op2, nloop, 4);
                VM.sysWriteln(origBranch.toString());
            }
            report("8a op1 and op2 may not be loop invariant");
            return true;
        }
    }
    BasicBlock target = Label.getBlock(IfCmp.getTarget(origBranch).target).block;
    if (!(op1 instanceof RegisterOperand)) {
        report("9 op1 of ifcmp isn't a register");
        return true;
    }
    RegisterOperand rop1 = (RegisterOperand) op1;
    Register reg = rop1.getRegister();
    if (reg.isPhysical()) {
        report("10 loops over physical register");
        return false;
    }
    if (succBlock == header && !CFGTransformations.inLoop(target, nloop)) {
        succBlock = target;
        target = header;
        cond.flipCode();
    }
    if (target != header) {
        report("11 ifcmp doesn't jump to header");
        return true;
    }
    Instruction iterator = null;
    Enumeration<Operand> defs = new RealDefs(rop1);
    while (defs.hasMoreElements()) {
        Operand def = defs.nextElement();
        Instruction inst = def.instruction;
        BasicBlock block = inst.getBasicBlock();
        // VM.sysWriteln(block + ": " + inst);
        if (CFGTransformations.inLoop(block, nloop)) {
            if (iterator == null) {
                iterator = inst;
            } else {
                report("12 iterator not unique.");
                return true;
            }
        }
    }
    if (iterator == null) {
        report("15 iterator not found.");
        return true;
    }
    if (iterator.getOpcode() != INT_ADD_opcode) {
        // dumpIR (ir, "malformed");
        report("16 iterator is no addition: " + iterator.operator());
        return true;
    }
    if (!rop1.similar(follow(Binary.getVal1(iterator)))) {
        // dumpIR (ir, "malformed");
        report("17 malformed iterator.\n" + iterator);
        return true;
    }
    Operand strideOp = follow(Binary.getVal2(iterator));
    if (!(strideOp instanceof IntConstantOperand)) {
        report("18 stride not constant");
        return true;
    }
    int stride = ((IntConstantOperand) strideOp).value;
    if (stride != 1 && stride != -1) {
        report("18b stride != +/-1 (" + stride + ")");
        return true;
    }
    if ((stride == 1 && ((cond.value != ConditionOperand.LESS) && cond.value != ConditionOperand.LESS_EQUAL && cond.value != ConditionOperand.NOT_EQUAL)) || (stride == -1 && ((cond.value != ConditionOperand.GREATER) && cond.value != ConditionOperand.GREATER_EQUAL && cond.value != ConditionOperand.NOT_EQUAL))) {
        report("19 unexpected condition: " + cond + "\n" + iterator + "\n" + origBranch);
        return true;
    }
    RegisterOperand outerGuard;
    BasicBlock outer = predBlock;
    while (outer.getNumberOfOut() == 1 && outer.getNumberOfIn() == 1) {
        outer = outer.getIn().nextElement();
    }
    if (outer.getNumberOfIn() > 0 && outer.getNumberOfOut() < 2) {
        report("23 no suitable outer guard found.");
        return true;
    }
    tmp = outer.firstBranchInstruction();
    if (tmp != null && GuardResultCarrier.conforms(tmp)) {
        outerGuard = GuardResultCarrier.getGuardResult(tmp);
    } else {
        outerGuard = ir.regpool.makeTempValidation();
    }
    // //////////
    // transfom
    // transform this:
    // 
    // Orig:
    // B
    // if i CC b goto Orig
    // else goto exit
    // 
    // exit:
    // 
    // into this:
    // 
    // 
    // stride == 1:           common:                      stride == -1:
    // --------------------------------------------------------------------------
    // guard0:
    // limit = b;
    // if a > b goto Orig                                  if b > a goto Orig
    // else guard1
    // 
    // 
    // guard 1:
    // remainder = b - a;                                  remainder = a - b;
    // if cond == '<='                                    if cond == '>='
    // remainder++;                                         remainder++;
    // remainder = remainder & 3
    // limit = a + remainder                               limit = a - remainder
    // if cond == '<='                                    if cond == '>='
    // limit--;                                            limit++;
    // if remainder == 0 goto mllp
    // goto Orig
    // 
    // Orig:
    // LOOP;
    // if i CC limit goto Orig
    // else guard2
    // 
    // guard2: if i CC b goto mllp
    // else exit
    // 
    // mllp: // landing pad
    // goto ml
    // 
    // ml:
    // LOOP;LOOP;LOOP;LOOP;
    // if i CC b goto ml
    // else exit
    // 
    // exit:
    // --------------------------------------------------------------------------
    report("...transforming.");
    if (DEBUG && ir.options.hasMETHOD_TO_PRINT() && ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString())) {
        dumpIR(ir, "before unroll");
    }
    CFGTransformations.killFallThroughs(ir, nloop);
    BasicBlock[] handles = makeSomeCopies(unrollFactor, ir, nloop, blocks, header, exitBlock, exitBlock);
    BasicBlock mainHeader = handles[0];
    BasicBlock mainExit = handles[1];
    // test block for well formed bounds
    BasicBlock guardBlock0 = header.createSubBlock(header.firstInstruction().getBytecodeIndex(), ir);
    predBlock.redirectOuts(header, guardBlock0, ir);
    // test block for iteration alignemnt
    BasicBlock guardBlock1 = header.createSubBlock(header.firstInstruction().getBytecodeIndex(), ir);
    // landing pad for orig loop
    BasicBlock olp = header.createSubBlock(header.firstInstruction().getBytecodeIndex(), ir);
    olp.setLandingPad();
    BasicBlock predSucc = predBlock.nextBasicBlockInCodeOrder();
    if (predSucc != null) {
        ir.cfg.breakCodeOrder(predBlock, predSucc);
        ir.cfg.linkInCodeOrder(olp, predSucc);
    }
    ir.cfg.linkInCodeOrder(predBlock, guardBlock0);
    ir.cfg.linkInCodeOrder(guardBlock0, guardBlock1);
    ir.cfg.linkInCodeOrder(guardBlock1, olp);
    // guard block for main loop
    BasicBlock guardBlock2 = header.createSubBlock(header.firstInstruction().getBytecodeIndex(), ir);
    // landing pad for main loop
    BasicBlock landingPad = header.createSubBlock(header.firstInstruction().getBytecodeIndex(), ir);
    landingPad.setLandingPad();
    BasicBlock mainLoop = exitBlock.nextBasicBlockInCodeOrder();
    ir.cfg.breakCodeOrder(exitBlock, mainLoop);
    ir.cfg.linkInCodeOrder(exitBlock, guardBlock2);
    ir.cfg.linkInCodeOrder(guardBlock2, landingPad);
    ir.cfg.linkInCodeOrder(landingPad, mainLoop);
    RegisterOperand remainder = ir.regpool.makeTemp(rop1.getType());
    RegisterOperand limit = ir.regpool.makeTemp(rop1.getType());
    // test whether a <= b for stride == 1 and a >= b for stride == -1
    tmp = guardBlock0.lastInstruction();
    tmp.insertBefore(Move.create(INT_MOVE, limit, op2.copy()));
    ConditionOperand g0cond = ConditionOperand.GREATER_EQUAL();
    if (stride == -1)
        g0cond = ConditionOperand.LESS_EQUAL();
    tmp.insertBefore(IfCmp.create(INT_IFCMP, outerGuard.copyD2D(), rop1.copyD2U(), op2.copy(), g0cond, olp.makeJumpTarget(), BranchProfileOperand.unlikely()));
    tmp.insertBefore(Goto.create(GOTO, guardBlock1.makeJumpTarget()));
    // align the loop iterations
    tmp = guardBlock1.lastInstruction();
    if (stride == 1) {
        tmp.insertBefore(Binary.create(INT_SUB, remainder, op2.copy(), rop1.copyD2U()));
    } else {
        tmp.insertBefore(Binary.create(INT_SUB, remainder, rop1.copyD2U(), op2.copy()));
    }
    if (cond.isGREATER_EQUAL() || cond.isLESS_EQUAL()) {
        tmp.insertBefore(Binary.create(INT_ADD, remainder.copyD2D(), remainder.copyD2U(), new IntConstantOperand(1)));
    }
    tmp.insertBefore(Binary.create(INT_ADD, remainder.copyD2D(), remainder.copyD2U(), new IntConstantOperand(-1)));
    tmp.insertBefore(Binary.create(INT_AND, remainder.copyD2D(), remainder.copyD2U(), new IntConstantOperand(unrollFactor - 1)));
    tmp.insertBefore(Binary.create(INT_ADD, remainder.copyD2D(), remainder.copyD2U(), new IntConstantOperand(1)));
    if (stride == 1) {
        tmp.insertBefore(Binary.create(INT_ADD, limit.copyD2U(), op1.copy(), remainder.copyD2U()));
    } else {
        tmp.insertBefore(Binary.create(INT_SUB, limit.copyD2U(), op1.copy(), remainder.copyD2U()));
    }
    if (cond.isLESS_EQUAL()) {
        tmp.insertBefore(Binary.create(INT_ADD, limit.copyD2D(), limit.copyD2U(), new IntConstantOperand(-1)));
    }
    if (cond.isGREATER_EQUAL()) {
        tmp.insertBefore(Binary.create(INT_ADD, limit.copyD2D(), limit.copyD2U(), new IntConstantOperand(1)));
    }
    tmp.insertBefore(Goto.create(GOTO, olp.makeJumpTarget()));
    // build landing pad for original loop
    tmp = olp.lastInstruction();
    tmp.insertBefore(Goto.create(GOTO, header.makeJumpTarget()));
    // change the back branch in the original loop
    deleteBranches(exitBlock);
    tmp = exitBlock.lastInstruction();
    tmp.insertBefore(IfCmp.create(INT_IFCMP, outerGuard.copyD2D(), rop1.copyU2U(), limit.copyD2U(), (ConditionOperand) cond.copy(), header.makeJumpTarget(), new BranchProfileOperand(1.0f - 1.0f / (unrollFactor / 2))));
    tmp.insertBefore(Goto.create(GOTO, guardBlock2.makeJumpTarget()));
    // only enter main loop if iterations left
    tmp = guardBlock2.lastInstruction();
    tmp.insertBefore(IfCmp.create(INT_IFCMP, outerGuard.copyD2D(), rop1.copyU2U(), op2.copy(), (ConditionOperand) cond.copy(), landingPad.makeJumpTarget(), new BranchProfileOperand(backBranchProbability)));
    tmp.insertBefore(Goto.create(GOTO, succBlock.makeJumpTarget()));
    // landing pad jumps to mainHeader
    tmp = landingPad.lastInstruction();
    tmp.insertBefore(Goto.create(GOTO, mainHeader.makeJumpTarget()));
    // repair back edge in mainExit
    if (VM.VerifyAssertions)
        VM._assert(mainExit != null);
    tmp = mainExit.lastInstruction();
    if (VM.VerifyAssertions) {
        VM._assert((mainExit.lastRealInstruction() == null) || !mainExit.lastRealInstruction().isBranch());
    }
    tmp.insertBefore(IfCmp.create(INT_IFCMP, ifcmpGuard.copyU2U(), rop1.copyU2U(), op2.copy(), (ConditionOperand) cond.copy(), mainHeader.makeJumpTarget(), new BranchProfileOperand(1.0f - (1.0f - backBranchProbability) * unrollFactor)));
    tmp.insertBefore(Goto.create(GOTO, succBlock.makeJumpTarget()));
    // recompute normal outs
    guardBlock0.recomputeNormalOut(ir);
    guardBlock1.recomputeNormalOut(ir);
    olp.recomputeNormalOut(ir);
    guardBlock2.recomputeNormalOut(ir);
    exitBlock.recomputeNormalOut(ir);
    landingPad.recomputeNormalOut(ir);
    mainExit.recomputeNormalOut(ir);
    if (DEBUG && ir.options.hasMETHOD_TO_PRINT() && ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString())) {
        dumpIR(ir, "after unroll");
    }
    return false;
}
Also used : BitVector(org.jikesrvm.util.BitVector) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)

Example 2 with ConditionOperand

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

the class BURS_Helpers method TRAP_IF_IMM.

/**
 * Take the generic LIR trap_if and coerce into the limited
 * vocabulary understood by the C trap handler on PPC.  See
 * TrapConstants.java.  Also see ConvertToLowLevelIR.java
 * which generates most of these TRAP_IFs.
 *
 * @param s the instruction to expand
 * @param longConstant is the argument a long constant?
 */
protected final void TRAP_IF_IMM(Instruction s, boolean longConstant) {
    RegisterOperand gRes = TrapIf.getClearGuardResult(s);
    RegisterOperand v1 = (RegisterOperand) TrapIf.getClearVal1(s);
    ConditionOperand cond = TrapIf.getClearCond(s);
    TrapCodeOperand tc = TrapIf.getClearTCode(s);
    switch(tc.getTrapCode()) {
        case RuntimeEntrypoints.TRAP_ARRAY_BOUNDS:
            {
                IntConstantOperand v2 = (IntConstantOperand) TrapIf.getClearVal2(s);
                if (cond.isLOWER_EQUAL()) {
                    EMIT(MIR_Trap.mutate(s, PPC_TWI, gRes, new PowerPCTrapOperand(cond), v1, v2, tc));
                } else if (cond.isHIGHER_EQUAL()) {
                    // have flip the operands and use non-immediate so trap handler can recognize.
                    RegisterOperand tmp = regpool.makeTempInt();
                    IntConstant(tmp.getRegister(), v2.value);
                    EMIT(MIR_Trap.mutate(s, PPC_TW, gRes, new PowerPCTrapOperand(cond.flipOperands()), tmp, v1, tc));
                } else {
                    throw new OptimizingCompilerException("Unexpected case of trap_if" + s);
                }
            }
            break;
        case RuntimeEntrypoints.TRAP_DIVIDE_BY_ZERO:
            {
                ConstantOperand v2 = (ConstantOperand) TrapIf.getClearVal2(s);
                if (VM.VerifyAssertions) {
                    if (longConstant) {
                        long val = ((LongConstantOperand) v2).value;
                        boolean caseMatchesExpected = val == 0L && cond.isEQUAL();
                        if (!caseMatchesExpected) {
                            String msg = "Unexpected case of trap_if" + s;
                            VM._assert(VM.NOT_REACHED, msg);
                        }
                    } else {
                        int val = ((IntConstantOperand) v2).value;
                        boolean caseMatchesExpected = val == 0L && cond.isEQUAL();
                        if (!caseMatchesExpected) {
                            String msg = "Unexpected case of trap_if" + s;
                            VM._assert(VM.NOT_REACHED, msg);
                        }
                    }
                }
                if (longConstant) {
                    if (VM.BuildFor32Addr) {
                        // A slightly ugly matter, but we need to deal with combining
                        // the two pieces of a long register from a LONG_ZERO_CHECK.
                        // A little awkward, but probably the easiest workaround...
                        RegisterOperand rr = regpool.makeTempInt();
                        EMIT(MIR_Binary.create(PPC_OR, rr, v1, I(regpool.getSecondReg(v1.getRegister()))));
                        v1 = rr.copyD2U();
                        v2 = IC(0);
                        EMIT(MIR_Trap.mutate(s, PPC_TWI, gRes, new PowerPCTrapOperand(cond), v1, v2, tc));
                    } else {
                        EMIT(MIR_Trap.mutate(s, PPC64_TDI, gRes, new PowerPCTrapOperand(cond), v1, v2, tc));
                    }
                } else {
                    EMIT(MIR_Trap.mutate(s, PPC_TWI, gRes, new PowerPCTrapOperand(cond), v1, v2, tc));
                }
            }
            break;
        default:
            throw new OptimizingCompilerException("Unexpected case of trap_if" + s);
    }
}
Also used : LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) PowerPCTrapOperand(org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCTrapOperand) PowerPCConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCConditionOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException)

Example 3 with ConditionOperand

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

the class BURS_Helpers method TRAP_IF.

// Take the generic LIR trap_if and coerce into the limited vocabulary
// understand by C trap handler on PPC.  See TrapConstants.java.
// Also see ConvertToLowLevelIR.java which generates most of these TRAP_IFs.
protected final void TRAP_IF(Instruction s) {
    RegisterOperand gRes = TrapIf.getClearGuardResult(s);
    RegisterOperand v1 = (RegisterOperand) TrapIf.getClearVal1(s);
    RegisterOperand v2 = (RegisterOperand) TrapIf.getClearVal2(s);
    ConditionOperand cond = TrapIf.getClearCond(s);
    TrapCodeOperand tc = TrapIf.getClearTCode(s);
    switch(tc.getTrapCode()) {
        case RuntimeEntrypoints.TRAP_ARRAY_BOUNDS:
            {
                if (cond.isLOWER_EQUAL()) {
                    EMIT(MIR_Trap.mutate(s, PPC_TW, gRes, new PowerPCTrapOperand(cond), v1, v2, tc));
                } else {
                    throw new OptimizingCompilerException("Unexpected case of trap_if" + s);
                }
            }
            break;
        default:
            throw new OptimizingCompilerException("Unexpected case of trap_if" + s);
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) PowerPCTrapOperand(org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCTrapOperand) PowerPCConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCConditionOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException)

Example 4 with ConditionOperand

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

the class ComplexLIR2MIRExpansion method boolean_cmp.

private static void boolean_cmp(Instruction s, IR ir, boolean cmp32Bit) {
    // undo the optimization because it cannot efficiently be generated
    Register res = BooleanCmp.getClearResult(s).getRegister();
    RegisterOperand one = (RegisterOperand) BooleanCmp.getClearVal1(s);
    Operand two = BooleanCmp.getClearVal2(s);
    ConditionOperand cond = BooleanCmp.getClearCond(s);
    res.setSpansBasicBlock();
    BasicBlock BB1 = s.getBasicBlock();
    BasicBlock BB4 = BB1.splitNodeAt(s, ir);
    s = s.remove();
    BasicBlock BB2 = BB1.createSubBlock(0, ir);
    BasicBlock BB3 = BB1.createSubBlock(0, ir);
    RegisterOperand t = ir.regpool.makeTempInt();
    t.getRegister().setCondition();
    Operator op;
    if (VM.BuildFor64Addr && !cmp32Bit) {
        if (two instanceof IntConstantOperand) {
            op = cond.isUNSIGNED() ? PPC64_CMPLI : PPC64_CMPI;
        } else {
            op = cond.isUNSIGNED() ? PPC64_CMPL : PPC64_CMP;
        }
    } else if (two instanceof IntConstantOperand) {
        op = cond.isUNSIGNED() ? PPC_CMPLI : PPC_CMPI;
    } else {
        op = cond.isUNSIGNED() ? PPC_CMPL : PPC_CMP;
    }
    BB1.appendInstruction(MIR_Binary.create(op, t, one, two));
    BB1.appendInstruction(MIR_CondBranch.create(PPC_BCOND, t.copyD2U(), PowerPCConditionOperand.get(cond), BB3.makeJumpTarget(), new BranchProfileOperand()));
    BB2.appendInstruction(MIR_Unary.create(PPC_LDI, I(res), IC(0)));
    BB2.appendInstruction(MIR_Branch.create(PPC_B, BB4.makeJumpTarget()));
    BB3.appendInstruction(MIR_Unary.create(PPC_LDI, I(res), IC(1)));
    // fix CFG
    BB1.insertOut(BB2);
    BB1.insertOut(BB3);
    BB2.insertOut(BB4);
    BB3.insertOut(BB4);
    ir.cfg.linkInCodeOrder(BB1, BB2);
    ir.cfg.linkInCodeOrder(BB2, BB3);
    ir.cfg.linkInCodeOrder(BB3, BB4);
}
Also used : Operator(org.jikesrvm.compilers.opt.ir.Operator) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) Register(org.jikesrvm.compilers.opt.ir.Register) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) PowerPCConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCConditionOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) PowerPCConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCConditionOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)

Example 5 with ConditionOperand

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

the class DynamicTypeCheckExpansion method instanceOf.

/**
 * Expand an instanceof instruction into the LIR sequence that implements
 * the dynamic type check.  Ref may contain a null ptr at runtime.
 *
 * @param s an INSTANCEOF or INSTANCEOF_UNRESOLVED instruction to expand
 * @param ir the enclosing IR
 * @return the last Instruction in the generated LIR sequence.
 */
static Instruction instanceOf(Instruction s, IR ir) {
    RegisterOperand result = InstanceOf.getClearResult(s);
    TypeReference LHStype = InstanceOf.getType(s).getTypeRef();
    Operand ref = InstanceOf.getClearRef(s);
    Instruction next = s.nextInstructionInCodeOrder();
    if (next.operator() == INT_IFCMP && IfCmp.getVal1(next) instanceof RegisterOperand && result.similar(IfCmp.getVal1(next))) {
        // The result of instanceof is being consumed by a conditional branch.
        // Optimize this case by generating a branching type check
        // instead of producing a value.
        // TODO: This is really not safe: suppose the if is NOT the
        // only use of the result of the instanceof.
        // The way to fix this is to add ifInstanceOf and ifNotInstanceOf
        // operators to the IR and have Simple transform
        // instanceof, intIfCmp based on the U/D chains.
        // See defect 2114.
        Operand val2 = IfCmp.getVal2(next);
        if (VM.VerifyAssertions)
            VM._assert(val2.isIntConstant());
        int ival2 = ((IntConstantOperand) val2).value;
        ConditionOperand cond = IfCmp.getCond(next);
        boolean branchCondition = (((ival2 == 0) && (cond.isNOT_EQUAL() || cond.isLESS_EQUAL())) || ((ival2 == 1) && (cond.isEQUAL() || cond.isGREATER_EQUAL())));
        BasicBlock branchBB = next.getBranchTarget();
        RegisterOperand oldGuard = IfCmp.getGuardResult(next);
        next.remove();
        BasicBlock fallThroughBB = fallThroughBB(s, ir);
        BasicBlock falseBranch = branchCondition ? fallThroughBB : branchBB;
        BasicBlock trueBranch = branchCondition ? branchBB : fallThroughBB;
        BranchProfileOperand bp = IfCmp.getClearBranchProfile(next);
        if (branchCondition)
            bp = bp.flip();
        Instruction nullComp = IfCmp.create(REF_IFCMP, oldGuard.copyRO(), ref.copy(), new NullConstantOperand(), ConditionOperand.EQUAL(), falseBranch.makeJumpTarget(), BranchProfileOperand.unlikely());
        s.insertBefore(nullComp);
        BasicBlock myBlock = s.getBasicBlock();
        BasicBlock instanceOfBlock = myBlock.splitNodeAt(nullComp, ir);
        myBlock.insertOut(instanceOfBlock);
        myBlock.insertOut(falseBranch);
        ir.cfg.linkInCodeOrder(myBlock, instanceOfBlock);
        Operand RHStib = getTIB(s, ir, ref, oldGuard.copyRO());
        return generateBranchingTypeCheck(s, ir, ref.copy(), LHStype, RHStib, trueBranch, falseBranch, oldGuard.copy().asRegister(), bp);
    } else {
        // Not a branching pattern
        RegisterOperand guard = ir.regpool.makeTempValidation();
        BasicBlock instanceOfBlock = s.getBasicBlock().segregateInstruction(s, ir);
        BasicBlock prevBB = instanceOfBlock.prevBasicBlockInCodeOrder();
        BasicBlock nextBB = instanceOfBlock.nextBasicBlockInCodeOrder();
        BasicBlock nullCaseBB = instanceOfBlock.createSubBlock(s.getBytecodeIndex(), ir, .01f);
        prevBB.appendInstruction(IfCmp.create(REF_IFCMP, guard, ref.copy(), new NullConstantOperand(), ConditionOperand.EQUAL(), nullCaseBB.makeJumpTarget(), BranchProfileOperand.unlikely()));
        nullCaseBB.appendInstruction(Move.create(INT_MOVE, result.copyD2D(), IC(0)));
        nullCaseBB.appendInstruction(Goto.create(GOTO, nextBB.makeJumpTarget()));
        // Stitch together the CFG; add nullCaseBB to the end of code array.
        prevBB.insertOut(nullCaseBB);
        nullCaseBB.insertOut(nextBB);
        ir.cfg.addLastInCodeOrder(nullCaseBB);
        Operand RHStib = getTIB(s, ir, ref, guard.copyD2U());
        return generateValueProducingTypeCheck(s, ir, ref.copy(), LHStype, RHStib, result);
    }
}
Also used : NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) 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) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TypeReference(org.jikesrvm.classloader.TypeReference) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Aggregations

ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)29 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)28 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)25 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)21 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)21 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)16 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)14 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)14 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)14 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)13 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)13 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)12 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)10 DoubleConstantOperand (org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand)10 FloatConstantOperand (org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand)10 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)9 IA32ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand)9 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)8 Register (org.jikesrvm.compilers.opt.ir.Register)7 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)7