From 7aca34858eb886677bc179658a6fffbb5ae54f66 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Mon, 30 Oct 2023 10:15:49 -0700 Subject: Lots of improvements to graphviz Merging common edges. Phis of same Region align. Phis use greek phi, and have a debug name. Scope carries the debug name. Phis are lightly colored. Common math names for math prims. Parse can optionally show the graph after closing the last scope. --- .../com/seaofnodes/simple/GraphVisualizer.java | 22 ++++++++++++++++++++-- .../main/java/com/seaofnodes/simple/Parser.java | 7 ++++--- .../java/com/seaofnodes/simple/node/AddNode.java | 12 ++++++------ .../java/com/seaofnodes/simple/node/BoolNode.java | 3 +++ .../java/com/seaofnodes/simple/node/DivNode.java | 11 +++++------ .../java/com/seaofnodes/simple/node/MinusNode.java | 9 ++++----- .../java/com/seaofnodes/simple/node/MulNode.java | 9 ++++----- .../java/com/seaofnodes/simple/node/MultiNode.java | 4 +--- .../main/java/com/seaofnodes/simple/node/Node.java | 5 +++++ .../java/com/seaofnodes/simple/node/PhiNode.java | 17 ++++++++--------- .../com/seaofnodes/simple/node/RegionNode.java | 8 ++------ .../java/com/seaofnodes/simple/node/ScopeNode.java | 15 +++++++++------ .../java/com/seaofnodes/simple/node/SubNode.java | 9 ++++----- .../java/com/seaofnodes/simple/Chapter05Test.java | 8 ++++---- 14 files changed, 79 insertions(+), 60 deletions(-) (limited to 'chapter05') diff --git a/chapter05/src/main/java/com/seaofnodes/simple/GraphVisualizer.java b/chapter05/src/main/java/com/seaofnodes/simple/GraphVisualizer.java index 79d98792..903a0684 100644 --- a/chapter05/src/main/java/com/seaofnodes/simple/GraphVisualizer.java +++ b/chapter05/src/main/java/com/seaofnodes/simple/GraphVisualizer.java @@ -32,6 +32,10 @@ public class GraphVisualizer { // Preserve node input order sb.append("\tordering=\"in\";\n"); + + // Merge multiple edges hitting the same node. Makes common shared + // nodes much prettier to look at. + sb.append("\tconcentrate=\"true\";\n"); // Just the Nodes first, in a cluster no edges nodes(sb, all); @@ -59,7 +63,7 @@ public class GraphVisualizer { if( n instanceof ProjNode || n instanceof ScopeNode ) continue; // Do not emit, rolled into MultiNode or Scope cluster already sb.append("\t\t").append(n.uniqueName()).append(" [ "); - String lab = n.label(); + String lab = n.glabel(); if( n instanceof MultiNode ) { // Make a box with the MultiNode on top, and all the projections on the bottom sb.append("shape=plaintext label=<\n"); @@ -77,7 +81,7 @@ public class GraphVisualizer { } sb.append("").append(proj.label()).append(""); + sb.append(">").append(proj.glabel()).append(""); } } if (doProjTable) { @@ -93,10 +97,24 @@ public class GraphVisualizer { // other nodes are ellipses, i.e. default shape if( n.isCFG() ) sb.append("shape=box style=filled fillcolor=yellow "); + if( n instanceof PhiNode ) + sb.append("style=filled fillcolor=lightyellow "); sb.append("label=\"").append(lab).append("\" "); } sb.append("];\n"); } + + // Force Region & Phis to line up + for( Node n : all ) { + if( n instanceof RegionNode region ) { + sb.append("\t\t{ rank=same; "); + for( Node phi : region._outputs ) + if( phi instanceof PhiNode ) + sb.append(phi.uniqueName()).append(";"); + sb.append("}\n"); + } + } + sb.append("\t}\n"); // End Node cluster } diff --git a/chapter05/src/main/java/com/seaofnodes/simple/Parser.java b/chapter05/src/main/java/com/seaofnodes/simple/Parser.java index 92b1f0d5..9993c48c 100644 --- a/chapter05/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter05/src/main/java/com/seaofnodes/simple/Parser.java @@ -86,7 +86,8 @@ public class Parser { private Node ctrl(Node n) { return _scope.ctrl(n); } - public StopNode parse() { + public StopNode parse() { return parse(false); } + public StopNode parse(boolean show) { _allScopes.push(_scope); _scope.push(); try { @@ -98,6 +99,7 @@ public class Parser { finally { _scope.pop(); _allScopes.pop(); + if( show ) showGraph(); } } @@ -135,7 +137,7 @@ public class Parser { else if (matchx("int")) return parseDecl(); else if (match ("{" )) return parseBlock(); else if (matchx("if" )) return parseIf(); - else if (matchx("#showGraph")) return showGraph(); + else if (matchx("#showGraph")) return require(showGraph(),";"); else return parseExpressionStatement(); } @@ -203,7 +205,6 @@ public class Parser { * @return {@code null} */ private Node showGraph() { - require(";"); System.out.println(new GraphVisualizer().generateDotOutput(this)); return null; } diff --git a/chapter05/src/main/java/com/seaofnodes/simple/node/AddNode.java b/chapter05/src/main/java/com/seaofnodes/simple/node/AddNode.java index 1e9cc6c9..e4ed83a6 100644 --- a/chapter05/src/main/java/com/seaofnodes/simple/node/AddNode.java +++ b/chapter05/src/main/java/com/seaofnodes/simple/node/AddNode.java @@ -3,12 +3,11 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.type.*; public class AddNode extends Node { - public AddNode(Node lhs, Node rhs) { - super(null, lhs, rhs); - } + public AddNode(Node lhs, Node rhs) { super(null, lhs, rhs); } - @Override - public String label() { return "Add"; } + @Override public String label() { return "Add"; } + + @Override public String glabel() { return "+"; } @Override StringBuilder _print1(StringBuilder sb) { @@ -87,7 +86,8 @@ public class AddNode extends Node { // Push constant up through the phi: x + (phi con0+con0 con1+con1...) for( int i=1; i> _scopes = new Stack<>(); - @Override - public String label() { return "Scope"; } + // Reverse lookup for nicer graph printing + private final ArrayList _rlabels = new ArrayList<>(); + + @Override public String label() { return "Scope"; } @Override StringBuilder _print1(StringBuilder sb) { @@ -43,8 +45,7 @@ public class ScopeNode extends Node { @Override public TypeBot compute() { return TypeBot.BOTTOM; } - @Override - public Node idealize() { return null; } + @Override public Node idealize() { return null; } // Add an empty lexical scope public HashMap push() { @@ -62,6 +63,7 @@ public class ScopeNode extends Node { HashMap scope = _scopes.lastElement(); if( scope.put(name,nIns()) != null ) return null; // Double define + _rlabels.add(name); return add_def(n); } @@ -105,9 +107,10 @@ public class ScopeNode extends Node { public ScopeNode dup() { ScopeNode dup = new ScopeNode(); for( HashMap tab : _scopes ) - dup._scopes.push(new HashMap(tab)); + dup._scopes.push(new HashMap<>(tab)); for( int i=0; i