src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 22,32 **** */ package org.graalvm.compiler.nodes.cfg; import java.util.ArrayList; import java.util.Arrays; ! import java.util.Collections; import java.util.List; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.CFGVerifier; import org.graalvm.compiler.core.common.cfg.Loop; --- 22,32 ---- */ package org.graalvm.compiler.nodes.cfg; import java.util.ArrayList; import java.util.Arrays; ! import java.util.BitSet; import java.util.List; import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph; import org.graalvm.compiler.core.common.cfg.CFGVerifier; import org.graalvm.compiler.core.common.cfg.Loop;
*** 34,43 **** --- 34,44 ---- import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractEndNode; + import org.graalvm.compiler.nodes.ControlSinkNode; import org.graalvm.compiler.nodes.ControlSplitNode; import org.graalvm.compiler.nodes.EndNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.IfNode;
*** 62,71 **** --- 63,79 ---- public final StructuredGraph graph; private NodeMap<Block> nodeToBlock; private Block[] reversePostOrder; private List<Loop<Block>> loops; + private int maxDominatorDepth; + + public interface RecursiveVisitor<V> { + V enter(Block b); + + void exit(Block b, V value); + } public static ControlFlowGraph compute(StructuredGraph graph, boolean connectBlocks, boolean computeLoops, boolean computeDominators, boolean computePostdominators) { ControlFlowGraph cfg = new ControlFlowGraph(graph); cfg.identifyBlocks(); cfg.computeProbabilities();
*** 77,115 **** cfg.computeDominators(); } if (computePostdominators) { cfg.computePostdominators(); } // there's not much to verify when connectBlocks == false assert !(connectBlocks || computeLoops || computeDominators || computePostdominators) || CFGVerifier.verify(cfg); return cfg; } private ControlFlowGraph(StructuredGraph graph) { this.graph = graph; this.nodeToBlock = graph.createNodeMap(); } private void computeDominators() { assert reversePostOrder[0].getPredecessorCount() == 0 : "start block has no predecessor and therefore no dominator"; Block[] blocks = reversePostOrder; for (int i = 1; i < blocks.length; i++) { Block block = blocks[i]; assert block.getPredecessorCount() > 0; Block dominator = null; for (Block pred : block.getPredecessors()) { if (!pred.isLoopEnd()) { dominator = ((dominator == null) ? pred : commonDominatorRaw(dominator, pred)); } } ! // set dominator block.setDominator(dominator); ! if (dominator.getDominated().equals(Collections.emptyList())) { ! dominator.setDominated(new ArrayList<>()); } ! dominator.getDominated().add(block); } calcDominatorRanges(getStartBlock(), reversePostOrder.length); } private static void calcDominatorRanges(Block block, int size) { Block[] stack = new Block[size]; --- 85,333 ---- cfg.computeDominators(); } if (computePostdominators) { cfg.computePostdominators(); } + // there's not much to verify when connectBlocks == false assert !(connectBlocks || computeLoops || computeDominators || computePostdominators) || CFGVerifier.verify(cfg); return cfg; } + public String dominatorTreeString() { + return dominatorTreeString(getStartBlock()); + } + + private static String dominatorTreeString(Block b) { + StringBuilder sb = new StringBuilder(); + sb.append(b); + sb.append("("); + Block firstDominated = b.getFirstDominated(); + while (firstDominated != null) { + if (firstDominated.getDominator().getPostdominator() == firstDominated) { + sb.append("!"); + } + sb.append(dominatorTreeString(firstDominated)); + firstDominated = firstDominated.getDominatedSibling(); + } + sb.append(") "); + return sb.toString(); + } + + @SuppressWarnings("unchecked") + public <V> void visitDominatorTreeDefault(RecursiveVisitor<V> visitor) { + + Block[] stack = new Block[maxDominatorDepth + 1]; + Block current = getStartBlock(); + int tos = 0; + Object[] values = null; + int valuesTOS = 0; + + while (tos >= 0) { + Block state = stack[tos]; + if (state == null || state.getDominator() == null || state.getDominator().getPostdominator() != state) { + if (state == null) { + // We enter this block for the first time. + V value = visitor.enter(current); + if (value != null || values != null) { + if (values == null) { + values = new Object[maxDominatorDepth + 1]; + } + values[valuesTOS++] = value; + } + + Block dominated = skipPostDom(current.getFirstDominated()); + if (dominated != null) { + // Descend into dominated. + stack[tos] = dominated; + current = dominated; + stack[++tos] = null; + continue; + } + } else { + Block next = skipPostDom(state.getDominatedSibling()); + if (next != null) { + // Descend into dominated. + stack[tos] = next; + current = next; + stack[++tos] = null; + continue; + } + } + + // Finished processing all normal dominators. + Block postDom = current.getPostdominator(); + if (postDom != null && postDom.getDominator() == current) { + // Descend into post dominator. + stack[tos] = postDom; + current = postDom; + stack[++tos] = null; + continue; + } + } + + // Finished processing this node, exit and pop from stack. + V value = null; + if (values != null && valuesTOS > 0) { + value = (V) values[--valuesTOS]; + } + visitor.exit(current, value); + current = current.getDominator(); + --tos; + } + } + + private static Block skipPostDom(Block block) { + if (block != null && block.getDominator().getPostdominator() == block) { + // This is an always reached block. + return block.getDominatedSibling(); + } + return block; + } + + private static final class DeferredExit { + + private DeferredExit(Block block, DeferredExit next) { + this.block = block; + this.next = next; + } + + private final Block block; + private final DeferredExit next; + } + + private static void addDeferredExit(DeferredExit[] deferredExits, Block b) { + Loop<Block> outermostExited = b.getDominator().getLoop(); + Loop<Block> exitBlockLoop = b.getLoop(); + assert outermostExited != null; + while (outermostExited.getParent() != null && outermostExited.getParent() != exitBlockLoop) { + outermostExited = outermostExited.getParent(); + } + int loopIndex = outermostExited.getIndex(); + deferredExits[loopIndex] = new DeferredExit(b, deferredExits[loopIndex]); + } + + @SuppressWarnings({"unchecked"}) + public <V> void visitDominatorTreeDeferLoopExits(RecursiveVisitor<V> visitor) { + Block[] stack = new Block[getBlocks().length]; + int tos = 0; + BitSet visited = new BitSet(getBlocks().length); + int loopCount = getLoops().size(); + DeferredExit[] deferredExits = new DeferredExit[loopCount]; + Object[] values = null; + int valuesTOS = 0; + stack[0] = getStartBlock(); + + while (tos >= 0) { + Block cur = stack[tos]; + int curId = cur.getId(); + if (visited.get(curId)) { + V value = null; + if (values != null && valuesTOS > 0) { + value = (V) values[--valuesTOS]; + } + visitor.exit(cur, value); + --tos; + if (cur.isLoopHeader()) { + int loopIndex = cur.getLoop().getIndex(); + DeferredExit deferredExit = deferredExits[loopIndex]; + if (deferredExit != null) { + while (deferredExit != null) { + stack[++tos] = deferredExit.block; + deferredExit = deferredExit.next; + } + deferredExits[loopIndex] = null; + } + } + } else { + visited.set(curId); + V value = visitor.enter(cur); + if (value != null || values != null) { + if (values == null) { + values = new Object[maxDominatorDepth + 1]; + } + values[valuesTOS++] = value; + } + + Block alwaysReached = cur.getPostdominator(); + if (alwaysReached != null) { + if (alwaysReached.getDominator() != cur) { + alwaysReached = null; + } else if (isDominatorTreeLoopExit(alwaysReached)) { + addDeferredExit(deferredExits, alwaysReached); + } else { + stack[++tos] = alwaysReached; + } + } + + Block b = cur.getFirstDominated(); + while (b != null) { + if (b != alwaysReached) { + if (isDominatorTreeLoopExit(b)) { + addDeferredExit(deferredExits, b); + } else { + stack[++tos] = b; + } + } + b = b.getDominatedSibling(); + } + } + } + } + + public <V> void visitDominatorTree(RecursiveVisitor<V> visitor, boolean deferLoopExits) { + if (deferLoopExits && this.getLoops().size() > 0) { + visitDominatorTreeDeferLoopExits(visitor); + } else { + visitDominatorTreeDefault(visitor); + } + } + + private static boolean isDominatorTreeLoopExit(Block b) { + Block dominator = b.getDominator(); + return dominator != null && b.getLoop() != dominator.getLoop() && (!b.isLoopHeader() || dominator.getLoopDepth() >= b.getLoopDepth()); + } + private ControlFlowGraph(StructuredGraph graph) { this.graph = graph; this.nodeToBlock = graph.createNodeMap(); } private void computeDominators() { assert reversePostOrder[0].getPredecessorCount() == 0 : "start block has no predecessor and therefore no dominator"; Block[] blocks = reversePostOrder; + int curMaxDominatorDepth = 0; for (int i = 1; i < blocks.length; i++) { Block block = blocks[i]; assert block.getPredecessorCount() > 0; Block dominator = null; for (Block pred : block.getPredecessors()) { if (!pred.isLoopEnd()) { dominator = ((dominator == null) ? pred : commonDominatorRaw(dominator, pred)); } } ! ! // Set dominator. block.setDominator(dominator); ! ! // Keep dominated linked list sorted by block ID such that predecessor blocks are always ! // before successor blocks. ! Block currentDominated = dominator.getFirstDominated(); ! if (currentDominated != null && currentDominated.getId() < block.getId()) { ! while (currentDominated.getDominatedSibling() != null && currentDominated.getDominatedSibling().getId() < block.getId()) { ! currentDominated = currentDominated.getDominatedSibling(); } ! block.setDominatedSibling(currentDominated.getDominatedSibling()); ! currentDominated.setDominatedSibling(block); ! } else { ! block.setDominatedSibling(dominator.getFirstDominated()); ! dominator.setFirstDominated(block); ! } ! ! curMaxDominatorDepth = Math.max(curMaxDominatorDepth, block.getDominatorDepth()); } + this.maxDominatorDepth = curMaxDominatorDepth; calcDominatorRanges(getStartBlock(), reversePostOrder.length); } private static void calcDominatorRanges(Block block, int size) { Block[] stack = new Block[size];
*** 117,142 **** int tos = 0; int myNumber = 0; do { Block cur = stack[tos]; ! List<Block> dominated = cur.getDominated(); if (cur.getDominatorNumber() == -1) { cur.setDominatorNumber(myNumber); ! if (dominated.size() > 0) { // Push children onto stack. ! for (Block b : dominated) { ! stack[++tos] = b; ! } } else { cur.setMaxChildDomNumber(myNumber); --tos; } ++myNumber; } else { ! cur.setMaxChildDomNumber(dominated.get(0).getMaxChildDominatorNumber()); --tos; } } while (tos >= 0); } --- 335,361 ---- int tos = 0; int myNumber = 0; do { Block cur = stack[tos]; ! Block dominated = cur.getFirstDominated(); if (cur.getDominatorNumber() == -1) { cur.setDominatorNumber(myNumber); ! if (dominated != null) { // Push children onto stack. ! do { ! stack[++tos] = dominated; ! dominated = dominated.getDominatedSibling(); ! } while (dominated != null); } else { cur.setMaxChildDomNumber(myNumber); --tos; } ++myNumber; } else { ! cur.setMaxChildDomNumber(dominated.getMaxChildDominatorNumber()); --tos; } } while (tos >= 0); }
*** 253,262 **** --- 472,483 ---- falseSucc.setPredecessors(ifPred); } else if (last instanceof LoopEndNode) { LoopEndNode loopEndNode = (LoopEndNode) last; block.setSuccessors(new Block[]{nodeMap.get(loopEndNode.loopBegin())}); // Nothing to do push onto the stack. + } else if (last instanceof ControlSinkNode) { + block.setSuccessors(Block.EMPTY_ARRAY); } else { assert !(last instanceof AbstractEndNode) : "Algorithm only supports EndNode and LoopEndNode."; int startTos = tos; Block[] ifPred = new Block[]{block}; for (Node suxNode : last.successors()) {
*** 340,355 **** LoopBeginNode loopBegin = (LoopBeginNode) block.getBeginNode(); probability *= loopBegin.loopFrequency(); } } if (probability < MIN_PROBABILITY) { ! block.setProbability(MIN_PROBABILITY); } else if (probability > MAX_PROBABILITY) { ! block.setProbability(MAX_PROBABILITY); ! } else { ! block.setProbability(probability); } } } private void computeLoopInformation() { --- 561,575 ---- LoopBeginNode loopBegin = (LoopBeginNode) block.getBeginNode(); probability *= loopBegin.loopFrequency(); } } if (probability < MIN_PROBABILITY) { ! probability = MIN_PROBABILITY; } else if (probability > MAX_PROBABILITY) { ! probability = MAX_PROBABILITY; } + block.setProbability(probability); } } private void computeLoopInformation() {
*** 469,479 **** } public void computePostdominators() { Block[] reversePostOrderTmp = this.reversePostOrder; - outer: for (int j = reversePostOrderTmp.length - 1; j >= 0; --j) { Block block = reversePostOrderTmp[j]; if (block.isLoopEnd()) { // We do not want the loop header registered as the postdominator of the loop end. continue; --- 689,698 ----
*** 494,504 **** // There is a dead end => no postdominator available. continue outer; } } assert !Arrays.asList(block.getSuccessors()).contains(postdominator) : "Block " + block + " has a wrong post dominator: " + postdominator; ! block.postdominator = postdominator; } } private static Block commonPostdominator(Block a, Block b) { Block iterA = a; --- 713,723 ---- // There is a dead end => no postdominator available. continue outer; } } assert !Arrays.asList(block.getSuccessors()).contains(postdominator) : "Block " + block + " has a wrong post dominator: " + postdominator; ! block.setPostDominator(postdominator); } } private static Block commonPostdominator(Block a, Block b) { Block iterA = a;
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/ControlFlowGraph.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File