use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class UpdateGCMaps2 method perform.
/**
* @param ir the IR
*/
@Override
public void perform(IR ir) {
GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
ScratchMap scratchMap = ir.stackManager.getScratchMap();
RegisterAllocatorState regAllocState = ir.MIRInfo.regAllocState;
if (LinearScan.GC_DEBUG) {
System.out.println("SCRATCH MAP:");
System.out.println();
System.out.println(scratchMap);
}
if (scratchMap.isEmpty())
return;
// Walk over each instruction that has a GC point.
for (GCIRMapElement GCelement : ir.MIRInfo.gcIRMap) {
// new elements to add to the gc map
HashSet<RegSpillListElement> newElements = new HashSet<RegSpillListElement>();
Instruction GCinst = GCelement.getInstruction();
int dfn = regAllocState.getDFN(GCinst);
if (LinearScan.GC_DEBUG) {
VM.sysWrite("GCelement at " + dfn + " , " + GCelement);
}
// a set of elements to delete from the GC Map
HashSet<RegSpillListElement> toDelete = new HashSet<RegSpillListElement>(3);
// For each element in the GC Map ...
for (RegSpillListElement elem : GCelement.regSpillList()) {
if (LinearScan.GC_DEBUG) {
VM.sysWriteln("Update " + elem);
}
if (elem.isSpill()) {
// check if the spilled value currently is cached in a scratch
// register
Register r = elem.getSymbolicReg();
Register scratch = scratchMap.getScratch(r, dfn);
if (scratch != null) {
if (LinearScan.GC_DEBUG) {
VM.sysWriteln("cached in scratch register " + scratch);
}
// we will add a new element noting that the scratch register
// also must be including in the GC map
RegSpillListElement newElem = new RegSpillListElement(r);
newElem.setRealReg(scratch);
newElements.add(newElem);
// valid value
if (scratchMap.isDirty(GCinst, r)) {
toDelete.add(elem);
}
}
} else {
// check if the physical register is currently spilled.
int n = elem.getRealRegNumber();
Register r = phys.get(n);
if (scratchMap.isScratch(r, dfn)) {
// spilled.
if (LinearScan.GC_DEBUG) {
VM.sysWriteln("CHANGE to spill location " + regAllocState.getSpill(r));
}
elem.setSpill(regAllocState.getSpill(r));
}
}
}
// delete all obsolete elements
for (RegSpillListElement deadElem : toDelete) {
GCelement.deleteRegSpillElement(deadElem);
}
// add each new Element to the gc map
for (RegSpillListElement newElem : newElements) {
GCelement.addRegSpillElement(newElem);
}
}
}
use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class CallingConvention method expandCallingConventions.
/**
* Expands calling conventions to make physical registers explicit in the
* IR when required for calls, returns, and the prologue.
*
* @param ir the governing IR
*/
public static void expandCallingConventions(IR ir) {
Queue<Instruction> calls = new Queue<Instruction>();
// occur because the newly copied syscalls would be processed, too.
for (Instruction inst = ir.firstInstructionInCodeOrder(); inst != null; inst = inst.nextInstructionInCodeOrder()) {
if (inst.isCall()) {
calls.insert(inst);
} else if (inst.isReturn()) {
returnExpand(inst, ir);
}
}
for (Instruction call : calls) {
callExpand(call, ir);
}
// expand the prologue instruction
expandPrologue(ir);
if (VM.BuildFor64Addr && ir.stackManager.hasSysCall()) {
// Recompute def-use data structures due to added blocks
// for syscall expansion.
DefUse.computeDU(ir);
// Temporaries used for parameters might now be in two blocks.
DefUse.recomputeSpansBasicBlock(ir);
// The SSA property might be invalidated by two definitions
// for a temporary used for a return value.
DefUse.recomputeSSA(ir);
}
}
use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class CallingConvention method expandPrologue.
private static void expandPrologue(IR ir) {
boolean useDU = ir.options.getOptLevel() >= 1;
if (useDU) {
// set up register lists for dead code elimination.
DefUse.computeDU(ir);
}
Instruction p = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
if (VM.VerifyAssertions)
VM._assert(p.operator() == IR_PROLOGUE);
Instruction start = p.nextInstructionInCodeOrder();
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
int gprIndex = 0;
int fprIndex = 0;
int paramByteOffset = ir.incomingParameterBytes() + 2 * WORDSIZE;
// count the number of FPR params in a pre-pass
int FPRRegisterParams = countFPRParamsInPrologue(p);
FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfFPRParams());
ir.MIRInfo.fpStackHeight = Math.max(ir.MIRInfo.fpStackHeight, FPRRegisterParams);
// deal with each parameter
for (Enumeration<Operand> e = p.getDefs(); e.hasMoreElements(); ) {
RegisterOperand symbOp = (RegisterOperand) e.nextElement();
TypeReference rType = symbOp.getType();
if (rType.isFloatingPointType()) {
int size;
if (rType.isFloatType()) {
size = BYTES_IN_FLOAT;
paramByteOffset -= WORDSIZE;
} else {
size = BYTES_IN_DOUBLE;
paramByteOffset -= 2 * WORDSIZE;
}
// if optimizing, only define the register if it has uses
if (!useDU || symbOp.getRegister().useList != null) {
if (fprIndex < PhysicalRegisterSet.getNumberOfFPRParams()) {
// the 2nd goes in F(k-2), etc...
if (SSE2_FULL) {
Register param = phys.getFPRParam(fprIndex);
if (rType.isFloatType()) {
start.insertBefore(MIR_Move.create(IA32_MOVSS, symbOp.copyRO(), F(param)));
} else {
start.insertBefore(MIR_Move.create(IA32_MOVSD, symbOp.copyRO(), D(param)));
}
} else {
Register param = phys.getFPRParam(FPRRegisterParams - fprIndex - 1);
start.insertBefore(MIR_Move.create(IA32_FMOV, symbOp.copyRO(), D(param)));
}
} else {
Operand M = new StackLocationOperand(true, paramByteOffset, size);
if (SSE2_FULL) {
if (rType.isFloatType()) {
start.insertBefore(MIR_Move.create(IA32_MOVSS, symbOp.copyRO(), M));
} else {
start.insertBefore(MIR_Move.create(IA32_MOVSD, symbOp.copyRO(), M));
}
} else {
start.insertBefore(MIR_Move.create(IA32_FMOV, symbOp.copyRO(), M));
}
}
}
fprIndex++;
} else {
// if optimizing, only define the register if it has uses
paramByteOffset -= WORDSIZE;
if (paramIsNativeLongOn64Bit(symbOp)) {
paramByteOffset -= WORDSIZE;
}
if (!useDU || symbOp.getRegister().useList != null) {
// t is object, 1/2 of a long, int, short, char, byte, or boolean
if (gprIndex < PhysicalRegisterSet.getNumberOfGPRParams()) {
// to give the register allocator more freedom, we
// insert two move instructions to get the physical into
// the symbolic. First a move from the physical to a fresh temp
// before start and second a move from the temp to the
// 'real' parameter symbolic after start.
RegisterOperand tmp = ir.regpool.makeTemp(rType);
Register param = phys.getGPRParam(gprIndex);
RegisterOperand pOp = new RegisterOperand(param, rType);
start.insertBefore(PhysicalRegisterTools.makeMoveInstruction(tmp, pOp));
Instruction m2 = PhysicalRegisterTools.makeMoveInstruction(symbOp.copyRO(), tmp.copyD2U());
start.insertBefore(m2);
start = m2;
} else {
int stackLocSize = WORDSIZE;
if (VM.BuildFor64Addr && rType.getMemoryBytes() <= BYTES_IN_INT) {
stackLocSize = BYTES_IN_INT;
}
Operand M = new StackLocationOperand(true, paramByteOffset, stackLocSize);
start.insertBefore(MIR_Move.create(IA32_MOV, symbOp.copyRO(), M));
}
}
gprIndex++;
}
}
if (VM.VerifyAssertions && paramByteOffset != 2 * WORDSIZE) {
String msg = "pb = " + paramByteOffset + "; expected " + 2 * WORDSIZE;
VM._assert(VM.NOT_REACHED, msg);
}
removeDefsFromPrologue(p);
}
use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class MIRSplitRanges method insertMoveBefore.
/**
* Inserts an instruction to move r1 into r2 before instruction s.
*
* @param r1 the move source
* @param r2 the move target
* @param s the instruction before which the move needs to be inserted
*/
private static void insertMoveBefore(RegisterOperand r2, RegisterOperand r1, Instruction s) {
Instruction m = PhysicalRegisterTools.makeMoveInstruction(r2, r1);
s.insertBefore(m);
}
use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class MIRSplitRanges method perform.
/**
* The main method.<p>
*
* We split live ranges for registers around PEIs which have catch
* blocks. Suppose we have a
* PEI s which uses a symbolic register r1. We must ensure that after
* register allocation, r1 is NOT assigned to a scratch location in s,
* since this would mess up code in the catch block that uses r1.<p>
*
* So, instead, we introduce a new temporary r2 which holds the value of
* r1. The live range for r2 spans only the instruction s. Later, we
* will ensure that r2 is never spilled.<p>
*
* TODO: This could be implemented more efficiently.
*
* @param ir the governing IR
*/
@Override
public final void perform(IR ir) {
java.util.HashMap<Register, Register> newMap = new java.util.HashMap<Register, Register>(5);
for (Enumeration<BasicBlock> be = ir.getBasicBlocks(); be.hasMoreElements(); ) {
BasicBlock bb = be.nextElement();
for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements(); ) {
Instruction s = ie.nextElement();
;
// clear the cache of register assignments
newMap.clear();
// here and in RegisterRestrictions!
if (s.isPEI() && s.operator() != IR_PROLOGUE) {
if (bb.hasApplicableExceptionalOut(s) || !RegisterRestrictions.SCRATCH_IN_PEI) {
splitAllLiveRanges(s, newMap, ir, false);
}
}
// (1) Some operands must be in registers
switch(s.getOpcode()) {
case MIR_LOWTABLESWITCH_opcode:
{
RegisterOperand rOp = MIR_LowTableSwitch.getIndex(s);
RegisterOperand temp = findOrCreateTemp(rOp, newMap, ir);
// NOTE: Index as marked as a DU because LowTableSwitch is
// going to destroy the value in the register.
// By construction (see ConvertToLowLevelIR), no one will
// ever read the value computed by a LowTableSwitch.
// Therefore, don't insert a move instruction after the
// LowTableSwitch (which would cause IR verification
// problems anyways, since LowTableSwitch is a branch).
// move r into 'temp' before s
insertMoveBefore(temp, rOp.copyRO(), s);
rOp.setRegister(temp.getRegister());
}
break;
}
}
}
}
Aggregations