use of org.jikesrvm.compilers.opt.ir.operand.MemoryOperand in project JikesRVM by JikesRVM.
the class StackManagerTest method instructionsWithMemoryOperandsAlwaysNeedScratch.
@Test
public void instructionsWithMemoryOperandsAlwaysNeedScratch() {
RegisterOperand result = new RegisterOperand(createRegister(), TypeReference.Int);
MemoryOperand value = MemoryOperand.B(new RegisterOperand(createRegister(), TypeReference.Int), (byte) 4, null, null);
Instruction scratchFreeMove = MIR_Move.create(IA32_MOV, result, value);
assertTrue(stackManager.needScratch(result.getRegister(), scratchFreeMove));
}
use of org.jikesrvm.compilers.opt.ir.operand.MemoryOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method FPR_2INT.
/**
* Expansion of FLOAT_2INT and DOUBLE_2INT, using the FIST instruction. This
* expansion does some boolean logic and conditional moves in order to avoid
* changing the floating-point rounding mode or inserting branches. Other
* expansions are possible, and may be better?
*
* @param s the instruction to expand
* @param result the result operand
* @param value the second operand
*/
protected final void FPR_2INT(Instruction s, RegisterOperand result, Operand value) {
MemoryOperand M;
// and in 'strict' IEEE mode.
if (value instanceof MemoryOperand) {
// value is in memory, all we have to do is load it
EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), value)));
} else {
// we must have a store/load sequence to cause IEEE rounding.
if (value instanceof BURSManagedFPROperand) {
if (VM.VerifyAssertions) {
opt_assert(value.similar(myFP0()));
}
EMIT(CPOS(s, MIR_Move.create(IA32_FSTP, MO_CONV(DW), value)));
EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), MO_CONV(DW))));
} else {
EMIT(CPOS(s, MIR_Move.create(IA32_FMOV, MO_CONV(DW), value)));
EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), MO_CONV(DW))));
}
}
// FP Stack: myFP0 = value
EMIT(CPOS(s, MIR_Move.create(IA32_FIST, MO_CONV(DW), myFP0())));
// MO_CONV now holds myFP0 converted to an integer (round-toward nearest)
// FP Stack: myFP0 == value
// isPositive == 1 iff 0.0 < value
// isNegative == 1 iff 0.0 > value
Register one = regpool.getInteger();
Register isPositive = regpool.getInteger();
Register isNegative = regpool.getInteger();
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(one, TypeReference.Int), IC(1))));
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(isPositive, TypeReference.Int), IC(0))));
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(isNegative, TypeReference.Int), IC(0))));
EMIT(CPOS(s, MIR_Nullary.create(IA32_FLDZ, myFP0())));
// FP Stack: myFP0 = 0.0; myFP1 = value
EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())));
// FP Stack: myFP0 = value
EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, new RegisterOperand(isPositive, TypeReference.Int), new RegisterOperand(one, TypeReference.Int), IA32ConditionOperand.LLT())));
EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, new RegisterOperand(isNegative, TypeReference.Int), new RegisterOperand(one, TypeReference.Int), IA32ConditionOperand.LGT())));
EMIT(CPOS(s, MIR_Move.create(IA32_FILD, myFP0(), MO_CONV(DW))));
// FP Stack: myFP0 = round(value), myFP1 = value
// addee = 1 iff round(x) < x
// subtractee = 1 iff round(x) > x
Register addee = regpool.getInteger();
Register subtractee = regpool.getInteger();
EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())));
// FP Stack: myFP0 = value
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(addee, TypeReference.Int), IC(0))));
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(subtractee, TypeReference.Int), IC(0))));
EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, new RegisterOperand(addee, TypeReference.Int), new RegisterOperand(one, TypeReference.Int), IA32ConditionOperand.LLT())));
EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, new RegisterOperand(subtractee, TypeReference.Int), new RegisterOperand(one, TypeReference.Int), IA32ConditionOperand.LGT())));
// Now a little tricky part.
// We will add 1 iff isNegative and x > round(x)
// We will subtract 1 iff isPositive and x < round(x)
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_AND, new RegisterOperand(addee, TypeReference.Int), new RegisterOperand(isNegative, TypeReference.Int))));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_AND, new RegisterOperand(subtractee, TypeReference.Int), new RegisterOperand(isPositive, TypeReference.Int))));
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, result.copy(), MO_CONV(DW))));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_ADD, result.copy(), new RegisterOperand(addee, TypeReference.Int))));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SUB, result.copy(), new RegisterOperand(subtractee, TypeReference.Int))));
// Compare myFP0 with (double)Integer.MAX_VALUE
M = loadFromJTOC(burs.ir, Entrypoints.maxintField.getOffset(), QW);
EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), M)));
// FP Stack: myFP0 = (double)Integer.MAX_VALUE; myFP1 = value
EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())));
// FP Stack: myFP0 = value
// If MAX_VALUE < value, then result := MAX_INT
Register maxInt = regpool.getInteger();
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(maxInt, TypeReference.Int), IC(Integer.MAX_VALUE))));
EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, result.copy(), new RegisterOperand(maxInt, TypeReference.Int), IA32ConditionOperand.LLT())));
// Compare myFP0 with (double)Integer.MIN_VALUE
M = MemoryOperand.D(Magic.getTocPointer().plus(Entrypoints.minintField.getOffset()), QW, null, null);
EMIT(CPOS(s, MIR_Move.create(IA32_FLD, myFP0(), M)));
// FP Stack: myFP0 = (double)Integer.MIN_VALUE; myFP1 = value
EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP1())));
// FP Stack: myFP0 = value
// If MIN_VALUE > value, then result := MIN_INT
Register minInt = regpool.getInteger();
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(minInt, TypeReference.Int), IC(Integer.MIN_VALUE))));
EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, result.copy(), new RegisterOperand(minInt, TypeReference.Int), IA32ConditionOperand.LGT())));
// Set condition flags: set PE iff myFP0 is a NaN
EMIT(CPOS(s, MIR_Compare.create(IA32_FCOMIP, myFP0(), myFP0())));
// FP Stack: back to original level (all BURS managed slots freed)
// If FP0 was classified as a NaN, then result := 0
Register zero = regpool.getInteger();
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(zero, TypeReference.Int), IC(0))));
EMIT(CPOS(s, MIR_CondMove.create(IA32_CMOV, result.copy(), new RegisterOperand(zero, TypeReference.Int), IA32ConditionOperand.PE())));
}
use of org.jikesrvm.compilers.opt.ir.operand.MemoryOperand in project JikesRVM by JikesRVM.
the class ComplexLIR2MIRExpansion method double_2long.
private static Instruction double_2long(Instruction s, IR ir) {
Instruction nextInstr = s.nextInstructionInCodeOrder();
while (Label.conforms(nextInstr) || BBend.conforms(nextInstr)) {
nextInstr = nextInstr.nextInstructionInCodeOrder();
}
// we need 6 basic blocks (in code order)
// 1: the current block that does a test to see if this is a regular f2l or
// branches to the maxint/NaN case
// 2: a block to perform a regular f2l
// 3: a block to test for NaN
// 4: a block to perform give maxint
// 5: a block to perform NaN
// 6: the next basic block
BasicBlock testBB = s.getBasicBlock();
BasicBlock nextBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, nextBB);
BasicBlock nanBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, nanBB);
BasicBlock maxintBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, maxintBB);
BasicBlock nanTestBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, nanTestBB);
BasicBlock d2lBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, d2lBB);
// branch if they are <= or unordered.
if (VM.BuildFor32Addr) {
RegisterOperand resultHi = Unary.getResult(s).copyRO();
resultHi.setType(TypeReference.Int);
RegisterOperand resultLo = new RegisterOperand(ir.regpool.getSecondReg(resultHi.getRegister()), TypeReference.Int);
RegisterOperand value = Unary.getVal(s).asRegister().copyRO();
RegisterOperand cw = ir.regpool.makeTempInt();
MemoryOperand maxlong = BURS_Helpers.loadFromJTOC(ir, Entrypoints.maxlongField.getOffset(), (byte) 8);
RegisterOperand st0 = new RegisterOperand(phys(ir).getST0(), TypeReference.Double);
RegisterOperand st1 = new RegisterOperand(phys(ir).getST1(), TypeReference.Double);
int offset = -ir.stackManager.allocateSpaceForConversion();
StackLocationOperand slLo = new StackLocationOperand(true, offset, 4);
StackLocationOperand slHi = new StackLocationOperand(true, offset + 4, 4);
StackLocationOperand sl = new StackLocationOperand(true, offset, 8);
MemoryOperand scratchLo = new MemoryOperand(ir.regpool.makeTROp(), null, (byte) 0, Entrypoints.scratchStorageField.getOffset(), (byte) 4, new LocationOperand(Entrypoints.scratchStorageField), null);
MemoryOperand scratchHi = new MemoryOperand(ir.regpool.makeTROp(), null, (byte) 0, Entrypoints.scratchStorageField.getOffset().plus(4), (byte) 4, new LocationOperand(Entrypoints.scratchStorageField), null);
s.insertBefore(CPOS(s, MIR_Move.create(IA32_MOVSD, sl, value)));
s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0, sl.copy())));
s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0.copyRO(), maxlong)));
MIR_Compare.mutate(s, IA32_FUCOMIP, st0.copyRO(), st1);
testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.LLE(), nanTestBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
testBB.insertOut(d2lBB);
testBB.insertOut(nanTestBB);
// Convert double to long knowing that if the value is < min long the Intel
// unspecified result is min long
// TODO: this would be a lot simpler and faster with SSE3's FISTTP instruction
d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FNSTCW, scratchLo.copy())));
d2lBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_MOVZX__W, cw, scratchLo.copy())));
d2lBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_OR, cw.copyRO(), IC(0xC00))));
d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, scratchHi, cw.copyRO())));
d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchHi.copy())));
d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FISTP, sl.copy(), st0.copyRO())));
d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchLo.copy())));
d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo, slLo)));
d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi, slHi)));
d2lBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
d2lBB.insertOut(nextBB);
// Did the compare find a NaN or a maximum integer?
nanTestBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FSTP, st0.copyRO(), st0.copyRO())));
nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.PE(), nanBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
nanTestBB.insertOut(nanBB);
nanTestBB.insertOut(maxintBB);
// Value was >= max long
maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo.copyRO(), IC((int) Long.MAX_VALUE))));
maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi.copyRO(), IC((int) (Long.MAX_VALUE >>> 32)))));
maxintBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
maxintBB.insertOut(nextBB);
// In case of NaN result is 0
nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultLo.copyRO(), IC(0))));
nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, resultHi.copyRO(), IC(0))));
nanBB.insertOut(nextBB);
return nextInstr;
} else {
RegisterOperand result = Unary.getResult(s).copyRO();
RegisterOperand value = Unary.getVal(s).asRegister().copyRO();
RegisterOperand cw = ir.regpool.makeTempInt();
MemoryOperand maxlong = BURS_Helpers.loadFromJTOC(ir, Entrypoints.maxlongField.getOffset(), (byte) 8);
RegisterOperand st0 = new RegisterOperand(phys(ir).getST0(), TypeReference.Double);
RegisterOperand st1 = new RegisterOperand(phys(ir).getST1(), TypeReference.Double);
int offset = -ir.stackManager.allocateSpaceForConversion();
StackLocationOperand sl = new StackLocationOperand(true, offset, 8);
MemoryOperand scratchLo = new MemoryOperand(ir.regpool.makeTROp(), null, (byte) 0, Entrypoints.scratchStorageField.getOffset(), (byte) 4, new LocationOperand(Entrypoints.scratchStorageField), null);
MemoryOperand scratchHi = new MemoryOperand(ir.regpool.makeTROp(), null, (byte) 0, Entrypoints.scratchStorageField.getOffset().plus(4), (byte) 4, new LocationOperand(Entrypoints.scratchStorageField), null);
s.insertBefore(CPOS(s, MIR_Move.create(IA32_MOVSD, sl, value)));
s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0, sl.copy())));
s.insertBefore(CPOS(s, MIR_Move.create(IA32_FLD, st0.copyRO(), maxlong)));
MIR_Compare.mutate(s, IA32_FUCOMIP, st0.copyRO(), st1);
testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.LLE(), nanTestBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
testBB.insertOut(d2lBB);
testBB.insertOut(nanTestBB);
// Convert double to long knowing that if the value is < min long the Intel
// unspecified result is min long
// TODO: this would be a lot simpler and faster with SSE3's FISTTP instruction
d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FNSTCW, scratchLo.copy())));
d2lBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_MOVZX__W, cw, scratchLo.copy())));
d2lBB.appendInstruction(CPOS(s, MIR_BinaryAcc.create(IA32_OR, cw.copyRO(), IC(0xC00))));
d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, scratchHi, cw.copyRO())));
d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchHi.copy())));
d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FISTP, sl.copy(), st0.copyRO())));
d2lBB.appendInstruction(CPOS(s, MIR_UnaryNoRes.create(IA32_FLDCW, scratchLo.copy())));
d2lBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, result, sl.copy())));
d2lBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
d2lBB.insertOut(nextBB);
// Did the compare find a NaN or a maximum integer?
nanTestBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_FSTP, st0.copyRO(), st0.copyRO())));
nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.PE(), nanBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
nanTestBB.insertOut(nanBB);
nanTestBB.insertOut(maxintBB);
// Value was >= max long
maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, result.copyRO(), LC(Long.MAX_VALUE))));
maxintBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
maxintBB.insertOut(nextBB);
// In case of NaN result is 0
nanBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, result.copyRO(), LC(0))));
nanBB.insertOut(nextBB);
return nextInstr;
}
}
use of org.jikesrvm.compilers.opt.ir.operand.MemoryOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method loadFromJTOC.
/**
* Create memory operand to load from a given jtoc offset
*
* @param ir the IR to use for getting a JTOC reg operand, if available
* @param offset location in JTOC
* @param size of value in JTOC
* @return created memory operand
*/
static MemoryOperand loadFromJTOC(IR ir, Offset offset, byte size) {
LocationOperand loc = new LocationOperand(offset);
Operand guard = TG();
if (JTOC_REGISTER == null) {
return MemoryOperand.D(Magic.getTocPointer().plus(offset), size, loc, guard);
} else {
return MemoryOperand.BD(ir.regpool.makeTocOp().asRegister(), offset, size, loc, guard);
}
}
use of org.jikesrvm.compilers.opt.ir.operand.MemoryOperand in project JikesRVM by JikesRVM.
the class SimpleSpillCost method calculate.
@Override
void calculate(IR ir) {
final double moveFactor = ir.options.REGALLOC_SIMPLE_SPILL_COST_MOVE_FACTOR;
final double memoryOperandFactor = ir.options.REGALLOC_SIMPLE_SPILL_COST_MEMORY_OPERAND_FACTOR;
for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements(); ) {
BasicBlock bb = e.nextElement();
for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements(); ) {
Instruction s = ie.nextElement();
double factor = (bb.getInfrequent()) ? 0.0 : 1.0;
if (s.isMove()) {
factor *= moveFactor;
}
double baseFactor = factor;
if (hasBadSizeMemoryOperand(s)) {
baseFactor *= memoryOperandFactor;
}
// first deal with non-memory operands
for (Enumeration<Operand> e2 = s.getRootOperands(); e2.hasMoreElements(); ) {
Operand op = e2.nextElement();
if (op.isRegister()) {
Register r = op.asRegister().getRegister();
if (r.isSymbolic()) {
update(r, baseFactor);
}
}
}
// now handle memory operands
factor *= memoryOperandFactor;
for (Enumeration<Operand> e2 = s.getMemoryOperands(); e2.hasMoreElements(); ) {
MemoryOperand M = (MemoryOperand) e2.nextElement();
if (M.base != null) {
Register r = M.base.getRegister();
if (r.isSymbolic()) {
update(r, factor);
}
}
if (M.index != null) {
Register r = M.index.getRegister();
if (r.isSymbolic()) {
update(r, factor);
}
}
}
}
}
}
Aggregations