Search in sources :

Example 1 with ControlFlowGraph

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

the class CompoundIntervalTest method addRangeChangesEndOfLastIntervalWhenRangesDirectlyFollowEachOther_DefUseSameInstruction.

@Test
public void addRangeChangesEndOfLastIntervalWhenRangesDirectlyFollowEachOther_DefUseSameInstruction() {
    Register reg = new Register(3);
    CompoundInterval ci = new CompoundInterval(DEFAULT_BEGIN, DEFAULT_END, reg);
    assertThat(ci.last().getEnd(), is(DEFAULT_END));
    RegisterAllocatorState regAllocState = new RegisterAllocatorState(1);
    Instruction empty = Empty.create(WRITE_FLOOR);
    Instruction defUse = Empty.create(WRITE_FLOOR);
    Instruction lastUse = Empty.create(WRITE_FLOOR);
    LiveIntervalElement live = new LiveIntervalElement(reg, defUse, lastUse);
    ControlFlowGraph emptyCfg = new ControlFlowGraph(0);
    BasicBlock bb = new BasicBlock(1, null, emptyCfg);
    bb.appendInstruction(empty);
    bb.appendInstruction(defUse);
    bb.appendInstruction(lastUse);
    regAllocState.initializeDepthFirstNumbering(10);
    regAllocState.setDFN(empty, DEFAULT_BEGIN);
    regAllocState.setDFN(defUse, DEFAULT_END);
    regAllocState.setDFN(lastUse, DEFAULT_END + 1);
    BasicInterval bi = ci.addRange(regAllocState, live, bb);
    assertNull(bi);
    assertThat(ci.last().getEnd(), is(DEFAULT_END + 1));
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) ControlFlowGraph(org.jikesrvm.compilers.opt.ir.ControlFlowGraph) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Test(org.junit.Test)

Example 2 with ControlFlowGraph

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

the class CompoundIntervalTest method addRangeChangesEndOfLastIntervalWhenRangesDirectlyFollowEachOther_DefUse.

@Test
public void addRangeChangesEndOfLastIntervalWhenRangesDirectlyFollowEachOther_DefUse() {
    Register reg = new Register(3);
    CompoundInterval ci = new CompoundInterval(DEFAULT_BEGIN, DEFAULT_END, reg);
    assertThat(ci.last().getEnd(), is(DEFAULT_END));
    RegisterAllocatorState regAllocState = new RegisterAllocatorState(1);
    Instruction def = Empty.create(WRITE_FLOOR);
    Instruction lastUse = Empty.create(WRITE_FLOOR);
    LiveIntervalElement live = new LiveIntervalElement(reg, def, lastUse);
    ControlFlowGraph emptyCfg = new ControlFlowGraph(0);
    BasicBlock bb = new BasicBlock(1, null, emptyCfg);
    bb.appendInstruction(def);
    bb.appendInstruction(lastUse);
    regAllocState.initializeDepthFirstNumbering(10);
    regAllocState.setDFN(def, DEFAULT_END);
    regAllocState.setDFN(lastUse, DEFAULT_END + 1);
    BasicInterval bi = ci.addRange(regAllocState, live, bb);
    assertNull(bi);
    assertThat(ci.last().getEnd(), is(DEFAULT_END + 1));
}
Also used : Register(org.jikesrvm.compilers.opt.ir.Register) ControlFlowGraph(org.jikesrvm.compilers.opt.ir.ControlFlowGraph) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) Test(org.junit.Test)

Example 3 with ControlFlowGraph

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

the class GenerationContext method createChildContext.

/**
 * Creates a child generation context from this context
 * and callerBB to generate IR for callsite.
 *
 * @param ebag the enclosing exception handlers (null if none)
 * @param callee the callee method to be inlined
 *        (may _not_ be equal to Call.getMethod(callSite).method)
 * @param callSite the Call instruction to be inlined.
 * @return the child context
 */
