Search in sources :

Example 81 with BasicBlock

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

the class BranchOptimizationDriver method removeUnreachableCode.

/**
 * Remove unreachable code
 *
 * @param ir the IR to optimize
 * @return true if did something, false otherwise
 */
protected final boolean removeUnreachableCode(IR ir) {
    boolean result = false;
    // trap instruction is dead.
    for (Instruction s = ir.firstInstructionInCodeOrder(); s != null; s = s.nextInstructionInCodeOrder()) {
        if (Trap.conforms(s)) {
            Instruction p = s.nextInstructionInCodeOrder();
            if (p.operator() != BBEND) {
                BasicBlock bb = s.getBasicBlock();
                do {
                    Instruction q = p;
                    p = p.nextInstructionInCodeOrder();
                    q.remove();
                } while (p.operator() != BBEND);
                bb.recomputeNormalOut(ir);
                result = true;
            }
        }
    }
    // (2) perform a Depth-first search of the control flow graph,
    // and remove any nodes not reachable from entry.
    BasicBlock entry = ir.cfg.entry();
    ir.cfg.clearDFS();
    entry.sortDFS();
    for (SpaceEffGraphNode node = entry; node != null; ) {
        // save it now before removeFromCFGAndCodeOrder nulls it out!!!
        SpaceEffGraphNode nextNode = node.getNext();
        if (!node.dfsVisited()) {
            BasicBlock bb = (BasicBlock) node;
            ir.cfg.removeFromCFGAndCodeOrder(bb);
            result = true;
        }
        node = nextNode;
    }
    return result;
}
Also used : BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) SpaceEffGraphNode(org.jikesrvm.compilers.opt.util.SpaceEffGraphNode)

Example 82 with BasicBlock

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

the class BranchOptimizationDriver method applySimplify.

/**
 * Perform branch simplifications.
 *
 * @param ir the IR to optimize
 * @return was something reduced
 */
private static boolean applySimplify(IR ir) {
    boolean didSomething = false;
    for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements(); ) {
        BasicBlock bb = e.nextElement();
        didSomething |= BranchSimplifier.simplify(bb, ir);
    }
    return didSomething;
}
Also used : BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock)

Example 83 with BasicBlock

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

the class BranchOptimizations method generateCondMove.

/**
 * Attempt to generate a straight-line sequence using conditional move
 * instructions, to replace a diamond control flow structure.
 *
 * <p>Suppose we have the following code, where e{n} is an expression:
 * <pre>
 * if (a op b) {
 *   x = e2;
 *   y = e3;
 * } else {
 *   z = e4;
 *   x = e5;
 * }
 * </pre>
 * We would transform this to:
 * <pre>
 * t1 = a;
 * t2 = b;
 * t3 = e2;
 * t4 = e3;
 * t5 = e4;
 * t6 = e5;
 * COND MOVE [if (t1 op t2) x := t3 else x := t6 ];
 * COND MOVE [if (t1 op t2) y := t4 else y := y];
 * COND MOVE [if (t1 op t2) z := z  else z := t5];
 * </pre>
 *
 * <p>Note that we rely on other optimizations (eg. copy propagation) to
 * clean up some of this unnecessary mess.
 *
 * <p>Note that in this example, we've increased the shortest path by 2
 * expression evaluations, 2 moves, and 3 cond moves, but eliminated one
 * conditional branch.
 *
 * <p>We apply a cost heuristic to guide this transformation:
 * We will eliminate a conditional branch iff it increases the shortest
 * path by no more than 'k' operations.  Currently, we count each
 * instruction (alu, move, or cond move) as 1 evaluation.
 * The parameter k is specified by OPT\_Options.COND_MOVE_CUTOFF.
 *
 * <p> In the example above, since we've increased the shortest path by
 * 6 instructions, we will only perform the transformation if {@code k >= 7}.
 *
 * <p> TODO items
 * <ul>
 * <li> consider smarter cost heuristics
 * <li> enhance downstream code generation to avoid redundant evaluation
 * of condition codes.
 * </ul>
 *
 * @param ir governing IR
 * @param bb basic block of cb
 * @param cb conditional branch instruction
 * @return true if the transformation succeeds, false otherwise
 */
