Search in sources :

Example 26 with ConditionOperand

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

the class BranchOptimizations method generateBooleanCompare.

/**
 * Attempt to generate a boolean compare opcode from a conditional branch.
 *
 * <pre>
 * 1)   IF .. GOTO A          replaced by  BOOLEAN_CMP x=..
 *      x = 0
 *      GOTO B
 *   A: x = 1
 *   B: ...
 * </pre>
 *
 * <p> Precondition: <code>IfCmp.conforms(<i>cb</i>)</code>
 *
 * @param ir governing IR
 * @param bb basic block of cb
 * @param cb conditional branch instruction
 * @param tb target block the branch instruction
 * @return {@code true} if and only if the transformation succeeds
 */
private boolean generateBooleanCompare(IR ir, BasicBlock bb, Instruction cb, BasicBlock tb) {
    if ((cb.operator() != INT_IFCMP) && (cb.operator() != REF_IFCMP)) {
        return false;
    }
    // make sure this is the last branch in the block
    if (cb.nextInstructionInCodeOrder().operator() != BBEND) {
        return false;
    }
    Operand val1 = IfCmp.getVal1(cb);
    Operand val2 = IfCmp.getVal2(cb);
    ConditionOperand condition = IfCmp.getCond(cb);
    // "not taken" path
    BasicBlock fb = cb.getBasicBlock().getNotTakenNextBlock();
    // make sure it's a diamond
    if (tb.getNumberOfNormalOut() != 1) {
        return false;
    }
    if (fb.getNumberOfNormalOut() != 1) {
        return false;
    }
    // join block
    BasicBlock jb = fb.getNormalOut().nextElement();
    // make sure it's a diamond
    if (!tb.pointsOut(jb)) {
        return false;
    }
    Instruction ti = tb.firstRealInstruction();
    Instruction fi = fb.firstRealInstruction();
    // or both returns
    if (ti == null || fi == null) {
        return false;
    }
    if (ti.operator() != fi.operator()) {
        return false;
    }
    if (ti.operator() != RETURN && ti.operator() != INT_MOVE) {
        return false;
    }
    // 
    if (ti.operator() == RETURN) {
        // make sure each of the target blocks contains only one instruction
        if (ti != tb.lastRealInstruction()) {
            return false;
        }
        if (fi != fb.lastRealInstruction()) {
            return false;
        }
        Operand tr = Return.getVal(ti);
        Operand fr = Return.getVal(fi);
        // make sure we're returning constants
        if (!(tr instanceof IntConstantOperand) || !(fr instanceof IntConstantOperand)) {
            return false;
        }
        int tv = ((IntConstantOperand) tr).value;
        int fv = ((IntConstantOperand) fr).value;
        if (!((tv == 1 && fv == 0) || (tv == 1 && fv == 0))) {
            return false;
        }
        RegisterOperand t = ir.regpool.makeTemp(TypeReference.Boolean);
        // Cases 1) and 2)
        if (tv == 0) {
            condition = condition.flipCode();
        }
        booleanCompareHelper(cb, t, val1.copy(), val2.copy(), condition);
        cb.insertAfter(Return.create(RETURN, t.copyD2U()));
    } else {
        // make sure each of the target blocks only does the move
        if (ti != tb.lastRealInstruction() && ti.nextInstructionInCodeOrder().operator() != GOTO) {
            return false;
        }
        if (fi != fb.lastRealInstruction() && fi.nextInstructionInCodeOrder().operator() != GOTO) {
            return false;
        }
        RegisterOperand t = Move.getResult(ti);
        // make sure both moves are to the same register
        if (t.getRegister() != Move.getResult(fi).getRegister()) {
            return false;
        }
        Operand tr = Move.getVal(ti);
        Operand fr = Move.getVal(fi);
        // make sure we're assigning constants
        if (!(tr instanceof IntConstantOperand) || !(fr instanceof IntConstantOperand)) {
            return false;
        }
        int tv = ((IntConstantOperand) tr).value;
        int fv = ((IntConstantOperand) fr).value;
        if (!((tv == 1 && fv == 0) || (tv == 0 && fv == 1))) {
            return false;
        }
        // Cases 3) and 4)
        if (tv == 0) {
            condition = condition.flipCode();
        }
        booleanCompareHelper(cb, t.copyRO(), val1.copy(), val2.copy(), condition);
        Instruction next = cb.nextInstructionInCodeOrder();
        if (next.operator() == GOTO) {
            Goto.setTarget(next, jb.makeJumpTarget());
        } else {
            cb.insertAfter(jb.makeGOTO());
        }
    }
    // fixup CFG
    bb.deleteOut(tb);
    bb.deleteOut(fb);
    // Note: if we processed returns,
    bb.insertOut(jb);
    // jb is the exit node.
    return true;
}
Also used : IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 27 with ConditionOperand

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

