Search in sources :

Example 56 with Register

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

the class StackManager method insertNormalPrologue.

/*
  * Insert the prologue.
  * The available scratch registers are normally: R0, S0, S1
  * However, if this is the prologue for a 'save volatile' frame,
  * then R0 is the only available scratch register.
  * The "normal" prologue must perform the following tasks:
  *    stack overflow check
  *    set TSR for the yieldpoint if there is a prologue yieldpoint instruction
  *    save lr
  *    store cmid
  *    buy stack frame
  *    store any used non volatiles
  * We schedule the prologue for this combination of operations,
  * since it is currently the common case.
  * When this changes, this code should be modifed accordingly.
  * The desired sequence is:
  *  1    mflr    00  # return addr
  *  2    l       S1 takeYieldpointOffset(PR)                # setting TSR for yield point
  *  3    stu     FP -frameSize(FP)                          # buy frame, save caller's fp
  *  4    l       S0 stackLimitOffset(S0)                    # stack overflow check
  *  5    <save used non volatiles>
  *  6    cmpi    TSR S1 0x0                                 # setting TSR for yield point (S1 is now free)
  *  7    lil     S1 CMID                                    # cmid
  *  8    st      00 STACKFRAME_RETURN_ADDRESS_OFFSET(FP)  # return addr (00 is now free)
  *  9    st      S1 STACKFRAME_METHOD_ID_OFFSET(FP)         # cmid
  *  10   tgt     S0, FP                                     # stack overflow check (already bought frame)
  */
/**
 * Schedule prologue for 'normal' case (see above)
 */
@Override
public void insertNormalPrologue() {
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
    Register FP = phys.getFP();
    Register TR = phys.getTR();
    Register TSR = phys.getTSR();
    Register R0 = phys.getTemp();
    Register S0 = phys.getGPR(FIRST_SCRATCH_GPR);
    Register S1 = phys.getGPR(LAST_SCRATCH_GPR);
    boolean interruptible = ir.method.isInterruptible();
    boolean stackOverflow = interruptible;
    boolean yp = hasPrologueYieldpoint();
    int frameFixedSize = getFrameFixedSize();
    ir.compiledMethod.setFrameFixedSize(frameFixedSize);
    if (frameFixedSize >= STACK_SIZE_GUARD || ir.compiledMethod.isSaveVolatile()) {
        insertExceptionalPrologue();
        return;
    }
    Instruction ptr = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
    if (VM.VerifyAssertions)
        VM._assert(ptr.getOpcode() == IR_PROLOGUE_opcode);
    // 1
    ptr.insertBefore(MIR_Move.create(PPC_MFSPR, A(R0), A(phys.getLR())));
    if (yp) {
        Offset offset = Entrypoints.takeYieldpointField.getOffset();
        if (VM.VerifyAssertions)
            VM._assert(fits(offset, 16));
        // 2
        ptr.insertBefore(MIR_Load.create(PPC_LInt, I(S1), A(TR), IC(PPCMaskLower16(offset))));
    }
    // 3
    ptr.insertBefore(MIR_StoreUpdate.create(PPC_STAddrU, A(FP), A(FP), IC(-frameSize)));
    if (stackOverflow) {
        Offset offset = Entrypoints.stackLimitField.getOffset();
        if (VM.VerifyAssertions)
            VM._assert(fits(offset, 16));
        // 4
        ptr.insertBefore(MIR_Load.create(PPC_LAddr, A(S0), A(phys.getTR()), IC(PPCMaskLower16(offset))));
    }
    // Now add any instructions to save the volatiles and nonvolatiles (5)
    saveNonVolatiles(ptr);
    if (yp) {
        // 6
        ptr.insertBefore(MIR_Binary.create(PPC_CMPI, I(TSR), I(S1), IC(0)));
    }
    int cmid = ir.compiledMethod.getId();
    if (cmid <= 0x7fff) {
        // 7
        ptr.insertBefore(MIR_Unary.create(PPC_LDI, I(S1), IC(cmid)));
    } else {
        // 7 (a)
        ptr.insertBefore(MIR_Unary.create(PPC_LDIS, I(S1), IC(cmid >>> 16)));
        // 7 (b)
        ptr.insertBefore(MIR_Binary.create(PPC_ORI, I(S1), I(S1), IC(cmid & 0xffff)));
    }
    ptr.insertBefore(MIR_Store.create(PPC_STAddr, A(R0), A(FP), // 8
    IC(frameSize + STACKFRAME_RETURN_ADDRESS_OFFSET.toInt())));
    // 9
    ptr.insertBefore(MIR_Store.create(PPC_STW, I(S1), A(FP), IC(STACKFRAME_METHOD_ID_OFFSET.toInt())));
    if (stackOverflow) {
        // Mutate the Prologue instruction into the trap
        MIR_Trap.mutate(ptr, PPC_TAddr, PowerPCTrapOperand.GREATER(), A(S0), A(FP), // 10
        TrapCodeOperand.StackOverflow());
    } else {
        // no stack overflow test, so we remove the IR_Prologue instruction
        ptr.remove();
    }
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ppc.PhysicalRegisterSet) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Offset(org.vmmagic.unboxed.Offset)

