Search in sources :

Example 51 with Instruction

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

the class UpdateGCMaps2 method perform.

/**
 *  @param ir the IR
 */
@Override
public void perform(IR ir) {
    GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
    ScratchMap scratchMap = ir.stackManager.getScratchMap();
    RegisterAllocatorState regAllocState = ir.MIRInfo.regAllocState;
    if (LinearScan.GC_DEBUG) {
        System.out.println("SCRATCH MAP:");
        System.out.println();
        System.out.println(scratchMap);
    }
    if (scratchMap.isEmpty())
        return;
    // Walk over each instruction that has a GC point.
    for (GCIRMapElement GCelement : ir.MIRInfo.gcIRMap) {
        // new elements to add to the gc map
        HashSet<RegSpillListElement> newElements = new HashSet<RegSpillListElement>();
        Instruction GCinst = GCelement.getInstruction();
        int dfn = regAllocState.getDFN(GCinst);
        if (LinearScan.GC_DEBUG) {
            VM.sysWrite("GCelement at " + dfn + " , " + GCelement);
        }
        // a set of elements to delete from the GC Map
        HashSet<RegSpillListElement> toDelete = new HashSet<RegSpillListElement>(3);
        // For each element in the GC Map ...
        for (RegSpillListElement elem : GCelement.regSpillList()) {
            if (LinearScan.GC_DEBUG) {
                VM.sysWriteln("Update " + elem);
            }
            if (elem.isSpill()) {
                // check if the spilled value currently is cached in a scratch
                // register
                Register r = elem.getSymbolicReg();
                Register scratch = scratchMap.getScratch(r, dfn);
                if (scratch != null) {
                    if (LinearScan.GC_DEBUG) {
                        VM.sysWriteln("cached in scratch register " + scratch);
                    }
                    // we will add a new element noting that the scratch register
                    // also must be including in the GC map
                    RegSpillListElement newElem = new RegSpillListElement(r);
                    newElem.setRealReg(scratch);
                    newElements.add(newElem);
                    // valid value
                    if (scratchMap.isDirty(GCinst, r)) {
                        toDelete.add(elem);
                    }
                }
            } else {
                // check if the physical register is currently spilled.
                int n = elem.getRealRegNumber();
                Register r = phys.get(n);
                if (scratchMap.isScratch(r, dfn)) {
                    // spilled.
                    if (LinearScan.GC_DEBUG) {
                        VM.sysWriteln("CHANGE to spill location " + regAllocState.getSpill(r));
                    }
                    elem.setSpill(regAllocState.getSpill(r));
                }
            }
        }
        // delete all obsolete elements
        for (RegSpillListElement deadElem : toDelete) {
            GCelement.deleteRegSpillElement(deadElem);
        }
        // add each new Element to the gc map
        for (RegSpillListElement newElem : newElements) {
            GCelement.addRegSpillElement(newElem);
        }
    }
}
Also used : GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) Register(org.jikesrvm.compilers.opt.ir.Register) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) GCIRMapElement(org.jikesrvm.compilers.opt.ir.GCIRMapElement) RegSpillListElement(org.jikesrvm.compilers.opt.ir.RegSpillListElement) HashSet(java.util.HashSet)

Example 52 with Instruction

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

the class CallingConvention method expandCallingConventions.

/**
 * Expands calling conventions to make physical registers explicit in the
 * IR when required for calls, returns, and the prologue.
 *
 * @param ir the governing IR
 */
public static void expandCallingConventions(IR ir) {
    Queue<Instruction> calls = new Queue<Instruction>();
    // occur because the newly copied syscalls would be processed, too.
    for (Instruction inst = ir.firstInstructionInCodeOrder(); inst != null; inst = inst.nextInstructionInCodeOrder()) {
        if (inst.isCall()) {
            calls.insert(inst);
        } else if (inst.isReturn()) {
            returnExpand(inst, ir);
        }
    }
    for (Instruction call : calls) {
        callExpand(call, ir);
    }
    // expand the prologue instruction
    expandPrologue(ir);
    if (VM.BuildFor64Addr && ir.stackManager.hasSysCall()) {
        // Recompute def-use data structures due to added blocks
        // for syscall expansion.
        DefUse.computeDU(ir);
        // Temporaries used for parameters might now be in two blocks.
        DefUse.recomputeSpansBasicBlock(ir);
        // The SSA property might be invalidated by two definitions
        // for a temporary used for a return value.
        DefUse.recomputeSSA(ir);
    }
}
Also used : Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Queue(org.jikesrvm.compilers.opt.util.Queue)

