Search in sources :

Example 51 with Register

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

the class StackManager method insertExceptionalPrologue.

/**
 * prologue for the exceptional case.
 * (1) R0 is the only available scratch register.
 * (2) stack overflow check has to come first.
 */
void insertExceptionalPrologue() {
    if (VM.VerifyAssertions) {
        VM._assert((frameSize & (STACKFRAME_ALIGNMENT - 1)) == 0, "Stack frame alignment error");
    }
    if (frameSize >= 0x7ff0) {
        throw new OptimizingCompilerException("Stackframe size exceeded!");
    }
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
    Register FP = phys.getFP();
    Register TR = phys.getTR();
    Register TSR = phys.getTSR();
    Register R0 = phys.getTemp();
    Register S1 = phys.getGPR(LAST_SCRATCH_GPR);
    boolean interruptible = ir.method.isInterruptible();
    boolean stackOverflow = interruptible;
    boolean yp = hasPrologueYieldpoint();
    Instruction ptr = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
    if (VM.VerifyAssertions)
        VM._assert(ptr.getOpcode() == IR_PROLOGUE_opcode);
    // Stack overflow check
    if (stackOverflow) {
        // R0 is fairly useless (can't be operand 1 of an addi or the base ptr
        // of a load) so, free up S1 for use by briefly saving its contents in the
        // return address slot of my caller's frame
        ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(S1), A(FP), IC(STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
        Offset offset = Entrypoints.stackLimitField.getOffset();
        if (VM.VerifyAssertions)
            VM._assert(fits(offset, 16));
        ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S1), A(phys.getTR()), IC(PPCMaskLower16(offset))));
        ptr.insertBefore(MIR_Binary.create(PPC_ADDI, A(R0), A(S1), IC(frameSize)));
        ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S1), A(FP), IC(STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
        // Mutate the Prologue holder instruction into the trap
        MIR_Trap.mutate(ptr, PPC_TAddr, PowerPCTrapOperand.LESS(), A(FP), A(R0), TrapCodeOperand.StackOverflow());
        // advance ptr because we want the remaining instructions to come after
        // the trap
        ptr = ptr.nextInstructionInCodeOrder();
    } else {
        // no stack overflow test, so we must remove the IR_Prologue instruction
        Instruction next = ptr.nextInstructionInCodeOrder();
        ptr.remove();
        ptr = next;
    }
    // Buy stack frame, save LR, caller's FP
    ptr.insertBefore(MIR_Move.create(PPC_MFSPR, A(R0), A(phys.getLR())));
    ptr.insertBefore(MIR_StoreUpdate.create(PPC_STAddrU, A(FP), A(FP), IC(-frameSize)));
    ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(R0), A(FP), IC(frameSize + STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
    // Store cmid
    int cmid = ir.compiledMethod.getId();
    if (cmid <= 0x7fff) {
        ptr.insertBefore(MIR_Unary.create(PPC_LDI, I(R0), IC(cmid)));
    } else {
        ptr.insertBefore(MIR_Unary.create(PPC_LDIS, I(R0), IC(cmid >>> 16)));
        ptr.insertBefore(MIR_Binary.create(PPC_ORI, I(R0), I(R0), IC(cmid & 0xffff)));
    }
    ptr.insertBefore(MIR_Store.create(PPC_STW, I(R0), A(FP), IC(STACKFRAME_METHOD_ID_OFFSET.toInt())));
    // Now save the volatile/nonvolatile registers
    if (ir.compiledMethod.isSaveVolatile()) {
        saveVolatiles(ptr);
    }
    saveNonVolatiles(ptr);
    // Threadswitch
    if (yp) {
        Offset offset = Entrypoints.takeYieldpointField.getOffset();
        if (VM.VerifyAssertions)
            VM._assert(fits(offset, 16));
        ptr.insertBefore(MIR_Load.create(PPC_LInt, I(R0), A(TR), IC(PPCMaskLower16(offset))));
        ptr.insertBefore(MIR_Binary.create(PPC_CMPI, I(TSR), I(R0), IC(0)));
    }
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ppc.PhysicalRegisterSet) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) OptimizingCompilerException(org.jikesrvm.compilers.opt.OptimizingCompilerException) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Offset(org.vmmagic.unboxed.Offset)

Example 52 with Register

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

the class StackManager method restoreScratchRegistersBefore.