the class BranchOptimizations method doCondMove.

/**
 * Perform the transformation to replace conditional branch with a
 * sequence using conditional moves.
 *
 * @param ir governing IR
 * @param diamond the IR diamond structure to replace
 * @param cb conditional branch instruction at the head of the diamond
 */
private void doCondMove(IR ir, Diamond diamond, Instruction cb) {
    BasicBlock taken = diamond.getTaken();
    BasicBlock notTaken = diamond.getNotTaken();
    // for each non-branch instruction s in the diamond,
    // copy s to a new instruction s'
    // and store a mapping from s to s'
    HashMap<Instruction, Instruction> takenInstructions = new HashMap<Instruction, Instruction>();
    Instruction[] takenInstructionList = copyAndMapInstructions(taken, takenInstructions);
    HashMap<Instruction, Instruction> notTakenInstructions = new HashMap<Instruction, Instruction>();
    Instruction[] notTakenInstructionList = copyAndMapInstructions(notTaken, notTakenInstructions);
    // Extract the values and condition from the conditional branch.
    Operand val1 = IfCmp.getVal1(cb);
    Operand val2 = IfCmp.getVal2(cb);
    ConditionOperand cond = IfCmp.getCond(cb);
    // Copy val1 and val2 to temporaries, just in case they're defined in
    // the diamond.  If they're not defined in the diamond, copy prop
    // should clean these moves up.
    RegisterOperand tempVal1 = ir.regpool.makeTemp(val1);
    Operator op = IRTools.getMoveOp(tempVal1.getType());
    cb.insertBefore(Move.create(op, tempVal1.copyRO(), val1.copy()));
    RegisterOperand tempVal2 = ir.regpool.makeTemp(val2);
    op = IRTools.getMoveOp(tempVal2.getType());
    cb.insertBefore(Move.create(op, tempVal2.copyRO(), val2.copy()));
    // For each instruction in each temporary set, rewrite it to def a new
    // temporary, and insert it before the branch.
    rewriteWithTemporaries(takenInstructionList, ir);
    rewriteWithTemporaries(notTakenInstructionList, ir);
    insertBefore(takenInstructionList, cb);
    insertBefore(notTakenInstructionList, cb);
    // For each register defined in the TAKEN branch, save a mapping to
    // the corresponding conditional move.
    HashMap<Register, Instruction> takenMap = new HashMap<Register, Instruction>();
    // First handle the taken branch.
    if (taken != null) {
        for (Enumeration<Instruction> e = taken.forwardRealInstrEnumerator(); e.hasMoreElements(); ) {
            Instruction s = e.nextElement();
            if (s.isBranch())
                continue;
            Operand def = s.getDefs().nextElement();
            // that will now be dead
            if (def.asRegister().getRegister().spansBasicBlock()) {
                Instruction tempS = takenInstructions.get(s);
                RegisterOperand temp = (RegisterOperand) tempS.getDefs().nextElement();
                op = IRTools.getCondMoveOp(def.asRegister().getType());
                Instruction cmov = CondMove.create(op, def.copy().asRegister(), tempVal1.copy(), tempVal2.copy(), cond.copy().asCondition(), temp.copy(), def.copy());
                takenMap.put(def.asRegister().getRegister(), cmov);
                cb.insertBefore(cmov);
            }
            s.remove();
        }
    }
    // For each register defined in the NOT-TAKEN branch, save a mapping to
    // the corresponding conditional move.
    HashMap<Register, Instruction> notTakenMap = new HashMap<Register, Instruction>();
    // Next handle the not taken branch.
    if (notTaken != null) {
        for (Enumeration<Instruction> e = notTaken.forwardRealInstrEnumerator(); e.hasMoreElements(); ) {
            Instruction s = e.nextElement();
            if (s.isBranch())
                continue;
            Operand def = s.getDefs().nextElement();
            // that will now be dead
            if (def.asRegister().getRegister().spansBasicBlock()) {
                Instruction tempS = notTakenInstructions.get(s);
                RegisterOperand temp = (RegisterOperand) tempS.getDefs().nextElement();
                Instruction prevCmov = takenMap.get(def.asRegister().getRegister());
                if (prevCmov != null) {
                    // if this register was also defined in the taken branch, change
                    // the previous cmov with a different 'False' Value
                    CondMove.setFalseValue(prevCmov, temp.copy());
                    notTakenMap.put(def.asRegister().getRegister(), prevCmov);
                } else {
                    // create a new cmov instruction
                    op = IRTools.getCondMoveOp(def.asRegister().getType());
                    Instruction cmov = CondMove.create(op, def.asRegister(), tempVal1.copy(), tempVal2.copy(), cond.copy().asCondition(), def.copy(), temp.copy());
                    cb.insertBefore(cmov);
                    notTakenMap.put(def.asRegister().getRegister(), cmov);
                }
            }
            s.remove();
        }
    }
    // Mutate the conditional branch into a GOTO.
    BranchOperand target = diamond.getBottom().makeJumpTarget();
    Goto.mutate(cb, GOTO, target);
    // Delete a potential GOTO after cb.
    Instruction next = cb.nextInstructionInCodeOrder();
    if (next.operator() != BBEND) {
        next.remove();
    }
    // Recompute the CFG.
    // fix the CFG
    diamond.getTop().recomputeNormalOut(ir);
}
Also used : Operator(org.jikesrvm.compilers.opt.ir.Operator) HashMap(java.util.HashMap) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) 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) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 28 with ConditionOperand

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