Example 53 with Instruction

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

the class CallingConvention method expandPrologue.

private static void expandPrologue(IR ir) {
    boolean useDU = ir.options.getOptLevel() >= 1;
    if (useDU) {
        // set up register lists for dead code elimination.
        DefUse.computeDU(ir);
    }
    Instruction p = ir.firstInstructionInCodeOrder().nextInstructionInCodeOrder();
    if (VM.VerifyAssertions)
        VM._assert(p.operator() == IR_PROLOGUE);
    Instruction start = p.nextInstructionInCodeOrder();
    PhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet().asIA32();
    int gprIndex = 0;
    int fprIndex = 0;
    int paramByteOffset = ir.incomingParameterBytes() + 2 * WORDSIZE;
    // count the number of FPR params in a pre-pass
    int FPRRegisterParams = countFPRParamsInPrologue(p);
    FPRRegisterParams = Math.min(FPRRegisterParams, PhysicalRegisterSet.getNumberOfFPRParams());
    ir.MIRInfo.fpStackHeight = Math.max(ir.MIRInfo.fpStackHeight, FPRRegisterParams);
    // deal with each parameter
    for (Enumeration<Operand> e = p.getDefs(); e.hasMoreElements(); ) {
        RegisterOperand symbOp = (RegisterOperand) e.nextElement();
        TypeReference rType = symbOp.getType();
        if (rType.isFloatingPointType()) {
            int size;
            if (rType.isFloatType()) {
                size = BYTES_IN_FLOAT;
                paramByteOffset -= WORDSIZE;
            } else {
                size = BYTES_IN_DOUBLE;
                paramByteOffset -= 2 * WORDSIZE;
            }
            // if optimizing, only define the register if it has uses
            if (!useDU || symbOp.getRegister().useList != null) {
                if (fprIndex < PhysicalRegisterSet.getNumberOfFPRParams()) {
                    // the 2nd goes in F(k-2), etc...
                    if (SSE2_FULL) {
                        Register param = phys.getFPRParam(fprIndex);
                        if (rType.isFloatType()) {
                            start.insertBefore(MIR_Move.create(IA32_MOVSS, symbOp.copyRO(), F(param)));
                        } else {
                            start.insertBefore(MIR_Move.create(IA32_MOVSD, symbOp.copyRO(), D(param)));
                        }
                    } else {
                        Register param = phys.getFPRParam(FPRRegisterParams - fprIndex - 1);
                        start.insertBefore(MIR_Move.create(IA32_FMOV, symbOp.copyRO(), D(param)));
                    }
                } else {
                    Operand M = new StackLocationOperand(true, paramByteOffset, size);
                    if (SSE2_FULL) {
                        if (rType.isFloatType()) {
                            start.insertBefore(MIR_Move.create(IA32_MOVSS, symbOp.copyRO(), M));
                        } else {
                            start.insertBefore(MIR_Move.create(IA32_MOVSD, symbOp.copyRO(), M));
                        }
                    } else {
                        start.insertBefore(MIR_Move.create(IA32_FMOV, symbOp.copyRO(), M));
                    }
                }
            }
            fprIndex++;
        } else {
            // if optimizing, only define the register if it has uses
            paramByteOffset -= WORDSIZE;
            if (paramIsNativeLongOn64Bit(symbOp)) {
                paramByteOffset -= WORDSIZE;
            }
            if (!useDU || symbOp.getRegister().useList != null) {
                // t is object, 1/2 of a long, int, short, char, byte, or boolean
                if (gprIndex < PhysicalRegisterSet.getNumberOfGPRParams()) {
                    // to give the register allocator more freedom, we
                    // insert two move instructions to get the physical into
                    // the symbolic.  First a move from the physical to a fresh temp
                    // before start and second a move from the temp to the
                    // 'real' parameter symbolic after start.
                    RegisterOperand tmp = ir.regpool.makeTemp(rType);
                    Register param = phys.getGPRParam(gprIndex);
                    RegisterOperand pOp = new RegisterOperand(param, rType);
                    start.insertBefore(PhysicalRegisterTools.makeMoveInstruction(tmp, pOp));
                    Instruction m2 = PhysicalRegisterTools.makeMoveInstruction(symbOp.copyRO(), tmp.copyD2U());
                    start.insertBefore(m2);
                    start = m2;
                } else {
                    int stackLocSize = WORDSIZE;
                    if (VM.BuildFor64Addr && rType.getMemoryBytes() <= BYTES_IN_INT) {
                        stackLocSize = BYTES_IN_INT;
                    }
                    Operand M = new StackLocationOperand(true, paramByteOffset, stackLocSize);
                    start.insertBefore(MIR_Move.create(IA32_MOV, symbOp.copyRO(), M));
                }
            }
            gprIndex++;
        }
    }
    if (VM.VerifyAssertions && paramByteOffset != 2 * WORDSIZE) {
        String msg = "pb = " + paramByteOffset + "; expected " + 2 * WORDSIZE;
        VM._assert(VM.NOT_REACHED, msg);
    }
    removeDefsFromPrologue(p);
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) 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) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) MemoryOperand(org.jikesrvm.compilers.opt.ir.operand.MemoryOperand) GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) PhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.ia32.PhysicalRegisterSet) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) StackLocationOperand(org.jikesrvm.compilers.opt.ir.operand.StackLocationOperand)