private boolean generateCondMove(IR ir, BasicBlock bb, Instruction cb) {
    final boolean VERBOSE = false;
    if (!VM.BuildForIA32)
        return false;
    if (!IfCmp.conforms(cb))
        return false;
    if (VERBOSE)
        System.out.println("CondMove: Looking to optimize " + cb);
    // Don't generate CMOVs for branches that can be folded.
    if (IfCmp.getVal1(cb).isConstant() && IfCmp.getVal2(cb).isConstant()) {
        if (VERBOSE)
            System.out.println("CondMove: fail - could be folded");
        return false;
    }
    // see if bb is the root of an if-then-else.
    Diamond diamond = Diamond.buildDiamond(bb);
    if (diamond == null) {
        if (VERBOSE)
            System.out.println("CondMove: fail - no diamond");
        return false;
    }
    BasicBlock taken = diamond.getTaken();
    BasicBlock notTaken = diamond.getNotTaken();
    // has a taboo instruction (eg., a PEI, store or divide).
    if (taken != null && hasCMTaboo(taken)) {
        if (VERBOSE)
            System.out.println("CondMove: fail - taken branch has taboo instruction");
        return false;
    }
    if (notTaken != null && hasCMTaboo(notTaken)) {
        if (VERBOSE)
            System.out.println("CondMove: fail - not taken branch has taboo instruction");
        return false;
    }
    ConditionOperand cond = IfCmp.getCond(cb);
    // Do not generate when we don't know the branch probability or
    // when branch probability is high. CMOVs reduce performance of
    // the out-of-order engine (Intel Optimization Guide -
    // Assembly/Compiler Coding Rule 2).
    // Ignore in the case of an abs() method as we can create tighter
    // instructions.
    BranchProfileOperand profile = IfCmp.getBranchProfile(cb);
    if ((Math.abs(profile.takenProbability - 0.5) >= ir.options.CONTROL_WELL_PREDICTED_CUTOFF) && !(cb.position() != null && cb.position().method.getName() == ABS && cond.isFLOATINGPOINT())) {
        if (VERBOSE)
            System.out.println("CondMove: fail - branch could be well predicted by branch predictor: " + profile.takenProbability);
        return false;
    }
    // if we must generate FCMP, make sure the condition code is OK
    if (cond.isFLOATINGPOINT()) {
        if (!fpConditionOK(cond)) {
            // Condition not OK, but maybe if we flip the operands
            if (!fpConditionOK(cond.flipOperands())) {
                // still not ok so flip operands back
                cond.flipOperands();
                // controlling just floating point moves
                if (!VM.BuildForSSE2Full || hasFloatingPointDef(taken, true) || hasFloatingPointDef(notTaken, true)) {
                    if (VERBOSE)
                        System.out.println("CondMove: fail - fp condition not OK: " + cond);
                    return false;
                }
            } else {
                // flip operands
                Operand val1 = IfCmp.getVal1(cb);
                Operand val2 = IfCmp.getVal2(cb);
                IfCmp.setVal1(cb, val2);
                IfCmp.setVal2(cb, val1);
            }
        }
    }
    if (!cond.isFLOATINGPOINT()) {
        // compares or for unsigned compares in x87
        if (VM.BuildForSSE2Full || !cond.isUNSIGNED()) {
            if (hasFloatingPointDef(taken, false) || hasFloatingPointDef(notTaken, false)) {
                if (VERBOSE)
                    System.out.println("CondMove: fail - not allowed integer condition controlling floating conditional move");
                return false;
            }
        }
    }
    // For now, do not generate CMOVs for longs.
    if (hasLongDef(taken) || hasLongDef(notTaken)) {
        return false;
    }
    // count the number of expression evaluations in each side of the
    // diamond
    int takenCost = 0;
    int notTakenCost = 0;
    if (taken != null)
        takenCost = evaluateCost(taken);
    if (notTaken != null)
        notTakenCost = evaluateCost(notTaken);
    // evaluate whether it's profitable.
    int shortestCost = Math.min(takenCost, notTakenCost);
    int xformCost = 2 * (takenCost + notTakenCost);
    int k = ir.options.CONTROL_COND_MOVE_CUTOFF;
    if (xformCost - shortestCost > k) {
        if (VERBOSE)
            System.out.println("CondMove: fail - cost too high");
        return false;
    }
    // Perform the transformation!
    doCondMove(ir, diamond, cb);
    return true;
}
Also used : 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) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)