/**
 * Walk over the currently available scratch registers.
 *
 * <p>For any scratch register r which is def'ed by instruction s,
 * spill r before s and remove r from the pool of available scratch
 * registers.
 *
 * <p>For any scratch register r which is used by instruction s,
 * restore r before s and remove r from the pool of available scratch
 * registers.
 *
 * <p>For any scratch register r which has current contents symb, and
 * symb is spilled to location M, and s defs M: the old value of symb is
 * dead.  Mark this.
 *
 * <p>Invalidate any scratch register assignments that are illegal in s.
 */
@Override
public void restoreScratchRegistersBefore(Instruction s) {
    for (Iterator<ScratchRegister> i = scratchInUse.iterator(); i.hasNext(); ) {
        ScratchRegister scratch = i.next();
        if (scratch.getCurrentContents() == null)
            continue;
        if (VERBOSE_DEBUG) {
            System.out.println("RESTORE: consider " + scratch);
        }
        boolean removed = false;
        boolean unloaded = false;
        if (definedIn(scratch.scratch, s) || (s.isCall() && s.operator() != CALL_SAVE_VOLATILE && scratch.scratch.isVolatile())) {
            // are killed.
            if (VERBOSE_DEBUG) {
                System.out.println("RESTORE : unload because defined " + scratch);
            }
            unloadScratchRegisterBefore(s, scratch);
            // update mapping information
            if (VERBOSE_DEBUG) {
                System.out.println("RSRB: End scratch interval " + scratch.scratch + " " + s);
            }
            scratchMap.endScratchInterval(scratch.scratch, s);
            Register scratchContents = scratch.getCurrentContents();
            if (scratchContents != null) {
                if (VERBOSE_DEBUG) {
                    System.out.println("RSRB: End symbolic interval " + scratch.getCurrentContents() + " " + s);
                }
                scratchMap.endSymbolicInterval(scratch.getCurrentContents(), s);
            }
            i.remove();
            removed = true;
            unloaded = true;
        }
        if (usedIn(scratch.scratch, s) || !isLegal(scratch.getCurrentContents(), scratch.scratch, s)) {
            // memory
            if (!unloaded) {
                if (VERBOSE_DEBUG) {
                    System.out.println("RESTORE : unload because used " + scratch);
                }
                unloadScratchRegisterBefore(s, scratch);
                // update mapping information
                if (VERBOSE_DEBUG) {
                    System.out.println("RSRB2: End scratch interval " + scratch.scratch + " " + s);
                }
                scratchMap.endScratchInterval(scratch.scratch, s);
                Register scratchContents = scratch.getCurrentContents();
                if (scratchContents != null) {
                    if (VERBOSE_DEBUG) {
                        System.out.println("RSRB2: End symbolic interval " + scratch.getCurrentContents() + " " + s);
                    }
                    scratchMap.endSymbolicInterval(scratch.getCurrentContents(), s);
                }
            }
            // so restore the correct contents.
            if (VERBOSE_DEBUG) {
                System.out.println("RESTORE : reload because used " + scratch);
            }
            reloadScratchRegisterBefore(s, scratch);
            if (!removed) {
                i.remove();
                removed = true;
            }
        }
    }
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register)

Example 53 with Register

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

the class StackManager method saveVolatiles.

/**
 * Insert code in the prologue to save the
 * volatile registers.
 *
 * @param inst
 */
private void saveVolatiles(Instruction inst) {
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
    // 1. save the volatile GPRs
    Register FP = phys.getFP();
    int i = 0;
    for (Enumeration<Register> e = phys.enumerateVolatileGPRs(); e.hasMoreElements(); i++) {
        Register r = e.nextElement();
        int location = saveVolatileGPRLocation[i];
        inst.insertBefore(MIR_Store.create(PPC_STAddr, A(r), A(FP), IC(location)));
    }
    // 2. save the volatile FPRs
    i = 0;
    for (Enumeration<Register> e = phys.enumerateVolatileFPRs(); e.hasMoreElements(); i++) {
        Register r = e.nextElement();
        int location = saveVolatileFPRLocation[i];
        inst.insertBefore(MIR_Store.create(PPC_STFD, D(r), A(FP), IC(location)));
    }
    // 3. Save some special registers
    Register temp = phys.getTemp();
    inst.insertBefore(MIR_Move.create(PPC_MFSPR, I(temp), I(phys.getXER())));
    inst.insertBefore(MIR_Store.create(PPC_STW, I(temp), A(FP), IC(saveXERLocation)));
    inst.insertBefore(MIR_Move.create(PPC_MFSPR, A(temp), A(phys.getCTR())));
    inst.insertBefore(MIR_Store.create(PPC_STAddr, A(temp), A(FP), IC(saveCTRLocation)));
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ppc.PhysicalRegisterSet) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet)

