Search in sources :

Example 1 with IntConstantOperand

use of org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand in project JikesRVM by JikesRVM.

the class AssemblerBase method operandCost.

private int operandCost(Operand op, boolean shortFormImmediate) {
    if (op instanceof MemoryOperand) {
        MemoryOperand mop = (MemoryOperand) op;
        // If it's a 2byte mem location, we're going to need an override prefix
        int prefix = mop.size == 2 ? 1 : 0;
        // Deal with EBP wierdness
        if (mop.base != null && mop.base.getRegister() == EBP) {
            if (mop.index != null) {
                // forced into SIB + 32 bit displacement no matter what disp is
                return prefix + 5;
            }
            if (fits(mop.disp, 8)) {
                return prefix + 1;
            } else {
                return prefix + 4;
            }
        }
        if (mop.index != null && mop.index.getRegister() == EBP) {
            // forced into SIB + 32 bit displacement no matter what disp is
            return prefix + 5;
        }
        // Deal with ESP wierdness -- requires SIB byte even when index is null
        if (mop.base != null && mop.base.getRegister() == ESP) {
            if (fits(mop.disp, 8)) {
                return prefix + 2;
            } else {
                return prefix + 5;
            }
        }
        if (mop.index == null) {
            // just displacement to worry about
            if (mop.disp.isZero()) {
                return prefix + 0;
            } else if (fits(mop.disp, 8)) {
                return prefix + 1;
            } else {
                return prefix + 4;
            }
        } else {
            // have a SIB
            if (mop.base == null && mop.scale != 0) {
                // forced to 32 bit displacement even if it would fit in 8
                return prefix + 5;
            } else {
                if (mop.disp.isZero()) {
                    return prefix + 1;
                } else if (fits(mop.disp, 8)) {
                    return prefix + 2;
                } else {
                    return prefix + 5;
                }
            }
        }
    } else if (op instanceof IntConstantOperand) {
        if (shortFormImmediate && fits(((IntConstantOperand) op).value, 8)) {
            return 1;
        } else {
            return 4;
        }
    } else {
        return 0;
    }
}
Also used : IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand)

Example 2 with IntConstantOperand

use of org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand in project JikesRVM by JikesRVM.

the class FinalMIRExpansion method expand.

/**
 * @param ir the IR to expand
 * @return return value is garbage for IA32
 */