the class BranchSimplifier method processIfCmp.

static boolean processIfCmp(IR ir, BasicBlock bb, Instruction s) {
    RegisterOperand guard = IfCmp.getGuardResult(s);
    Operand val1 = IfCmp.getVal1(s);
    Operand val2 = IfCmp.getVal2(s);
    {
        int cond = IfCmp.getCond(s).evaluate(val1, val2);
        if (cond != ConditionOperand.UNKNOWN) {
            // constant fold
            if (cond == ConditionOperand.TRUE) {
                // branch taken
                insertTrueGuard(s, guard);
                Goto.mutate(s, GOTO, IfCmp.getTarget(s));
                removeBranchesAfterGotos(bb);
            } else {
                // branch not taken
                insertTrueGuard(s, guard);
                s.remove();
            }
            return true;
        }
    }
    if (val1.isConstant() && !val2.isConstant()) {
        // Canonicalize by making second argument the constant
        IfCmp.setVal1(s, val2);
        IfCmp.setVal2(s, val1);
        IfCmp.setCond(s, IfCmp.getCond(s).flipOperands());
    }
    if (val2.isIntConstant()) {
        // Tricks to get compare against zero.
        int value = ((IntConstantOperand) val2).value;
        ConditionOperand cond = IfCmp.getCond(s);
        if (value == 1) {
            if (cond.isLESS()) {
                IfCmp.setCond(s, ConditionOperand.LESS_EQUAL());
                IfCmp.setVal2(s, new IntConstantOperand(0));
            } else if (cond.isGREATER_EQUAL()) {
                IfCmp.setCond(s, ConditionOperand.GREATER());
                IfCmp.setVal2(s, new IntConstantOperand(0));
            }
        } else if (value == -1) {
            if (cond.isGREATER()) {
                IfCmp.setCond(s, ConditionOperand.GREATER_EQUAL());
                IfCmp.setVal2(s, new IntConstantOperand(0));
            } else if (cond.isLESS_EQUAL()) {
                IfCmp.setCond(s, ConditionOperand.LESS());
                IfCmp.setVal2(s, new IntConstantOperand(0));
            }
        }
    }
    return false;
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)

Example 29 with ConditionOperand

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

the class InstrumentationSamplingFramework method createCheck.

/**
 * Append a check to a basic block, and make it jump to the right places.
 *
 * @param checkBB The block to append the CBS check to.
 * @param noInstBB The basic block to jump to if the CBS check fails
 * @param instBB The basicBlock to jump to if the CBS check succeeds
 * @param fallthroughToInstBB Should checkBB fallthrough to instBB
 *                            (otherwise it must fallthrough to noInstBB)
 * @param ir the IR that contains the blocks
 */
private void createCheck(BasicBlock checkBB, BasicBlock noInstBB, BasicBlock instBB, boolean fallthroughToInstBB, IR ir) {
    appendLoad(checkBB, ir);
    // Depending on where you fallthrough, set the condition correctly
    ConditionOperand cond = null;
    BranchOperand target = null;
    BranchProfileOperand profileOperand = null;
    if (fallthroughToInstBB) {
        // The instrumented basic block is the fallthrough of checkBB,
        // so make the branch jump to the non-instrumented block.
        cond = ConditionOperand.GREATER();
        target = noInstBB.makeJumpTarget();
        // Taken frequently
        profileOperand = new BranchProfileOperand(1.0f);
    } else {
        // The non-instrumented basic block is the fallthrough of checkBB,
        // so make the branch jump to the instrumented block.
        cond = ConditionOperand.LESS_EQUAL();
        target = instBB.makeJumpTarget();
        // Taken infrequently
        profileOperand = new BranchProfileOperand(0.0f);
    }
    RegisterOperand guard = ir.regpool.makeTempValidation();
    checkBB.appendInstruction(IfCmp.create(INT_IFCMP, guard, cbsReg.copyRO(), new IntConstantOperand(0), cond, target, profileOperand));
    checkBB.recomputeNormalOut(ir);
    // Insert the decrement and store in the block that is the
    // successor of the check
    prependStore(noInstBB, ir);
    prependDecrement(noInstBB, ir);
    // Insert a counter reset in the duplicated block.
    prependCounterReset(instBB, ir);
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

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