use of org.jikesrvm.compilers.opt.ir.operand.MemoryOperand in project JikesRVM by JikesRVM.
the class ComplexLIR2MIRExpansion method double_2int.
private static Instruction double_2int(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 d2i or
// branches to the maxint/NaN case
// 2: a block to perform a regular d2i
// 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 d2iBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, d2iBB);
// Move the maxint value and the value into registers and compare and
// branch if they are <= or unordered. NB we don't use a memory operand as
// that would require 2 jccs
RegisterOperand result = Unary.getResult(s);
RegisterOperand value = Unary.getVal(s).asRegister();
MemoryOperand maxint = BURS_Helpers.loadFromJTOC(ir, Entrypoints.maxintField.getOffset(), (byte) 8);
RegisterOperand maxintReg = ir.regpool.makeTempFloat();
s.insertBefore(CPOS(s, MIR_Move.create(IA32_MOVSD, maxintReg, maxint)));
MIR_Compare.mutate(s, IA32_UCOMISD, maxintReg.copyRO(), value);
testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.LLE(), nanTestBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
testBB.insertOut(d2iBB);
testBB.insertOut(nanTestBB);
// Convert float to int knowing that if the value is < min int the Intel
// unspecified result is min int
d2iBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_CVTTSD2SI, result.copyRO(), value.copy())));
d2iBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
d2iBB.insertOut(nextBB);
// Did the compare find a NaN or a maximum integer?
nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.PE(), nanBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
nanTestBB.insertOut(nanBB);
nanTestBB.insertOut(maxintBB);
// Value was >= max integer
maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, result.copyRO(), IC(Integer.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(), IC(0))));
nanBB.insertOut(nextBB);
return nextInstr;
}
use of org.jikesrvm.compilers.opt.ir.operand.MemoryOperand in project JikesRVM by JikesRVM.
the class ComplexLIR2MIRExpansion method float_2int.
private static Instruction float_2int(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 f2i or
// branches to the maxint/NaN case
// 2: a block to perform a regular f2i
// 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 f2iBB = testBB.splitNodeAt(s, ir);
ir.cfg.linkInCodeOrder(testBB, f2iBB);
// Move the maxintFloat value and the value into registers and compare and
// branch if they are <= or unordered. NB we don't use a memory operand as
// that would require 2 jccs
RegisterOperand result = Unary.getResult(s).copyRO();
RegisterOperand value = Unary.getVal(s).asRegister();
MemoryOperand maxint = BURS_Helpers.loadFromJTOC(ir, Entrypoints.maxintFloatField.getOffset(), (byte) 4);
RegisterOperand maxintReg = ir.regpool.makeTempFloat();
s.insertBefore(CPOS(s, MIR_Move.create(IA32_MOVSS, maxintReg, maxint)));
MIR_Compare.mutate(s, IA32_UCOMISS, maxintReg.copyRO(), value);
testBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.LLE(), nanTestBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
testBB.insertOut(f2iBB);
testBB.insertOut(nanTestBB);
// Convert float to int knowing that if the value is < min int the Intel
// unspecified result is min int
f2iBB.appendInstruction(CPOS(s, MIR_Unary.create(IA32_CVTTSS2SI, result, value.copy())));
f2iBB.appendInstruction(CPOS(s, MIR_Branch.create(IA32_JMP, nextBB.makeJumpTarget())));
f2iBB.insertOut(nextBB);
// Did the compare find a NaN or a maximum integer?
nanTestBB.appendInstruction(CPOS(s, MIR_CondBranch.create(IA32_JCC, IA32ConditionOperand.PE(), nanBB.makeJumpTarget(), BranchProfileOperand.unlikely())));
nanTestBB.insertOut(nanBB);
nanTestBB.insertOut(maxintBB);
// Value was >= max integer
maxintBB.appendInstruction(CPOS(s, MIR_Move.create(IA32_MOV, result.copyRO(), IC(Integer.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(), IC(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 LONG_SHL.
/**
* Expansion of LONG_SHL
* @param s the instruction to expand
* @param result the result operand
* @param val1 the shifted operand
* @param val2 the shift amount operand
* @param maskWith3f should the shift operand by masked with 0x3f? This is
* default behaviour on Intel but it differs from how we combine
* shift operands in HIR
*/
protected final void LONG_SHL(Instruction s, Operand result, Operand val1, Operand val2, boolean maskWith3f) {
if (!val2.isIntConstant()) {
// the most efficient form of expanding a shift by a variable amount
// requires a branch so leave for complex operators
// NB if !maskWith3f - we assume that a mask with 0x3F was required as
// no optimizations currently exploits shift by registers of > 63
// returning 0
Binary.mutate(s, LONG_SHL, result.asRegister(), val1, val2);
EMIT(s);
} else if (result.isRegister()) {
int shift = val2.asIntConstant().value;
Register lhsReg = result.asRegister().getRegister();
Register lowlhsReg = burs.ir.regpool.getSecondReg(lhsReg);
Register rhsReg1 = val1.asRegister().getRegister();
Register lowrhsReg1 = burs.ir.regpool.getSecondReg(rhsReg1);
if (shift == 0) {
// operation is a nop.
if (!result.similar(val1)) {
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int))));
}
} else if (shift == 1) {
if (!result.similar(val1)) {
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int))));
}
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_ADD, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lowlhsReg, TypeReference.Int))));
EMIT(MIR_BinaryAcc.mutate(s, IA32_ADC, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(lhsReg, TypeReference.Int)));
} else if (shift == 2) {
// bits to shift in: tmp = lowrhsReg >> 30
Register tmp = regpool.getInteger();
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(tmp, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, new RegisterOperand(tmp, TypeReference.Int), IC(30))));
// compute top half: lhsReg = (rhsReg1 << 2) + tmp
EMIT(CPOS(s, MIR_Lea.create(IA32_LEA, new RegisterOperand(lhsReg, TypeReference.Int), MemoryOperand.BIS(new RegisterOperand(tmp, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int), (byte) 2, (byte) 4, null, null))));
// compute bottom half: lowlhsReg = lowlhsReg << 2
EMIT(CPOS(s, MIR_Lea.create(IA32_LEA, new RegisterOperand(lowlhsReg, TypeReference.Int), new // base
MemoryOperand(// base
null, // index
new RegisterOperand(lowrhsReg1, TypeReference.Int), // scale
(byte) 2, // displacement
Offset.zero(), // size
(byte) 4, // location
null, // guard
null))));
} else if (shift == 3) {
// bits to shift in: tmp = lowrhsReg >>> 29
Register tmp = regpool.getInteger();
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(tmp, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, new RegisterOperand(tmp, TypeReference.Int), IC(29))));
// compute top half: lhsReg = (rhsReg1 << 3) + tmp
EMIT(CPOS(s, MIR_Lea.create(IA32_LEA, new RegisterOperand(lhsReg, TypeReference.Int), MemoryOperand.BIS(new RegisterOperand(tmp, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int), (byte) 3, (byte) 4, null, null))));
// compute bottom half: lowlhsReg = lowlhsReg << 3
EMIT(CPOS(s, MIR_Lea.create(IA32_LEA, new RegisterOperand(lowlhsReg, TypeReference.Int), new // base
MemoryOperand(// base
null, // index
new RegisterOperand(lowrhsReg1, TypeReference.Int), // scale
(byte) 3, // displacement
Offset.zero(), // size
(byte) 4, // location
null, // guard
null))));
} else if (shift < 32) {
if (!result.similar(val1)) {
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(rhsReg1, TypeReference.Int))));
}
// bits to shift in: tmp = lowrhsReg >>> (32 - shift)
Register tmp = regpool.getInteger();
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(tmp, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SHR, new RegisterOperand(tmp, TypeReference.Int), IC(32 - shift))));
// compute top half: lhsReg = (lhsReg1 << shift) | tmp
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SHL, new RegisterOperand(lhsReg, TypeReference.Int), IC(shift))));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_OR, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(tmp, TypeReference.Int))));
// compute bottom half: lowlhsReg = lowlhsReg << shift
if (!result.similar(val1)) {
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
}
EMIT(MIR_BinaryAcc.mutate(s, IA32_SHL, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(shift)));
} else if (shift == 32) {
// lhsReg = lowrhsReg1
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
// lowlhsReg = 0
EMIT(MIR_Move.mutate(s, IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(0)));
} else if (shift == 33) {
// lhsReg = lowrhsReg1 << 1
EMIT(CPOS(s, MIR_Lea.create(IA32_LEA, new RegisterOperand(lhsReg, TypeReference.Int), new // base
MemoryOperand(// base
null, // index
new RegisterOperand(lowrhsReg1, TypeReference.Int), // scale
(byte) 1, // displacement
Offset.zero(), // size
(byte) 4, // location
null, // guard
null))));
// lowlhsReg = 0
EMIT(MIR_Move.mutate(s, IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(0)));
} else if (shift == 34) {
// lhsReg = lowrhsReg1 << 2
EMIT(CPOS(s, MIR_Lea.create(IA32_LEA, new RegisterOperand(lhsReg, TypeReference.Int), new // base
MemoryOperand(// base
null, // index
new RegisterOperand(lowrhsReg1, TypeReference.Int), // scale
(byte) 2, // displacement
Offset.zero(), // size
(byte) 4, // location
null, // guard
null))));
// lowlhsReg = 0
EMIT(MIR_Move.mutate(s, IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(0)));
} else if (shift == 35) {
// lhsReg = lowrhsReg1 << 3
EMIT(CPOS(s, MIR_Lea.create(IA32_LEA, new RegisterOperand(lhsReg, TypeReference.Int), new // base
MemoryOperand(// base
null, // index
new RegisterOperand(lowrhsReg1, TypeReference.Int), // scale
(byte) 3, // displacement
Offset.zero(), // size
(byte) 4, // location
null, // guard
null))));
// lowlhsReg = 0
EMIT(MIR_Move.mutate(s, IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(0)));
} else {
if ((maskWith3f) || (shift < 64)) {
// lhsReg = lowrhsReg1 << ((shift - 32) & 0x1f)
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), new RegisterOperand(lowrhsReg1, TypeReference.Int))));
EMIT(CPOS(s, MIR_BinaryAcc.create(IA32_SHL, new RegisterOperand(lhsReg, TypeReference.Int), IC((shift - 32) & 0x1F))));
// lowlhsReg = 0
EMIT(MIR_Move.mutate(s, IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(0)));
} else {
// lhsReg = 0
EMIT(CPOS(s, MIR_Move.create(IA32_MOV, new RegisterOperand(lhsReg, TypeReference.Int), IC(0))));
// lowlhsReg = 0
EMIT(MIR_Move.mutate(s, IA32_MOV, new RegisterOperand(lowlhsReg, TypeReference.Int), IC(0)));
}
}
} else {
throw new OptimizingCompilerException("BURS_Helpers", "unexpected parameters: " + result + "=" + val1 + "<<" + val2);
}
}
use of org.jikesrvm.compilers.opt.ir.operand.MemoryOperand in project JikesRVM by JikesRVM.
the class FinalMIRExpansion method expandFmov.
/**
* expand an FMOV pseudo-insruction.
*
* @param s the instruction to expand
* @param phys controlling physical register set
*/
private static void expandFmov(Instruction s, PhysicalRegisterSet phys) {
Operand result = MIR_Move.getClearResult(s);
Operand value = MIR_Move.getClearValue(s);
if (result.isRegister() && value.isRegister()) {
if (result.similar(value)) {
// eliminate useless move
s.remove();
} else {
int i = PhysicalRegisterSet.getFPRIndex(result.asRegister().getRegister());
int j = PhysicalRegisterSet.getFPRIndex(value.asRegister().getRegister());
if (j == 0) {
// We have FMOV Fi, F0
// Expand as:
// FST F(i) (copy F0 to F(i))
MIR_Move.mutate(s, IA32_FST, D(phys.getFPR(i)), D(phys.getFPR(0)));
} else {
// We have FMOV Fi, Fj
// Expand as:
// FLD Fj (push Fj on FP stack).
// FSTP F(i+1) (copy F0 to F(i+1) and then pop register stack)
s.insertBefore(MIR_Move.create(IA32_FLD, D(phys.getFPR(0)), value));
MIR_Move.mutate(s, IA32_FSTP, D(phys.getFPR(i + 1)), D(phys.getFPR(0)));
}
}
} else if (value instanceof MemoryOperand) {
if (result instanceof MemoryOperand) {
// We have FMOV M1, M2
// Expand as:
// FLD M1 (push M1 on FP stack).
// FSTP M2 (copy F0 to M2 and pop register stack)
s.insertBefore(MIR_Move.create(IA32_FLD, D(phys.getFPR(0)), value));
MIR_Move.mutate(s, IA32_FSTP, result, D(phys.getFPR(0)));
} else {
// FSTP F(i+1) (copy F0 to F(i+1) and pop register stack)
if (VM.VerifyAssertions)
VM._assert(result.isRegister());
int i = PhysicalRegisterSet.getFPRIndex(result.asRegister().getRegister());
s.insertBefore(MIR_Move.create(IA32_FLD, D(phys.getFPR(0)), value));
MIR_Move.mutate(s, IA32_FSTP, D(phys.getFPR(i + 1)), D(phys.getFPR(0)));
}
} else {
// We have FMOV M, Fi
if (VM.VerifyAssertions)
VM._assert(value.isRegister());
if (VM.VerifyAssertions) {
VM._assert(result instanceof MemoryOperand);
}
int i = PhysicalRegisterSet.getFPRIndex(value.asRegister().getRegister());
if (i != 0) {
// Expand as:
// FLD Fi (push Fi on FP stack).
// FSTP M (store F0 in M and pop register stack);
s.insertBefore(MIR_Move.create(IA32_FLD, D(phys.getFPR(0)), value));
MIR_Move.mutate(s, IA32_FSTP, result, D(phys.getFPR(0)));
} else {
// Expand as:
// FST M (store F0 in M);
MIR_Move.mutate(s, IA32_FST, result, value);
}
}
}
use of org.jikesrvm.compilers.opt.ir.operand.MemoryOperand in project JikesRVM by JikesRVM.
the class Instruction method putOperand.
/**
* NOTE: It is incorrect to use putOperand with a constant argument
* outside of the automatically generated code in Operators.
* The only approved direct use of getOperand is in a loop over
* some subset of an instruction's operands (all of them, all uses, all defs).
*
* @param i which operand to set
* @param op the operand to set it to
*/
public void putOperand(int i, Operand op) {
if (op == null) {
ops[i] = null;
} else {
// Operands that are already associated with this
// instruction may occur here (e.g. during calls
// to mutate(..) ). Those don't need any changes.
Instruction instHandle = op.instruction;
if (instHandle != this && instHandle != null) {
if (VM.VerifyAssertions) {
String msg = "Operand " + op + " was supposed to be inserted into " + this + " but still points to " + op.instruction + " ! \nPossible " + " solutions to this problem include calling .copy() on the " + " operand (e.g. op.copy()) or using getClear* methods instead " + " (e.g. Load.getClearResult(..) instead of Load.getResult(..)).";
VM._assert(VM.NOT_REACHED, msg);
} else {
// Operands must not be shared to make sure that correctness is maintained.
// Ensure this by inserting a copy to paper over the mistake that the caller
// made.
op = outOfLineCopy(op);
}
}
op.instruction = this;
ops[i] = op;
if (op instanceof MemoryOperand) {
MemoryOperand mOp = op.asMemory();
op = mOp.loc;
if (op != null)
op.instruction = this;
op = mOp.guard;
if (op != null)
op.instruction = this;
op = mOp.base;
if (op != null)
op.instruction = this;
op = mOp.index;
if (op != null)
op.instruction = this;
}
}
}
Aggregations