public static int expand(IR ir) {
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
    MachineCodeOffsets mcOffsets = ir.MIRInfo.mcOffsets;
    for (Instruction next, p = ir.firstInstructionInCodeOrder(); p != null; p = next) {
        next = p.nextInstructionInCodeOrder();
        mcOffsets.setMachineCodeOffset(p, -1);
        switch(p.getOpcode()) {
            case IA32_MOVAPS_opcode:
                // a reg-reg move turned into a memory move where we can't guarantee alignment
                if (MIR_Move.getResult(p).isMemory() || MIR_Move.getValue(p).isMemory()) {
                    MIR_Move.mutate(p, IA32_MOVSS, MIR_Move.getClearResult(p), MIR_Move.getClearValue(p));
                }
                break;
            case IA32_MOVAPD_opcode:
                // a reg-reg move turned into a memory move where we can't guarantee alignment
                if (MIR_Move.getResult(p).isMemory() || MIR_Move.getValue(p).isMemory()) {
                    MIR_Move.mutate(p, IA32_MOVSD, MIR_Move.getClearResult(p), MIR_Move.getClearValue(p));
                }
                break;
            case IA32_TEST_opcode:
                // must be first; we can just commute it here.
                if (MIR_Test.getVal2(p).isMemory()) {
                    Operand tmp = MIR_Test.getClearVal1(p);
                    MIR_Test.setVal1(p, MIR_Test.getClearVal2(p));
                    MIR_Test.setVal2(p, tmp);
                }
                break;
            case NULL_CHECK_opcode:
                {
                    // mutate this into a TRAPIF, and then fall through to the the
                    // TRAP_IF case.
                    Operand ref = NullCheck.getRef(p);
                    MIR_TrapIf.mutate(p, IA32_TRAPIF, null, ref.copy(), IC(0), IA32ConditionOperand.EQ(), TrapCodeOperand.NullPtr());
                }
            // There is no break statement here on purpose!
            case IA32_TRAPIF_opcode:
                {
                    // split the basic block right before the IA32_TRAPIF
                    BasicBlock thisBlock = p.getBasicBlock();
                    BasicBlock trap = thisBlock.createSubBlock(p.getBytecodeIndex(), ir, 0f);
                    thisBlock.insertOut(trap);
                    BasicBlock nextBlock = thisBlock.splitNodeWithLinksAt(p, ir);
                    thisBlock.insertOut(trap);
                    TrapCodeOperand tc = MIR_TrapIf.getClearTrapCode(p);
                    p.remove();
                    mcOffsets.setMachineCodeOffset(nextBlock.firstInstruction(), -1);
                    // add code to thisBlock to conditionally jump to trap
                    Instruction cmp = MIR_Compare.create(IA32_CMP, MIR_TrapIf.getVal1(p).copy(), MIR_TrapIf.getVal2(p).copy());
                    if (p.isMarkedAsPEI()) {
                        // The trap if was explictly marked, which means that it has
                        // a memory operand into which we've folded a null check.
                        // Actually need a GC map for both the compare and the INT.
                        cmp.markAsPEI();
                        cmp.copyPosition(p);
                        ir.MIRInfo.gcIRMap.insertTwin(p, cmp);
                    }
                    thisBlock.appendInstruction(cmp);
                    thisBlock.appendInstruction(MIR_CondBranch.create(IA32_JCC, (IA32ConditionOperand) MIR_TrapIf.getCond(p).copy(), trap.makeJumpTarget(), null));
                    // add block at end to hold trap instruction, and
                    // insert trap sequence
                    ir.cfg.addLastInCodeOrder(trap);
                    if (tc.isArrayBounds()) {
                        // attempt to store index expression in processor object for
                        // C trap handler
                        Operand index = MIR_TrapIf.getVal2(p);
                        if (!(index instanceof RegisterOperand || index instanceof IntConstantOperand)) {
                            // index was spilled, and
                            index = IC(0xdeadbeef);
                        // we can't get it back here.
                        }
                        MemoryOperand mo = MemoryOperand.BD(ir.regpool.makeTROp(), ArchEntrypoints.arrayIndexTrapParamField.getOffset(), (byte) 4, null, null);
                        trap.appendInstruction(MIR_Move.create(IA32_MOV, mo, index.copy()));
                    }
                    // NOTE: must make p the trap instruction: it is the GC point!
                    // IMPORTANT: must also inform the GCMap that the instruction has
                    // been moved!!!
                    trap.appendInstruction(MIR_Trap.mutate(p, IA32_INT, null, tc));
                    ir.MIRInfo.gcIRMap.moveToEnd(p);
                    if (tc.isStackOverflow()) {
                        // only stackoverflow traps resume at next instruction.
                        trap.appendInstruction(MIR_Branch.create(IA32_JMP, nextBlock.makeJumpTarget()));
                    }
                }
                break;
            case IA32_FMOV_ENDING_LIVE_RANGE_opcode:
                {
                    Operand result = MIR_Move.getResult(p);
                    Operand value = MIR_Move.getValue(p);
                    if (result.isRegister() && value.isRegister()) {
                        if (result.similar(value)) {
                            // eliminate useless move
                            p.remove();
                        } else {
                            int i = PhysicalRegisterSet.getFPRIndex(result.asRegister().getRegister());
                            int j = PhysicalRegisterSet.getFPRIndex(value.asRegister().getRegister());
                            if (i == 0) {
                                MIR_XChng.mutate(p, IA32_FXCH, result, value);
                            } else if (j == 0) {
                                MIR_XChng.mutate(p, IA32_FXCH, value, result);
                            } else {
                                expandFmov(p, phys);
                            }
                        }
                    } else {
                        expandFmov(p, phys);
                    }
                    break;
                }
            case DUMMY_DEF_opcode:
            case DUMMY_USE_opcode:
            case REQUIRE_ESP_opcode:
            case ADVISE_ESP_opcode:
                p.remove();
                break;
            case IA32_FMOV_opcode:
                expandFmov(p, phys);
                break;
            case IA32_MOV_opcode:
                // Convert 0L to 0 to allow optimization into XOR.
                if (MIR_Move.getResult(p).isRegister() && MIR_Move.getValue(p).isLongConstant() && MIR_Move.getValue(p).asLongConstant().value == 0L) {
                    MIR_Move.setValue(p, IC(0));
                }
                // Replace result = IA32_MOV 0 with result = IA32_XOR result, result
                if (MIR_Move.getResult(p).isRegister() && MIR_Move.getValue(p).isIntConstant() && MIR_Move.getValue(p).asIntConstant().value == 0) {
                    // Calculate what flags are defined in coming instructions before a use of a flag or BBend
                    Instruction x = next;
                    int futureDefs = 0;
                    while (!BBend.conforms(x) && !PhysicalDefUse.usesEFLAGS(x.operator())) {
                        futureDefs |= x.operator().implicitDefs;
                        x = x.nextInstructionInCodeOrder();
                    }
                    // If the flags will be destroyed prior to use or we reached the end of the basic block
                    if (BBend.conforms(x) || (futureDefs & PhysicalDefUse.maskAF_CF_OF_PF_SF_ZF) == PhysicalDefUse.maskAF_CF_OF_PF_SF_ZF) {
                        Operand result = MIR_Move.getClearResult(p);
                        MIR_BinaryAcc.mutate(p, IA32_XOR, result, result.copy());
                    }
                }
                break;
            case IA32_SET__B_opcode:
                // Replace <cmp>, set__b, movzx__b with xor, <cmp>, set__b
                if (MIR_Set.getResult(p).isRegister() && MIR_Unary.conforms(next) && (next.operator() == IA32_MOVZX__B) && MIR_Unary.getResult(next).isRegister() && MIR_Unary.getVal(next).similar(MIR_Unary.getResult(next)) && MIR_Unary.getVal(next).similar(MIR_Set.getResult(p))) {
                    // Find instruction in this basic block that defines flags
                    Instruction x = p.prevInstructionInCodeOrder();
                    Operand result = MIR_Unary.getResult(next);
                    boolean foundCmp = false;
                    outer: while (!Label.conforms(x)) {
                        Enumeration<Operand> e = x.getUses();
                        while (e.hasMoreElements()) {
                            // used by the <cmp> or intervening instruction
                            if (e.nextElement().similar(result)) {
                                break outer;
                            }
                        }
                        if (PhysicalDefUse.definesEFLAGS(x.operator()) && !PhysicalDefUse.usesEFLAGS(x.operator())) {
                            // we found a <cmp> that doesn't use the result or the flags
                            // that would be clobbered by the xor
                            foundCmp = true;
                            break outer;
                        }
                        x = x.prevInstructionInCodeOrder();
                    }
                    if (foundCmp) {
                        // We found the <cmp>, mutate the movzx__b into an xor and insert it before the <cmp>
                        next.remove();
                        MIR_BinaryAcc.mutate(next, IA32_XOR, result, MIR_Unary.getVal(next));
                        x.insertBefore(next);
                        // get ready for the next instruction
                        next = p.nextInstructionInCodeOrder();
                    }
                }
                break;
            case IA32_LEA_opcode:
                {
                    // Sometimes we're over eager in BURS in using LEAs and after register
                    // allocation we can simplify to the accumulate form
                    // replace reg1 = LEA [reg1 + reg2] with reg1 = reg1 + reg2
                    // replace reg1 = LEA [reg1 + c1] with reg1 = reg1 + c1
                    // replace reg1 = LEA [reg1 << c1] with reg1 = reg1 << c1
                    MemoryOperand value = MIR_Lea.getValue(p);
                    RegisterOperand result = MIR_Lea.getResult(p);
                    if ((value.base != null && value.base.getRegister() == result.getRegister()) || (value.index != null && value.index.getRegister() == result.getRegister())) {
                        // Calculate what flags are defined in coming instructions before a use of a flag or BBend
                        Instruction x = next;
                        int futureDefs = 0;
                        while (!BBend.conforms(x) && !PhysicalDefUse.usesEFLAGS(x.operator())) {
                            futureDefs |= x.operator().implicitDefs;
                            x = x.nextInstructionInCodeOrder();
                        }
                        // If the flags will be destroyed prior to use or we reached the end of the basic block
                        if (BBend.conforms(x) || (futureDefs & PhysicalDefUse.maskAF_CF_OF_PF_SF_ZF) == PhysicalDefUse.maskAF_CF_OF_PF_SF_ZF) {
                            if (value.base != null && value.index != null && value.index.getRegister() == result.getRegister() && value.disp.isZero() && value.scale == 0) {
                                // reg1 = lea [base + reg1] -> add reg1, base
                                MIR_BinaryAcc.mutate(p, IA32_ADD, result, value.base);
                            } else if (value.base != null && value.base.getRegister() == result.getRegister() && value.index != null && value.disp.isZero() && value.scale == 0) {
                                // reg1 = lea [reg1 + index] -> add reg1, index
                                MIR_BinaryAcc.mutate(p, IA32_ADD, result, value.index);
                            } else if (value.base != null && value.base.getRegister() == result.getRegister() && value.index == null) {
                                if (VM.VerifyAssertions)
                                    VM._assert(fits(value.disp, 32));
                                // reg1 = lea [reg1 + disp] -> add reg1, disp
                                MIR_BinaryAcc.mutate(p, IA32_ADD, result, IC(value.disp.toInt()));
                            } else if (value.base == null && value.index != null && value.index.getRegister() == result.getRegister() && value.scale == 0) {
                                if (VM.VerifyAssertions)
                                    VM._assert(fits(value.disp, 32));
                                // reg1 = lea [reg1 + disp] -> add reg1, disp
                                MIR_BinaryAcc.mutate(p, IA32_ADD, result, IC(value.disp.toInt()));
                            } else if (value.base == null && value.index != null && value.index.getRegister() == result.getRegister() && value.disp.isZero()) {
                                // reg1 = lea [reg1 << scale] -> shl reg1, scale
                                if (value.scale == 0) {
                                    p.remove();
                                } else if (value.scale == 1) {
                                    MIR_BinaryAcc.mutate(p, IA32_ADD, result, value.index);
                                } else {
                                    MIR_BinaryAcc.mutate(p, IA32_SHL, result, IC(value.scale));
                                }
                            }
                        }
                    }
                }
                break;
            case IA32_FCLEAR_opcode:
                expandFClear(p, ir);
                break;
            case IA32_JCC2_opcode:
                p.insertBefore(MIR_CondBranch.create(IA32_JCC, MIR_CondBranch2.getClearCond1(p), MIR_CondBranch2.getClearTarget1(p), MIR_CondBranch2.getClearBranchProfile1(p)));
                MIR_CondBranch.mutate(p, IA32_JCC, MIR_CondBranch2.getClearCond2(p), MIR_CondBranch2.getClearTarget2(p), MIR_CondBranch2.getClearBranchProfile2(p));
                break;
            case CALL_SAVE_VOLATILE_opcode:
                p.changeOperatorTo(IA32_CALL);
                break;
            case IA32_LOCK_CMPXCHG_opcode:
                p.insertBefore(MIR_Empty.create(IA32_LOCK));
                p.changeOperatorTo(IA32_CMPXCHG);
                break;
            case IA32_LOCK_CMPXCHG8B_opcode:
                p.insertBefore(MIR_Empty.create(IA32_LOCK));
                p.changeOperatorTo(IA32_CMPXCHG8B);
                break;
            case YIELDPOINT_PROLOGUE_opcode:
                expandYieldpoint(p, ir, Entrypoints.optThreadSwitchFromPrologueMethod, IA32ConditionOperand.NE());
                break;
            case YIELDPOINT_EPILOGUE_opcode:
                expandYieldpoint(p, ir, Entrypoints.optThreadSwitchFromEpilogueMethod, IA32ConditionOperand.NE());
                break;
            case YIELDPOINT_BACKEDGE_opcode:
                expandYieldpoint(p, ir, Entrypoints.optThreadSwitchFromBackedgeMethod, IA32ConditionOperand.GT());
                break;
            case YIELDPOINT_OSR_opcode:
                // must yield, does not check threadSwitch request
                expandUnconditionalYieldpoint(p, ir, Entrypoints.optThreadSwitchFromOsrOptMethod);
                break;
        }
    }
    return 0;
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) Enumeration(java.util.Enumeration) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) IA32ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ia32.IA32ConditionOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) MachineCodeOffsets(org.jikesrvm.compilers.opt.mir2mc.MachineCodeOffsets) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 3 with IntConstantOperand