Example 84 with BasicBlock

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

the class BranchOptimizations method processGoto.

/**
 * Perform optimizations for a Goto.
 *
 * <p> Patterns:
 * <pre>
 *    1)      GOTO A       replaced by  GOTO B
 *         A: GOTO B
 *
 *    2)      GOTO A       replaced by  IF .. GOTO B
 *         A: IF .. GOTO B              GOTO C
 *         C: ...
 *    3)   GOTO next instruction eliminated
 *    4)      GOTO A       replaced by  GOTO B
 *         A: LABEL
 *            BBEND
 *         B:
 *    5)   GOTO BBn where BBn has exactly one in edge
 *         - move BBn immediately after the GOTO in the code order,
 *           so that pattern 3) will create a fallthrough
 * </pre>
 *
 * <p> Precondition: Goto.conforms(g)
 *
 * @param ir governing IR
 * @param g the instruction to optimize
 * @param bb the basic block holding g
 * @return {@code true} if made a transformation
 */
private boolean processGoto(IR ir, Instruction g, BasicBlock bb) {
    BasicBlock targetBlock = g.getBranchTarget();
    // don't optimize jumps to a code motion landing pad
    if (targetBlock.getLandingPad())
        return false;
    Instruction targetLabel = targetBlock.firstInstruction();
    // get the first real instruction at the g target
    // NOTE: this instruction is not necessarily in targetBlock,
    // iff targetBlock has no real instructions
    Instruction targetInst = firstRealInstructionFollowing(targetLabel);
    if (targetInst == null || targetInst == g) {
        return false;
    }
    Instruction nextLabel = firstLabelFollowing(g);
    if (targetLabel == nextLabel) {
        // found a GOTO to the next instruction.  just remove it.
        g.remove();
        return true;
    }
    if (Goto.conforms(targetInst)) {
        // unconditional branch to unconditional branch.
        // replace g with goto to targetInst's target
        Instruction target2 = firstRealInstructionFollowing(targetInst.getBranchTarget().firstInstruction());
        if (target2 == targetInst) {
            // This happens in jByteMark.EmFloatPnt.denormalize() due to a while(true) {}
            return false;
        }
        Goto.setTarget(g, (BranchOperand) Goto.getTarget(targetInst).copy());
        // fix the CFG
        bb.recomputeNormalOut(ir);
        return true;
    }
    if (targetBlock.isEmpty()) {
        // GOTO an empty basic block.  Change target to the
        // next block.
        BasicBlock nextBlock = targetBlock.getFallThroughBlock();
        Goto.setTarget(g, nextBlock.makeJumpTarget());
        // fix the CFG
        bb.recomputeNormalOut(ir);
        return true;
    }
    if (mayDuplicateCondBranches && IfCmp.conforms(targetInst)) {
        // multiple conditional branches in a single basic block.
        if (!g.prevInstructionInCodeOrder().isBranch() && (targetInst.nextInstructionInCodeOrder().operator() == BBEND || targetInst.nextInstructionInCodeOrder().operator() == GOTO)) {
            Instruction copy = targetInst.copyWithoutLinks();
            g.replace(copy);
            Instruction newGoto = targetInst.getBasicBlock().getNotTakenNextBlock().makeGOTO();
            copy.insertAfter(newGoto);
            // fix the CFG
            bb.recomputeNormalOut(ir);
            return true;
        }
    }
    // try to create a fallthrough
    if (mayReorderCode && targetBlock.getNumberOfIn() == 1) {
        BasicBlock ftBlock = targetBlock.getFallThroughBlock();
        if (ftBlock != null) {
            BranchOperand ftTarget = ftBlock.makeJumpTarget();
            targetBlock.appendInstruction(CPOS(g, Goto.create(GOTO, ftTarget)));
        }
        ir.cfg.removeFromCodeOrder(targetBlock);
        ir.cfg.insertAfterInCodeOrder(bb, targetBlock);
        // fix the CFG
        targetBlock.recomputeNormalOut(ir);
        return true;
    }
    return false;
}
Also used : BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) BranchOperand(org.jikesrvm.compilers.opt.ir.operand.BranchOperand)