public GenerationContext createChildContext(ExceptionHandlerBasicBlockBag ebag, NormalMethod callee, Instruction callSite) {
    // Note: In this method, use "this" explicitly to refer to parent fields in order
    // to avoid confusing parent/child fields.
    GenerationContext child = new GenerationContext();
    child.method = callee;
    if (this.options.frequencyCounters() || this.options.inverseFrequencyCounters()) {
        child.branchProfiles = EdgeCounts.getBranchProfiles(callee);
    }
    child.parent = this;
    child.original_cm = this.original_cm;
    // Some state gets directly copied to the child
    child.options = this.options;
    child.temps = this.temps;
    child._ncGuards = this._ncGuards;
    child.exit = this.exit;
    child.inlinePlan = this.inlinePlan;
    // Now inherit state based on callSite
    child.inlineSequence = new InlineSequence(child.method, callSite.position(), callSite);
    child.enclosingHandlers = ebag;
    child.arguments = new Operand[Call.getNumberOfParams(callSite)];
    for (int i = 0; i < child.arguments.length; i++) {
        // copy instead
        child.arguments[i] = Call.getParam(callSite, i).copy();
    // of clearing in case inlining aborts.
    }
    if (Call.hasResult(callSite)) {
        child.resultReg = Call.getResult(callSite).copyD2D().getRegister();
        // it will...
        child.resultReg.setSpansBasicBlock();
    }
    // Initialize the child CFG, prologue, and epilogue blocks
    child.cfg = new ControlFlowGraph(this.cfg.numberOfNodes());
    child.prologue = new BasicBlock(PROLOGUE_BCI, child.inlineSequence, child.cfg);
    child.prologue.setExceptionHandlers(ebag);
    child.epilogue = new BasicBlock(EPILOGUE_BCI, child.inlineSequence, child.cfg);
    child.epilogue.setExceptionHandlers(ebag);
    child.cfg.addLastInCodeOrder(child.prologue);
    child.cfg.addLastInCodeOrder(child.epilogue);
    // Set up the local pool
    child.initLocalPool();
    // Insert moves from child.arguments to child's locals in prologue
    TypeReference[] params = child.method.getParameterTypes();
    int numParams = params.length;
    int argIdx = 0;
    int localNum = 0;
    if (!child.method.isStatic()) {
        Operand receiver = child.arguments[argIdx];
        argIdx++;
        RegisterOperand local = null;
        if (receiver.isRegister()) {
            RegisterOperand objPtr = receiver.asRegister();
            if (ClassLoaderProxy.includesType(child.method.getDeclaringClass().getTypeRef(), objPtr.getType()) != YES) {
                // narrow type of actual to match formal static type implied by method
                // Can be precise but not assignable if enough classes aren't loaded
                objPtr.clearPreciseType();
                objPtr.setDeclaredType();
                objPtr.setType(child.method.getDeclaringClass().getTypeRef());
            }
            local = child.makeLocal(localNum, objPtr);
            localNum++;
            // Avoid confusion in BC2IR of callee
            child.arguments[0] = local;
        // when objPtr is a local in the caller.
        } else if (receiver.isConstant()) {
            local = child.makeLocal(localNum, receiver.getType());
            localNum++;
            local.setPreciseType();
            // Constants trivially non-null
            RegisterOperand guard = child.makeNullCheckGuard(local.getRegister());
            BC2IR.setGuardForRegOp(local, guard);
            child.prologue.appendInstruction(Move.create(GUARD_MOVE, guard.copyRO(), new TrueGuardOperand()));
        } else {
            OptimizingCompilerException.UNREACHABLE("Unexpected receiver operand");
        }
        Instruction s = Move.create(REF_MOVE, local, receiver);
        s.setSourcePosition(PROLOGUE_BCI, callSite.position());
        child.prologue.appendInstruction(s);
    }
    for (int paramIdx = 0; paramIdx < numParams; paramIdx++, argIdx++) {
        TypeReference argType = params[paramIdx];
        RegisterOperand formal;
        Operand actual = child.arguments[argIdx];
        if (actual.isRegister()) {
            RegisterOperand rActual = actual.asRegister();
            if (ClassLoaderProxy.includesType(argType, rActual.getType()) != YES) {
                // narrow type of actual to match formal static type implied by method
                // Can be precise but not
                rActual.clearPreciseType();
                // assignable if enough classes aren't loaded
                rActual.setDeclaredType();
                rActual.setType(argType);
            }
            formal = child.makeLocal(localNum, rActual);
            localNum++;
            // Avoid confusion in BC2IR of
            child.arguments[argIdx] = formal;
        // callee when arg is a local in the caller.
        } else {
            formal = child.makeLocal(localNum, argType);
            localNum++;
        }
        Instruction s = Move.create(IRTools.getMoveOp(argType), formal, actual);
        s.setSourcePosition(PROLOGUE_BCI, callSite.position());
        child.prologue.appendInstruction(s);
        if (argType.isLongType() || argType.isDoubleType()) {
            // longs and doubles take two local words
            localNum++;
        }
    }
    child.completePrologue(false);
    child.completeEpilogue(false);
    child.completeExceptionHandlers(false);
    return child;
}
Also used : RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) TypeOperand(org.jikesrvm.compilers.opt.ir.operand.TypeOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) ClassConstantOperand(org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand) AddressConstantOperand(org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand) ControlFlowGraph(org.jikesrvm.compilers.opt.ir.ControlFlowGraph) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock) InlineSequence(org.jikesrvm.compilers.opt.inlining.InlineSequence) TypeReference(org.jikesrvm.classloader.TypeReference) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)

Example 4 with ControlFlowGraph

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

the class IntervalAnalysis method perform.

/**
 * compute live intervals for this ir
 * the result is a sorted (by beginning point) set of compound
 * intervals, stored in the private 'intervals' field.
 *
 * @param ir the ir
 */
