Search in sources :

Example 61 with Instruction

use of org.jikesrvm.compilers.opt.ir.Instruction 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 62 with Instruction

use of org.jikesrvm.compilers.opt.ir.Instruction 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 63 with Instruction

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

the class EnterSSA method removeUnreachableOperands.

@SuppressWarnings("unused")
private void removeUnreachableOperands(HashSet<Instruction> scalarPhis) {
    for (Instruction phi : scalarPhis) {
        boolean didSomething = true;
        while (didSomething) {
            didSomething = false;
            for (int j = 0; j < Phi.getNumberOfValues(phi); j++) {
                Operand v = Phi.getValue(phi, j);
                if (v instanceof UnreachableOperand) {
                    // rewrite the phi instruction to remove the unreachable
                    // operand
                    didSomething = true;
                    Instruction tmpPhi = phi.copyWithoutLinks();
                    Phi.mutate(phi, PHI, Phi.getResult(tmpPhi), Phi.getNumberOfValues(phi) - 1);
                    int m = 0;
                    for (int k = 0; k < Phi.getNumberOfValues(phi); k++) {
                        if (k == j)
                            continue;
                        Phi.setValue(phi, m, Phi.getValue(tmpPhi, k));
                        Phi.setPred(phi, m, Phi.getPred(tmpPhi, k));
                        m++;
                    }
                }
            }
        }
    }
}
Also used : UnreachableOperand(org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand) BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) HeapOperand(org.jikesrvm.compilers.opt.ir.operand.HeapOperand) UnreachableOperand(org.jikesrvm.compilers.opt.ir.operand.UnreachableOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 64 with Instruction

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

the class EnterSSA method makePhiInstruction.

/**
 * Create a phi-function instruction
 *
 * @param r the symbolic register
 * @param bb the basic block holding the new phi function
 * @return the instruction r = PHI null,null,..,null
 */
private Instruction makePhiInstruction(Register r, BasicBlock bb) {
    int n = bb.getNumberOfIn();
    Enumeration<BasicBlock> in = bb.getIn();
    TypeReference type = null;
    Instruction s = Phi.create(PHI, new RegisterOperand(r, type), n);
    for (int i = 0; i < n; i++) {
        RegisterOperand junk = new RegisterOperand(r, type);
        Phi.setValue(s, i, junk);
        BasicBlock pred = in.nextElement();
        Phi.setPred(s, i, new BasicBlockOperand(pred));
    }
    s.setSourcePosition(SSA_SYNTH_BCI, ir.getGc().getInlineSequence());
    return s;
}
Also used : BasicBlockOperand(org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 65 with Instruction

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

the class EnterSSA method rectifyPhiTypes.

/*
   * Compute type information for operands in each phi instruction.
   *
   * PRECONDITION: Def-use chains computed.
   * SIDE EFFECT: empties the scalarPhis set
   */
private void rectifyPhiTypes() {
    if (DEBUG)
        System.out.println("Rectify phi types.");
    removeAllUnreachablePhis(scalarPhis);
    int noRehashCapacity = (int) (scalarPhis.size() * 1.5f);
    HashMap<Instruction, PhiTypeInformation> phiTypes = new HashMap<Instruction, PhiTypeInformation>(noRehashCapacity);
    while (!scalarPhis.isEmpty()) {
        boolean didSomething = false;
        for (Iterator<Instruction> i = scalarPhis.iterator(); i.hasNext(); ) {
            Instruction phi = i.next();
            phiTypes.put(phi, PhiTypeInformation.NO_NULL_TYPE);
            if (DEBUG)
                System.out.println("PHI: " + phi);
            TypeReference meet = meetPhiType(phi, phiTypes);
            if (DEBUG)
                System.out.println("MEET: " + meet);
            if (meet != null) {
                didSomething = true;
                if (phiTypes.get(phi) == PhiTypeInformation.NO_NULL_TYPE)
                    i.remove();
                RegisterOperand result = (RegisterOperand) Phi.getResult(phi);
                result.setType(meet);
                for (Enumeration<RegisterOperand> e = DefUse.uses(result.getRegister()); e.hasMoreElements(); ) {
                    RegisterOperand rop = e.nextElement();
                    if (rop.getType() != meet) {
                        rop.clearPreciseType();
                        rop.setType(meet);
                    }
                }
            }
        }
        if (!didSomething) {
            // iteration has bottomed out.
            return;
        }
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) HashMap(java.util.HashMap) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Aggregations

Instruction (org.jikesrvm.compilers.opt.ir.Instruction)356 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)204 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)144 BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)117 Register (org.jikesrvm.compilers.opt.ir.Register)106 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)72 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)61 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)61 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)54 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)53 Test (org.junit.Test)49 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)46 TypeReference (org.jikesrvm.classloader.TypeReference)38 BranchOperand (org.jikesrvm.compilers.opt.ir.operand.BranchOperand)38 NullConstantOperand (org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand)35 BasicBlockOperand (org.jikesrvm.compilers.opt.ir.operand.BasicBlockOperand)33 HeapOperand (org.jikesrvm.compilers.opt.ir.operand.HeapOperand)33 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)31 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)28 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)27