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));
}
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));
}
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;
}
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 ****");
}
}
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 & 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;
}
Aggregations