Example 85 with BasicBlock

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

the class BranchOptimizations method processTwoTargetConditionalBranch.

/**
 * Perform optimizations for a two way conditional branch.
 *
 * <p> Precondition: IfCmp2.conforms(cb)
 *
 * @param ir the governing IR
 * @param cb the instruction to optimize
 * @param bb the basic block holding if
 * @return {@code true} iff made a transformation
 */
private boolean processTwoTargetConditionalBranch(IR ir, Instruction cb, BasicBlock bb) {
    // First condition/target
    Instruction target1Label = IfCmp2.getTarget1(cb).target;
    Instruction target1Inst = firstRealInstructionFollowing(target1Label);
    Instruction nextLabel = firstLabelFollowing(cb);
    boolean endsBlock = cb.nextInstructionInCodeOrder().operator() == BBEND;
    if (target1Inst != null && target1Inst != cb) {
        if (Goto.conforms(target1Inst)) {
            // conditional branch to unconditional branch.
            // change conditional branch target to latter's target
            IfCmp2.setTarget1(cb, (BranchOperand) Goto.getTarget(target1Inst).copy());
            // fix CFG
            bb.recomputeNormalOut(ir);
            return true;
        }
        BasicBlock target1Block = target1Label.getBasicBlock();
        if (target1Block.isEmpty()) {
            // branch to an empty block.  Change target to the next block.
            BasicBlock nextBlock = target1Block.getFallThroughBlock();
            IfCmp2.setTarget1(cb, nextBlock.makeJumpTarget());
            // fix the CFG
            bb.recomputeNormalOut(ir);
            return true;
        }
    }
    // Second condition/target
    Instruction target2Label = IfCmp2.getTarget2(cb).target;
    Instruction target2Inst = firstRealInstructionFollowing(target2Label);
    if (target2Inst != null && target2Inst != cb) {
        if (Goto.conforms(target2Inst)) {
            // conditional branch to unconditional branch.
            // change conditional branch target to latter's target
            IfCmp2.setTarget2(cb, (BranchOperand) Goto.getTarget(target2Inst).copy());
            // fix CFG
            bb.recomputeNormalOut(ir);
            return true;
        }
        if ((target2Label == nextLabel) && endsBlock) {
            // found a conditional branch to the next instruction. Reduce to IfCmp
            if (VM.VerifyAssertions)
                VM._assert(cb.operator() == INT_IFCMP2);
            IfCmp.mutate(cb, INT_IFCMP, IfCmp2.getGuardResult(cb), IfCmp2.getVal1(cb), IfCmp2.getVal2(cb), IfCmp2.getCond1(cb), IfCmp2.getTarget1(cb), IfCmp2.getBranchProfile1(cb));
            return true;
        }
        BasicBlock target2Block = target2Label.getBasicBlock();
        if (target2Block.isEmpty()) {
            // branch to an empty block.  Change target to the next block.
            BasicBlock nextBlock = target2Block.getFallThroughBlock();
            IfCmp2.setTarget2(cb, nextBlock.makeJumpTarget());
            // fix the CFG
            bb.recomputeNormalOut(ir);
            return true;
        }
    }
    // if fall through to a goto; replicate the goto
    if (endsBlock) {
        Instruction nextI = firstRealInstructionFollowing(nextLabel);
        if (nextI != null && Goto.conforms(nextI)) {
            // replicate Goto
            cb.insertAfter(nextI.copyWithoutLinks());
            // fix the CFG
            bb.recomputeNormalOut(ir);
            return true;
        }
    }
    return false;
}
Also used : BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Aggregations

BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)219 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)117 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)93 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)66 ExceptionHandlerBasicBlock (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)52 Register (org.jikesrvm.compilers.opt.ir.Register)50 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)48 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)37 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)33 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)27 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)24 HeapOperand (org.jikesrvm.compilers.opt.ir.operand.HeapOperand)21 BasicBlockOperand (org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand)20 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)19 TypeReference (org.jikesrvm.classloader.TypeReference)18 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)18 Test (org.junit.Test)17 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)16 InlineSequence (org.jikesrvm.compilers.opt.inlining.InlineSequence)14 MemoryOperand (org.jikesrvm.compilers.opt.ir.operand.MemoryOperand)14