use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class ExpandRuntimeServices method perform.
/**
* Given an HIR, expand operators that are implemented as calls to
* runtime service methods. This method should be called as one of the
* first steps in lowering HIR into LIR.
*
* @param ir The HIR to expand
*/
@Override
public void perform(IR ir) {
// resync generation context -- yuck...
ir.getGc().resync();
for (Instruction inst = ir.firstInstructionInCodeOrder(); inst != null; inst = next) {
next = inst.nextInstructionInCodeOrder();
int opcode = inst.getOpcode();
switch(opcode) {
case NEW_opcode:
{
TypeOperand Type = New.getClearType(inst);
RVMClass cls = (RVMClass) Type.getVMType();
IntConstantOperand hasFinalizer = IRTools.IC(cls.hasFinalizer() ? 1 : 0);
RVMMethod callSite = inst.position().getMethod();
IntConstantOperand allocator = IRTools.IC(MemoryManager.pickAllocator(cls, callSite));
IntConstantOperand align = IRTools.IC(ObjectModel.getAlignment(cls));
IntConstantOperand offset = IRTools.IC(ObjectModel.getOffsetForAlignment(cls, false));
Operand tib = ConvertToLowLevelIR.getTIB(inst, ir, Type);
if (VM.BuildForIA32 && VM.runningVM) {
// shield BC2IR from address constants
RegisterOperand tmp = ir.regpool.makeTemp(TypeReference.TIB);
inst.insertBefore(Move.create(REF_MOVE, tmp, tib));
tib = tmp.copyRO();
}
IntConstantOperand site = IRTools.IC(MemoryManager.getAllocationSite(true));
RVMMethod target = Entrypoints.resolvedNewScalarMethod;
Call.mutate7(inst, CALL, New.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), IRTools.IC(cls.getInstanceSize()), tib, hasFinalizer, allocator, align, offset, site);
next = inst.prevInstructionInCodeOrder();
if (ir.options.H2L_INLINE_NEW) {
if (inst.getBasicBlock().getInfrequent())
container.counter1++;
container.counter2++;
if (!ir.options.FREQ_FOCUS_EFFORT || !inst.getBasicBlock().getInfrequent()) {
inline(inst, ir);
}
}
}
break;
case NEW_UNRESOLVED_opcode:
{
int typeRefId = New.getType(inst).getTypeRef().getId();
RVMMethod target = Entrypoints.unresolvedNewScalarMethod;
IntConstantOperand site = IRTools.IC(MemoryManager.getAllocationSite(true));
Call.mutate2(inst, CALL, New.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), IRTools.IC(typeRefId), site);
}
break;
case NEWARRAY_opcode:
{
TypeOperand Array = NewArray.getClearType(inst);
RVMArray array = (RVMArray) Array.getVMType();
Operand numberElements = NewArray.getClearSize(inst);
boolean inline = numberElements instanceof IntConstantOperand;
Operand width = IRTools.IC(array.getLogElementSize());
Operand headerSize = IRTools.IC(ObjectModel.computeArrayHeaderSize(array));
RVMMethod callSite = inst.position().getMethod();
IntConstantOperand allocator = IRTools.IC(MemoryManager.pickAllocator(array, callSite));
IntConstantOperand align = IRTools.IC(ObjectModel.getAlignment(array));
IntConstantOperand offset = IRTools.IC(ObjectModel.getOffsetForAlignment(array, false));
Operand tib = ConvertToLowLevelIR.getTIB(inst, ir, Array);
if (VM.BuildForIA32 && VM.runningVM) {
// shield BC2IR from address constants
RegisterOperand tmp = ir.regpool.makeTemp(TypeReference.TIB);
inst.insertBefore(Move.create(REF_MOVE, tmp, tib));
tib = tmp.copyRO();
}
IntConstantOperand site = IRTools.IC(MemoryManager.getAllocationSite(true));
RVMMethod target = Entrypoints.resolvedNewArrayMethod;
Call.mutate8(inst, CALL, NewArray.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), numberElements, width, headerSize, tib, allocator, align, offset, site);
next = inst.prevInstructionInCodeOrder();
if (inline && ir.options.H2L_INLINE_NEW) {
if (inst.getBasicBlock().getInfrequent())
container.counter1++;
container.counter2++;
if (!ir.options.FREQ_FOCUS_EFFORT || !inst.getBasicBlock().getInfrequent()) {
inline(inst, ir);
}
}
}
break;
case NEWARRAY_UNRESOLVED_opcode:
{
int typeRefId = NewArray.getType(inst).getTypeRef().getId();
Operand numberElements = NewArray.getClearSize(inst);
RVMMethod target = Entrypoints.unresolvedNewArrayMethod;
IntConstantOperand site = IRTools.IC(MemoryManager.getAllocationSite(true));
Call.mutate3(inst, CALL, NewArray.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), numberElements, IRTools.IC(typeRefId), site);
}
break;
case NEWOBJMULTIARRAY_opcode:
{
int dimensions = Multianewarray.getNumberOfDimensions(inst);
RVMMethod callSite = inst.position().getMethod();
int typeRefId = Multianewarray.getType(inst).getTypeRef().getId();
if (dimensions == 2) {
RVMMethod target = Entrypoints.optNew2DArrayMethod;
Call.mutate4(inst, CALL, Multianewarray.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), IRTools.IC(callSite.getId()), Multianewarray.getClearDimension(inst, 0), Multianewarray.getClearDimension(inst, 1), IRTools.IC(typeRefId));
} else {
// Step 1: Create an int array to hold the dimensions.
TypeOperand dimArrayType = new TypeOperand(RVMArray.IntArray);
RegisterOperand dimArray = ir.regpool.makeTemp(TypeReference.IntArray);
dimArray.setPreciseType();
next = NewArray.create(NEWARRAY, dimArray, dimArrayType, new IntConstantOperand(dimensions));
inst.insertBefore(next);
// Step 2: Assign the dimension values to dimArray
for (int i = 0; i < dimensions; i++) {
LocationOperand loc = new LocationOperand(TypeReference.Int);
inst.insertBefore(AStore.create(INT_ASTORE, Multianewarray.getClearDimension(inst, i), dimArray.copyD2U(), IRTools.IC(i), loc, IRTools.TG()));
}
// Step 3. Plant call to OptLinker.newArrayArray
RVMMethod target = Entrypoints.optNewArrayArrayMethod;
Call.mutate3(inst, CALL, Multianewarray.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), IRTools.IC(callSite.getId()), dimArray.copyD2U(), IRTools.IC(typeRefId));
}
}
break;
case ATHROW_opcode:
{
RVMMethod target = Entrypoints.athrowMethod;
MethodOperand methodOp = MethodOperand.STATIC(target);
// Record the fact that this is a non-returning call.
methodOp.setIsNonReturningCall(true);
Call.mutate1(inst, CALL, null, IRTools.AC(target.getOffset()), methodOp, Athrow.getClearValue(inst));
}
break;
case MONITORENTER_opcode:
{
Operand ref = MonitorOp.getClearRef(inst);
RVMType refType = ref.getType().peekType();
if (refType != null && !refType.getThinLockOffset().isMax()) {
RVMMethod target = Entrypoints.inlineLockMethod;
Call.mutate2(inst, CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), MonitorOp.getClearGuard(inst), ref, IRTools.AC(refType.getThinLockOffset()));
next = inst.prevInstructionInCodeOrder();
if (inst.getBasicBlock().getInfrequent())
container.counter1++;
container.counter2++;
if (!ir.options.FREQ_FOCUS_EFFORT || !inst.getBasicBlock().getInfrequent()) {
inline(inst, ir);
}
} else {
RVMMethod target = Entrypoints.lockMethod;
Call.mutate1(inst, CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), MonitorOp.getClearGuard(inst), ref);
}
}
break;
case MONITOREXIT_opcode:
{
Operand ref = MonitorOp.getClearRef(inst);
RVMType refType = ref.getType().peekType();
if (refType != null && !refType.getThinLockOffset().isMax()) {
RVMMethod target = Entrypoints.inlineUnlockMethod;
Call.mutate2(inst, CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), MonitorOp.getClearGuard(inst), ref, IRTools.AC(refType.getThinLockOffset()));
next = inst.prevInstructionInCodeOrder();
if (inst.getBasicBlock().getInfrequent())
container.counter1++;
container.counter2++;
if (!ir.options.FREQ_FOCUS_EFFORT || !inst.getBasicBlock().getInfrequent()) {
inline(inst, ir);
}
} else {
RVMMethod target = Entrypoints.unlockMethod;
Call.mutate1(inst, CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), MonitorOp.getClearGuard(inst), ref);
}
}
break;
case REF_ASTORE_opcode:
{
if (NEEDS_OBJECT_ASTORE_BARRIER) {
RVMMethod target = Entrypoints.objectArrayWriteBarrierMethod;
Instruction wb = Call.create3(CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), AStore.getClearGuard(inst), AStore.getArray(inst).copy(), AStore.getIndex(inst).copy(), AStore.getValue(inst).copy());
replaceInstructionWithBarrier(inst, wb);
if (ir.options.H2L_INLINE_WRITE_BARRIER) {
inline(wb, ir, true);
}
}
}
break;
case BYTE_ASTORE_opcode:
{
if (NEEDS_BYTE_ASTORE_BARRIER) {
primitiveArrayStoreHelper(Entrypoints.byteArrayWriteBarrierMethod, inst, ir);
}
}
break;
case DOUBLE_ASTORE_opcode:
{
if (NEEDS_DOUBLE_ASTORE_BARRIER) {
primitiveArrayStoreHelper(Entrypoints.doubleArrayWriteBarrierMethod, inst, ir);
}
}
break;
case FLOAT_ASTORE_opcode:
{
if (NEEDS_FLOAT_ASTORE_BARRIER) {
primitiveArrayStoreHelper(Entrypoints.floatArrayWriteBarrierMethod, inst, ir);
}
}
break;
case INT_ASTORE_opcode:
{
if (NEEDS_INT_ASTORE_BARRIER) {
primitiveArrayStoreHelper(Entrypoints.intArrayWriteBarrierMethod, inst, ir);
}
}
break;
case LONG_ASTORE_opcode:
{
if (NEEDS_LONG_ASTORE_BARRIER) {
primitiveArrayStoreHelper(Entrypoints.longArrayWriteBarrierMethod, inst, ir);
}
}
break;
case SHORT_ASTORE_opcode:
{
TypeReference type = AStore.getLocation(inst).getElementType();
if (NEEDS_SHORT_ASTORE_BARRIER && type.isShortType()) {
primitiveArrayStoreHelper(Entrypoints.shortArrayWriteBarrierMethod, inst, ir);
} else if (NEEDS_CHAR_ASTORE_BARRIER) {
if (VM.VerifyAssertions)
VM._assert(type.isCharType());
primitiveArrayStoreHelper(Entrypoints.charArrayWriteBarrierMethod, inst, ir);
}
}
break;
case REF_ALOAD_opcode:
{
if (NEEDS_OBJECT_ALOAD_BARRIER) {
RVMMethod target = Entrypoints.objectArrayReadBarrierMethod;
Instruction rb = Call.create2(CALL, ALoad.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), ALoad.getClearGuard(inst), ALoad.getArray(inst).copy(), ALoad.getIndex(inst).copy());
replaceInstructionWithBarrier(inst, rb);
inline(rb, ir, true);
}
}
break;
case PUTFIELD_opcode:
{
if (NEEDS_OBJECT_PUTFIELD_BARRIER) {
LocationOperand loc = PutField.getLocation(inst);
FieldReference fieldRef = loc.getFieldRef();
if (!fieldRef.getFieldContentsType().isPrimitiveType()) {
// reference PUTFIELD
RVMField field = fieldRef.peekResolvedField();
if (field == null || !field.isUntraced()) {
RVMMethod target = Entrypoints.objectFieldWriteBarrierMethod;
Instruction wb = Call.create4(CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), PutField.getClearGuard(inst), PutField.getRef(inst).copy(), PutField.getValue(inst).copy(), PutField.getOffset(inst).copy(), IRTools.IC(fieldRef.getId()));
replaceInstructionWithBarrier(inst, wb);
if (ir.options.H2L_INLINE_WRITE_BARRIER) {
inline(wb, ir, true);
}
}
} else {
// primitive PUTFIELD
if (NEEDS_BOOLEAN_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isBooleanType()) {
primitiveObjectFieldStoreHelper(Entrypoints.booleanFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_BYTE_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isByteType()) {
primitiveObjectFieldStoreHelper(Entrypoints.byteFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_CHAR_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isCharType()) {
primitiveObjectFieldStoreHelper(Entrypoints.charFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_DOUBLE_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isDoubleType()) {
primitiveObjectFieldStoreHelper(Entrypoints.doubleFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_FLOAT_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isFloatType()) {
primitiveObjectFieldStoreHelper(Entrypoints.floatFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_INT_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isIntType()) {
primitiveObjectFieldStoreHelper(Entrypoints.intFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_LONG_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isLongType()) {
primitiveObjectFieldStoreHelper(Entrypoints.longFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_SHORT_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isShortType()) {
primitiveObjectFieldStoreHelper(Entrypoints.shortFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_WORD_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isWordType()) {
primitiveObjectFieldStoreHelper(Entrypoints.wordFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_ADDRESS_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isAddressType()) {
primitiveObjectFieldStoreHelper(Entrypoints.addressFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_EXTENT_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isExtentType()) {
primitiveObjectFieldStoreHelper(Entrypoints.extentFieldWriteBarrierMethod, inst, ir, fieldRef);
} else if (NEEDS_OFFSET_PUTFIELD_BARRIER && fieldRef.getFieldContentsType().isOffsetType()) {
primitiveObjectFieldStoreHelper(Entrypoints.offsetFieldWriteBarrierMethod, inst, ir, fieldRef);
}
}
}
}
break;
case GETFIELD_opcode:
{
if (NEEDS_OBJECT_GETFIELD_BARRIER) {
LocationOperand loc = GetField.getLocation(inst);
FieldReference fieldRef = loc.getFieldRef();
if (GetField.getResult(inst).getType().isReferenceType()) {
RVMField field = fieldRef.peekResolvedField();
if (field == null || !field.isUntraced()) {
RVMMethod target = Entrypoints.objectFieldReadBarrierMethod;
Instruction rb = Call.create3(CALL, GetField.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), GetField.getClearGuard(inst), GetField.getRef(inst).copy(), GetField.getOffset(inst).copy(), IRTools.IC(fieldRef.getId()));
replaceInstructionWithBarrier(inst, rb);
inline(rb, ir, true);
}
}
}
}
break;
case PUTSTATIC_opcode:
{
if (NEEDS_OBJECT_PUTSTATIC_BARRIER) {
LocationOperand loc = PutStatic.getLocation(inst);
FieldReference field = loc.getFieldRef();
if (!field.getFieldContentsType().isPrimitiveType()) {
RVMMethod target = Entrypoints.objectStaticWriteBarrierMethod;
Instruction wb = Call.create3(CALL, null, IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), PutStatic.getValue(inst).copy(), PutStatic.getOffset(inst).copy(), IRTools.IC(field.getId()));
replaceInstructionWithBarrier(inst, wb);
if (ir.options.H2L_INLINE_WRITE_BARRIER) {
inline(wb, ir, true);
}
}
}
}
break;
case GETSTATIC_opcode:
{
if (NEEDS_OBJECT_GETSTATIC_BARRIER) {
LocationOperand loc = GetStatic.getLocation(inst);
FieldReference field = loc.getFieldRef();
if (!field.getFieldContentsType().isPrimitiveType()) {
RVMMethod target = Entrypoints.objectStaticReadBarrierMethod;
Instruction rb = Call.create2(CALL, GetStatic.getClearResult(inst), IRTools.AC(target.getOffset()), MethodOperand.STATIC(target), GetStatic.getOffset(inst).copy(), IRTools.IC(field.getId()));
replaceInstructionWithBarrier(inst, rb);
inline(rb, ir, true);
}
}
}
break;
default:
break;
}
}
// If we actually inlined anything, clean up the mess
if (didSomething) {
if (branchOpts == null) {
branchOpts = new BranchOptimizations(-1, true, true);
}
branchOpts.perform(ir, true);
if (_os == null) {
_os = new Simple(1, false, false, false, false);
}
_os.perform(ir);
}
// signal that we do not intend to use the gc in other phases anymore.
ir.getGc().close();
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class GenerateMagic method mapToMetadata.
private static LocationOperand mapToMetadata(Operand metadata) {
if (metadata instanceof IntConstantOperand) {
int index = ((IntConstantOperand) metadata).value;
if (index == 0)
return null;
MemberReference mr = MemberReference.getMemberRef(index);
return new LocationOperand(mr.asFieldReference());
}
return null;
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand in project JikesRVM by JikesRVM.
the class GenerateMachineSpecificMagic method generateMagic.
/**
* "Semantic inlining" of methods of the Magic class.
* Based on the methodName, generate a sequence of opt instructions
* that implement the magic, updating the stack as necessary
*
* @param bc2ir the bc2ir object generating the ir containing this magic
* @param gc == bc2ir.gc
* @param meth the RVMMethod that is the magic method
* @return {@code true} if and only if magic was generated
*/
public static boolean generateMagic(BC2IR bc2ir, GenerationContext gc, MethodReference meth) throws MagicNotImplementedException {
Atom methodName = meth.getName();
PhysicalRegisterSet phys = gc.getTemps().getPhysicalRegisterSet().asIA32();
if (methodName == MagicNames.getESIAsThread) {
RegisterOperand rop = gc.getTemps().makeTROp();
bc2ir.markGuardlessNonNull(rop);
bc2ir.push(rop);
} else if (methodName == MagicNames.setESIAsThread) {
Operand val = bc2ir.popRef();
if (val instanceof RegisterOperand) {
bc2ir.appendInstruction(Move.create(REF_MOVE, gc.getTemps().makeTROp(), val));
} else {
String msg = " Unexpected operand Magic.setESIAsThread";
throw MagicNotImplementedException.UNEXPECTED(msg);
}
} else if (methodName == MagicNames.getFramePointer) {
gc.forceFrameAllocation();
RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
RVMField f = ArchEntrypoints.framePointerField;
RegisterOperand pr = new RegisterOperand(phys.getESI(), TypeReference.Address);
bc2ir.appendInstruction(GetField.create(GETFIELD, val, pr.copy(), new AddressConstantOperand(f.getOffset()), new LocationOperand(f), new TrueGuardOperand()));
bc2ir.push(val.copyD2U());
} else if (methodName == MagicNames.getJTOC || methodName == MagicNames.getTocPointer) {
TypeReference t = (methodName == MagicNames.getJTOC ? TypeReference.IntArray : TypeReference.Address);
RegisterOperand val = gc.getTemps().makeTemp(t);
AddressConstantOperand addr = new AddressConstantOperand(Magic.getTocPointer());
bc2ir.appendInstruction(Move.create(REF_MOVE, val, addr));
bc2ir.push(val.copyD2U());
} else if (methodName == MagicNames.synchronizeInstructionCache) {
// nothing required on Intel
} else if (methodName == MagicNames.prefetch) {
bc2ir.appendInstruction(CacheOp.create(PREFETCH, bc2ir.popAddress()));
} else if (methodName == MagicNames.pause) {
bc2ir.appendInstruction(Empty.create(PAUSE));
} else if (methodName == MagicNames.illegalInstruction) {
bc2ir.appendInstruction(Empty.create(ILLEGAL_INSTRUCTION));
} else if (methodName == MagicNames.getCallerFramePointer) {
Operand fp = bc2ir.popAddress();
RegisterOperand val = gc.getTemps().makeTemp(TypeReference.Address);
bc2ir.appendInstruction(Load.create(REF_LOAD, val, fp, offsetOperand(STACKFRAME_FRAME_POINTER_OFFSET), null));
bc2ir.push(val.copyD2U());
} else if (methodName == MagicNames.setCallerFramePointer) {
Operand val = bc2ir.popAddress();
Operand fp = bc2ir.popAddress();
bc2ir.appendInstruction(Store.create(REF_STORE, val, fp, offsetOperand(STACKFRAME_FRAME_POINTER_OFFSET), null));
} else if (methodName == MagicNames.getCompiledMethodID) {
Operand fp = bc2ir.popAddress();
RegisterOperand val = gc.getTemps().makeTempInt();
bc2ir.appendInstruction(Load.create(INT_LOAD, val, fp, offsetOperand(STACKFRAME_METHOD_ID_OFFSET), null));
bc2ir.push(val.copyD2U());
} else if (methodName == MagicNames.setCompiledMethodID) {
Operand val = bc2ir.popInt();
Operand fp = bc2ir.popAddress();
bc2ir.appendInstruction(Store.create(INT_STORE, val, fp, offsetOperand(STACKFRAME_METHOD_ID_OFFSET), null));
} else if (methodName == MagicNames.getReturnAddressLocation) {
Operand fp = bc2ir.popAddress();
Instruction s = bc2ir._binaryHelper(REF_ADD, fp, offsetOperand(STACKFRAME_RETURN_ADDRESS_OFFSET), TypeReference.Address);
bc2ir.appendInstruction(s);
} else {
// Distinguish between magics that we know we don't implement
// (and never plan to implement) and those (usually new ones)
// that we want to be warned that we don't implement.
String msg = " Magic method not implemented: " + meth;
if (methodName == MagicNames.returnToNewStack) {
throw MagicNotImplementedException.EXPECTED(msg);
} else {
return false;
// throw MagicNotImplementedException.UNEXPECTED(msg);
}
}
return true;
}
use of org.jikesrvm.compilers.opt.ir.operand.LocationOperand 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.LocationOperand in project JikesRVM by JikesRVM.
the class BURS_Helpers method SET_EXCEPTION_OBJECT.
/**
* Emit code to move a value in a register to the stack location
* where a caught exception object is expected to be.
*/
protected final void SET_EXCEPTION_OBJECT(Instruction s) {
burs.ir.stackManager.forceFrameAllocation();
int offset = burs.ir.stackManager.allocateSpaceForCaughtException();
Register FP = regpool.getPhysicalRegisterSet().asPPC().getFP();
LocationOperand loc = new LocationOperand(-offset);
RegisterOperand obj = (RegisterOperand) CacheOp.getRef(s);
EMIT(MIR_Store.mutate(s, PPC_STAddr, obj, A(FP), IC(offset), loc, TG()));
}
Aggregations