use of org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand 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 IntConstantOperand

use of org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand in project JikesRVM by JikesRVM.

the class LoopUnrolling method unrollLeaf.

boolean unrollLeaf(LSTNode t, IR ir) {
    int instructionsInLoop = 0;
    BasicBlock exitBlock = null, backEdgeBlock = null, succBlock = null, predBlock = null;
    BitVector nloop = t.getLoop();
    BasicBlock header = t.header;
    Instruction tmp;
    if (ir.hasReachableExceptionHandlers()) {
        report("0 IR may have exception handlers");
        return false;
    }
    // determine loop structure by looking at its blocks
    Enumeration<BasicBlock> loopBlocks = ir.getBasicBlocks(nloop);
    int blocks = 0;
    while (loopBlocks.hasMoreElements()) {
        BasicBlock b = loopBlocks.nextElement();
        blocks++;
        // check for size
        instructionsInLoop += b.getNumberOfRealInstructions();
        if (instructionsInLoop > MaxInstructions) {
            report("1 is too big");
            return false;
        }
        // look at the in edges. We want the header to be the only
        // block with out of loop incoming edges.
        Enumeration<BasicBlock> e = b.getIn();
        if (b != header) {
            while (e.hasMoreElements()) {
                BasicBlock o = e.nextElement();
                if (!CFGTransformations.inLoop(o, nloop)) {
                    report("2 interior pointers.");
                    return true;
                }
            }
        } else {
            // check the headers predecessors: there should be
            // one out of loop input and one backedge.
            // We can extend this for loops with several backedges,
            // if they all have the same conditions.
            int inEdges = 0;
            while (e.hasMoreElements()) {
                inEdges++;
                BasicBlock o = e.nextElement();
                if (!CFGTransformations.inLoop(o, nloop)) {
                    if (predBlock == null) {
                        predBlock = o;
                    } else {
                        report("3 multi entry header.");
                        return true;
                    }
                } else {
                    if (backEdgeBlock == null) {
                        backEdgeBlock = o;
                    } else {
                        report("4 multiple back edges.");
                        return true;
                    }
                }
            }
        }
        // look at the out edges to find loop exits
        e = b.getOut();
        while (e.hasMoreElements()) {
            BasicBlock out = e.nextElement();
            if (!CFGTransformations.inLoop(out, nloop)) {
                if (exitBlock == null) {
                    exitBlock = b;
                } else {
                    report("5 multiple exit blocks.");
                    return true;
                }
            }
        }
    }
    // exitBlock must equal backEdgeBlock
    if (exitBlock == null) {
        report("6 no exit block found...infinite loop?");
        return true;
    }
    if (exitBlock != backEdgeBlock) {
        report("7 exit block is not immediate predecessor of loop head");
        return true;
    }
    // exitBlock must exit (skip over pads in critical edges)
    while (exitBlock.getNumberOfOut() == 1 && exitBlock.getNumberOfIn() == 1) {
        exitBlock = exitBlock.getIn().nextElement();
    }
    if (exitBlock == header && blocks > 1) {
        report("6 while loop? (" + blocks + ")");
        return true;
    }
    // So far, so good. Examine the exit test.
    Instruction origBranch = exitBlock.firstBranchInstruction();
    if (origBranch != exitBlock.lastRealInstruction()) {
        Instruction aGoto = origBranch.nextInstructionInCodeOrder();
        if (aGoto.getOpcode() != GOTO_opcode) {
            report("7 too complex exit");
            return true;
        }
        succBlock = Label.getBlock(Goto.getTarget(aGoto).target).block;
        if (VM.VerifyAssertions) {
            VM._assert(aGoto == exitBlock.lastRealInstruction());
        }
    } else {
        succBlock = exitBlock.getFallThroughBlock();
    }
    if (origBranch.getOpcode() != INT_IFCMP_opcode) {
        report("8 branch isn't int_ifcmp: " + origBranch.operator() + ".");
        return true;
    }
    // examine operands:
    Operand op1 = follow(IfCmp.getVal1(origBranch));
    Operand op2 = follow(IfCmp.getVal2(origBranch));
    ConditionOperand cond = (ConditionOperand) IfCmp.getCond(origBranch).copy();
    RegisterOperand ifcmpGuard = IfCmp.getGuardResult(origBranch);
    float backBranchProbability = IfCmp.getBranchProfile(origBranch).takenProbability;
    if (!loopInvariant(op2, nloop, 4)) {
        if (loopInvariant(op1, nloop, 4)) {
            Operand op = op1;
            op1 = op2;
            op2 = op;
            cond.flipOperands();
        } else {
            if (DEBUG) {
                printDefs(op1, nloop, 4);
                printDefs(op2, nloop, 4);
                VM.sysWriteln(origBranch.toString());
            }
            report("8a op1 and op2 may not be loop invariant");
            return true;
        }
    }
    BasicBlock target = Label.getBlock(IfCmp.getTarget(origBranch).target).block;
    if (!(op1 instanceof RegisterOperand)) {
        report("9 op1 of ifcmp isn't a register");
        return true;
    }
    RegisterOperand rop1 = (RegisterOperand) op1;
    Register reg = rop1.getRegister();
    if (reg.isPhysical()) {
        report("10 loops over physical register");
        return false;
    }
    if (succBlock == header && !CFGTransformations.inLoop(target, nloop)) {
        succBlock = target;
        target = header;
        cond.flipCode();
    }
    if (target != header) {
        report("11 ifcmp doesn't jump to header");
        return true;
    }
    Instruction iterator = null;
    Enumeration<Operand> defs = new RealDefs(rop1);
    while (defs.hasMoreElements()) {
        Operand def = defs.nextElement();
        Instruction inst = def.instruction;
        BasicBlock block = inst.getBasicBlock();
        // VM.sysWriteln(block + ": " + inst);
        if (CFGTransformations.inLoop(block, nloop)) {
            if (iterator == null) {
                iterator = inst;
            } else {
                report("12 iterator not unique.");
                return true;
            }
        }
    }
    if (iterator == null) {
        report("15 iterator not found.");
        return true;
    }
    if (iterator.getOpcode() != INT_ADD_opcode) {
        // dumpIR (ir, "malformed");
        report("16 iterator is no addition: " + iterator.operator());
        return true;
    }
    if (!rop1.similar(follow(Binary.getVal1(iterator)))) {
        // dumpIR (ir, "malformed");
        report("17 malformed iterator.\n" + iterator);
        return true;
    }
    Operand strideOp = follow(Binary.getVal2(iterator));
    if (!(strideOp instanceof IntConstantOperand)) {
        report("18 stride not constant");
        return true;
    }
    int stride = ((IntConstantOperand) strideOp).value;
    if (stride != 1 && stride != -1) {
        report("18b stride != +/-1 (" + stride + ")");
        return true;
    }
    if ((stride == 1 && ((cond.value != ConditionOperand.LESS) && cond.value != ConditionOperand.LESS_EQUAL && cond.value != ConditionOperand.NOT_EQUAL)) || (stride == -1 && ((cond.value != ConditionOperand.GREATER) && cond.value != ConditionOperand.GREATER_EQUAL && cond.value != ConditionOperand.NOT_EQUAL))) {
        report("19 unexpected condition: " + cond + "\n" + iterator + "\n" + origBranch);
        return true;
    }
    RegisterOperand outerGuard;
    BasicBlock outer = predBlock;
    while (outer.getNumberOfOut() == 1 && outer.getNumberOfIn() == 1) {
        outer = outer.getIn().nextElement();
    }
    if (outer.getNumberOfIn() > 0 && outer.getNumberOfOut() < 2) {
        report("23 no suitable outer guard found.");
        return true;
    }
    tmp = outer.firstBranchInstruction();
    if (tmp != null && GuardResultCarrier.conforms(tmp)) {
        outerGuard = GuardResultCarrier.getGuardResult(tmp);
    } else {
        outerGuard = ir.regpool.makeTempValidation();
    }
    // //////////
    // transfom
    // transform this:
    // 
    // Orig:
    // B
    // if i CC b goto Orig
    // else goto exit
    // 
    // exit:
    // 
    // into this:
    // 
    // 
    // stride == 1:           common:                      stride == -1:
    // --------------------------------------------------------------------------
    // guard0:
    // limit = b;
    // if a > b goto Orig                                  if b > a goto Orig
    // else guard1
    // 
    // 
    // guard 1:
    // remainder = b - a;                                  remainder = a - b;
    // if cond == '<='                                    if cond == '>='
    // remainder++;                                         remainder++;
    // remainder = remainder & 3
    // limit = a + remainder                               limit = a - remainder
    // if cond == '<='                                    if cond == '>='
    // limit--;                                            limit++;
    // if remainder == 0 goto mllp
    // goto Orig
    // 
    // Orig:
    // LOOP;
    // if i CC limit goto Orig
    // else guard2
    // 
    // guard2: if i CC b goto mllp
    // else exit
    // 
    // mllp: // landing pad
    // goto ml
    // 
    // ml:
    // LOOP;LOOP;LOOP;LOOP;
    // if i CC b goto ml
    // else exit
    // 
    // exit:
    // --------------------------------------------------------------------------
    report("...transforming.");
    if (DEBUG && ir.options.hasMETHOD_TO_PRINT() && ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString())) {
        dumpIR(ir, "before unroll");
    }
    CFGTransformations.killFallThroughs(ir, nloop);
    BasicBlock[] handles = makeSomeCopies(unrollFactor, ir, nloop, blocks, header, exitBlock, exitBlock);
    BasicBlock mainHeader = handles[0];
    BasicBlock mainExit = handles[1];
    // test block for well formed bounds
    BasicBlock guardBlock0 = header.createSubBlock(header.firstInstruction().getBytecodeIndex(), ir);
    predBlock.redirectOuts(header, guardBlock0, ir);
    // test block for iteration alignemnt
    BasicBlock guardBlock1 = header.createSubBlock(header.firstInstruction().getBytecodeIndex(), ir);
    // landing pad for orig loop
    BasicBlock olp = header.createSubBlock(header.firstInstruction().getBytecodeIndex(), ir);
    olp.setLandingPad();
    BasicBlock predSucc = predBlock.nextBasicBlockInCodeOrder();
    if (predSucc != null) {
        ir.cfg.breakCodeOrder(predBlock, predSucc);
        ir.cfg.linkInCodeOrder(olp, predSucc);
    }
    ir.cfg.linkInCodeOrder(predBlock, guardBlock0);
    ir.cfg.linkInCodeOrder(guardBlock0, guardBlock1);
    ir.cfg.linkInCodeOrder(guardBlock1, olp);
    // guard block for main loop
    BasicBlock guardBlock2 = header.createSubBlock(header.firstInstruction().getBytecodeIndex(), ir);
    // landing pad for main loop
    BasicBlock landingPad = header.createSubBlock(header.firstInstruction().getBytecodeIndex(), ir);
    landingPad.setLandingPad();
    BasicBlock mainLoop = exitBlock.nextBasicBlockInCodeOrder();
    ir.cfg.breakCodeOrder(exitBlock, mainLoop);
    ir.cfg.linkInCodeOrder(exitBlock, guardBlock2);
    ir.cfg.linkInCodeOrder(guardBlock2, landingPad);
    ir.cfg.linkInCodeOrder(landingPad, mainLoop);
    RegisterOperand remainder = ir.regpool.makeTemp(rop1.getType());
    RegisterOperand limit = ir.regpool.makeTemp(rop1.getType());
    // test whether a <= b for stride == 1 and a >= b for stride == -1
    tmp = guardBlock0.lastInstruction();
    tmp.insertBefore(Move.create(INT_MOVE, limit, op2.copy()));
    ConditionOperand g0cond = ConditionOperand.GREATER_EQUAL();
    if (stride == -1)
        g0cond = ConditionOperand.LESS_EQUAL();
    tmp.insertBefore(IfCmp.create(INT_IFCMP, outerGuard.copyD2D(), rop1.copyD2U(), op2.copy(), g0cond, olp.makeJumpTarget(), BranchProfileOperand.unlikely()));
    tmp.insertBefore(Goto.create(GOTO, guardBlock1.makeJumpTarget()));
    // align the loop iterations
    tmp = guardBlock1.lastInstruction();
    if (stride == 1) {
        tmp.insertBefore(Binary.create(INT_SUB, remainder, op2.copy(), rop1.copyD2U()));
    } else {
        tmp.insertBefore(Binary.create(INT_SUB, remainder, rop1.copyD2U(), op2.copy()));
    }
    if (cond.isGREATER_EQUAL() || cond.isLESS_EQUAL()) {
        tmp.insertBefore(Binary.create(INT_ADD, remainder.copyD2D(), remainder.copyD2U(), new IntConstantOperand(1)));
    }
    tmp.insertBefore(Binary.create(INT_ADD, remainder.copyD2D(), remainder.copyD2U(), new IntConstantOperand(-1)));
    tmp.insertBefore(Binary.create(INT_AND, remainder.copyD2D(), remainder.copyD2U(), new IntConstantOperand(unrollFactor - 1)));
    tmp.insertBefore(Binary.create(INT_ADD, remainder.copyD2D(), remainder.copyD2U(), new IntConstantOperand(1)));
    if (stride == 1) {
        tmp.insertBefore(Binary.create(INT_ADD, limit.copyD2U(), op1.copy(), remainder.copyD2U()));
    } else {
        tmp.insertBefore(Binary.create(INT_SUB, limit.copyD2U(), op1.copy(), remainder.copyD2U()));
    }
    if (cond.isLESS_EQUAL()) {
        tmp.insertBefore(Binary.create(INT_ADD, limit.copyD2D(), limit.copyD2U(), new IntConstantOperand(-1)));
    }
    if (cond.isGREATER_EQUAL()) {
        tmp.insertBefore(Binary.create(INT_ADD, limit.copyD2D(), limit.copyD2U(), new IntConstantOperand(1)));
    }
    tmp.insertBefore(Goto.create(GOTO, olp.makeJumpTarget()));
    // build landing pad for original loop
    tmp = olp.lastInstruction();
    tmp.insertBefore(Goto.create(GOTO, header.makeJumpTarget()));
    // change the back branch in the original loop
    deleteBranches(exitBlock);
    tmp = exitBlock.lastInstruction();
    tmp.insertBefore(IfCmp.create(INT_IFCMP, outerGuard.copyD2D(), rop1.copyU2U(), limit.copyD2U(), (ConditionOperand) cond.copy(), header.makeJumpTarget(), new BranchProfileOperand(1.0f - 1.0f / (unrollFactor / 2))));
    tmp.insertBefore(Goto.create(GOTO, guardBlock2.makeJumpTarget()));
    // only enter main loop if iterations left
    tmp = guardBlock2.lastInstruction();
    tmp.insertBefore(IfCmp.create(INT_IFCMP, outerGuard.copyD2D(), rop1.copyU2U(), op2.copy(), (ConditionOperand) cond.copy(), landingPad.makeJumpTarget(), new BranchProfileOperand(backBranchProbability)));
    tmp.insertBefore(Goto.create(GOTO, succBlock.makeJumpTarget()));
    // landing pad jumps to mainHeader
    tmp = landingPad.lastInstruction();
    tmp.insertBefore(Goto.create(GOTO, mainHeader.makeJumpTarget()));
    // repair back edge in mainExit
    if (VM.VerifyAssertions)
        VM._assert(mainExit != null);
    tmp = mainExit.lastInstruction();
    if (VM.VerifyAssertions) {
        VM._assert((mainExit.lastRealInstruction() == null) || !mainExit.lastRealInstruction().isBranch());
    }
    tmp.insertBefore(IfCmp.create(INT_IFCMP, ifcmpGuard.copyU2U(), rop1.copyU2U(), op2.copy(), (ConditionOperand) cond.copy(), mainHeader.makeJumpTarget(), new BranchProfileOperand(1.0f - (1.0f - backBranchProbability) * unrollFactor)));
    tmp.insertBefore(Goto.create(GOTO, succBlock.makeJumpTarget()));
    // recompute normal outs
    guardBlock0.recomputeNormalOut(ir);
    guardBlock1.recomputeNormalOut(ir);
    olp.recomputeNormalOut(ir);
    guardBlock2.recomputeNormalOut(ir);
    exitBlock.recomputeNormalOut(ir);
    landingPad.recomputeNormalOut(ir);
    mainExit.recomputeNormalOut(ir);
    if (DEBUG && ir.options.hasMETHOD_TO_PRINT() && ir.options.fuzzyMatchMETHOD_TO_PRINT(ir.method.toString())) {
        dumpIR(ir, "after unroll");
    }
    return false;
}
Also used : BitVector(org.jikesrvm.util.BitVector) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) 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) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)