@Override
public void perform(IR ir) {
    this.ir = ir;
    this.regAllocState = ir.MIRInfo.regAllocState;
    ControlFlowGraph cfg = ir.cfg;
    GenericPhysicalRegisterSet phys = ir.regpool.getPhysicalRegisterSet();
    LinearScanState state = new LinearScanState();
    ir.MIRInfo.linearScanState = state;
    // create topological list and a reverse topological list
    // the results are on listOfBlocks and reverseTopFirst lists
    createTopAndReverseList(cfg);
    // give dfn values to each instruction
    assignDepthFirstNumbers(cfg);
    // initialize registers
    initializeRegisters();
    int lastBeginSeen = -1;
    // visit each basic block in the listOfBlocks list
    for (BasicBlock bb = listOfBlocks; bb != null; bb = (BasicBlock) bb.nextSorted) {
        // visit each live interval for this basic block
        LiveInterval liveIntervals = ir.getLivenessInformation();
        for (LiveIntervalElement live = liveIntervals.getFirstLiveIntervalElement(bb); live != null; live = live.getNext()) {
            // begin.
            if (VM.VerifyAssertions) {
                int begin = regAllocState.getDfnBegin(live, bb);
                VM._assert(begin >= lastBeginSeen);
                lastBeginSeen = begin;
            }
            // skip registers which are not allocated.
            if (live.getRegister().isPhysical() && !phys.isAllocatable(live.getRegister())) {
                continue;
            }
            CompoundInterval resultingInterval = processLiveInterval(live, bb);
            if (!bb.getInfrequent() && resultingInterval != null) {
                resultingInterval.setFrequent();
            }
        }
    }
    // debug support
    if (LinearScan.VERBOSE_DEBUG) {
        VM.sysWriteln("**** start of interval dump " + ir.method + " ****");
        VM.sysWrite(ir.MIRInfo.linearScanState.intervals.toString());
        VM.sysWriteln("**** end   of interval dump ****");
    }
}
Also used : GenericPhysicalRegisterSet(org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet) ControlFlowGraph(org.jikesrvm.compilers.opt.ir.ControlFlowGraph) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) LiveInterval(org.jikesrvm.compilers.opt.liveness.LiveInterval)

Example 5 with ControlFlowGraph

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

the class GenerationContext method createSynthetic.

/**
 * Only for internal use by Inliner (when inlining multiple targets)
 * This is probably not the prettiest way to handle this, but it requires
 * no changes to BC2IR's &amp; Inliner's high level control logic.
 *
 * @param parent the parent GC
 * @param ebag the enclosing exception handlers (null if none)
 * @return the synthetic context
 */
public static GenerationContext createSynthetic(GenerationContext parent, ExceptionHandlerBasicBlockBag ebag) {
    // Create the CFG. Initially contains prologue and epilogue
    GenerationContext child = new GenerationContext();
    child.cfg = new ControlFlowGraph(-100000);
    // It may be wrong to use the parent inline sequence as the
    // position here, but it seems to work out.  This is a synthetic
    // context that is just used as a container for multiple inlined
    // targets, so in the cases that I've observed where the prologue
    // and epilogue don't disappear, it was correct to have the
    // parent's position. -- Matt
    child.prologue = new BasicBlock(PROLOGUE_BCI, parent.inlineSequence, parent.cfg);
    child.prologue.setExceptionHandlers(ebag);
    child.epilogue = new BasicBlock(EPILOGUE_BCI, parent.inlineSequence, parent.cfg);
    child.epilogue.setExceptionHandlers(ebag);
    child.cfg.addLastInCodeOrder(child.prologue);
    child.cfg.addLastInCodeOrder(child.epilogue);
    return child;
}
Also used : ControlFlowGraph(org.jikesrvm.compilers.opt.ir.ControlFlowGraph) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) ExceptionHandlerBasicBlock(org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)

Aggregations

BasicBlock (org.jikesrvm.compilers.opt.ir.BasicBlock)8 ControlFlowGraph (org.jikesrvm.compilers.opt.ir.ControlFlowGraph)8 Register (org.jikesrvm.compilers.opt.ir.Register)4 Test (org.junit.Test)4 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)3 ExceptionHandlerBasicBlock (org.jikesrvm.compilers.opt.ir.ExceptionHandlerBasicBlock)2 TypeReference (org.jikesrvm.classloader.TypeReference)1 InlineSequence (org.jikesrvm.compilers.opt.inlining.InlineSequence)1 GenericPhysicalRegisterSet (org.jikesrvm.compilers.opt.ir.GenericPhysicalRegisterSet)1 AddressConstantOperand (org.jikesrvm.compilers.opt.ir.operand.AddressConstantOperand)1 BranchProfileOperand (org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand)1 ClassConstantOperand (org.jikesrvm.compilers.opt.ir.operand.ClassConstantOperand)1 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)1 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)1 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)1 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)1 TypeOperand (org.jikesrvm.compilers.opt.ir.operand.TypeOperand)1 LiveInterval (org.jikesrvm.compilers.opt.liveness.LiveInterval)1