use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class StackManager method insertNormalPrologue.
/*
* Insert the prologue.
* The available scratch registers are normally: R0, S0, S1
* However, if this is the prologue for a 'save volatile' frame,
* then R0 is the only available scratch register.
* The "normal" prologue must perform the following tasks:
* stack overflow check
* set TSR for the yieldpoint if there is a prologue yieldpoint instruction
* save lr
* store cmid
* buy stack frame
* store any used non volatiles
* We schedule the prologue for this combination of operations,
* since it is currently the common case.
* When this changes, this code should be modifed accordingly.
* The desired sequence is:
* 1 mflr 00 # return addr
* 2 l S1 takeYieldpointOffset(PR) # setting TSR for yield point
* 3 stu FP -frameSize(FP) # buy frame, save caller's fp
* 4 l S0 stackLimitOffset(S0) # stack overflow check
* 5 <save used non volatiles>
* 6 cmpi TSR S1 0x0 # setting TSR for yield point (S1 is now free)
* 7 lil S1 CMID # cmid
* 8 st 00 STACKFRAME_RETURN_ADDRESS_OFFSET(FP) # return addr (00 is now free)
* 9 st S1 STACKFRAME_METHOD_ID_OFFSET(FP) # cmid
* 10 tgt S0, FP # stack overflow check (already bought frame)
*/
/**
* Schedule prologue for 'normal' case (see above)
*/
@Override
public void insertNormalPrologue() {
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
Register FP = phys.getFP();
Register TR = phys.getTR();
Register TSR = phys.getTSR();
Register R0 = phys.getTemp();
Register S0 = phys.getGPR(FIRST_SCRATCH_GPR);
Register S1 = phys.getGPR(LAST_SCRATCH_GPR);
boolean interruptible = ir.method.isInterruptible();
boolean stackOverflow = interruptible;
boolean yp = hasPrologueYieldpoint();
int frameFixedSize = getFrameFixedSize();
ir.compiledMethod.setFrameFixedSize(frameFixedSize);
if (frameFixedSize >= STACK_SIZE_GUARD || ir.compiledMethod.isSaveVolatile()) {
insertExceptionalPrologue();
return;
}
Instruction ptr = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
if (VM.VerifyAssertions)
VM._assert(ptr.getOpcode() == IR_PROLOGUE_opcode);
// 1
ptr.insertBefore(MIR_Move.create(PPC_MFSPR, A(R0), A(phys.getLR())));
if (yp) {
Offset offset = Entrypoints.takeYieldpointField.getOffset();
if (VM.VerifyAssertions)
VM._assert(fits(offset, 16));
// 2
ptr.insertBefore(MIR_Load.create(PPC_LInt, I(S1), A(TR), IC(PPCMaskLower16(offset))));
}
// 3
ptr.insertBefore(MIR_StoreUpdate.create(PPC_STAddrU, A(FP), A(FP), IC(-frameSize)));
if (stackOverflow) {
Offset offset = Entrypoints.stackLimitField.getOffset();
if (VM.VerifyAssertions)
VM._assert(fits(offset, 16));
// 4
ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S0), A(phys.getTR()), IC(PPCMaskLower16(offset))));
}
// Now add any instructions to save the volatiles and nonvolatiles (5)
saveNonVolatiles(ptr);
if (yp) {
// 6
ptr.insertBefore(MIR_Binary.create(PPC_CMPI, I(TSR), I(S1), IC(0)));
}
int cmid = ir.compiledMethod.getId();
if (cmid <= 0x7fff) {
// 7
ptr.insertBefore(MIR_Unary.create(PPC_LDI, I(S1), IC(cmid)));
} else {
// 7 (a)
ptr.insertBefore(MIR_Unary.create(PPC_LDIS, I(S1), IC(cmid >>> 16)));
// 7 (b)
ptr.insertBefore(MIR_Binary.create(PPC_ORI, I(S1), I(S1), IC(cmid & 0xffff)));
}
ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(R0), A(FP), // 8
IC(frameSize + STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
// 9
ptr.insertBefore(MIR_Store.create(PPC_STW, I(S1), A(FP), IC(STACKFRAME_METHOD_ID_OFFSET.toInt())));
if (stackOverflow) {
// Mutate the Prologue instruction into the trap
MIR_Trap.mutate(ptr, PPC_TAddr, PowerPCTrapOperand.GREATER(), A(S0), A(FP), // 10
TrapCodeOperand.StackOverflow());
} else {
// no stack overflow test, so we remove the IR_Prologue instruction
ptr.remove();
}
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class StackManager method restoreNonVolatiles.
/**
* Insert code before a return instruction to restore the nonvolatile
* registers.
*
* @param inst the return instruction
*/
private void restoreNonVolatiles(Instruction inst) {
GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
int nNonvolatileGPRS = ir.compiledMethod.getNumberOfNonvolatileGPRs();
// 1. restore the nonvolatile GPRs
int n = nNonvolatileGPRS - 1;
Register FP = phys.getFP();
if (VM.BuildFor32Addr && n > MULTIPLE_CUTOFF) {
// use an lm
Register nv = null;
for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements() && n >= 0; n--) {
nv = e.nextElement();
}
n++;
RegisterOperand range = I(nv);
// YUCK!!! Why is this crap in register operand??
int offset = getNonvolatileGPROffset(n);
inst.insertBefore(MIR_Load.create(PPC_LMW, range, A(FP), IC(offset)));
} else {
for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements() && n >= 0; n--) {
Register nv = e.nextElement();
int offset = getNonvolatileGPROffset(n);
inst.insertBefore(MIR_Load.create(PPC_LAddr, A(nv), A(FP), IC(offset)));
}
}
// Note that save-volatiles are forbidden from using nonvolatile FPRs.
if (!ir.compiledMethod.isSaveVolatile()) {
// 1. restore the nonvolatile FPRs
int nNonvolatileFPRS = ir.compiledMethod.getNumberOfNonvolatileFPRs();
n = nNonvolatileFPRS - 1;
// use a sequence of load instructions
for (Enumeration<Register> e = phys.enumerateNonvolatileFPRsBackwards(); e.hasMoreElements() && n >= 0; n--) {
Register nv = e.nextElement();
int offset = getNonvolatileFPROffset(n);
inst.insertBefore(MIR_Load.create(PPC_LFD, D(nv), A(FP), IC(offset)));
}
}
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class StackManager method insertUnspillBefore.
/**
* Insert a load of a physical register from a spill location before
* instruction s.
*
* @param s the instruction before which the spill should occur
* @param r the register (should be physical) to spill
* @param type one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or
* CONDITION_VALUE
* @param location the spill location
*/
@Override
public void insertUnspillBefore(Instruction s, Register r, Register type, int location) {
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
Register FP = phys.getFP();
if (type.isCondition()) {
Register temp = phys.getTemp();
s.insertBefore(MIR_Load.create(PPC_LWZ, I(temp), A(FP), IC(location + BYTES_IN_ADDRESS - BYTES_IN_INT)));
} else if (type.isDouble()) {
s.insertBefore(MIR_Load.create(PPC_LFD, D(r), A(FP), IC(location)));
} else if (type.isFloat()) {
s.insertBefore(MIR_Load.create(PPC_LFS, F(r), A(FP), IC(location + BYTES_IN_ADDRESS - BYTES_IN_FLOAT)));
} else if (type.isNatural()) {
// integer or half of long
s.insertBefore(MIR_Load.create(PPC_LAddr, A(r), A(FP), IC(location)));
} else {
throw new OptimizingCompilerException("insertUnspillBefore", "unknown type:" + type);
}
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class StackManager method insertEpilogue.
/**
* Insert the epilogue before a particular return instruction.
*
* @param ret the return instruction.
*/
private void insertEpilogue(Instruction ret) {
// 1. Restore any saved registers
if (ir.compiledMethod.isSaveVolatile()) {
restoreVolatileRegisters(ret);
}
restoreNonVolatiles(ret);
// 2. Restore return address
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
Register temp = phys.getTemp();
Register FP = phys.getFP();
ret.insertBefore(MIR_Load.create(PPC_LAddr, A(temp), A(FP), IC(STACKFRAME_RETURN_ADDRESS_OFFSET.toInt() + frameSize)));
// 3. Load return address into LR
ret.insertBefore(MIR_Move.create(PPC_MTSPR, A(phys.getLR()), A(phys.getTemp())));
// 4. Restore old FP
ret.insertBefore(MIR_Binary.create(PPC_ADDI, A(FP), A(FP), IC(frameSize)));
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class EnterSSA method patchPEIgeneratedValues.
/**
* Work around some problems with PEI-generated values and
* handlers. Namely, if a PEI has a return value, rename the
* result register before and after the PEI in order to reflect the fact
* that the PEI may not actually assign the result register.
*/
private void patchPEIgeneratedValues() {
// this only applies if there are exception handlers
if (!ir.hasReachableExceptionHandlers())
return;
HashSet<Pair<BasicBlock, RegisterOperand>> needed = new HashSet<Pair<BasicBlock, RegisterOperand>>(4);
Enumeration<BasicBlock> blocks = ir.getBasicBlocks();
while (blocks.hasMoreElements()) {
BasicBlock block = blocks.nextElement();
if (block.getExceptionalOut().hasMoreElements()) {
Instruction pei = block.lastRealInstruction();
if (pei != null && pei.isPEI() && ResultCarrier.conforms(pei)) {
boolean copyNeeded = false;
RegisterOperand v = ResultCarrier.getResult(pei);
// void calls and the like... :(
if (v != null) {
Register orig = v.getRegister();
{
Enumeration<BasicBlock> out = block.getApplicableExceptionalOut(pei);
while (out.hasMoreElements()) {
BasicBlock exp = out.nextElement();
LiveSet explive = live.getLiveInfo(exp).getIn();
if (explive.contains(orig)) {
copyNeeded = true;
break;
}
}
}
if (copyNeeded) {
Enumeration<BasicBlock> out = block.getApplicableExceptionalOut(pei);
while (out.hasMoreElements()) {
BasicBlock exp = out.nextElement();
needed.add(new Pair<BasicBlock, RegisterOperand>(exp, v));
}
}
}
}
}
}
// having determine where copies should be inserted, now insert them.
if (!needed.isEmpty()) {
for (Pair<BasicBlock, RegisterOperand> copy : needed) {
BasicBlock inBlock = copy.first;
RegisterOperand registerOp = copy.second;
TypeReference type = registerOp.getType();
Register register = registerOp.getRegister();
Register temp = ir.regpool.getReg(register);
inBlock.prependInstruction(SSA.makeMoveInstruction(ir, register, temp, type));
Enumeration<BasicBlock> outBlocks = inBlock.getIn();
while (outBlocks.hasMoreElements()) {
BasicBlock outBlock = outBlocks.nextElement();
Instruction x = SSA.makeMoveInstruction(ir, temp, register, type);
SSA.addAtEnd(ir, outBlock, x, true);
}
}
// Recompute liveness information. You might be tempted to incrementally
// update it, but it's tricky, so resist.....do the obvious, but easy thing!
prepare();
}
}
Aggregations