Search in sources :

Example 1 with Register

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();
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet)

Example 2 with Register

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;
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) Register(org.jikesrvm.compilers.opt.ir.Register) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ppc.PhysicalRegisterSet) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Offset(org.vmmagic.unboxed.Offset)

Example 3 with Register

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>&lt;parent,ebag&gt;</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;
    }
}
Also used : GenerationContext(org.jikesrvm.compilers.opt.bc2ir.GenerationContext) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) RVMType(org.jikesrvm.classloader.RVMType) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RVMClass(org.jikesrvm.classloader.RVMClass) RVMMethod(org.jikesrvm.classloader.RVMMethod) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) NormalMethod(org.jikesrvm.classloader.NormalMethod) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) TypeReference(org.jikesrvm.classloader.TypeReference) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException)

Example 4 with Register

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;
    }
}
Also used : Operator(org.jikesrvm.compilers.opt.ir.Operator) FieldReference(org.jikesrvm.classloader.FieldReference) Register(org.jikesrvm.compilers.opt.ir.Register) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) RVMField(org.jikesrvm.classloader.RVMField) TypeReference(org.jikesrvm.classloader.TypeReference) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) HashSet(java.util.HashSet)

Example 5 with Register

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);
    }
}
Also used : Operator(org.jikesrvm.compilers.opt.ir.Operator) Register(org.jikesrvm.compilers.opt.ir.Register) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) RVMType(org.jikesrvm.classloader.RVMType) TIBConstantOperand(org.jikesrvm.compilers.opt.ir.operand.TIBConstantOperand) TypeReference(org.jikesrvm.classloader.TypeReference) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) HashSet(java.util.HashSet)

Aggregations

Register (org.jikesrvm.compilers.opt.ir.Register)279 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)144 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)106 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)82 Test (org.junit.Test)52 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)50 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)45 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)43 GenericPhysicalRegisterSet (org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet)40 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)39 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)32 MemoryOperand (org.jikesrvm.compilers.opt.ir.operand.MemoryOperand)30 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)29 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)27 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)26 OsrPoint (org.jikesrvm.compilers.opt.ir.OsrPoint)25 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)24 IA32ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand)23 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)22 StackLocationOperand (org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand)22