use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class AssemblerBase method isQuad.
/**
* Does the given instruction operate upon quad-sized data
* <em>for the purposes of assembling the instruction</em>?
* The opt compiler does not represent the size of register data, so
* it is necessary to determine whether to emit a quad instruction.
* As described above, this method is only concerned with quad data
* that changes the instruction. For example, this method will return
* {@code false} for {@code FSTP}. {@code FSTP} operates on quad-data
* but the instruction's operation is the same for 32-bit and 64-bit
* mode, so it is not a quad instruction for the purposes of this method.
* <p>
* This method typically looks at the memory operand, if any, and
* checks whether that is a byte. This method also recognizes
* the operator convention that __q on the end of the operator
* name means operate upon quad data. Moreover, it looks at data types
* for x64.
*
* @param inst the instruction being queried
* @return {@code true} if instruction operates upon quad data <b>AND</b>
* is treated as a quad instruction for the purpose of assembling the
* machine code
*/
boolean isQuad(Instruction inst) {
for (Operator opr : quadSizeOperators) {
if (opr == inst.operator()) {
return true;
}
}
if (VM.BuildFor32Addr) {
for (int i = 0; i < inst.getNumberOfOperands(); i++) {
Operand op = inst.getOperand(i);
if (op instanceof MemoryOperand) {
return ((MemoryOperand) op).size == 8;
}
}
} else {
// 64-bit
for (int i = 0; i < inst.getNumberOfOperands(); i++) {
Operand op = inst.getOperand(i);
if (op == null) {
// The operand may only be null for a few cases.
if (VM.VerifyAssertions) {
// Return has 2 return operands on IA32 because it
// must be able to return a 64-bit value. On x64, only
// one of the operands is needed, the other one is null.
boolean isReturn = MIR_Return.conforms(inst);
if (isReturn) {
VM._assert(i == MIR_Return.indexOfVal2(inst));
}
// Guards may be null for divides
boolean isDivide = MIR_Divide.conforms(inst);
if (isDivide) {
VM._assert(i == MIR_Divide.indexOfGuard(inst));
}
// For all other cases, all operands must be non null
String msg = inst.toString();
VM._assert(isReturn || isDivide, msg);
}
continue;
}
if (op.isLong() || op.isRef() || op.isAddress()) {
return true;
}
boolean quadMemOp = false;
if (op instanceof MemoryOperand) {
quadMemOp = op.asMemory().size == 8;
} else if (op instanceof StackLocationOperand) {
quadMemOp = op.asStackLocation().getSize() == 8;
}
// even if this one won't
if (quadMemOp) {
return true;
}
}
}
return false;
}
use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class ObjectReplacer method scalarReplace.
/**
* Replace a given use of a object with its scalar equivalent
*
* @param use the use to replace
* @param scalars an array of scalar register operands to replace
* the object's fields with
* @param fields the object's fields
* @param visited the registers that were already seen
*/
private void scalarReplace(RegisterOperand use, RegisterOperand[] scalars, ArrayList<RVMField> fields, Set<Register> visited) {
Instruction inst = use.instruction;
try {
switch(inst.getOpcode()) {
case PUTFIELD_opcode:
{
FieldReference fr = PutField.getLocation(inst).getFieldRef();
if (VM.VerifyAssertions)
VM._assert(fr.isResolved());
RVMField f = fr.peekResolvedField();
int index = fields.indexOf(f);
TypeReference type = scalars[index].getType();
Operator moveOp = IRTools.getMoveOp(type);
Instruction i = Move.create(moveOp, scalars[index].copyRO(), PutField.getClearValue(inst));
inst.insertBefore(i);
DefUse.removeInstructionAndUpdateDU(inst);
DefUse.updateDUForNewInstruction(i);
}
break;
case GETFIELD_opcode:
{
FieldReference fr = GetField.getLocation(inst).getFieldRef();
if (VM.VerifyAssertions)
VM._assert(fr.isResolved());
RVMField f = fr.peekResolvedField();
int index = fields.indexOf(f);
TypeReference type = scalars[index].getType();
Operator moveOp = IRTools.getMoveOp(type);
Instruction i = Move.create(moveOp, GetField.getClearResult(inst), scalars[index].copyRO());
inst.insertBefore(i);
DefUse.removeInstructionAndUpdateDU(inst);
DefUse.updateDUForNewInstruction(i);
}
break;
case MONITORENTER_opcode:
inst.insertBefore(Empty.create(READ_CEILING));
DefUse.removeInstructionAndUpdateDU(inst);
break;
case MONITOREXIT_opcode:
inst.insertBefore(Empty.create(WRITE_FLOOR));
DefUse.removeInstructionAndUpdateDU(inst);
break;
case CALL_opcode:
case NULL_CHECK_opcode:
// (SJF) TODO: Why wasn't this caught by BC2IR for
// java.lang.Double.<init> (Ljava/lang/String;)V ?
DefUse.removeInstructionAndUpdateDU(inst);
break;
case CHECKCAST_opcode:
case CHECKCAST_NOTNULL_opcode:
case CHECKCAST_UNRESOLVED_opcode:
{
// We cannot handle removing the checkcast if the result of the
// checkcast test is unknown
TypeReference lhsType = TypeCheck.getType(inst).getTypeRef();
if (ClassLoaderProxy.includesType(lhsType, klass.getTypeRef()) == YES) {
if (visited == null) {
visited = new HashSet<Register>();
}
Register copy = TypeCheck.getResult(inst).getRegister();
if (!visited.contains(copy)) {
visited.add(copy);
transform2(copy, inst, scalars, fields, visited);
// NB will remove inst
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
} else {
Instruction i2 = Trap.create(TRAP, null, TrapCodeOperand.CheckCast());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
}
break;
case INSTANCEOF_opcode:
case INSTANCEOF_NOTNULL_opcode:
case INSTANCEOF_UNRESOLVED_opcode:
{
// We cannot handle removing the instanceof if the result of the
// instanceof test is unknown
TypeReference lhsType = InstanceOf.getType(inst).getTypeRef();
Instruction i2;
if (ClassLoaderProxy.includesType(lhsType, klass.getTypeRef()) == YES) {
i2 = Move.create(INT_MOVE, InstanceOf.getClearResult(inst), IC(1));
} else {
i2 = Move.create(INT_MOVE, InstanceOf.getClearResult(inst), IC(0));
}
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case GET_OBJ_TIB_opcode:
{
Instruction i2 = Move.create(REF_MOVE, GuardedUnary.getClearResult(inst), new TIBConstantOperand(klass));
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case REF_MOVE_opcode:
{
if (visited == null) {
visited = new HashSet<Register>();
}
Register copy = Move.getResult(use.instruction).getRegister();
if (!visited.contains(copy)) {
visited.add(copy);
transform2(copy, inst, scalars, fields, visited);
// NB will remove inst
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
}
break;
default:
throw new OptimizingCompilerException("ObjectReplacer: unexpected use " + inst);
}
} catch (Exception e) {
OptimizingCompilerException oe = new OptimizingCompilerException("Error handling use (" + use + ") of: " + inst);
oe.initCause(e);
throw oe;
}
}
use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class ShortArrayReplacer method scalarReplace.
/**
* Replace a given use of an array with its scalar equivalent.
*
* @param use the use to replace
* @param scalars an array of scalar register operands to replace
* the array with
* @param visited TODO currently useless. Is this parameter
* necessary or should it be removed?
*/
private void scalarReplace(RegisterOperand use, RegisterOperand[] scalars, Set<Register> visited) {
Instruction inst = use.instruction;
RVMType type = vmArray.getElementType();
switch(inst.getOpcode()) {
case INT_ALOAD_opcode:
case LONG_ALOAD_opcode:
case FLOAT_ALOAD_opcode:
case DOUBLE_ALOAD_opcode:
case BYTE_ALOAD_opcode:
case UBYTE_ALOAD_opcode:
case USHORT_ALOAD_opcode:
case SHORT_ALOAD_opcode:
case REF_ALOAD_opcode:
{
// of a trap
if (ALoad.getIndex(inst).isIntConstant()) {
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
int index = ALoad.getIndex(inst).asIntConstant().value;
if (index >= 0 && index < size) {
Instruction i2 = Move.create(moveOp, ALoad.getClearResult(inst), scalars[index].copyRO());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
} else {
if (VM.BuildForIA32) {
if (size == 0) {
DefUse.removeInstructionAndUpdateDU(inst);
} else if (size == 1) {
int index = 0;
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
Instruction i2 = Move.create(moveOp, ALoad.getClearResult(inst), scalars[index].copyRO());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
Operator moveOp = IRTools.getCondMoveOp(type.getTypeRef());
Instruction i2 = CondMove.create(moveOp, ALoad.getClearResult(inst), ALoad.getClearIndex(inst), IC(0), ConditionOperand.EQUAL(), scalars[0].copyRO(), scalars[1].copyRO());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
} else {
if (size == 1) {
int index = 0;
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
Instruction i2 = Move.create(moveOp, ALoad.getClearResult(inst), scalars[index].copyRO());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
}
}
}
break;
case INT_ASTORE_opcode:
case LONG_ASTORE_opcode:
case FLOAT_ASTORE_opcode:
case DOUBLE_ASTORE_opcode:
case BYTE_ASTORE_opcode:
case SHORT_ASTORE_opcode:
case REF_ASTORE_opcode:
{
// of a trap
if (AStore.getIndex(inst).isIntConstant()) {
int index = AStore.getIndex(inst).asIntConstant().value;
if (index >= 0 && index < size) {
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
Instruction i2 = Move.create(moveOp, scalars[index].copyRO(), AStore.getClearValue(inst));
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
} else {
if (VM.BuildForIA32) {
if (size == 0) {
DefUse.removeInstructionAndUpdateDU(inst);
} else if (size == 1) {
int index = 0;
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
Instruction i2 = Move.create(moveOp, scalars[index].copyRO(), AStore.getClearValue(inst));
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
Operator moveOp = IRTools.getCondMoveOp(type.getTypeRef());
Operand value = AStore.getClearValue(inst);
Instruction i2 = CondMove.create(moveOp, scalars[0].copyRO(), AStore.getIndex(inst), IC(0), ConditionOperand.EQUAL(), value, scalars[0].copyRO());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
Instruction i3 = CondMove.create(moveOp, scalars[1].copyRO(), AStore.getIndex(inst), IC(0), ConditionOperand.NOT_EQUAL(), value, scalars[1].copyRO());
i2.insertAfter(i3);
DefUse.updateDUForNewInstruction(i3);
}
} else {
if (size == 1) {
int index = 0;
Operator moveOp = IRTools.getMoveOp(type.getTypeRef());
Instruction i2 = Move.create(moveOp, scalars[index].copyRO(), AStore.getClearValue(inst));
DefUse.replaceInstructionAndUpdateDU(inst, i2);
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
}
}
}
break;
case NULL_CHECK_opcode:
{
// Null check on result of new array must succeed
Instruction i2 = Move.create(GUARD_MOVE, NullCheck.getClearGuardResult(inst), new TrueGuardOperand());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case BOUNDS_CHECK_opcode:
{
// Remove or create trap as appropriate
Instruction i2 = TrapIf.create(TRAP_IF, BoundsCheck.getClearGuardResult(inst), IC(size), BoundsCheck.getClearIndex(inst), ConditionOperand.LOWER_EQUAL(), TrapCodeOperand.ArrayBounds());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case CHECKCAST_opcode:
case CHECKCAST_NOTNULL_opcode:
case CHECKCAST_UNRESOLVED_opcode:
{
// We cannot handle removing the checkcast if the result of the
// checkcast test is unknown
TypeReference lhsType = TypeCheck.getType(inst).getTypeRef();
if (ClassLoaderProxy.includesType(lhsType, vmArray.getTypeRef()) == YES) {
if (visited == null) {
visited = new HashSet<Register>();
}
Register copy = TypeCheck.getResult(inst).getRegister();
if (!visited.contains(copy)) {
visited.add(copy);
transform2(copy, inst, scalars);
// NB will remove inst
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
} else {
Instruction i2 = Trap.create(TRAP, null, TrapCodeOperand.CheckCast());
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
}
break;
case INSTANCEOF_opcode:
case INSTANCEOF_NOTNULL_opcode:
case INSTANCEOF_UNRESOLVED_opcode:
{
// We cannot handle removing the instanceof if the result of the
// instanceof test is unknown
TypeReference lhsType = InstanceOf.getType(inst).getTypeRef();
Instruction i2;
if (ClassLoaderProxy.includesType(lhsType, vmArray.getTypeRef()) == YES) {
i2 = Move.create(INT_MOVE, InstanceOf.getClearResult(inst), IC(1));
} else {
i2 = Move.create(INT_MOVE, InstanceOf.getClearResult(inst), IC(0));
}
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case GET_OBJ_TIB_opcode:
{
Instruction i2 = Move.create(REF_MOVE, GuardedUnary.getClearResult(inst), new TIBConstantOperand(vmArray));
DefUse.replaceInstructionAndUpdateDU(inst, i2);
}
break;
case REF_MOVE_opcode:
{
if (visited == null) {
visited = new HashSet<Register>();
}
Register copy = Move.getResult(inst).getRegister();
if (!visited.contains(copy)) {
visited.add(copy);
transform2(copy, inst, scalars);
// NB will remove inst
} else {
DefUse.removeInstructionAndUpdateDU(inst);
}
}
break;
default:
throw new OptimizingCompilerException("Unexpected instruction: " + inst);
}
}
use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class DepGraph method computeControlAndBarrierDependences.
/**
* Compute control and barrier (acquire/release) dependences
* in two passes (one forward, one reverse over the instructions
* from start to end.
*
* @param start start instruction
* @param end end instruction
*/
private void computeControlAndBarrierDependences(Instruction start, Instruction end) {
// (1) In a forward pass, we add the following dependences:
// a) No load instruction may rise above an acquire
// b) No instruction may rise above an UNINT_BEGIN (conservative),
// a yieldpoint (we placed the yieldpoints where we wanted them),
// a GET_CAUGHT_EXCEPTION, or an IR_PROLOGUE.
// c) No GC point may rise above an UNINT_END
DepGraphNode lastTotalBarrier = null;
DepGraphNode lastGCBarrier = null;
DepGraphNode lastAcquire = null;
for (DepGraphNode pnode = (DepGraphNode) firstNode(); pnode != null; pnode = (DepGraphNode) pnode.getNext()) {
Instruction p = pnode.instruction();
if (lastTotalBarrier != null) {
lastTotalBarrier.insertOutEdge(pnode, CONTROL);
}
if (lastGCBarrier != null) {
lastGCBarrier.insertOutEdge(pnode, CONTROL);
}
if (lastAcquire != null && p.isImplicitLoad()) {
lastAcquire.insertOutEdge(pnode, CONTROL);
}
Operator pop = p.operator();
if (p.isYieldPoint() || pop == IR_PROLOGUE || pop == UNINT_BEGIN || pop == GET_TIME_BASE || pop == GET_CAUGHT_EXCEPTION) {
lastTotalBarrier = pnode;
}
if (pop == UNINT_END) {
lastGCBarrier = pnode;
}
if (p.isAcquire() || p.isDynamicLinkingPoint()) {
lastAcquire = pnode;
}
}
// (2) In a backward pass we add the following dependences:
// a) No store instruction may sink below a release.
// b) No instruction may sink below an UNINT_END (conservative),
// a branch/return, a SET_CAUGHT_EXCEPTION, or a yieldpoint
// (again want to pin yieldpoints).
// c) No GC point may sink below an UNINT_BEGIN
lastTotalBarrier = null;
lastGCBarrier = null;
DepGraphNode lastRelease = null;
for (DepGraphNode pnode = (DepGraphNode) lastNode(); pnode != null; pnode = (DepGraphNode) pnode.getPrev()) {
Instruction p = pnode.instruction();
if (lastTotalBarrier != null) {
pnode.insertOutEdge(lastTotalBarrier, CONTROL);
}
if (lastGCBarrier != null) {
pnode.insertOutEdge(lastGCBarrier, CONTROL);
}
if (lastRelease != null && p.isImplicitStore()) {
pnode.insertOutEdge(lastRelease, CONTROL);
}
Operator pop = p.operator();
if (p.isBranch() || p.isReturn() || p.isYieldPoint() || pop == UNINT_END || pop == GET_TIME_BASE || pop == SET_CAUGHT_EXCEPTION) {
lastTotalBarrier = pnode;
}
if (pop == UNINT_BEGIN) {
lastGCBarrier = pnode;
}
if (p.isRelease() || p.isDynamicLinkingPoint()) {
lastRelease = pnode;
}
}
}
use of org.jikesrvm.compilers.opt.ir.Operator in project JikesRVM by JikesRVM.
the class BURS_Helpers method CMP2.
/**
* emit basic code to handle an INT_IFCMP2 when no folding
* of the compare into some other computation is possible.
*/
protected final void CMP2(Instruction s, RegisterOperand val1, Operand val2, ConditionOperand cond1, ConditionOperand cond2, boolean immediate) {
Operator op1;
Operator op2;
if (immediate) {
op1 = cond1.isUNSIGNED() ? PPC_CMPLI : PPC_CMPI;
op2 = cond2.isUNSIGNED() ? PPC_CMPLI : PPC_CMPI;
} else {
op1 = cond1.isUNSIGNED() ? PPC_CMPL : PPC_CMP;
op2 = cond2.isUNSIGNED() ? PPC_CMPL : PPC_CMP;
}
if (op1 == op2) {
RegisterOperand cr = regpool.makeTempCondition();
EMIT(MIR_Binary.create(op1, cr, val1, val2));
EMIT(MIR_CondBranch2.mutate(s, PPC_BCOND2, cr.copyD2U(), new PowerPCConditionOperand(cond1), IfCmp2.getTarget1(s), IfCmp2.getBranchProfile1(s), new PowerPCConditionOperand(cond2), IfCmp2.getTarget2(s), IfCmp2.getBranchProfile2(s)));
} else {
RegisterOperand cr1 = regpool.makeTempCondition();
RegisterOperand cr2 = regpool.makeTempCondition();
EMIT(MIR_Binary.create(op1, cr1, val1, val2));
EMIT(MIR_Binary.create(op2, cr2, val1, val2));
EMIT(MIR_CondBranch.create(PPC_BCOND, cr1.copyD2U(), new PowerPCConditionOperand(cond1), IfCmp2.getTarget1(s), IfCmp2.getBranchProfile1(s)));
EMIT(MIR_CondBranch.mutate(s, PPC_BCOND, cr2.copyD2U(), new PowerPCConditionOperand(cond2), IfCmp2.getTarget2(s), IfCmp2.getBranchProfile2(s)));
}
}
Aggregations