Example 57 with Register

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

the class StackManager method restoreNonVolatiles.

/**
 * Insert code before a return instruction to restore the nonvolatile
 * registers.
 *
 * @param inst the return instruction
 */
private void restoreNonVolatiles(Instruction inst) {
    GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
    int nNonvolatileGPRS = ir.compiledMethod.getNumberOfNonvolatileGPRs();
    // 1. restore the nonvolatile GPRs
    int n = nNonvolatileGPRS - 1;
    Register FP = phys.getFP();
    if (VM.BuildFor32Addr && n > MULTIPLE_CUTOFF) {
        // use an lm
        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_Load.create(PPC_LMW, range, A(FP), IC(offset)));
    } else {
        for (Enumeration<Register> e = phys.enumerateNonvolatileGPRsBackwards(); e.hasMoreElements() && n >= 0; n--) {
            Register nv = e.nextElement();
            int offset = getNonvolatileGPROffset(n);
            inst.insertBefore(MIR_Load.create(PPC_LAddr, A(nv), A(FP), IC(offset)));
        }
    }
    // Note that save-volatiles are forbidden from using nonvolatile FPRs.
    if (!ir.compiledMethod.isSaveVolatile()) {
        // 1. restore the nonvolatile FPRs
        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_Load.create(PPC_LFD, 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)

Example 58 with Register

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

the class StackManager method insertUnspillBefore.

/**
 * Insert a load of a physical register from a spill location before
 * instruction s.
 *
 * @param s the instruction before which the spill should occur
 * @param r the register (should be physical) to spill
 * @param type one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or
 *                    CONDITION_VALUE
 * @param location the spill location
 */
@Override
public void insertUnspillBefore(Instruction s, Register r, Register type, int location) {
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
    Register FP = phys.getFP();
    if (type.isCondition()) {
        Register temp = phys.getTemp();
        s.insertBefore(MIR_Load.create(PPC_LWZ, I(temp), A(FP), IC(location + BYTES_IN_ADDRESS - BYTES_IN_INT)));
    } else if (type.isDouble()) {
        s.insertBefore(MIR_Load.create(PPC_LFD, D(r), A(FP), IC(location)));
    } else if (type.isFloat()) {
        s.insertBefore(MIR_Load.create(PPC_LFS, F(r), A(FP), IC(location + BYTES_IN_ADDRESS - BYTES_IN_FLOAT)));
    } else if (type.isNatural()) {
        // integer or half of long
        s.insertBefore(MIR_Load.create(PPC_LAddr, A(r), A(FP), IC(location)));
    } else {
        throw new OptimizingCompilerException("insertUnspillBefore", "unknown type:" + type);
    }
}
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)

Example 59 with Register

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

the class StackManager method insertEpilogue.

/**
 * Insert the epilogue before a particular return instruction.
 *
 * @param ret the return instruction.
 */