Example 5 with IntConstantOperand

use of org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand in project JikesRVM by JikesRVM.

the class BURS_Helpers method TRAP_IF_IMM.

/**
 * Take the generic LIR trap_if and coerce into the limited
 * vocabulary understood by the C trap handler on PPC.  See
 * TrapConstants.java.  Also see ConvertToLowLevelIR.java
 * which generates most of these TRAP_IFs.
 *
 * @param s the instruction to expand
 * @param longConstant is the argument a long constant?
 */
protected final void TRAP_IF_IMM(Instruction s, boolean longConstant) {
    RegisterOperand gRes = TrapIf.getClearGuardResult(s);
    RegisterOperand v1 = (RegisterOperand) TrapIf.getClearVal1(s);
    ConditionOperand cond = TrapIf.getClearCond(s);
    TrapCodeOperand tc = TrapIf.getClearTCode(s);
    switch(tc.getTrapCode()) {
        case RuntimeEntrypoints.TRAP_ARRAY_BOUNDS:
            {
                IntConstantOperand v2 = (IntConstantOperand) TrapIf.getClearVal2(s);
                if (cond.isLOWER_EQUAL()) {
                    EMIT(MIR_Trap.mutate(s, PPC_TWI, gRes, new PowerPCTrapOperand(cond), v1, v2, tc));
                } else if (cond.isHIGHER_EQUAL()) {
                    // have flip the operands and use non-immediate so trap handler can recognize.
                    RegisterOperand tmp = regpool.makeTempInt();
                    IntConstant(tmp.getRegister(), v2.value);
                    EMIT(MIR_Trap.mutate(s, PPC_TW, gRes, new PowerPCTrapOperand(cond.flipOperands()), tmp, v1, tc));
                } else {
                    throw new OptimizingCompilerException("Unexpected case of trap_if" + s);
                }
            }
            break;
        case RuntimeEntrypoints.TRAP_DIVIDE_BY_ZERO:
            {
                ConstantOperand v2 = (ConstantOperand) TrapIf.getClearVal2(s);
                if (VM.VerifyAssertions) {
                    if (longConstant) {
                        long val = ((LongConstantOperand) v2).value;
                        boolean caseMatchesExpected = val == 0L && cond.isEQUAL();
                        if (!caseMatchesExpected) {
                            String msg = "Unexpected case of trap_if" + s;
                            VM._assert(VM.NOT_REACHED, msg);
                        }
                    } else {
                        int val = ((IntConstantOperand) v2).value;
                        boolean caseMatchesExpected = val == 0L && cond.isEQUAL();
                        if (!caseMatchesExpected) {
                            String msg = "Unexpected case of trap_if" + s;
                            VM._assert(VM.NOT_REACHED, msg);
                        }
                    }
                }
                if (longConstant) {
                    if (VM.BuildFor32Addr) {
                        // A slightly ugly matter, but we need to deal with combining
                        // the two pieces of a long register from a LONG_ZERO_CHECK.
                        // A little awkward, but probably the easiest workaround...
                        RegisterOperand rr = regpool.makeTempInt();
                        EMIT(MIR_Binary.create(PPC_OR, rr, v1, I(regpool.getSecondReg(v1.getRegister()))));
                        v1 = rr.copyD2U();
                        v2 = IC(0);
                        EMIT(MIR_Trap.mutate(s, PPC_TWI, gRes, new PowerPCTrapOperand(cond), v1, v2, tc));
                    } else {
                        EMIT(MIR_Trap.mutate(s, PPC64_TDI, gRes, new PowerPCTrapOperand(cond), v1, v2, tc));
                    }
                } else {
                    EMIT(MIR_Trap.mutate(s, PPC_TWI, gRes, new PowerPCTrapOperand(cond), v1, v2, tc));
                }
            }
            break;
        default:
            throw new OptimizingCompilerException("Unexpected case of trap_if" + s);
    }
}
Also used : LongConstantOperand(org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) ConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ConstantOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) PowerPCTrapOperand(org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCTrapOperand) PowerPCConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ppc.PowerPCConditionOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException)

Aggregations

IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)49 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)41 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)28 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)23 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)21 LongConstantOperand (org.jikesrvm.compilers.opt.ir.operand.LongConstantOperand)21 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)19 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)18 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)17 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)16 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)16 DoubleConstantOperand (org.jikesrvm.compilers.opt.ir.operand.DoubleConstantOperand)15 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)15 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)15 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)14 FloatConstantOperand (org.jikesrvm.compilers.opt.ir.operand.FloatConstantOperand)13 ConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ConstantOperand)12 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)11 TypeReference (org.jikesrvm.classloader.TypeReference)10 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)9