use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method resolveMember.
/**
* Generate the code to resolve a member (field/method) reference.
* @param s the RESOLVE_MEMBER instruction to expand
* @param ir the containing ir object
* @return the last expanded instruction
*/
private static Instruction resolveMember(Instruction s, IR ir) {
Operand memberOp = Unary.getClearVal(s);
RegisterOperand offset = Unary.getClearResult(s);
int dictId;
if (memberOp instanceof LocationOperand) {
dictId = ((LocationOperand) memberOp).getFieldRef().getId();
} else {
dictId = ((MethodOperand) memberOp).getMemberRef().getId();
}
BranchProfileOperand bp = BranchProfileOperand.never();
BasicBlock predBB = s.getBasicBlock();
BasicBlock succBB = predBB.splitNodeAt(s.prevInstructionInCodeOrder(), ir);
BasicBlock testBB = predBB.createSubBlock(s.getBytecodeIndex(), ir, 1f - bp.takenProbability);
BasicBlock resolveBB = predBB.createSubBlock(s.getBytecodeIndex(), ir, bp.takenProbability);
s.remove();
// Get the offset from the appropriate RVMClassLoader array
// and check to see if it is valid
RegisterOperand offsetTable = getStatic(testBB.lastInstruction(), ir, Entrypoints.memberOffsetsField);
testBB.appendInstruction(Load.create(INT_LOAD, offset.copyRO(), offsetTable, AC(Offset.fromIntZeroExtend(dictId << LOG_BYTES_IN_INT)), new LocationOperand(TypeReference.Int), TG()));
testBB.appendInstruction(Unary.create(INT_2ADDRSigExt, offset, offset.copy()));
testBB.appendInstruction(IfCmp.create(REF_IFCMP, ir.regpool.makeTempValidation(), offset.copy(), AC(Address.fromIntSignExtend(NEEDS_DYNAMIC_LINK)), ConditionOperand.EQUAL(), resolveBB.makeJumpTarget(), bp));
// Handle the offset being invalid
resolveBB.appendInstruction(CacheOp.mutate(s, RESOLVE, memberOp));
resolveBB.appendInstruction(testBB.makeGOTO());
// Put together the CFG links & code order
predBB.insertOut(testBB);
ir.cfg.linkInCodeOrder(predBB, testBB);
testBB.insertOut(succBB);
testBB.insertOut(resolveBB);
ir.cfg.linkInCodeOrder(testBB, succBB);
// backedge
resolveBB.insertOut(testBB);
// stick resolution code in outer space.
ir.cfg.addLastInCodeOrder(resolveBB);
return testBB.lastInstruction();
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand 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.BranchProfileOperand 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.BranchProfileOperand 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);
}
}
use of org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method convertToBranchingTypeCheck.
/**
* Generate wrapper around branching type check to get a
* value producing type check.
* @param s The Instruction that is to be replaced by
* a value producing type check
* @param ir The IR containing the instruction to be expanded.
* @param RHSobj The RegisterOperand containing the rhs object.
* @param LHStype The TypeReference to be tested against.
* @param RHStib The Operand containing the TIB of the rhs.
* @param result The RegisterOperand that the result of dynamic
* @return the opt instruction immediately before the instruction to
* continue expansion.
*/
private static Instruction convertToBranchingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, RegisterOperand result) {
BasicBlock myBlock = s.getBasicBlock();
BasicBlock contBlock = myBlock.splitNodeAt(s, ir);
int subBlockStart = s.getBytecodeIndex();
BasicBlock trueBlock = myBlock.createSubBlock(subBlockStart, ir);
BasicBlock falseBlock = myBlock.createSubBlock(subBlockStart, ir);
myBlock.insertOut(trueBlock);
myBlock.insertOut(falseBlock);
trueBlock.insertOut(contBlock);
falseBlock.insertOut(contBlock);
ir.cfg.linkInCodeOrder(myBlock, trueBlock);
ir.cfg.linkInCodeOrder(trueBlock, falseBlock);
ir.cfg.linkInCodeOrder(falseBlock, contBlock);
trueBlock.appendInstruction(Move.create(INT_MOVE, result, IC(1)));
trueBlock.appendInstruction(Goto.create(GOTO, contBlock.makeJumpTarget()));
falseBlock.appendInstruction(Move.create(INT_MOVE, result.copyD2D(), IC(0)));
return generateBranchingTypeCheck(s, ir, RHSobj, LHStype, RHStib, trueBlock, falseBlock, ir.regpool.makeTempValidation(), new BranchProfileOperand());
}
Aggregations