private void insertEpilogue(Instruction ret) {
    // 1. Restore any saved registers
    if (ir.compiledMethod.isSaveVolatile()) {
        restoreVolatileRegisters(ret);
    }
    restoreNonVolatiles(ret);
    // 2. Restore return address
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asPPC();
    Register temp = phys.getTemp();
    Register FP = phys.getFP();
    ret.insertBefore(MIR_Load.create(PPC_LAddr, A(temp), A(FP), IC(STACKFRAME_RETURN_ADDRESS_OFFSET.toInt() + frameSize)));
    // 3. Load return address into LR
    ret.insertBefore(MIR_Move.create(PPC_MTSPR, A(phys.getLR()), A(phys.getTemp())));
    // 4. Restore old FP
    ret.insertBefore(MIR_Binary.create(PPC_ADDI, A(FP), A(FP), IC(frameSize)));
}
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 60 with Register

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

the class EnterSSA method patchPEIgeneratedValues.

/**
 * Work around some problems with PEI-generated values and
 * handlers.  Namely, if a PEI has a return value, rename the
 * result register before and after the PEI in order to reflect the fact
 * that the PEI may not actually assign the result register.
 */
private void patchPEIgeneratedValues() {
    // this only applies if there are exception handlers
    if (!ir.hasReachableExceptionHandlers())
        return;
    HashSet<Pair<BasicBlock, RegisterOperand>> needed = new HashSet<Pair<BasicBlock, RegisterOperand>>(4);
    Enumeration<BasicBlock> blocks = ir.getBasicBlocks();
    while (blocks.hasMoreElements()) {
        BasicBlock block = blocks.nextElement();
        if (block.getExceptionalOut().hasMoreElements()) {
            Instruction pei = block.lastRealInstruction();
            if (pei != null && pei.isPEI() && ResultCarrier.conforms(pei)) {
                boolean copyNeeded = false;
                RegisterOperand v = ResultCarrier.getResult(pei);
                // void calls and the like... :(
                if (v != null) {
                    Register orig = v.getRegister();
                    {
                        Enumeration<BasicBlock> out = block.getApplicableExceptionalOut(pei);
                        while (out.hasMoreElements()) {
                            BasicBlock exp = out.nextElement();
                            LiveSet explive = live.getLiveInfo(exp).getIn();
                            if (explive.contains(orig)) {
                                copyNeeded = true;
                                break;
                            }
                        }
                    }
                    if (copyNeeded) {
                        Enumeration<BasicBlock> out = block.getApplicableExceptionalOut(pei);
                        while (out.hasMoreElements()) {
                            BasicBlock exp = out.nextElement();
                            needed.add(new Pair<BasicBlock, RegisterOperand>(exp, v));
                        }
                    }
                }
            }
        }
    }
    // having determine where copies should be inserted, now insert them.
    if (!needed.isEmpty()) {
        for (Pair<BasicBlock, RegisterOperand> copy : needed) {
            BasicBlock inBlock = copy.first;
            RegisterOperand registerOp = copy.second;
            TypeReference type = registerOp.getType();
            Register register = registerOp.getRegister();
            Register temp = ir.regpool.getReg(register);
            inBlock.prependInstruction(SSA.makeMoveInstruction(ir, register, temp, type));
            Enumeration<BasicBlock> outBlocks = inBlock.getIn();
            while (outBlocks.hasMoreElements()) {
                BasicBlock outBlock = outBlocks.nextElement();
                Instruction x = SSA.makeMoveInstruction(ir, temp, register, type);
                SSA.addAtEnd(ir, outBlock, x, true);
            }
        }
        // Recompute liveness information.  You might be tempted to incrementally
        // update it, but it's tricky, so resist.....do the obvious, but easy thing!
        prepare();
    }
}
Also used : LiveSet(org.jikesrvm.compilers.opt.liveness.LiveSet) Enumeration(java.util.Enumeration) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) TypeReference(org.jikesrvm.classloader.TypeReference) Pair(org.jikesrvm.util.Pair) 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