use of org.graalvm.compiler.graph.Node in project graal by oracle.
the class NoDeadCodeVerifyHandler method verify.
@Override
public void verify(DebugContext debug, Object object, String format, Object... args) {
OptionValues options = debug.getOptions();
if (Options.NDCV.getValue(options) != OFF && object instanceof StructuredGraph) {
StructuredGraph graph = (StructuredGraph) object;
List<Node> before = graph.getNodes().snapshot();
new DeadCodeEliminationPhase().run(graph);
List<Node> after = graph.getNodes().snapshot();
assert after.size() <= before.size();
if (before.size() != after.size()) {
if (discovered.put(format, Boolean.TRUE) == null) {
before.removeAll(after);
String prefix = format == null ? "" : format + ": ";
GraalError error = new GraalError("%sfound dead nodes in %s: %s", prefix, graph, before);
if (Options.NDCV.getValue(options) == INFO) {
System.out.println(error.getMessage());
} else if (Options.NDCV.getValue(options) == VERBOSE) {
error.printStackTrace(System.out);
} else {
assert Options.NDCV.getValue(options) == FATAL;
throw error;
}
}
}
}
}
use of org.graalvm.compiler.graph.Node 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.graph.Node in project graal by oracle.
the class FixedNodeProbabilityCache method findBegin.
private static FixedNode findBegin(FixedNode node) {
FixedNode current = node;
while (true) {
assert current != null;
Node predecessor = current.predecessor();
if (current instanceof AbstractBeginNode) {
if (predecessor == null) {
break;
} else if (predecessor.successors().count() != 1) {
assert predecessor instanceof ControlSplitNode : "a FixedNode with multiple successors needs to be a ControlSplitNode: " + current + " / " + predecessor;
break;
}
} else if (predecessor == null) {
current = null;
break;
}
current = (FixedNode) predecessor;
}
return current;
}
use of org.graalvm.compiler.graph.Node in project graal by oracle.
the class InferStamps method inferStamps.
/**
* Infer the stamps for all Object nodes in the graph, to make the stamps as precise as
* possible. For example, this propagates the word-type through phi functions. To handle phi
* functions at loop headers, the stamp inference is called until a fix point is reached.
* <p>
* This method can be used when it is needed that stamps are inferred before the first run of
* the canonicalizer. For example, word type rewriting must run before the first run of the
* canonicalizer because many nodes are not prepared to see the word type during
* canonicalization.
*/
public static void inferStamps(StructuredGraph graph) {
/*
* We want to make the stamps more precise. For cyclic phi functions, this means we have to
* ignore the initial stamp because the imprecise stamp would always propagate around the
* cycle. We therefore set the stamp to an illegal stamp, which is automatically ignored
* when the phi function performs the "meet" operator on its input stamps.
*/
for (Node n : graph.getNodes()) {
if (n instanceof ValuePhiNode) {
ValueNode node = (ValueNode) n;
if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) {
assert node.stamp(NodeView.DEFAULT).hasValues() : "We assume all Phi and Proxy stamps are legal before the analysis";
node.setStamp(node.stamp(NodeView.DEFAULT).empty());
}
}
}
boolean stampChanged;
// The algorithm is not guaranteed to reach a stable state.
int z = 0;
do {
stampChanged = false;
/*
* We could use GraphOrder.forwardGraph() to process the nodes in a defined order and
* propagate long def-use chains in fewer iterations. However, measurements showed that
* we have few iterations anyway, and the overhead of computing the order is much higher
* than the benefit.
*/
for (Node n : graph.getNodes()) {
if (n instanceof ValueNode) {
ValueNode node = (ValueNode) n;
if (node.stamp(NodeView.DEFAULT) instanceof ObjectStamp) {
stampChanged |= node.inferStamp();
}
}
}
++z;
} while (stampChanged && z < 10000);
/*
* Check that all the illegal stamps we introduced above are correctly replaced with real
* stamps again.
*/
assert checkNoEmptyStamp(graph);
}
use of org.graalvm.compiler.graph.Node in project graal by oracle.
the class MemoryScheduleVerification method processBlock.
@Override
protected EconomicSet<FloatingReadNode> processBlock(Block block, EconomicSet<FloatingReadNode> currentState) {
AbstractBeginNode beginNode = block.getBeginNode();
if (beginNode instanceof AbstractMergeNode) {
AbstractMergeNode abstractMergeNode = (AbstractMergeNode) beginNode;
for (PhiNode phi : abstractMergeNode.phis()) {
if (phi instanceof MemoryPhiNode) {
MemoryPhiNode memoryPhiNode = (MemoryPhiNode) phi;
addFloatingReadUsages(currentState, memoryPhiNode);
}
}
}
for (Node n : blockToNodesMap.get(block)) {
if (n instanceof MemoryCheckpoint) {
if (n instanceof MemoryCheckpoint.Single) {
MemoryCheckpoint.Single single = (MemoryCheckpoint.Single) n;
processLocation(n, single.getLocationIdentity(), currentState);
} else if (n instanceof MemoryCheckpoint.Multi) {
MemoryCheckpoint.Multi multi = (MemoryCheckpoint.Multi) n;
for (LocationIdentity location : multi.getLocationIdentities()) {
processLocation(n, location, currentState);
}
}
addFloatingReadUsages(currentState, n);
} else if (n instanceof MemoryNode) {
addFloatingReadUsages(currentState, n);
} else if (n instanceof FloatingReadNode) {
FloatingReadNode floatingReadNode = (FloatingReadNode) n;
if (floatingReadNode.getLastLocationAccess() != null && floatingReadNode.getLocationIdentity().isMutable()) {
if (currentState.contains(floatingReadNode)) {
// Floating read was found in the state.
currentState.remove(floatingReadNode);
} else {
throw new RuntimeException("Floating read node " + n + " was not found in the state, i.e., it was killed by a memory check point before its place in the schedule. Block=" + block + ", block begin: " + block.getBeginNode() + " block loop: " + block.getLoop() + ", " + blockToNodesMap.get(block).get(0));
}
}
}
}
return currentState;
}
Aggregations