Example 54 with Register

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

the class StackManager method restoreVolatileRegisters.

/**
 * Insert code before a return instruction to restore the
 * volatile registers.
 *
 * @param inst the return instruction
 */
private void restoreVolatileRegisters(Instruction inst) {
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
    // 1. restore the volatile GPRs
    Register FP = phys.getFP();
    int i = 0;
    for (Enumeration<Register> e = phys.enumerateVolatileGPRs(); e.hasMoreElements(); i++) {
        Register r = e.nextElement();
        int location = saveVolatileGPRLocation[i];
        inst.insertBefore(MIR_Load.create(PPC_LAddr, A(r), A(FP), IC(location)));
    }
    // 2. restore the volatile FPRs
    i = 0;
    for (Enumeration<Register> e = phys.enumerateVolatileFPRs(); e.hasMoreElements(); i++) {
        Register r = e.nextElement();
        int location = saveVolatileFPRLocation[i];
        inst.insertBefore(MIR_Load.create(PPC_LFD, D(r), A(FP), IC(location)));
    }
    // 3. Restore some special registers
    Register temp = phys.getTemp();
    inst.insertBefore(MIR_Load.create(PPC_LInt, I(temp), A(FP), IC(saveXERLocation)));
    inst.insertBefore(MIR_Move.create(PPC_MTSPR, I(phys.getXER()), I(temp)));
    inst.insertBefore(MIR_Load.create(PPC_LAddr, A(temp), A(FP), IC(saveCTRLocation)));
    inst.insertBefore(MIR_Move.create(PPC_MTSPR, A(phys.getCTR()), A(temp)));
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ppc.PhysicalRegisterSet) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet)

Example 55 with Register

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

the class StackManager method saveNonVolatiles.

/**
 * Insert code into the prologue to save any used non-volatile
 * registers.
 *
 * @param inst the first instruction after the prologue.
 */
private void saveNonVolatiles(Instruction inst) {
    GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
    int nNonvolatileGPRS = ir.compiledMethod.getNumberOfNonvolatileGPRs();
    if (ir.compiledMethod.isSaveVolatile()) {
        // pretend we use all non-volatiles
        nNonvolatileGPRS = PhysicalRegisterSet.getNumberOfNonvolatileGPRs();
    }
    // 1. save the nonvolatile GPRs
    int n = nNonvolatileGPRS - 1;
    Register FP = phys.getFP();
    if (VM.BuildFor32Addr && n > MULTIPLE_CUTOFF) {
        // use a stm
        Register nv = null;
        for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements() && n >= 0; n--) {
            nv = e.nextElement();
        }
        n++;
        RegisterOperand range = I(nv);
        // YUCK!!! Why is this crap in register operand??
        int offset = getNonvolatileGPROffset(n);
        inst.insertBefore(MIR_Store.create(PPC_STMW, range, A(FP), IC(offset)));
    } else {
        // use a sequence of load instructions
        for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements() && n >= 0; n--) {
            Register nv = e.nextElement();
            int offset = getNonvolatileGPROffset(n);
            inst.insertBefore(MIR_Store.create(PPC_STAddr, A(nv), A(FP), IC(offset)));
        }
    }
    // 1. save the nonvolatile FPRs
    if (ir.compiledMethod.isSaveVolatile()) {
    // DANGER: as an optimization, we assume that a SaveVolatile method
    // will never use nonvolatile FPRs.
    // this invariant is not checked!!!!!
    // TODO: We really need some way to verify that this is true.
    } else {
        int nNonvolatileFPRS = ir.compiledMethod.getNumberOfNonvolatileFPRs();
        n = nNonvolatileFPRS - 1;
        // use a sequence of load instructions
        for (Enumeration<Register> e = phys.enumerateNonvolatileFPRsBackwards(); e.hasMoreElements() && n >= 0; n--) {
            Register nv = e.nextElement();
            int offset = getNonvolatileFPROffset(n);
            inst.insertBefore(MIR_Store.create(PPC_STFD, D(nv), A(FP), IC(offset)));
        }
    }
}
Also used : GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register)

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