Example 54 with Instruction

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

the class MIRSplitRanges method insertMoveBefore.

/**
 * Inserts an instruction to move r1 into r2 before instruction s.
 *
 * @param r1 the move source
 * @param r2 the move target
 * @param s the instruction before which the move needs to be inserted
 */
private static void insertMoveBefore(RegisterOperand r2, RegisterOperand r1, Instruction s) {
    Instruction m = PhysicalRegisterTools.makeMoveInstruction(r2, r1);
    s.insertBefore(m);
}
Also used : Instruction(org.jikesrvm.compilers.opt.ir.Instruction)

Example 55 with Instruction

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

the class MIRSplitRanges method perform.

/**
 * The main method.<p>
 *
 * We split live ranges for registers around PEIs which have catch
 * blocks.  Suppose we have a
 * PEI s which uses a symbolic register r1.  We must ensure that after
 * register allocation, r1 is NOT assigned to a scratch location in s,
 * since this would mess up code in the catch block that uses r1.<p>
 *
 * So, instead, we introduce a new temporary r2 which holds the value of
 * r1.  The live range for r2 spans only the instruction s.  Later, we
 * will ensure that r2 is never spilled.<p>
 *
 * TODO: This could be implemented more efficiently.
 *
 * @param ir the governing IR
 */
@Override
public final void perform(IR ir) {
    java.util.HashMap<Register, Register> newMap = new java.util.HashMap<Register, Register>(5);
    for (Enumeration<BasicBlock> be = ir.getBasicBlocks(); be.hasMoreElements(); ) {
        BasicBlock bb = be.nextElement();
        for (Enumeration<Instruction> ie = bb.forwardInstrEnumerator(); ie.hasMoreElements(); ) {
            Instruction s = ie.nextElement();
            ;
            // clear the cache of register assignments
            newMap.clear();
            // here and in RegisterRestrictions!
            if (s.isPEI() && s.operator() != IR_PROLOGUE) {
                if (bb.hasApplicableExceptionalOut(s) || !RegisterRestrictions.SCRATCH_IN_PEI) {
                    splitAllLiveRanges(s, newMap, ir, false);
                }
            }
            // (1) Some operands must be in registers
            switch(s.getOpcode()) {
                case MIR_LOWTABLESWITCH_opcode:
                    {
                        RegisterOperand rOp = MIR_LowTableSwitch.getIndex(s);
                        RegisterOperand temp = findOrCreateTemp(rOp, newMap, ir);
                        // NOTE: Index as marked as a DU because LowTableSwitch is
                        // going to destroy the value in the register.
                        // By construction (see ConvertToLowLevelIR), no one will
                        // ever read the value computed by a LowTableSwitch.
                        // Therefore, don't insert a move instruction after the
                        // LowTableSwitch (which would cause IR verification
                        // problems anyways, since LowTableSwitch is a branch).
                        // move r into 'temp' before s
                        insertMoveBefore(temp, rOp.copyRO(), s);
                        rOp.setRegister(temp.getRegister());
                    }
                    break;
            }
        }
    }
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) Register(org.jikesrvm.compilers.opt.ir.Register) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) 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