use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class StackManager method insertExceptionalPrologue.
/**
* prologue for the exceptional case.
* (1) R0 is the only available scratch register.
* (2) stack overflow check has to come first.
*/
void insertExceptionalPrologue() {
if (VM.VerifyAssertions) {
VM._assert((frameSize & (STACKFRAME_ALIGNMENT - 1)) == 0, "Stack frame alignment error");
}
if (frameSize >= 0x7ff0) {
throw new OptimizingCompilerException("Stackframe size exceeded!");
}
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
Register FP = phys.getFP();
Register TR = phys.getTR();
Register TSR = phys.getTSR();
Register R0 = phys.getTemp();
Register S1 = phys.getGPR(LAST_SCRATCH_GPR);
boolean interruptible = ir.method.isInterruptible();
boolean stackOverflow = interruptible;
boolean yp = hasPrologueYieldpoint();
Instruction ptr = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
if (VM.VerifyAssertions)
VM._assert(ptr.getOpcode() == IR_PROLOGUE_opcode);
// Stack overflow check
if (stackOverflow) {
// R0 is fairly useless (can't be operand 1 of an addi or the base ptr
// of a load) so, free up S1 for use by briefly saving its contents in the
// return address slot of my caller's frame
ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(S1), A(FP), IC(STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
Offset offset = Entrypoints.stackLimitField.getOffset();
if (VM.VerifyAssertions)
VM._assert(fits(offset, 16));
ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S1), A(phys.getTR()), IC(PPCMaskLower16(offset))));
ptr.insertBefore(MIR_Binary.create(PPC_ADDI, A(R0), A(S1), IC(frameSize)));
ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S1), A(FP), IC(STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
// Mutate the Prologue holder instruction into the trap
MIR_Trap.mutate(ptr, PPC_TAddr, PowerPCTrapOperand.LESS(), A(FP), A(R0), TrapCodeOperand.StackOverflow());
// advance ptr because we want the remaining instructions to come after
// the trap
ptr = ptr.nextInstructionInCodeOrder();
} else {
// no stack overflow test, so we must remove the IR_Prologue instruction
Instruction next = ptr.nextInstructionInCodeOrder();
ptr.remove();
ptr = next;
}
// Buy stack frame, save LR, caller's FP
ptr.insertBefore(MIR_Move.create(PPC_MFSPR, A(R0), A(phys.getLR())));
ptr.insertBefore(MIR_StoreUpdate.create(PPC_STAddrU, A(FP), A(FP), IC(-frameSize)));
ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(R0), A(FP), IC(frameSize + STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
// Store cmid
int cmid = ir.compiledMethod.getId();
if (cmid <= 0x7fff) {
ptr.insertBefore(MIR_Unary.create(PPC_LDI, I(R0), IC(cmid)));
} else {
ptr.insertBefore(MIR_Unary.create(PPC_LDIS, I(R0), IC(cmid >>> 16)));
ptr.insertBefore(MIR_Binary.create(PPC_ORI, I(R0), I(R0), IC(cmid & 0xffff)));
}
ptr.insertBefore(MIR_Store.create(PPC_STW, I(R0), A(FP), IC(STACKFRAME_METHOD_ID_OFFSET.toInt())));
// Now save the volatile/nonvolatile registers
if (ir.compiledMethod.isSaveVolatile()) {
saveVolatiles(ptr);
}
saveNonVolatiles(ptr);
// Threadswitch
if (yp) {
Offset offset = Entrypoints.takeYieldpointField.getOffset();
if (VM.VerifyAssertions)
VM._assert(fits(offset, 16));
ptr.insertBefore(MIR_Load.create(PPC_LInt, I(R0), A(TR), IC(PPCMaskLower16(offset))));
ptr.insertBefore(MIR_Binary.create(PPC_CMPI, I(TSR), I(R0), IC(0)));
}
}
use of org.jikesrvm.compilers.opt.ir.Instruction 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.Instruction in project JikesRVM by JikesRVM.
the class EnterSSA method removeUnreachableOperands.
@SuppressWarnings("unused")
private void removeUnreachableOperands(HashSet<Instruction> scalarPhis) {
for (Instruction phi : scalarPhis) {
boolean didSomething = true;
while (didSomething) {
didSomething = false;
for (int j = 0; j < Phi.getNumberOfValues(phi); j++) {
Operand v = Phi.getValue(phi, j);
if (v instanceof UnreachableOperand) {
// rewrite the phi instruction to remove the unreachable
// operand
didSomething = true;
Instruction tmpPhi = phi.copyWithoutLinks();
Phi.mutate(phi, PHI, Phi.getResult(tmpPhi), Phi.getNumberOfValues(phi) - 1);
int m = 0;
for (int k = 0; k < Phi.getNumberOfValues(phi); k++) {
if (k == j)
continue;
Phi.setValue(phi, m, Phi.getValue(tmpPhi, k));
Phi.setPred(phi, m, Phi.getPred(tmpPhi, k));
m++;
}
}
}
}
}
}
use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class EnterSSA method makePhiInstruction.
/**
* Create a phi-function instruction
*
* @param r the symbolic register
* @param bb the basic block holding the new phi function
* @return the instruction r = PHI null,null,..,null
*/
private Instruction makePhiInstruction(Register r, BasicBlock bb) {
int n = bb.getNumberOfIn();
Enumeration<BasicBlock> in = bb.getIn();
TypeReference type = null;
Instruction s = Phi.create(PHI, new RegisterOperand(r, type), n);
for (int i = 0; i < n; i++) {
RegisterOperand junk = new RegisterOperand(r, type);
Phi.setValue(s, i, junk);
BasicBlock pred = in.nextElement();
Phi.setPred(s, i, new BasicBlockOperand(pred));
}
s.setSourcePosition(SSA_SYNTH_BCI, ir.getGc().getInlineSequence());
return s;
}
use of org.jikesrvm.compilers.opt.ir.Instruction in project JikesRVM by JikesRVM.
the class EnterSSA method rectifyPhiTypes.
/*
* Compute type information for operands in each phi instruction.
*
* PRECONDITION: Def-use chains computed.
* SIDE EFFECT: empties the scalarPhis set
*/
private void rectifyPhiTypes() {
if (DEBUG)
System.out.println("Rectify phi types.");
removeAllUnreachablePhis(scalarPhis);
int noRehashCapacity = (int) (scalarPhis.size() * 1.5f);
HashMap<Instruction, PhiTypeInformation> phiTypes = new HashMap<Instruction, PhiTypeInformation>(noRehashCapacity);
while (!scalarPhis.isEmpty()) {
boolean didSomething = false;
for (Iterator<Instruction> i = scalarPhis.iterator(); i.hasNext(); ) {
Instruction phi = i.next();
phiTypes.put(phi, PhiTypeInformation.NO_NULL_TYPE);
if (DEBUG)
System.out.println("PHI: " + phi);
TypeReference meet = meetPhiType(phi, phiTypes);
if (DEBUG)
System.out.println("MEET: " + meet);
if (meet != null) {
didSomething = true;
if (phiTypes.get(phi) == PhiTypeInformation.NO_NULL_TYPE)
i.remove();
RegisterOperand result = (RegisterOperand) Phi.getResult(phi);
result.setType(meet);
for (Enumeration<RegisterOperand> e = DefUse.uses(result.getRegister()); e.hasMoreElements(); ) {
RegisterOperand rop = e.nextElement();
if (rop.getType() != meet) {
rop.clearPreciseType();
rop.setType(meet);
}
}
}
}
if (!didSomething) {
// iteration has bottomed out.
return;
}
}
}
Aggregations