use of org.jikesrvm.compilers.opt.OptimizingCompilerException in project JikesRVM by JikesRVM.
the class LoadElimination method replaceLoads.
/**
* Walk over each instruction. If its a USE (load) of a heap
* variable and the value is available, then replace the load
* with a move from a register.
* <p>
* POSTCONDITION: sets up the mapping 'registers' from value number
* to temporary register
* @param ir the IR
* @param available information on which values are available
* @param registers a place to store information about temp registers
* @return mapping from heap variables to value numbers
*/
static UseRecordSet replaceLoads(IR ir, DF_Solution available, HashMap<UseRecord, Register> registers) {
UseRecordSet result = new UseRecordSet();
SSADictionary ssa = ir.HIRInfo.dictionary;
GlobalValueNumberState valueNumbers = ir.HIRInfo.valueNumbers;
for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements(); ) {
Instruction s = e.nextElement();
if (!GetField.conforms(s) && !GetStatic.conforms(s) && !ALoad.conforms(s)) {
continue;
}
// this instruction is a USE of heap variable H.
// get the lattice cell that holds the available indices
// for this heap variable
HeapOperand<?>[] H = ssa.getHeapUses(s);
if (H == null) {
// TODO: clean up HIR representation of these magics
continue;
}
if (H.length != 1) {
throw new OptimizingCompilerException("LoadElimination: load with wrong number of heap uses");
}
if (GetField.conforms(s) || GetStatic.conforms(s)) {
int valueNumber = -1;
if (GetField.conforms(s)) {
Object address = GetField.getRef(s);
valueNumber = valueNumbers.getValueNumber(address);
} else {
// for getStatic, always use the value number 0
valueNumber = 0;
}
ObjectCell cell = (ObjectCell) available.lookup(H[0].getHeapVariable());
if (cell == null) {
// nothing available
continue;
}
// .. if H{valueNumber} is available ...
if (cell.contains(valueNumber)) {
result.add(H[0].getHeapVariable(), valueNumber);
TypeReference type = ResultCarrier.getResult(s).getType();
Register r = findOrCreateRegister(H[0].getHeapType(), valueNumber, registers, ir.regpool, type);
if (DEBUG) {
System.out.println("ELIMINATING LOAD " + s);
}
replaceLoadWithMove(r, s);
}
} else {
// ALoad.conforms(s)
Object array = ALoad.getArray(s);
Object index = ALoad.getIndex(s);
ArrayCell cell = (ArrayCell) available.lookup(H[0].getHeapVariable());
if (cell == null) {
// nothing available
continue;
}
int v1 = valueNumbers.getValueNumber(array);
int v2 = valueNumbers.getValueNumber(index);
// .. if H{<v1,v2>} is available ...
if (cell.contains(v1, v2)) {
result.add(H[0].getHeapVariable(), v1, v2);
TypeReference type = ALoad.getResult(s).getType();
Register r = findOrCreateRegister(H[0].getHeapVariable().getHeapType(), v1, v2, registers, ir.regpool, type);
if (DEBUG) {
System.out.println("ELIMINATING LOAD " + s);
}
replaceLoadWithMove(r, s);
}
}
}
return result;
}
use of org.jikesrvm.compilers.opt.OptimizingCompilerException in project JikesRVM by JikesRVM.
the class PiNodes method getGenerator.
/*
* TODO Convert to JavaDoc and add missing tags.
* <p>
* Get the instruction a Pi node is linked to.
* <strong>PRECONDITION: </strong> register lists computed and valid.
*/
public static Instruction getGenerator(Instruction def) {
if (def.operator() != PI) {
throw new OptimizingCompilerException("Not a PI Node!");
}
Operand g = GuardedUnary.getGuard(def);
Instruction link = g.asRegister().getRegister().defList.instruction;
return link;
}
use of org.jikesrvm.compilers.opt.OptimizingCompilerException in project JikesRVM by JikesRVM.
the class OptMachineCodeMap method generateMCInformation.
// //////////////////////////////////////////
// Create the map (at compile time)
// //////////////////////////////////////////
/**
* This method walks the IR map, and for each entry it creates
* the machine code mapping information for the entry.
* It is called during the compilation of the method, not at GC time.
* @param irMap the irmap to translate from
* @param DUMP_MAPS dump while we work
* @param mcOffsets machine code offset information
* @return the machine code map
*/
private static OptMachineCodeMap generateMCInformation(GCIRMap irMap, boolean DUMP_MAPS, MachineCodeOffsets mcOffsets) {
CallSiteTree inliningMap = new CallSiteTree();
int numEntries = 0;
// construct and encode the inlining information for those entries.
for (GCIRMapElement irMapElem : irMap) {
numEntries++;
Instruction instr = irMapElem.getInstruction();
if (instr.position() == null && instr.getBytecodeIndex() != INSTRUMENTATION_BCI) {
if ((VM.BuildForIA32 && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.conforms(instr) && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.hasMethod(instr)) || (VM.BuildForPowerPC && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.conforms(instr) && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.hasMethod(instr))) {
throw new OptimizingCompilerException("position required for all call instructions " + instr);
}
} else {
inliningMap.addLocation(instr.position());
}
}
// if no entries, then we are done.
if (numEntries == 0)
return emptyMachineCodeMap;
int[] inlineEncoding = OptEncodedCallSiteTree.getEncoding(inliningMap);
// (2) Encode the primary machine code mapping information and the GCMaps.
OptGCMap gcMapBuilder = new OptGCMap();
int[] tmpMC = new int[numEntries * SIZEOF_HUGE_ENTRY];
int lastMCInfoEntry = 0;
for (GCIRMapElement irMapElem : irMap) {
Instruction instr = irMapElem.getInstruction();
if (DUMP_MAPS)
VM.sysWrite("IR Map for " + instr + "\n\t" + irMapElem);
// retrieve the machine code offset (in bytes) from the instruction,
ensureCorrectMapConstruction(mcOffsets, instr);
int mco = mcOffsets.getMachineCodeOffset(instr);
if (mco < 0) {
VM.sysWrite("Negative machine code MCOffset found:" + mco);
Instruction i = irMapElem.getInstruction();
int machineCodeOffsetForI = mcOffsets.getMachineCodeOffset(i);
VM.sysWriteln(i.getBytecodeIndex() + ", " + i + ", " + machineCodeOffsetForI);
throw new OptimizingCompilerException("Negative machine code MCOffset found");
}
// create GC map and get GCI
int gci = gcMapBuilder.generateGCMapEntry(irMapElem);
// get bci information
int bci = instr.getBytecodeIndex();
if (bci < 0) {
if ((bci == UNKNOWN_BCI) && ((VM.BuildForIA32 && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.conforms(instr) && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.hasMethod(instr)) || (VM.BuildForPowerPC && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.conforms(instr) && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.hasMethod(instr)))) {
throw new OptimizingCompilerException("valid bytecode index required for all calls " + instr);
}
bci = -1;
}
// get index into inline encoding
int iei = -1;
if (instr.position() != null) {
iei = inliningMap.find(instr.position()).encodedOffset;
}
// set the call info
int cm = 0;
if ((VM.BuildForIA32 && org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.conforms(instr)) || (VM.BuildForPowerPC && org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.conforms(instr))) {
MethodOperand mo;
if (VM.BuildForIA32) {
mo = org.jikesrvm.compilers.opt.ir.ia32.MIR_Call.getMethod(instr);
} else {
if (VM.VerifyAssertions)
VM._assert(VM.BuildForPowerPC);
mo = org.jikesrvm.compilers.opt.ir.ppc.MIR_Call.getMethod(instr);
}
if (mo != null && mo.isGuardedInlineOffBranch()) {
cm = IS_GUARDED_CALL;
} else {
cm = IS_UNGUARDED_CALL;
}
}
// Encode this entry into MCInformation
if (bci < INVALID_BCI && iei < INVALID_IEI && gci < INVALID_GCI && mco < (OFFSET_MASK >>> OFFSET_SHIFT)) {
// use a small entry
if (bci == -1)
bci = INVALID_BCI;
if (iei == -1)
iei = INVALID_IEI;
if (gci == -1)
gci = INVALID_GCI;
if (VM.VerifyAssertions) {
VM._assert((cm & (CALL_MASK >>> CALL_SHIFT)) == cm);
VM._assert((bci & (BCI_MASK >>> BCI_SHIFT)) == bci);
VM._assert((iei & (IEI_MASK >>> IEI_SHIFT)) == iei);
VM._assert((gci & (GCI_MASK >>> GCI_SHIFT)) == gci);
VM._assert((mco & (OFFSET_MASK >>> OFFSET_SHIFT)) == mco);
}
int t = START_OF_ENTRY;
t |= (cm << CALL_SHIFT);
t |= (bci << BCI_SHIFT);
t |= (iei << IEI_SHIFT);
t |= (gci << GCI_SHIFT);
t |= (mco << OFFSET_SHIFT);
tmpMC[lastMCInfoEntry++] = t;
} else if (bci < BIG_INVALID_BCI && iei < BIG_INVALID_IEI && gci < BIG_INVALID_GCI && mco < (BIG_OFFSET_MASK >>> BIG_OFFSET_SHIFT)) {
// use a big entry
if (bci == -1)
bci = BIG_INVALID_BCI;
if (iei == -1)
iei = BIG_INVALID_IEI;
if (gci == -1)
gci = BIG_INVALID_GCI;
if (VM.VerifyAssertions) {
VM._assert((cm & (BIG_CALL_MASK >>> BIG_CALL_SHIFT)) == cm);
VM._assert((bci & (BIG_BCI_MASK >>> BIG_BCI_SHIFT)) == bci);
VM._assert((iei & (BIG_IEI_MASK >>> BIG_IEI_SHIFT)) == iei);
VM._assert((gci & (BIG_GCI_MASK >>> BIG_GCI_SHIFT)) == gci);
VM._assert((mco & (BIG_OFFSET_MASK >>> BIG_OFFSET_SHIFT)) == mco);
}
int startIdx = lastMCInfoEntry;
tmpMC[startIdx] = START_OF_BIG_ENTRY;
tmpMC[startIdx + BIG_CALL_IDX_ADJ] |= (cm << BIG_CALL_SHIFT);
tmpMC[startIdx + BIG_BCI_IDX_ADJ] |= (bci << BIG_BCI_SHIFT);
tmpMC[startIdx + BIG_OFFSET_IDX_ADJ] |= (mco << BIG_OFFSET_SHIFT);
tmpMC[startIdx + BIG_GCI_IDX_ADJ] |= (gci << BIG_GCI_SHIFT);
tmpMC[startIdx + BIG_IEI_IDX_ADJ] |= (iei << BIG_IEI_SHIFT);
lastMCInfoEntry += SIZEOF_BIG_ENTRY;
} else {
// use a huge entry
if (bci == -1)
bci = HUGE_INVALID_BCI;
if (iei == -1)
iei = HUGE_INVALID_IEI;
if (gci == -1)
gci = HUGE_INVALID_GCI;
if (VM.VerifyAssertions) {
VM._assert((cm & (HUGE_CALL_MASK >>> HUGE_CALL_SHIFT)) == cm);
VM._assert((bci & (HUGE_BCI_MASK >>> HUGE_BCI_SHIFT)) == bci);
VM._assert((iei & (HUGE_IEI_MASK >>> HUGE_IEI_SHIFT)) == iei);
VM._assert((gci & (HUGE_GCI_MASK >>> HUGE_GCI_SHIFT)) == gci);
VM._assert((mco & (HUGE_OFFSET_MASK >>> HUGE_OFFSET_SHIFT)) == mco);
}
int startIdx = lastMCInfoEntry;
tmpMC[startIdx] = START_OF_HUGE_ENTRY;
tmpMC[startIdx + HUGE_CALL_IDX_ADJ] |= (cm << HUGE_CALL_SHIFT);
tmpMC[startIdx + HUGE_BCI_IDX_ADJ] |= (bci << HUGE_BCI_SHIFT);
tmpMC[startIdx + HUGE_OFFSET_IDX_ADJ] |= (mco << HUGE_OFFSET_SHIFT);
tmpMC[startIdx + HUGE_GCI_IDX_ADJ] |= (gci << HUGE_GCI_SHIFT);
tmpMC[startIdx + HUGE_IEI_IDX_ADJ] |= (iei << HUGE_IEI_SHIFT);
lastMCInfoEntry += SIZEOF_HUGE_ENTRY;
}
}
int[] mcInformation = new int[lastMCInfoEntry];
System.arraycopy(tmpMC, 0, mcInformation, 0, mcInformation.length);
int[] gcMaps = gcMapBuilder.finish();
return new OptMachineCodeMap(mcInformation, gcMaps, inlineEncoding);
}
use of org.jikesrvm.compilers.opt.OptimizingCompilerException in project JikesRVM by JikesRVM.
the class UpdateOSRMaps method perform.
/**
* Iterate over the IR-based OSR map, and update symbolic registers
* with real reg number or spill locations.
* Verify there are only two types of operands:
* ConstantOperand
* RegisterOperand
* for integer constant, we save the value of the integer
*
* The LONG register has another half part.
*
* CodeSpill replaces any allocated symbolic register by
* physical registers.
*/
@Override
public void perform(IR ir) throws OptimizingCompilerException {
/* for each osr instruction */
for (VariableMapElement elm : ir.MIRInfo.osrVarMap.list) {
// MethodVariables mvar = mvarsList.get(numMvars);
for (MethodVariables mvar : elm.mvars) {
// LocalRegPair tuple = tupleList.get(numTuple);
for (LocalRegPair tuple : mvar.tupleList) {
Operand op = tuple.operand;
if (op.isRegister()) {
Register sym_reg = ((RegisterOperand) op).getRegister();
setRealPosition(ir, tuple, sym_reg);
// get another half part of long register
if (VM.BuildFor32Addr && (tuple.typeCode == LongTypeCode)) {
LocalRegPair other = tuple._otherHalf;
Operand other_op = other.operand;
if (VM.VerifyAssertions)
VM._assert(other_op.isRegister());
Register other_reg = ((RegisterOperand) other_op).getRegister();
setRealPosition(ir, other, other_reg);
}
/* According to ConvertToLowLevelIR, StringConstant, LongConstant,
* NullConstant, FloatConstant, and DoubleConstant are all materialized
* The only thing left is the integer constants which could encode
* non-moveable objects.
* POTENTIAL DRAWBACKS: since any long, float, and double are moved
* to register and treated as use, it may consume more registers and
* add unnecessary MOVEs.
*
* Perhaps, ConvertToLowLevelIR can skip OsrPoint instruction.
*/
} else if (op.isIntConstant()) {
setTupleValue(tuple, ICONST, ((IntConstantOperand) op).value);
if (VM.BuildFor32Addr && (tuple.typeCode == LongTypeCode)) {
LocalRegPair other = tuple._otherHalf;
Operand other_op = other.operand;
if (VM.VerifyAssertions)
VM._assert(other_op.isIntConstant());
setTupleValue(other, ICONST, ((IntConstantOperand) other_op).value);
}
} else if (op.isAddressConstant()) {
setTupleValue(tuple, ACONST, ((AddressConstantOperand) op).value.toWord());
} else if (VM.BuildFor64Addr && op.isLongConstant()) {
setTupleValue(tuple, LCONST, Word.fromLong(((LongConstantOperand) op).value));
} else {
throw new OptimizingCompilerException("LinearScan", "Unexpected operand type at ", op.toString());
}
// for the op type
}
// for each tuple
}
// for each inlined method
}
// for each osr instruction
}
use of org.jikesrvm.compilers.opt.OptimizingCompilerException in project JikesRVM by JikesRVM.
the class IndexPropagationSystem method makeCell.
/**
* Create an DF_LatticeCell corresponding to an HeapVariable
* @param o the heap variable
* @return a new lattice cell corresponding to this heap variable
*/
@Override
protected DF_LatticeCell makeCell(Object o) {
if (!(o instanceof HeapVariable)) {
throw new OptimizingCompilerException("IndexPropagation:makeCell");
}
DF_LatticeCell result = null;
Object heapType = ((HeapVariable<?>) o).getHeapType();
if (heapType instanceof TypeReference) {
result = new ArrayCell((HeapVariable<?>) o);
} else {
result = new ObjectCell((HeapVariable<?>) o);
}
return result;
}
Aggregations