use of org.graalvm.compiler.nodes.cfg.Block in project graal by oracle.
the class ReentrantBlockIterator method apply.
public static <StateT> EconomicMap<FixedNode, StateT> apply(BlockIteratorClosure<StateT> closure, Block start, StateT initialState, Predicate<Block> stopAtBlock) {
Deque<Block> blockQueue = new ArrayDeque<>();
/*
* States are stored on EndNodes before merges, and on BeginNodes after ControlSplitNodes.
*/
EconomicMap<FixedNode, StateT> states = EconomicMap.create(Equivalence.IDENTITY);
StateT state = initialState;
Block current = start;
StructuredGraph graph = start.getBeginNode().graph();
CompilationAlarm compilationAlarm = CompilationAlarm.current();
while (true) {
if (compilationAlarm.hasExpired()) {
int period = CompilationAlarm.Options.CompilationExpirationPeriod.getValue(graph.getOptions());
if (period > 120) {
throw new PermanentBailoutException("Compilation exceeded %d seconds during CFG traversal", period);
} else {
throw new RetryableBailoutException("Compilation exceeded %d seconds during CFG traversal", period);
}
}
Block next = null;
if (stopAtBlock != null && stopAtBlock.test(current)) {
states.put(current.getBeginNode(), state);
} else {
state = closure.processBlock(current, state);
Block[] successors = current.getSuccessors();
if (successors.length == 0) {
// nothing to do...
} else if (successors.length == 1) {
Block successor = successors[0];
if (successor.isLoopHeader()) {
if (current.isLoopEnd()) {
// nothing to do... loop ends only lead to loop begins we've already
// visited
states.put(current.getEndNode(), state);
} else {
recurseIntoLoop(closure, blockQueue, states, state, successor);
}
} else if (current.getEndNode() instanceof AbstractEndNode) {
AbstractEndNode end = (AbstractEndNode) current.getEndNode();
// add the end node and see if the merge is ready for processing
AbstractMergeNode merge = end.merge();
if (allEndsVisited(states, current, merge)) {
ArrayList<StateT> mergedStates = mergeStates(states, state, current, successor, merge);
state = closure.merge(successor, mergedStates);
next = successor;
} else {
assert !states.containsKey(end);
states.put(end, state);
}
} else {
next = successor;
}
} else {
next = processMultipleSuccessors(closure, blockQueue, states, state, successors);
}
}
// get next queued block
if (next != null) {
current = next;
} else if (blockQueue.isEmpty()) {
return states;
} else {
current = blockQueue.removeFirst();
assert current.getPredecessorCount() == 1;
assert states.containsKey(current.getBeginNode());
state = states.removeKey(current.getBeginNode());
}
}
}
use of org.graalvm.compiler.nodes.cfg.Block in project graal by oracle.
the class NodeCostUtil method computeGraphCycles.
@SuppressWarnings("try")
public static double computeGraphCycles(StructuredGraph graph, boolean fullSchedule) {
Function<Block, Iterable<? extends Node>> blockToNodes;
ControlFlowGraph cfg;
if (fullSchedule) {
SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS, true);
schedule.apply(graph);
cfg = graph.getLastSchedule().getCFG();
blockToNodes = b -> graph.getLastSchedule().getBlockToNodesMap().get(b);
} else {
cfg = ControlFlowGraph.compute(graph, true, true, false, false);
BlockMap<List<FixedNode>> nodes = new BlockMap<>(cfg);
for (Block b : cfg.getBlocks()) {
ArrayList<FixedNode> curNodes = new ArrayList<>();
for (FixedNode node : b.getNodes()) {
curNodes.add(node);
}
nodes.put(b, curNodes);
}
blockToNodes = b -> nodes.get(b);
}
double weightedCycles = 0D;
DebugContext debug = graph.getDebug();
try (DebugContext.Scope s = debug.scope("NodeCostSummary")) {
for (Block block : cfg.getBlocks()) {
for (Node n : blockToNodes.apply(block)) {
double probWeighted = n.estimatedNodeCycles().value * block.probability();
assert Double.isFinite(probWeighted);
weightedCycles += probWeighted;
if (debug.isLogEnabled()) {
debug.log("Node %s contributes cycles:%f size:%d to graph %s [block prob:%f]", n, n.estimatedNodeCycles().value * block.probability(), n.estimatedNodeSize().value, graph, block.probability());
}
}
}
}
assert weightedCycles >= 0D;
assert Double.isFinite(weightedCycles);
return weightedCycles;
}
use of org.graalvm.compiler.nodes.cfg.Block in project graal by oracle.
the class GraphScheduleTest method assertOrderedAfterSchedule.
protected void assertOrderedAfterSchedule(ScheduleResult ibp, Node a, Node b) {
NodeMap<Block> nodeToBlock = ibp.getCFG().getNodeToBlock();
Block bBlock = nodeToBlock.get(b);
Block aBlock = nodeToBlock.get(a);
if (bBlock == aBlock) {
List<Node> instructions = ibp.nodesFor(bBlock);
Assert.assertTrue(a + " should be before " + b, instructions.indexOf(b) > instructions.indexOf(a));
} else {
Block block = bBlock;
while (block != null) {
if (block == aBlock) {
return;
}
block = block.getDominator();
}
Assert.fail("block of A doesn't dominate the block of B");
}
}
use of org.graalvm.compiler.nodes.cfg.Block in project graal by oracle.
the class GraalCompilerState method preLIRGeneration.
/**
* Sets up {@link LIR} generation.
*/
protected final void preLIRGeneration() {
assert request.graph.isFrozen() : "Graph not frozen.";
Object stub = null;
schedule = request.graph.getLastSchedule();
ControlFlowGraph cfg = deepCopy(schedule.getCFG());
Block[] blocks = cfg.getBlocks();
Block startBlock = cfg.getStartBlock();
assert startBlock != null;
assert startBlock.getPredecessorCount() == 0;
codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder, getGraphOptions(), getGraphDebug());
FrameMapBuilder frameMapBuilder = request.backend.newFrameMapBuilder(registerConfig);
lirGenRes = request.backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, request.graph, stub);
lirGenTool = request.backend.newLIRGenerator(lirGenRes);
nodeLirGen = request.backend.newNodeLIRBuilder(request.graph, lirGenTool);
}
use of org.graalvm.compiler.nodes.cfg.Block in project graal by oracle.
the class EffectsClosure method processLoop.
@Override
@SuppressWarnings("try")
protected final List<BlockT> processLoop(Loop<Block> loop, BlockT initialState) {
if (initialState.isDead()) {
ArrayList<BlockT> states = new ArrayList<>();
for (int i = 0; i < loop.getExits().size(); i++) {
states.add(initialState);
}
return states;
}
/*
* Special case nested loops: To avoid an exponential runtime for nested loops we try to
* only process them as little times as possible.
*
* In the first iteration of an outer most loop we go into the inner most loop(s). We run
* the first iteration of the inner most loop and then, if necessary, a second iteration.
*
* We return from the recursion and finish the first iteration of the outermost loop. If we
* have to do a second iteration in the outer most loop we go again into the inner most
* loop(s) but this time we already know all states that are killed by the loop so inside
* the loop we will only have those changes that propagate from the first iteration of the
* outer most loop into the current loop. We strip the initial loop state for the inner most
* loops and do the first iteration with the (possible) changes from outer loops. If there
* are no changes we only have to do 1 iteration and are done.
*
*/
BlockT initialStateRemovedKilledLocations = stripKilledLoopLocations(loop, cloneState(initialState));
BlockT loopEntryState = initialStateRemovedKilledLocations;
BlockT lastMergedState = cloneState(initialStateRemovedKilledLocations);
processInitialLoopState(loop, lastMergedState);
MergeProcessor mergeProcessor = createMergeProcessor(loop.getHeader());
/*
* Iterative loop processing: we take the predecessor state as the loop's starting state,
* processing the loop contents, merge the states of all loop ends, and check whether the
* resulting state is equal to the starting state. If it is, the loop processing has
* finished, if not, another iteration is needed.
*
* This processing converges because the merge processing always makes the starting state
* more generic, e.g., adding phis instead of non-phi values.
*/
for (int iteration = 0; iteration < 10; iteration++) {
try (Indent i = debug.logAndIndent("================== Process Loop Effects Closure: block:%s begin node:%s", loop.getHeader(), loop.getHeader().getBeginNode())) {
LoopInfo<BlockT> info = ReentrantBlockIterator.processLoop(this, loop, cloneState(lastMergedState));
List<BlockT> states = new ArrayList<>();
states.add(initialStateRemovedKilledLocations);
states.addAll(info.endStates);
doMergeWithoutDead(mergeProcessor, states);
debug.log("MergeProcessor New State: %s", mergeProcessor.newState);
debug.log("===== vs.");
debug.log("Last Merged State: %s", lastMergedState);
if (mergeProcessor.newState.equivalentTo(lastMergedState)) {
blockEffects.get(loop.getHeader()).insertAll(mergeProcessor.mergeEffects, 0);
loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects);
assert info.exitStates.size() == loop.getExits().size();
loopEntryStates.put((LoopBeginNode) loop.getHeader().getBeginNode(), loopEntryState);
assert assertExitStatesNonEmpty(loop, info);
processKilledLoopLocations(loop, initialStateRemovedKilledLocations, mergeProcessor.newState);
return info.exitStates;
} else {
lastMergedState = mergeProcessor.newState;
for (Block block : loop.getBlocks()) {
blockEffects.get(block).clear();
}
}
}
}
throw new GraalError("too many iterations at %s", loop);
}
Aggregations