use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class FinalMIRExpansion method expandFClear.
/**
* expand an FCLEAR pseudo-insruction using FFREEs.
*
* @param s the instruction to expand
* @param ir the containing IR
*/
private static void expandFClear(Instruction s, IR ir) {
int nSave = MIR_UnaryNoRes.getVal(s).asIntConstant().value;
int fpStackHeight = ir.MIRInfo.fpStackHeight;
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
for (int i = nSave; i < fpStackHeight; i++) {
Register f = phys.getFPR(i);
s.insertBefore(MIR_Nullary.create(IA32_FFREE, D(f)));
}
// Remove the FCLEAR.
s.remove();
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class FinalMIRExpansion method findOrCreateYieldpointBlock.
/**
* Return a basic block holding the call to a runtime yield service.
* Create a new basic block at the end of the code order if necessary.
*
* @param ir the governing IR
* @param whereFrom is this yieldpoint from the PROLOGUE, EPILOGUE, or a
* BACKEDGE?
*/
static BasicBlock findOrCreateYieldpointBlock(IR ir, int whereFrom) {
RVMMethod meth = null;
PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
Register zero = phys.getGPR(0);
// state for creating the block
if (whereFrom == RVMThread.PROLOGUE) {
if (ir.MIRInfo.prologueYieldpointBlock != null) {
return ir.MIRInfo.prologueYieldpointBlock;
} else {
meth = Entrypoints.optThreadSwitchFromPrologueMethod;
}
} else if (whereFrom == RVMThread.BACKEDGE) {
if (ir.MIRInfo.backedgeYieldpointBlock != null) {
return ir.MIRInfo.backedgeYieldpointBlock;
} else {
meth = Entrypoints.optThreadSwitchFromBackedgeMethod;
}
} else if (whereFrom == RVMThread.EPILOGUE) {
if (ir.MIRInfo.epilogueYieldpointBlock != null) {
return ir.MIRInfo.epilogueYieldpointBlock;
} else {
meth = Entrypoints.optThreadSwitchFromEpilogueMethod;
}
} else if (whereFrom == RVMThread.OSROPT) {
if (ir.MIRInfo.osrYieldpointBlock != null) {
return ir.MIRInfo.osrYieldpointBlock;
} else {
meth = Entrypoints.optThreadSwitchFromOsrOptMethod;
}
}
// Not found. create new basic block holding the requested yieldpoint
// method
BasicBlock result = new BasicBlock(-1, null, ir.cfg);
ir.cfg.addLastInCodeOrder(result);
Register JTOC = phys.getJTOC();
Register CTR = phys.getCTR();
Offset offset = meth.getOffset();
if (fits(offset, 16)) {
result.appendInstruction(MIR_Load.create(PPC_LAddr, A(zero), A(JTOC), IC(PPCMaskLower16(offset))));
} else {
// not implemented
if (VM.VerifyAssertions)
VM._assert(fits(offset, 32));
result.appendInstruction(MIR_Binary.create(PPC_ADDIS, A(zero), A(JTOC), IC(PPCMaskUpper16(offset))));
result.appendInstruction(MIR_Load.create(PPC_LAddr, A(zero), A(zero), IC(PPCMaskLower16(offset))));
}
result.appendInstruction(MIR_Move.create(PPC_MTSPR, A(CTR), A(zero)));
result.appendInstruction(MIR_Branch.create(PPC_BCTR));
// cache the create block and then return it
if (whereFrom == RVMThread.PROLOGUE) {
ir.MIRInfo.prologueYieldpointBlock = result;
} else if (whereFrom == RVMThread.BACKEDGE) {
ir.MIRInfo.backedgeYieldpointBlock = result;
} else if (whereFrom == RVMThread.EPILOGUE) {
ir.MIRInfo.epilogueYieldpointBlock = result;
} else if (whereFrom == RVMThread.OSROPT) {
ir.MIRInfo.osrYieldpointBlock = result;
}
return result;
}
use of org.jikesrvm.compilers.opt.ir.Register in project JikesRVM by JikesRVM.
the class Inliner method execute.
/**
* Return a generation context that represents the
* execution of inlDec in the context <code><parent,ebag></code> for
* the call instruction callSite.
* <p> PRECONDITION: inlDec.isYes()
* <p> POSTCONDITIONS:
* Let gc be the returned generation context.
* <ul>
* <li> gc.cfg.firstInCodeOrder is the entry to the inlined context
* <li>gc.cfg.lastInCodeOrder is the exit from the inlined context
* <li> GenerationContext.transferState(parent, child) has been called.
* </ul>
*
* @param inlDec the inlining decision to execute
* @param parent the caller generation context
* @param ebag exception handler scope for the caller
* @param callSite the callsite to execute
* @return a generation context that represents the execution of the
* inline decision in the given context
*/
public static GenerationContext execute(InlineDecision inlDec, GenerationContext parent, ExceptionHandlerBasicBlockBag ebag, Instruction callSite) {
if (inlDec.needsGuard()) {
// Step 1: create the synthetic generation context we'll
// return to our caller.
GenerationContext container = GenerationContext.createSynthetic(parent, ebag);
container.getCfg().breakCodeOrder(container.getPrologue(), container.getEpilogue());
// Step 2: (a) Print a message (optional)
// (b) Generate the child GC for each target
RVMMethod[] targets = inlDec.getTargets();
byte[] guards = inlDec.getGuards();
GenerationContext[] children = new GenerationContext[targets.length];
for (int i = 0; i < targets.length; i++) {
NormalMethod callee = (NormalMethod) targets[i];
// (a)
if (parent.getOptions().PRINT_INLINE_REPORT) {
String guard = guards[i] == OptOptions.INLINE_GUARD_CLASS_TEST ? " (class test) " : " (method test) ";
VM.sysWriteln("\tGuarded inline" + guard + " " + callee + " into " + callSite.position().getMethod() + " at bytecode " + callSite.getBytecodeIndex());
}
// (b)
children[i] = parent.createChildContext(ebag, callee, callSite);
BC2IR.generateHIR(children[i]);
children[i].transferStateToParent();
}
// special purpose coding wrapping the calls to Operand.meet.
if (Call.hasResult(callSite)) {
Register reg = Call.getResult(callSite).getRegister();
container.setResult(children[0].getResult());
for (int i = 1; i < targets.length; i++) {
if (children[i].getResult() != null) {
container.setResult((container.getResult() == null) ? children[i].getResult() : Operand.meet(container.getResult(), children[i].getResult(), reg));
}
}
if (!inlDec.OSRTestFailed()) {
// Account for the non-predicted case as well...
RegisterOperand failureCaseResult = Call.getResult(callSite).copyRO();
container.setResult((container.getResult() == null) ? failureCaseResult : Operand.meet(container.getResult(), failureCaseResult, reg));
}
}
// Step 4: Create a block to contain a copy of the original call or an OSR_Yieldpoint
// to cover the case that all predictions fail.
BasicBlock testFailed = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
testFailed.setExceptionHandlers(ebag);
if (COUNT_FAILED_GUARDS && Controller.options.INSERT_DEBUGGING_COUNTERS) {
// Get a dynamic count of how many times guards fail at runtime.
// Need a name for the event to count. In this example, a
// separate counter for each method by using the method name
// as the event name. You could also have used just the string
// "Guarded inline failed" to keep only one counter.
String eventName = "Guarded inline failed: " + callSite.position().getMethod().toString();
// Create instruction that will increment the counter
// corresponding to the named event.
Instruction counterInst = AOSDatabase.debuggingCounterData.getCounterInstructionForEvent(eventName);
testFailed.appendInstruction(counterInst);
}
if (inlDec.OSRTestFailed()) {
// note where we're storing the osr barrier instruction
Instruction lastOsrBarrier = parent.getOSRBarrierFromInst(callSite);
Instruction s = BC2IR._osrHelper(lastOsrBarrier, parent);
s.copyPosition(callSite);
testFailed.appendInstruction(s);
testFailed.insertOut(parent.getExit());
} else {
Instruction call = callSite.copyWithoutLinks();
Call.getMethod(call).setIsGuardedInlineOffBranch(true);
call.copyPosition(callSite);
testFailed.appendInstruction(call);
testFailed.insertOut(container.getEpilogue());
// BC2IR.maybeInlineMethod).
if (ebag != null) {
for (Enumeration<BasicBlock> e = ebag.enumerator(); e.hasMoreElements(); ) {
BasicBlock handler = e.nextElement();
testFailed.insertOut(handler);
}
}
testFailed.setCanThrowExceptions();
testFailed.setMayThrowUncaughtException();
}
container.getCfg().linkInCodeOrder(testFailed, container.getEpilogue());
testFailed.setInfrequent();
// Step 5: Patch together all the callees by generating guard blocks
BasicBlock firstIfBlock = testFailed;
// Note: We know that receiver must be a register
// operand (and not a string constant) because we are doing a
// guarded inlining....if it was a string constant we'd have
// been able to inline without a guard.
Operand receiver = Call.getParam(callSite, 0);
MethodOperand mo = Call.getMethod(callSite);
boolean isInterface = mo.isInterface();
if (isInterface) {
if (VM.BuildForIMTInterfaceInvocation) {
RVMType interfaceType = mo.getTarget().getDeclaringClass();
TypeReference recTypeRef = receiver.getType();
RVMClass recType = (RVMClass) recTypeRef.peekType();
// Attempt to avoid inserting the check by seeing if the
// known static type of the receiver implements the interface.
boolean requiresImplementsTest = true;
if (recType != null && recType.isResolved() && !recType.isInterface()) {
byte doesImplement = ClassLoaderProxy.includesType(interfaceType.getTypeRef(), recTypeRef);
requiresImplementsTest = doesImplement != YES;
}
if (requiresImplementsTest) {
RegisterOperand checkedReceiver = parent.getTemps().makeTemp(receiver);
Instruction dtc = TypeCheck.create(MUST_IMPLEMENT_INTERFACE, checkedReceiver, receiver.copy(), new TypeOperand(interfaceType), Call.getGuard(callSite).copy());
dtc.copyPosition(callSite);
checkedReceiver.refine(interfaceType.getTypeRef());
Call.setParam(callSite, 0, checkedReceiver.copyRO());
testFailed.prependInstruction(dtc);
}
}
}
// "logical" test and to share test insertion for interfaces/virtuals.
for (int i = children.length - 1; i >= 0; i--, testFailed = firstIfBlock) {
firstIfBlock = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
firstIfBlock.setExceptionHandlers(ebag);
BasicBlock lastIfBlock = firstIfBlock;
RVMMethod target = children[i].getMethod();
Instruction tmp;
if (isInterface) {
RVMClass callDeclClass = mo.getTarget().getDeclaringClass();
if (!callDeclClass.isInterface()) {
// the entire compilation.
throw new OptimizingCompilerException("Attempted guarded inline of invoke interface when decl class of target method may not be an interface");
}
// We potentially have to generate IR to perform two tests here:
// (1) Does the receiver object implement callDeclClass?
// (2) Given that it does, is target the method that would
// be invoked for this receiver?
// It is quite common to be able to answer (1) "YES" at compile
// time, in which case we only have to generate IR to establish
// (2) at runtime.
byte doesImplement = ClassLoaderProxy.includesType(callDeclClass.getTypeRef(), target.getDeclaringClass().getTypeRef());
if (doesImplement != YES) {
// implements the interface).
if (parent.getOptions().PRINT_INLINE_REPORT) {
VM.sysWriteln("\t\tRequired additional instanceof " + callDeclClass + " test");
}
firstIfBlock = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
firstIfBlock.setExceptionHandlers(ebag);
RegisterOperand instanceOfResult = parent.getTemps().makeTempInt();
tmp = InstanceOf.create(INSTANCEOF_NOTNULL, instanceOfResult, new TypeOperand(callDeclClass), receiver.copy(), Call.getGuard(callSite));
tmp.copyPosition(callSite);
firstIfBlock.appendInstruction(tmp);
tmp = IfCmp.create(INT_IFCMP, parent.getTemps().makeTempValidation(), instanceOfResult.copyD2U(), new IntConstantOperand(0), ConditionOperand.EQUAL(), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
tmp.copyPosition(callSite);
firstIfBlock.appendInstruction(tmp);
firstIfBlock.insertOut(testFailed);
firstIfBlock.insertOut(lastIfBlock);
container.getCfg().linkInCodeOrder(firstIfBlock, lastIfBlock);
}
}
if (guards[i] == OptOptions.INLINE_GUARD_CLASS_TEST) {
tmp = InlineGuard.create(IG_CLASS_TEST, receiver.copy(), Call.getGuard(callSite).copy(), new TypeOperand(target.getDeclaringClass()), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
} else if (guards[i] == OptOptions.INLINE_GUARD_METHOD_TEST) {
// declaring class.
if (isInterface) {
RegisterOperand t = parent.getTemps().makeTempInt();
Instruction test = InstanceOf.create(INSTANCEOF_NOTNULL, t, new TypeOperand(target.getDeclaringClass().getTypeRef()), receiver.copy());
test.copyPosition(callSite);
lastIfBlock.appendInstruction(test);
Instruction cmp = IfCmp.create(INT_IFCMP, parent.getTemps().makeTempValidation(), t.copyD2U(), new IntConstantOperand(0), ConditionOperand.EQUAL(), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
cmp.copyPosition(callSite);
lastIfBlock.appendInstruction(cmp);
BasicBlock subclassTest = new BasicBlock(callSite.getBytecodeIndex(), callSite.position(), parent.getCfg());
lastIfBlock.insertOut(testFailed);
lastIfBlock.insertOut(subclassTest);
container.getCfg().linkInCodeOrder(lastIfBlock, subclassTest);
lastIfBlock = subclassTest;
}
tmp = InlineGuard.create(IG_METHOD_TEST, receiver.copy(), Call.getGuard(callSite).copy(), MethodOperand.VIRTUAL(target.getMemberRef().asMethodReference(), target), testFailed.makeJumpTarget(), BranchProfileOperand.unlikely());
} else {
tmp = InlineGuard.create(IG_PATCH_POINT, receiver.copy(), Call.getGuard(callSite).copy(), MethodOperand.VIRTUAL(target.getMemberRef().asMethodReference(), target), testFailed.makeJumpTarget(), inlDec.OSRTestFailed() ? BranchProfileOperand.never() : BranchProfileOperand.unlikely());
}
tmp.copyPosition(callSite);
lastIfBlock.appendInstruction(tmp);
lastIfBlock.insertOut(testFailed);
lastIfBlock.insertOut(children[i].getPrologue());
container.getCfg().linkInCodeOrder(lastIfBlock, children[i].getCfg().firstInCodeOrder());
if (children[i].getEpilogue() != null) {
children[i].getEpilogue().appendInstruction(container.getEpilogue().makeGOTO());
children[i].getEpilogue().insertOut(container.getEpilogue());
}
container.getCfg().linkInCodeOrder(children[i].getCfg().lastInCodeOrder(), testFailed);
}
// Step 6: finish by linking container.prologue & testFailed
container.getPrologue().insertOut(testFailed);
container.getCfg().linkInCodeOrder(container.getPrologue(), testFailed);
return container;
} else {
if (VM.VerifyAssertions)
VM._assert(inlDec.getNumberOfTargets() == 1);
NormalMethod callee = (NormalMethod) inlDec.getTargets()[0];
if (parent.getOptions().PRINT_INLINE_REPORT) {
VM.sysWriteln("\tInline " + callee + " into " + callSite.position().getMethod() + " at bytecode " + callSite.getBytecodeIndex());
}
GenerationContext child = parent.createChildContext(ebag, callee, callSite);
BC2IR.generateHIR(child);
child.transferStateToParent();
return child;
}
}
use of org.jikesrvm.compilers.opt.ir.Register 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.Register 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);
}
}
Aggregations