use of org.jikesrvm.compilers.opt.ir.operand.RegisterOperand in project JikesRVM by JikesRVM.
the class CallingConvention method countFPRParams.
private static int countFPRParams(Instruction call) {
int result = 0;
// walk over the parameters
int numParams = MIR_Call.getNumberOfParams(call);
for (int i = 0; i < numParams; i++) {
Operand param = MIR_Call.getParam(call, i);
if (param.isRegister()) {
RegisterOperand symb = (RegisterOperand) param;
if (symb.getType().isFloatingPointType()) {
result++;
}
}
}
return result;
}
use of org.jikesrvm.compilers.opt.ir.operand.RegisterOperand in project JikesRVM by JikesRVM.
the class CallingConvention method saveNonvolatilesBeforeSysCall.
/**
* Save all nonvolatile registers before a syscall.
* We do this in case the sys call does not respect our
* register conventions.<p>
*
* We save/restore all nonvolatiles and the PR, whether
* or not this routine uses them. This may be a tad inefficient, but if
* you're making a system call, you probably don't care.
*
* @param call the sys call
* @param ir the IR that contains the call
*/
static void saveNonvolatilesBeforeSysCall(Instruction call, IR ir) {
GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
StackManager sm = (StackManager) ir.stackManager;
// get the offset into the stack frame of where to stash the first
// nonvolatile for this case.
int location = sm.getOffsetForSysCall();
// save each non-volatile
for (Enumeration<Register> e = phys.enumerateNonvolatileGPRs(); e.hasMoreElements(); ) {
Register r = e.nextElement();
Operand M = new StackLocationOperand(true, -location, (byte) WORDSIZE);
call.insertBefore(MIR_Move.create(IA32_MOV, M, new RegisterOperand(r, wordType)));
location += WORDSIZE;
}
// save the thread register
Operand M = new StackLocationOperand(true, -location, (byte) WORDSIZE);
call.insertBefore(MIR_Move.create(IA32_MOV, M, ir.regpool.makeTROp()));
// save the JTOC, if present
if (JTOC_REGISTER != null) {
location += WORDSIZE;
Operand jtocSave = new StackLocationOperand(true, -location, (byte) WORDSIZE);
call.insertBefore(MIR_Move.create(IA32_MOV, jtocSave, ir.regpool.makeTocOp()));
}
}
use of org.jikesrvm.compilers.opt.ir.operand.RegisterOperand in project JikesRVM by JikesRVM.
the class MIRSplitRanges method findOrCreateTemp.
/**
* Finds or creates a temporary register to cache a symbolic register.
*
* @param rOp the symbolic register operand
* @param map a mapping from symbolics to temporaries
* @param ir the governing IR
* @return a register operand to cache the symbolic register
*/
private static RegisterOperand findOrCreateTemp(RegisterOperand rOp, java.util.HashMap<Register, Register> map, IR ir) {
Register tReg = map.get(rOp.getRegister());
if (tReg == null) {
RegisterOperand tOp = ir.regpool.makeTemp(rOp.getType());
map.put(rOp.getRegister(), tOp.getRegister());
return tOp;
} else {
return new RegisterOperand(tReg, rOp.getType());
}
}
use of org.jikesrvm.compilers.opt.ir.operand.RegisterOperand 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;
}
}
}
}
use of org.jikesrvm.compilers.opt.ir.operand.RegisterOperand in project JikesRVM by JikesRVM.
the class StackManager method saveFloatingPointState.
/**
* Insert code into the prologue to save the floating point state.
*
* @param inst the first instruction after the prologue.
*/
private void saveFloatingPointState(Instruction inst) {
if (SSE2_FULL) {
GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
for (int i = 0; i < 8; i++) {
inst.insertBefore(MIR_Move.create(IA32_MOVQ, new StackLocationOperand(true, -fsaveLocation + (i * BYTES_IN_DOUBLE), BYTES_IN_DOUBLE), new RegisterOperand(phys.getFPR(i), TypeReference.Double)));
}
} else {
Operand M = new StackLocationOperand(true, -fsaveLocation, 4);
inst.insertBefore(MIR_FSave.create(IA32_FNSAVE, M));
}
}
Aggregations