use of org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method doArrayStore.
/**
* Expand an array store.
* @param s the instruction to expand
* @param ir the containing IR
* @param op the store operator to use
* @param logwidth the log base 2 of the element type's size
*/
public static void doArrayStore(Instruction s, IR ir, Operator op, int logwidth) {
if (LOWER_ARRAY_ACCESS) {
Operand value = AStore.getClearValue(s);
Operand array = AStore.getClearArray(s);
Operand index = AStore.getClearIndex(s);
Operand offset;
LocationOperand loc = AStore.getClearLocation(s);
if (index instanceof IntConstantOperand) {
// constant propagation
offset = AC(Address.fromIntZeroExtend(((IntConstantOperand) index).value << logwidth));
} else {
if (logwidth != 0) {
offset = insertBinary(s, ir, INT_SHL, TypeReference.Int, index, IC(logwidth));
offset = InsertUnary(s, ir, INT_2ADDRZerExt, TypeReference.Offset, offset.copy());
} else {
offset = InsertUnary(s, ir, INT_2ADDRZerExt, TypeReference.Offset, index);
}
}
Store.mutate(s, op, value, array, offset, loc, AStore.getClearGuard(s));
}
}
use of org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand in project JikesRVM by JikesRVM.
the class ConvertToLowLevelIR method doArrayLoad.
/**
* Expand an array load.
* @param s the instruction to expand
* @param ir the containing IR
* @param op the load operator to use
* @param logwidth the log base 2 of the element type's size
*/
public static void doArrayLoad(Instruction s, IR ir, Operator op, int logwidth) {
if (LOWER_ARRAY_ACCESS) {
RegisterOperand result = ALoad.getClearResult(s);
Operand array = ALoad.getClearArray(s);
Operand index = ALoad.getClearIndex(s);
Operand offset;
LocationOperand loc = ALoad.getClearLocation(s);
if (index instanceof IntConstantOperand) {
// constant propagation
offset = AC(Address.fromIntZeroExtend(((IntConstantOperand) index).value << logwidth));
} else {
if (logwidth != 0) {
offset = insertBinary(s, ir, INT_SHL, TypeReference.Int, index, IC(logwidth));
offset = InsertUnary(s, ir, INT_2ADDRZerExt, TypeReference.Offset, offset.copy());
} else {
offset = InsertUnary(s, ir, INT_2ADDRZerExt, TypeReference.Offset, index);
}
}
Load.mutate(s, op, result, array, offset, loc, ALoad.getClearGuard(s));
}
}
use of org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand 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.IntConstantOperand 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.IntConstantOperand in project JikesRVM by JikesRVM.
the class DynamicTypeCheckExpansion method generateBranchingTypeCheck.
/**
* Generate a branching dynamic type check.
* This routine assumes that the CFG and code order are already
* correctly established.
* This routine must either remove s or mutate it.
*
* @param s The Instruction that is to be replaced by a
* branching 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 trueBlock The BasicBlock to continue at if the typecheck
* evaluates to true
* @param falseBlock The BasicBlock to continue at if the typecheck
* evaluates to false.
* @param oldGuard A suitable guard operand (not necessarily related
* the instruction that is to be replaced).
* @param falseProb The probability that typecheck will branch to the falseBlock
* @return the opt instruction immediately before the instruction to
* continue expansion.
*/
private static Instruction generateBranchingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, BasicBlock trueBlock, BasicBlock falseBlock, RegisterOperand oldGuard, BranchProfileOperand falseProb) {
Instruction continueAt = Goto.create(GOTO, trueBlock.makeJumpTarget());
continueAt.copyPosition(s);
s.insertBefore(continueAt);
s.remove();
if (LHStype.isClassType()) {
RVMClass LHSclass = (RVMClass) LHStype.peekType();
if (LHSclass != null && LHSclass.isResolved()) {
// class or interface
if (LHSclass.isInterface()) {
// A resolved interface (case 4)
int interfaceIndex = LHSclass.getDoesImplementIndex();
int interfaceMask = LHSclass.getDoesImplementBitMask();
RegisterOperand doesImpl = InsertUnary(continueAt, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
RegisterOperand doesImplLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, doesImplLength, IC(interfaceIndex), ConditionOperand.LESS_EQUAL(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(lengthCheck);
BasicBlock oldBlock = continueAt.getBasicBlock();
oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
// required due to splitNode!
oldBlock.insertOut(falseBlock);
}
RegisterOperand entry = InsertLoadOffset(continueAt, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
RegisterOperand bit = insertBinary(continueAt, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, bit, IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
} else {
// A resolved class (cases 5 and 6 in DynamicTypeCheck)
if (LHSclass.isFinal()) {
// For a final class, we can do a PTR compare of
// rhsTIB and the TIB of the class
Operand classTIB = getTIB(continueAt, ir, LHSclass);
continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
} else {
// Do the full blown case 5 or 6 typecheck.
int LHSDepth = LHSclass.getTypeDepth();
int LHSId = LHSclass.getId();
RegisterOperand superclassIds = InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
RegisterOperand superclassIdsLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, superclassIdsLength, IC(LHSDepth), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(lengthCheck);
BasicBlock oldBlock = continueAt.getBasicBlock();
oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
// required due to splitNode!
oldBlock.insertOut(falseBlock);
}
RegisterOperand refCandidate = InsertLoadOffset(continueAt, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, refCandidate, IC(LHSId), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
} else {
// A non-resolved class or interface. Case 3 of DynamicTypeCheck
// Branch on the result of a call to
// RuntimeEntrypoints.instance
RegisterOperand result = ir.regpool.makeTempInt();
RVMMethod target = Entrypoints.instanceOfMethod;
Instruction call = Call.create2(CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
call.copyPosition(continueAt);
continueAt.insertBefore(call);
call = callHelper(call, ir);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, result.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
if (LHStype.isArrayType()) {
// Case 2 of DynamicTypeCheck: LHS is an array.
RVMArray LHSArray = (RVMArray) LHStype.peekType();
if (LHSArray != null) {
Operand classTIB = getTIB(continueAt, ir, LHSArray);
RVMType innermostElementType = LHSArray.getInnermostElementType();
if (innermostElementType.isPrimitiveType() || innermostElementType.isUnboxedType() || (innermostElementType.asClass().isResolved() && innermostElementType.asClass().isFinal())) {
// [^k of primitive or [^k of final class. Just like final classes,
// a PTR compare of rhsTIB and the TIB of the class gives the answer.
continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
// TODO: branch probability calculation is somewhat bogus for this case.
Instruction shortcircuit = IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.EQUAL(), trueBlock.makeJumpTarget(), new BranchProfileOperand());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(shortcircuit);
BasicBlock myBlock = shortcircuit.getBasicBlock();
BasicBlock mainBlock = myBlock.splitNodeWithLinksAt(shortcircuit, ir);
// must come after the splitNodeAt
myBlock.insertOut(trueBlock);
RegisterOperand rhsType = InsertUnary(continueAt, ir, GET_TYPE_FROM_TIB, TypeReference.Type, RHStib.copy());
if (innermostElementType.isJavaLangObjectType()) {
IntConstantOperand lhsDimension = IC(LHStype.getDimensionality());
RegisterOperand rhsDimension = getField(continueAt, ir, rhsType, Entrypoints.dimensionField);
Instruction dimTest = IfCmp2.create(INT_IFCMP2, oldGuard, rhsDimension, lhsDimension, ConditionOperand.GREATER(), trueBlock.makeJumpTarget(), ((BranchProfileOperand) falseProb.copy()).flip(), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), (BranchProfileOperand) falseProb.copy());
if (oldGuard != null) {
oldGuard = oldGuard.copyD2D();
}
continueAt.insertBefore(dimTest);
// BasicBlock testBlock =
mainBlock.splitNodeWithLinksAt(dimTest, ir);
mainBlock.insertOut(trueBlock);
mainBlock.insertOut(falseBlock);
RegisterOperand rhsInnermostElementTypeDimension = getField(continueAt, ir, rhsType.copyU2U(), Entrypoints.innermostElementTypeDimensionField);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, rhsInnermostElementTypeDimension, IC(0), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
}
// Not a case we want to handle inline
RVMMethod target = Entrypoints.instanceOfMethod;
RegisterOperand callResult = ir.regpool.makeTempInt();
Instruction call = Call.create2(CALL, callResult, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
call.copyPosition(continueAt);
continueAt.insertBefore(call);
call = callHelper(call, ir);
continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, callResult.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
return continueAt;
}
OptimizingCompilerException.UNREACHABLE();
return null;
}
Aggregations