use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method lookup.
/**
* Expand a lookupswitch.
* @param switchInstr The instruction to expand
* @param ir The containing IR
* @return the next {@link Instruction} after the generated LIR sequence.
*/
static Instruction lookup(Instruction switchInstr, IR ir) {
Instruction bbend = switchInstr.nextInstructionInCodeOrder();
BasicBlock thisBB = bbend.getBasicBlock();
BasicBlock nextBB = thisBB.nextBasicBlockInCodeOrder();
// Blow away the old Normal ControlFlowGraph edges to prepare for new links
thisBB.deleteNormalOut();
switchInstr.remove();
BranchOperand defTarget = LookupSwitch.getClearDefault(switchInstr);
BasicBlock defaultBB = defTarget.target.getBasicBlock();
int high = LookupSwitch.getNumberOfTargets(switchInstr) - 1;
if (high < 0) {
// no cases in switch; just jump to defaultBB
thisBB.appendInstruction(Goto.create(GOTO, defTarget));
thisBB.insertOut(defaultBB);
} else {
Operand match = LookupSwitch.getValue(switchInstr);
if (match.isConstant()) {
// switch on a constant
int value = match.asIntConstant().value;
int numMatches = LookupSwitch.getNumberOfMatches(switchInstr);
BranchOperand target = LookupSwitch.getDefault(switchInstr);
for (int i = 0; i < numMatches; i++) {
if (value == LookupSwitch.getMatch(switchInstr, i).value) {
target = LookupSwitch.getTarget(switchInstr, i);
break;
}
}
thisBB.appendInstruction(Goto.create(GOTO, target));
thisBB.insertOut(target.target.getBasicBlock());
} else {
RegisterOperand reg = match.asRegister();
// If you're not already at the end of the code order
if (nextBB != null) {
ir.cfg.breakCodeOrder(thisBB, nextBB);
}
// generate the binary search tree into thisBB
BasicBlock lastNewBB = _lookupswitchHelper(switchInstr, reg, defaultBB, ir, thisBB, 0, high, Integer.MIN_VALUE, Integer.MAX_VALUE);
if (nextBB != null) {
ir.cfg.linkInCodeOrder(lastNewBB, nextBB);
}
}
}
// skip all the instrs just inserted by _lookupswitchHelper
if (nextBB != null) {
return nextBB.firstInstruction();
} else {
return thisBB.lastInstruction();
}
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method tableswitch.
/**
* Expand a tableswitch.
* @param s the instruction to expand
* @param ir the containing IR
* @return the last Instruction in the generated LIR sequence.
*/
static Instruction tableswitch(Instruction s, IR ir) {
Instruction s2;
int lowLimit = TableSwitch.getLow(s).value;
int highLimit = TableSwitch.getHigh(s).value;
int number = highLimit - lowLimit + 1;
if (VM.VerifyAssertions) {
// also checks that there are < 2^31 targets
VM._assert(number > 0);
}
Operand val = TableSwitch.getClearValue(s);
BranchOperand defaultLabel = TableSwitch.getClearDefault(s);
if (number < ir.options.CONTROL_TABLESWITCH_CUTOFF) {
// convert into a lookupswitch
Instruction l = LookupSwitch.create(LOOKUPSWITCH, val, null, null, defaultLabel, TableSwitch.getClearDefaultBranchProfile(s), number * 3);
for (int i = 0; i < number; i++) {
LookupSwitch.setMatch(l, i, IC(lowLimit + i));
LookupSwitch.setTarget(l, i, TableSwitch.getClearTarget(s, i));
LookupSwitch.setBranchProfile(l, i, TableSwitch.getClearBranchProfile(s, i));
}
s.insertAfter(CPOS(s, l));
return s.remove();
}
RegisterOperand reg = val.asRegister();
BasicBlock BB1 = s.getBasicBlock();
BasicBlock BB2 = BB1.splitNodeAt(s, ir);
BasicBlock defaultBB = defaultLabel.target.getBasicBlock();
/**
***** First basic block
*/
RegisterOperand t;
if (lowLimit != 0) {
t = insertBinary(s, ir, INT_ADD, TypeReference.Int, reg, IC(-lowLimit));
} else {
t = reg.copyU2U();
}
BranchProfileOperand defaultProb = TableSwitch.getClearDefaultBranchProfile(s);
s.replace(CPOS(s, IfCmp.create(INT_IFCMP, ir.regpool.makeTempValidation(), t, IC(highLimit - lowLimit), ConditionOperand.HIGHER(), defaultLabel, defaultProb)));
// Reweight branches to account for the default branch going. If
// the default probability was ALWAYS then when we recompute the
// weight to be a proportion of the total number of branches.
final boolean defaultIsAlways = defaultProb.takenProbability >= 1f;
final float weight = defaultIsAlways ? 1f / number : 1f / (1f - defaultProb.takenProbability);
/**
******** second Basic Block *****
*/
s2 = CPOS(s, LowTableSwitch.create(LOWTABLESWITCH, t.copyRO(), number * 2));
boolean containsDefault = false;
for (int i = 0; i < number; i++) {
BranchOperand b = TableSwitch.getClearTarget(s, i);
LowTableSwitch.setTarget(s2, i, b);
BranchProfileOperand bp = TableSwitch.getClearBranchProfile(s, i);
if (defaultIsAlways) {
bp.takenProbability = weight;
} else {
bp.takenProbability *= weight;
}
LowTableSwitch.setBranchProfile(s2, i, bp);
if (b.target == defaultLabel.target) {
containsDefault = true;
}
}
// Fixup the CFG and code order.
BB1.insertOut(BB2);
BB1.insertOut(defaultBB);
ir.cfg.linkInCodeOrder(BB1, BB2);
if (!containsDefault) {
BB2.deleteOut(defaultBB);
}
// This actually happens (very occasionally), and is easy to test for.
if (BB2.getNumberOfNormalOut() == 1) {
BB2.appendInstruction(CPOS(s, Goto.create(GOTO, LowTableSwitch.getClearTarget(s2, 0))));
} else {
BB2.appendInstruction(s2);
}
// continue at next BB
s = BB2.lastInstruction();
return s;
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method _lookupswitchHelper.
/**
* Helper function to generate the binary search tree for
* a lookupswitch bytecode
*
* @param switchInstr the lookupswitch instruction
* @param defaultBB the basic block of the default case
* @param ir the ir object
* @param curBlock the basic block to insert instructions into
* @param reg the RegisterOperand that contains the valued being switched on
* @param low the low index of cases (operands of switchInstr)
* @param high the high index of cases (operands of switchInstr)
* @param min minimum for the current case
* @param max maximum for the current case
* @return the last basic block created
*/
private static BasicBlock _lookupswitchHelper(Instruction switchInstr, RegisterOperand reg, BasicBlock defaultBB, IR ir, BasicBlock curBlock, int low, int high, int min, int max) {
if (VM.VerifyAssertions) {
VM._assert(low <= high, "broken control logic in _lookupswitchHelper");
}
// find middle
int middle = (low + high) >> 1;
// The following are used below to store the computed branch
// probabilities for the branches that are created to implement
// the binary search. Used only if basic block frequencies available
float lessProb = 0.0f;
float greaterProb = 0.0f;
float equalProb = 0.0f;
float sum = 0.0f;
// Sum the probabilities for all targets < middle
for (int i = low; i < middle; i++) {
lessProb += LookupSwitch.getBranchProfile(switchInstr, i).takenProbability;
}
// Sum the probabilities for all targets > middle
for (int i = middle + 1; i <= high; i++) {
greaterProb += LookupSwitch.getBranchProfile(switchInstr, i).takenProbability;
}
equalProb = LookupSwitch.getBranchProfile(switchInstr, middle).takenProbability;
// generated may not).
if (low == 0) {
lessProb += LookupSwitch.getDefaultBranchProfile(switchInstr).takenProbability;
}
// Now normalize them so they are relative to the sum of the
// branches being considered in this piece of the subtree
sum = lessProb + equalProb + greaterProb;
if (sum > 0) {
// check for divide by zero
lessProb /= sum;
equalProb /= sum;
greaterProb /= sum;
}
IntConstantOperand val = LookupSwitch.getClearMatch(switchInstr, middle);
int value = val.value;
BasicBlock greaterBlock = middle == high ? defaultBB : curBlock.createSubBlock(0, ir);
BasicBlock lesserBlock = low == middle ? defaultBB : curBlock.createSubBlock(0, ir);
// Generate this level of tests
BranchOperand branch = LookupSwitch.getClearTarget(switchInstr, middle);
BasicBlock branchBB = branch.target.getBasicBlock();
curBlock.insertOut(branchBB);
if (low != high) {
if (value == min) {
curBlock.appendInstruction(IfCmp.create(INT_IFCMP, ir.regpool.makeTempValidation(), reg.copy(), val, ConditionOperand.EQUAL(), branchBB.makeJumpTarget(), new BranchProfileOperand(equalProb)));
} else {
// To compute the probability of the second compare, the first
// probability must be removed since the second branch is
// considered only if the first fails.
float secondIfProb = 0.0f;
sum = equalProb + greaterProb;
if (sum > 0) {
// if divide by zero, leave as is
secondIfProb = equalProb / sum;
}
curBlock.appendInstruction(IfCmp2.create(INT_IFCMP2, ir.regpool.makeTempValidation(), reg.copy(), val, ConditionOperand.LESS(), lesserBlock.makeJumpTarget(), new BranchProfileOperand(lessProb), ConditionOperand.EQUAL(), branchBB.makeJumpTarget(), new BranchProfileOperand(secondIfProb)));
curBlock.insertOut(lesserBlock);
}
} else {
// Base case: middle was the only case left to consider
if (min == max) {
curBlock.appendInstruction(Goto.create(GOTO, branch));
curBlock.insertOut(branchBB);
} else {
curBlock.appendInstruction(IfCmp.create(INT_IFCMP, ir.regpool.makeTempValidation(), reg.copy(), val, ConditionOperand.EQUAL(), branchBB.makeJumpTarget(), new BranchProfileOperand(equalProb)));
BasicBlock newBlock = curBlock.createSubBlock(0, ir);
curBlock.insertOut(newBlock);
ir.cfg.linkInCodeOrder(curBlock, newBlock);
curBlock = newBlock;
curBlock.appendInstruction(defaultBB.makeGOTO());
curBlock.insertOut(defaultBB);
}
}
// Generate sublevels as needed and splice together instr & bblist
if (middle < high) {
curBlock.insertOut(greaterBlock);
ir.cfg.linkInCodeOrder(curBlock, greaterBlock);
curBlock = _lookupswitchHelper(switchInstr, reg, defaultBB, ir, greaterBlock, middle + 1, high, value + 1, max);
}
if (low < middle) {
ir.cfg.linkInCodeOrder(curBlock, lesserBlock);
curBlock = _lookupswitchHelper(switchInstr, reg, defaultBB, ir, lesserBlock, low, middle - 1, min, value - 1);
}
return curBlock;
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchOperand 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.operand.BranchOperand in project JikesRVM by JikesRVM.
the class BranchOptimizations method flipConditionalBranch.
/**
* Flip a conditional branch and remove the trailing goto.
* See comment 3) of processConditionalBranch
*
* <p> Precondition isFlipCandidate(cb)
* @param cb the conditional branch instruction
*/
private void flipConditionalBranch(Instruction cb) {
// get the trailing GOTO instruction
Instruction g = cb.nextInstructionInCodeOrder();
BranchOperand gTarget = (BranchOperand) (Goto.getTarget(g).copy());
// now flip the test and set the new target
IfCmp.setCond(cb, IfCmp.getCond(cb).flipCode());
IfCmp.setTarget(cb, gTarget);
// Update the branch probability. It is now the opposite
cb.flipBranchProbability();
// finally, remove the trailing GOTO instruction
g.remove();
}
Aggregations