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;
}
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;
}
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;
}
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;
}
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;
}
Aggregations