From e4dc3273f201ae741637b626998637cce973546b Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Fri, 2 Oct 2026 13:04:34 -0700 Subject: First pass README updates --- README.md | 10 +- chapter01/README.md | 40 +- chapter01/docs/01-graph.json | 14 + chapter01/docs/01-graph.svg | 129 +- chapter01/docs/01-use-def.json | 13 + chapter01/docs/01-use-def.svg | 104 +- chapter01/docs/Makefile | 13 +- chapter02/README.md | 55 +- chapter02/docs/02-demonstration-peephole.json | 14 + chapter02/docs/02-demonstration-peephole.svg | 127 +- .../docs/02-demonstration-pre-peephole-nokill.json | 17 + .../docs/02-demonstration-pre-peephole-nokill.svg | 184 ++- chapter02/docs/02-demonstration-pre-peephole.json | 16 + chapter02/docs/02-demonstration-pre-peephole.svg | 168 ++- chapter02/docs/02-post-peephole-ex1.json | 14 + chapter02/docs/02-post-peephole-ex1.svg | 129 +- chapter02/docs/02-pre-peephole-ex1.json | 21 + chapter02/docs/02-pre-peephole-ex1.svg | 269 ++-- chapter02/docs/Makefile | 13 +- .../main/java/com/seaofnodes/simple/type/Type.java | 5 + chapter03/README.md | 72 +- chapter03/docs/03-graph1.json | 17 + chapter03/docs/03-graph1.svg | 222 ++- chapter03/docs/03-graph2.json | 18 + chapter03/docs/03-graph2.svg | 226 ++- chapter03/docs/03-graph3.json | 19 + chapter03/docs/03-graph3.svg | 242 ++-- chapter03/docs/03-graph4.json | 17 + chapter03/docs/03-graph4.svg | 211 ++- chapter03/docs/03-graph5.json | 17 + chapter03/docs/03-graph5.svg | 211 ++- chapter03/docs/Makefile | 13 +- .../main/java/com/seaofnodes/simple/type/Type.java | 5 + chapter04/README.md | 69 +- chapter04/docs/04-arg1.json | 16 + chapter04/docs/04-arg1.svg | 165 ++- chapter04/docs/04-arg2.json | 16 + chapter04/docs/04-arg2.svg | 162 +-- chapter04/docs/04-post-peephole.json | 18 + chapter04/docs/04-post-peephole.svg | 198 ++- chapter04/docs/04-pre-peephole.json | 20 + chapter04/docs/04-pre-peephole.svg | 232 ++- chapter04/docs/Makefile | 13 +- chapter04/docs/projnode.json | 14 + chapter04/docs/projnode.svg | 74 + .../main/java/com/seaofnodes/simple/type/Type.java | 9 +- chapter05/README.md | 37 +- chapter05/docs/05-graph1.json | 25 + chapter05/docs/05-graph1.svg | 348 ++--- chapter05/docs/05-graph2.json | 27 + chapter05/docs/05-graph2.svg | 354 ++--- chapter05/docs/05-graph3.json | 28 + chapter05/docs/05-graph3.svg | 343 ++--- chapter05/docs/05-graph4.json | 28 + chapter05/docs/05-graph4.svg | 343 ++--- chapter05/docs/05-graph5.json | 27 + chapter05/docs/05-graph5.svg | 318 ++--- chapter05/docs/05-graph6.json | 26 + chapter05/docs/05-graph6.svg | 293 ++-- chapter05/docs/05-graph7.json | 31 + chapter05/docs/05-graph7.svg | 409 ++---- chapter05/docs/05-graph8.json | 45 + chapter05/docs/05-graph8.svg | 618 +++----- chapter05/docs/05-graph9.json | 26 + chapter05/docs/05-graph9.svg | 291 ++-- chapter05/docs/Makefile | 13 +- chapter06/README.md | 15 +- chapter06/docs/06-graph1-post.json | 16 + chapter06/docs/06-graph1-post.svg | 147 +- chapter06/docs/06-graph1-pre.json | 24 + chapter06/docs/06-graph1-pre.svg | 271 ++-- chapter06/docs/06-graph2-post.json | 16 + chapter06/docs/06-graph2-post.svg | 147 +- chapter06/docs/06-graph2-pre.json | 24 + chapter06/docs/06-graph2-pre.svg | 262 ++-- chapter06/docs/06-graph3-nonconst-peephole.json | 24 + chapter06/docs/06-graph3-nonconst-peephole.svg | 259 ++-- chapter06/docs/06-graph3-nonconst.json | 35 + chapter06/docs/06-graph3-nonconst.svg | 440 ++---- chapter06/docs/Makefile | 13 +- chapter07/README.md | 10 +- chapter07/docs/07-graph1.json | 27 + chapter07/docs/07-graph1.svg | 390 ++--- chapter07/docs/07-graph2.json | 26 + chapter07/docs/07-graph2.svg | 303 ++-- chapter07/docs/07-graph3.json | 40 + chapter07/docs/07-graph3.svg | 548 +++---- chapter07/docs/07-graph4.json | 37 + chapter07/docs/07-graph4.svg | 488 +++---- chapter07/docs/Makefile | 13 +- chapter08/README.md | 36 +- chapter08/docs/08-graph1.json | 39 + chapter08/docs/08-graph1.svg | 533 +++---- chapter08/docs/08-graph2.json | 39 + chapter08/docs/08-graph2.svg | 501 +++---- chapter08/docs/08-graph3.json | 40 + chapter08/docs/08-graph3.svg | 565 +++----- chapter08/docs/Makefile | 13 +- chapter09/README.md | 51 +- chapter09/docs/09-graph1.json | 28 + chapter09/docs/09-graph1.svg | 352 ++--- chapter09/docs/09-graph2.json | 26 + chapter09/docs/09-graph2.svg | 318 ++--- chapter09/docs/09-graph3.json | 19 + chapter09/docs/09-graph3.svg | 205 ++- chapter09/docs/09-graph4.json | 16 + chapter09/docs/09-graph4.svg | 147 +- chapter09/docs/09-graph5.json | 27 + chapter09/docs/09-graph5.svg | 334 ++--- chapter09/docs/09-graph6.json | 26 + chapter09/docs/09-graph6.svg | 303 ++-- chapter09/docs/Makefile | 13 +- chapter10a/README.md | 8 +- chapter10a/docs/example1.gv | 20 +- chapter10a/docs/example1.svg | 48 +- chapter10a/docs/example2a.gv | 21 +- chapter10a/docs/example2a.svg | 56 +- chapter10a/docs/example2b.gv | 22 +- chapter10a/docs/example2b.svg | 48 +- chapter10a/docs/example2c.gv | 17 +- chapter10a/docs/example2c.svg | 34 +- chapter10a/docs/lattice.gv | 2 +- chapter10a/docs/lattice.svg | 233 ++- chapter10b/README.md | 7 +- chapter10b/docs/example1.gv | 23 +- chapter10b/docs/example1.svg | 60 +- chapter10b/docs/example2a.gv | 21 +- chapter10b/docs/example2a.svg | 58 +- chapter10b/docs/example2b.gv | 23 +- chapter10b/docs/example2b.svg | 72 +- chapter10b/docs/example2c.gv | 19 +- chapter10b/docs/example2c.svg | 38 +- chapter10b/docs/lattice.gv | 2 +- chapter10b/docs/lattice.svg | 154 +- chapter11/README.md | 26 +- chapter11/docs/Makefile | 15 +- chapter11/docs/graph1.json | 33 + chapter11/docs/graph1.svg | 457 ++---- chapter11/docs/graph2.json | 33 + chapter11/docs/graph2.svg | 486 ++----- chapter11/docs/graph3-snip.json | 20 + chapter11/docs/graph3-snip.svg | 102 ++ chapter11/docs/graph3.json | 33 + chapter11/docs/graph3.svg | 500 ++----- chapter11/docs/graph4.json | 42 + chapter11/docs/graph4.svg | 616 +++----- chapter11/docs/graph5.json | 42 + chapter11/docs/graph5.svg | 659 +++------ chapter11/docs/graph6.json | 42 + chapter11/docs/graph6.svg | 658 +++------ chapter11/docs/graph7.json | 16 + chapter11/docs/graph7.svg | 132 +- chapter11/docs/graph8.json | 21 + chapter11/docs/graph8.svg | 213 ++- chapter12/README.md | 14 +- chapter12/docs/lattice.gv | 313 ++-- chapter12/docs/lattice.svg | 1306 +++++++++-------- chapter13/README.md | 45 +- chapter14/README.md | 75 +- chapter14/docs/lattice.gv | 355 ++--- chapter14/docs/lattice.svg | 1494 +++++++++++--------- chapter15/README.md | 49 +- chapter16/README.md | 15 +- chapter17/README.md | 14 +- chapter18/README.md | 41 +- chapter19/README.md | 28 +- chapter20/README.md | 57 +- chapter21/README.md | 3 + chapter22/README.md | 22 +- chapter23/README.md | 65 +- chapter24/README.md | 33 +- chapter25/README.md | 3 + docs/type-float.svg | 5 + graph/README.md | 34 +- graph/docs.mk | 24 + graph/render_docs.py | 71 + 176 files changed, 10602 insertions(+), 13083 deletions(-) create mode 100644 chapter01/docs/01-graph.json create mode 100644 chapter01/docs/01-use-def.json create mode 100644 chapter02/docs/02-demonstration-peephole.json create mode 100644 chapter02/docs/02-demonstration-pre-peephole-nokill.json create mode 100644 chapter02/docs/02-demonstration-pre-peephole.json create mode 100644 chapter02/docs/02-post-peephole-ex1.json create mode 100644 chapter02/docs/02-pre-peephole-ex1.json create mode 100644 chapter03/docs/03-graph1.json create mode 100644 chapter03/docs/03-graph2.json create mode 100644 chapter03/docs/03-graph3.json create mode 100644 chapter03/docs/03-graph4.json create mode 100644 chapter03/docs/03-graph5.json create mode 100644 chapter04/docs/04-arg1.json create mode 100644 chapter04/docs/04-arg2.json create mode 100644 chapter04/docs/04-post-peephole.json create mode 100644 chapter04/docs/04-pre-peephole.json create mode 100644 chapter04/docs/projnode.json create mode 100644 chapter04/docs/projnode.svg create mode 100644 chapter05/docs/05-graph1.json create mode 100644 chapter05/docs/05-graph2.json create mode 100644 chapter05/docs/05-graph3.json create mode 100644 chapter05/docs/05-graph4.json create mode 100644 chapter05/docs/05-graph5.json create mode 100644 chapter05/docs/05-graph6.json create mode 100644 chapter05/docs/05-graph7.json create mode 100644 chapter05/docs/05-graph8.json create mode 100644 chapter05/docs/05-graph9.json create mode 100644 chapter06/docs/06-graph1-post.json create mode 100644 chapter06/docs/06-graph1-pre.json create mode 100644 chapter06/docs/06-graph2-post.json create mode 100644 chapter06/docs/06-graph2-pre.json create mode 100644 chapter06/docs/06-graph3-nonconst-peephole.json create mode 100644 chapter06/docs/06-graph3-nonconst.json create mode 100644 chapter07/docs/07-graph1.json create mode 100644 chapter07/docs/07-graph2.json create mode 100644 chapter07/docs/07-graph3.json create mode 100644 chapter07/docs/07-graph4.json create mode 100644 chapter08/docs/08-graph1.json create mode 100644 chapter08/docs/08-graph2.json create mode 100644 chapter08/docs/08-graph3.json create mode 100644 chapter09/docs/09-graph1.json create mode 100644 chapter09/docs/09-graph2.json create mode 100644 chapter09/docs/09-graph3.json create mode 100644 chapter09/docs/09-graph4.json create mode 100644 chapter09/docs/09-graph5.json create mode 100644 chapter09/docs/09-graph6.json create mode 100644 chapter11/docs/graph1.json create mode 100644 chapter11/docs/graph2.json create mode 100644 chapter11/docs/graph3-snip.json create mode 100644 chapter11/docs/graph3-snip.svg create mode 100644 chapter11/docs/graph3.json create mode 100644 chapter11/docs/graph4.json create mode 100644 chapter11/docs/graph5.json create mode 100644 chapter11/docs/graph6.json create mode 100644 chapter11/docs/graph7.json create mode 100644 chapter11/docs/graph8.json create mode 100644 docs/type-float.svg create mode 100644 graph/docs.mk create mode 100644 graph/render_docs.py diff --git a/README.md b/README.md index 4ed1e307..0bc961f5 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ This repo is intended to demonstrate the Sea-of-Nodes compiler IR. The Sea-of-Nodes is the core IR inside of HotSpot's C2 compiler and Google's V8 compiler and Sun/Oracle's Graal compiler. -Since we are show casing the SoN IR, the *language* being implemented is less +Since we are showcasing the SoN IR, the *language* being implemented is less important. We're using a very simple language similar to C or Java, but with far fewer features. Simple is strongly typed, object-oriented, with first-class *functions* not *closures*. Object references are pointers, and null @@ -16,12 +16,12 @@ has a minimal syntax that can be parsed with a recursive descent parser. The Sea-of-Nodes is used for machine code generation in these industrial strength systems - but for this demonstration the backend is both difficult and -less important. This repo targets X86, RISC5 and ARM64 at least with +less important. This repo targets x86-64, RISC-V and ARM64 with ahead-of-time compilation - but with an eye towards JIT compilation. This repo also is not intended to be a complete language in any sense, and so -the backend starts with levering Java: the Evaluator (first appears in Chapter -10a) directly slowly interprets the SoN IR. Code-gen first appears in Chapter +the backend starts with a Java evaluator (first introduced in Chapter +8) that directly interprets the SoN IR. Code generation first appears in Chapter 19. @@ -74,7 +74,7 @@ The Simple language is styled after a subset of C or Java. ## Building across chapters The optional [interactive graph viewer](graph/README.md) is shared in `graph/`. -Chapters 10a, 10b, and 18–25 launch it with `make view` from the chapter directory. +Chapters 1–25, including 10a and 10b, launch it with `make view` from the chapter directory. The [debug printers](print/README.md) are shared in `print/`; Chapter 2 needs only a one-line expression format. A shared `BaseNode` supplies identity and edge diff --git a/chapter01/README.md b/chapter01/README.md index 17e24ea0..ebe2811e 100644 --- a/chapter01/README.md +++ b/chapter01/README.md @@ -1,21 +1,23 @@ # Chapter 1: Introduction +[Introduction](../README.md) | +[Next: Chapter 2](../chapter02/README.md) + # Table of Contents -1. [Implementation Language](#implementation-language) -2. [Assumptions](#assumptions) -3. [Architecture](#architecture) -4. [Data Structures](#data-structures) -5. [Intermediate Representation as a Graph of Nodes](#intermediate-representation-as-a-graph-of-nodes) -6. [Nodes are in a Graph](#nodes-are-in-a-graph) -7. [Types of Nodes](#types-of-nodes) -8. [Unique Node ID](#unique-node-id) -9. [Start Node](#start-node) +1. [Implementation Language](#implementation-language) +2. [Assumptions](#assumptions) +3. [Architecture](#architecture) +4. [Data Structures](#data-structures) +5. [Intermediate Representation as a Graph of Nodes](#intermediate-representation-as-a-graph-of-nodes) +6. [Nodes are in a Graph](#nodes-are-in-a-graph) +7. [Types of Nodes](#types-of-nodes) +8. [Unique Node ID](#unique-node-id) +9. [Start Node](#start-node) 10. [Constant Node](#constant-node) 11. [Return Node](#return-node) 12. [Representation](#representation) - You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter01) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch. @@ -41,7 +43,7 @@ Our implementation language is Java. We chose Java as it is widely available and ## Assumptions We assume that the reader is familiar with traditional linear intermediate representations, and is familiar with terms such as Basic Block, Control Flow Graph, etc. No attempt is made to explain these topics. -If necessary the reader can consult a standard compiler text book. +If necessary the reader can consult a standard compiler textbook. ## Architecture @@ -50,7 +52,7 @@ a number of pessimistic peephole optimizations can be performed while parsing a ## Data Structures -Our data structures are based upon the descriptions provided in following papers: +Our data structures are based upon the descriptions provided in the following papers: * [From Quads to Graphs: An Intermediate Representation's Journey](http://softlib.rice.edu/pub/CRPC-TRs/reports/CRPC-TR93366-S.pdf) * [Combining Analyses, Combining Optimizations](https://dl.acm.org/doi/pdf/10.1145/201059.201061) @@ -73,9 +75,9 @@ Each `Node` represents an "instruction" as it may appear in traditional IRs. ### Nodes are in a Graph The key idea of the Sea of Nodes IR is that each Node is linked to other Nodes by def-use dependencies. -As this is such an important and fundamental aspect of the IR, it is important to understand how we implement this, and depict in graph visuals. +As this is such an important and fundamental aspect of the IR, it is important to understand how we implement this, and depict this in graph visuals. -The base `Node` class maintains a list of Nodes that are inputs to it. An input is an edge from a "def" to a "use". What this means is that if `B` is definition, and `A` uses `B`, +The base `Node` class maintains a list of Nodes that are inputs to it. An input is an edge from a "def" to a "use". What this means is that if `B` is a definition, and `A` uses `B`, then there is a def-use edge from `B` to `A`. Visually we show an arrow from the "use" to the "def". Here is an example: @@ -110,7 +112,7 @@ public abstract class Node { *

* Outputs directly match inputs, making a directed graph that can be * walked in either direction. These outputs are typically used for - * efficient optimizations but otherwise have no semantics meaning. + * efficient optimizations but otherwise have no semantic meaning. */ public final ArrayList _outputs; } @@ -173,7 +175,7 @@ The Return's output is the value from the data node. ### Representation -Here is visualization of the program: +Here is a visualization of the program: ``` return 1; @@ -181,7 +183,7 @@ return 1; ![Sea of Nodes Visual](./docs/01-graph.svg) -* Control nodes appear as square boxes with yellow background -* Control edges are in bold red -* The edges from Constants to Start are shown in dotted lines as these are not true control edges +* Control nodes appear as rectangular boxes with pale yellow backgrounds +* Control edges are red and thicker than data edges +* The edges from Constants to Start are shown as dashed gray lines as these are not true control edges * We label each edge with its position in the `_inputs` array, thus `0` means the edge is `_inputs[0]`. diff --git a/chapter01/docs/01-graph.json b/chapter01/docs/01-graph.json new file mode 100644 index 00000000..f489c4fe --- /dev/null +++ b/chapter01/docs/01-graph.json @@ -0,0 +1,14 @@ +{ + "ver": 1, + "comp": "chapter01/docs/01-graph.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 2, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 3, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 2, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter01/docs/01-graph.svg b/chapter01/docs/01-graph.svg index 7f511966..d8ec5cb7 100644 --- a/chapter01/docs/01-graph.svg +++ b/chapter01/docs/01-graph.svg @@ -1,56 +1,73 @@ - - - - - - -chapter01 - - -cluster_Nodes - - - - -Start1 - -Start - - - -Con_2 - -#1 - - - -Con_2->Start1 - - -0 - - - -Return3 - -Return - - - -Return3->Start1 - - -0 - - - -Return3->Con_2 - - -1 - - - +#2[0] → #1 · ASSOC#3[0] → #1 · CTRL#3[1] → #2 · DATAStart  #1#1 Start +Type not computed + +#1  #2#2 #1 +Type not computed + +[0] → #1 ASSOC0Return  #3#3 Return +Type not computed + +[0] → #1 CTRL +[1] → #2 DATA01 diff --git a/chapter01/docs/01-use-def.json b/chapter01/docs/01-use-def.json new file mode 100644 index 00000000..5e6f2df6 --- /dev/null +++ b/chapter01/docs/01-use-def.json @@ -0,0 +1,13 @@ +{ + "ver": 1, + "comp": "chapter01/docs/01-use-def.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "A", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": null}, + {"id": 2, "label": "B", "type": null, "kind": "DATA", "edges": [], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter01/docs/01-use-def.svg b/chapter01/docs/01-use-def.svg index 644ab5a2..b0ecd3da 100644 --- a/chapter01/docs/01-use-def.svg +++ b/chapter01/docs/01-use-def.svg @@ -1,35 +1,69 @@ - - - - - - -chapter01 - - -cluster_Nodes - - - - -A - -A - - - -B - -B - - - -A->B - - - - - +#1[0] → #2 · DATAA  #1#1 A +Type not computed + +[0] → #2 DATA0B  #2#2 B +Type not computed + + diff --git a/chapter01/docs/Makefile b/chapter01/docs/Makefile index 12659b8f..6fa0f057 100644 --- a/chapter01/docs/Makefile +++ b/chapter01/docs/Makefile @@ -1,12 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter02/README.md b/chapter02/README.md index eda25269..9b6d3651 100644 --- a/chapter02/README.md +++ b/chapter02/README.md @@ -1,5 +1,8 @@ # Chapter 2: Arithmetic +[Previous: Chapter 1](../chapter01/README.md) | +[Next: Chapter 3](../chapter03/README.md) + # Table of Contents @@ -24,7 +27,7 @@ Here is the [complete language grammar](docs/02-grammar.md) for this chapter. ## Extensions to Intermediate Representation -In [Chapter 1](../chapter01/README.md) we introduced following nodes. +In [Chapter 1](../chapter01/README.md) we introduced the following nodes. | Node Name | Type | Description | Inputs | Value | |-----------|---------|------------------------------------|------------------------------------------------------------------|-------------------------------------------------------| @@ -32,7 +35,7 @@ In [Chapter 1](../chapter01/README.md) we introduced following nodes. | Return | Control | End of function | Predecessor control node, Data node value | Return value of the function | | Constant | Data | Constants such as integer literals | None, however Start node is set as input to enable graph walking | Value of the constant | -We extend the set of nodes by adding following additional node types. +We extend the set of nodes by adding the following additional node types. | Node Name | Type | Description | Inputs | Value | |-----------|------|-------------------------------|------------------------------------------------------------|-----------------------------| @@ -51,7 +54,7 @@ equality. This is by far the most common case. In [Chapter In both cases the choice of value-vs-reference equality is intentional: it is *never* correct to "just pick one or the other kind of equality". When in doubt check the context: only *Global Value Numbering* uses value equality; -everywhere we mean reference equality. +everywhere else we mean reference equality. ## Peephole Optimizations @@ -77,7 +80,7 @@ may *kill* the unused constants `1` and `2`. ## Constant Folding and Constant Propagation -In this chapter and next we focus on a particular peephole optimization: +In this chapter and the next we focus on a particular peephole optimization: constant folding and constant propagation. Since we do not have non-constant values until [Chapter 4](../chapter04/README.md), the main feature we demonstrate now is constant folding. However, we introduce some additional ideas into the compiler at this stage, to @@ -91,14 +94,14 @@ optimizations such as: constant. This idea can be extended in a number of ways and is called [Partial Evaluation](https://en.wikipedia.org/wiki/Partial_evaluation). * The compiler may be able to identify regions of code that are dead and no - longer needed, such as when a conditional branch always take one of the + longer needed, such as when a conditional branch always takes one of the branches ([Chapter 6](../chapter06/README.md)). * Pointers may be known to be not-null, and a null check can be skipped ([Chapter 10a](../chapter10a/README.md)). * Array indices may be known to be in-range, and a range check can be skipped. * Many additional optimizations are possible when the compiler learns more about the possible set of Node values. -In order to achieve above, we need a way to talk about what kinds of values a Node can take +In order to achieve this, we need a way to talk about what kinds of values a Node can take on at runtime - we call these Types, and we annotate Nodes with Types. The Type annotation serves two purposes: @@ -106,8 +109,8 @@ The Type annotation serves two purposes: * it defines the set of operations allowed on the Node * it defines the set of values the Node takes on -The Type itself is represented as a Java class; the Java classes are used as -convenient to represent the Type's structure; all types are subtypes of the +The Type itself is represented as a Java class; the Java classes provide a +convenient way to represent the Type's structure; all types are subtypes of the class `Type`. For now, we only have the following hierarchy of types: ``` @@ -116,7 +119,7 @@ Type ``` It turns out that the set of values associated with a Type at a specific Node -can be conveniently represented as a *lattice* +can be conveniently represented as a *lattice* [wiki/Lattice_(order)](https://en.wikipedia.org/wiki/Lattice_(order)). Our lattice has the following structure: ![Lattice](./docs/lattice.svg) @@ -130,7 +133,7 @@ Our lattice elements can be one of three types: Node's value is **not** a compile time constant. An invariant of peephole optimizations is that the type of a Node always moves -*up* the lattice (towards "top"); peepholes are *pessmistic* assuming the worst +*up* the lattice (towards "top"); peepholes are *pessimistic* assuming the worst until they can prove better. A later *optimistic* optimization will start all Nodes at *top* and move Types *down* the lattice as eager assumptions are proven wrong. @@ -161,9 +164,9 @@ optimizes each node as it is built; it does not retain this entire intermediate ![Example Visual](./docs/02-pre-peephole-ex1.svg) -* Control nodes appear as square boxes with yellow background -* Control edges are in bold red -* The edges from Constants to Start are shown in dotted lines as these are not true control edges +* Control nodes appear as rectangular boxes with pale yellow backgrounds +* Control edges are red and thicker than data edges +* The edges from Constants to Start are shown as dashed gray lines as these are not true control edges * We label each edge with its position in the node's list of inputs. @@ -177,7 +180,7 @@ To demonstrate how the optimisation works, let's consider the following code: ``` return 1+2; ``` -This is parsed as: +This is parsed as: ```java var lhs = parseMultiplication(); if (match("+")) return new AddNode(lhs, parseAddition()).peephole(); @@ -198,22 +201,22 @@ When the peephole is called on the AddNode node it first calls the compute funct return Type.BOTTOM; } ``` -In our case both of the operands(`1`, `2`) are constants, and instance of +In our case both of the operands(`1`, `2`) are constants, and instances of `TypeInteger`. Since `compute` returns a type, and we know that both of our operands are constants, we can do -constant propagation/folding where we compute the result of the expression so that instead of having `1+2` we can +constant propagation/folding where we compute the result of the expression so that instead of having `1+2` we can have `3`. -The 'TypeInteger' interface inherits from type but also has a field that stores the value observed for that type. +The `TypeInteger` class inherits from `Type` but also has a field that stores the value observed for that type. ```java - private final long _con + private final long _con; ``` AddNode has the layout: ![Example Visual](./docs/02-demonstration-pre-peephole.svg) -Since, we already know the value of both of the operands, we can just add them together and replace the +Since we already know the value of both of the operands, we can just add them together and replace the old node with a constant node that just holds the result of the expression. To do this - we have to recognize this happens when the type computed for the node is already a constant, but the node @@ -229,19 +232,19 @@ Note how we return a constant type when doing constant folding ```java return TypeInteger.constant(i0.value()+i1.value()); ``` -We can create a constant node in the following way: +We can create a constant node in the following way: ```java return new ConstantNode(type).peephole(); ``` -This recursively calls the peephole algorithm. +This recursively calls the peephole algorithm. Now, we end up with this: ![Example Visual](./docs/02-demonstration-pre-peephole-nokill.svg) -Notice, how we added the constant node holding a constant value of `3`. +Notice how we added the constant node holding a constant value of `3`. The remaining add node is unused and can be killed. -We can call the kill function before this way: +We can call the kill function first: ```java // Replace constant computations from non-constants with a constant node if (!(this instanceof ConstantNode) && type.isConstant()) { @@ -263,19 +266,19 @@ public void kill( ) { ``` `isUnused` - This makes sure the current node has no outputs. -Ideally, in our case there would be one output as the return statement is +Ideally, in our case there would be one output as the return statement is using the add expression. However, the optimisation happens before even creating the return node, which means that at this point there are no users of the add node. -We can now freely go ahead and delete the node. +We can now freely go ahead and delete the node. ```java for(int i=0; i - - - - - -chapter02 - - -cluster_Nodes - - - - -Start1 - -Start - - - -Con_5 - -#3 - - - -Con_5->Start1 - - -0 - - - -Return6 - -Return - - - -Return6->Start1 - - -0 - - - -Return6->Con_5 - - -1 - - - \ No newline at end of file +#5[0] → #1 · ASSOC#6[0] → #1 · CTRL#6[1] → #5 · DATAStart  #1#1 Start +Type not computed + +#3  #5#5 #3 +Type not computed + +[0] → #1 ASSOC0Return  #6#6 Return +Type not computed + +[0] → #1 CTRL +[1] → #5 DATA01 diff --git a/chapter02/docs/02-demonstration-pre-peephole-nokill.json b/chapter02/docs/02-demonstration-pre-peephole-nokill.json new file mode 100644 index 00000000..6a952f88 --- /dev/null +++ b/chapter02/docs/02-demonstration-pre-peephole-nokill.json @@ -0,0 +1,17 @@ +{ + "ver": 1, + "comp": "chapter02/docs/02-demonstration-pre-peephole-nokill.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 2, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 3, "label": "#2", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 4, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 2, "role": "DATA", "label": null}, {"idx": 2, "def": 3, "role": "DATA", "label": null}], "proj": null}, + {"id": 5, "label": "#3", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 6, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 5, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter02/docs/02-demonstration-pre-peephole-nokill.svg b/chapter02/docs/02-demonstration-pre-peephole-nokill.svg index 3d4f53df..a40e5981 100644 --- a/chapter02/docs/02-demonstration-pre-peephole-nokill.svg +++ b/chapter02/docs/02-demonstration-pre-peephole-nokill.svg @@ -1,100 +1,84 @@ - - - - - - -chapter02 - - -cluster_Nodes - - - - -Start1 - -Start - - - -Con_2 - -#1 - - - -Con_2->Start1 - - -0 - - - -Con_3 - -#2 - - - -Con_3->Start1 - - -0 - - - -Add4 - -+ - - - -Add4->Con_2 - - -1 - - - -Add4->Con_3 - - -2 - - - -Con_5 - -#3 - - - -Con_5->Start1 - - -0 - - - -Return6 - -Return - - - -Return6->Start1 - - -0 - - - -Return6->Con_5 - - -1 - - - \ No newline at end of file +#2[0] → #1 · ASSOC#3[0] → #1 · ASSOC#4[1] → #2 · DATA#4[2] → #3 · DATA#5[0] → #1 · ASSOC#6[0] → #1 · CTRL#6[1] → #5 · DATAStart  #1#1 Start +Type not computed + +#1  #2#2 #1 +Type not computed + +[0] → #1 ASSOC0#2  #3#3 #2 +Type not computed + +[0] → #1 ASSOC0+  #4#4 + +Type not computed + +[0] → — DATA +[1] → #2 DATA +[2] → #3 DATA012#3  #5#5 #3 +Type not computed + +[0] → #1 ASSOC0Return  #6#6 Return +Type not computed + +[0] → #1 CTRL +[1] → #5 DATA01 diff --git a/chapter02/docs/02-demonstration-pre-peephole.json b/chapter02/docs/02-demonstration-pre-peephole.json new file mode 100644 index 00000000..b29cf6dd --- /dev/null +++ b/chapter02/docs/02-demonstration-pre-peephole.json @@ -0,0 +1,16 @@ +{ + "ver": 1, + "comp": "chapter02/docs/02-demonstration-pre-peephole.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 2, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 3, "label": "#2", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 4, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 2, "role": "DATA", "label": null}, {"idx": 2, "def": 3, "role": "DATA", "label": null}], "proj": null}, + {"id": 5, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter02/docs/02-demonstration-pre-peephole.svg b/chapter02/docs/02-demonstration-pre-peephole.svg index 49624652..8809a0c0 100644 --- a/chapter02/docs/02-demonstration-pre-peephole.svg +++ b/chapter02/docs/02-demonstration-pre-peephole.svg @@ -1,87 +1,81 @@ - - - - - - -chapter02 - - -cluster_Nodes - - - - -Start1 - -Start - - - -Con_2 - -#1 - - - -Con_2->Start1 - - -0 - - - -Con_3 - -#2 - - - -Con_3->Start1 - - -0 - - - -Add4 - -+ - - - -Add4->Con_2 - - -1 - - - -Add4->Con_3 - - -2 - - - -Return5 - -Return - - - -Return5->Start1 - - -0 - - - -Return5->Add4 - - -1 - - - \ No newline at end of file +#2[0] → #1 · ASSOC#3[0] → #1 · ASSOC#4[1] → #2 · DATA#4[2] → #3 · DATA#5[0] → #1 · CTRL#5[1] → #4 · DATAStart  #1#1 Start +Type not computed + +#1  #2#2 #1 +Type not computed + +[0] → #1 ASSOC0#2  #3#3 #2 +Type not computed + +[0] → #1 ASSOC0+  #4#4 + +Type not computed + +[0] → — DATA +[1] → #2 DATA +[2] → #3 DATA012Return  #5#5 Return +Type not computed + +[0] → #1 CTRL +[1] → #4 DATA01 diff --git a/chapter02/docs/02-post-peephole-ex1.json b/chapter02/docs/02-post-peephole-ex1.json new file mode 100644 index 00000000..e9c6d1eb --- /dev/null +++ b/chapter02/docs/02-post-peephole-ex1.json @@ -0,0 +1,14 @@ +{ + "ver": 1, + "comp": "chapter02/docs/02-post-peephole-ex1.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 13, "label": "#2", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 14, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 13, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter02/docs/02-post-peephole-ex1.svg b/chapter02/docs/02-post-peephole-ex1.svg index db27e30d..6674839e 100644 --- a/chapter02/docs/02-post-peephole-ex1.svg +++ b/chapter02/docs/02-post-peephole-ex1.svg @@ -1,56 +1,73 @@ - - - - - - -chapter02 - - -cluster_Nodes - - - - -Start1 - -Start - - - -Con_13 - -#2 - - - -Con_13->Start1 - - -0 - - - -Return14 - -Return - - - -Return14->Start1 - - -0 - - - -Return14->Con_13 - - -1 - - - +#13[0] → #1 · ASSOC#14[0] → #1 · CTRL#14[1] → #13 · DATAStart  #1#1 Start +Type not computed + +#2  #13#13 #2 +Type not computed + +[0] → #1 ASSOC0Return  #14#14 Return +Type not computed + +[0] → #1 CTRL +[1] → #13 DATA01 diff --git a/chapter02/docs/02-pre-peephole-ex1.json b/chapter02/docs/02-pre-peephole-ex1.json new file mode 100644 index 00000000..012bd814 --- /dev/null +++ b/chapter02/docs/02-pre-peephole-ex1.json @@ -0,0 +1,21 @@ +{ + "ver": 1, + "comp": "chapter02/docs/02-pre-peephole-ex1.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 2, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 3, "label": "#2", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 4, "label": "#3", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 5, "label": "*", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 3, "role": "DATA", "label": null}, {"idx": 2, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 6, "label": "#5", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 1, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 7, "label": "-", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 8, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 2, "role": "DATA", "label": null}, {"idx": 2, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter02/docs/02-pre-peephole-ex1.svg b/chapter02/docs/02-pre-peephole-ex1.svg index 29c76bd8..e2e5f785 100644 --- a/chapter02/docs/02-pre-peephole-ex1.svg +++ b/chapter02/docs/02-pre-peephole-ex1.svg @@ -1,168 +1,101 @@ - - - - - - -chapter02 - - -cluster_Nodes - - - - -Start1 - -Start - - - -Con_2 - -#1 - - - -Con_2->Start1 - - -0 - - - -Con_3 - -#2 - - - -Con_3->Start1 - - -0 - - - -Con_4 - -#3 - - - -Con_4->Start1 - - -0 - - - -Mul5 - -* - - - -Mul5->Con_3 - - -1 - - - -Mul5->Con_4 - - -2 - - - -Con_6 - -#5 - - - -Con_6->Start1 - - -0 - - - -Minus7 - -- - - - -Minus7->Con_6 - - -1 - - - -Add8 - -+ - - - -Add8->Mul5 - - -1 - - - -Add8->Minus7 - - -2 - - - -Add9 - -+ - - - -Add9->Con_2 - - -1 - - - -Add9->Add8 - - -2 - - - -Return10 - -Return - - - -Return10->Start1 - - -0 - - - -Return10->Add9 - - -1 - - - +#2[0] → #1 · ASSOC#3[0] → #1 · ASSOC#4[0] → #1 · ASSOC#5[1] → #3 · DATA#5[2] → #4 · DATA#6[0] → #1 · ASSOC#7[1] → #6 · DATA#8[1] → #5 · DATA#8[2] → #7 · DATA#9[1] → #2 · DATA#9[2] → #8 · DATA#10[0] → #1 · CTRL#10[1] → #9 · DATAStart  #1#1 Start +Type not computed + +#1  #2#2 #1 +Type not computed + +[0] → #1 ASSOC0#2  #3#3 #2 +Type not computed + +[0] → #1 ASSOC0#3  #4#4 #3 +Type not computed + +[0] → #1 ASSOC0*  #5#5 * +Type not computed + +[0] → — DATA +[1] → #3 DATA +[2] → #4 DATA012#5  #6#6 #5 +Type not computed + +[0] → #1 ASSOC0-  #7#7 - +Type not computed + +[0] → — DATA +[1] → #6 DATA01+  #8#8 + +Type not computed + +[0] → — DATA +[1] → #5 DATA +[2] → #7 DATA012+  #9#9 + +Type not computed + +[0] → — DATA +[1] → #2 DATA +[2] → #8 DATA012Return  #10#10 Return +Type not computed + +[0] → #1 CTRL +[1] → #9 DATA01 diff --git a/chapter02/docs/Makefile b/chapter02/docs/Makefile index 12659b8f..6fa0f057 100644 --- a/chapter02/docs/Makefile +++ b/chapter02/docs/Makefile @@ -1,12 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter02/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter02/src/main/java/com/seaofnodes/simple/type/Type.java index 7ea17bfb..b98ce6de 100644 --- a/chapter02/src/main/java/com/seaofnodes/simple/type/Type.java +++ b/chapter02/src/main/java/com/seaofnodes/simple/type/Type.java @@ -36,5 +36,10 @@ public class Type { public boolean isConstant() { return _type == TTOP; } + @Override + public String toString() { + return print(new StringBuilder()).toString(); + } + public StringBuilder print(StringBuilder sb) {return is_simple() ? sb.append(STRS[_type]) : sb;} } diff --git a/chapter03/README.md b/chapter03/README.md index e8944e12..5998efad 100644 --- a/chapter03/README.md +++ b/chapter03/README.md @@ -1,13 +1,15 @@ # Chapter 3: Variable Declarations +[Previous: Chapter 2](../chapter02/README.md) | +[Next: Chapter 4](../chapter04/README.md) + # Table of Contents 1. [Extensions to Intermediate Representation](#extensions-to-intermediate-representation) 2. [Symbol Tables](#symbol-tables) 3. [ScopeNode](#scopenode) 4. [Demonstration](#demonstration) -5. [Identification of Basic Blocks in SoN graph](#identification-of-basic-blocks-in-son-graph) -6. [Enabling peephole optimizations](#enabling-peephole-optimizations) +5. [Enabling peephole optimizations](#enabling-peephole-optimizations) You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter03) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch and [compare](https://github.com/SeaOfNodes/Simple/compare/linear-chapter02...linear-chapter03) it to the previous chapter. @@ -29,7 +31,7 @@ Here is the [complete language grammar](docs/03-grammar.md) for this chapter. ## Extensions to Intermediate Representation -To recap, our list of Nodes are: +To recap, our list of Nodes is: | Node Name | Type | Description | Inputs | Value | |-----------|---------|------------------------------------|------------------------------------------------------------------|-------------------------------------------------------| @@ -67,17 +69,17 @@ the stack of symbol tables, in lexical order. A ScopeNode encapsulates the stack of symbol tables that are used to implement lexical scopes. -* The nodes referenced by the names in a lexical scope become inputs to the ScopeNode; this makes ScopeNode a user of these values, thus keeping them alive while a particular lexical scope is alive. - When the lexical scope ends, those inputs are removed. This is crucial because peepholes will remove dead Nodes and every new Node is effectively dead at the instance of creation without such a reference. -* In [Chapter 5](../chapter05/README.md) when we implement branches, the ScopeNode gets duplicated at a branch point and then gets merged when the branch joins. This allows - the names to evolve in each branch independently. At the merge point names that have diverged require a Phi node. +* The nodes referenced by the names in a lexical scope become inputs to the ScopeNode; this makes ScopeNode a user of these values, thus keeping them alive while a particular lexical scope is alive. + When the lexical scope ends, those inputs are removed. This is crucial because peepholes will remove dead Nodes and every new Node is effectively dead at the instant of creation without such a reference. +* In [Chapter 5](../chapter05/README.md) when we implement branches, the ScopeNode gets duplicated at a branch point and then gets merged when the branch joins. This allows + the names to evolve in each branch independently. At the merge point names that have diverged require a Phi node. * In [Chapter 7](../chapter07/README.md) additional logic is deployed for handling Phis from back edges. * The ScopeNode is used to track some other values such as the Control token starting from [Chapter 4](../chapter04/README.md), and whole memory starting from [Chapter 10a](../chapter10a/README.md). Special name bindings are used for these, and each name is tracked across branches and then merged at merge points. * In [Chapter 10a](../chapter10a/README.md) the ScopeNode is enhanced to also maintain the declared type for each name. From an implementation standpoint, each symbol table is represented as a `HashMap`, where the `String` is the variable name, and the `Integer` is an index into the inputs of the -ScopeNode. To access the Node associated with a name, first the symbol table is consulted, and then the ScopeNode's inputs to find the required Node. +ScopeNode. To access the Node associated with a name, first the symbol table is consulted, and then the ScopeNode's inputs to find the required Node. The stack of symbol tables is represented as `Stack>`. When a lexical scope is exited, we not only pop the symbol table representing the @@ -93,9 +95,9 @@ that uses the variable) this is when the expression dies: ``` -In the visualization, we show the ScopeNode in a separate box running -underneath the main IR graph; the stack of symbol tables is shown inside the -box. We show the edge from each variable in the symbol table to the defining +In the visualization, we show the ScopeNode in a separate purple box. Each +binding is labelled with its lexical scope level. We show the edge from each +variable in the symbol table to the defining Node in the graph. The ScopeNode is neither a Data Node nor a Control Node; it really is a utility for maintaining symbol tables, name lookups, plays a crucial role in deciding where Phi nodes are required. @@ -105,7 +107,7 @@ A ScopeNode has no outputs. ## Demonstration -We show the output from following code. +We show the output from the following code. ``` 01 int a=1; @@ -118,7 +120,7 @@ We show the output from following code. 09 return c; ``` -* When we start parsing above, we start with a symbol table (at level 0). +* When we start parsing the example above, we start with a symbol table (at level 0). The variables `a`, `b`, and `c` are registered in this table. * On line 4, we start a nested scope. At this point, a new symbol table is pushed (at level 1). * On line 5, a variable `b` is declared. `b` is registered in the symbol table at level 1. This then @@ -130,8 +132,8 @@ result of this example is `return 4;`. ![Graph1](./docs/03-graph1.svg) -The diagram shows the ScopeNode and the symbol tables in the bottom cluster. -Each table is annotated by its scope level, and shows the variables defined in that scope. +The diagram shows the ScopeNode's bindings with their scope levels. The two +bindings for `b` belong to different lexical scopes. * When we exit the nested scope on line 8, the symbol table at level 1 is popped. * At line 9, our graph looks like this: @@ -140,43 +142,43 @@ Each table is annotated by its scope level, and shows the variables defined in t As we see, only 1 symbol table is present at this point. -We can also have multiple scopes at the same level during the execution of the program, -but only one will be active at a time because the symbol table can only hold one symbol table +We can also have multiple scopes at the same level during the execution of the program, +but only one will be active at a time because the symbol table can only hold one symbol table for each scope level. For example: ``` -01 int a=1; -02 int b=2; -03 int c=0; -04 { -05 int b=5; -06 c=a+b; -08 } +01 int a=1; +02 int b=2; +03 int c=0; +04 { +05 int b=5; +06 c=a+b; +08 } 09 { -10 int e=6; -11 c = a+e; -13 } -14 return c; +10 int e=6; +11 c = a+e; +13 } +14 return c; ``` Here both scopes starting from `(04-08)` and `(09-13)` are at the same level: ```java public final Stack> _scopes; ``` -The `_scopes` stack holds nested scopes, with index 0 representing the highest (global) -scope and deeper indices representing more nested scopes. -Popping returns the current scope and moves to the outer one. +The `_scopes` stack holds nested scopes, with index 0 representing the highest (global) +scope and deeper indices representing more nested scopes. +Popping returns the current scope and moves to the outer one. There is a direct one-to-one mapping between each index and its corresponding scope. -The first nested scope(04-08): +The first nested scope (04-08): ![Graph4](./docs/03-graph4.svg) -The second nested scope(09-13): +The second nested scope (09-13): ![Graph5](./docs/03-graph5.svg) - - In both cases the index which represents the deepness of the scope is 1. + - In both cases the index which represents the depth of the scope is 1. ## Enabling peephole optimizations Once we enable peephole optimizations, the parser is able to reduce all the expressions down to a @@ -190,7 +192,7 @@ constant. This is illustrated nicely below. 05 return (x0-x1)*(x0-x1) + (y0-y1)*(y0-y1); ``` -The graph for above, is displayed below. +The graph for the example above is displayed below. ![Graph2](./docs/03-graph3.svg) diff --git a/chapter03/docs/03-graph1.json b/chapter03/docs/03-graph1.json new file mode 100644 index 00000000..5dce5431 --- /dev/null +++ b/chapter03/docs/03-graph1.json @@ -0,0 +1,17 @@ +{ + "ver": 1, + "comp": "chapter03/docs/03-graph1.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 3, "role": "ASSOC", "label": "0: a"}, {"idx": 1, "def": 4, "role": "ASSOC", "label": "0: b"}, {"idx": 2, "def": 7, "role": "ASSOC", "label": "0: c"}, {"idx": 3, "def": 6, "role": "ASSOC", "label": "1: b"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 4, "label": "#2", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 6, "label": "#3", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 7, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 3, "role": "DATA", "label": null}, {"idx": 2, "def": 6, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter03/docs/03-graph1.svg b/chapter03/docs/03-graph1.svg index ab6f9600..9ad933d5 100644 --- a/chapter03/docs/03-graph1.svg +++ b/chapter03/docs/03-graph1.svg @@ -1,136 +1,86 @@ - - - - - - -chapter03 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - -cluster_Scope1_1 - - - - -Start2 - -Start - - - -Con_3 - -#1 - - - -Con_3->Start2 - - -0 - - - -Con_4 - -#2 - - - -Con_4->Start2 - - -0 - - - -Con_6 - -#3 - - - -Con_6->Start2 - - -0 - - - -Add7 - -+ - - - -Add7->Con_3 - - -1 - - - -Add7->Con_6 - - -2 - - - -Scope1_0 - - -0 - -a - -b - -c - - - -Scope1_0:Scope1_0_a->Con_3 - - - - - -Scope1_0:Scope1_0_b->Con_4 - - - - - -Scope1_0:Scope1_0_c->Add7 - - - - - -Scope1_1 - - -1 - -b - - - -Scope1_1:Scope1_1_b->Con_6 - - - - - +#1[0] → #3 · ASSOC · 0: a#1[1] → #4 · ASSOC · 0: b#1[2] → #7 · ASSOC · 0: c#1[3] → #6 · ASSOC · 1: b#3[0] → #2 · ASSOC#4[0] → #2 · ASSOC#6[0] → #2 · ASSOC#7[1] → #3 · DATA#7[2] → #6 · DATAScope  #1#1 Scope +Type not computed + +[0] → #3 ASSOC 0: a +[1] → #4 ASSOC 0: b +[2] → #7 ASSOC 0: c +[3] → #6 ASSOC 1: b0: a0: b0: c1: b0123Start  #2#2 Start +Type not computed + +#1  #3#3 #1 +Type not computed + +[0] → #2 ASSOC0#2  #4#4 #2 +Type not computed + +[0] → #2 ASSOC0#3  #6#6 #3 +Type not computed + +[0] → #2 ASSOC0+  #7#7 + +Type not computed + +[0] → — DATA +[1] → #3 DATA +[2] → #6 DATA012 diff --git a/chapter03/docs/03-graph2.json b/chapter03/docs/03-graph2.json new file mode 100644 index 00000000..80397161 --- /dev/null +++ b/chapter03/docs/03-graph2.json @@ -0,0 +1,18 @@ +{ + "ver": 1, + "comp": "chapter03/docs/03-graph2.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 3, "role": "ASSOC", "label": "0: a"}, {"idx": 1, "def": 4, "role": "ASSOC", "label": "0: b"}, {"idx": 2, "def": 7, "role": "ASSOC", "label": "0: c"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 4, "label": "#2", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 6, "label": "#3", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 7, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 3, "role": "DATA", "label": null}, {"idx": 2, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 8, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter03/docs/03-graph2.svg b/chapter03/docs/03-graph2.svg index 0a539c6a..d59e5dc0 100644 --- a/chapter03/docs/03-graph2.svg +++ b/chapter03/docs/03-graph2.svg @@ -1,137 +1,89 @@ - - - - - - -chapter03 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - - -Start2 - -Start - - - -Con_3 - -#1 - - - -Con_3->Start2 - - -0 - - - -Con_4 - -#2 - - - -Con_4->Start2 - - -0 - - - -Con_6 - -#3 - - - -Con_6->Start2 - - -0 - - - -Add7 - -+ - - - -Add7->Con_3 - - -1 - - - -Add7->Con_6 - - -2 - - - -Return8 - -Return - - - -Return8->Start2 - - -0 - - - -Return8->Add7 - - -1 - - - -Scope1_0 - - -0 - -a - -b - -c - - - -Scope1_0:Scope1_0_a->Con_3 - - - - - -Scope1_0:Scope1_0_b->Con_4 - - - - - -Scope1_0:Scope1_0_c->Add7 - - - - - +#1[0] → #3 · ASSOC · 0: a#1[1] → #4 · ASSOC · 0: b#1[2] → #7 · ASSOC · 0: c#3[0] → #2 · ASSOC#4[0] → #2 · ASSOC#6[0] → #2 · ASSOC#7[1] → #3 · DATA#7[2] → #6 · DATA#8[0] → #2 · CTRL#8[1] → #7 · DATAScope  #1#1 Scope +Type not computed + +[0] → #3 ASSOC 0: a +[1] → #4 ASSOC 0: b +[2] → #7 ASSOC 0: c0: a0: b0: c012Start  #2#2 Start +Type not computed + +#1  #3#3 #1 +Type not computed + +[0] → #2 ASSOC0#2  #4#4 #2 +Type not computed + +[0] → #2 ASSOC0#3  #6#6 #3 +Type not computed + +[0] → #2 ASSOC0+  #7#7 + +Type not computed + +[0] → — DATA +[1] → #3 DATA +[2] → #6 DATA012Return  #8#8 Return +Type not computed + +[0] → #2 CTRL +[1] → #7 DATA01 diff --git a/chapter03/docs/03-graph3.json b/chapter03/docs/03-graph3.json new file mode 100644 index 00000000..a6d6175a --- /dev/null +++ b/chapter03/docs/03-graph3.json @@ -0,0 +1,19 @@ +{ + "ver": 1, + "comp": "chapter03/docs/03-graph3.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 4, "role": "ASSOC", "label": "0: y0"}, {"idx": 1, "def": 3, "role": "ASSOC", "label": "0: x0"}, {"idx": 2, "def": 6, "role": "ASSOC", "label": "0: y1"}, {"idx": 3, "def": 5, "role": "ASSOC", "label": "0: x1"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 4, "label": "#2", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 5, "label": "#3", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 6, "label": "#4", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 20, "label": "#8", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 21, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}, {"idx": 1, "def": 20, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter03/docs/03-graph3.svg b/chapter03/docs/03-graph3.svg index 623bd902..89eed120 100644 --- a/chapter03/docs/03-graph3.svg +++ b/chapter03/docs/03-graph3.svg @@ -1,151 +1,91 @@ - - - - - - -chapter03 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - - -Start2 - -Start - - - -Con_3 - -#1 - - - -Con_3->Start2 - - -0 - - - -Con_4 - -#2 - - - -Con_4->Start2 - - -0 - - - -Con_20 - -#8 - - - -Con_20->Start2 - - -0 - - - -Con_5 - -#3 - - - -Con_5->Start2 - - -0 - - - -Return21 - -Return - - - -Return21->Start2 - - -0 - - - -Return21->Con_20 - - -1 - - - -Con_6 - -#4 - - - -Con_6->Start2 - - -0 - - - -Scope1_0 - - -0 - -y0 - -x0 - -y1 - -x1 - - - -Scope1_0:Scope1_0_x0->Con_3 - - - - - -Scope1_0:Scope1_0_y0->Con_4 - - - - - -Scope1_0:Scope1_0_x1->Con_5 - - - - - -Scope1_0:Scope1_0_y1->Con_6 - - - - - +#1[0] → #4 · ASSOC · 0: y0#1[1] → #3 · ASSOC · 0: x0#1[2] → #6 · ASSOC · 0: y1#1[3] → #5 · ASSOC · 0: x1#3[0] → #2 · ASSOC#4[0] → #2 · ASSOC#5[0] → #2 · ASSOC#6[0] → #2 · ASSOC#20[0] → #2 · ASSOC#21[0] → #2 · CTRL#21[1] → #20 · DATAScope  #1#1 Scope +Type not computed + +[0] → #4 ASSOC 0: y0 +[1] → #3 ASSOC 0: x0 +[2] → #6 ASSOC 0: y1 +[3] → #5 ASSOC 0: x10: y00: x00: y10: x10123Start  #2#2 Start +Type not computed + +#1  #3#3 #1 +Type not computed + +[0] → #2 ASSOC0#2  #4#4 #2 +Type not computed + +[0] → #2 ASSOC0#3  #5#5 #3 +Type not computed + +[0] → #2 ASSOC0#4  #6#6 #4 +Type not computed + +[0] → #2 ASSOC0#8  #20#20 #8 +Type not computed + +[0] → #2 ASSOC0Return  #21#21 Return +Type not computed + +[0] → #2 CTRL +[1] → #20 DATA01 diff --git a/chapter03/docs/03-graph4.json b/chapter03/docs/03-graph4.json new file mode 100644 index 00000000..b594eee2 --- /dev/null +++ b/chapter03/docs/03-graph4.json @@ -0,0 +1,17 @@ +{ + "ver": 1, + "comp": "chapter03/docs/03-graph4.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 3, "role": "ASSOC", "label": "0: a"}, {"idx": 1, "def": 4, "role": "ASSOC", "label": "0: b"}, {"idx": 2, "def": 8, "role": "ASSOC", "label": "0: c"}, {"idx": 3, "def": 6, "role": "ASSOC", "label": "1: b"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 4, "label": "#2", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 6, "label": "#5", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 8, "label": "#6", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter03/docs/03-graph4.svg b/chapter03/docs/03-graph4.svg index 6838e1d4..c773ef9b 100644 --- a/chapter03/docs/03-graph4.svg +++ b/chapter03/docs/03-graph4.svg @@ -1,127 +1,84 @@ - - - - - - -chapter03 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - -cluster_Scope1_1 - - - - -Start2 - -Start - - - -Con_3 - -#1 - - - -Con_3->Start2 - - -0 - - - -Con_4 - -#2 - - - -Con_4->Start2 - - -0 - - - -Con_6 - -#5 - - - -Con_6->Start2 - - -0 - - - -Con_8 - -#6 - - - -Con_8->Start2 - - -0 - - - -Scope1_0 - - -0 - -a - -b - -c - - - -Scope1_0:Scope1_0_a->Con_3 - - - - - -Scope1_0:Scope1_0_b->Con_4 - - - - - -Scope1_0:Scope1_0_c->Con_8 - - - - - -Scope1_1 - - -1 - -b - - - -Scope1_1:Scope1_1_b->Con_6 - - - - - \ No newline at end of file +#1[0] → #3 · ASSOC · 0: a#1[1] → #4 · ASSOC · 0: b#1[2] → #8 · ASSOC · 0: c#1[3] → #6 · ASSOC · 1: b#3[0] → #2 · ASSOC#4[0] → #2 · ASSOC#6[0] → #2 · ASSOC#8[0] → #2 · ASSOCScope  #1#1 Scope +Type not computed + +[0] → #3 ASSOC 0: a +[1] → #4 ASSOC 0: b +[2] → #8 ASSOC 0: c +[3] → #6 ASSOC 1: b0: a0: b0: c1: b0123Start  #2#2 Start +Type not computed + +#1  #3#3 #1 +Type not computed + +[0] → #2 ASSOC0#2  #4#4 #2 +Type not computed + +[0] → #2 ASSOC0#5  #6#6 #5 +Type not computed + +[0] → #2 ASSOC0#6  #8#8 #6 +Type not computed + +[0] → #2 ASSOC0 diff --git a/chapter03/docs/03-graph5.json b/chapter03/docs/03-graph5.json new file mode 100644 index 00000000..476ad586 --- /dev/null +++ b/chapter03/docs/03-graph5.json @@ -0,0 +1,17 @@ +{ + "ver": 1, + "comp": "chapter03/docs/03-graph5.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 3, "role": "ASSOC", "label": "0: a"}, {"idx": 1, "def": 4, "role": "ASSOC", "label": "0: b"}, {"idx": 2, "def": 11, "role": "ASSOC", "label": "0: c"}, {"idx": 3, "def": 9, "role": "ASSOC", "label": "1: e"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "#1", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 4, "label": "#2", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 9, "label": "#6", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null}, + {"id": 11, "label": "#7", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "ASSOC", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter03/docs/03-graph5.svg b/chapter03/docs/03-graph5.svg index 48e69cb7..a62d03bb 100644 --- a/chapter03/docs/03-graph5.svg +++ b/chapter03/docs/03-graph5.svg @@ -1,127 +1,84 @@ - - - - - - -chapter03 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - -cluster_Scope1_1 - - - - -Start2 - -Start - - - -Con_3 - -#1 - - - -Con_3->Start2 - - -0 - - - -Con_4 - -#2 - - - -Con_4->Start2 - - -0 - - - -Con_9 - -#6 - - - -Con_9->Start2 - - -0 - - - -Con_11 - -#7 - - - -Con_11->Start2 - - -0 - - - -Scope1_0 - - -0 - -a - -b - -c - - - -Scope1_0:Scope1_0_a->Con_3 - - - - - -Scope1_0:Scope1_0_b->Con_4 - - - - - -Scope1_0:Scope1_0_c->Con_11 - - - - - -Scope1_1 - - -1 - -e - - - -Scope1_1:Scope1_1_e->Con_9 - - - - - \ No newline at end of file +#1[0] → #3 · ASSOC · 0: a#1[1] → #4 · ASSOC · 0: b#1[2] → #11 · ASSOC · 0: c#1[3] → #9 · ASSOC · 1: e#3[0] → #2 · ASSOC#4[0] → #2 · ASSOC#9[0] → #2 · ASSOC#11[0] → #2 · ASSOCScope  #1#1 Scope +Type not computed + +[0] → #3 ASSOC 0: a +[1] → #4 ASSOC 0: b +[2] → #11 ASSOC 0: c +[3] → #9 ASSOC 1: e0: a0: b0: c1: e0123Start  #2#2 Start +Type not computed + +#1  #3#3 #1 +Type not computed + +[0] → #2 ASSOC0#2  #4#4 #2 +Type not computed + +[0] → #2 ASSOC0#6  #9#9 #6 +Type not computed + +[0] → #2 ASSOC0#7  #11#11 #7 +Type not computed + +[0] → #2 ASSOC0 diff --git a/chapter03/docs/Makefile b/chapter03/docs/Makefile index 12659b8f..6fa0f057 100644 --- a/chapter03/docs/Makefile +++ b/chapter03/docs/Makefile @@ -1,12 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter03/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter03/src/main/java/com/seaofnodes/simple/type/Type.java index 7ea17bfb..b98ce6de 100644 --- a/chapter03/src/main/java/com/seaofnodes/simple/type/Type.java +++ b/chapter03/src/main/java/com/seaofnodes/simple/type/Type.java @@ -36,5 +36,10 @@ public class Type { public boolean isConstant() { return _type == TTOP; } + @Override + public String toString() { + return print(new StringBuilder()).toString(); + } + public StringBuilder print(StringBuilder sb) {return is_simple() ? sb.append(STRS[_type]) : sb;} } diff --git a/chapter04/README.md b/chapter04/README.md index fd77392c..e7ae71d2 100644 --- a/chapter04/README.md +++ b/chapter04/README.md @@ -1,26 +1,29 @@ # Chapter 4: External Argument and Comparisons +[Previous: Chapter 3](../chapter03/README.md) | +[Next: Chapter 5](../chapter05/README.md) + # Table of Contents 1. [Extensions to Intermediate Representation](#extensions-to-intermediate-representation) 2. [Projection Nodes](#projection-nodes) 3. [Visualisation](#visualisation) -5. [Initial values](#initial-values) -6. [When Is Control Not-Null?](#when-is-control-not-null) -5. [Note Regarding Visualizations](#note-regarding-visualizations) -6. [Changes to Type System](#changes-to-type-system) -7. [Tuple Types](#tuple-types) -8. [$ctrl name binding](#ctrl-name-binding) -9. [More Peephole Optimizations](#more-peephole-optimizations) -10. [Peephole Walkthrough](#peephole-walkthrough) -11. [Dead Code Elimination(DCE)](#dead-code-eliminationdce) +4. [Initial values](#initial-values) +5. [When Is Control Not-Null?](#when-is-control-not-null) +6. [Note Regarding Visualizations](#note-regarding-visualizations) +7. [Changes to Type System](#changes-to-type-system) +8. [Tuple Types](#tuple-types) +9. [$ctrl name binding](#ctrl-name-binding) +10. [More Peephole Optimizations](#more-peephole-optimizations) +11. [Peephole Walkthrough](#peephole-walkthrough) +12. [Dead Code Elimination(DCE)](#dead-code-eliminationdce) You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter04) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch and [compare](https://github.com/SeaOfNodes/Simple/compare/linear-chapter03...linear-chapter04) it to the previous chapter. -In this chapter we extend the language grammar with following features: +In this chapter we extend the language grammar with the following features: -* The program receives a single argument named `arg` of integer type from external environment. +* The program receives a single argument named `arg` of integer type from the external environment. * Expressions support comparison operators. * We introduce a scope sensitive name binding `$ctrl` for the current incoming control node. Thus, our Return is no longer hard-wired to Start, instead it @@ -69,15 +72,15 @@ In the visuals, projection nodes are shown as rectangular boxes inside the node ### Visualisation -![ProjNode](./docs/projnode.png) +![Start and its control and argument projections](./docs/projnode.svg) In the visual above, the projection nodes have been tagged by the names -associated with the outputs of the Start node. Both MultiNode that contain -Control and Control nodes are yellow. `$ctrl` and `arg` are outputs(users) of +associated with the outputs of the Start node. Both MultiNodes that contain +Control and Control nodes are yellow. `$ctrl` and `arg` are outputs (users) of StartNode(`START`) and have their MultiNode as their only input in slot 0. The `label` has no semantics and is used during debug printing. -```java +```java public ProjNode(MultiNode ctrl, int idx, String label) { super(ctrl); ``` @@ -130,37 +133,37 @@ The graph: constant. The `arg` was originally defined by a ProjNode; but when peephole is called the computed type is a constant, and the ProjNode gets replaced with a ConstantNode: - + ```java public final Node peephole( ) { - Type type = _type = compute(); + Type type = _type = compute(); /* type = {TypeInteger@1527} "2" */ // ProjNode is not a constant unlike its type. if (!(this instanceof ConstantNode) && type.isConstant()) /* Create Constant(2) */ return deadCodeElim(new ConstantNode(type).peephole()); - + /* won't get called */ ... ``` If you don't pass an argument you get `TypeInteger.BOT` -```java +```java Parser parser = new Parser("return arg; "); ... - + public Parser(String source) { this(source, TypeInteger.BOT); } - + ``` We clearly see this is not a constant: ```java -public final static TypeInteger BOT = new TypeInteger(false, 1); +public final static TypeInteger BOT = new TypeInteger(false, 1); /* _is_con = false */ ``` @@ -177,7 +180,7 @@ In later chapters, `$ctrl` will point to other control nodes, such as #### Note Regarding Visualizations From this chapter onwards we omit the edges from Constants to Start node, mainly to reduce -clutter and help draw reader's attention to the more important aspects of the graph. +clutter and help draw the reader's attention to the more important aspects of the graph. @@ -195,7 +198,7 @@ associated with a Type at a specific Node can be conveniently represented as a [lattice](https://en.wikipedia.org/wiki/Lattice_(order)). The type itself is identified by the Java class `Type` and subtypes. The type -implementation uses Java classes as convenient to deal with a Types' internal +implementation uses Java classes as a convenient way to deal with a Type's internal structure - but the Java classes have no relation to a Type's place in the lattice. @@ -239,20 +242,20 @@ In the table above `Con1` and `Con2` represent two distinct integer values, and * The `meet` of any integer with itself is that integer. * The `meet` of two unrelated integer constants is `IntBot`. -Currently, all our integer valued nodes are either a constant or a `IntBot` integer type. +Currently, all our integer valued nodes are either a constant or an `IntBot` integer type. When we start optimizing loops, we will start seeing `IntTop` values. ### Tuple Types -Tuple types need a little more explaination: they are a fixed-size grouping of +Tuple types need a little more explanation: they are a fixed-size grouping of types; literally a `Type[]`. Tuples represent a collection of otherwise unrelated types, and come from `MultiNode`s. `ProjNode`s will take the appropriate `Type` array element out of a Tuple. The `StartNode` now produces a 2-element `TypeTuple` with control and the type of `arg`: `[ctrl, TypeInteger.INTBOT]` The lattice `meet` operator on Tuples is done element by element; each array -element recursively calls `meet`. Tuples of mixed sizes are a internal +element recursively calls `meet`. Tuples of mixed sizes are an internal compiler error, and the `meet` uses Bottom for them. @@ -284,7 +287,7 @@ We would expect the compiler to output `arg+3` here, but as it stands what we ge ![Graph1](./docs/04-pre-peephole.svg) -We need to perform some algebraic simplifications to enable better outcome. For +We need to perform some algebraic simplifications to enable a better outcome. For example, we need to rearrange the expression as follows: ``` @@ -303,7 +306,7 @@ Here is a list of peepholes introduced in this Chapter, more will be introduced |-----------------------|-----------------------|------------------------------------------------| | (arg + 0 ) | arg | Add of zero identity | | (arg - 0 ) | arg | Sub of zero identity | -| (arg * 1 ) | arg | Multiple of one identity | +| (arg * 1 ) | arg | Multiply by one identity | | (con + arg) | (arg + con) | Move constants to right, to encourage folding | | (con * arg) | (arg * con) | Move constants to right, to encourage folding | | (con1 + (arg + con2)) | (arg + (con1 + con2)) | Move constants to right, to encourage folding | @@ -374,18 +377,18 @@ public final Node peephole( ) { } ``` -The peephole method does following: +The peephole method does the following: - Compute a Type for the node. - If the Type is a Constant and the node is not a ConstantNode, replace with a ConstantNode, recursively invoking peephole on the new constant. - Otherwise, ask the Node for a better replacement via a call to `idealize()`. - The "better replacement" is things like `(1+2)` becomes `3` and `1+(x+2))` + The "better replacement" is things like `(1+2)` becomes `3` and `1+(x+2)` becomes `(x+(1+2))`. -- - Each Node subtype is responsible for deciding what the `idealize()` step +- Each Node subtype is responsible for deciding what the `idealize()` step should do. If there is a better replacement then the node returns a non `null` value. -- - If we see a non `null` value, something changed, so we invoke `peephole()` +- If we see a non `null` value, something changed, so we invoke `peephole()` again and then also run dead code elimination on the (now dead and replaced) `this` node. diff --git a/chapter04/docs/04-arg1.json b/chapter04/docs/04-arg1.json new file mode 100644 index 00000000..b16dc51b --- /dev/null +++ b/chapter04/docs/04-arg1.json @@ -0,0 +1,16 @@ +{ + "ver": 1, + "comp": "chapter04/docs/04-arg1.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": "0: $ctrl"}, {"idx": 1, "def": 5, "role": "ASSOC", "label": "0: arg"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 4, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 5, "label": "2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 6, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 4, "role": "CTRL", "label": null}, {"idx": 1, "def": 5, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter04/docs/04-arg1.svg b/chapter04/docs/04-arg1.svg index cf4599c5..b948e7cd 100644 --- a/chapter04/docs/04-arg1.svg +++ b/chapter04/docs/04-arg1.svg @@ -1,84 +1,81 @@ - - - - - - -chapter04 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - -cluster_Scope1_1 - - - - -Start2 - - -Start - - - -$ctrl - - - -Con_5 - -2 - - - -Return6 - -Return - - - -Return6->Start2:p0 - - -0 - - - -Return6->Con_5 - - -1 - - - -Scope1_0 - - -0 - -$ctrl - -arg - - - -Scope1_0:Scope1_0_arg->Con_5 - - - - - -Scope1_1 - - -1 - - - \ No newline at end of file +#1[1] → #5 · ASSOC · 0: arg#6[0] → #4 · CTRL#6[1] → #5 · DATAScope  #1#1 Scope +Type not computed + +[0] → — ASSOC 0: $ctrl +[1] → #5 ASSOC 0: arg0: $ctrl0: arg01Start  #2#2 Start +Type not computed + +$ctrl  #4/0#4 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRL2  #5#5 2 +Type not computed + +Return  #6#6 Return +Type not computed + +[0] → #4 CTRL +[1] → #5 DATA01 diff --git a/chapter04/docs/04-arg2.json b/chapter04/docs/04-arg2.json new file mode 100644 index 00000000..5d2d7fde --- /dev/null +++ b/chapter04/docs/04-arg2.json @@ -0,0 +1,16 @@ +{ + "ver": 1, + "comp": "chapter04/docs/04-arg2.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": "0: $ctrl"}, {"idx": 1, "def": 6, "role": "ASSOC", "label": "0: arg"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 4, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 5, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 4, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 6, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}} + ], + "groups": [ + ] +} diff --git a/chapter04/docs/04-arg2.svg b/chapter04/docs/04-arg2.svg index 2b3b47a3..aebd8b0d 100644 --- a/chapter04/docs/04-arg2.svg +++ b/chapter04/docs/04-arg2.svg @@ -1,80 +1,82 @@ - - - - - - -chapter04 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - -cluster_Scope1_1 - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Return5 - -Return - - - -Return5->Start2:p0 - - -0 - - - -Return5->Start2:p1 - - -1 - - - -Scope1_0 - - -0 - -$ctrl - -arg - - - -Scope1_0:Scope1_0_arg->Start2:p1 - - - - - -Scope1_1 - - -1 - - - \ No newline at end of file +#1[1] → #6 · ASSOC · 0: arg#5[0] → #4 · CTRL#5[1] → #6 · DATAScope  #1#1 Scope +Type not computed + +[0] → — ASSOC 0: $ctrl +[1] → #6 ASSOC 0: arg0: $ctrl0: arg01Start  #2#2 Start +Type not computed + +$ctrl  #4/0#4 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLReturn  #5#5 Return +Type not computed + +[0] → #4 CTRL +[1] → #6 DATA01arg  #6/1#6 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATA diff --git a/chapter04/docs/04-post-peephole.json b/chapter04/docs/04-post-peephole.json new file mode 100644 index 00000000..4890ca67 --- /dev/null +++ b/chapter04/docs/04-post-peephole.json @@ -0,0 +1,18 @@ +{ + "ver": 1, + "comp": "chapter04/docs/04-post-peephole.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": "0: $ctrl"}, {"idx": 1, "def": 5, "role": "ASSOC", "label": "0: arg"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 4, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 5, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 10, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 11, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "DATA", "label": null}, {"idx": 2, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 12, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 4, "role": "CTRL", "label": null}, {"idx": 1, "def": 11, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter04/docs/04-post-peephole.svg b/chapter04/docs/04-post-peephole.svg index 550c16ef..530155dd 100644 --- a/chapter04/docs/04-post-peephole.svg +++ b/chapter04/docs/04-post-peephole.svg @@ -1,108 +1,90 @@ - - - - - - -chapter04 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - -cluster_Scope1_1 - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Con_10 - -#3 - - - -Add11 - -+ - - - -Add11->Start2:p1 - - -1 - - - -Add11->Con_10 - - -2 - - - -Return12 - -Return - - - -Return12->Start2:p0 - - -0 - - - -Return12->Add11 - - -1 - - - -Scope1_0 - - -0 - -$ctrl - -arg - - - -Scope1_0:Scope1_0_arg->Start2:p1 - - - - - -Scope1_1 - - -1 - - - +#1[1] → #5 · ASSOC · 0: arg#11[1] → #5 · DATA#11[2] → #10 · DATA#12[0] → #4 · CTRL#12[1] → #11 · DATAScope  #1#1 Scope +Type not computed + +[0] → — ASSOC 0: $ctrl +[1] → #5 ASSOC 0: arg0: $ctrl0: arg01Start  #2#2 Start +Type not computed + +$ctrl  #4/0#4 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLarg  #5/1#5 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATA#3  #10#10 #3 +Type not computed + ++  #11#11 + +Type not computed + +[0] → — DATA +[1] → #5 DATA +[2] → #10 DATA012Return  #12#12 Return +Type not computed + +[0] → #4 CTRL +[1] → #11 DATA01 diff --git a/chapter04/docs/04-pre-peephole.json b/chapter04/docs/04-pre-peephole.json new file mode 100644 index 00000000..839c16e7 --- /dev/null +++ b/chapter04/docs/04-pre-peephole.json @@ -0,0 +1,20 @@ +{ + "ver": 1, + "comp": "chapter04/docs/04-pre-peephole.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": "0: $ctrl"}, {"idx": 1, "def": 10, "role": "ASSOC", "label": "0: arg"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 4, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 5, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 6, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 7, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}, {"idx": 2, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 8, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 4, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}} + ], + "groups": [ + ] +} diff --git a/chapter04/docs/04-pre-peephole.svg b/chapter04/docs/04-pre-peephole.svg index 9ec38d27..5ad17b13 100644 --- a/chapter04/docs/04-pre-peephole.svg +++ b/chapter04/docs/04-pre-peephole.svg @@ -1,134 +1,98 @@ - - - - - - -chapter04 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - -cluster_Scope1_1 - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Con_5 - -#1 - - - -Con_6 - -#2 - - - -Add7 - -+ - - - -Add7->Start2:p1 - - -1 - - - -Add7->Con_6 - - -2 - - - -Add8 - -+ - - - -Add8->Con_5 - - -1 - - - -Add8->Add7 - - -2 - - - -Return9 - -Return - - - -Return9->Start2:p0 - - -0 - - - -Return9->Add8 - - -1 - - - -Scope1_0 - - -0 - -$ctrl - -arg - - - -Scope1_0:Scope1_0_arg->Start2:p1 - - - - - -Scope1_1 - - -1 - - - +#1[1] → #10 · ASSOC · 0: arg#7[1] → #10 · DATA#7[2] → #6 · DATA#8[1] → #5 · DATA#8[2] → #7 · DATA#9[0] → #4 · CTRL#9[1] → #8 · DATAScope  #1#1 Scope +Type not computed + +[0] → — ASSOC 0: $ctrl +[1] → #10 ASSOC 0: arg0: $ctrl0: arg01Start  #2#2 Start +Type not computed + +$ctrl  #4/0#4 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRL#1  #5#5 #1 +Type not computed + +#2  #6#6 #2 +Type not computed + ++  #7#7 + +Type not computed + +[0] → — DATA +[1] → #10 DATA +[2] → #6 DATA012+  #8#8 + +Type not computed + +[0] → — DATA +[1] → #5 DATA +[2] → #7 DATA012Return  #9#9 Return +Type not computed + +[0] → #4 CTRL +[1] → #8 DATA01arg  #10/1#10 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATA diff --git a/chapter04/docs/Makefile b/chapter04/docs/Makefile index 12659b8f..6fa0f057 100644 --- a/chapter04/docs/Makefile +++ b/chapter04/docs/Makefile @@ -1,12 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter04/docs/projnode.json b/chapter04/docs/projnode.json new file mode 100644 index 00000000..3d4d20cf --- /dev/null +++ b/chapter04/docs/projnode.json @@ -0,0 +1,14 @@ +{ + "ver": 1, + "comp": "chapter04/docs/projnode.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 4, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 6, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}} + ], + "groups": [ + ] +} diff --git a/chapter04/docs/projnode.svg b/chapter04/docs/projnode.svg new file mode 100644 index 00000000..b1291cdb --- /dev/null +++ b/chapter04/docs/projnode.svg @@ -0,0 +1,74 @@ +Start  #2#2 Start +Type not computed + +$ctrl  #4/0#4 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLarg  #6/1#6 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATA diff --git a/chapter04/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter04/src/main/java/com/seaofnodes/simple/type/Type.java index 1e50bdda..466fb739 100644 --- a/chapter04/src/main/java/com/seaofnodes/simple/type/Type.java +++ b/chapter04/src/main/java/com/seaofnodes/simple/type/Type.java @@ -41,12 +41,13 @@ public class Type { public boolean isConstant() { return _type == TTOP; } - public StringBuilder print(StringBuilder sb) {return is_simple() ? sb.append(STRS[_type]) : sb;} - - public Type meet(Type other) { return Type.BOTTOM; } - @Override public final String toString() { return print(new StringBuilder()).toString(); } + + public StringBuilder print(StringBuilder sb) {return is_simple() ? sb.append(STRS[_type]) : sb;} + + public Type meet(Type other) { return Type.BOTTOM; } + } diff --git a/chapter05/README.md b/chapter05/README.md index 2732066e..f7ff382c 100644 --- a/chapter05/README.md +++ b/chapter05/README.md @@ -1,11 +1,14 @@ # Chapter 5: If Statement, Phi, and Region +[Previous: Chapter 4](../chapter04/README.md) | +[Next: Chapter 6](../chapter06/README.md) + # Table of Contents 1. [Recap](#recap) 2. [New Nodes](#new-nodes) 3. [`IfNode`](#ifnode) -4. [`PhiNode` ](#phinode) +4. [`PhiNode`](#phinode) 5. [`RegionNode`](#regionnode) 6. [Pinned data nodes](#we-do-not-associate-a-control-edge-on-every-data-node-in-the-graph) 7. [`Stop` Nodes](#stop-nodes) @@ -19,9 +22,7 @@ 15. [Finally](#finally) 16. [Example 2](#example-2) 17. [Example 3](#example-3) -18. [Example 3](#example-3) -19. [More Examples](#more-examples) - +18. [More Examples](#more-examples) You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter05) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch and [compare](https://github.com/SeaOfNodes/Simple/compare/linear-chapter04...linear-chapter05) it to the previous chapter. @@ -50,7 +51,7 @@ Here is a recap of the nodes introduced in previous chapters: | Sub | Data | 2 | Subtract a value from another | Two data nodes, the first one is subtracted by the second one | Result of the subtraction | | Mul | Data | 2 | Multiply two values | Two data nodes without restrictions on the order | Result of the multiplication | | Div | Data | 2 | Divide a value by another | Two data nodes, the first one is divided by the second one | Result of the division | -| Minus | Data | 2 | Negate a value | One data node which value is negated | Result of the negation | +| Minus | Data | 2 | Negate a value | One data node that value is negated | Result of the negation | | Scope | Symbol Table | 3 | Represents scopes in the graph | Nodes that represent the current value of variables | None | > A `Proj` is a control node when it projects a control slot: `Proj#0` off `Start`, @@ -92,7 +93,7 @@ Integer arithmetic likewise retains an integer result type when it cannot fold. In this Sea of Nodes, there is an embedded Control Flow Graph - and like a normal CFG there are merge points where two basic blocks flow into one. The `Region` node takes control from each predecessor control (block) as input and -produces a merged control as an output.[^2] +produces a merged control as an output.[^2] Both `Return` and `If` take control in slot 0. `PhiNode`s need their corresponding `RegionNode` to know when to merge data values, so again slot 0 @@ -125,7 +126,7 @@ When we parse an `if` statement, the control flow splits at that point. We must track the names being updated in each part of the `if` statement, and then merge them at the end. The implementation follows the description in *Combining Analyses, Combining Optimizations*[^4]. -This involves following: +This involves the following: 1. We create an `IfNode` with the current control token, i.e. the node mapped to `$ctrl`, and the `if` predicate expression as inputs. @@ -154,7 +155,7 @@ Implementation is in [`parseIf` method in `Parser`](https://github.com/SeaOfNode ## Operations on ScopeNodes As explained above, we duplicate ScopeNodes and merge them at a later point. There are some -subtleties in how this is implemented that is worth going over. +subtleties in how this is implemented that are worth going over. ### Duplicating a ScopeNode @@ -175,7 +176,7 @@ At the merge point we merge two ScopeNodes. The goals are: 2) A new Region node is created representing the merged control flow. The phis have this region node as the first input. 3) After the merge is completed, the duplicate is discarded, and its use of each of the nodes is also deleted. -The merging logic takes advantage of that fact that the two ScopeNodes have the bound nodes in the same order in the list of inputs. This was ensured during duplicating the ScopeNode. +The merging logic takes advantage of the fact that the two ScopeNodes have the bound nodes in the same order in the list of inputs. This was ensured during duplicating the ScopeNode. Although only the innermost occurrence of a name can have its binding changed, we scan all the nodes in our input list, and simply ignore ones where the binding has not changed. For implementation [see `ScopeNode.mergeScopes()`](https://github.com/SeaOfNodes/Simple/blob/main/chapter05/src/main/java/com/seaofnodes/simple/node/ScopeNode.java#L164-L173) @@ -195,7 +196,7 @@ return a; ### Before Merging -Following shows the graph just before we merge the two branches of the `if` statement in a `Region` node. +The following shows the graph just before we merge the two branches of the `if` statement in a `Region` node. ![Graph1](./docs/05-graph1.svg) @@ -225,7 +226,7 @@ Here is the graph after the `return` statement was parsed and processed. ## Example #2 Consider the following code snippet: -```java +```java int b = 0; int c = 0; if (arg == 1) { @@ -241,16 +242,16 @@ return b; The value of `b` depends on which path the control flow took. To resolve this, a Φ (Phi) function is inserted. -``` +``` b = Phi(Region,2, 1); // values vary -c = Phi(Region,1, 0); // valuse vary, but dead +c = Phi(Region,1, 0); // values vary, but dead ``` The `Phi` for `c` will die when the scope where `c` is defined dies. This does not happen when merging but after the `return`. `return` is using `b` so `b` stays alive. -Before, we go ahead and parse down the if statement we duplicate the scope: +Before we go ahead and parse down the if statement we duplicate the scope: ```java ScopeNode fScope = _scope.dup(); /* Scope[$ctrl:$ctrl, arg:arg][b:0, c:0]*/ @@ -270,7 +271,7 @@ Notice, this branch modified and set a new value for both symbols currently exis Now, we set the scope back to where we started (without the modifications that `ifT` made) ```java -_scope = fScope; +_scope = fScope; ``` We then will proceed and parse down the second branch of the if statement: @@ -278,12 +279,12 @@ We then will proceed and parse down the second branch of the if statement: if (matchx("else")) { parseStatement(); fScope = _scope; - + /* Scope[$ctrl:False, arg:arg][b:1, c:0]*/ } ``` -This branch modified the values of `b` and `c`. Since the branch arms are also +The two branches modified `b`; only the true branch modified `c`. Since the branch arms are also lexical scopes, they cannot introduce new symbols in the current (outer) scope. This means that the order of the name bindings stayed the same. Excluding the first control node, we loop through and compare the nodes corresponding to the @@ -303,7 +304,7 @@ representing this conflict: ## Example #3 -Phi's implement a peephole illustrated in the example: +Phis implement a peephole illustrated in the example: ```java int a=arg==2; diff --git a/chapter05/docs/05-graph1.json b/chapter05/docs/05-graph1.json new file mode 100644 index 00000000..a2b4a7bd --- /dev/null +++ b/chapter05/docs/05-graph1.json @@ -0,0 +1,25 @@ +{ + "ver": 1, + "comp": "chapter05/docs/05-graph1.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 11, "role": "ASSOC", "label": "0: $ctrl"}, {"idx": 1, "def": 10, "role": "ASSOC", "label": "0: arg"}, {"idx": 2, "def": 14, "role": "ASSOC", "label": "1: a"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 4, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 12, "role": "ASSOC", "label": "0: $ctrl"}, {"idx": 1, "def": 10, "role": "ASSOC", "label": "0: arg"}, {"idx": 2, "def": 16, "role": "ASSOC", "label": "1: a"}], "proj": null}, + {"id": 6, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 7, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 6, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 11, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 9, "role": "CTRL", "label": null}], "proj": {"par": 9, "idx": 0}}, + {"id": 12, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 9, "role": "CTRL", "label": null}], "proj": {"par": 9, "idx": 1}}, + {"id": 13, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 14, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "-", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}, {"idx": 2, "def": 15, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter05/docs/05-graph1.svg b/chapter05/docs/05-graph1.svg index efe0a0e8..97813974 100644 --- a/chapter05/docs/05-graph1.svg +++ b/chapter05/docs/05-graph1.svg @@ -1,228 +1,120 @@ - - - - - - -chapter05 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - -cluster_Scope1_1 - - - -cluster_Scope12_0 - - - -cluster_Scope12_1 - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Con_7 - -#1 - - - -EQNode8 - -== - - - -EQNode8->Start2:p1 - - -1 - - - -EQNode8->Con_7 - - -2 - - - -If9 - - -If - - - -True - - -False - - - -If9->Start2:p0 - - -0 - - - -If9->EQNode8 - - -1 - - - -Con_13 - -#2 - - - -Add14 - -+ - - - -Add14->Start2:p1 - - -1 - - - -Add14->Con_13 - - -2 - - - -Con_15 - -#3 - - - -Sub16 - -- - - - -Sub16->Start2:p1 - - -1 - - - -Sub16->Con_15 - - -2 - - - -Scope1_0 - - -0 - -$ctrl - -arg - - - -Scope1_0:Scope1_0_arg->Start2:p1 - - - - - -Scope1_0:Scope1_0_$ctrl->If9:p0 - - - - - -Scope1_1 - - -1 - -a - - - -Scope1_1:Scope1_1_a->Add14 - - - - - -Scope12_0 - - -0 - -$ctrl - -arg - - - -Scope12_0:Scope12_0_arg->Start2:p1 - - - - - -Scope12_0:Scope12_0_$ctrl->If9:p1 - - - - - -Scope12_1 - - -1 - -a - - - -Scope12_1:Scope12_1_a->Sub16 - - - - - +#1[0] → #11 · ASSOC · 0: $ctrl#1[1] → #10 · ASSOC · 0: arg#1[2] → #14 · ASSOC · 1: a#4[0] → #12 · ASSOC · 0: $ctrl#4[1] → #10 · ASSOC · 0: arg#4[2] → #16 · ASSOC · 1: a#8[1] → #10 · DATA#8[2] → #7 · DATA#9[0] → #6 · CTRL#9[1] → #8 · DATA#14[1] → #10 · DATA#14[2] → #13 · DATA#16[1] → #10 · DATA#16[2] → #15 · DATAScope  #1#1 Scope +Type not computed + +[0] → #11 ASSOC 0: $ctrl +[1] → #10 ASSOC 0: arg +[2] → #14 ASSOC 1: a0: $ctrl0: arg1: a012Start  #2#2 Start +Type not computed + +Scope  #4#4 Scope +Type not computed + +[0] → #12 ASSOC 0: $ctrl +[1] → #10 ASSOC 0: arg +[2] → #16 ASSOC 1: a0: $ctrl0: arg1: a012$ctrl  #6/0#6 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRL#1  #7#7 #1 +Type not computed + +==  #8#8 == +Type not computed + +[0] → — DATA +[1] → #10 DATA +[2] → #7 DATA012If  #9#9 If +Type not computed + +[0] → #6 CTRL +[1] → #8 DATA01arg  #10/1#10 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #11/0#11 True +Projection 0 of #9 +Type not computed + +[0] → #9 CTRLFalse  #12/1#12 False +Projection 1 of #9 +Type not computed + +[0] → #9 CTRL#2  #13#13 #2 +Type not computed + ++  #14#14 + +Type not computed + +[0] → — DATA +[1] → #10 DATA +[2] → #13 DATA012#3  #15#15 #3 +Type not computed + +-  #16#16 - +Type not computed + +[0] → — DATA +[1] → #10 DATA +[2] → #15 DATA012 diff --git a/chapter05/docs/05-graph2.json b/chapter05/docs/05-graph2.json new file mode 100644 index 00000000..5980da2b --- /dev/null +++ b/chapter05/docs/05-graph2.json @@ -0,0 +1,27 @@ +{ + "ver": 1, + "comp": "chapter05/docs/05-graph2.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 17, "role": "ASSOC", "label": "0: $ctrl"}, {"idx": 1, "def": 5, "role": "ASSOC", "label": "0: arg"}, {"idx": 2, "def": 18, "role": "ASSOC", "label": "1: a"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 4, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 5, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 6, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 9, "role": "CTRL", "label": null}], "proj": {"par": 9, "idx": 0}}, + {"id": 7, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 4, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 9, "role": "CTRL", "label": null}], "proj": {"par": 9, "idx": 1}}, + {"id": 13, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 14, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "DATA", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "-", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "DATA", "label": null}, {"idx": 2, "def": 15, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "CTRL", "label": null}, {"idx": 2, "def": 10, "role": "CTRL", "label": null}], "proj": null}, + {"id": 18, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 17, "role": "ASSOC", "label": null}, {"idx": 1, "def": 14, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 9, "par": 0, "nodes": [6, 8, 9, 10, 14, 16, 17, 18]} + ] +} diff --git a/chapter05/docs/05-graph2.svg b/chapter05/docs/05-graph2.svg index d5e48a9e..bd06978a 100644 --- a/chapter05/docs/05-graph2.svg +++ b/chapter05/docs/05-graph2.svg @@ -1,229 +1,125 @@ - - - - - - -chapter05 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - -cluster_Scope1_1 - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Con_7 - -#1 - - - -EQNode8 - -== - - - -EQNode8->Start2:p1 - - -1 - - - -EQNode8->Con_7 - - -2 - - - -If9 - - -If - - - -True - - -False - - - -If9->Start2:p0 - - -0 - - - -If9->EQNode8 - - -1 - - - -Con_13 - -#2 - - - -Add14 - -+ - - - -Add14->Start2:p1 - - -1 - - - -Add14->Con_13 - - -2 - - - -Con_15 - -#3 - - - -Sub16 - -- - - - -Sub16->Start2:p1 - - -1 - - - -Sub16->Con_15 - - -2 - - - -Region17 - -Region - - - -Region17->If9:p0 - - -1 - - - -Region17->If9:p1 - - -2 - - - -Phi_a18 - -φ_a - - - -Phi_a18->Add14 - - -1 - - - -Phi_a18->Sub16 - - -2 - - - -Phi_a18->Region17 - - -0 - - - -Scope1_0 - - -0 - -$ctrl - -arg - - - -Scope1_0:Scope1_0_arg->Start2:p1 - - - - - -Scope1_0:Scope1_0_$ctrl->Region17 - - - - - -Scope1_1 - - -1 - -a - - - -Scope1_1:Scope1_1_a->Phi_a18 - - - - - +#1[0] → #17 · ASSOC · 0: $ctrl#1[1] → #5 · ASSOC · 0: arg#1[2] → #18 · ASSOC · 1: a#8[1] → #5 · DATA#8[2] → #7 · DATA#9[0] → #4 · CTRL#9[1] → #8 · DATA#14[1] → #5 · DATA#14[2] → #13 · DATA#16[1] → #5 · DATA#16[2] → #15 · DATA#17[1] → #6 · CTRL#17[2] → #10 · CTRL#18[1] → #14 · DATA#18[2] → #16 · DATAScope  #1#1 Scope +Type not computed + +[0] → #17 ASSOC 0: $ctrl +[1] → #5 ASSOC 0: arg +[2] → #18 ASSOC 1: a0: $ctrl0: arg1: a012Start  #2#2 Start +Type not computed + +$ctrl  #4/0#4 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLarg  #5/1#5 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #6/0#6 True +Projection 0 of #9 +Type not computed + +[0] → #9 CTRL#1  #7#7 #1 +Type not computed + +==  #8#8 == +Type not computed + +[0] → — DATA +[1] → #5 DATA +[2] → #7 DATA012If  #9#9 If +Type not computed + +[0] → #4 CTRL +[1] → #8 DATA01False  #10/1#10 False +Projection 1 of #9 +Type not computed + +[0] → #9 CTRL#2  #13#13 #2 +Type not computed + ++  #14#14 + +Type not computed + +[0] → — DATA +[1] → #5 DATA +[2] → #13 DATA012#3  #15#15 #3 +Type not computed + +-  #16#16 - +Type not computed + +[0] → — DATA +[1] → #5 DATA +[2] → #15 DATA012Region  #17#17 Region +Type not computed + +[0] → — DATA +[1] → #6 CTRL +[2] → #10 CTRL012φ_a  #18#18 φ_a +Type not computed + +[0] → #17 ASSOC +[1] → #14 DATA +[2] → #16 DATA[0] → #17012If  #9If · 8 nodes−Fold region diff --git a/chapter05/docs/05-graph3.json b/chapter05/docs/05-graph3.json new file mode 100644 index 00000000..16d74821 --- /dev/null +++ b/chapter05/docs/05-graph3.json @@ -0,0 +1,28 @@ +{ + "ver": 1, + "comp": "chapter05/docs/05-graph3.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 19, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 9, "role": "CTRL", "label": null}], "proj": {"par": 9, "idx": 0}}, + {"id": 6, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 9, "role": "CTRL", "label": null}], "proj": {"par": 9, "idx": 1}}, + {"id": 7, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 13, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 14, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "-", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 15, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 6, "role": "CTRL", "label": null}], "proj": null}, + {"id": 18, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 17, "role": "ASSOC", "label": null}, {"idx": 1, "def": 14, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 19, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}, {"idx": 1, "def": 18, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 9, "par": 0, "nodes": [5, 6, 8, 9, 14, 16, 17, 18]} + ] +} diff --git a/chapter05/docs/05-graph3.svg b/chapter05/docs/05-graph3.svg index 855fdc2c..50255072 100644 --- a/chapter05/docs/05-graph3.svg +++ b/chapter05/docs/05-graph3.svg @@ -1,216 +1,127 @@ - - - - - - -chapter05 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return19 - -Return - - - -Stop3->Return19 - - -0 - - - -Con_7 - -#1 - - - -EQNode8 - -== - - - -EQNode8->Start2:p1 - - -1 - - - -EQNode8->Con_7 - - -2 - - - -If9 - - -If - - - -True - - -False - - - -If9->Start2:p0 - - -0 - - - -If9->EQNode8 - - -1 - - - -Con_13 - -#2 - - - -Add14 - -+ - - - -Add14->Start2:p1 - - -1 - - - -Add14->Con_13 - - -2 - - - -Con_15 - -#3 - - - -Sub16 - -- - - - -Sub16->Start2:p1 - - -1 - - - -Sub16->Con_15 - - -2 - - - -Region17 - -Region - - - -Region17->If9:p0 - - -1 - - - -Region17->If9:p1 - - -2 - - - -Phi_a18 - -φ_a - - - -Phi_a18->Add14 - - -1 - - - -Phi_a18->Sub16 - - -2 - - - -Phi_a18->Region17 - - -0 - - - -Return19->Region17 - - -0 - - - -Return19->Phi_a18 - - -1 - - - +#3[0] → #19 · CTRL#8[1] → #4 · DATA#8[2] → #7 · DATA#9[0] → #1 · CTRL#9[1] → #8 · DATA#14[1] → #4 · DATA#14[2] → #13 · DATA#16[1] → #4 · DATA#16[2] → #15 · DATA#17[1] → #5 · CTRL#17[2] → #6 · CTRL#18[1] → #14 · DATA#18[2] → #16 · DATA#19[0] → #17 · CTRL#19[1] → #18 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #19 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #9 +Type not computed + +[0] → #9 CTRLFalse  #6/1#6 False +Projection 1 of #9 +Type not computed + +[0] → #9 CTRL#1  #7#7 #1 +Type not computed + +==  #8#8 == +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #7 DATA012If  #9#9 If +Type not computed + +[0] → #1 CTRL +[1] → #8 DATA01#2  #13#13 #2 +Type not computed + ++  #14#14 + +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #13 DATA012#3  #15#15 #3 +Type not computed + +-  #16#16 - +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #15 DATA012Region  #17#17 Region +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #6 CTRL012φ_a  #18#18 φ_a +Type not computed + +[0] → #17 ASSOC +[1] → #14 DATA +[2] → #16 DATA[0] → #17012Return  #19#19 Return +Type not computed + +[0] → #17 CTRL +[1] → #18 DATA01If  #9If · 8 nodes−Fold region diff --git a/chapter05/docs/05-graph4.json b/chapter05/docs/05-graph4.json new file mode 100644 index 00000000..36527f8d --- /dev/null +++ b/chapter05/docs/05-graph4.json @@ -0,0 +1,28 @@ +{ + "ver": 1, + "comp": "chapter05/docs/05-graph4.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 18, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 10, "role": "CTRL", "label": null}], "proj": {"par": 10, "idx": 0}}, + {"id": 6, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 7, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 8, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 9, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 10, "role": "CTRL", "label": null}], "proj": {"par": 10, "idx": 1}}, + {"id": 14, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 15, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 14, "role": "DATA", "label": null}], "proj": null}, + {"id": 16, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 11, "role": "CTRL", "label": null}], "proj": null}, + {"id": 17, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 16, "role": "ASSOC", "label": null}, {"idx": 1, "def": 15, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 18, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}, {"idx": 1, "def": 17, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 10, "par": 0, "nodes": [5, 7, 9, 10, 11, 15, 16, 17]} + ] +} diff --git a/chapter05/docs/05-graph4.svg b/chapter05/docs/05-graph4.svg index 3fcee500..58f0cb18 100644 --- a/chapter05/docs/05-graph4.svg +++ b/chapter05/docs/05-graph4.svg @@ -1,216 +1,127 @@ - - - - - - -chapter05 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return18 - -Return - - - -Stop3->Return18 - - -0 - - - -Con_6 - -#2 - - - -EQNode7 - -== - - - -EQNode7->Start2:p1 - - -1 - - - -EQNode7->Con_6 - - -2 - - - -Con_8 - -#1 - - - -EQNode9 - -== - - - -EQNode9->Start2:p1 - - -1 - - - -EQNode9->Con_8 - - -2 - - - -If10 - - -If - - - -True - - -False - - - -If10->Start2:p0 - - -0 - - - -If10->EQNode9 - - -1 - - - -Con_14 - -#3 - - - -EQNode15 - -== - - - -EQNode15->Start2:p1 - - -1 - - - -EQNode15->Con_14 - - -2 - - - -Region16 - -Region - - - -Region16->If10:p0 - - -1 - - - -Region16->If10:p1 - - -2 - - - -Phi_a17 - -φ_a - - - -Phi_a17->EQNode7 - - -2 - - - -Phi_a17->EQNode15 - - -1 - - - -Phi_a17->Region16 - - -0 - - - -Return18->Region16 - - -0 - - - -Return18->Phi_a17 - - -1 - - - +#3[0] → #18 · CTRL#7[1] → #4 · DATA#7[2] → #6 · DATA#9[1] → #4 · DATA#9[2] → #8 · DATA#10[0] → #1 · CTRL#10[1] → #9 · DATA#15[1] → #4 · DATA#15[2] → #14 · DATA#16[1] → #5 · CTRL#16[2] → #11 · CTRL#17[1] → #15 · DATA#17[2] → #7 · DATA#18[0] → #16 · CTRL#18[1] → #17 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #18 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #10 +Type not computed + +[0] → #10 CTRL#2  #6#6 #2 +Type not computed + +==  #7#7 == +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #6 DATA012#1  #8#8 #1 +Type not computed + +==  #9#9 == +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #8 DATA012If  #10#10 If +Type not computed + +[0] → #1 CTRL +[1] → #9 DATA01False  #11/1#11 False +Projection 1 of #10 +Type not computed + +[0] → #10 CTRL#3  #14#14 #3 +Type not computed + +==  #15#15 == +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #14 DATA012Region  #16#16 Region +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #11 CTRL012φ_a  #17#17 φ_a +Type not computed + +[0] → #16 ASSOC +[1] → #15 DATA +[2] → #7 DATA[0] → #16012Return  #18#18 Return +Type not computed + +[0] → #16 CTRL +[1] → #17 DATA01If  #10If · 8 nodes−Fold region diff --git a/chapter05/docs/05-graph5.json b/chapter05/docs/05-graph5.json new file mode 100644 index 00000000..b9dc070b --- /dev/null +++ b/chapter05/docs/05-graph5.json @@ -0,0 +1,27 @@ +{ + "ver": 1, + "comp": "chapter05/docs/05-graph5.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 21, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 10, "role": "CTRL", "label": null}], "proj": {"par": 10, "idx": 0}}, + {"id": 6, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 7, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 10, "role": "CTRL", "label": null}], "proj": {"par": 10, "idx": 1}}, + {"id": 8, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 9, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 14, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 7, "role": "CTRL", "label": null}], "proj": null}, + {"id": 19, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 16, "role": "ASSOC", "label": null}, {"idx": 1, "def": 14, "role": "DATA", "label": null}, {"idx": 2, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 20, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 19, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}, {"idx": 1, "def": 20, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 10, "par": 0, "nodes": [5, 7, 9, 10, 16, 19]} + ] +} diff --git a/chapter05/docs/05-graph5.svg b/chapter05/docs/05-graph5.svg index 4f6fa4bd..4d137bda 100644 --- a/chapter05/docs/05-graph5.svg +++ b/chapter05/docs/05-graph5.svg @@ -1,196 +1,122 @@ - - - - - - -chapter05 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return21 - -Return - - - -Stop3->Return21 - - -0 - - - -Con_6 - -#2 - - - -Con_8 - -#1 - - - -EQNode9 - -== - - - -EQNode9->Start2:p1 - - -1 - - - -EQNode9->Con_8 - - -2 - - - -If10 - - -If - - - -True - - -False - - - -If10->Start2:p0 - - -0 - - - -If10->EQNode9 - - -1 - - - -Con_14 - -#3 - - - -Region16 - -Region - - - -Region16->If10:p0 - - -1 - - - -Region16->If10:p1 - - -2 - - - -Phi_a19 - -φ_a - - - -Phi_a19->Con_6 - - -2 - - - -Phi_a19->Con_14 - - -1 - - - -Phi_a19->Region16 - - -0 - - - -EQNode20 - -== - - - -EQNode20->Start2:p1 - - -1 - - - -EQNode20->Phi_a19 - - -2 - - - -Return21->Region16 - - -0 - - - -Return21->EQNode20 - - -1 - - - +#3[0] → #21 · CTRL#9[1] → #4 · DATA#9[2] → #8 · DATA#10[0] → #1 · CTRL#10[1] → #9 · DATA#16[1] → #5 · CTRL#16[2] → #7 · CTRL#19[1] → #14 · DATA#19[2] → #6 · DATA#20[1] → #4 · DATA#20[2] → #19 · DATA#21[0] → #16 · CTRL#21[1] → #20 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #21 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #10 +Type not computed + +[0] → #10 CTRL#2  #6#6 #2 +Type not computed + +False  #7/1#7 False +Projection 1 of #10 +Type not computed + +[0] → #10 CTRL#1  #8#8 #1 +Type not computed + +==  #9#9 == +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #8 DATA012If  #10#10 If +Type not computed + +[0] → #1 CTRL +[1] → #9 DATA01#3  #14#14 #3 +Type not computed + +Region  #16#16 Region +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #7 CTRL012φ_a  #19#19 φ_a +Type not computed + +[0] → #16 ASSOC +[1] → #14 DATA +[2] → #6 DATA[0] → #16012==  #20#20 == +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #19 DATA012Return  #21#21 Return +Type not computed + +[0] → #16 CTRL +[1] → #20 DATA01If  #10If · 6 nodes−Fold region diff --git a/chapter05/docs/05-graph6.json b/chapter05/docs/05-graph6.json new file mode 100644 index 00000000..1039bb08 --- /dev/null +++ b/chapter05/docs/05-graph6.json @@ -0,0 +1,26 @@ +{ + "ver": 1, + "comp": "chapter05/docs/05-graph6.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 19, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 10, "role": "CTRL", "label": null}], "proj": {"par": 10, "idx": 0}}, + {"id": 6, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 7, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 10, "role": "CTRL", "label": null}], "proj": {"par": 10, "idx": 1}}, + {"id": 8, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 9, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "#4", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 7, "role": "CTRL", "label": null}], "proj": null}, + {"id": 17, "label": "φ_c", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 16, "role": "ASSOC", "label": null}, {"idx": 1, "def": 15, "role": "DATA", "label": null}, {"idx": 2, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 19, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}, {"idx": 1, "def": 17, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 10, "par": 0, "nodes": [5, 7, 9, 10, 16, 17]} + ] +} diff --git a/chapter05/docs/05-graph6.svg b/chapter05/docs/05-graph6.svg index 71527d7f..831a6a07 100644 --- a/chapter05/docs/05-graph6.svg +++ b/chapter05/docs/05-graph6.svg @@ -1,176 +1,117 @@ - - - - - - -chapter05 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return19 - -Return - - - -Stop3->Return19 - - -0 - - - -Con_6 - -#3 - - - -Con_8 - -#1 - - - -EQNode9 - -== - - - -EQNode9->Start2:p1 - - -1 - - - -EQNode9->Con_8 - - -2 - - - -If10 - - -If - - - -True - - -False - - - -If10->Start2:p0 - - -0 - - - -If10->EQNode9 - - -1 - - - -Con_15 - -#4 - - - -Region16 - -Region - - - -Region16->If10:p0 - - -1 - - - -Region16->If10:p1 - - -2 - - - -Phi_c17 - -φ_c - - - -Phi_c17->Con_6 - - -2 - - - -Phi_c17->Con_15 - - -1 - - - -Phi_c17->Region16 - - -0 - - - -Return19->Region16 - - -0 - - - -Return19->Phi_c17 - - -1 - - - +#3[0] → #19 · CTRL#9[1] → #4 · DATA#9[2] → #8 · DATA#10[0] → #1 · CTRL#10[1] → #9 · DATA#16[1] → #5 · CTRL#16[2] → #7 · CTRL#17[1] → #15 · DATA#17[2] → #6 · DATA#19[0] → #16 · CTRL#19[1] → #17 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #19 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #10 +Type not computed + +[0] → #10 CTRL#3  #6#6 #3 +Type not computed + +False  #7/1#7 False +Projection 1 of #10 +Type not computed + +[0] → #10 CTRL#1  #8#8 #1 +Type not computed + +==  #9#9 == +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #8 DATA012If  #10#10 If +Type not computed + +[0] → #1 CTRL +[1] → #9 DATA01#4  #15#15 #4 +Type not computed + +Region  #16#16 Region +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #7 CTRL012φ_c  #17#17 φ_c +Type not computed + +[0] → #16 ASSOC +[1] → #15 DATA +[2] → #6 DATA[0] → #16012Return  #19#19 Return +Type not computed + +[0] → #16 CTRL +[1] → #17 DATA01If  #10If · 6 nodes−Fold region diff --git a/chapter05/docs/05-graph7.json b/chapter05/docs/05-graph7.json new file mode 100644 index 00000000..df6cf547 --- /dev/null +++ b/chapter05/docs/05-graph7.json @@ -0,0 +1,31 @@ +{ + "ver": 1, + "comp": "chapter05/docs/05-graph7.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 51, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}], "proj": {"par": 12, "idx": 0}}, + {"id": 6, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}], "proj": {"par": 12, "idx": 1}}, + {"id": 10, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 11, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 12, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 11, "role": "DATA", "label": null}], "proj": null}, + {"id": 19, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 20, "label": "*", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 19, "role": "DATA", "label": null}], "proj": null}, + {"id": 31, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 6, "role": "CTRL", "label": null}], "proj": null}, + {"id": 37, "label": "φ_b", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 31, "role": "ASSOC", "label": null}, {"idx": 1, "def": 20, "role": "DATA", "label": null}, {"idx": 2, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 42, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 37, "role": "DATA", "label": null}, {"idx": 2, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 46, "label": "#4", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 48, "label": "#5", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 49, "label": "φ_ab", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 31, "role": "ASSOC", "label": null}, {"idx": 1, "def": 46, "role": "DATA", "label": null}, {"idx": 2, "def": 48, "role": "DATA", "label": null}], "proj": null}, + {"id": 50, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 42, "role": "DATA", "label": null}, {"idx": 2, "def": 49, "role": "DATA", "label": null}], "proj": null}, + {"id": 51, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 31, "role": "CTRL", "label": null}, {"idx": 1, "def": 50, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 12, "par": 0, "nodes": [5, 6, 11, 12, 20, 31, 37, 49]} + ] +} diff --git a/chapter05/docs/05-graph7.svg b/chapter05/docs/05-graph7.svg index 8ba5ebd6..4ef44b41 100644 --- a/chapter05/docs/05-graph7.svg +++ b/chapter05/docs/05-graph7.svg @@ -1,269 +1,140 @@ - - - - - - -chapter05 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return51 - -Return - - - -Stop3->Return51 - - -0 - - - -Phi_b37 - -φ_b - - - -Phi_b37->Start2:p1 - -2 - - - -Mul20 - -* - - - -Phi_b37->Mul20 - - -1 - - - -Region31 - -Region - - - -Phi_b37->Region31 - - -0 - - - -Con_10 - -#1 - - - -Add42 - -+ - - - -Add42->Start2:p1 - - - - -2 - - - -Add42->Phi_b37 - - -1 - - - -EQNode11 - -== - - - -EQNode11->Start2:p1 - - -1 - - - -EQNode11->Con_10 - - -2 - - - -If12 - - -If - - - -True - - -False - - - -If12->Start2:p0 - - -0 - - - -If12->EQNode11 - - -1 - - - -Con_46 - -#4 - - - -Con_48 - -#5 - - - -Phi_ab49 - -φ_ab - - - -Phi_ab49->Con_46 - - -1 - - - -Phi_ab49->Con_48 - - -2 - - - -Phi_ab49->Region31 - - -0 - - - -Add50 - -+ - - - -Add50->Add42 - - -1 - - - -Add50->Phi_ab49 - - -2 - - - -Con_19 - -#2 - - - -Return51->Add50 - - -1 - - - -Return51->Region31 - - -0 - - - -Mul20->Start2:p1 - -1 - - - -Mul20->Con_19 - - -2 - - - -Region31->If12:p0 - - -1 - - - -Region31->If12:p1 - - -2 - - - +#3[0] → #51 · CTRL#11[1] → #4 · DATA#11[2] → #10 · DATA#12[0] → #1 · CTRL#12[1] → #11 · DATA#20[1] → #4 · DATA#20[2] → #19 · DATA#31[1] → #5 · CTRL#31[2] → #6 · CTRL#37[1] → #20 · DATA#37[2] → #4 · DATA#42[1] → #37 · DATA#42[2] → #4 · DATA#49[1] → #46 · DATA#49[2] → #48 · DATA#50[1] → #42 · DATA#50[2] → #49 · DATA#51[0] → #31 · CTRL#51[1] → #50 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #51 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #12 +Type not computed + +[0] → #12 CTRLFalse  #6/1#6 False +Projection 1 of #12 +Type not computed + +[0] → #12 CTRL#1  #10#10 #1 +Type not computed + +==  #11#11 == +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #10 DATA012If  #12#12 If +Type not computed + +[0] → #1 CTRL +[1] → #11 DATA01#2  #19#19 #2 +Type not computed + +*  #20#20 * +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #19 DATA012Region  #31#31 Region +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #6 CTRL012φ_b  #37#37 φ_b +Type not computed + +[0] → #31 ASSOC +[1] → #20 DATA +[2] → #4 DATA[0] → #31012+  #42#42 + +Type not computed + +[0] → — DATA +[1] → #37 DATA +[2] → #4 DATA012#4  #46#46 #4 +Type not computed + +#5  #48#48 #5 +Type not computed + +φ_ab  #49#49 φ_ab +Type not computed + +[0] → #31 ASSOC +[1] → #46 DATA +[2] → #48 DATA[0] → #31012+  #50#50 + +Type not computed + +[0] → — DATA +[1] → #42 DATA +[2] → #49 DATA012Return  #51#51 Return +Type not computed + +[0] → #31 CTRL +[1] → #50 DATA01If  #12If · 8 nodes−Fold region diff --git a/chapter05/docs/05-graph8.json b/chapter05/docs/05-graph8.json new file mode 100644 index 00000000..887d1e8a --- /dev/null +++ b/chapter05/docs/05-graph8.json @@ -0,0 +1,45 @@ +{ + "ver": 1, + "comp": "chapter05/docs/05-graph8.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 0, "role": "ASSOC", "label": "0: $ctrl"}, {"idx": 1, "def": 6, "role": "ASSOC", "label": "0: arg"}, {"idx": 2, "def": 34, "role": "ASSOC", "label": "1: a"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 35, "role": "CTRL", "label": null}], "proj": null}, + {"id": 5, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 6, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 7, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 9, "role": "CTRL", "label": null}], "proj": {"par": 9, "idx": 0}}, + {"id": 11, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 9, "role": "CTRL", "label": null}], "proj": {"par": 9, "idx": 1}}, + {"id": 12, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 15, "role": "CTRL", "label": null}], "proj": {"par": 15, "idx": 0}}, + {"id": 13, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 14, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "DATA", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 10, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "DATA", "label": null}], "proj": null}, + {"id": 16, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 15, "role": "CTRL", "label": null}], "proj": {"par": 15, "idx": 1}}, + {"id": 17, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": {"par": 25, "idx": 0}}, + {"id": 18, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": {"par": 25, "idx": 1}}, + {"id": 19, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 20, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 21, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 12, "role": "CTRL", "label": null}, {"idx": 2, "def": 16, "role": "CTRL", "label": null}], "proj": null}, + {"id": 22, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 21, "role": "ASSOC", "label": null}, {"idx": 1, "def": 19, "role": "DATA", "label": null}, {"idx": 2, "def": 20, "role": "DATA", "label": null}], "proj": null}, + {"id": 23, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 24, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "DATA", "label": null}, {"idx": 2, "def": 23, "role": "DATA", "label": null}], "proj": null}, + {"id": 25, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 24, "role": "DATA", "label": null}], "proj": null}, + {"id": 29, "label": "#4", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 30, "label": "#5", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 31, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 17, "role": "CTRL", "label": null}, {"idx": 2, "def": 18, "role": "CTRL", "label": null}], "proj": null}, + {"id": 32, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 31, "role": "ASSOC", "label": null}, {"idx": 1, "def": 29, "role": "DATA", "label": null}, {"idx": 2, "def": 30, "role": "DATA", "label": null}], "proj": null}, + {"id": 33, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 21, "role": "CTRL", "label": null}, {"idx": 2, "def": 31, "role": "CTRL", "label": null}], "proj": null}, + {"id": 34, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 33, "role": "ASSOC", "label": null}, {"idx": 1, "def": 22, "role": "DATA", "label": null}, {"idx": 2, "def": 32, "role": "DATA", "label": null}], "proj": null}, + {"id": 35, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 33, "role": "CTRL", "label": null}, {"idx": 1, "def": 34, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 9, "par": 0, "nodes": [8, 9, 10, 11, 33, 34]}, + {"id": 15, "par": 9, "nodes": [12, 14, 15, 16, 21, 22]}, + {"id": 25, "par": 9, "nodes": [17, 18, 24, 25, 31, 32]} + ] +} diff --git a/chapter05/docs/05-graph8.svg b/chapter05/docs/05-graph8.svg index e5310db4..bf0f8aa0 100644 --- a/chapter05/docs/05-graph8.svg +++ b/chapter05/docs/05-graph8.svg @@ -1,430 +1,188 @@ - - - - - - -chapter05 - - -cluster_Nodes - - - -cluster_Scope1_0 - - - -cluster_Scope1_1 - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return35 - -Return - - - -Stop3->Return35 - - -0 - - - -Con_7 - -#1 - - - -EQNode8 - -== - - - -EQNode8->Start2:p1 - - -1 - - - -EQNode8->Con_7 - - -2 - - - -If9 - - -If - - - -True - - -False - - - -If9->Start2:p0 - - -0 - - - -If9->EQNode8 - - -1 - - - -Con_13 - -#2 - - - -EQNode14 - -== - - - -EQNode14->Start2:p1 - - -1 - - - -EQNode14->Con_13 - - -2 - - - -If15 - - -If - - - -True - - -False - - - -If15->If9:p0 - - -0 - - - -If15->EQNode14 - - -1 - - - -Con_19 - -#2 - - - -Con_20 - -#3 - - - -Region21 - -Region - - - -Region21->If15:p0 - - -1 - - - -Region21->If15:p1 - - -2 - - - -Phi_a22 - -φ_a - - - -Phi_a22->Con_19 - - -1 - - - -Phi_a22->Con_20 - - -2 - - - -Phi_a22->Region21 - - -0 - - - -Con_23 - -#3 - - - -EQNode24 - -== - - - -EQNode24->Start2:p1 - - -1 - - - -EQNode24->Con_23 - - -2 - - - -If25 - - -If - - - -True - - -False - - - -If25->If9:p1 - - -0 - - - -If25->EQNode24 - - -1 - - - -Con_29 - -#4 - - - -Con_30 - -#5 - - - -Region31 - -Region - - - -Region31->If25:p0 - - -1 - - - -Region31->If25:p1 - - -2 - - - -Phi_a32 - -φ_a - - - -Phi_a32->Con_29 - - -1 - - - -Phi_a32->Con_30 - - -2 - - - -Phi_a32->Region31 - - -0 - - - -Region33 - -Region - - - -Region33->Region21 - - -1 - - - -Region33->Region31 - - -2 - - - -Phi_a34 - -φ_a - - - -Phi_a34->Phi_a22 - - -1 - - - -Phi_a34->Phi_a32 - - -2 - - - -Phi_a34->Region33 - - -0 - - - -Return35->Region33 - - -0 - - - -Return35->Phi_a34 - - -1 - - - -Scope1_0 - - -0 - -$ctrl - -arg - - - -Scope1_0:Scope1_0_arg->Start2:p1 - - - - - -Scope1_1 - - -1 - -a - - - -Scope1_1:Scope1_1_a->Phi_a34 - - - - - +#1[1] → #6 · ASSOC · 0: arg#1[2] → #34 · ASSOC · 1: a#3[0] → #35 · CTRL#8[1] → #6 · DATA#8[2] → #7 · DATA#9[0] → #5 · CTRL#9[1] → #8 · DATA#14[1] → #6 · DATA#14[2] → #13 · DATA#15[0] → #10 · CTRL#15[1] → #14 · DATA#21[1] → #12 · CTRL#21[2] → #16 · CTRL#22[1] → #19 · DATA#22[2] → #20 · DATA#24[1] → #6 · DATA#24[2] → #23 · DATA#25[0] → #11 · CTRL#25[1] → #24 · DATA#31[1] → #17 · CTRL#31[2] → #18 · CTRL#32[1] → #29 · DATA#32[2] → #30 · DATA#33[1] → #21 · CTRL#33[2] → #31 · CTRL#34[1] → #22 · DATA#34[2] → #32 · DATA#35[0] → #33 · CTRL#35[1] → #34 · DATAScope  #1#1 Scope +Type not computed + +[0] → — ASSOC 0: $ctrl +[1] → #6 ASSOC 0: arg +[2] → #34 ASSOC 1: a0: $ctrl0: arg1: a012Start  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #35 CTRL0$ctrl  #5/0#5 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLarg  #6/1#6 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATA#1  #7#7 #1 +Type not computed + +==  #8#8 == +Type not computed + +[0] → — DATA +[1] → #6 DATA +[2] → #7 DATA012If  #9#9 If +Type not computed + +[0] → #5 CTRL +[1] → #8 DATA01True  #10/0#10 True +Projection 0 of #9 +Type not computed + +[0] → #9 CTRLFalse  #11/1#11 False +Projection 1 of #9 +Type not computed + +[0] → #9 CTRLTrue  #12/0#12 True +Projection 0 of #15 +Type not computed + +[0] → #15 CTRL#2  #13#13 #2 +Type not computed + +==  #14#14 == +Type not computed + +[0] → — DATA +[1] → #6 DATA +[2] → #13 DATA012If  #15#15 If +Type not computed + +[0] → #10 CTRL +[1] → #14 DATA01False  #16/1#16 False +Projection 1 of #15 +Type not computed + +[0] → #15 CTRLTrue  #17/0#17 True +Projection 0 of #25 +Type not computed + +[0] → #25 CTRLFalse  #18/1#18 False +Projection 1 of #25 +Type not computed + +[0] → #25 CTRL#2  #19#19 #2 +Type not computed + +#3  #20#20 #3 +Type not computed + +Region  #21#21 Region +Type not computed + +[0] → — DATA +[1] → #12 CTRL +[2] → #16 CTRL012φ_a  #22#22 φ_a +Type not computed + +[0] → #21 ASSOC +[1] → #19 DATA +[2] → #20 DATA[0] → #21012#3  #23#23 #3 +Type not computed + +==  #24#24 == +Type not computed + +[0] → — DATA +[1] → #6 DATA +[2] → #23 DATA012If  #25#25 If +Type not computed + +[0] → #11 CTRL +[1] → #24 DATA01#4  #29#29 #4 +Type not computed + +#5  #30#30 #5 +Type not computed + +Region  #31#31 Region +Type not computed + +[0] → — DATA +[1] → #17 CTRL +[2] → #18 CTRL012φ_a  #32#32 φ_a +Type not computed + +[0] → #31 ASSOC +[1] → #29 DATA +[2] → #30 DATA[0] → #31012Region  #33#33 Region +Type not computed + +[0] → — DATA +[1] → #21 CTRL +[2] → #31 CTRL012φ_a  #34#34 φ_a +Type not computed + +[0] → #33 ASSOC +[1] → #22 DATA +[2] → #32 DATA[0] → #33012Return  #35#35 Return +Type not computed + +[0] → #33 CTRL +[1] → #34 DATA01If  #9If · 18 nodes−Fold regionIf  #15If · 6 nodes−Fold regionIf  #25If · 6 nodes−Fold region diff --git a/chapter05/docs/05-graph9.json b/chapter05/docs/05-graph9.json new file mode 100644 index 00000000..deb1b540 --- /dev/null +++ b/chapter05/docs/05-graph9.json @@ -0,0 +1,26 @@ +{ + "ver": 1, + "comp": "chapter05/docs/05-graph9.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 20, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 10, "role": "CTRL", "label": null}], "proj": {"par": 10, "idx": 0}}, + {"id": 6, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 10, "role": "CTRL", "label": null}], "proj": {"par": 10, "idx": 1}}, + {"id": 8, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 9, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 14, "label": "2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 17, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 6, "role": "CTRL", "label": null}], "proj": null}, + {"id": 18, "label": "φ_b", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 17, "role": "ASSOC", "label": null}, {"idx": 1, "def": 14, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 20, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}, {"idx": 1, "def": 18, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 10, "par": 0, "nodes": [5, 6, 9, 10, 17, 18]} + ] +} diff --git a/chapter05/docs/05-graph9.svg b/chapter05/docs/05-graph9.svg index dff4d63f..cc52c5bd 100644 --- a/chapter05/docs/05-graph9.svg +++ b/chapter05/docs/05-graph9.svg @@ -1,174 +1,117 @@ - - - - - - -chapter05 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return20 - -Return - - - -Stop3->Return20 - - -0 - - - -Con_8 - -1 - - - -EQ9 - -== - - - -EQ9->Start2:p1 - - -1 - - - -EQ9->Con_8 - - -2 - - - -If10 - - -If - - - -True - - -False - - - -If10->Start2:p0 - - -0 - - - -If10->EQ9 - - -1 - - - -Con_14 - -2 - - - -Con_16 - -1 - - - -Region17 - -Region - - - -Region17->If10:p0 - - -1 - - - -Region17->If10:p1 - - -2 - - - -Phi_b18 - -φ_b - - - -Phi_b18->Con_14 - - -1 - - - -Phi_b18->Con_16 - - -2 - - - -Phi_b18->Region17 - - -0 - - - -Return20->Region17 - - -0 - - - -Return20->Phi_b18 - - -1 - - - \ No newline at end of file +#3[0] → #20 · CTRL#9[1] → #4 · DATA#9[2] → #8 · DATA#10[0] → #1 · CTRL#10[1] → #9 · DATA#17[1] → #5 · CTRL#17[2] → #6 · CTRL#18[1] → #14 · DATA#18[2] → #16 · DATA#20[0] → #17 · CTRL#20[1] → #18 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #20 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #10 +Type not computed + +[0] → #10 CTRLFalse  #6/1#6 False +Projection 1 of #10 +Type not computed + +[0] → #10 CTRL1  #8#8 1 +Type not computed + +==  #9#9 == +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #8 DATA012If  #10#10 If +Type not computed + +[0] → #1 CTRL +[1] → #9 DATA012  #14#14 2 +Type not computed + +1  #16#16 1 +Type not computed + +Region  #17#17 Region +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #6 CTRL012φ_b  #18#18 φ_b +Type not computed + +[0] → #17 ASSOC +[1] → #14 DATA +[2] → #16 DATA[0] → #17012Return  #20#20 Return +Type not computed + +[0] → #17 CTRL +[1] → #18 DATA01If  #10If · 6 nodes−Fold region diff --git a/chapter05/docs/Makefile b/chapter05/docs/Makefile index 12659b8f..6fa0f057 100644 --- a/chapter05/docs/Makefile +++ b/chapter05/docs/Makefile @@ -1,12 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter06/README.md b/chapter06/README.md index 3442b1cc..14e21bbc 100644 --- a/chapter06/README.md +++ b/chapter06/README.md @@ -1,10 +1,13 @@ # Chapter 6: Peepholes for If +[Previous: Chapter 5](../chapter05/README.md) | +[Next: Chapter 7](../chapter07/README.md) + # Table of Contents 1. [Type System Revision](#type-system-revision) 2. [Peephole of `if`](#peephole-of-if) -3. [`Region` and `Phi`](#Region-and-Phi) +3. [`Region` and `Phi`](#region-and-phi) 4. [Discussion](#discussion) 5. [Expanding Peephole Beyond Constant Expressions](#expanding-peephole-beyond-constant-expressions) 6. [Dominators](#dominators) @@ -48,7 +51,7 @@ The entire revised Lattice is shown below: parsing, the normal graph building machinery takes care of cleaning up dead nodes. * When we peephole an `If` node we test if the predicate is a constant. If so, - then one branch or the other dead, depending on if the constant is `0` or not. + then one branch or the other is dead, depending on if the constant is `0` or not. * When we add the `Proj` nodes, in this scenario, we already know one of the projections is dead. The peephole of the relevant `Proj` node replaces the `Proj` with a `Constant` of type "~Ctrl" indicating dead control. * At this point our dead code elimination would kill the `If` node since it has no uses @@ -62,7 +65,7 @@ The entire revised Lattice is shown below: * The parsing then continues as normal. * The other changes are when we reach the merge point with a dead control. * Again keeping with our strategy we merge as normal, including creating `Phi` nodes. -* The `Region` may have have one of its inputs as "~Ctrl". This will be seen +* The `Region` may have one of its inputs as "~Ctrl". This will be seen by the `Phi` which then optimizes itself. If the `Phi` has just one live input, the `Phi` peephole replaces itself with the remaining input. * Finally, at the end, when the `Region` node is peepholed, we see that it has only one live input and no Phi uses @@ -70,7 +73,7 @@ The entire revised Lattice is shown below: ## `Region` and `Phi` -One of the invariants we maintain is that the for each control input to a +One of the invariants we maintain is that for each control input to a `Region` every `Phi` has a 1-to-1 relationship with a data input. Thus, if a `Region` loses a control input, every `Phi`'s corresponding data input must be deleted. Conversely, we cannot collapse a Region until it has no dependent @@ -122,7 +125,7 @@ After peephole: ## Expanding Peephole Beyond Constant Expressions While our peephole of the `CFG` collapses dead code when the expression is -a compile time constant. it does not do as well as it could with following example: +a compile-time constant, it does not do as well as it could with the following example: ```java int a = 0; @@ -188,7 +191,7 @@ the outcome of the present `if` is fully determined. The code that does this check is in the [`compute` method of the `if`](https://github.com/SeaOfNodes/Simple/blob/main/chapter06/src/main/java/com/seaofnodes/simple/node/IfNode.java#L38-L45). The `idom` method in `Node` provides a default implementation of the depth based immediate dominator calculation. -`Region`'s [override this](https://github.com/SeaOfNodes/Simple/blob/main/chapter06/src/main/java/com/seaofnodes/simple/node/RegionNode.java#L57-L74) to implement the more complex search described above. +`Region` [overrides this](https://github.com/SeaOfNodes/Simple/blob/main/chapter06/src/main/java/com/seaofnodes/simple/node/RegionNode.java#L57-L74) to implement the more complex search described above. It turns out that to simplify the example above, we need a [further peephole in our `Add` node](https://github.com/SeaOfNodes/Simple/blob/main/chapter06/src/main/java/com/seaofnodes/simple/node/AddNode.java#L64-L67). diff --git a/chapter06/docs/06-graph1-post.json b/chapter06/docs/06-graph1-post.json new file mode 100644 index 00000000..325d473a --- /dev/null +++ b/chapter06/docs/06-graph1-post.json @@ -0,0 +1,16 @@ +{ + "ver": 1, + "comp": "chapter06/docs/06-graph1-post.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 13, "role": "CTRL", "label": null}], "proj": null}, + {"id": 12, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 13, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 12, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter06/docs/06-graph1-post.svg b/chapter06/docs/06-graph1-post.svg index faabcd8c..faef1501 100644 --- a/chapter06/docs/06-graph1-post.svg +++ b/chapter06/docs/06-graph1-post.svg @@ -1,67 +1,80 @@ - - - - - - -chapter06 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - - - -Stop3 - -Stop - - - -Return13 - -Return - - - -Stop3->Return13 - - -0 - - - -Con_12 - -#2 - - - -Return13->Start2:p0 - - -0 - - - -Return13->Con_12 - - -1 - - - +#3[0] → #13 · CTRL#13[0] → #1 · CTRL#13[1] → #12 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #13 CTRL0#2  #12#12 #2 +Type not computed + +Return  #13#13 Return +Type not computed + +[0] → #1 CTRL +[1] → #12 DATA01 diff --git a/chapter06/docs/06-graph1-pre.json b/chapter06/docs/06-graph1-pre.json new file mode 100644 index 00000000..18615f2c --- /dev/null +++ b/chapter06/docs/06-graph1-pre.json @@ -0,0 +1,24 @@ +{ + "ver": 1, + "comp": "chapter06/docs/06-graph1-pre.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}, {"idx": 1, "def": 16, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 7, "role": "CTRL", "label": null}], "proj": {"par": 7, "idx": 0}}, + {"id": 5, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 7, "role": "CTRL", "label": null}], "proj": {"par": 7, "idx": 1}}, + {"id": 6, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 7, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 12, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 4, "role": "CTRL", "label": null}, {"idx": 1, "def": 11, "role": "DATA", "label": null}], "proj": null}, + {"id": 13, "label": "#~CONTROL", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 14, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 13, "role": "DATA", "label": null}, {"idx": 2, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 15, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 14, "role": "CTRL", "label": null}, {"idx": 1, "def": 15, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter06/docs/06-graph1-pre.svg b/chapter06/docs/06-graph1-pre.svg index f80edcfc..2ba929f8 100644 --- a/chapter06/docs/06-graph1-pre.svg +++ b/chapter06/docs/06-graph1-pre.svg @@ -1,160 +1,111 @@ - - - - - - -chapter06 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - - - -Stop3 - -Stop - - - -Return12 - -Return - - - -Stop3->Return12 - - -0 - - - -Return16 - -Return - - - -Stop3->Return16 - - -1 - - - -Con_6 - -#1 - - - -If7 - - -If - - - -True - - -False - - - -If7->Start2:p0 - - -0 - - - -If7->Con_6 - - -1 - - - -Con_11 - -#2 - - - -Return12->If7:p0 - - -0 - - - -Return12->Con_11 - - -1 - - - -Con_13 - -#~CONTROL - - - -Region14 - -Region - - - -Region14->If7:p1 - - -2 - - - -Region14->Con_13 - - -1 - - - -Con_15 - -#1 - - - -Return16->Region14 - - -0 - - - -Return16->Con_15 - - -1 - - - +#3[0] → #12 · CTRL#3[1] → #16 · CTRL#7[0] → #1 · CTRL#7[1] → #6 · DATA#12[0] → #4 · CTRL#12[1] → #11 · DATA#14[1] → #13 · DATA#14[2] → #5 · CTRL#16[0] → #14 · CTRL#16[1] → #15 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #12 CTRL +[1] → #16 CTRL01True  #4/0#4 True +Projection 0 of #7 +Type not computed + +[0] → #7 CTRLFalse  #5/1#5 False +Projection 1 of #7 +Type not computed + +[0] → #7 CTRL#1  #6#6 #1 +Type not computed + +If  #7#7 If +Type not computed + +[0] → #1 CTRL +[1] → #6 DATA01#2  #11#11 #2 +Type not computed + +Return  #12#12 Return +Type not computed + +[0] → #4 CTRL +[1] → #11 DATA01#~CONTROL  #13#13 #~CONTROL +Type not computed + +Region  #14#14 Region +Type not computed + +[0] → — DATA +[1] → #13 DATA +[2] → #5 CTRL012#1  #15#15 #1 +Type not computed + +Return  #16#16 Return +Type not computed + +[0] → #14 CTRL +[1] → #15 DATA01 diff --git a/chapter06/docs/06-graph2-post.json b/chapter06/docs/06-graph2-post.json new file mode 100644 index 00000000..31be64c2 --- /dev/null +++ b/chapter06/docs/06-graph2-post.json @@ -0,0 +1,16 @@ +{ + "ver": 1, + "comp": "chapter06/docs/06-graph2-post.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}], "proj": null}, + {"id": 13, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 17, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 13, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter06/docs/06-graph2-post.svg b/chapter06/docs/06-graph2-post.svg index 269eb15c..db95f198 100644 --- a/chapter06/docs/06-graph2-post.svg +++ b/chapter06/docs/06-graph2-post.svg @@ -1,67 +1,80 @@ - - - - - - -chapter06 - - -cluster_Nodes - - - - -Return17 - -Return - - - -Start2 - - -Start - - - -$ctrl - - - -Return17->Start2:p0 - - -0 - - - -Con_13 - -#2 - - - -Return17->Con_13 - - -1 - - - -Stop3 - -Stop - - - -Stop3->Return17 - - -0 - - - +#3[0] → #17 · CTRL#17[0] → #1 · CTRL#17[1] → #13 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #17 CTRL0#2  #13#13 #2 +Type not computed + +Return  #17#17 Return +Type not computed + +[0] → #1 CTRL +[1] → #13 DATA01 diff --git a/chapter06/docs/06-graph2-pre.json b/chapter06/docs/06-graph2-pre.json new file mode 100644 index 00000000..fd187946 --- /dev/null +++ b/chapter06/docs/06-graph2-pre.json @@ -0,0 +1,24 @@ +{ + "ver": 1, + "comp": "chapter06/docs/06-graph2-pre.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}], "proj": {"par": 8, "idx": 0}}, + {"id": 5, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}], "proj": {"par": 8, "idx": 1}}, + {"id": 7, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 12, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 13, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 14, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "CTRL", "label": null}, {"idx": 2, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 15, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 14, "role": "ASSOC", "label": null}, {"idx": 1, "def": 12, "role": "DATA", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 16, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 14, "role": "CTRL", "label": null}, {"idx": 1, "def": 15, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 8, "par": 0, "nodes": [4, 5, 8, 14, 15]} + ] +} diff --git a/chapter06/docs/06-graph2-pre.svg b/chapter06/docs/06-graph2-pre.svg index e9a4dd55..bbc372f3 100644 --- a/chapter06/docs/06-graph2-pre.svg +++ b/chapter06/docs/06-graph2-pre.svg @@ -1,154 +1,108 @@ - - - - - - -chapter06 - - -cluster_Nodes - - - - -Return16 - -Return - - - -Region14 - -Region - - - -Return16->Region14 - - -0 - - - -Phi_a15 - -φ_a - - - -Return16->Phi_a15 - - -1 - - - -Start2 - - -Start - - - -$ctrl - - - -Stop3 - -Stop - - - -Stop3->Return16 - - -0 - - - -Con_7 - -#1 - - - -If8 - - -If - - - -True - - -False - - - -If8->Start2:p0 - - -0 - - - -If8->Con_7 - - -1 - - - -Con_12 - -#2 - - - -Con_13 - -#3 - - - -Region14->If8:p0 - - -1 - - - -Region14->If8:p1 - - -2 - - - -Phi_a15->Con_12 - - -1 - - - -Phi_a15->Con_13 - - -2 - - - -Phi_a15->Region14 - - -0 - - - +#3[0] → #16 · CTRL#8[0] → #1 · CTRL#8[1] → #7 · DATA#14[1] → #4 · CTRL#14[2] → #5 · CTRL#15[1] → #12 · DATA#15[2] → #13 · DATA#16[0] → #14 · CTRL#16[1] → #15 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #16 CTRL0True  #4/0#4 True +Projection 0 of #8 +Type not computed + +[0] → #8 CTRLFalse  #5/1#5 False +Projection 1 of #8 +Type not computed + +[0] → #8 CTRL#1  #7#7 #1 +Type not computed + +If  #8#8 If +Type not computed + +[0] → #1 CTRL +[1] → #7 DATA01#2  #12#12 #2 +Type not computed + +#3  #13#13 #3 +Type not computed + +Region  #14#14 Region +Type not computed + +[0] → — DATA +[1] → #4 CTRL +[2] → #5 CTRL012φ_a  #15#15 φ_a +Type not computed + +[0] → #14 ASSOC +[1] → #12 DATA +[2] → #13 DATA[0] → #14012Return  #16#16 Return +Type not computed + +[0] → #14 CTRL +[1] → #15 DATA01If  #8If · 5 nodes−Fold region diff --git a/chapter06/docs/06-graph3-nonconst-peephole.json b/chapter06/docs/06-graph3-nonconst-peephole.json new file mode 100644 index 00000000..7f1f183c --- /dev/null +++ b/chapter06/docs/06-graph3-nonconst-peephole.json @@ -0,0 +1,24 @@ +{ + "ver": 1, + "comp": "chapter06/docs/06-graph3-nonconst-peephole.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 31, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}], "proj": {"par": 8, "idx": 0}}, + {"id": 6, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}], "proj": {"par": 8, "idx": 1}}, + {"id": 8, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 22, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 6, "role": "CTRL", "label": null}], "proj": null}, + {"id": 27, "label": "#4", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 29, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 30, "label": "φ_ab", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 22, "role": "ASSOC", "label": null}, {"idx": 1, "def": 27, "role": "DATA", "label": null}, {"idx": 2, "def": 29, "role": "DATA", "label": null}], "proj": null}, + {"id": 31, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 22, "role": "CTRL", "label": null}, {"idx": 1, "def": 30, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 8, "par": 0, "nodes": [5, 6, 8, 22, 30]} + ] +} diff --git a/chapter06/docs/06-graph3-nonconst-peephole.svg b/chapter06/docs/06-graph3-nonconst-peephole.svg index c312ffc5..85728510 100644 --- a/chapter06/docs/06-graph3-nonconst-peephole.svg +++ b/chapter06/docs/06-graph3-nonconst-peephole.svg @@ -1,150 +1,109 @@ - - - - - - -chapter06 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return31 - -Return - - - -Stop3->Return31 - - -0 - - - -Region22 - -Region - - - -If8 - - -If - - - -True - - -False - - - -Region22->If8:p0 - - -1 - - - -Region22->If8:p1 - - -2 - - - -If8->Start2:p0 - - -0 - - - -If8->Start2:p1 - - -1 - - - -Con_27 - -#4 - - - -Con_29 - -#1 - - - -Phi_ab30 - -φ_ab - - - -Phi_ab30->Region22 - - -0 - - - -Phi_ab30->Con_27 - - -1 - - - -Phi_ab30->Con_29 - - -2 - - - -Return31->Region22 - - -0 - - - -Return31->Phi_ab30 - - -1 - - - +#3[0] → #31 · CTRL#8[0] → #1 · CTRL#8[1] → #4 · DATA#22[1] → #5 · CTRL#22[2] → #6 · CTRL#30[1] → #27 · DATA#30[2] → #29 · DATA#31[0] → #22 · CTRL#31[1] → #30 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #31 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #8 +Type not computed + +[0] → #8 CTRLFalse  #6/1#6 False +Projection 1 of #8 +Type not computed + +[0] → #8 CTRLIf  #8#8 If +Type not computed + +[0] → #1 CTRL +[1] → #4 DATA01Region  #22#22 Region +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #6 CTRL012#4  #27#27 #4 +Type not computed + +#1  #29#29 #1 +Type not computed + +φ_ab  #30#30 φ_ab +Type not computed + +[0] → #22 ASSOC +[1] → #27 DATA +[2] → #29 DATA[0] → #22012Return  #31#31 Return +Type not computed + +[0] → #22 CTRL +[1] → #30 DATA01If  #8If · 5 nodes−Fold region diff --git a/chapter06/docs/06-graph3-nonconst.json b/chapter06/docs/06-graph3-nonconst.json new file mode 100644 index 00000000..77bb6d2c --- /dev/null +++ b/chapter06/docs/06-graph3-nonconst.json @@ -0,0 +1,35 @@ +{ + "ver": 1, + "comp": "chapter06/docs/06-graph3-nonconst.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}], "proj": {"par": 8, "idx": 0}}, + {"id": 6, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 7, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}], "proj": {"par": 8, "idx": 1}}, + {"id": 10, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 13, "role": "CTRL", "label": null}], "proj": {"par": 13, "idx": 0}}, + {"id": 11, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 13, "role": "CTRL", "label": null}], "proj": {"par": 13, "idx": 1}}, + {"id": 12, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 13, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 18, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 19, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 10, "role": "CTRL", "label": null}, {"idx": 2, "def": 11, "role": "CTRL", "label": null}], "proj": null}, + {"id": 20, "label": "φ_b", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 19, "role": "ASSOC", "label": null}, {"idx": 1, "def": 17, "role": "DATA", "label": null}, {"idx": 2, "def": 18, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 19, "role": "CTRL", "label": null}, {"idx": 2, "def": 9, "role": "CTRL", "label": null}], "proj": null}, + {"id": 22, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 21, "role": "ASSOC", "label": null}, {"idx": 1, "def": 12, "role": "DATA", "label": null}, {"idx": 2, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 23, "label": "φ_b", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 21, "role": "ASSOC", "label": null}, {"idx": 1, "def": 20, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 24, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 23, "role": "DATA", "label": null}, {"idx": 2, "def": 22, "role": "DATA", "label": null}], "proj": null}, + {"id": 25, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 21, "role": "CTRL", "label": null}, {"idx": 1, "def": 24, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 8, "par": 0, "nodes": [5, 8, 9, 21, 22, 23, 24]}, + {"id": 13, "par": 8, "nodes": [10, 11, 13, 19, 20]} + ] +} diff --git a/chapter06/docs/06-graph3-nonconst.svg b/chapter06/docs/06-graph3-nonconst.svg index dee852e4..d46d4bb1 100644 --- a/chapter06/docs/06-graph3-nonconst.svg +++ b/chapter06/docs/06-graph3-nonconst.svg @@ -1,290 +1,150 @@ - - - - - - -chapter06 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return25 - -Return - - - -Stop3->Return25 - - -0 - - - -Con_6 - -#0 - - - -Con_7 - -#1 - - - -If8 - - -If - - - -True - - -False - - - -If8->Start2:p0 - - -0 - - - -If8->Start2:p1 - - -1 - - - -Con_12 - -#2 - - - -If13 - - -If - - - -True - - -False - - - -If13->Start2:p1 - - -1 - - - -If13->If8:p0 - - -0 - - - -Con_17 - -#2 - - - -Con_18 - -#3 - - - -Region19 - -Region - - - -Region19->If13:p0 - - -1 - - - -Region19->If13:p1 - - -2 - - - -Phi_b20 - -φ_b - - - -Phi_b20->Con_17 - - -1 - - - -Phi_b20->Con_18 - - -2 - - - -Phi_b20->Region19 - - -0 - - - -Region21 - -Region - - - -Region21->If8:p1 - - -2 - - - -Region21->Region19 - - -1 - - - -Phi_a22 - -φ_a - - - -Phi_a22->Con_6 - - -2 - - - -Phi_a22->Con_12 - - -1 - - - -Phi_a22->Region21 - - -0 - - - -Phi_b23 - -φ_b - - - -Phi_b23->Con_7 - - -2 - - - -Phi_b23->Phi_b20 - - -1 - - - -Phi_b23->Region21 - - -0 - - - -Add24 - -+ - - - -Add24->Phi_a22 - - -2 - - - -Add24->Phi_b23 - - -1 - - - -Return25->Region21 - - -0 - - - -Return25->Add24 - - -1 - - - +#3[0] → #25 · CTRL#8[0] → #1 · CTRL#8[1] → #4 · DATA#13[0] → #5 · CTRL#13[1] → #4 · DATA#19[1] → #10 · CTRL#19[2] → #11 · CTRL#20[1] → #17 · DATA#20[2] → #18 · DATA#21[1] → #19 · CTRL#21[2] → #9 · CTRL#22[1] → #12 · DATA#22[2] → #6 · DATA#23[1] → #20 · DATA#23[2] → #7 · DATA#24[1] → #23 · DATA#24[2] → #22 · DATA#25[0] → #21 · CTRL#25[1] → #24 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #25 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #8 +Type not computed + +[0] → #8 CTRL#0  #6#6 #0 +Type not computed + +#1  #7#7 #1 +Type not computed + +If  #8#8 If +Type not computed + +[0] → #1 CTRL +[1] → #4 DATA01False  #9/1#9 False +Projection 1 of #8 +Type not computed + +[0] → #8 CTRLTrue  #10/0#10 True +Projection 0 of #13 +Type not computed + +[0] → #13 CTRLFalse  #11/1#11 False +Projection 1 of #13 +Type not computed + +[0] → #13 CTRL#2  #12#12 #2 +Type not computed + +If  #13#13 If +Type not computed + +[0] → #5 CTRL +[1] → #4 DATA01#2  #17#17 #2 +Type not computed + +#3  #18#18 #3 +Type not computed + +Region  #19#19 Region +Type not computed + +[0] → — DATA +[1] → #10 CTRL +[2] → #11 CTRL012φ_b  #20#20 φ_b +Type not computed + +[0] → #19 ASSOC +[1] → #17 DATA +[2] → #18 DATA[0] → #19012Region  #21#21 Region +Type not computed + +[0] → — DATA +[1] → #19 CTRL +[2] → #9 CTRL012φ_a  #22#22 φ_a +Type not computed + +[0] → #21 ASSOC +[1] → #12 DATA +[2] → #6 DATA[0] → #21012φ_b  #23#23 φ_b +Type not computed + +[0] → #21 ASSOC +[1] → #20 DATA +[2] → #7 DATA[0] → #21012+  #24#24 + +Type not computed + +[0] → — DATA +[1] → #23 DATA +[2] → #22 DATA012Return  #25#25 Return +Type not computed + +[0] → #21 CTRL +[1] → #24 DATA01If  #8If · 12 nodes−Fold regionIf  #13If · 5 nodes−Fold region diff --git a/chapter06/docs/Makefile b/chapter06/docs/Makefile index 12659b8f..6fa0f057 100644 --- a/chapter06/docs/Makefile +++ b/chapter06/docs/Makefile @@ -1,12 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter07/README.md b/chapter07/README.md index d701278a..5a49d3ef 100644 --- a/chapter07/README.md +++ b/chapter07/README.md @@ -1,5 +1,8 @@ # Chapter 7: While Statement +[Previous: Chapter 6](../chapter06/README.md) | +[Next: Chapter 8](../chapter08/README.md) + # Table of Contents 1. [Dealing With Back Edges](#dealing-with-back-edges) @@ -7,7 +10,7 @@ 3. [Detailed Steps](#detailed-steps) 4. [Visualization](#visualization) 5. [Nested Loops](#nested-loops) -5. [Loop With Nested If](#loop-with-nested-if) +6. [Loop With Nested If](#loop-with-nested-if) You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter07) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch and [compare](https://github.com/SeaOfNodes/Simple/compare/linear-chapter06...linear-chapter07) it to the previous chapter. @@ -94,7 +97,7 @@ until we complete parsing the loop body. Other nodes continue to optimize normal The newly created region becomes the current control. 2. We duplicate the current Scope node. This involves duplicating all the symbols at - every level with the scope, and creating phis for every symbol except the `$ctrl` binding. + every level within the scope, and creating phis for every symbol except the `$ctrl` binding. ```java // Make a new Scope for the body. @@ -196,7 +199,8 @@ The example quoted above is shown below at an intermediate state: ![Graph1](./docs/07-graph1.svg) -* Three Scopes are shown, reading clockwise, the loop head, exit and the body. +* Three Scopes are shown: the loop head, exit, and body. Their `$ctrl` bindings + point to Loop, False, and True, respectively. The final graph looks like this: diff --git a/chapter07/docs/07-graph1.json b/chapter07/docs/07-graph1.json new file mode 100644 index 00000000..0f2c6c4d --- /dev/null +++ b/chapter07/docs/07-graph1.json @@ -0,0 +1,27 @@ +{ + "ver": 1, + "comp": "chapter07/docs/07-graph1.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 18, "role": "ASSOC", "label": "3: $ctrl"}, {"idx": 1, "def": 16, "role": "ASSOC", "label": "3: arg"}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 5, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 6, "role": "ASSOC", "label": "2: $ctrl"}, {"idx": 1, "def": 8, "role": "ASSOC", "label": "2: arg"}], "proj": null}, + {"id": 6, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 14, "role": "CTRL", "label": null}], "proj": null}, + {"id": 8, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 6, "role": "ASSOC", "label": null}, {"idx": 1, "def": 17, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "10", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 10, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 6, "role": "CTRL", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 12, "label": "Scope", "type": null, "kind": "SCOPE", "edges": [{"idx": 0, "def": 19, "role": "ASSOC", "label": "2: $ctrl"}, {"idx": 1, "def": 8, "role": "ASSOC", "label": "2: arg"}], "proj": null}, + {"id": 14, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 15, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 15, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 18, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 0}}, + {"id": 19, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 1}} + ], + "groups": [ + {"id": 6, "par": 0, "nodes": [6, 8]} + ] +} diff --git a/chapter07/docs/07-graph1.svg b/chapter07/docs/07-graph1.svg index 94248cfb..e6ee94a4 100644 --- a/chapter07/docs/07-graph1.svg +++ b/chapter07/docs/07-graph1.svg @@ -1,268 +1,122 @@ - - - - - - -chapter07 - - -cluster_Nodes - - - -cluster_Scope7_1 - - - -cluster_Scope7_2 - - - -cluster_Scope7_3 - - - -cluster_Scope1_1 - - - -cluster_Scope1_2 - - - -cluster_Scope14_1 - - - -cluster_Scope14_2 - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Loop6 - -Loop - - - -Loop6->Start2:p0 - - -1 - - - -Phi_arg8 - -φ_arg - - - -Phi_arg8->Start2:p1 - - -1 - - - -Phi_arg8->Loop6 - - -0 - - - -Con_9 - -10 - - - -LT10 - -< - - - -LT10->Phi_arg8 - - -1 - - - -LT10->Con_9 - - -2 - - - -If11 - - -If - - - -True - - -False - - - -If11->Loop6 - - -0 - - - -If11->LT10 - - -1 - - - -Con_15 - -1 - - - -Add16 - -+ - - - -Add16->Phi_arg8 - - -1 - - - -Add16->Con_15 - - -2 - - - -Scope7_1 - - -2 - - - -Scope7_2 - - -1 - - - -Scope7_3 - - -0 - -$ctrl - -arg - - - -Scope7_3:Scope7_3_$ctrl->If11:p0 - - - - - -Scope7_3:Scope7_3_arg->Add16 - - - - - -Scope1_1 - - -1 - - - -Scope1_2 - - -0 - -$ctrl - -arg - - - -Scope1_2:Scope1_2_$ctrl->Loop6 - - - - - -Scope1_2:Scope1_2_arg->Phi_arg8 - - - - - -Scope14_1 - - -1 - - - -Scope14_2 - - -0 - -$ctrl - -arg - - - -Scope14_2:Scope14_2_arg->Phi_arg8 - - - - - -Scope14_2:Scope14_2_$ctrl->If11:p1 - - - - - +#1[0] → #18 · ASSOC · 3: $ctrl#1[1] → #16 · ASSOC · 3: arg#5[0] → #6 · ASSOC · 2: $ctrl#5[1] → #8 · ASSOC · 2: arg#6[1] → #14 · CTRL#8[1] → #17 · DATA#10[1] → #8 · DATA#10[2] → #9 · DATA#11[0] → #6 · CTRL#11[1] → #10 · DATA#12[0] → #19 · ASSOC · 2: $ctrl#12[1] → #8 · ASSOC · 2: arg#16[1] → #8 · DATA#16[2] → #15 · DATAScope  #1#1 Scope +Type not computed + +[0] → #18 ASSOC 3: $ctrl +[1] → #16 ASSOC 3: arg3: $ctrl3: arg01Start  #2#2 Start +Type not computed + +Scope  #5#5 Scope +Type not computed + +[0] → #6 ASSOC 2: $ctrl +[1] → #8 ASSOC 2: arg2: $ctrl2: arg01Loop  #6#6 Loop +Type not computed + +[0] → — DATA +[1] → #14 CTRL01φ_arg  #8#8 φ_arg +Type not computed + +[0] → #6 ASSOC +[1] → #17 DATA[0] → #60110  #9#9 10 +Type not computed + +<  #10#10 < +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #9 DATA012If  #11#11 If +Type not computed + +[0] → #6 CTRL +[1] → #10 DATA01Scope  #12#12 Scope +Type not computed + +[0] → #19 ASSOC 2: $ctrl +[1] → #8 ASSOC 2: arg2: $ctrl2: arg01$ctrl  #14/0#14 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRL1  #15#15 1 +Type not computed + ++  #16#16 + +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #15 DATA012arg  #17/1#17 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #18/0#18 True +Projection 0 of #11 +Type not computed + +[0] → #11 CTRLFalse  #19/1#19 False +Projection 1 of #11 +Type not computed + +[0] → #11 CTRLLoop  #6Loop · 2 nodes−Fold region diff --git a/chapter07/docs/07-graph2.json b/chapter07/docs/07-graph2.json new file mode 100644 index 00000000..cc0e6d6c --- /dev/null +++ b/chapter07/docs/07-graph2.json @@ -0,0 +1,26 @@ +{ + "ver": 1, + "comp": "chapter07/docs/07-graph2.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 0}}, + {"id": 6, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 1, "role": "CTRL", "label": null}, {"idx": 2, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 7, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 1}}, + {"id": 8, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 6, "role": "ASSOC", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "10", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 10, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 6, "role": "CTRL", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 15, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 7, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 6, "par": 0, "nodes": [5, 6, 7, 8, 10, 11, 16]} + ] +} diff --git a/chapter07/docs/07-graph2.svg b/chapter07/docs/07-graph2.svg index 1fec9556..72153555 100644 --- a/chapter07/docs/07-graph2.svg +++ b/chapter07/docs/07-graph2.svg @@ -1,184 +1,119 @@ - - - - - - -chapter07 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return17 - -Return - - - -Stop3->Return17 - - -0 - - - -Loop6 - -Loop - - - -Loop6->Start2:p0 - - -1 - - - -If11 - - -If - - - -True - - -False - - - -Loop6->If11:p0 - - -2 - - - -Phi_arg8 - -φ_arg - - - -Phi_arg8->Start2:p1 - - -1 - - - -Phi_arg8->Loop6 - - -0 - - - -Add16 - -+ - - - -Con_9 - -10 - - - -LT10 - -< - - - -LT10->Phi_arg8 - - -1 - - - -LT10->Con_9 - - -2 - - - -If11->Loop6 - - -0 - - - -If11->LT10 - - -1 - - - -Con_15 - -1 - - - -Add16->Phi_arg8 - - - -1 - - - -Add16->Con_15 - - -2 - - - -Return17->Phi_arg8 - - -1 - - - -Return17->If11:p1 - - -0 - - - +#3[0] → #17 · CTRL#6[1] → #1 · CTRL#6[2] → #5 · CTRL#8[1] → #4 · DATA#8[2] → #16 · DATA#10[1] → #8 · DATA#10[2] → #9 · DATA#11[0] → #6 · CTRL#11[1] → #10 · DATA#16[1] → #8 · DATA#16[2] → #15 · DATA#17[0] → #7 · CTRL#17[1] → #8 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #17 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #11 +Type not computed + +[0] → #11 CTRLLoop  #6#6 Loop +Type not computed + +[0] → — DATA +[1] → #1 CTRL +[2] → #5 CTRL012False  #7/1#7 False +Projection 1 of #11 +Type not computed + +[0] → #11 CTRLφ_arg  #8#8 φ_arg +Type not computed + +[0] → #6 ASSOC +[1] → #4 DATA +[2] → #16 DATA[0] → #601210  #9#9 10 +Type not computed + +<  #10#10 < +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #9 DATA012If  #11#11 If +Type not computed + +[0] → #6 CTRL +[1] → #10 DATA011  #15#15 1 +Type not computed + ++  #16#16 + +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #15 DATA012Return  #17#17 Return +Type not computed + +[0] → #7 CTRL +[1] → #8 DATA01Loop  #6Loop · 7 nodes−Fold region diff --git a/chapter07/docs/07-graph3.json b/chapter07/docs/07-graph3.json new file mode 100644 index 00000000..26dbc457 --- /dev/null +++ b/chapter07/docs/07-graph3.json @@ -0,0 +1,40 @@ +{ + "ver": 1, + "comp": "chapter07/docs/07-graph3.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 35, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 14, "role": "CTRL", "label": null}], "proj": {"par": 14, "idx": 0}}, + {"id": 6, "label": "0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 7, "label": "0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 1, "role": "CTRL", "label": null}, {"idx": 2, "def": 15, "role": "CTRL", "label": null}], "proj": null}, + {"id": 9, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 14, "role": "CTRL", "label": null}], "proj": {"par": 14, "idx": 1}}, + {"id": 10, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 28, "role": "CTRL", "label": null}], "proj": {"par": 28, "idx": 0}}, + {"id": 11, "label": "φ_sum", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 8, "role": "ASSOC", "label": null}, {"idx": 1, "def": 6, "role": "DATA", "label": null}, {"idx": 2, "def": 24, "role": "DATA", "label": null}], "proj": null}, + {"id": 12, "label": "φ_i", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 8, "role": "ASSOC", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 19, "role": "DATA", "label": null}], "proj": null}, + {"id": 13, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 12, "role": "DATA", "label": null}, {"idx": 2, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 14, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 28, "role": "CTRL", "label": null}], "proj": {"par": 28, "idx": 1}}, + {"id": 18, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 19, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 12, "role": "DATA", "label": null}, {"idx": 2, "def": 18, "role": "DATA", "label": null}], "proj": null}, + {"id": 20, "label": "0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 21, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 10, "role": "CTRL", "label": null}], "proj": null}, + {"id": 24, "label": "φ_sum", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 21, "role": "ASSOC", "label": null}, {"idx": 1, "def": 11, "role": "DATA", "label": null}, {"idx": 2, "def": 32, "role": "DATA", "label": null}], "proj": null}, + {"id": 26, "label": "φ_j", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 21, "role": "ASSOC", "label": null}, {"idx": 1, "def": 20, "role": "DATA", "label": null}, {"idx": 2, "def": 34, "role": "DATA", "label": null}], "proj": null}, + {"id": 27, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 26, "role": "DATA", "label": null}, {"idx": 2, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 28, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 21, "role": "CTRL", "label": null}, {"idx": 1, "def": 27, "role": "DATA", "label": null}], "proj": null}, + {"id": 32, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 26, "role": "DATA", "label": null}, {"idx": 2, "def": 24, "role": "DATA", "label": null}], "proj": null}, + {"id": 33, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 34, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 26, "role": "DATA", "label": null}, {"idx": 2, "def": 33, "role": "DATA", "label": null}], "proj": null}, + {"id": 35, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 9, "role": "CTRL", "label": null}, {"idx": 1, "def": 11, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 8, "par": 0, "nodes": [5, 8, 9, 11, 12, 13, 14, 19]}, + {"id": 21, "par": 8, "nodes": [10, 15, 21, 24, 26, 27, 28, 32, 34]} + ] +} diff --git a/chapter07/docs/07-graph3.svg b/chapter07/docs/07-graph3.svg index a9a0e8d0..181b72a9 100644 --- a/chapter07/docs/07-graph3.svg +++ b/chapter07/docs/07-graph3.svg @@ -1,373 +1,175 @@ - - - - - - -chapter07 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return35 - -Return - - - -Stop3->Return35 - - -0 - - - -Con_6 - -0 - - - -Con_7 - -0 - - - -Loop8 - -Loop - - - -Loop8->Start2:p0 - - -1 - - - -If28 - - -If - - - -True - - -False - - - -Loop8->If28:p1 - - -2 - - - -Phi_sum11 - -φ_sum - - - -Phi_sum11->Con_6 - - -1 - - - -Phi_sum11->Loop8 - - -0 - - - -Phi_sum24 - -φ_sum - - - -Phi_i12 - -φ_i - - - -Phi_i12->Con_7 - - -1 - - - -Phi_i12->Loop8 - - -0 - - - -Add19 - -+ - - - -LT13 - -< - - - -LT13->Start2:p1 - - -2 - - - -LT13->Phi_i12 - - -1 - - - -If14 - - -If - - - -True - - -False - - - -If14->Loop8 - - -0 - - - -If14->LT13 - - -1 - - - -Con_18 - -1 - - - -Add19->Phi_i12 - - - -1 - - - -Add19->Con_18 - - -2 - - - -Con_20 - -0 - - - -Loop21 - -Loop - - - -Loop21->If14:p0 - - -1 - - - -Loop21->If28:p0 - - -2 - - - -Phi_sum24->Phi_sum11 - - - -1 - - - -Phi_sum24->Loop21 - - -0 - - - -Add32 - -+ - - - -Phi_j26 - -φ_j - - - -Phi_j26->Con_20 - - -1 - - - -Phi_j26->Loop21 - - -0 - - - -Add34 - -+ - - - -LT27 - -< - - - -LT27->Start2:p1 - - -2 - - - -LT27->Phi_j26 - - -1 - - - -If28->Loop21 - - -0 - - - -If28->LT27 - - -1 - - - -Add32->Phi_sum24 - - - -2 - - - -Add32->Phi_j26 - - -1 - - - -Con_33 - -1 - - - -Add34->Phi_j26 - - - -1 - - - -Add34->Con_33 - - -2 - - - -Return35->Phi_sum11 - - -1 - - - -Return35->If14:p1 - - -0 - - - +#3[0] → #35 · CTRL#8[1] → #1 · CTRL#8[2] → #15 · CTRL#11[1] → #6 · DATA#11[2] → #24 · DATA#12[1] → #7 · DATA#12[2] → #19 · DATA#13[1] → #12 · DATA#13[2] → #4 · DATA#14[0] → #8 · CTRL#14[1] → #13 · DATA#19[1] → #12 · DATA#19[2] → #18 · DATA#21[1] → #5 · CTRL#21[2] → #10 · CTRL#24[1] → #11 · DATA#24[2] → #32 · DATA#26[1] → #20 · DATA#26[2] → #34 · DATA#27[1] → #26 · DATA#27[2] → #4 · DATA#28[0] → #21 · CTRL#28[1] → #27 · DATA#32[1] → #26 · DATA#32[2] → #24 · DATA#34[1] → #26 · DATA#34[2] → #33 · DATA#35[0] → #9 · CTRL#35[1] → #11 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #35 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #14 +Type not computed + +[0] → #14 CTRL0  #6#6 0 +Type not computed + +0  #7#7 0 +Type not computed + +Loop  #8#8 Loop +Type not computed + +[0] → — DATA +[1] → #1 CTRL +[2] → #15 CTRL012False  #9/1#9 False +Projection 1 of #14 +Type not computed + +[0] → #14 CTRLTrue  #10/0#10 True +Projection 0 of #28 +Type not computed + +[0] → #28 CTRLφ_sum  #11#11 φ_sum +Type not computed + +[0] → #8 ASSOC +[1] → #6 DATA +[2] → #24 DATA[0] → #8012φ_i  #12#12 φ_i +Type not computed + +[0] → #8 ASSOC +[1] → #7 DATA +[2] → #19 DATA[0] → #8012<  #13#13 < +Type not computed + +[0] → — DATA +[1] → #12 DATA +[2] → #4 DATA012If  #14#14 If +Type not computed + +[0] → #8 CTRL +[1] → #13 DATA01False  #15/1#15 False +Projection 1 of #28 +Type not computed + +[0] → #28 CTRL1  #18#18 1 +Type not computed + ++  #19#19 + +Type not computed + +[0] → — DATA +[1] → #12 DATA +[2] → #18 DATA0120  #20#20 0 +Type not computed + +Loop  #21#21 Loop +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #10 CTRL012φ_sum  #24#24 φ_sum +Type not computed + +[0] → #21 ASSOC +[1] → #11 DATA +[2] → #32 DATA[0] → #21012φ_j  #26#26 φ_j +Type not computed + +[0] → #21 ASSOC +[1] → #20 DATA +[2] → #34 DATA[0] → #21012<  #27#27 < +Type not computed + +[0] → — DATA +[1] → #26 DATA +[2] → #4 DATA012If  #28#28 If +Type not computed + +[0] → #21 CTRL +[1] → #27 DATA01+  #32#32 + +Type not computed + +[0] → — DATA +[1] → #26 DATA +[2] → #24 DATA0121  #33#33 1 +Type not computed + ++  #34#34 + +Type not computed + +[0] → — DATA +[1] → #26 DATA +[2] → #33 DATA012Return  #35#35 Return +Type not computed + +[0] → #9 CTRL +[1] → #11 DATA01Loop  #8Loop · 17 nodes−Fold regionLoop  #21Loop · 9 nodes−Fold region diff --git a/chapter07/docs/07-graph4.json b/chapter07/docs/07-graph4.json new file mode 100644 index 00000000..a9848505 --- /dev/null +++ b/chapter07/docs/07-graph4.json @@ -0,0 +1,37 @@ +{ + "ver": 1, + "comp": "chapter07/docs/07-graph4.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 30, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 15, "role": "CTRL", "label": null}], "proj": {"par": 15, "idx": 0}}, + {"id": 5, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 15, "role": "CTRL", "label": null}], "proj": {"par": 15, "idx": 1}}, + {"id": 6, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 7, "label": "2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 1, "role": "CTRL", "label": null}, {"idx": 2, "def": 27, "role": "CTRL", "label": null}], "proj": null}, + {"id": 9, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 21, "role": "CTRL", "label": null}], "proj": {"par": 21, "idx": 0}}, + {"id": 10, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 21, "role": "CTRL", "label": null}], "proj": {"par": 21, "idx": 1}}, + {"id": 11, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 8, "role": "ASSOC", "label": null}, {"idx": 1, "def": 6, "role": "DATA", "label": null}, {"idx": 2, "def": 28, "role": "DATA", "label": null}], "proj": null}, + {"id": 12, "label": "φ_b", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 8, "role": "ASSOC", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 29, "role": "DATA", "label": null}], "proj": null}, + {"id": 13, "label": "10", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 14, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 11, "role": "DATA", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "DATA", "label": null}], "proj": null}, + {"id": 19, "label": "2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 20, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 11, "role": "DATA", "label": null}, {"idx": 2, "def": 19, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 4, "role": "CTRL", "label": null}, {"idx": 1, "def": 20, "role": "DATA", "label": null}], "proj": null}, + {"id": 25, "label": "3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 26, "label": "4", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 27, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 9, "role": "CTRL", "label": null}, {"idx": 2, "def": 10, "role": "CTRL", "label": null}], "proj": null}, + {"id": 28, "label": "φ_a", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 27, "role": "ASSOC", "label": null}, {"idx": 1, "def": 25, "role": "DATA", "label": null}, {"idx": 2, "def": 11, "role": "DATA", "label": null}], "proj": null}, + {"id": 29, "label": "φ_b", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 27, "role": "ASSOC", "label": null}, {"idx": 1, "def": 12, "role": "DATA", "label": null}, {"idx": 2, "def": 26, "role": "DATA", "label": null}], "proj": null}, + {"id": 30, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 12, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 8, "par": 0, "nodes": [4, 5, 8, 11, 12, 14, 15]}, + {"id": 21, "par": 8, "nodes": [9, 10, 20, 21, 27, 28, 29]} + ] +} diff --git a/chapter07/docs/07-graph4.svg b/chapter07/docs/07-graph4.svg index cf42453d..0fc498f7 100644 --- a/chapter07/docs/07-graph4.svg +++ b/chapter07/docs/07-graph4.svg @@ -1,329 +1,159 @@ - - - - - - -chapter07 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - - - -Stop3 - -Stop - - - -Return30 - -Return - - - -Stop3->Return30 - - -0 - - - -Con_6 - -1 - - - -Con_7 - -2 - - - -Loop8 - -Loop - - - -Loop8->Start2:p0 - - -1 - - - -Region27 - -Region - - - -Loop8->Region27 - - -2 - - - -Phi_a11 - -φ_a - - - -Phi_a11->Con_6 - - -1 - - - -Phi_a11->Loop8 - - -0 - - - -Phi_a28 - -φ_a - - - -Phi_b12 - -φ_b - - - -Phi_b12->Con_7 - - -1 - - - -Phi_b12->Loop8 - - -0 - - - -Phi_b29 - -φ_b - - - -Con_13 - -10 - - - -LT14 - -< - - - -LT14->Phi_a11 - - -1 - - - -LT14->Con_13 - - -2 - - - -If15 - - -If - - - -True - - -False - - - -If15->Loop8 - - -0 - - - -If15->LT14 - - -1 - - - -Con_19 - -2 - - - -EQ20 - -== - - - -EQ20->Phi_a11 - - -1 - - - -EQ20->Con_19 - - -2 - - - -If21 - - -If - - - -True - - -False - - - -If21->If15:p0 - - -0 - - - -If21->EQ20 - - -1 - - - -Con_25 - -3 - - - -Con_26 - -4 - - - -Region27->If21:p0 - - -1 - - - -Region27->If21:p1 - - -2 - - - -Phi_a28->Phi_a11 - - - -2 - - - -Phi_a28->Con_25 - - -1 - - - -Phi_a28->Region27 - - -0 - - - -Phi_b29->Phi_b12 - - - -1 - - - -Phi_b29->Con_26 - - -2 - - - -Phi_b29->Region27 - - -0 - - - -Return30->Phi_b12 - - -1 - - - -Return30->If15:p1 - - -0 - - - +#3[0] → #30 · CTRL#8[1] → #1 · CTRL#8[2] → #27 · CTRL#11[1] → #6 · DATA#11[2] → #28 · DATA#12[1] → #7 · DATA#12[2] → #29 · DATA#14[1] → #11 · DATA#14[2] → #13 · DATA#15[0] → #8 · CTRL#15[1] → #14 · DATA#20[1] → #11 · DATA#20[2] → #19 · DATA#21[0] → #4 · CTRL#21[1] → #20 · DATA#27[1] → #9 · CTRL#27[2] → #10 · CTRL#28[1] → #25 · DATA#28[2] → #11 · DATA#29[1] → #12 · DATA#29[2] → #26 · DATA#30[0] → #5 · CTRL#30[1] → #12 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #30 CTRL0True  #4/0#4 True +Projection 0 of #15 +Type not computed + +[0] → #15 CTRLFalse  #5/1#5 False +Projection 1 of #15 +Type not computed + +[0] → #15 CTRL1  #6#6 1 +Type not computed + +2  #7#7 2 +Type not computed + +Loop  #8#8 Loop +Type not computed + +[0] → — DATA +[1] → #1 CTRL +[2] → #27 CTRL012True  #9/0#9 True +Projection 0 of #21 +Type not computed + +[0] → #21 CTRLFalse  #10/1#10 False +Projection 1 of #21 +Type not computed + +[0] → #21 CTRLφ_a  #11#11 φ_a +Type not computed + +[0] → #8 ASSOC +[1] → #6 DATA +[2] → #28 DATA[0] → #8012φ_b  #12#12 φ_b +Type not computed + +[0] → #8 ASSOC +[1] → #7 DATA +[2] → #29 DATA[0] → #801210  #13#13 10 +Type not computed + +<  #14#14 < +Type not computed + +[0] → — DATA +[1] → #11 DATA +[2] → #13 DATA012If  #15#15 If +Type not computed + +[0] → #8 CTRL +[1] → #14 DATA012  #19#19 2 +Type not computed + +==  #20#20 == +Type not computed + +[0] → — DATA +[1] → #11 DATA +[2] → #19 DATA012If  #21#21 If +Type not computed + +[0] → #4 CTRL +[1] → #20 DATA013  #25#25 3 +Type not computed + +4  #26#26 4 +Type not computed + +Region  #27#27 Region +Type not computed + +[0] → — DATA +[1] → #9 CTRL +[2] → #10 CTRL012φ_a  #28#28 φ_a +Type not computed + +[0] → #27 ASSOC +[1] → #25 DATA +[2] → #11 DATA[0] → #27012φ_b  #29#29 φ_b +Type not computed + +[0] → #27 ASSOC +[1] → #12 DATA +[2] → #26 DATA[0] → #27012Return  #30#30 Return +Type not computed + +[0] → #5 CTRL +[1] → #12 DATA01Loop  #8Loop · 14 nodes−Fold regionIf  #21If · 7 nodes−Fold region diff --git a/chapter07/docs/Makefile b/chapter07/docs/Makefile index 12659b8f..6fa0f057 100644 --- a/chapter07/docs/Makefile +++ b/chapter07/docs/Makefile @@ -1,12 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter08/README.md b/chapter08/README.md index f1718fbb..46e4eeca 100644 --- a/chapter08/README.md +++ b/chapter08/README.md @@ -1,18 +1,20 @@ # Chapter 8: Lazy Phis, Break, Continue, and Evaluator +[Previous: Chapter 7](../chapter07/README.md) | +[Next: Chapter 9](../chapter09/README.md) + # Table of Contents 1. [Lazy Phi Creation](#lazy-phi-creation) 2. [Continue statement](#continue-statement) 3. [Break statement](#break-statement) -4. [Parser Considerations ](#parser-considerations) -5. [Identification of Basic Blocks in SoN graph](#identification-of-basic-blocks-in-son-graph) -6. [Examples](#examples) - -[Example 1](#example-1) - -[Example 2](#example-2) - -[Example 3](#example-3) +4. [Parser Considerations](#parser-considerations) +5. [Examples](#examples) + - [Example 1](#example-1) + - [Example 2](#example-2) + - [Example 3](#example-3) -7. [Sea of Nodes Graph Evaluator](#sea-of-nodes-graph-evaluator) +6. [Sea of Nodes Graph Evaluator](#sea-of-nodes-graph-evaluator) You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter08) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch and [compare](https://github.com/SeaOfNodes/Simple/compare/linear-chapter07...linear-chapter08) it to the previous chapter. @@ -68,7 +70,7 @@ We do this as follows: ? loop.in(idx) // Set real Phi in the loop head // The phi takes its one input (no backedge yet) from a recursive - // lookup, which might have insert a Phi in every loop nest. + // lookup, which might have inserted a Phi in every loop nest. : loop.setDef(idx,new PhiNode(name,loop.ctrl(),loop.update(name,null,nestingLevel),null).peephole()); setDef(idx,old); } @@ -80,7 +82,7 @@ We do this as follows: ```java if( in(i) != that.in(i) ) // No need for redundant Phis - // If we are in lazy phi mode we need to a lookup + // If we are in lazy phi mode we need to do a lookup // by name as it will trigger a phi creation setDef(i, new PhiNode(ns[i], r, this.lookup(ns[i]), that.lookup(ns[i])).peephole()); ``` @@ -105,7 +107,7 @@ We do this as follows: ## `continue` Statement -In chapter7, we had a single backedge from the loop's end flowing back to the +In Chapter 7, we had a single backedge from the loop's end flowing back to the loop head. With the addition of a `continue` statement, we can have multiple backedges @@ -115,10 +117,10 @@ We have several ways of implementing these backedges. 1. The traditional way would be to let each backedge from `continue` merge into the loop head. Phis would require as many inputs as there are edges. The - downside is now are Loops are not simply nested. This makes it difficult to + downside is now our Loops are not simply nested. This makes it difficult to do many kinds of peephole-based loop optimizations, such as "partially rolling" the loop to allow more loop invariants to get hoisted. -2. An alternative is collect all `continue`s at a single merge point (`Region`) +2. An alternative is to collect all `continue`s at a single merge point (`Region`) and then create a single backedge flowing from the continue `Region` to the loop head. 3. A third approach is to create a stack of continue `Region`s rather than a @@ -148,7 +150,7 @@ scope into it to generate a continue Scope and `Region`. Subsequently, when we see another `continue`, we need to construct a new `Region` and merge the previous continue Scope with the current Scope. -The implementation is a variation of above. +The implementation is a variation of the above. * The first `continue` triggers a dupe of the current scope; we prune any nested lexical scopes deeper than the head scope, removing any name bindings @@ -274,11 +276,11 @@ With that brief setup done, the control projection from the Start node is traver At this point, control flow is at the first region of the program, but it is treated just the same as any other region. There are two things that must be done at each region. First, resolve all phis to a specific value; and second to determine where control flow will continue to. -It may seem like more than that should be done, but by resolving phi nodes, any logic that is specific to the control flow path for the given will be resolved. Any other work will eventually be resolved later on as-needed. This is sufficient for the program to run! +It may seem like more than that should be done, but by resolving phi nodes, any logic that is specific to the control flow path for the given region will be resolved. Any other work will eventually be resolved later on as-needed. This is sufficient for the program to run! Finding the next place control flow will move to after a region is straightforward because any region only has a single control node that uses it. So we search for that node in the Region's users. -Once we have that node, our behavior depends on what type of control flow node we've landed on. There are only 3 options: `RegionNode`, `IfNode`, and `ReturnNode`. If it is another `RegionNode`, we do the same again. If it's a `ReturnNode`, we can resolve the returned expression and return the program's value. Finally, for an `IfNode`, we must first resolve the test expression so that we can choose the false (projection 0) or true (projection 1) branch. Whichever projection from the `IfNode` is chosen, we step through that projection on to the control node (a `RegionNode`) that uses it. +Once we have that node, our behavior depends on what type of control flow node we've landed on. There are only 3 options: `RegionNode`, `IfNode`, and `ReturnNode`. If it is another `RegionNode`, we do the same again. If it's a `ReturnNode`, we can resolve the returned expression and return the program's value. Finally, for an `IfNode`, we must first resolve the test expression so that we can choose the true (projection 0) or false (projection 1) branch. Whichever projection from the `IfNode` is chosen, we step through that projection on to the control node (a `RegionNode`) that uses it. We talk about resolving nodes above, but what does that mean? A node will either have a value (for instance a constant), will already be resolved with the resolved value cached, or it will operate on nodes that it uses, which must be resolved. Once a node's inputs are resolved, its operation may be performed on them. For instance, an `AddNode`'s value will be the sum of its two inputs. Once the value is resolved, the resolved value is returned. @@ -289,7 +291,7 @@ Looping is almost functional with that, too, with only a couple of small extra d Finally, while calculating the value of `PhiNode`s in the loop region, we must be careful to compute all of their new values before we update any of their cached values. That's because as a loop iterates, we must ensure that all `PhiNode` values are consistently the value from the same point in time. Once all of the new values are calculated, we can update the cache for all of them at once. To illustrate this, consider the following code: ```java -t = 0; +int t = 0; while(arg < 10) { t = arg; arg = arg + 1; @@ -309,4 +311,4 @@ arg=arg+arg; return arg; ``` -On the other hand, this engine is not designed to be particularly fast! Because not all expressions are cached, it's possible to construct programs like the preceeding one which have exponential runtime. +On the other hand, this engine is not designed to be particularly fast! Because not all expressions are cached, it's possible to construct programs like the preceding one which have exponential runtime. diff --git a/chapter08/docs/08-graph1.json b/chapter08/docs/08-graph1.json new file mode 100644 index 00000000..130a79bd --- /dev/null +++ b/chapter08/docs/08-graph1.json @@ -0,0 +1,39 @@ +{ + "ver": 1, + "comp": "chapter08/docs/08-graph1.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 40, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 0}}, + {"id": 6, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 1, "role": "CTRL", "label": null}, {"idx": 2, "def": 39, "role": "CTRL", "label": null}], "proj": null}, + {"id": 7, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 1}}, + {"id": 8, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 6, "role": "ASSOC", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "10", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 10, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 6, "role": "CTRL", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 12, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 19, "role": "CTRL", "label": null}], "proj": {"par": 19, "idx": 0}}, + {"id": 13, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 19, "role": "CTRL", "label": null}], "proj": {"par": 19, "idx": 1}}, + {"id": 14, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 28, "role": "CTRL", "label": null}], "proj": {"par": 28, "idx": 0}}, + {"id": 15, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 15, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "5", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 18, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 16, "role": "DATA", "label": null}, {"idx": 2, "def": 17, "role": "DATA", "label": null}], "proj": null}, + {"id": 19, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 18, "role": "DATA", "label": null}], "proj": null}, + {"id": 20, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 28, "role": "CTRL", "label": null}], "proj": {"par": 28, "idx": 1}}, + {"id": 26, "label": "6", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 27, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 16, "role": "DATA", "label": null}, {"idx": 2, "def": 26, "role": "DATA", "label": null}], "proj": null}, + {"id": 28, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 13, "role": "CTRL", "label": null}, {"idx": 1, "def": 27, "role": "DATA", "label": null}], "proj": null}, + {"id": 34, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 7, "role": "CTRL", "label": null}, {"idx": 2, "def": 14, "role": "CTRL", "label": null}], "proj": null}, + {"id": 35, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 34, "role": "ASSOC", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 39, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 12, "role": "CTRL", "label": null}, {"idx": 2, "def": 20, "role": "CTRL", "label": null}], "proj": null}, + {"id": 40, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 34, "role": "CTRL", "label": null}, {"idx": 1, "def": 35, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 6, "par": 0, "nodes": [5, 6, 7, 8, 10, 11, 12, 13, 14, 18, 19, 20, 27, 28, 39]} + ] +} diff --git a/chapter08/docs/08-graph1.svg b/chapter08/docs/08-graph1.svg index 0f23a746..67630205 100644 --- a/chapter08/docs/08-graph1.svg +++ b/chapter08/docs/08-graph1.svg @@ -1,359 +1,174 @@ - - - - - - -chapter08 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return40 - -Return - - - -Stop3->Return40 - - -0 - - - -Loop6 - -Loop - - - -Loop6->Start2:p0 - - -1 - - - -Region39 - -Region - - - -Loop6->Region39 - - -2 - - - -Phi_arg8 - -φ_arg - - - -Phi_arg8->Start2:p1 - - -1 - - - -Phi_arg8->Loop6 - - -0 - - - -Add16 - -+ - - - -Con_9 - -10 - - - -LT10 - -< - - - -LT10->Phi_arg8 - - -1 - - - -LT10->Con_9 - - -2 - - - -If11 - - -If - - - -True - - -False - - - -If11->Loop6 - - -0 - - - -If11->LT10 - - -1 - - - -Con_15 - -1 - - - -Add16->Phi_arg8 - - - -1 - - - -Add16->Con_15 - - -2 - - - -Con_17 - -5 - - - -EQ18 - -== - - - -EQ18->Add16 - - -1 - - - -EQ18->Con_17 - - -2 - - - -If19 - - -If - - - -True - - -False - - - -If19->If11:p0 - - -0 - - - -If19->EQ18 - - -1 - - - -Con_26 - -6 - - - -EQ27 - -== - - - -EQ27->Add16 - - - -1 - - - -EQ27->Con_26 - - -2 - - - -If28 - - -If - - - -True - - -False - - - -If28->If19:p1 - - -0 - - - -If28->EQ27 - - -1 - - - -Region34 - -Region - - - -Region34->If11:p1 - - -1 - - - -Region34->If28:p0 - - -2 - - - -Phi_arg35 - -φ_arg - - - -Phi_arg35->Phi_arg8 - - -1 - - - -Phi_arg35->Add16 - -2 - - - -Phi_arg35->Region34 - - -0 - - - -Region39->If19:p0 - - -1 - - - -Region39->If28:p1 - - -2 - - - -Return40->Region34 - - -0 - - - -Return40->Phi_arg35 - - -1 - - - +#3[0] → #40 · CTRL#6[1] → #1 · CTRL#6[2] → #39 · CTRL#8[1] → #4 · DATA#8[2] → #16 · DATA#10[1] → #8 · DATA#10[2] → #9 · DATA#11[0] → #6 · CTRL#11[1] → #10 · DATA#16[1] → #8 · DATA#16[2] → #15 · DATA#18[1] → #16 · DATA#18[2] → #17 · DATA#19[0] → #5 · CTRL#19[1] → #18 · DATA#27[1] → #16 · DATA#27[2] → #26 · DATA#28[0] → #13 · CTRL#28[1] → #27 · DATA#34[1] → #7 · CTRL#34[2] → #14 · CTRL#35[1] → #8 · DATA#35[2] → #16 · DATA#39[1] → #12 · CTRL#39[2] → #20 · CTRL#40[0] → #34 · CTRL#40[1] → #35 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #40 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #11 +Type not computed + +[0] → #11 CTRLLoop  #6#6 Loop +Type not computed + +[0] → — DATA +[1] → #1 CTRL +[2] → #39 CTRL012False  #7/1#7 False +Projection 1 of #11 +Type not computed + +[0] → #11 CTRLφ_arg  #8#8 φ_arg +Type not computed + +[0] → #6 ASSOC +[1] → #4 DATA +[2] → #16 DATA[0] → #601210  #9#9 10 +Type not computed + +<  #10#10 < +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #9 DATA012If  #11#11 If +Type not computed + +[0] → #6 CTRL +[1] → #10 DATA01True  #12/0#12 True +Projection 0 of #19 +Type not computed + +[0] → #19 CTRLFalse  #13/1#13 False +Projection 1 of #19 +Type not computed + +[0] → #19 CTRLTrue  #14/0#14 True +Projection 0 of #28 +Type not computed + +[0] → #28 CTRL1  #15#15 1 +Type not computed + ++  #16#16 + +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #15 DATA0125  #17#17 5 +Type not computed + +==  #18#18 == +Type not computed + +[0] → — DATA +[1] → #16 DATA +[2] → #17 DATA012If  #19#19 If +Type not computed + +[0] → #5 CTRL +[1] → #18 DATA01False  #20/1#20 False +Projection 1 of #28 +Type not computed + +[0] → #28 CTRL6  #26#26 6 +Type not computed + +==  #27#27 == +Type not computed + +[0] → — DATA +[1] → #16 DATA +[2] → #26 DATA012If  #28#28 If +Type not computed + +[0] → #13 CTRL +[1] → #27 DATA01Region  #34#34 Region +Type not computed + +[0] → — DATA +[1] → #7 CTRL +[2] → #14 CTRL012φ_arg  #35#35 φ_arg +Type not computed + +[0] → #34 ASSOC +[1] → #8 DATA +[2] → #16 DATA[0] → #34012Region  #39#39 Region +Type not computed + +[0] → — DATA +[1] → #12 CTRL +[2] → #20 CTRL012Return  #40#40 Return +Type not computed + +[0] → #34 CTRL +[1] → #35 DATA01Loop  #6Loop · 15 nodes−Fold region diff --git a/chapter08/docs/08-graph2.json b/chapter08/docs/08-graph2.json new file mode 100644 index 00000000..6f25aaad --- /dev/null +++ b/chapter08/docs/08-graph2.json @@ -0,0 +1,39 @@ +{ + "ver": 1, + "comp": "chapter08/docs/08-graph2.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 39, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 0}}, + {"id": 6, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 1, "role": "CTRL", "label": null}, {"idx": 2, "def": 38, "role": "CTRL", "label": null}], "proj": null}, + {"id": 7, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 1}}, + {"id": 8, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 6, "role": "ASSOC", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "10", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 10, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 6, "role": "CTRL", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 12, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 19, "role": "CTRL", "label": null}], "proj": {"par": 19, "idx": 0}}, + {"id": 13, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 19, "role": "CTRL", "label": null}], "proj": {"par": 19, "idx": 1}}, + {"id": 14, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 28, "role": "CTRL", "label": null}], "proj": {"par": 28, "idx": 0}}, + {"id": 15, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 15, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "5", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 18, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 16, "role": "DATA", "label": null}, {"idx": 2, "def": 17, "role": "DATA", "label": null}], "proj": null}, + {"id": 19, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 18, "role": "DATA", "label": null}], "proj": null}, + {"id": 20, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 28, "role": "CTRL", "label": null}], "proj": {"par": 28, "idx": 1}}, + {"id": 26, "label": "6", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 27, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 16, "role": "DATA", "label": null}, {"idx": 2, "def": 26, "role": "DATA", "label": null}], "proj": null}, + {"id": 28, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 13, "role": "CTRL", "label": null}, {"idx": 1, "def": 27, "role": "DATA", "label": null}], "proj": null}, + {"id": 34, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 12, "role": "CTRL", "label": null}, {"idx": 2, "def": 14, "role": "CTRL", "label": null}], "proj": null}, + {"id": 38, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 34, "role": "CTRL", "label": null}, {"idx": 2, "def": 20, "role": "CTRL", "label": null}], "proj": null}, + {"id": 39, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 7, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 6, "par": 0, "nodes": [5, 6, 7, 8, 10, 11, 16]}, + {"id": 19, "par": 6, "nodes": [12, 13, 14, 18, 19, 20, 27, 28, 34, 38]} + ] +} diff --git a/chapter08/docs/08-graph2.svg b/chapter08/docs/08-graph2.svg index 1f497470..be8bd367 100644 --- a/chapter08/docs/08-graph2.svg +++ b/chapter08/docs/08-graph2.svg @@ -1,332 +1,169 @@ - - - - - - -chapter08 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return39 - -Return - - - -Stop3->Return39 - - -0 - - - -Loop6 - -Loop - - - -Loop6->Start2:p0 - - -1 - - - -Region38 - -Region - - - -Loop6->Region38 - - -2 - - - -Phi_arg8 - -φ_arg - - - -Phi_arg8->Start2:p1 - - -1 - - - -Phi_arg8->Loop6 - - -0 - - - -Add16 - -+ - - - -Con_9 - -10 - - - -LT10 - -< - - - -LT10->Phi_arg8 - - -1 - - - -LT10->Con_9 - - -2 - - - -If11 - - -If - - - -True - - -False - - - -If11->Loop6 - - -0 - - - -If11->LT10 - - -1 - - - -Con_15 - -1 - - - -Add16->Phi_arg8 - - - -1 - - - -Add16->Con_15 - - -2 - - - -Con_17 - -5 - - - -EQ18 - -== - - - -EQ18->Add16 - - -1 - - - -EQ18->Con_17 - - -2 - - - -If19 - - -If - - - -True - - -False - - - -If19->If11:p0 - - -0 - - - -If19->EQ18 - - -1 - - - -Con_26 - -6 - - - -EQ27 - -== - - - -EQ27->Add16 - - -1 - - - -EQ27->Con_26 - - -2 - - - -If28 - - -If - - - -True - - -False - - - -If28->If19:p1 - - -0 - - - -If28->EQ27 - - -1 - - - -Region34 - -Region - - - -Region34->If19:p0 - - -1 - - - -Region34->If28:p0 - - -2 - - - -Region38->If28:p1 - - -2 - - - -Region38->Region34 - - -1 - - - -Return39->Phi_arg8 - - -1 - - - -Return39->If11:p1 - - -0 - - - +#3[0] → #39 · CTRL#6[1] → #1 · CTRL#6[2] → #38 · CTRL#8[1] → #4 · DATA#8[2] → #16 · DATA#10[1] → #8 · DATA#10[2] → #9 · DATA#11[0] → #6 · CTRL#11[1] → #10 · DATA#16[1] → #8 · DATA#16[2] → #15 · DATA#18[1] → #16 · DATA#18[2] → #17 · DATA#19[0] → #5 · CTRL#19[1] → #18 · DATA#27[1] → #16 · DATA#27[2] → #26 · DATA#28[0] → #13 · CTRL#28[1] → #27 · DATA#34[1] → #12 · CTRL#34[2] → #14 · CTRL#38[1] → #34 · CTRL#38[2] → #20 · CTRL#39[0] → #7 · CTRL#39[1] → #8 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #39 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #11 +Type not computed + +[0] → #11 CTRLLoop  #6#6 Loop +Type not computed + +[0] → — DATA +[1] → #1 CTRL +[2] → #38 CTRL012False  #7/1#7 False +Projection 1 of #11 +Type not computed + +[0] → #11 CTRLφ_arg  #8#8 φ_arg +Type not computed + +[0] → #6 ASSOC +[1] → #4 DATA +[2] → #16 DATA[0] → #601210  #9#9 10 +Type not computed + +<  #10#10 < +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #9 DATA012If  #11#11 If +Type not computed + +[0] → #6 CTRL +[1] → #10 DATA01True  #12/0#12 True +Projection 0 of #19 +Type not computed + +[0] → #19 CTRLFalse  #13/1#13 False +Projection 1 of #19 +Type not computed + +[0] → #19 CTRLTrue  #14/0#14 True +Projection 0 of #28 +Type not computed + +[0] → #28 CTRL1  #15#15 1 +Type not computed + ++  #16#16 + +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #15 DATA0125  #17#17 5 +Type not computed + +==  #18#18 == +Type not computed + +[0] → — DATA +[1] → #16 DATA +[2] → #17 DATA012If  #19#19 If +Type not computed + +[0] → #5 CTRL +[1] → #18 DATA01False  #20/1#20 False +Projection 1 of #28 +Type not computed + +[0] → #28 CTRL6  #26#26 6 +Type not computed + +==  #27#27 == +Type not computed + +[0] → — DATA +[1] → #16 DATA +[2] → #26 DATA012If  #28#28 If +Type not computed + +[0] → #13 CTRL +[1] → #27 DATA01Region  #34#34 Region +Type not computed + +[0] → — DATA +[1] → #12 CTRL +[2] → #14 CTRL012Region  #38#38 Region +Type not computed + +[0] → — DATA +[1] → #34 CTRL +[2] → #20 CTRL012Return  #39#39 Return +Type not computed + +[0] → #7 CTRL +[1] → #8 DATA01Loop  #6Loop · 17 nodes−Fold regionIf  #19If · 10 nodes−Fold region diff --git a/chapter08/docs/08-graph3.json b/chapter08/docs/08-graph3.json new file mode 100644 index 00000000..a795c51d --- /dev/null +++ b/chapter08/docs/08-graph3.json @@ -0,0 +1,40 @@ +{ + "ver": 1, + "comp": "chapter08/docs/08-graph3.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 39, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 0}}, + {"id": 6, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 1, "role": "CTRL", "label": null}, {"idx": 2, "def": 20, "role": "CTRL", "label": null}], "proj": null}, + {"id": 7, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 1}}, + {"id": 8, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 6, "role": "ASSOC", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "10", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 10, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 6, "role": "CTRL", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 12, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 19, "role": "CTRL", "label": null}], "proj": {"par": 19, "idx": 0}}, + {"id": 13, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 19, "role": "CTRL", "label": null}], "proj": {"par": 19, "idx": 1}}, + {"id": 14, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 30, "role": "CTRL", "label": null}], "proj": {"par": 30, "idx": 0}}, + {"id": 15, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 16, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 15, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "5", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 18, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 16, "role": "DATA", "label": null}, {"idx": 2, "def": 17, "role": "DATA", "label": null}], "proj": null}, + {"id": 19, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 18, "role": "DATA", "label": null}], "proj": null}, + {"id": 20, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 30, "role": "CTRL", "label": null}], "proj": {"par": 30, "idx": 1}}, + {"id": 25, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 7, "role": "CTRL", "label": null}, {"idx": 2, "def": 12, "role": "CTRL", "label": null}], "proj": null}, + {"id": 26, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 25, "role": "ASSOC", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 28, "label": "6", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 29, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 16, "role": "DATA", "label": null}, {"idx": 2, "def": 28, "role": "DATA", "label": null}], "proj": null}, + {"id": 30, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 13, "role": "CTRL", "label": null}, {"idx": 1, "def": 29, "role": "DATA", "label": null}], "proj": null}, + {"id": 36, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 25, "role": "CTRL", "label": null}, {"idx": 2, "def": 14, "role": "CTRL", "label": null}], "proj": null}, + {"id": 37, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 36, "role": "ASSOC", "label": null}, {"idx": 1, "def": 26, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 39, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 36, "role": "CTRL", "label": null}, {"idx": 1, "def": 37, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 6, "par": 0, "nodes": [5, 6, 7, 8, 10, 11, 12, 13, 14, 18, 19, 20, 29, 30]} + ] +} diff --git a/chapter08/docs/08-graph3.svg b/chapter08/docs/08-graph3.svg index 12aafcc5..d2c78bc5 100644 --- a/chapter08/docs/08-graph3.svg +++ b/chapter08/docs/08-graph3.svg @@ -1,386 +1,179 @@ - - - - - - -chapter08 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return39 - -Return - - - -Stop3->Return39 - - -0 - - - -Loop6 - -Loop - - - -Loop6->Start2:p0 - - -1 - - - -If30 - - -If - - - -True - - -False - - - -Loop6->If30:p1 - - -2 - - - -Phi_arg8 - -φ_arg - - - -Phi_arg8->Start2:p1 - - -1 - - - -Phi_arg8->Loop6 - - -0 - - - -Add16 - -+ - - - -Con_9 - -10 - - - -LT10 - -< - - - -LT10->Phi_arg8 - - -1 - - - -LT10->Con_9 - - -2 - - - -If11 - - -If - - - -True - - -False - - - -If11->Loop6 - - -0 - - - -If11->LT10 - - -1 - - - -Con_15 - -1 - - - -Add16->Phi_arg8 - - - -1 - - - -Add16->Con_15 - - -2 - - - -Con_17 - -5 - - - -EQ18 - -== - - - -EQ18->Add16 - - -1 - - - -EQ18->Con_17 - - -2 - - - -If19 - - -If - - - -True - - -False - - - -If19->If11:p0 - - -0 - - - -If19->EQ18 - - -1 - - - -Region25 - -Region - - - -Region25->If11:p1 - - -1 - - - -Region25->If19:p0 - - -2 - - - -Phi_arg26 - -φ_arg - - - -Phi_arg26->Phi_arg8 - - -1 - - - -Phi_arg26->Add16 - - -2 - - - -Phi_arg26->Region25 - - -0 - - - -Con_28 - -6 - - - -EQ29 - -== - - - -EQ29->Add16 - - -1 - - - -EQ29->Con_28 - - -2 - - - -If30->If19:p1 - - -0 - - - -If30->EQ29 - - -1 - - - -Region36 - -Region - - - -Region36->Region25 - - -1 - - - -Region36->If30:p0 - - -2 - - - -Phi_arg37 - -φ_arg - - - -Phi_arg37->Add16 - - -2 - - - -Phi_arg37->Phi_arg26 - - -1 - - - -Phi_arg37->Region36 - - -0 - - - -Return39->Region36 - - -0 - - - -Return39->Phi_arg37 - - -1 - - - +#3[0] → #39 · CTRL#6[1] → #1 · CTRL#6[2] → #20 · CTRL#8[1] → #4 · DATA#8[2] → #16 · DATA#10[1] → #8 · DATA#10[2] → #9 · DATA#11[0] → #6 · CTRL#11[1] → #10 · DATA#16[1] → #8 · DATA#16[2] → #15 · DATA#18[1] → #16 · DATA#18[2] → #17 · DATA#19[0] → #5 · CTRL#19[1] → #18 · DATA#25[1] → #7 · CTRL#25[2] → #12 · CTRL#26[1] → #8 · DATA#26[2] → #16 · DATA#29[1] → #16 · DATA#29[2] → #28 · DATA#30[0] → #13 · CTRL#30[1] → #29 · DATA#36[1] → #25 · CTRL#36[2] → #14 · CTRL#37[1] → #26 · DATA#37[2] → #16 · DATA#39[0] → #36 · CTRL#39[1] → #37 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #39 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #11 +Type not computed + +[0] → #11 CTRLLoop  #6#6 Loop +Type not computed + +[0] → — DATA +[1] → #1 CTRL +[2] → #20 CTRL012False  #7/1#7 False +Projection 1 of #11 +Type not computed + +[0] → #11 CTRLφ_arg  #8#8 φ_arg +Type not computed + +[0] → #6 ASSOC +[1] → #4 DATA +[2] → #16 DATA[0] → #601210  #9#9 10 +Type not computed + +<  #10#10 < +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #9 DATA012If  #11#11 If +Type not computed + +[0] → #6 CTRL +[1] → #10 DATA01True  #12/0#12 True +Projection 0 of #19 +Type not computed + +[0] → #19 CTRLFalse  #13/1#13 False +Projection 1 of #19 +Type not computed + +[0] → #19 CTRLTrue  #14/0#14 True +Projection 0 of #30 +Type not computed + +[0] → #30 CTRL1  #15#15 1 +Type not computed + ++  #16#16 + +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #15 DATA0125  #17#17 5 +Type not computed + +==  #18#18 == +Type not computed + +[0] → — DATA +[1] → #16 DATA +[2] → #17 DATA012If  #19#19 If +Type not computed + +[0] → #5 CTRL +[1] → #18 DATA01False  #20/1#20 False +Projection 1 of #30 +Type not computed + +[0] → #30 CTRLRegion  #25#25 Region +Type not computed + +[0] → — DATA +[1] → #7 CTRL +[2] → #12 CTRL012φ_arg  #26#26 φ_arg +Type not computed + +[0] → #25 ASSOC +[1] → #8 DATA +[2] → #16 DATA[0] → #250126  #28#28 6 +Type not computed + +==  #29#29 == +Type not computed + +[0] → — DATA +[1] → #16 DATA +[2] → #28 DATA012If  #30#30 If +Type not computed + +[0] → #13 CTRL +[1] → #29 DATA01Region  #36#36 Region +Type not computed + +[0] → — DATA +[1] → #25 CTRL +[2] → #14 CTRL012φ_arg  #37#37 φ_arg +Type not computed + +[0] → #36 ASSOC +[1] → #26 DATA +[2] → #16 DATA[0] → #36012Return  #39#39 Return +Type not computed + +[0] → #36 CTRL +[1] → #37 DATA01Loop  #6Loop · 14 nodes−Fold region diff --git a/chapter08/docs/Makefile b/chapter08/docs/Makefile index 12659b8f..6fa0f057 100644 --- a/chapter08/docs/Makefile +++ b/chapter08/docs/Makefile @@ -1,12 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter09/README.md b/chapter09/README.md index d3b55a19..2a9abe4e 100644 --- a/chapter09/README.md +++ b/chapter09/README.md @@ -1,17 +1,19 @@ # Chapter 9: Global Value Numbering and Iterative Peepholes +[Previous: Chapter 8](../chapter08/README.md) | +[Next: Chapter 10a](../chapter10a/README.md) + # Table of Contents 1. [Engineering Peepholes](#engineering-peepholes) 2. [Global Value Numbering](#global-value-numbering) 3. [Post-Parse Iterative Peepholes](#post-parse-iterative-peepholes) 4. [Distant Neighbors](#distant-neighbors) -5. [Identification of Basic Blocks in SoN graph](#identification-of-basic-blocks-in-son-graph) -6. [Other Concerns](#other-concerns) -7. [Common SubExpressions via GVN](#common-subexpressions-via-gvn) - - [Example 1](#example-1) - - [Example 2](#example-2) -8. [Post Parse Iterative Optimizations](#post-parse-iterative-optimizations) +5. [Other Concerns](#other-concerns) +6. [Common SubExpressions via GVN](#common-subexpressions-via-gvn) + - [Example 1](#example-1) + - [Example 2](#example-2) +7. [Post Parse Iterative Optimizations](#post-parse-iterative-optimizations) You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter09) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch and [compare](https://github.com/SeaOfNodes/Simple/compare/linear-chapter08...linear-chapter09) it to the previous chapter. @@ -41,7 +43,7 @@ opcode and inputs. If two Nodes do the same function on the same inputs, they get the same result - and can be shared. * We add a global static hash table `GVN` in Node. -* We add a `Node.equals` call. Two Nodes are equals if they have the same +* We add a `Node.equals` call. Two Nodes are equal if they have the same opcode - same Java class - on the same inputs. * We add a `hashCode` on the Node opcode (proxy: Node string name) and inputs. * `ConstantNode` and a few others need some extra custom bits here: the @@ -50,8 +52,7 @@ get the same result - and can be shared. Note the intentional *value* equality here. In many places in Simple we use *reference* equality - e.g. node/edge maintenance is via reference equality, not -value equality, so e.g. the `Utils.find()` call finds via reference. Through -out the Simple project whenever a Node lookup is happening, beware if its via +value equality, so e.g. the `Utils.find()` call finds via reference. Throughout the Simple project whenever a Node lookup is happening, beware if it's via *value* or *reference* equality; this is not always explicitly called out but should be obvious from context. @@ -72,7 +73,7 @@ remove the Node from `GVN` first, before modifying the edges. "edge-locked" and IS in `GVN`. * The `hashCode` function uses the cached hash if available and disallows an accidental zero hash. -* We add a `unlock()` call to remove a Node from `GVN` before any edge is +* We add an `unlock()` call to remove a Node from `GVN` before any edge is changed. This is inserted in front of all calls which hack Node edges. All edge modify code paths already ensure the Node is re-peepholed, and during this revisit the Node will get re-inserted in the `GVN` table. @@ -112,19 +113,19 @@ Rinse, Repeat until the worklist runs dry. The main issues we have to deal with: * Nodes have uses; replacing some set of Nodes with another requires more graph - reworking. Not rocket science, but it can be fiddly. Its helpful to have a + reworking. Not rocket science, but it can be fiddly. It's helpful to have a small set of graph munging utilities, and the strong invariant that the graph is stable and correct between peepholes. In our case `Node.subsume` does most of the munging, building on our prior stable Node utilities. -* Changing a Node also changes the graph "neighborhood". The neigbors need to +* Changing a Node also changes the graph "neighborhood". The neighbors need to be checked to see if THEY can also peephole, and so on. After any peephole - or graph update we put a Nodes uses and defs on the worklist. + or graph update we put a Node's uses and defs on the worklist. * Our strong invariant is that for all Nodes, either they are on the worklist OR no peephole applies. This invariant is easy to check, although expensive. Basically the normal "iterate peepholes to a fixed point" is linear, and this - check is linear at each peephole step... so quadratic overall. Its a useful + check is linear at each peephole step... so quadratic overall. It's a useful assert, but one we can disable once the overall algorithm is stable - and then turn it back on again when some new set of peepholes is misbehaving. The code for this is turned on in `IterPeeps.iterate` as `assert @@ -143,11 +144,11 @@ Updating "B" throws the dependent list ("this") onto the "todo" list. An example of a distant neighbor check is in `AddNode`, where we check for stacked constants: `(Add (Add x 2) 1)` and we'd like `(Add x 3)` instead. Suppose we're doing this check and we find instead `(Add (Phi (Add x 2) self) -1)` The check naturally bails out at the `Phi` since its not an `Add`, but the +1)` The check naturally bails out at the `Phi` since it's not an `Add`, but the `(Phi y self)` only has one unique input, and will itself peephole to `y` eventually. When it does, our stacked `Add` peephole can apply. So the failing Add peephole calls `phi.addDep(Add)` and registers a dependency on the -`Phi`. If the `Phi` indeed later optimizes, we add its depencencies (e.g. the +`Phi`. If the `Phi` indeed later optimizes, we add its dependencies (e.g. the `Add`) back on our `IterPeeps` worklist and retry the stacked Add peephole. The general rule is: @@ -173,7 +174,7 @@ In this chapter we trigger on following patterns Changes: -* We add a `ArrayList _deps` field to Node; initially null. +* We add an `ArrayList _deps` field to Node; initially null. * Some peepholes (see above) add dependencies if they fail a remote check, by calling `distant.addDep(this)`. The `addDep` call creates `_deps` and filters for various kinds of duplicate adds. @@ -191,7 +192,7 @@ There are more issues we will want to deal with in a later Chapter: - Dead infinite loops often lead to infinite peephole cycles... if only we would get around to working on the "base" of the dead loop it would fold up. - - Some peepholes naturally reduce the graph directly; while some keeps its + - Some peepholes naturally reduce the graph directly; while some keep its size the same but reduce other things (e.g. swapping a Mul-by-2 with a Shift), and we might end up with a few which try to grow the graph briefly before collapsing. @@ -211,15 +212,15 @@ There are more issues we will want to deal with in a later Chapter: many peep patterns might go quadratic if approached from one end or another, because they modify something then push it back onto the list where it immediately gets pulled again. I.e., you end up spinning in a loop repeating - the same peeps while slowly migrating a e.g. left-spine add-tree into a - right-spine add-tree. A psuedo-random pull uses randomization to defeat bad + the same peeps while slowly migrating e.g. left-spine add-tree into a + right-spine add-tree. A pseudo-random pull uses randomization to defeat bad peep patterns. * Why isn't `IterPeeps` just passing over all of the Nodes once or twice, instead of using a worklist with the `addDeps` mechanism? We could even visit them in a defs-before-uses order (e.g. Reverse Post Order). - In the absense of loops exactly one such pass will find all local peepholes, + In the absence of loops exactly one such pass will find all local peepholes, and indeed the Parser already does this. However, this will fail to find opportunities at loops and farther remote cases - and to get those peepholes around loops will require another visit. It is easy to construct a case @@ -249,7 +250,7 @@ else { return x; ``` -Prior to GVN, this would result in following graph. Note that the `arg+arg` is translated to `arg*2`. +Prior to GVN, this would result in the following graph. Note that the `arg+arg` is translated to `arg*2`. ![Graph1](./docs/09-graph1.svg) @@ -269,8 +270,8 @@ Without GVN the peepholes cannot see that both sides of the subtraction have the ![Graph3](./docs/09-graph3.svg) -- Each multiplication(*) node has two edges going to `arg`. -- In the example above, we fused them to make the graph more readable. +- Each multiplication(*) node has two edges going to `arg`. +- The input-slot labels distinguish these two uses of the same definition. With GVN, the peepholes can do a better job: @@ -290,7 +291,7 @@ return arg; ``` While parsing the `while` loop it is not yet known that `step` is a constant and will not change. Therefore, -without the post parse optimization we get following: +without the post parse optimization we get the following: ![Graph5](./docs/09-graph5.svg) diff --git a/chapter09/docs/09-graph1.json b/chapter09/docs/09-graph1.json new file mode 100644 index 00000000..746d4de2 --- /dev/null +++ b/chapter09/docs/09-graph1.json @@ -0,0 +1,28 @@ +{ + "ver": 1, + "comp": "chapter09/docs/09-graph1.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 18, "role": "CTRL", "label": null}, {"idx": 1, "def": 24, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 0}}, + {"id": 6, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 1}}, + {"id": 7, "label": "2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "*", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "10", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 10, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 16, "label": "2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 17, "label": "*", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 18, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 17, "role": "DATA", "label": null}], "proj": null}, + {"id": 20, "label": "1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 21, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 20, "role": "DATA", "label": null}], "proj": null}, + {"id": 24, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 6, "role": "CTRL", "label": null}, {"idx": 1, "def": 21, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter09/docs/09-graph1.svg b/chapter09/docs/09-graph1.svg index fce8d53c..e639b36b 100644 --- a/chapter09/docs/09-graph1.svg +++ b/chapter09/docs/09-graph1.svg @@ -1,222 +1,130 @@ - - - - - - -chapter08 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return18 - -Return - - - -Stop3->Return18 - - -0 - - - -Return24 - -Return - - - -Stop3->Return24 - - -1 - - - -Con_7 - -2 - - - -Mul8 - -* - - - -Mul8->Start2:p1 - - -1 - - - -Mul8->Con_7 - - -2 - - - -Con_9 - -10 - - - -LT10 - -< - - - -LT10->Start2:p1 - - -1 - - - -LT10->Con_9 - - -2 - - - -If11 - - -If - - - -True - - -False - - - -If11->Start2:p0 - - -0 - - - -If11->LT10 - - -1 - - - -Con_16 - -2 - - - -Mul17 - -* - - - -Mul17->Start2:p1 - - -1 - - - -Mul17->Con_16 - - -2 - - - -Return18->If11:p0 - - -0 - - - -Return18->Mul17 - - -1 - - - -Con_20 - -1 - - - -Add21 - -+ - - - -Add21->Mul8 - - -1 - - - -Add21->Con_20 - - -2 - - - -Return24->If11:p1 - - -0 - - - -Return24->Add21 - - -1 - - - +#3[0] → #18 · CTRL#3[1] → #24 · CTRL#8[1] → #4 · DATA#8[2] → #7 · DATA#10[1] → #4 · DATA#10[2] → #9 · DATA#11[0] → #1 · CTRL#11[1] → #10 · DATA#17[1] → #4 · DATA#17[2] → #16 · DATA#18[0] → #5 · CTRL#18[1] → #17 · DATA#21[1] → #8 · DATA#21[2] → #20 · DATA#24[0] → #6 · CTRL#24[1] → #21 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #18 CTRL +[1] → #24 CTRL01arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #11 +Type not computed + +[0] → #11 CTRLFalse  #6/1#6 False +Projection 1 of #11 +Type not computed + +[0] → #11 CTRL2  #7#7 2 +Type not computed + +*  #8#8 * +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #7 DATA01210  #9#9 10 +Type not computed + +<  #10#10 < +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #9 DATA012If  #11#11 If +Type not computed + +[0] → #1 CTRL +[1] → #10 DATA012  #16#16 2 +Type not computed + +*  #17#17 * +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #16 DATA012Return  #18#18 Return +Type not computed + +[0] → #5 CTRL +[1] → #17 DATA011  #20#20 1 +Type not computed + ++  #21#21 + +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #20 DATA012Return  #24#24 Return +Type not computed + +[0] → #6 CTRL +[1] → #21 DATA01 diff --git a/chapter09/docs/09-graph2.json b/chapter09/docs/09-graph2.json new file mode 100644 index 00000000..5b449041 --- /dev/null +++ b/chapter09/docs/09-graph2.json @@ -0,0 +1,26 @@ +{ + "ver": 1, + "comp": "chapter09/docs/09-graph2.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 18, "role": "CTRL", "label": null}, {"idx": 1, "def": 24, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 0}}, + {"id": 6, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}], "proj": {"par": 11, "idx": 1}}, + {"id": 7, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "*", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "#10", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 11, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 18, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}], "proj": null}, + {"id": 20, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}, {"idx": 2, "def": 21, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 24, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 6, "role": "CTRL", "label": null}, {"idx": 1, "def": 20, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter09/docs/09-graph2.svg b/chapter09/docs/09-graph2.svg index 111ec172..a2484f5c 100644 --- a/chapter09/docs/09-graph2.svg +++ b/chapter09/docs/09-graph2.svg @@ -1,196 +1,122 @@ - - - - - - -chapter09 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return18 - -Return - - - -Stop3->Return18 - - -0 - - - -Return24 - -Return - - - -Stop3->Return24 - - -1 - - - -Con_7 - -#2 - - - -Mul8 - -* - - - -Mul8->Start2:p1 - - -1 - - - -Mul8->Con_7 - - -2 - - - -LT9 - -< - - - -LT9->Start2:p1 - - -1 - - - -Con_10 - -#10 - - - -LT9->Con_10 - - -2 - - - -If11 - - -If - - - -True - - -False - - - -If11->Start2:p0 - - -0 - - - -If11->LT9 - - -1 - - - -Return18->Mul8 - - -1 - - - -Return18->If11:p0 - - -0 - - - -Add20 - -+ - - - -Add20->Mul8 - - -1 - - - -Con_21 - -#1 - - - -Add20->Con_21 - - -2 - - - -Return24->If11:p1 - - -0 - - - -Return24->Add20 - - -1 - - - +#3[0] → #18 · CTRL#3[1] → #24 · CTRL#8[1] → #4 · DATA#8[2] → #7 · DATA#9[1] → #4 · DATA#9[2] → #10 · DATA#11[0] → #1 · CTRL#11[1] → #9 · DATA#18[0] → #5 · CTRL#18[1] → #8 · DATA#20[1] → #8 · DATA#20[2] → #21 · DATA#24[0] → #6 · CTRL#24[1] → #20 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #18 CTRL +[1] → #24 CTRL01arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #11 +Type not computed + +[0] → #11 CTRLFalse  #6/1#6 False +Projection 1 of #11 +Type not computed + +[0] → #11 CTRL#2  #7#7 #2 +Type not computed + +*  #8#8 * +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #7 DATA012<  #9#9 < +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #10 DATA012#10  #10#10 #10 +Type not computed + +If  #11#11 If +Type not computed + +[0] → #1 CTRL +[1] → #9 DATA01Return  #18#18 Return +Type not computed + +[0] → #5 CTRL +[1] → #8 DATA01+  #20#20 + +Type not computed + +[0] → — DATA +[1] → #8 DATA +[2] → #21 DATA012#1  #21#21 #1 +Type not computed + +Return  #24#24 Return +Type not computed + +[0] → #6 CTRL +[1] → #20 DATA01 diff --git a/chapter09/docs/09-graph3.json b/chapter09/docs/09-graph3.json new file mode 100644 index 00000000..57546e51 --- /dev/null +++ b/chapter09/docs/09-graph3.json @@ -0,0 +1,19 @@ +{ + "ver": 1, + "comp": "chapter09/docs/09-graph3.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 9, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 6, "label": "*", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 7, "label": "*", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 8, "label": "-", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "DATA", "label": null}, {"idx": 2, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 9, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 8, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter09/docs/09-graph3.svg b/chapter09/docs/09-graph3.svg index f26c96e8..51804b59 100644 --- a/chapter09/docs/09-graph3.svg +++ b/chapter09/docs/09-graph3.svg @@ -1,109 +1,96 @@ - - - - - - -chapter08 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return9 - -Return - - - -Stop3->Return9 - - -0 - - - -Mul6 - -* - - - -Mul6->Start2:p1 - - -1 - - - -Mul7 - -* - - - -Mul7->Start2:p1 - - -1 - - - -Sub8 - -- - - - -Sub8->Mul6 - - -1 - - - -Sub8->Mul7 - - -2 - - - -Return9->Start2:p0 - - -0 - - - -Return9->Sub8 - - -1 - - - +#3[0] → #9 · CTRL#6[1] → #4 · DATA#6[2] → #4 · DATA#7[1] → #4 · DATA#7[2] → #4 · DATA#8[1] → #6 · DATA#8[2] → #7 · DATA#9[0] → #1 · CTRL#9[1] → #8 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #9 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATA*  #6#6 * +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #4 DATA012*  #7#7 * +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #4 DATA012-  #8#8 - +Type not computed + +[0] → — DATA +[1] → #6 DATA +[2] → #7 DATA012Return  #9#9 Return +Type not computed + +[0] → #1 CTRL +[1] → #8 DATA01 diff --git a/chapter09/docs/09-graph4.json b/chapter09/docs/09-graph4.json new file mode 100644 index 00000000..accad3ff --- /dev/null +++ b/chapter09/docs/09-graph4.json @@ -0,0 +1,16 @@ +{ + "ver": 1, + "comp": "chapter09/docs/09-graph4.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 10, "role": "CTRL", "label": null}], "proj": null}, + {"id": 9, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 10, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter09/docs/09-graph4.svg b/chapter09/docs/09-graph4.svg index 4eef5414..89045214 100644 --- a/chapter09/docs/09-graph4.svg +++ b/chapter09/docs/09-graph4.svg @@ -1,67 +1,80 @@ - - - - - - -chapter09 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - - - -Stop3 - -Stop - - - -Return10 - -Return - - - -Stop3->Return10 - - -0 - - - -Con_9 - -#0 - - - -Return10->Start2:p0 - - -0 - - - -Return10->Con_9 - - -1 - - - +#3[0] → #10 · CTRL#10[0] → #1 · CTRL#10[1] → #9 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #10 CTRL0#0  #9#9 #0 +Type not computed + +Return  #10#10 Return +Type not computed + +[0] → #1 CTRL +[1] → #9 DATA01 diff --git a/chapter09/docs/09-graph5.json b/chapter09/docs/09-graph5.json new file mode 100644 index 00000000..31957bfa --- /dev/null +++ b/chapter09/docs/09-graph5.json @@ -0,0 +1,27 @@ +{ + "ver": 1, + "comp": "chapter09/docs/09-graph5.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 21, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}], "proj": {"par": 12, "idx": 0}}, + {"id": 6, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 7, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 1, "role": "CTRL", "label": null}, {"idx": 2, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 8, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}], "proj": {"par": 12, "idx": 1}}, + {"id": 9, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 7, "role": "ASSOC", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 18, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}, {"idx": 2, "def": 11, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "#10", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 12, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 7, "role": "CTRL", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 16, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "DATA", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 18, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 16, "role": "DATA", "label": null}, {"idx": 2, "def": 6, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 7, "par": 0, "nodes": [5, 7, 8, 9, 10, 12, 16, 18]} + ] +} diff --git a/chapter09/docs/09-graph5.svg b/chapter09/docs/09-graph5.svg index 9d0698db..7457cb38 100644 --- a/chapter09/docs/09-graph5.svg +++ b/chapter09/docs/09-graph5.svg @@ -1,210 +1,124 @@ - - - - - - -chapter09 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return21 - -Return - - - -Stop3->Return21 - - -0 - - - -Con_6 - -#1 - - - -Loop7 - -Loop - - - -Loop7->Start2:p0 - - -1 - - - -If12 - - -If - - - -True - - -False - - - -Loop7->If12:p0 - - -2 - - - -Phi_arg9 - -φ_arg - - - -Phi_arg9->Start2:p1 - - -1 - - - -Phi_arg9->Loop7 - - -0 - - - -Add18 - -+ - - - -Phi_arg9->Add18 - - -2 - - - -LT10 - -< - - - -LT10->Phi_arg9 - - -1 - - - -Con_11 - -#10 - - - -LT10->Con_11 - - -2 - - - -If12->Loop7 - - -0 - - - -If12->LT10 - - -1 - - - -Add16 - -+ - - - -Add16->Con_6 - - -1 - - - -Add16->Phi_arg9 - - -2 - - - -Add18->Con_6 - - -2 - - - -Add18->Add16 - - -1 - - - -Return21->Phi_arg9 - - -1 - - - -Return21->If12:p1 - - -0 - - - +#3[0] → #21 · CTRL#7[1] → #1 · CTRL#7[2] → #5 · CTRL#9[1] → #4 · DATA#9[2] → #18 · DATA#10[1] → #9 · DATA#10[2] → #11 · DATA#12[0] → #7 · CTRL#12[1] → #10 · DATA#16[1] → #6 · DATA#16[2] → #9 · DATA#18[1] → #16 · DATA#18[2] → #6 · DATA#21[0] → #8 · CTRL#21[1] → #9 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #21 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #12 +Type not computed + +[0] → #12 CTRL#1  #6#6 #1 +Type not computed + +Loop  #7#7 Loop +Type not computed + +[0] → — DATA +[1] → #1 CTRL +[2] → #5 CTRL012False  #8/1#8 False +Projection 1 of #12 +Type not computed + +[0] → #12 CTRLφ_arg  #9#9 φ_arg +Type not computed + +[0] → #7 ASSOC +[1] → #4 DATA +[2] → #18 DATA[0] → #7012<  #10#10 < +Type not computed + +[0] → — DATA +[1] → #9 DATA +[2] → #11 DATA012#10  #11#11 #10 +Type not computed + +If  #12#12 If +Type not computed + +[0] → #7 CTRL +[1] → #10 DATA01+  #16#16 + +Type not computed + +[0] → — DATA +[1] → #6 DATA +[2] → #9 DATA012+  #18#18 + +Type not computed + +[0] → — DATA +[1] → #16 DATA +[2] → #6 DATA012Return  #21#21 Return +Type not computed + +[0] → #8 CTRL +[1] → #9 DATA01Loop  #7Loop · 8 nodes−Fold region diff --git a/chapter09/docs/09-graph6.json b/chapter09/docs/09-graph6.json new file mode 100644 index 00000000..09fa1202 --- /dev/null +++ b/chapter09/docs/09-graph6.json @@ -0,0 +1,26 @@ +{ + "ver": 1, + "comp": "chapter09/docs/09-graph6.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 21, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 5, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}], "proj": {"par": 12, "idx": 0}}, + {"id": 6, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}], "proj": {"par": 12, "idx": 1}}, + {"id": 7, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 1, "role": "CTRL", "label": null}, {"idx": 2, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 9, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 7, "role": "ASSOC", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 25, "role": "DATA", "label": null}], "proj": null}, + {"id": 10, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}, {"idx": 2, "def": 11, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "#10", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 12, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 7, "role": "CTRL", "label": null}, {"idx": 1, "def": 10, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 6, "role": "CTRL", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 24, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 25, "label": "+", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 9, "role": "DATA", "label": null}, {"idx": 2, "def": 24, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 7, "par": 0, "nodes": [5, 6, 7, 9, 10, 12, 25]} + ] +} diff --git a/chapter09/docs/09-graph6.svg b/chapter09/docs/09-graph6.svg index 36c70099..2d530c46 100644 --- a/chapter09/docs/09-graph6.svg +++ b/chapter09/docs/09-graph6.svg @@ -1,184 +1,119 @@ - - - - - - -chapter09 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -arg - - - -Stop3 - -Stop - - - -Return21 - -Return - - - -Stop3->Return21 - - -0 - - - -Loop7 - -Loop - - - -Loop7->Start2:p0 - - -1 - - - -If12 - - -If - - - -True - - -False - - - -Loop7->If12:p0 - - -2 - - - -Phi_arg9 - -φ_arg - - - -Phi_arg9->Start2:p1 - - -1 - - - -Phi_arg9->Loop7 - - -0 - - - -Add25 - -+ - - - -LT10 - -< - - - -LT10->Phi_arg9 - - -1 - - - -Con_11 - -#10 - - - -LT10->Con_11 - - -2 - - - -If12->Loop7 - - -0 - - - -If12->LT10 - - -1 - - - -Return21->Phi_arg9 - - -1 - - - -Return21->If12:p1 - - -0 - - - -Con_24 - -#2 - - - -Add25->Phi_arg9 - - - -1 - - - -Add25->Con_24 - - -2 - - - +#3[0] → #21 · CTRL#7[1] → #1 · CTRL#7[2] → #5 · CTRL#9[1] → #4 · DATA#9[2] → #25 · DATA#10[1] → #9 · DATA#10[2] → #11 · DATA#12[0] → #7 · CTRL#12[1] → #10 · DATA#21[0] → #6 · CTRL#21[1] → #9 · DATA#25[1] → #9 · DATA#25[2] → #24 · DATA$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #21 CTRL0arg  #4/1#4 arg +Projection 1 of #2 +Type not computed + +[0] → #2 DATATrue  #5/0#5 True +Projection 0 of #12 +Type not computed + +[0] → #12 CTRLFalse  #6/1#6 False +Projection 1 of #12 +Type not computed + +[0] → #12 CTRLLoop  #7#7 Loop +Type not computed + +[0] → — DATA +[1] → #1 CTRL +[2] → #5 CTRL012φ_arg  #9#9 φ_arg +Type not computed + +[0] → #7 ASSOC +[1] → #4 DATA +[2] → #25 DATA[0] → #7012<  #10#10 < +Type not computed + +[0] → — DATA +[1] → #9 DATA +[2] → #11 DATA012#10  #11#11 #10 +Type not computed + +If  #12#12 If +Type not computed + +[0] → #7 CTRL +[1] → #10 DATA01Return  #21#21 Return +Type not computed + +[0] → #6 CTRL +[1] → #9 DATA01#2  #24#24 #2 +Type not computed + ++  #25#25 + +Type not computed + +[0] → — DATA +[1] → #9 DATA +[2] → #24 DATA012Loop  #7Loop · 7 nodes−Fold region diff --git a/chapter09/docs/Makefile b/chapter09/docs/Makefile index 12659b8f..6fa0f057 100644 --- a/chapter09/docs/Makefile +++ b/chapter09/docs/Makefile @@ -1,12 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter10a/README.md b/chapter10a/README.md index 80a1f46c..b9ea258a 100644 --- a/chapter10a/README.md +++ b/chapter10a/README.md @@ -45,7 +45,7 @@ are `{ctrl, $mem, result}`. The memory edge is a dependency, not a copy of the heap. The graph determines the legal execution order. In hardware, a Store updates physical memory -directly. In the evaluator, a Store updates an objects' attached memory array. +directly. In the evaluator, a Store updates an object's attached memory array. ## Memory is an SSA variable @@ -269,7 +269,7 @@ If `bar` is `null` then we would like `!bar` to evaluate to `true`. In the else branch we know `bar` is not null, hence the assignment to `bar.a` should be allowed. -To enable this behaviour, we make following enhancements. +To enable this behaviour, we make the following enhancements. * We track the null-ness of a pointer in the Type system, and hence in every Node that ptr type flows through. @@ -286,7 +286,7 @@ To enable this behaviour, we make following enhancements. * The up-cast is represented by the `CastNode` op, and if applicable, we replace all occurrences of the original predicate with the up-cast in the - current scope. The change is local to each branch of the `If`; occuring + current scope. The change is local to each branch of the `If`; occurring separately for the true and the false branches of the `If` (and the false branch inverts the predicate). @@ -295,7 +295,7 @@ To enable this behaviour, we make following enhancements. and `CastNode`. * When computing a type for Not, we produce an Integer type when its input is a - ptr. When the input is a `null` we convert to `1` and when is a not `null` + ptr. When the input is a `null` we convert to `1` and when it is a non-null ptr value, we convert to `0`. See `NotNode.compute()`. diff --git a/chapter10a/docs/example1.gv b/chapter10a/docs/example1.gv index d399b562..9585b8e4 100644 --- a/chapter10a/docs/example1.gv +++ b/chapter10a/docs/example1.gv @@ -1,10 +1,16 @@ digraph Memory { + // IR styles match graph/web/render.js; arrows are use -> definition. + graph [bgcolor="#fafbfc" fontname="Helvetica" nodesep=0.35 ranksep=0.55 splines=ortho]; + node [fontname="Helvetica" fontsize=12 color="#758191" fontcolor="#152330" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + edge [fontname="Helvetica" fontsize=9 color="#536477" fontcolor="#364352" arrowsize=0.7 penwidth=1.5]; + rankdir=RL; - node [shape=box]; - M0 [label="Initial memory"]; - X [label="Store p.x = 3"]; - Y [label="Store p.y = arg"]; - L [label="Load p.x"]; - L -> Y -> X -> M0 [color=blue]; - Return -> Y [color=blue]; Return -> L; + + M0 [label="Initial memory" shape=octagon style="filled" fillcolor="#dcecff"]; + X [label="Store p.x = 3" shape=octagon style="filled" fillcolor="#dcecff"]; + Y [label="Store p.y = arg" shape=octagon style="filled" fillcolor="#dcecff"]; + L [label="Load p.x" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + L -> Y -> X -> M0 [color="#2867b2"]; + Return -> Y [color="#2867b2"]; Return -> L; + Return [shape=box style="filled" fillcolor="#fff1c4"]; } diff --git a/chapter10a/docs/example1.svg b/chapter10a/docs/example1.svg index d1c5e3bd..fdb4864c 100644 --- a/chapter10a/docs/example1.svg +++ b/chapter10a/docs/example1.svg @@ -4,70 +4,70 @@ - - + + Memory - + M0 - -Initial memory + +Initial memory X - -Store p.x = 3 + +Store p.x = 3 X->M0 - - + + Y - -Store p.y = arg + +Store p.y = arg Y->X - - + + L - -Load p.x + +Load p.x L->Y - - + + Return - -Return + +Return Return->Y - - + + Return->L - - + + diff --git a/chapter10a/docs/example2a.gv b/chapter10a/docs/example2a.gv index ec5afbdc..93a8a904 100644 --- a/chapter10a/docs/example2a.gv +++ b/chapter10a/docs/example2a.gv @@ -1,10 +1,17 @@ digraph Memory { + // IR styles match graph/web/render.js; arrows are use -> definition. + graph [bgcolor="#fafbfc" fontname="Helvetica" nodesep=0.35 ranksep=0.55 splines=ortho]; + node [fontname="Helvetica" fontsize=12 color="#758191" fontcolor="#152330" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + edge [fontname="Helvetica" fontsize=9 color="#536477" fontcolor="#364352" arrowsize=0.7 penwidth=1.5]; + rankdir=RL; - node [shape=box]; - M [label="Incoming memory"]; - A [label="True: Store x"]; - B [label="False: Store y"]; - P [label="Phi(memory)"]; - P -> A -> M [color=blue]; P -> B -> M [color=blue]; - P -> Region [style=dashed]; Return -> P [color=blue]; + + M [label="Incoming memory" shape=octagon style="filled" fillcolor="#dcecff"]; + A [label="True: Store x" shape=octagon style="filled" fillcolor="#dcecff"]; + B [label="False: Store x" shape=octagon style="filled" fillcolor="#dcecff"]; + P [label="Phi(memory)" shape=hexagon style="filled" fillcolor="#f5e4fa"]; + P -> A -> M [color="#2867b2"]; P -> B -> M [color="#2867b2"]; + P -> Region [style=dashed,color="#9396a3"]; Return -> P [color="#2867b2"]; + Return [shape=box style="filled" fillcolor="#fff1c4"]; + Region [shape=trapezium style="filled" fillcolor="#fff1c4"]; } diff --git a/chapter10a/docs/example2a.svg b/chapter10a/docs/example2a.svg index f9a9b4fd..f0bbf531 100644 --- a/chapter10a/docs/example2a.svg +++ b/chapter10a/docs/example2a.svg @@ -4,82 +4,82 @@ - - + + Memory - + M - -Incoming memory + +Incoming memory A - -True: Store x + +True: Store x A->M - - + + B - -False: Store y + +False: Store x B->M - - + + P - -Phi(memory) + +Phi(memory) P->A - - + + P->B - - + + Region - -Region + +Region P->Region - - + + Return - -Return + +Return Return->P - - + + diff --git a/chapter10a/docs/example2b.gv b/chapter10a/docs/example2b.gv index 3f3309e5..c7d64509 100644 --- a/chapter10a/docs/example2b.gv +++ b/chapter10a/docs/example2b.gv @@ -1,11 +1,19 @@ digraph Memory { + // IR styles match graph/web/render.js; arrows are use -> definition. + graph [bgcolor="#fafbfc" fontname="Helvetica" nodesep=0.35 ranksep=0.55 splines=ortho]; + node [fontname="Helvetica" fontsize=12 color="#758191" fontcolor="#152330" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + edge [fontname="Helvetica" fontsize=9 color="#536477" fontcolor="#364352" arrowsize=0.7 penwidth=1.5]; + rankdir=RL; - node [shape=box]; - P [label="Phi(memory)"]; - S [label="Loop-body Store"]; - P -> Entry [color=blue]; - P -> S [color=blue,constraint=false]; // Backedge must not place Store before Phi. - S -> P [color=blue]; - P -> Loop [style=dashed]; Return -> P [color=blue]; + + P [label="Phi(memory)" shape=hexagon style="filled" fillcolor="#f5e4fa"]; + S [label="Loop-body Store" shape=octagon style="filled" fillcolor="#dcecff"]; + P -> Entry [color="#2867b2"]; + P -> S [color="#2867b2",constraint=false]; // Backedge must not place Store before Phi. + S -> P [color="#2867b2"]; + P -> Loop [style=dashed,color="#9396a3"]; Return -> P [color="#2867b2"]; Return -> S [style=invis]; // Layout only: Phi, Store, Return from left to right. + Return [shape=box style="filled" fillcolor="#fff1c4"]; + Entry [shape=octagon style="filled" fillcolor="#dcecff"]; + Loop [shape=box style="rounded,filled" fillcolor="#ffe0ab"]; } diff --git a/chapter10a/docs/example2b.svg b/chapter10a/docs/example2b.svg index 8fff33d4..77ebec85 100644 --- a/chapter10a/docs/example2b.svg +++ b/chapter10a/docs/example2b.svg @@ -4,70 +4,70 @@ - - + + Memory - + P - -Phi(memory) + +Phi(memory) S - -Loop-body Store + +Loop-body Store P->S - - + + Entry - -Entry + +Entry P->Entry - - + + Loop - -Loop + +Loop P->Loop - - + + S->P - - + + Return - -Return + +Return Return->P - - + + diff --git a/chapter10a/docs/example2c.gv b/chapter10a/docs/example2c.gv index ef8a5fc8..f3a52b4d 100644 --- a/chapter10a/docs/example2c.gv +++ b/chapter10a/docs/example2c.gv @@ -1,9 +1,14 @@ digraph Memory { + // IR styles match graph/web/render.js; arrows are use -> definition. + graph [bgcolor="#fafbfc" fontname="Helvetica" nodesep=0.35 ranksep=0.55 splines=ortho]; + node [fontname="Helvetica" fontsize=12 color="#758191" fontcolor="#152330" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + edge [fontname="Helvetica" fontsize=9 color="#536477" fontcolor="#364352" arrowsize=0.7 penwidth=1.5]; + rankdir=RL; - node [shape=box]; - M [label="Prior memory"]; - L [label="Load p.x"]; - S [label="Store p.x"]; - L -> M [color=blue]; S -> M [color=blue]; - S -> L [style=dashed,label="execute load first"]; + + M [label="Prior memory" shape=octagon style="filled" fillcolor="#dcecff"]; + L [label="Load p.x" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + S [label="Store p.x" shape=octagon style="filled" fillcolor="#dcecff"]; + L -> M [color="#2867b2"]; S -> M [color="#2867b2"]; + S -> L [style=dashed,xlabel="execute load first"]; } diff --git a/chapter10a/docs/example2c.svg b/chapter10a/docs/example2c.svg index c7b37912..2aa8fa2d 100644 --- a/chapter10a/docs/example2c.svg +++ b/chapter10a/docs/example2c.svg @@ -4,47 +4,47 @@ - - + + Memory - + M - -Prior memory + +Prior memory L - -Load p.x + +Load p.x L->M - - + + S - -Store p.x + +Store p.x S->M - - + + S->L - - -execute load first + + +execute load first diff --git a/chapter10a/docs/lattice.gv b/chapter10a/docs/lattice.gv index 733a5287..eb4d7fb1 100644 --- a/chapter10a/docs/lattice.gv +++ b/chapter10a/docs/lattice.gv @@ -69,7 +69,7 @@ digraph Lattice { STRUCT_BOT [label="⊥:struct\n[struct bottom]"]; STRUCT_PERSON [label="Person\nage: int", shape=box]; STRUCT_S1 [label="s1\nx: int", shape=box]; - STRUCT_S2 [label="s2\nx: int, y: *s1", shape=box]; + STRUCT_S2 [label="s2\nx: int, y: int", shape=box]; STRUCT_MORE [label="…", shape=box]; {rank=same; STRUCT_PERSON; STRUCT_S1; STRUCT_S2; STRUCT_MORE;} STRUCT_PERSON -> STRUCT_S1 -> STRUCT_S2 -> STRUCT_MORE [style=invis]; diff --git a/chapter10a/docs/lattice.svg b/chapter10a/docs/lattice.svg index 24c0de8c..c8bed535 100644 --- a/chapter10a/docs/lattice.svg +++ b/chapter10a/docs/lattice.svg @@ -4,122 +4,122 @@ - - + + Lattice - + cluster_control - -Control + +Control cluster_integer - -Integer + +Integer cluster_pointer - -Pointer = nullability × struct type + +Pointer = nullability × struct type cluster_struct - -Struct -named collection of named scalar types + +Struct +named collection of named scalar types cluster_memory - -Memory + +Memory cluster_tuple - -Tuple -collection of types + +Tuple +collection of types TOP - -⊤ + +⊤ XCTRL - -⊤:ctrl + +⊤:ctrl TOP->XCTRL - - + + INT_TOP - -⊤:int + +⊤:int TOP->INT_TOP - - + + PTR_TOP - -⊤:ptr -[*⊤:struct] + +⊤:ptr +[*⊤:struct] TOP->PTR_TOP - - + + STRUCT_TOP - -⊤:struct -[struct top] + +⊤:struct +[struct top] TOP->STRUCT_TOP - - + + MEM_TOP - -⊤:mem + +⊤:mem TOP->MEM_TOP - - + + TUPLE_TOP - -⊤:tuple + +⊤:tuple TOP->TUPLE_TOP - - + + @@ -136,8 +136,8 @@ XCTRL->CTRL - - + + @@ -155,8 +155,8 @@ INT_TOP->INT_NEG - - + + @@ -167,8 +167,8 @@ INT_TOP->INT_ZERO - - + + @@ -179,8 +179,8 @@ INT_TOP->INT_POS - - + + @@ -218,51 +218,50 @@ PTR_NULL - -null -[*⊤:struct?] + +null PTR_TOP->PTR_NULL - - + + PTR_PERSON - -*Person + +*Person PTR_TOP->PTR_PERSON - - + + PTR_S1 - -*s1 + +*s1 PTR_TOP->PTR_S1 - - + + PTR_MORE - -*s2, … + +*s2, … PTR_TOP->PTR_MORE - - + + @@ -287,8 +286,8 @@ PTR_NULL->PTR_PERSON_NIL - - + + @@ -299,8 +298,8 @@ PTR_NULL->PTR_S1_NIL - - + + @@ -311,8 +310,8 @@ PTR_NULL->PTR_MORE_NIL - - + + @@ -331,41 +330,41 @@ PTR_PERSON->PTR_ANY - - + + PTR_PERSON->PTR_PERSON_NIL - - + + PTR_S1->PTR_ANY - - + + PTR_S1->PTR_S1_NIL - - + + PTR_MORE->PTR_ANY - - + + PTR_MORE->PTR_MORE_NIL - - + + @@ -397,8 +396,8 @@ STRUCT_TOP->STRUCT_PERSON - - + + @@ -410,8 +409,8 @@ STRUCT_TOP->STRUCT_S1 - - + + @@ -423,8 +422,8 @@ STRUCT_TOP->STRUCT_S2 - - + + @@ -435,8 +434,8 @@ STRUCT_TOP->STRUCT_MORE - - + + @@ -488,8 +487,8 @@ MEM_TOP->MEM_BOT - - + + @@ -501,38 +500,38 @@ TUPLE1 - -(type) + +(type) TUPLE_TOP->TUPLE1 - - + + TUPLE2 - -(type, type) + +(type, type) TUPLE_TOP->TUPLE2 - - + + TUPLEN - -(type, …) + +(type, …) TUPLE_TOP->TUPLEN - - + + @@ -549,22 +548,22 @@ TUPLE1->TUPLE_BOT - - + + TUPLE2->TUPLE_BOT - - + + TUPLEN->TUPLE_BOT - - + + diff --git a/chapter10b/README.md b/chapter10b/README.md index dfdf74d5..671d53c3 100644 --- a/chapter10b/README.md +++ b/chapter10b/README.md @@ -171,11 +171,10 @@ alias to become known later, using the same representation. Its private constructor memory, escape tracking, incomplete types, and module alias remapping are separate extensions and are not needed here. -Chapters 11-15 use this representation, including alias-specific load/store +Chapters 11-24 use this representation, including alias-specific load/store anti-dependencies. Chapter 15 adds allocation with partial memory and typed -alias contents. Chapters 16-24 currently retain their older parser-managed -memory chains; forwarding through those snapshots is tracked in the -[backport queue](../docs/chapter-backports.md). +alias contents. Chapter 16 extends initialization to constructor values, and +Chapter 18 carries whole memory across function calls. ## Build and test diff --git a/chapter10b/docs/example1.gv b/chapter10b/docs/example1.gv index 0b0a5feb..5e059d77 100644 --- a/chapter10b/docs/example1.gv +++ b/chapter10b/docs/example1.gv @@ -1,13 +1,20 @@ digraph Memory { + // IR styles match graph/web/render.js; arrows are use -> definition. + graph [bgcolor="#fafbfc" fontname="Helvetica" nodesep=0.35 ranksep=0.55 splines=ortho]; + node [fontname="Helvetica" fontsize=12 color="#758191" fontcolor="#152330" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + edge [fontname="Helvetica" fontsize=9 color="#536477" fontcolor="#364352" arrowsize=0.7 penwidth=1.5]; + rankdir=BT; - node [shape=box]; - M [label="Initial memory"]; - X [label="Store x = 42"]; - Y [label="Loop: Store y"]; - L [label="Load x (42)"]; - L -> X -> M [color=blue]; Y -> M [color=green]; - MemMerge -> X [color=blue]; MemMerge -> Y [color=green]; - Return -> MemMerge; Return -> L; + + M [label="Initial memory" shape=octagon style="filled" fillcolor="#dcecff"]; + X [label="Store x = 42" shape=octagon style="filled" fillcolor="#dcecff"]; + Y [label="Loop: Store y" shape=octagon style="filled" fillcolor="#dcecff"]; + L [label="Load x (42)" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + L -> X -> M [color="#2867b2"]; Y -> M [color="#2867b2"]; + MemMerge -> X [color="#2867b2"]; MemMerge -> Y [color="#2867b2"]; + Return -> MemMerge [color="#2867b2"]; Return -> L; { rank=same; MemMerge -> L [style=invis]; } Y -> X [style=invis]; // Layout only: keep the stores in code order. + Return [shape=box style="filled" fillcolor="#fff1c4"]; + MemMerge [shape=octagon style="filled" fillcolor="#dcecff"]; } diff --git a/chapter10b/docs/example1.svg b/chapter10b/docs/example1.svg index 384b6e12..f0b57612 100644 --- a/chapter10b/docs/example1.svg +++ b/chapter10b/docs/example1.svg @@ -4,90 +4,90 @@ - - + + Memory - + M - -Initial memory + +Initial memory X - -Store x = 42 + +Store x = 42 X->M - - + + Y - -Loop: Store y + +Loop: Store y Y->M - - + + L - -Load x (42) + +Load x (42) L->X - - + + MemMerge - -MemMerge + +MemMerge MemMerge->X - - + + MemMerge->Y - - + + Return - -Return + +Return Return->L - - + + Return->MemMerge - - + + diff --git a/chapter10b/docs/example2a.gv b/chapter10b/docs/example2a.gv index d92eea41..187e63b9 100644 --- a/chapter10b/docs/example2a.gv +++ b/chapter10b/docs/example2a.gv @@ -1,10 +1,17 @@ digraph Memory { + // IR styles match graph/web/render.js; arrows are use -> definition. + graph [bgcolor="#fafbfc" fontname="Helvetica" nodesep=0.35 ranksep=0.55 splines=ortho]; + node [fontname="Helvetica" fontsize=12 color="#758191" fontcolor="#152330" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + edge [fontname="Helvetica" fontsize=9 color="#536477" fontcolor="#364352" arrowsize=0.7 penwidth=1.5]; + rankdir=RL; - node [shape=box]; - M [label="Default memory"]; - X [label="Store x"]; - Y [label="Store y"]; - X -> M [color=blue]; Y -> M [color=green]; - MemMerge -> M [label="default"]; MemMerge -> X [label="x",color=blue]; - MemMerge -> Y [label="y",color=green]; Return -> MemMerge; + + M [label="Default memory" shape=octagon style="filled" fillcolor="#dcecff"]; + X [label="Store x" shape=octagon style="filled" fillcolor="#dcecff"]; + Y [label="Store y" shape=octagon style="filled" fillcolor="#dcecff"]; + X -> M [color="#2867b2"]; Y -> M [color="#2867b2"]; + MemMerge -> M [xlabel="default",color="#2867b2"]; MemMerge -> X [xlabel="x",color="#2867b2"]; + MemMerge -> Y [xlabel="y",color="#2867b2"]; Return -> MemMerge [color="#2867b2"]; + Return [shape=box style="filled" fillcolor="#fff1c4"]; + MemMerge [shape=octagon style="filled" fillcolor="#dcecff"]; } diff --git a/chapter10b/docs/example2a.svg b/chapter10b/docs/example2a.svg index 97fb144e..47bc3a8f 100644 --- a/chapter10b/docs/example2a.svg +++ b/chapter10b/docs/example2a.svg @@ -4,79 +4,79 @@ - - + + Memory - + M - -Default memory + +Default memory X - -Store x + +Store x X->M - - + + Y - -Store y + +Store y Y->M - - + + MemMerge - -MemMerge + +MemMerge MemMerge->M - - -default + + +default MemMerge->X - - -x + + +x MemMerge->Y - - -y + + +y Return - -Return + +Return Return->MemMerge - - + + diff --git a/chapter10b/docs/example2b.gv b/chapter10b/docs/example2b.gv index 4ddd36b5..39b87a6a 100644 --- a/chapter10b/docs/example2b.gv +++ b/chapter10b/docs/example2b.gv @@ -1,10 +1,19 @@ digraph Memory { + // IR styles match graph/web/render.js; arrows are use -> definition. + graph [bgcolor="#fafbfc" fontname="Helvetica" nodesep=0.35 ranksep=0.55 splines=ortho]; + node [fontname="Helvetica" fontsize=12 color="#758191" fontcolor="#152330" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + edge [fontname="Helvetica" fontsize=9 color="#536477" fontcolor="#364352" arrowsize=0.7 penwidth=1.5]; + rankdir=RL; - node [shape=box]; - P [label="MemPhi(x)"]; - B [label="BulkMemPhi(All except x)"]; - P -> Left [label="slice x",color=blue]; P -> Right [label="slice x",color=blue]; - B -> Left; B -> Right; - P -> Region [style=dashed]; B -> Region [style=dashed]; - MemMerge -> P [label="x",color=blue]; MemMerge -> B [label="default"]; + + P [label="MemPhi(x)" shape=hexagon style="filled" fillcolor="#f5e4fa"]; + B [label="BulkMemPhi(All except x)" shape=hexagon style="filled" fillcolor="#f5e4fa"]; + P -> Left [xlabel="slice x",color="#2867b2"]; P -> Right [xlabel="slice x",color="#2867b2"]; + B -> Left [color="#2867b2"]; B -> Right [color="#2867b2"]; + P -> Region [style=dashed,color="#9396a3"]; B -> Region [style=dashed,color="#9396a3"]; + MemMerge -> P [xlabel="x",color="#2867b2"]; MemMerge -> B [xlabel="default",color="#2867b2"]; + MemMerge [shape=octagon style="filled" fillcolor="#dcecff"]; + Left [shape=octagon style="filled" fillcolor="#dcecff"]; + Right [shape=octagon style="filled" fillcolor="#dcecff"]; + Region [shape=trapezium style="filled" fillcolor="#fff1c4"]; } diff --git a/chapter10b/docs/example2b.svg b/chapter10b/docs/example2b.svg index 4e0616f1..cb10b90b 100644 --- a/chapter10b/docs/example2b.svg +++ b/chapter10b/docs/example2b.svg @@ -4,98 +4,98 @@ - - + + Memory - + P - -MemPhi(x) + +MemPhi(x) Left - -Left + +Left P->Left - - -slice x + + +slice x Right - -Right + +Right P->Right - - -slice x + + +slice x Region - -Region + +Region P->Region - - + + B - -BulkMemPhi(All except x) + +BulkMemPhi(All except x) B->Left - - + + B->Right - - + + B->Region - - + + MemMerge - -MemMerge + +MemMerge MemMerge->P - - -x + + +x MemMerge->B - - -default + + +default diff --git a/chapter10b/docs/example2c.gv b/chapter10b/docs/example2c.gv index 4fae3bba..b32d186d 100644 --- a/chapter10b/docs/example2c.gv +++ b/chapter10b/docs/example2c.gv @@ -1,10 +1,15 @@ digraph Memory { + // IR styles match graph/web/render.js; arrows are use -> definition. + graph [bgcolor="#fafbfc" fontname="Helvetica" nodesep=0.35 ranksep=0.55 splines=ortho]; + node [fontname="Helvetica" fontsize=12 color="#758191" fontcolor="#152330" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + edge [fontname="Helvetica" fontsize=9 color="#536477" fontcolor="#364352" arrowsize=0.7 penwidth=1.5]; + rankdir=RL; - node [shape=box]; - M [label="Prior x memory"]; - L [label="Load p.x"]; - S [label="Store p.x"]; - L -> M [color=blue]; S -> M [color=blue]; - S -> L [style=dashed,label="execute load first"]; - Y [label="Store p.y: independent"]; + + M [label="Prior x memory" shape=octagon style="filled" fillcolor="#dcecff"]; + L [label="Load p.x" shape=box style="rounded,filled" fillcolor="#edf3f7"]; + S [label="Store p.x" shape=octagon style="filled" fillcolor="#dcecff"]; + L -> M [color="#2867b2"]; S -> M [color="#2867b2"]; + S -> L [style=dashed,xlabel="execute load first"]; + Y [label="Store p.y: independent" shape=octagon style="filled" fillcolor="#dcecff"]; } diff --git a/chapter10b/docs/example2c.svg b/chapter10b/docs/example2c.svg index 8249d677..531fabfe 100644 --- a/chapter10b/docs/example2c.svg +++ b/chapter10b/docs/example2c.svg @@ -4,53 +4,53 @@ - - + + Memory - + M - -Prior x memory + +Prior x memory L - -Load p.x + +Load p.x L->M - - + + S - -Store p.x + +Store p.x S->M - - + + S->L - - -execute load first + + +execute load first Y - -Store p.y: independent + +Store p.y: independent diff --git a/chapter10b/docs/lattice.gv b/chapter10b/docs/lattice.gv index f9fb2b09..a37a1738 100644 --- a/chapter10b/docs/lattice.gv +++ b/chapter10b/docs/lattice.gv @@ -69,7 +69,7 @@ digraph Lattice { STRUCT_BOT [label="⊥:struct\n[struct bottom]"]; STRUCT_PERSON [label="Person\nage: int", shape=box]; STRUCT_S1 [label="s1\nx: int", shape=box]; - STRUCT_S2 [label="s2\nx: int, y: *s1", shape=box]; + STRUCT_S2 [label="s2\nx: int, y: int", shape=box]; STRUCT_MORE [label="…", shape=box]; {rank=same; STRUCT_PERSON; STRUCT_S1; STRUCT_S2; STRUCT_MORE;} STRUCT_PERSON -> STRUCT_S1 -> STRUCT_S2 -> STRUCT_MORE [style=invis]; diff --git a/chapter10b/docs/lattice.svg b/chapter10b/docs/lattice.svg index a11452b9..ff554601 100644 --- a/chapter10b/docs/lattice.svg +++ b/chapter10b/docs/lattice.svg @@ -4,11 +4,11 @@ - + Lattice - + cluster_control @@ -26,21 +26,21 @@ cluster_struct - -Struct -named collection of named scalar types + +Struct +named collection of named scalar types cluster_memory - -Memory -precise alias slices + +Memory +precise alias slices cluster_tuple - -Tuple -collection of types + +Tuple +collection of types @@ -101,26 +101,26 @@ MEM_TOP - -⊤:mem + +⊤:mem TOP->MEM_TOP - - + + TUPLE_TOP - -⊤:tuple + +⊤:tuple TOP->TUPLE_TOP - - + + @@ -416,27 +416,27 @@ STRUCT_S2 - -s2 -x: int, y: *s1 + +s2 +x: int, y: int STRUCT_TOP->STRUCT_S2 - - + + STRUCT_MORE - -… + +… STRUCT_TOP->STRUCT_MORE - - + + @@ -469,152 +469,152 @@ STRUCT_S2->STRUCT_BOT - - + + STRUCT_MORE->STRUCT_BOT - - + + MEM_ALIAS2 - -MEM#2 + +MEM#2 MEM_TOP->MEM_ALIAS2 - - + + MEM_ALIAS3 - -MEM#3 + +MEM#3 MEM_TOP->MEM_ALIAS3 - - + + MEM_MORE - -… + +… MEM_TOP->MEM_MORE - - + + MEM_BOT - -⊥:mem + +⊥:mem MEM_BOT->BOT - - + + MEM_ALIAS2->MEM_BOT - - + + MEM_ALIAS3->MEM_BOT - - + + MEM_MORE->MEM_BOT - - + + TUPLE1 - -(type) + +(type) TUPLE_TOP->TUPLE1 - - + + TUPLE2 - -(type, type) + +(type, type) TUPLE_TOP->TUPLE2 - - + + TUPLEN - -(type, …) + +(type, …) TUPLE_TOP->TUPLEN - - + + TUPLE_BOT - -⊥:tuple + +⊥:tuple TUPLE_BOT->BOT - - + + TUPLE1->TUPLE_BOT - - + + TUPLE2->TUPLE_BOT - - + + TUPLEN->TUPLE_BOT - - + + diff --git a/chapter11/README.md b/chapter11/README.md index b91f4fd7..58adbbfb 100644 --- a/chapter11/README.md +++ b/chapter11/README.md @@ -1,5 +1,8 @@ # Chapter 11: Global Code Motion +[Previous: Chapter 10b](../chapter10b/README.md) | +[Next: Chapter 12](../chapter12/README.md) + This chapter schedules the memory representation introduced in [10b](../chapter10b/README.md): one parser-visible `$mem`, with `MemMerge`, `MemPhi`, and `BulkMemPhi` recovering independent field chains. Start supplies @@ -20,7 +23,7 @@ their Region, just like scalar Phis. 1. [High Level Overview](#high-level-overview) 2. [Scheduling Walk Through](#scheduling-walk-through) 3. [Scheduling a Loop](#scheduling-a-loop) -4. [Components of the Global Code Motion Algorithm ](#components-of-the-global-code-motion-algorithm) +4. [Components of the Global Code Motion Algorithm](#components-of-the-global-code-motion-algorithm) 5. [Identification of Basic Blocks in SoN graph](#identification-of-basic-blocks-in-son-graph) 6. [Handling Infinite Loops](#handling-infinite-loops) 7. [Dominators](#dominators) @@ -30,13 +33,12 @@ their Region, just like scalar Phis. 11. [Inserting Anti Dependencies](#inserting-anti-dependencies) 12. [Video Walk Through](#video-walk-through) - You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter11) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch and [compare](https://github.com/SeaOfNodes/Simple/compare/linear-chapter10b...linear-chapter11) it to the previous chapter. The original input source program defines a sequence in which things happen. As we parse the program into Sea of Nodes representation and perform various optimizations, this sequence is not fully maintained. The optimized Sea of Nodes graph is driven more -by dependencies between nodes rather that the sequence of instructions in the original source program. +by dependencies between nodes rather than the sequence of instructions in the original source program. Our goal in this chapter is to look at how we can recover a schedule for executing instructions from an optimized Sea of Nodes graph. This schedule needs to preserve the semantics of the original source program, @@ -85,7 +87,7 @@ if (arg) v.f=1; return i; ``` -First lets look at the graph before scheduling. +First let's look at the graph before scheduling. These walkthrough diagrams show the precise `S.f` chain and the final MemMerge consumed by Return. The unchanged default memory comes from Start; @@ -100,13 +102,13 @@ Observe that * Ditto for Phi nodes which are attached to the Region nodes. * So what remains are the "floating" Data nodes that do not have a control input at this stage. In this example, these are the load `.f` and store `.f=` nodes. -Now, lets look at the graph after we run the early schedule. +Now, let's look at the graph after we run the early schedule. ![Graph2](./docs/graph2.svg) * Observe that the load `.f` and the stores `.f=` now have control edges to the `$ctrl` projection from Start. Thus, the early schedule has put the Data nodes in the first basic block. -* This is because the inputs to these nodes are have the `$ctrl` projection as the immediate dominator. +* This is because the inputs to these nodes have the `$ctrl` projection as the immediate dominator. The graph below shows the schedule post late scheduling. @@ -114,7 +116,7 @@ The graph below shows the schedule post late scheduling. The snip below shows the main changes in the graph: -![Graph3-snip](./docs/graph3-snip.jpg) +![Store ordered after the earlier load](./docs/graph3-snip.svg) * The store `.f=` now has an anti-dependency on the load `.f`; this ensures that the store is scheduled after the load, as required by program semantics. We discuss anti-dependencies in detail later. * Observe also that the store `.f=` is now bound to the True branch of the If node. @@ -168,7 +170,7 @@ We have already alluded to several components of the GCM algorithm in passing ab ## Identification of Basic Blocks in SoN graph -The Sea of Nodes graph already captures the programs control flow graph. This information is implicit in the control nodes and edges from control nodes to other types of nodes. +The Sea of Nodes graph already captures the program's control flow graph. This information is implicit in the control nodes and edges from control nodes to other types of nodes. To recap, Control starts at the Start node, via a projection that is bound to the name `$ctrl`. As the control flows in the program, this name binding gets updated, and control is passed around, until it reaches the Stop node. @@ -204,7 +206,7 @@ while (1) {} return 0; ``` -First lets look at the graph resulting from this: +First let's look at the graph resulting from this: ![Graph7](./docs/graph7.svg) @@ -218,7 +220,7 @@ The implementation is in the Loop node: // If this is an unreachable loop, it may not have an exit. If it does not // (i.e., infinite loop), force an exit to make it reachable. public void forceExit( StopNode stop ) { - // Walk the backedge, then immediate dominator tree util we hit this + // Walk the backedge, then immediate dominator tree until we hit this // Loop again. If we ever hit a CProj from an If (as opposed to // directly on the If) we found our exit. CFGNode x = back(); @@ -332,7 +334,7 @@ class StopNode extends CFGNode { Simple's Sea of Nodes graph identifies loops explicitly via Loop nodes. Since the language provides a single way to create a loop, using the `while` statement, it is not necessary to implement a generic loop discovery process. -We do however need to compute a loop depth. This is done similar to how we compute the dominator depth. +We do however need to compute a loop depth. This is done similarly to how we compute the dominator depth. ```java class CFGNode { @@ -374,7 +376,7 @@ class StopNode extends CFGNode { ## Early Schedule -The GCM algorithm proper starts with the computation of the early schedule, during which do an upward DFS walk on the "inputs" of each Node, starting from the bottom (Stop). We schedule each data node to the +The GCM algorithm proper starts with the computation of the early schedule, during which we do an upward DFS walk on the "inputs" of each Node, starting from the bottom (Stop). We schedule each data node to the first control block where they are dominated by their inputs. A pre-condition of this is to ensure that infinite loops have been "fixed" as described earlier. diff --git a/chapter11/docs/Makefile b/chapter11/docs/Makefile index 055882b2..6fa0f057 100644 --- a/chapter11/docs/Makefile +++ b/chapter11/docs/Makefile @@ -1,14 +1 @@ -GV := $(wildcard *.gv) -SVG := $(patsubst %.gv,%.svg,$(GV)) -.DELETE_ON_ERROR: - -.PHONY: all -all: $(SVG) - -%.svg: %.gv - dot -Tsvg $< > $@ - @sed -i 's/\r$$//' $@ - -.PHONY: clean -clean: - @rm -f $(SVG) +include ../../graph/docs.mk diff --git a/chapter11/docs/graph1.json b/chapter11/docs/graph1.json new file mode 100644 index 00000000..748bdae9 --- /dev/null +++ b/chapter11/docs/graph1.json @@ -0,0 +1,33 @@ +{ + "ver": 1, + "comp": "chapter11/docs/graph1.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 224, "role": "MEM", "label": null}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 5, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 7, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 2}}, + {"id": 8, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}], "proj": {"par": 17, "idx": 0}}, + {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 10, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}], "proj": {"par": 17, "idx": 1}}, + {"id": 11, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 12, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 11, "role": "DATA", "label": null}], "proj": null}, + {"id": 13, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 14, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 12, "role": "MEM", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 16, "label": ".f", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 22, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}], "proj": null}, + {"id": 23, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "CTRL", "label": null}, {"idx": 2, "def": 10, "role": "CTRL", "label": null}], "proj": null}, + {"id": 25, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 23, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 224, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 23, "role": "ASSOC", "label": null}, {"idx": 1, "def": 22, "role": "MEM", "label": null}, {"idx": 2, "def": 14, "role": "MEM", "label": null}], "proj": null} + ], + "groups": [ + {"id": 17, "par": 0, "nodes": [8, 10, 17, 22, 23, 224]} + ] +} diff --git a/chapter11/docs/graph1.svg b/chapter11/docs/graph1.svg index 422d790e..ef4d0293 100644 --- a/chapter11/docs/graph1.svg +++ b/chapter11/docs/graph1.svg @@ -1,306 +1,151 @@ - - - - - - -chapter11 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -$mem - -arg - - - -MemMerge - -MemMerge - - - -MemMerge->Start2:p1 - - -1 - - - -Phi_224 - -MemPhi_2 - - - -MemMerge->Phi_224 - - -2 - - - -Stop3 - -Stop - - - -Return25 - -Return - - - -Stop3->Return25 - - -0 - - - -Con_4 - -#0 - - - -new9 - -new S - - - -new9->Start2:p0 - - -0 - - - -Con_11 - -#2 - - - -Store12 - -.f = - - - -Store12->Start2:p1 - - -1 - - - -Store12->new9 - - -2 - - - -Store12->Con_11 - - -3 - - - -new13 - -new S - - - -new13->Start2:p0 - - -0 - - - -Store14 - -.f = - - - -Store14->Con_4 - - -3 - - - -Store14->Store12 - - -1 - - - -Store14->new13 - - -2 - - - -Load16 - -.f - - - -Load16->new9 - - - -2 - - - -Load16->Store14 - - -1 - - - -If17 - - -If - - - -True - - -False - - - -If17->Start2:p0 - - - -0 - - - -If17->Start2:p2 - - -1 - - - -Con_21 - -#1 - - - -Store22 - -.f = - - - -Store22->new9 - -2 - - - -Store22->Store14 - - -1 - - - -Store22->Con_21 - - -3 - - - -Region23 - -Region - - - -Region23->If17:p0 - - -1 - - - -Phi_224->Store14 - - -2 - - - -Phi_224->Store22 - - -1 - - - -Phi_224->Region23 - - -0 - - - -Return25->MemMerge - - -1 - - - -Return25->Load16 - - -2 - - - -Return25->Region23 - - -0 - - - +#1[1] → #6 · MEM#1[2] → #224 · MEM#3[0] → #25 · CTRL#9[0] → #5 · CTRL#12[1] → #6 · MEM#12[2] → #9 · DATA#12[3] → #11 · DATA#13[0] → #5 · CTRL#14[1] → #12 · MEM#14[2] → #13 · DATA#14[3] → #4 · DATA#16[1] → #14 · MEM#16[2] → #9 · DATA#17[0] → #5 · CTRL#17[1] → #7 · DATA#22[1] → #14 · MEM#22[2] → #9 · DATA#22[3] → #21 · DATA#23[1] → #8 · CTRL#23[2] → #10 · CTRL#25[0] → #23 · CTRL#25[1] → #1 · MEM#25[2] → #16 · DATA#224[1] → #22 · MEM#224[2] → #14 · MEMMemMerge  #1#1 MemMerge +Type not computed + +[0] → — DATA +[1] → #6 MEM +[2] → #224 MEM012Start  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #25 CTRL0#0  #4#4 #0 +Type not computed + +$ctrl  #5/0#5 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRL$mem  #6/1#6 $mem +Projection 1 of #2 +Type not computed + +[0] → #2 MEMarg  #7/2#7 arg +Projection 2 of #2 +Type not computed + +[0] → #2 DATATrue  #8/0#8 True +Projection 0 of #17 +Type not computed + +[0] → #17 CTRLnew S  #9#9 new S +Type not computed + +[0] → #5 CTRL0False  #10/1#10 False +Projection 1 of #17 +Type not computed + +[0] → #17 CTRL#2  #11#11 #2 +Type not computed + +.f =  #12#12 .f = +Type not computed + +[0] → — DATA +[1] → #6 MEM +[2] → #9 DATA +[3] → #11 DATA0123new S  #13#13 new S +Type not computed + +[0] → #5 CTRL0.f =  #14#14 .f = +Type not computed + +[0] → — DATA +[1] → #12 MEM +[2] → #13 DATA +[3] → #4 DATA0123.f  #16#16 .f +Type not computed + +[0] → — DATA +[1] → #14 MEM +[2] → #9 DATA012If  #17#17 If +Type not computed + +[0] → #5 CTRL +[1] → #7 DATA01#1  #21#21 #1 +Type not computed + +.f =  #22#22 .f = +Type not computed + +[0] → — DATA +[1] → #14 MEM +[2] → #9 DATA +[3] → #21 DATA0123Region  #23#23 Region +Type not computed + +[0] → — DATA +[1] → #8 CTRL +[2] → #10 CTRL012Return  #25#25 Return +Type not computed + +[0] → #23 CTRL +[1] → #1 MEM +[2] → #16 DATA012MemPhi_2  #224#224 MemPhi_2 +Type not computed + +[0] → #23 ASSOC +[1] → #22 MEM +[2] → #14 MEM[0] → #23012If  #17If · 6 nodes−Fold region diff --git a/chapter11/docs/graph2.json b/chapter11/docs/graph2.json new file mode 100644 index 00000000..7c50307d --- /dev/null +++ b/chapter11/docs/graph2.json @@ -0,0 +1,33 @@ +{ + "ver": 1, + "comp": "chapter11/docs/graph2.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 23, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 224, "role": "MEM", "label": null}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 5, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 7, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 2}}, + {"id": 8, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}], "proj": {"par": 17, "idx": 0}}, + {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 10, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}], "proj": {"par": 17, "idx": 1}}, + {"id": 11, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 12, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 11, "role": "DATA", "label": null}], "proj": null}, + {"id": 13, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 14, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 12, "role": "MEM", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 16, "label": ".f", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 22, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}], "proj": null}, + {"id": 23, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "CTRL", "label": null}, {"idx": 2, "def": 10, "role": "CTRL", "label": null}], "proj": null}, + {"id": 25, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 23, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 224, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 23, "role": "ASSOC", "label": null}, {"idx": 1, "def": 22, "role": "MEM", "label": null}, {"idx": 2, "def": 14, "role": "MEM", "label": null}], "proj": null} + ], + "groups": [ + {"id": 17, "par": 0, "nodes": [1, 8, 10, 17, 23, 224]} + ] +} diff --git a/chapter11/docs/graph2.svg b/chapter11/docs/graph2.svg index b8d43cc9..a3afd14f 100644 --- a/chapter11/docs/graph2.svg +++ b/chapter11/docs/graph2.svg @@ -1,335 +1,151 @@ - - - - - - -chapter11 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -$mem - -arg - - - -MemMerge - -MemMerge - - - -MemMerge->Start2:p1 - - -1 - - - -Region23 - -Region - - - -MemMerge->Region23 - - -0 - - - -Phi_224 - -MemPhi_2 - - - -MemMerge->Phi_224 - - -2 - - - -Stop3 - -Stop - - - -Return25 - -Return - - - -Stop3->Return25 - - -0 - - - -Con_4 - -#0 - - - -new9 - -new S - - - -new9->Start2:p0 - - -0 - - - -Con_11 - -#2 - - - -Store12 - -.f = - - - -Store12->Start2:p0 - - - -0 - - - -Store12->new9 - - -2 - - - -Store12->Con_11 - - -3 - - - -new13 - -new S - - - -new13->Start2:p0 - - -0 - - - -Store14 - -.f = - - - -Store14->Start2:p0 - - -0 - - - -Store14->Con_4 - - -3 - - - -Store14->Store12 - - -1 - - - -Store14->new13 - - -2 - - - -Load16 - -.f - - - -Load16->Start2:p0 - - - -0 - - - -Load16->new9 - - - -2 - - - -Load16->Store14 - - -1 - - - -If17 - - -If - - - -True - - -False - - - -If17->Start2:p0 - -0 - - - -Con_21 - -#1 - - - -Store22 - -.f = - - - -Store22->Start2:p0 - - -0 - - - -Store22->new9 - -2 - - - -Store22->Store14 - - -1 - - - -Store22->Con_21 - - -3 - - - -Region23->If17:p0 - - -1 - - - -Region23->If17:p1 - - -2 - - - -Phi_224->Store14 - - -2 - - - -Phi_224->Store22 - - -1 - - - -Phi_224->Region23 - - -0 - - - -Return25->MemMerge - - -1 - - - -Return25->Load16 - - - -2 - - - -Return25->Region23 - - -0 - - - +#1[0] → #23 · CTRL#1[1] → #6 · MEM#1[2] → #224 · MEM#3[0] → #25 · CTRL#9[0] → #5 · CTRL#12[0] → #5 · CTRL#12[1] → #6 · MEM#12[2] → #9 · DATA#12[3] → #11 · DATA#13[0] → #5 · CTRL#14[0] → #5 · CTRL#14[1] → #12 · MEM#14[2] → #13 · DATA#14[3] → #4 · DATA#16[0] → #5 · CTRL#16[1] → #14 · MEM#16[2] → #9 · DATA#17[0] → #5 · CTRL#17[1] → #7 · DATA#22[0] → #5 · CTRL#22[1] → #14 · MEM#22[2] → #9 · DATA#22[3] → #21 · DATA#23[1] → #8 · CTRL#23[2] → #10 · CTRL#25[0] → #23 · CTRL#25[1] → #1 · MEM#25[2] → #16 · DATA#224[1] → #22 · MEM#224[2] → #14 · MEMMemMerge  #1#1 MemMerge +Type not computed + +[0] → #23 CTRL +[1] → #6 MEM +[2] → #224 MEM012Start  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #25 CTRL0#0  #4#4 #0 +Type not computed + +$ctrl  #5/0#5 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRL$mem  #6/1#6 $mem +Projection 1 of #2 +Type not computed + +[0] → #2 MEMarg  #7/2#7 arg +Projection 2 of #2 +Type not computed + +[0] → #2 DATATrue  #8/0#8 True +Projection 0 of #17 +Type not computed + +[0] → #17 CTRLnew S  #9#9 new S +Type not computed + +[0] → #5 CTRL0False  #10/1#10 False +Projection 1 of #17 +Type not computed + +[0] → #17 CTRL#2  #11#11 #2 +Type not computed + +.f =  #12#12 .f = +Type not computed + +[0] → #5 CTRL +[1] → #6 MEM +[2] → #9 DATA +[3] → #11 DATA0123new S  #13#13 new S +Type not computed + +[0] → #5 CTRL0.f =  #14#14 .f = +Type not computed + +[0] → #5 CTRL +[1] → #12 MEM +[2] → #13 DATA +[3] → #4 DATA0123.f  #16#16 .f +Type not computed + +[0] → #5 CTRL +[1] → #14 MEM +[2] → #9 DATA012If  #17#17 If +Type not computed + +[0] → #5 CTRL +[1] → #7 DATA01#1  #21#21 #1 +Type not computed + +.f =  #22#22 .f = +Type not computed + +[0] → #5 CTRL +[1] → #14 MEM +[2] → #9 DATA +[3] → #21 DATA0123Region  #23#23 Region +Type not computed + +[0] → — DATA +[1] → #8 CTRL +[2] → #10 CTRL012Return  #25#25 Return +Type not computed + +[0] → #23 CTRL +[1] → #1 MEM +[2] → #16 DATA012MemPhi_2  #224#224 MemPhi_2 +Type not computed + +[0] → #23 ASSOC +[1] → #22 MEM +[2] → #14 MEM[0] → #23012If  #17If · 6 nodes−Fold region diff --git a/chapter11/docs/graph3-snip.json b/chapter11/docs/graph3-snip.json new file mode 100644 index 00000000..00b3e744 --- /dev/null +++ b/chapter11/docs/graph3-snip.json @@ -0,0 +1,20 @@ +{ + "ver": 1, + "comp": "chapter11/docs/graph3-snip.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 5, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 8, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}], "proj": {"par": 17, "idx": 0}}, + {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 14, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 0, "role": "MEM", "label": null}, {"idx": 2, "def": 0, "role": "DATA", "label": null}, {"idx": 3, "def": 0, "role": "DATA", "label": null}], "proj": null}, + {"id": 16, "label": ".f", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 0, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 22, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}, {"idx": 4, "def": 16, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + ] +} diff --git a/chapter11/docs/graph3-snip.svg b/chapter11/docs/graph3-snip.svg new file mode 100644 index 00000000..cf6420c5 --- /dev/null +++ b/chapter11/docs/graph3-snip.svg @@ -0,0 +1,102 @@ +#9[0] → #5 · CTRL#14[0] → #5 · CTRL#16[0] → #5 · CTRL#16[1] → #14 · MEM#16[2] → #9 · DATA#17[0] → #5 · CTRL#22[0] → #8 · CTRL#22[1] → #14 · MEM#22[2] → #9 · DATA#22[3] → #21 · DATA#22[4] → #16 · DATAStart  #2#2 Start +Type not computed + +$ctrl  #5/0#5 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLTrue  #8/0#8 True +Projection 0 of #17 +Type not computed + +[0] → #17 CTRLnew S  #9#9 new S +Type not computed + +[0] → #5 CTRL0.f =  #14#14 .f = +Type not computed + +[0] → #5 CTRL +[1] → — MEM +[2] → — DATA +[3] → — DATA0123.f  #16#16 .f +Type not computed + +[0] → #5 CTRL +[1] → #14 MEM +[2] → #9 DATA012If  #17#17 If +Type not computed + +[0] → #5 CTRL +[1] → — DATA01#1  #21#21 #1 +Type not computed + +.f =  #22#22 .f = +Type not computed + +[0] → #8 CTRL +[1] → #14 MEM +[2] → #9 DATA +[3] → #21 DATA +[4] → #16 DATA01234 diff --git a/chapter11/docs/graph3.json b/chapter11/docs/graph3.json new file mode 100644 index 00000000..998c6f87 --- /dev/null +++ b/chapter11/docs/graph3.json @@ -0,0 +1,33 @@ +{ + "ver": 1, + "comp": "chapter11/docs/graph3.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 23, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 224, "role": "MEM", "label": null}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 5, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 7, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 2}}, + {"id": 8, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}], "proj": {"par": 17, "idx": 0}}, + {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 10, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 17, "role": "CTRL", "label": null}], "proj": {"par": 17, "idx": 1}}, + {"id": 11, "label": "#2", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 12, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 11, "role": "DATA", "label": null}], "proj": null}, + {"id": 13, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 14, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 12, "role": "MEM", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 16, "label": ".f", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 22, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}, {"idx": 4, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 23, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 8, "role": "CTRL", "label": null}, {"idx": 2, "def": 10, "role": "CTRL", "label": null}], "proj": null}, + {"id": 25, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 23, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 16, "role": "DATA", "label": null}], "proj": null}, + {"id": 224, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 23, "role": "ASSOC", "label": null}, {"idx": 1, "def": 22, "role": "MEM", "label": null}, {"idx": 2, "def": 14, "role": "MEM", "label": null}], "proj": null} + ], + "groups": [ + {"id": 17, "par": 0, "nodes": [1, 8, 10, 17, 22, 23, 224]} + ] +} diff --git a/chapter11/docs/graph3.svg b/chapter11/docs/graph3.svg index a16a1733..6fe5fe73 100644 --- a/chapter11/docs/graph3.svg +++ b/chapter11/docs/graph3.svg @@ -1,348 +1,152 @@ - - - - - - -chapter11 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -$mem - -arg - - - -MemMerge - -MemMerge - - - -MemMerge->Start2:p1 - - -1 - - - -Region23 - -Region - - - -MemMerge->Region23 - - -0 - - - -Phi_224 - -MemPhi_2 - - - -MemMerge->Phi_224 - - -2 - - - -Stop3 - -Stop - - - -Return25 - -Return - - - -Stop3->Return25 - - -0 - - - -Con_4 - -#0 - - - -new9 - -new S - - - -new9->Start2:p0 - - -0 - - - -Con_11 - -#2 - - - -Store12 - -.f = - - - -Store12->Start2:p0 - - - -0 - - - -Store12->new9 - - -2 - - - -Store12->Con_11 - - -3 - - - -new13 - -new S - - - -new13->Start2:p0 - - -0 - - - -Store14 - -.f = - - - -Store14->Start2:p0 - -0 - - - -Store14->Con_4 - - -3 - - - -Store14->Store12 - - -1 - - - -Store14->new13 - - -2 - - - -Load16 - -.f - - - -Load16->Start2:p0 - - - -0 - - - -Load16->new9 - - -2 - - - -Load16->Store14 - - -1 - - - -If17 - - -If - - - -True - - -False - - - -If17->Start2:p0 - - -0 - - - -If17->Start2:p2 - - -1 - - - -Con_21 - -#1 - - - -Store22 - -.f = - - - -Store22->new9 - - -2 - - - -Store22->Store14 - - -1 - - - -Store22->Load16 - - -4 - - - -Store22->If17:p0 - - -0 - - - -Store22->Con_21 - - -3 - - - -Region23->If17:p0 - - -1 - - - -Region23->If17:p1 - - -2 - - - -Phi_224->Store14 - - -2 - - - -Phi_224->Store22 - - -1 - - - -Phi_224->Region23 - - -0 - - - -Return25->MemMerge - - -1 - - - -Return25->Load16 - - -2 - - - -Return25->Region23 - - -0 - - - +#1[0] → #23 · CTRL#1[1] → #6 · MEM#1[2] → #224 · MEM#3[0] → #25 · CTRL#9[0] → #5 · CTRL#12[0] → #5 · CTRL#12[1] → #6 · MEM#12[2] → #9 · DATA#12[3] → #11 · DATA#13[0] → #5 · CTRL#14[0] → #5 · CTRL#14[1] → #12 · MEM#14[2] → #13 · DATA#14[3] → #4 · DATA#16[0] → #5 · CTRL#16[1] → #14 · MEM#16[2] → #9 · DATA#17[0] → #5 · CTRL#17[1] → #7 · DATA#22[0] → #8 · CTRL#22[1] → #14 · MEM#22[2] → #9 · DATA#22[3] → #21 · DATA#22[4] → #16 · DATA#23[1] → #8 · CTRL#23[2] → #10 · CTRL#25[0] → #23 · CTRL#25[1] → #1 · MEM#25[2] → #16 · DATA#224[1] → #22 · MEM#224[2] → #14 · MEMMemMerge  #1#1 MemMerge +Type not computed + +[0] → #23 CTRL +[1] → #6 MEM +[2] → #224 MEM012Start  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #25 CTRL0#0  #4#4 #0 +Type not computed + +$ctrl  #5/0#5 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRL$mem  #6/1#6 $mem +Projection 1 of #2 +Type not computed + +[0] → #2 MEMarg  #7/2#7 arg +Projection 2 of #2 +Type not computed + +[0] → #2 DATATrue  #8/0#8 True +Projection 0 of #17 +Type not computed + +[0] → #17 CTRLnew S  #9#9 new S +Type not computed + +[0] → #5 CTRL0False  #10/1#10 False +Projection 1 of #17 +Type not computed + +[0] → #17 CTRL#2  #11#11 #2 +Type not computed + +.f =  #12#12 .f = +Type not computed + +[0] → #5 CTRL +[1] → #6 MEM +[2] → #9 DATA +[3] → #11 DATA0123new S  #13#13 new S +Type not computed + +[0] → #5 CTRL0.f =  #14#14 .f = +Type not computed + +[0] → #5 CTRL +[1] → #12 MEM +[2] → #13 DATA +[3] → #4 DATA0123.f  #16#16 .f +Type not computed + +[0] → #5 CTRL +[1] → #14 MEM +[2] → #9 DATA012If  #17#17 If +Type not computed + +[0] → #5 CTRL +[1] → #7 DATA01#1  #21#21 #1 +Type not computed + +.f =  #22#22 .f = +Type not computed + +[0] → #8 CTRL +[1] → #14 MEM +[2] → #9 DATA +[3] → #21 DATA +[4] → #16 DATA01234Region  #23#23 Region +Type not computed + +[0] → — DATA +[1] → #8 CTRL +[2] → #10 CTRL012Return  #25#25 Return +Type not computed + +[0] → #23 CTRL +[1] → #1 MEM +[2] → #16 DATA012MemPhi_2  #224#224 MemPhi_2 +Type not computed + +[0] → #23 ASSOC +[1] → #22 MEM +[2] → #14 MEM[0] → #23012If  #17If · 7 nodes−Fold region diff --git a/chapter11/docs/graph4.json b/chapter11/docs/graph4.json new file mode 100644 index 00000000..b021c03f --- /dev/null +++ b/chapter11/docs/graph4.json @@ -0,0 +1,42 @@ +{ + "ver": 1, + "comp": "chapter11/docs/graph4.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 37, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 5, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 7, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 2}}, + {"id": 8, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}], "proj": {"par": 16, "idx": 0}}, + {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 10, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 32, "role": "CTRL", "label": null}], "proj": null}, + {"id": 12, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}], "proj": {"par": 16, "idx": 1}}, + {"id": 13, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 11, "role": "ASSOC", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 35, "role": "DATA", "label": null}], "proj": null}, + {"id": 14, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": {"par": 25, "idx": 0}}, + {"id": 16, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": {"par": 25, "idx": 1}}, + {"id": 21, "label": "//", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 22, "role": "DATA", "label": null}], "proj": null}, + {"id": 22, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 23, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 13, "role": "DATA", "label": null}, {"idx": 2, "def": 24, "role": "DATA", "label": null}], "proj": null}, + {"id": 24, "label": "#5", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 25, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 23, "role": "DATA", "label": null}], "proj": null}, + {"id": 31, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 230, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}], "proj": null}, + {"id": 32, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 15, "role": "CTRL", "label": null}, {"idx": 2, "def": 17, "role": "CTRL", "label": null}], "proj": null}, + {"id": 35, "label": "-", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 13, "role": "DATA", "label": null}, {"idx": 2, "def": 36, "role": "DATA", "label": null}], "proj": null}, + {"id": 36, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 37, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 230, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 11, "role": "ASSOC", "label": null}, {"idx": 1, "def": 10, "role": "MEM", "label": null}, {"idx": 2, "def": 233, "role": "MEM", "label": null}], "proj": null}, + {"id": 233, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 32, "role": "ASSOC", "label": null}, {"idx": 1, "def": 31, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null} + ], + "groups": [ + {"id": 11, "par": 0, "nodes": [8, 10, 11, 12, 13, 14, 16, 35, 230]}, + {"id": 25, "par": 11, "nodes": [15, 17, 21, 23, 25, 31, 32, 233]} + ] +} diff --git a/chapter11/docs/graph4.svg b/chapter11/docs/graph4.svg index 2730813a..c268b4e9 100644 --- a/chapter11/docs/graph4.svg +++ b/chapter11/docs/graph4.svg @@ -1,429 +1,187 @@ - - - - - - -chapter11 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -$mem - -arg - - - -MemMerge - -MemMerge - - - -MemMerge->Start2:p1 - - -1 - - - -Phi_230 - -MemPhi_2 - - - -MemMerge->Phi_230 - - -2 - - - -Stop3 - -Stop - - - -Return37 - -Return - - - -Stop3->Return37 - - -0 - - - -Con_4 - -#0 - - - -new9 - -new S - - - -new9->Start2:p0 - - -0 - - - -Store10 - -.f = - - - -Store10->Start2:p1 - - -1 - - - -Store10->Con_4 - - -3 - - - -Store10->new9 - - -2 - - - -Loop11 - -Loop - - - -Loop11->Start2:p0 - - -1 - - - -Region32 - -Region - - - -Loop11->Region32 - - -2 - - - -Phi_arg13 - -φ_arg - - - -Phi_arg13->Start2:p2 - - -1 - - - -Phi_arg13->Loop11 - - -0 - - - -Sub35 - -- - - - -LT14 - -< - - - -LT14->Con_4 - - -1 - - - -LT14->Phi_arg13 - - -2 - - - -If16 - - -If - - - -True - - -False - - - -If16->Loop11 - - -0 - - - -If16->LT14 - - -1 - - - -Div21 - -// - - - -Div21->Start2:p2 - - -1 - - - -Con_22 - -#3 - - - -Div21->Con_22 - - -2 - - - -EQ23 - -== - - - -EQ23->Phi_arg13 - - -1 - - - -Con_24 - -#5 - - - -EQ23->Con_24 - - -2 - - - -If25 - - -If - - - -True - - -False - - - -If25->If16:p0 - - -0 - - - -If25->EQ23 - - -1 - - - -Phi_230->Store10 - - -1 - - - -Phi_230->Loop11 - - -0 - - - -Phi_233 - -MemPhi_2 - - - -Store31 - -.f = - - - -Store31->new9 - - - -2 - - - -Store31->Div21 - - -3 - - - -Store31->Phi_230 - - -1 - - - -Region32->If25:p0 - - -1 - - - -Region32->If25:p1 - - -2 - - - -Phi_233->Phi_230 - - - -2 - - - -Phi_233->Store31 - - -1 - - - -Phi_233->Region32 - - -0 - - - -Sub35->Phi_arg13 - - - -1 - - - -Con_36 - -#1 - - - -Sub35->Con_36 - - -2 - - - -Return37->MemMerge - - -1 - - - -Return37->new9 - - -2 - - - -Return37->If16:p1 - - -0 - - - +#1[1] → #6 · MEM#1[2] → #230 · MEM#3[0] → #37 · CTRL#9[0] → #5 · CTRL#10[1] → #6 · MEM#10[2] → #9 · DATA#10[3] → #4 · DATA#11[1] → #5 · CTRL#11[2] → #32 · CTRL#13[1] → #7 · DATA#13[2] → #35 · DATA#14[1] → #4 · DATA#14[2] → #13 · DATA#16[0] → #11 · CTRL#16[1] → #14 · DATA#21[1] → #7 · DATA#21[2] → #22 · DATA#23[1] → #13 · DATA#23[2] → #24 · DATA#25[0] → #8 · CTRL#25[1] → #23 · DATA#31[1] → #230 · MEM#31[2] → #9 · DATA#31[3] → #21 · DATA#32[1] → #15 · CTRL#32[2] → #17 · CTRL#35[1] → #13 · DATA#35[2] → #36 · DATA#37[0] → #12 · CTRL#37[1] → #1 · MEM#37[2] → #9 · DATA#230[1] → #10 · MEM#230[2] → #233 · MEM#233[1] → #31 · MEM#233[2] → #230 · MEMMemMerge  #1#1 MemMerge +Type not computed + +[0] → — DATA +[1] → #6 MEM +[2] → #230 MEM012Start  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #37 CTRL0#0  #4#4 #0 +Type not computed + +$ctrl  #5/0#5 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRL$mem  #6/1#6 $mem +Projection 1 of #2 +Type not computed + +[0] → #2 MEMarg  #7/2#7 arg +Projection 2 of #2 +Type not computed + +[0] → #2 DATATrue  #8/0#8 True +Projection 0 of #16 +Type not computed + +[0] → #16 CTRLnew S  #9#9 new S +Type not computed + +[0] → #5 CTRL0.f =  #10#10 .f = +Type not computed + +[0] → — DATA +[1] → #6 MEM +[2] → #9 DATA +[3] → #4 DATA0123Loop  #11#11 Loop +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #32 CTRL012False  #12/1#12 False +Projection 1 of #16 +Type not computed + +[0] → #16 CTRLφ_arg  #13#13 φ_arg +Type not computed + +[0] → #11 ASSOC +[1] → #7 DATA +[2] → #35 DATA[0] → #11012<  #14#14 < +Type not computed + +[0] → — DATA +[1] → #4 DATA +[2] → #13 DATA012True  #15/0#15 True +Projection 0 of #25 +Type not computed + +[0] → #25 CTRLIf  #16#16 If +Type not computed + +[0] → #11 CTRL +[1] → #14 DATA01False  #17/1#17 False +Projection 1 of #25 +Type not computed + +[0] → #25 CTRL//  #21#21 // +Type not computed + +[0] → — DATA +[1] → #7 DATA +[2] → #22 DATA012#3  #22#22 #3 +Type not computed + +==  #23#23 == +Type not computed + +[0] → — DATA +[1] → #13 DATA +[2] → #24 DATA012#5  #24#24 #5 +Type not computed + +If  #25#25 If +Type not computed + +[0] → #8 CTRL +[1] → #23 DATA01.f =  #31#31 .f = +Type not computed + +[0] → — DATA +[1] → #230 MEM +[2] → #9 DATA +[3] → #21 DATA0123Region  #32#32 Region +Type not computed + +[0] → — DATA +[1] → #15 CTRL +[2] → #17 CTRL012-  #35#35 - +Type not computed + +[0] → — DATA +[1] → #13 DATA +[2] → #36 DATA012#1  #36#36 #1 +Type not computed + +Return  #37#37 Return +Type not computed + +[0] → #12 CTRL +[1] → #1 MEM +[2] → #9 DATA012MemPhi_2  #230#230 MemPhi_2 +Type not computed + +[0] → #11 ASSOC +[1] → #10 MEM +[2] → #233 MEM[0] → #11012MemPhi_2  #233#233 MemPhi_2 +Type not computed + +[0] → #32 ASSOC +[1] → #31 MEM +[2] → #230 MEM[0] → #32012Loop  #11Loop · 17 nodes−Fold regionIf  #25If · 8 nodes−Fold region diff --git a/chapter11/docs/graph5.json b/chapter11/docs/graph5.json new file mode 100644 index 00000000..2211cb19 --- /dev/null +++ b/chapter11/docs/graph5.json @@ -0,0 +1,42 @@ +{ + "ver": 1, + "comp": "chapter11/docs/graph5.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 37, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 5, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 7, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 2}}, + {"id": 8, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}], "proj": {"par": 16, "idx": 0}}, + {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 10, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 32, "role": "CTRL", "label": null}], "proj": null}, + {"id": 12, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}], "proj": {"par": 16, "idx": 1}}, + {"id": 13, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 11, "role": "ASSOC", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 35, "role": "DATA", "label": null}], "proj": null}, + {"id": 14, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": {"par": 25, "idx": 0}}, + {"id": 16, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": {"par": 25, "idx": 1}}, + {"id": 21, "label": "//", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 22, "role": "DATA", "label": null}], "proj": null}, + {"id": 22, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 23, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 13, "role": "DATA", "label": null}, {"idx": 2, "def": 24, "role": "DATA", "label": null}], "proj": null}, + {"id": 24, "label": "#5", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 25, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 23, "role": "DATA", "label": null}], "proj": null}, + {"id": 31, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 230, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}], "proj": null}, + {"id": 32, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 15, "role": "CTRL", "label": null}, {"idx": 2, "def": 17, "role": "CTRL", "label": null}], "proj": null}, + {"id": 35, "label": "-", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 13, "role": "DATA", "label": null}, {"idx": 2, "def": 36, "role": "DATA", "label": null}], "proj": null}, + {"id": 36, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 37, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 230, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 11, "role": "ASSOC", "label": null}, {"idx": 1, "def": 10, "role": "MEM", "label": null}, {"idx": 2, "def": 233, "role": "MEM", "label": null}], "proj": null}, + {"id": 233, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 32, "role": "ASSOC", "label": null}, {"idx": 1, "def": 31, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null} + ], + "groups": [ + {"id": 11, "par": 0, "nodes": [1, 8, 11, 12, 13, 14, 16, 23, 31, 35, 230]}, + {"id": 25, "par": 11, "nodes": [15, 17, 25, 32, 233]} + ] +} diff --git a/chapter11/docs/graph5.svg b/chapter11/docs/graph5.svg index 9336ac3e..1669e008 100644 --- a/chapter11/docs/graph5.svg +++ b/chapter11/docs/graph5.svg @@ -1,472 +1,187 @@ - - - - - - -chapter11 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -$mem - -arg - - - -MemMerge - -MemMerge - - - -MemMerge->Start2:p1 - - -1 - - - -Loop11 - -Loop - - - -MemMerge->Loop11 - - -0 - - - -Phi_230 - -MemPhi_2 - - - -MemMerge->Phi_230 - - -2 - - - -Stop3 - -Stop - - - -Return37 - -Return - - - -Stop3->Return37 - - -0 - - - -Con_4 - -#0 - - - -new9 - -new S - - - -new9->Start2:p0 - - -0 - - - -Store10 - -.f = - - - -Store10->Start2:p0 - - -0 - - - -Store10->Con_4 - - -3 - - - -Store10->new9 - - -2 - - - -Loop11->Start2:p0 - - -1 - - - -Region32 - -Region - - - -Loop11->Region32 - - -2 - - - -Phi_arg13 - -φ_arg - - - -Phi_arg13->Start2:p2 - - -1 - - - -Phi_arg13->Loop11 - - -0 - - - -Sub35 - -- - - - -LT14 - -< - - - -LT14->Con_4 - - -1 - - - -LT14->Loop11 - - -0 - - - -LT14->Phi_arg13 - - -2 - - - -If16 - - -If - - - -True - - -False - - - -If16->Loop11 - - -0 - - - -If16->LT14 - - -1 - - - -Div21 - -// - - - -Div21->Start2 - - -0 - - - -Div21->Start2:p2 - - -1 - - - -Con_22 - -#3 - - - -Div21->Con_22 - - -2 - - - -EQ23 - -== - - - -EQ23->Loop11 - - -0 - - - -EQ23->Phi_arg13 - - -1 - - - -Con_24 - -#5 - - - -EQ23->Con_24 - - -2 - - - -If25 - - -If - - - -True - - -False - - - -If25->If16:p0 - - -0 - - - -If25->EQ23 - - -1 - - - -Phi_230->Store10 - - -1 - - - -Phi_230->Loop11 - - -0 - - - -Phi_233 - -MemPhi_2 - - - -Store31 - -.f = - - - -Store31->new9 - - -2 - - - -Store31->Loop11 - - -0 - - - -Store31->Div21 - - - -3 - - - -Store31->Phi_230 - - -1 - - - -Region32->If25:p0 - - -1 - - - -Region32->If25:p1 - - -2 - - - -Phi_233->Phi_230 - - - -2 - - - -Phi_233->Store31 - - -1 - - - -Phi_233->Region32 - - -0 - - - -Sub35->Loop11 - - -0 - - - -Sub35->Phi_arg13 - - - -1 - - - -Con_36 - -#1 - - - -Sub35->Con_36 - - -2 - - - -Return37->MemMerge - - -1 - - - -Return37->new9 - - - -2 - - - -Return37->If16:p1 - - -0 - - - +#1[0] → #11 · CTRL#1[1] → #6 · MEM#1[2] → #230 · MEM#3[0] → #37 · CTRL#9[0] → #5 · CTRL#10[0] → #5 · CTRL#10[1] → #6 · MEM#10[2] → #9 · DATA#10[3] → #4 · DATA#11[1] → #5 · CTRL#11[2] → #32 · CTRL#13[1] → #7 · DATA#13[2] → #35 · DATA#14[0] → #11 · CTRL#14[1] → #4 · DATA#14[2] → #13 · DATA#16[0] → #11 · CTRL#16[1] → #14 · DATA#21[0] → #2 · CTRL#21[1] → #7 · DATA#21[2] → #22 · DATA#23[0] → #11 · CTRL#23[1] → #13 · DATA#23[2] → #24 · DATA#25[0] → #8 · CTRL#25[1] → #23 · DATA#31[0] → #11 · CTRL#31[1] → #230 · MEM#31[2] → #9 · DATA#31[3] → #21 · DATA#32[1] → #15 · CTRL#32[2] → #17 · CTRL#35[0] → #11 · CTRL#35[1] → #13 · DATA#35[2] → #36 · DATA#37[0] → #12 · CTRL#37[1] → #1 · MEM#37[2] → #9 · DATA#230[1] → #10 · MEM#230[2] → #233 · MEM#233[1] → #31 · MEM#233[2] → #230 · MEMMemMerge  #1#1 MemMerge +Type not computed + +[0] → #11 CTRL +[1] → #6 MEM +[2] → #230 MEM012Start  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #37 CTRL0#0  #4#4 #0 +Type not computed + +$ctrl  #5/0#5 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRL$mem  #6/1#6 $mem +Projection 1 of #2 +Type not computed + +[0] → #2 MEMarg  #7/2#7 arg +Projection 2 of #2 +Type not computed + +[0] → #2 DATATrue  #8/0#8 True +Projection 0 of #16 +Type not computed + +[0] → #16 CTRLnew S  #9#9 new S +Type not computed + +[0] → #5 CTRL0.f =  #10#10 .f = +Type not computed + +[0] → #5 CTRL +[1] → #6 MEM +[2] → #9 DATA +[3] → #4 DATA0123Loop  #11#11 Loop +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #32 CTRL012False  #12/1#12 False +Projection 1 of #16 +Type not computed + +[0] → #16 CTRLφ_arg  #13#13 φ_arg +Type not computed + +[0] → #11 ASSOC +[1] → #7 DATA +[2] → #35 DATA[0] → #11012<  #14#14 < +Type not computed + +[0] → #11 CTRL +[1] → #4 DATA +[2] → #13 DATA012True  #15/0#15 True +Projection 0 of #25 +Type not computed + +[0] → #25 CTRLIf  #16#16 If +Type not computed + +[0] → #11 CTRL +[1] → #14 DATA01False  #17/1#17 False +Projection 1 of #25 +Type not computed + +[0] → #25 CTRL//  #21#21 // +Type not computed + +[0] → #2 CTRL +[1] → #7 DATA +[2] → #22 DATA012#3  #22#22 #3 +Type not computed + +==  #23#23 == +Type not computed + +[0] → #11 CTRL +[1] → #13 DATA +[2] → #24 DATA012#5  #24#24 #5 +Type not computed + +If  #25#25 If +Type not computed + +[0] → #8 CTRL +[1] → #23 DATA01.f =  #31#31 .f = +Type not computed + +[0] → #11 CTRL +[1] → #230 MEM +[2] → #9 DATA +[3] → #21 DATA0123Region  #32#32 Region +Type not computed + +[0] → — DATA +[1] → #15 CTRL +[2] → #17 CTRL012-  #35#35 - +Type not computed + +[0] → #11 CTRL +[1] → #13 DATA +[2] → #36 DATA012#1  #36#36 #1 +Type not computed + +Return  #37#37 Return +Type not computed + +[0] → #12 CTRL +[1] → #1 MEM +[2] → #9 DATA012MemPhi_2  #230#230 MemPhi_2 +Type not computed + +[0] → #11 ASSOC +[1] → #10 MEM +[2] → #233 MEM[0] → #11012MemPhi_2  #233#233 MemPhi_2 +Type not computed + +[0] → #32 ASSOC +[1] → #31 MEM +[2] → #230 MEM[0] → #32012Loop  #11Loop · 16 nodes−Fold regionIf  #25If · 5 nodes−Fold region diff --git a/chapter11/docs/graph6.json b/chapter11/docs/graph6.json new file mode 100644 index 00000000..1c08947a --- /dev/null +++ b/chapter11/docs/graph6.json @@ -0,0 +1,42 @@ +{ + "ver": 1, + "comp": "chapter11/docs/graph6.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "MemMerge", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 37, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 5, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 6, "label": "$mem", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 2, "role": "MEM", "label": null}], "proj": {"par": 2, "idx": 1}}, + {"id": 7, "label": "arg", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 2, "role": "DATA", "label": null}], "proj": {"par": 2, "idx": 2}}, + {"id": 8, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}], "proj": {"par": 16, "idx": 0}}, + {"id": 9, "label": "new S", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 10, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 6, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 11, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 5, "role": "CTRL", "label": null}, {"idx": 2, "def": 32, "role": "CTRL", "label": null}], "proj": null}, + {"id": 12, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 16, "role": "CTRL", "label": null}], "proj": {"par": 16, "idx": 1}}, + {"id": 13, "label": "φ_arg", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 11, "role": "ASSOC", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 35, "role": "DATA", "label": null}], "proj": null}, + {"id": 14, "label": "<", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}, {"idx": 2, "def": 13, "role": "DATA", "label": null}], "proj": null}, + {"id": 15, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": {"par": 25, "idx": 0}}, + {"id": 16, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 11, "role": "CTRL", "label": null}, {"idx": 1, "def": 14, "role": "DATA", "label": null}], "proj": null}, + {"id": 17, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 25, "role": "CTRL", "label": null}], "proj": {"par": 25, "idx": 1}}, + {"id": 21, "label": "//", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 5, "role": "CTRL", "label": null}, {"idx": 1, "def": 7, "role": "DATA", "label": null}, {"idx": 2, "def": 22, "role": "DATA", "label": null}], "proj": null}, + {"id": 22, "label": "#3", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 23, "label": "==", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 13, "role": "DATA", "label": null}, {"idx": 2, "def": 24, "role": "DATA", "label": null}], "proj": null}, + {"id": 24, "label": "#5", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 25, "label": "If", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 23, "role": "DATA", "label": null}], "proj": null}, + {"id": 31, "label": ".f =", "type": null, "kind": "MEM", "edges": [{"idx": 0, "def": 15, "role": "CTRL", "label": null}, {"idx": 1, "def": 230, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}, {"idx": 3, "def": 21, "role": "DATA", "label": null}], "proj": null}, + {"id": 32, "label": "Region", "type": null, "kind": "REGION", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 15, "role": "CTRL", "label": null}, {"idx": 2, "def": 17, "role": "CTRL", "label": null}], "proj": null}, + {"id": 35, "label": "-", "type": null, "kind": "DATA", "edges": [{"idx": 0, "def": 32, "role": "CTRL", "label": null}, {"idx": 1, "def": 13, "role": "DATA", "label": null}, {"idx": 2, "def": 36, "role": "DATA", "label": null}], "proj": null}, + {"id": 36, "label": "#1", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 37, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 12, "role": "CTRL", "label": null}, {"idx": 1, "def": 1, "role": "MEM", "label": null}, {"idx": 2, "def": 9, "role": "DATA", "label": null}], "proj": null}, + {"id": 230, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 11, "role": "ASSOC", "label": null}, {"idx": 1, "def": 10, "role": "MEM", "label": null}, {"idx": 2, "def": 233, "role": "MEM", "label": null}], "proj": null}, + {"id": 233, "label": "MemPhi_2", "type": null, "kind": "PHI", "edges": [{"idx": 0, "def": 32, "role": "ASSOC", "label": null}, {"idx": 1, "def": 31, "role": "MEM", "label": null}, {"idx": 2, "def": 230, "role": "MEM", "label": null}], "proj": null} + ], + "groups": [ + {"id": 11, "par": 0, "nodes": [8, 11, 12, 13, 14, 16, 23, 230]}, + {"id": 25, "par": 11, "nodes": [15, 17, 25, 31, 32, 35, 233]} + ] +} diff --git a/chapter11/docs/graph6.svg b/chapter11/docs/graph6.svg index 8b8bb190..8862f25c 100644 --- a/chapter11/docs/graph6.svg +++ b/chapter11/docs/graph6.svg @@ -1,471 +1,187 @@ - - - - - - -chapter11 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - -$mem - -arg - - - -MemMerge - -MemMerge - - - -MemMerge->Start2:p1 - - -1 - - - -If16 - - -If - - - -True - - -False - - - -MemMerge->If16:p1 - - -0 - - - -Phi_230 - -MemPhi_2 - - - -MemMerge->Phi_230 - -2 - - - -Stop3 - -Stop - - - -Return37 - -Return - - - -Stop3->Return37 - - -0 - - - -Con_4 - -#0 - - - -new9 - -new S - - - -new9->Start2:p0 - - -0 - - - -Store10 - -.f = - - - -Store10->Start2:p0 - - -0 - - - -Store10->Con_4 - - -3 - - - -Store10->new9 - - -2 - - - -Loop11 - -Loop - - - -Loop11->Start2:p0 - - -1 - - - -Region32 - -Region - - - -Loop11->Region32 - - -2 - - - -Phi_arg13 - -φ_arg - - - -Phi_arg13->Start2:p2 - - -1 - - - -Phi_arg13->Loop11 - - -0 - - - -Sub35 - -- - - - -LT14 - -< - - - -LT14->Con_4 - - -1 - - - -LT14->Loop11 - - -0 - - - -LT14->Phi_arg13 - - -2 - - - -If16->Loop11 - - -0 - - - -If16->LT14 - - -1 - - - -Div21 - -// - - - -Div21->Start2:p0 - - -0 - - - -Div21->Start2:p2 - - -1 - - - -Con_22 - -#3 - - - -Div21->Con_22 - - -2 - - - -EQ23 - -== - - - -EQ23->Phi_arg13 - - -1 - - - -EQ23->If16:p0 - - -0 - - - -Con_24 - -#5 - - - -EQ23->Con_24 - - -2 - - - -If25 - - -If - - - -True - - -False - - - -If25->If16:p0 - - -0 - - - -If25->EQ23 - - -1 - - - -Phi_230->Store10 - - -1 - - - -Phi_230->Loop11 - - -0 - - - -Phi_233 - -MemPhi_2 - - - -Store31 - -.f = - - - -Store31->new9 - - - - -2 - - - -Store31->Div21 - - -3 - - - -Store31->If25:p0 - - -0 - - - -Store31->Phi_230 - - - -1 - - - -Region32->If25:p0 - - -1 - - - -Region32->If25:p1 - - -2 - - - -Phi_233->Phi_230 - - - -2 - - - -Phi_233->Store31 - - -1 - - - -Phi_233->Region32 - - -0 - - - -Sub35->Phi_arg13 - - - -1 - - - -Sub35->Region32 - - -0 - - - -Con_36 - -#1 - - - -Sub35->Con_36 - - -2 - - - -Return37->MemMerge - - -1 - - - -Return37->new9 - -2 - - - -Return37->If16:p1 - - -0 - - - +#1[0] → #12 · CTRL#1[1] → #6 · MEM#1[2] → #230 · MEM#3[0] → #37 · CTRL#9[0] → #5 · CTRL#10[0] → #5 · CTRL#10[1] → #6 · MEM#10[2] → #9 · DATA#10[3] → #4 · DATA#11[1] → #5 · CTRL#11[2] → #32 · CTRL#13[1] → #7 · DATA#13[2] → #35 · DATA#14[0] → #11 · CTRL#14[1] → #4 · DATA#14[2] → #13 · DATA#16[0] → #11 · CTRL#16[1] → #14 · DATA#21[0] → #5 · CTRL#21[1] → #7 · DATA#21[2] → #22 · DATA#23[0] → #8 · CTRL#23[1] → #13 · DATA#23[2] → #24 · DATA#25[0] → #8 · CTRL#25[1] → #23 · DATA#31[0] → #15 · CTRL#31[1] → #230 · MEM#31[2] → #9 · DATA#31[3] → #21 · DATA#32[1] → #15 · CTRL#32[2] → #17 · CTRL#35[0] → #32 · CTRL#35[1] → #13 · DATA#35[2] → #36 · DATA#37[0] → #12 · CTRL#37[1] → #1 · MEM#37[2] → #9 · DATA#230[1] → #10 · MEM#230[2] → #233 · MEM#233[1] → #31 · MEM#233[2] → #230 · MEMMemMerge  #1#1 MemMerge +Type not computed + +[0] → #12 CTRL +[1] → #6 MEM +[2] → #230 MEM012Start  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #37 CTRL0#0  #4#4 #0 +Type not computed + +$ctrl  #5/0#5 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRL$mem  #6/1#6 $mem +Projection 1 of #2 +Type not computed + +[0] → #2 MEMarg  #7/2#7 arg +Projection 2 of #2 +Type not computed + +[0] → #2 DATATrue  #8/0#8 True +Projection 0 of #16 +Type not computed + +[0] → #16 CTRLnew S  #9#9 new S +Type not computed + +[0] → #5 CTRL0.f =  #10#10 .f = +Type not computed + +[0] → #5 CTRL +[1] → #6 MEM +[2] → #9 DATA +[3] → #4 DATA0123Loop  #11#11 Loop +Type not computed + +[0] → — DATA +[1] → #5 CTRL +[2] → #32 CTRL012False  #12/1#12 False +Projection 1 of #16 +Type not computed + +[0] → #16 CTRLφ_arg  #13#13 φ_arg +Type not computed + +[0] → #11 ASSOC +[1] → #7 DATA +[2] → #35 DATA[0] → #11012<  #14#14 < +Type not computed + +[0] → #11 CTRL +[1] → #4 DATA +[2] → #13 DATA012True  #15/0#15 True +Projection 0 of #25 +Type not computed + +[0] → #25 CTRLIf  #16#16 If +Type not computed + +[0] → #11 CTRL +[1] → #14 DATA01False  #17/1#17 False +Projection 1 of #25 +Type not computed + +[0] → #25 CTRL//  #21#21 // +Type not computed + +[0] → #5 CTRL +[1] → #7 DATA +[2] → #22 DATA012#3  #22#22 #3 +Type not computed + +==  #23#23 == +Type not computed + +[0] → #8 CTRL +[1] → #13 DATA +[2] → #24 DATA012#5  #24#24 #5 +Type not computed + +If  #25#25 If +Type not computed + +[0] → #8 CTRL +[1] → #23 DATA01.f =  #31#31 .f = +Type not computed + +[0] → #15 CTRL +[1] → #230 MEM +[2] → #9 DATA +[3] → #21 DATA0123Region  #32#32 Region +Type not computed + +[0] → — DATA +[1] → #15 CTRL +[2] → #17 CTRL012-  #35#35 - +Type not computed + +[0] → #32 CTRL +[1] → #13 DATA +[2] → #36 DATA012#1  #36#36 #1 +Type not computed + +Return  #37#37 Return +Type not computed + +[0] → #12 CTRL +[1] → #1 MEM +[2] → #9 DATA012MemPhi_2  #230#230 MemPhi_2 +Type not computed + +[0] → #11 ASSOC +[1] → #10 MEM +[2] → #233 MEM[0] → #11012MemPhi_2  #233#233 MemPhi_2 +Type not computed + +[0] → #32 ASSOC +[1] → #31 MEM +[2] → #230 MEM[0] → #32012Loop  #11Loop · 15 nodes−Fold regionIf  #25If · 7 nodes−Fold region diff --git a/chapter11/docs/graph7.json b/chapter11/docs/graph7.json new file mode 100644 index 00000000..c1c86b07 --- /dev/null +++ b/chapter11/docs/graph7.json @@ -0,0 +1,16 @@ +{ + "ver": 1, + "comp": "chapter11/docs/graph7.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 8, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 1, "role": "CTRL", "label": null}, {"idx": 2, "def": 8, "role": "CTRL", "label": null}], "proj": null} + ], + "groups": [ + {"id": 8, "par": 0, "nodes": [8]} + ] +} diff --git a/chapter11/docs/graph7.svg b/chapter11/docs/graph7.svg index 854660ec..e83b8d54 100644 --- a/chapter11/docs/graph7.svg +++ b/chapter11/docs/graph7.svg @@ -1,54 +1,78 @@ - - - - - - -chapter11 - - -cluster_Nodes - - - - -Start2 - - -Start - - - -$ctrl - - - -Con_4 - -#0 - - - -Loop8 - -Loop - - - -Loop8->Start2:p0 - - -1 - - - -Loop8->Loop8 - - -2 - - - +#8[1] → #1 · CTRL#8[2] → #8 · CTRL$ctrl  #1/0#1 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLStart  #2#2 Start +Type not computed + +#0  #4#4 #0 +Type not computed + +Loop  #8#8 Loop +Type not computed + +[0] → — DATA +[1] → #1 CTRL +[2] → #8 CTRL012Loop  #8Loop · 1 nodes−Fold region diff --git a/chapter11/docs/graph8.json b/chapter11/docs/graph8.json new file mode 100644 index 00000000..ab2ef65c --- /dev/null +++ b/chapter11/docs/graph8.json @@ -0,0 +1,21 @@ +{ + "ver": 1, + "comp": "chapter11/docs/graph8.svg", + "step": 1, + "roots": [], + "scope": 0, + "nodes": [ + {"id": 1, "label": "True", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 18, "role": "CTRL", "label": null}], "proj": {"par": 18, "idx": 0}}, + {"id": 2, "label": "Start", "type": null, "kind": "CTRL", "edges": [], "proj": null}, + {"id": 3, "label": "Stop", "type": null, "kind": "STOP", "edges": [{"idx": 0, "def": 21, "role": "CTRL", "label": null}], "proj": null}, + {"id": 4, "label": "#0", "type": null, "kind": "DATA", "edges": [], "proj": null}, + {"id": 5, "label": "False", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 18, "role": "CTRL", "label": null}], "proj": {"par": 18, "idx": 1}}, + {"id": 6, "label": "$ctrl", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 2, "role": "CTRL", "label": null}], "proj": {"par": 2, "idx": 0}}, + {"id": 8, "label": "Loop", "type": null, "kind": "LOOP", "edges": [{"idx": 0, "def": 0, "role": "DATA", "label": null}, {"idx": 1, "def": 6, "role": "CTRL", "label": null}, {"idx": 2, "def": 5, "role": "CTRL", "label": null}], "proj": null}, + {"id": 18, "label": "Never", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 8, "role": "CTRL", "label": null}, {"idx": 1, "def": 4, "role": "DATA", "label": null}], "proj": null}, + {"id": 21, "label": "Return", "type": null, "kind": "CTRL", "edges": [{"idx": 0, "def": 1, "role": "CTRL", "label": null}, {"idx": 1, "def": 0, "role": "DATA", "label": null}, {"idx": 2, "def": 4, "role": "DATA", "label": null}], "proj": null} + ], + "groups": [ + {"id": 8, "par": 0, "nodes": [1, 5, 8, 18]} + ] +} diff --git a/chapter11/docs/graph8.svg b/chapter11/docs/graph8.svg index a89eeeb5..4db46240 100644 --- a/chapter11/docs/graph8.svg +++ b/chapter11/docs/graph8.svg @@ -1,115 +1,98 @@ - - - - - - -chapter11 - - -cluster_Nodes - - - - -Never18 - - -Never - - - -True - - -False - - - -Con_4 - -#0 - - - -Never18->Con_4 - - -1 - - - -Loop8 - -Loop - - - -Never18->Loop8 - - -0 - - - -Start2 - - -Start - - - -$ctrl - - - -Stop3 - -Stop - - - -Return21 - -Return - - - -Stop3->Return21 - - -0 - - - -Return21->Never18:p0 - - -0 - - - -Return21->Con_4 - - -2 - - - -Loop8->Never18:p1 - - -2 - - - -Loop8->Start2:p0 - - -1 - - - +#3[0] → #21 · CTRL#8[1] → #6 · CTRL#8[2] → #5 · CTRL#18[0] → #8 · CTRL#18[1] → #4 · DATA#21[0] → #1 · CTRL#21[2] → #4 · DATATrue  #1/0#1 True +Projection 0 of #18 +Type not computed + +[0] → #18 CTRLStart  #2#2 Start +Type not computed + +Stop  #3#3 Stop +Type not computed + +[0] → #21 CTRL0#0  #4#4 #0 +Type not computed + +False  #5/1#5 False +Projection 1 of #18 +Type not computed + +[0] → #18 CTRL$ctrl  #6/0#6 $ctrl +Projection 0 of #2 +Type not computed + +[0] → #2 CTRLLoop  #8#8 Loop +Type not computed + +[0] → — DATA +[1] → #6 CTRL +[2] → #5 CTRL012Never  #18#18 Never +Type not computed + +[0] → #8 CTRL +[1] → #4 DATA01Return  #21#21 Return +Type not computed + +[0] → #1 CTRL +[1] → — DATA +[2] → #4 DATA012Loop  #8Loop · 4 nodes−Fold region diff --git a/chapter12/README.md b/chapter12/README.md index 28fbb6dc..49cc5e02 100644 --- a/chapter12/README.md +++ b/chapter12/README.md @@ -1,5 +1,8 @@ # Chapter 12: Floats +[Previous: Chapter 11](../chapter11/README.md) | +[Next: Chapter 13](../chapter13/README.md) + Memory keeps Chapter 11's single `$mem` binding and lazy `MemMerge`, `MemPhi`, and `BulkMemPhi` partitions. Start produces `{ctrl, $mem, arg}` and Return consumes `{ctrl, $mem, result}`; floating-point arithmetic needs no new memory @@ -30,7 +33,7 @@ There is no corresponding way right now to round a `flt` back to an `int`: int x = 3.14; // error ``` -Here is Newton's method to a square root: +Here is Newton's method for computing a square root: ```java flt guess = arg; // Initial guess is just argument while( true ) { @@ -52,11 +55,12 @@ Floating point operations have their own Nodes: | MinusF | Unary negate | | EQF, LTF, LEF | FP compare operators | -And their own section in the Type lattice: +Within the Type lattice, we add the following domain: -Within the Type Lattice, we now add the following domain: +* ![Float](../docs/type-float.svg) - Float values. The same shape as the Integer values, but floats + with a top (`TOP`, ⊤), bottom (`BOT`, ⊥), and constants. -* Float type - Float values. The same shape as the Integer values, but floats - with a TOP, BOT and constants +The other domains retain Chapter 10b's named structs, nullable pointers, and +precise memory aliases. ![Graph1](./docs/lattice.svg) diff --git a/chapter12/docs/lattice.gv b/chapter12/docs/lattice.gv index 23b3f7a7..f3b5051c 100644 --- a/chapter12/docs/lattice.gv +++ b/chapter12/docs/lattice.gv @@ -1,182 +1,135 @@ digraph Lattice { - compound = true; - // Define nodes - splines=false; - node [shape=circle, style=filled]; - nodesep=0.6; - - TOP [label=<⊤>, fillcolor=black, fontcolor=white]; - BOT [label=<⊥>, fillcolor=black, fontcolor=white]; - - // ---------------------- - // Control - XCTRL [label=<⊤:ctrl>, fillcolor=yellow, shape=oval]; - CTRL [label=<⊥:ctrl>, fillcolor=yellow, shape=oval]; - - TOP -> XCTRL; - XCTRL -> CTRL; - CTRL -> BOT; - - // ---------------------- - // Integers - INT_TOP [label=<⊤:int>, fillcolor=lightblue, shape=oval]; - INT_BOT [label=<⊥:int>, fillcolor=lightblue, shape=oval]; - - INT_MINDOTS [label="...", fillcolor=lightblue, shape=oval]; - INT_ZERO [label="0" , fillcolor=lightblue]; - INT_MAXDOTS [label="...", fillcolor=lightblue, shape=oval]; - - TOP -> INT_TOP; - INT_TOP -> INT_MINDOTS; - INT_TOP -> INT_ZERO; - INT_TOP -> INT_MAXDOTS; - INT_MINDOTS -> INT_BOT; - INT_ZERO -> INT_BOT; - INT_MAXDOTS -> INT_BOT; - INT_BOT -> BOT; - - INT_MINDOTS -> INT_ZERO -> INT_MAXDOTS [style=invis]; - - // ---------------------- - // Floats - FLT_TOP [label=<⊤:flt>, fillcolor=aqua, shape=oval]; - FLT_BOT [label=<⊥:flt>, fillcolor=aqua, shape=oval]; - - FLT_MINDOTS [label="...", fillcolor=aqua, shape=oval]; - FLT_ZERO [label="0" , fillcolor=aqua]; - FLT_MAXDOTS [label="...", fillcolor=aqua, shape=oval]; - - TOP -> FLT_TOP; - FLT_TOP -> FLT_MINDOTS; - FLT_TOP -> FLT_ZERO; - FLT_TOP -> FLT_MAXDOTS; - FLT_MINDOTS -> FLT_BOT; - FLT_ZERO -> FLT_BOT; - FLT_MAXDOTS -> FLT_BOT; - FLT_BOT -> BOT; - - FLT_MINDOTS -> FLT_ZERO -> FLT_MAXDOTS [style=invis]; - - // ---------------------- - // Pointers, just a boolean nil/not and a struct - PTR [shape=none, fillcolor=none, label=< - - - -
*ptr
struct
- >]; - PTR0 [shape=none, fillcolor=none, label=< - - - -
*ptr?
struct
- >]; - - TOP -> PTR; - PTR -> PTR0; - PTR0 -> BOT; - - // ---------------------- - // Structs - STRUCT_TOP [label=<⊤:struct>, fillcolor=lightgreen, shape=oval]; - STRUCT_BOT [label=<⊥:struct>, fillcolor=lightgreen, shape=oval]; - - STRUCT_S1 [shape=none, fillcolor=none, label=< - - -
fieldint/ptr
- >]; - STRUCT_S2 [shape=none, fillcolor=none, label=< - - - -
fieldint/ptr
fieldint/ptr
- >]; - STRUCT_SN [shape=none, fillcolor=none, label=< - - - - -
fieldint/ptr
... int/ptr
fieldint/ptr
- >]; - - - TOP -> STRUCT_TOP; - STRUCT_TOP -> STRUCT_S1; - STRUCT_TOP -> STRUCT_S2; - STRUCT_TOP -> STRUCT_SN; - STRUCT_S1 -> STRUCT_BOT; - STRUCT_S2 -> STRUCT_BOT; - STRUCT_SN -> STRUCT_BOT; - STRUCT_BOT -> BOT; - - STRUCT_S1 -> STRUCT_S2 -> STRUCT_SN [style=invis]; - - // ---------------------- - // Memory - MEM_TOP [label=<⊤:mem>, fillcolor=blue, fontcolor=white, shape=oval]; - MEM_BOT [label=<⊥:mem>, fillcolor=blue, fontcolor=white, shape=oval]; - MEM_ALIAS1 [label="#1" , fillcolor=blue, fontcolor=white]; - MEM_ALIASDOTS [label="..." , fillcolor=blue, fontcolor=white, shape=oval]; - MEM_ALIASN [label="#n" , fillcolor=blue, fontcolor=white]; - - TOP -> MEM_TOP; - MEM_TOP -> MEM_ALIAS1; - MEM_TOP -> MEM_ALIASDOTS; - MEM_TOP -> MEM_ALIASN; - MEM_ALIAS1 -> MEM_BOT; - MEM_ALIASDOTS -> MEM_BOT; - MEM_ALIASN -> MEM_BOT; - MEM_BOT -> BOT; - - MEM_ALIAS1 -> MEM_ALIASDOTS -> MEM_ALIASN [style=invis]; - - // ---------------------- - // Tuples - - TUPLE_TOP [label=<⊤:tuple>, fillcolor=pink, shape=oval]; - TUPLE_BOT [label=<⊥:tuple>, fillcolor=pink, shape=oval]; - - TUPLE1 [shape=none, fillcolor=none, label=< - - - -
Tuple
type
- >]; - TUPLE2 [shape=none, fillcolor=none, label=< - - - - -
Tuple
type
type
- >]; - TUPLEN [shape=none, fillcolor=none, label=< - - - - - -
Tuple
type
...
type
- >]; - - - TOP -> TUPLE_TOP; - TUPLE_TOP -> TUPLE1; - TUPLE_TOP -> TUPLE2; - TUPLE_TOP -> TUPLEN; - TUPLE1 -> TUPLE_BOT; - TUPLE2 -> TUPLE_BOT; - TUPLEN -> TUPLE_BOT; - TUPLE_BOT -> BOT; - - // ---------------------- - // Additional customization - {rank=same; TOP;} - {rank=same; INT_TOP; FLT_TOP; XCTRL; STRUCT_TOP; MEM_TOP; TUPLE_TOP} - {rank=same; INT_MINDOTS; INT_ZERO; INT_MAXDOTS; - FLT_MINDOTS; FLT_ZERO; FLT_MAXDOTS; - STRUCT_S1; STRUCT_S2; STRUCT_SN; - MEM_ALIAS1; MEM_ALIASDOTS; MEM_ALIASN;} - {rank=same; INT_BOT; FLT_BOT; CTRL; STRUCT_BOT; MEM_BOT; TUPLE_BOT} - {rank=same; BOT;} + rankdir=TB; + newrank=true; + // Preserve the same-rank ordering edges through cluster layout. + remincross=false; + nodesep=0.22; + ranksep=0.65; + node [shape=ellipse, style=filled, fontname="DejaVu Sans", fontsize=13]; + edge [color="#555555", arrowsize=0.6]; + + // These arrows are lattice-order edges, not use/definition edges. + TOP [label="⊤", fillcolor=black, fontcolor=white]; + BOT [label="⊥", fillcolor=black, fontcolor=white]; + + subgraph cluster_control { + label="Control"; fontname="Arial"; color="#cccccc"; + node [fillcolor="#ffff00"]; + XCTRL [label="⊤:ctrl"]; + CTRL [label="⊥:ctrl"]; + XCTRL -> CTRL; + } + + subgraph cluster_integer { + label="Integer"; fontname="Arial"; color="#cccccc"; + node [fillcolor="#add8e6"]; + INT_TOP [label="⊤:int"]; + INT_BOT [label="⊥:int"]; + INT_NEG [label="… −2, −1"]; + INT_ZERO [label="0"]; + INT_POS [label="1, 2, …"]; + {rank=same; INT_NEG; INT_ZERO; INT_POS;} + INT_NEG -> INT_ZERO -> INT_POS [style=invis]; + INT_TOP -> {INT_NEG INT_ZERO INT_POS}; + {INT_NEG INT_ZERO INT_POS} -> INT_BOT; + } + + subgraph cluster_float { + label="Float"; fontname="Arial"; color="#cccccc"; + FLT_TOP [label=<⊤:flt>, fillcolor=aqua, shape=oval]; + FLT_BOT [label=<⊥:flt>, fillcolor=aqua, shape=oval]; + + FLT_MINDOTS [label="… negative constants", fillcolor=aqua, shape=oval]; + FLT_ZERO [label="0.0" , fillcolor=aqua]; + FLT_MAXDOTS [label="positive constants …", fillcolor=aqua, shape=oval]; + + FLT_TOP -> FLT_MINDOTS; + FLT_TOP -> FLT_ZERO; + FLT_TOP -> FLT_MAXDOTS; + FLT_MINDOTS -> FLT_BOT; + FLT_ZERO -> FLT_BOT; + FLT_MAXDOTS -> FLT_BOT; + + FLT_MINDOTS -> FLT_ZERO -> FLT_MAXDOTS [style=invis]; + + {rank=same; FLT_MINDOTS; FLT_ZERO; FLT_MAXDOTS;} + } + + subgraph cluster_pointer { + label="Pointer = nullability × struct type"; + fontname="Arial"; color="#cccccc"; + node [fillcolor="#008000", fontcolor=white]; + PTR_TOP [label="⊤:ptr\n[*⊤:struct]"]; + PTR_BOT [label="⊥:ptr\n[*⊥:struct?]"]; + PTR_NULL [label="null"]; + PTR_ANY [label="*⊥:struct\n[ptr any struct]"]; + PTR_PERSON [label="*Person"]; + PTR_S1 [label="*s1"]; + PTR_MORE [label="*s2, …"]; + PTR_PERSON_NIL [label="*Person?"]; + PTR_S1_NIL [label="*s1?"]; + PTR_MORE_NIL [label="*s2?, …"]; + {rank=same; PTR_PERSON; PTR_S1; PTR_MORE; PTR_NULL;} + {rank=same; PTR_ANY; PTR_PERSON_NIL; PTR_S1_NIL; PTR_MORE_NIL;} + PTR_PERSON -> PTR_S1 -> PTR_MORE -> PTR_NULL [style=invis]; + PTR_ANY -> PTR_PERSON_NIL -> PTR_S1_NIL -> PTR_MORE_NIL [style=invis]; + PTR_TOP -> {PTR_PERSON PTR_S1 PTR_MORE PTR_NULL}; + {PTR_PERSON PTR_S1 PTR_MORE} -> PTR_ANY; + PTR_PERSON -> PTR_PERSON_NIL; + PTR_S1 -> PTR_S1_NIL; + PTR_MORE -> PTR_MORE_NIL; + PTR_NULL -> {PTR_PERSON_NIL PTR_S1_NIL PTR_MORE_NIL}; + {PTR_ANY PTR_PERSON_NIL PTR_S1_NIL PTR_MORE_NIL} -> PTR_BOT; + } + + subgraph cluster_struct { + label="Struct\nnamed collection of named scalar types"; + fontname="Arial"; color="#cccccc"; + node [fillcolor="#90ee90"]; + STRUCT_TOP [label="⊤:struct\n[struct top]"]; + STRUCT_BOT [label="⊥:struct\n[struct bottom]"]; + STRUCT_PERSON [label="Person\nage: int", shape=box]; + STRUCT_S1 [label="s1\nx: int", shape=box]; + STRUCT_S2 [label="s2\nx: int, y: flt", shape=box]; + STRUCT_MORE [label="…", shape=box]; + {rank=same; STRUCT_PERSON; STRUCT_S1; STRUCT_S2; STRUCT_MORE;} + STRUCT_PERSON -> STRUCT_S1 -> STRUCT_S2 -> STRUCT_MORE [style=invis]; + STRUCT_TOP -> {STRUCT_PERSON STRUCT_S1 STRUCT_S2 STRUCT_MORE}; + {STRUCT_PERSON STRUCT_S1 STRUCT_S2 STRUCT_MORE} -> STRUCT_BOT; + } + + subgraph cluster_memory { + label="Memory\nprecise alias slices"; fontname="Arial"; color="#cccccc"; + node [fillcolor="#00008b", fontcolor=white]; + MEM_TOP [label="⊤:mem"]; + MEM_BOT [label="⊥:mem"]; + MEM_ALIAS2 [label="MEM#2"]; + MEM_ALIAS3 [label="MEM#3"]; + MEM_MORE [label="…"]; + {rank=same; MEM_ALIAS2; MEM_ALIAS3; MEM_MORE;} + MEM_ALIAS2 -> MEM_ALIAS3 -> MEM_MORE [style=invis]; + MEM_TOP -> {MEM_ALIAS2 MEM_ALIAS3 MEM_MORE}; + {MEM_ALIAS2 MEM_ALIAS3 MEM_MORE} -> MEM_BOT; + } + + subgraph cluster_tuple { + label="Tuple\ncollection of types"; + fontname="Arial"; color="#cccccc"; + node [fillcolor="#ffc0cb"]; + TUPLE_TOP [label="⊤:tuple"]; + TUPLE_BOT [label="⊥:tuple"]; + TUPLE1 [label="(type)", shape=box]; + TUPLE2 [label="(type, type)", shape=box]; + TUPLEN [label="(type, …)", shape=box]; + {rank=same; TUPLE1; TUPLE2; TUPLEN;} + TUPLE1 -> TUPLE2 -> TUPLEN [style=invis]; + TUPLE_TOP -> {TUPLE1 TUPLE2 TUPLEN}; + {TUPLE1 TUPLE2 TUPLEN} -> TUPLE_BOT; + } + + TOP -> {XCTRL INT_TOP FLT_TOP PTR_TOP STRUCT_TOP MEM_TOP TUPLE_TOP}; + {CTRL INT_BOT FLT_BOT PTR_BOT STRUCT_BOT MEM_BOT TUPLE_BOT} -> BOT; + {rank=same; XCTRL; INT_TOP; FLT_TOP; PTR_TOP; STRUCT_TOP; MEM_TOP; TUPLE_TOP;} + {rank=same; CTRL; INT_BOT; FLT_BOT; PTR_BOT; STRUCT_BOT; MEM_BOT; TUPLE_BOT;} + XCTRL -> INT_TOP -> FLT_TOP -> PTR_TOP -> STRUCT_TOP -> MEM_TOP -> TUPLE_TOP [style=invis]; } diff --git a/chapter12/docs/lattice.svg b/chapter12/docs/lattice.svg index 1bb4f692..bc64abb6 100644 --- a/chapter12/docs/lattice.svg +++ b/chapter12/docs/lattice.svg @@ -1,598 +1,708 @@ - - - - - - -Lattice - - - -TOP - -⊤ - - - -XCTRL - -⊤ -:ctrl - - - -TOP->XCTRL - - - - - -INT_TOP - -⊤ -:int - - - -TOP->INT_TOP - - - - - -FLT_TOP - -⊤ -:flt - - - -TOP->FLT_TOP - - - - - -PTR - - - -*ptr - - -struct - - - -TOP->PTR - - - - - -STRUCT_TOP - -⊤ -:struct - - - -TOP->STRUCT_TOP - - - - - -MEM_TOP - -⊤ -:mem - - - -TOP->MEM_TOP - - - - - -TUPLE_TOP - -⊤ -:tuple - - - -TOP->TUPLE_TOP - - - - - -BOT - -⊥ - - - -CTRL - -⊥ -:ctrl - - - -XCTRL->CTRL - - - - - -CTRL->BOT - - - - - -INT_MINDOTS - -... - - - -INT_TOP->INT_MINDOTS - - - - - -INT_ZERO - -0 - - - -INT_TOP->INT_ZERO - - - - - -INT_MAXDOTS - -... - - - -INT_TOP->INT_MAXDOTS - - - - - -INT_BOT - -⊥ -:int - - - -INT_BOT->BOT - - - - - -INT_MINDOTS->INT_BOT - - - - - - -INT_ZERO->INT_BOT - - - - - - -INT_MAXDOTS->INT_BOT - - - - - -FLT_MINDOTS - -... - - - -FLT_TOP->FLT_MINDOTS - - - - - -FLT_ZERO - -0 - - - -FLT_TOP->FLT_ZERO - - - - - -FLT_MAXDOTS - -... - - - -FLT_TOP->FLT_MAXDOTS - - - - - -FLT_BOT - -⊥ -:flt - - - -FLT_BOT->BOT - - - - - -FLT_MINDOTS->FLT_BOT - - - - - - -FLT_ZERO->FLT_BOT - - - - - - -FLT_MAXDOTS->FLT_BOT - - - - - -PTR0 - - - -*ptr? - - -struct - - - -PTR->PTR0 - - - - - -PTR0->BOT - - - - - -STRUCT_S1 - - - -field - - - - - - - - -int/ptr - - - -STRUCT_TOP->STRUCT_S1 - - - - - -STRUCT_S2 - - - -field - - - - - - - - -int/ptr - - -field - - - - - - - - -int/ptr - - - -STRUCT_TOP->STRUCT_S2 - - - - - -STRUCT_SN - - - -field - - - - - - - - -int/ptr - - -...   - - - - - - - - -int/ptr - - -field - - - - - - - - -int/ptr - - - -STRUCT_TOP->STRUCT_SN - - - - - -STRUCT_BOT - -⊥ -:struct - - - -STRUCT_BOT->BOT - - - - - -STRUCT_S1->STRUCT_BOT - - - - - - -STRUCT_S2->STRUCT_BOT - - - - - - -STRUCT_SN->STRUCT_BOT - - - - - -MEM_ALIAS1 - -#1 - - - -MEM_TOP->MEM_ALIAS1 - - - - - -MEM_ALIASDOTS - -... - - - -MEM_TOP->MEM_ALIASDOTS - - - - - -MEM_ALIASN - -#n - - - -MEM_TOP->MEM_ALIASN - - - - - -MEM_BOT - -⊥ -:mem - - - -MEM_BOT->BOT - - - - - -MEM_ALIAS1->MEM_BOT - - - - - - -MEM_ALIASDOTS->MEM_BOT - - - - - - -MEM_ALIASN->MEM_BOT - - - - - -TUPLE1 - - - -Tuple - - -type - - - -TUPLE_TOP->TUPLE1 - - - - - -TUPLE2 - - - -Tuple - - -type - - -type - - - -TUPLE_TOP->TUPLE2 - - - - - -TUPLEN - - - -Tuple - - -type - - -... - - -type - - - -TUPLE_TOP->TUPLEN - - - - - -TUPLE_BOT - -⊥ -:tuple - - - -TUPLE_BOT->BOT - - - - - -TUPLE1->TUPLE_BOT - - - - - -TUPLE2->TUPLE_BOT - - - - - -TUPLEN->TUPLE_BOT - - - - - + + + + + + +Lattice + + +cluster_control + +Control + + +cluster_integer + +Integer + + +cluster_float + +Float + + +cluster_pointer + +Pointer = nullability × struct type + + +cluster_struct + +Struct +named collection of named scalar types + + +cluster_memory + +Memory +precise alias slices + + +cluster_tuple + +Tuple +collection of types + + + +TOP + +⊤ + + + +XCTRL + +⊤:ctrl + + + +TOP->XCTRL + + + + + +INT_TOP + +⊤:int + + + +TOP->INT_TOP + + + + + +FLT_TOP + +⊤ +:flt + + + +TOP->FLT_TOP + + + + + +PTR_TOP + +⊤:ptr +[*⊤:struct] + + + +TOP->PTR_TOP + + + + + +STRUCT_TOP + +⊤:struct +[struct top] + + + +TOP->STRUCT_TOP + + + + + +MEM_TOP + +⊤:mem + + + +TOP->MEM_TOP + + + + + +TUPLE_TOP + +⊤:tuple + + + +TOP->TUPLE_TOP + + + + + +BOT + +⊥ + + + +CTRL + +⊥:ctrl + + + +XCTRL->CTRL + + + + + + +CTRL->BOT + + + + + +INT_NEG + +… −2, −1 + + + +INT_TOP->INT_NEG + + + + + +INT_ZERO + +0 + + + +INT_TOP->INT_ZERO + + + + + +INT_POS + +1, 2, … + + + +INT_TOP->INT_POS + + + + + + +INT_BOT + +⊥:int + + + +INT_BOT->BOT + + + + + +INT_NEG->INT_BOT + + + + + + +INT_ZERO->INT_BOT + + + + + + +INT_POS->INT_BOT + + + + + +FLT_MINDOTS + +… negative constants + + + +FLT_TOP->FLT_MINDOTS + + + + + +FLT_ZERO + +0.0 + + + +FLT_TOP->FLT_ZERO + + + + + +FLT_MAXDOTS + +positive constants … + + + +FLT_TOP->FLT_MAXDOTS + + + + + + +FLT_BOT + +⊥ +:flt + + + +FLT_BOT->BOT + + + + + +FLT_MINDOTS->FLT_BOT + + + + + + +FLT_ZERO->FLT_BOT + + + + + + +FLT_MAXDOTS->FLT_BOT + + + + + +PTR_NULL + +null + + + +PTR_TOP->PTR_NULL + + + + + +PTR_PERSON + +*Person + + + +PTR_TOP->PTR_PERSON + + + + + +PTR_S1 + +*s1 + + + +PTR_TOP->PTR_S1 + + + + + +PTR_MORE + +*s2, … + + + +PTR_TOP->PTR_MORE + + + + + + +PTR_BOT + +⊥:ptr +[*⊥:struct?] + + + +PTR_BOT->BOT + + + + + +PTR_PERSON_NIL + +*Person? + + + +PTR_NULL->PTR_PERSON_NIL + + + + + +PTR_S1_NIL + +*s1? + + + +PTR_NULL->PTR_S1_NIL + + + + + +PTR_MORE_NIL + +*s2?, … + + + +PTR_NULL->PTR_MORE_NIL + + + + + +PTR_ANY + +*⊥:struct +[ptr any struct] + + + +PTR_ANY->PTR_BOT + + + + + + +PTR_PERSON->PTR_ANY + + + + + + +PTR_PERSON->PTR_PERSON_NIL + + + + + +PTR_S1->PTR_ANY + + + + + + +PTR_S1->PTR_S1_NIL + + + + + + +PTR_MORE->PTR_ANY + + + + + +PTR_MORE->PTR_MORE_NIL + + + + + +PTR_PERSON_NIL->PTR_BOT + + + + + + +PTR_S1_NIL->PTR_BOT + + + + + + +PTR_MORE_NIL->PTR_BOT + + + + + +STRUCT_PERSON + +Person +age: int + + + +STRUCT_TOP->STRUCT_PERSON + + + + + +STRUCT_S1 + +s1 +x: int + + + +STRUCT_TOP->STRUCT_S1 + + + + + +STRUCT_S2 + +s2 +x: int, y: flt + + + +STRUCT_TOP->STRUCT_S2 + + + + + +STRUCT_MORE + +… + + + +STRUCT_TOP->STRUCT_MORE + + + + + + +STRUCT_BOT + +⊥:struct +[struct bottom] + + + +STRUCT_BOT->BOT + + + + + +STRUCT_PERSON->STRUCT_BOT + + + + + + +STRUCT_S1->STRUCT_BOT + + + + + + +STRUCT_S2->STRUCT_BOT + + + + + + +STRUCT_MORE->STRUCT_BOT + + + + + +MEM_ALIAS2 + +MEM#2 + + + +MEM_TOP->MEM_ALIAS2 + + + + + +MEM_ALIAS3 + +MEM#3 + + + +MEM_TOP->MEM_ALIAS3 + + + + + +MEM_MORE + +… + + + +MEM_TOP->MEM_MORE + + + + + + +MEM_BOT + +⊥:mem + + + +MEM_BOT->BOT + + + + + +MEM_ALIAS2->MEM_BOT + + + + + + +MEM_ALIAS3->MEM_BOT + + + + + + +MEM_MORE->MEM_BOT + + + + + +TUPLE1 + +(type) + + + +TUPLE_TOP->TUPLE1 + + + + + +TUPLE2 + +(type, type) + + + +TUPLE_TOP->TUPLE2 + + + + + +TUPLEN + +(type, …) + + + +TUPLE_TOP->TUPLEN + + + + + +TUPLE_BOT + +⊥:tuple + + + +TUPLE_BOT->BOT + + + + + +TUPLE1->TUPLE_BOT + + + + + + +TUPLE2->TUPLE_BOT + + + + + + +TUPLEN->TUPLE_BOT + + + + + diff --git a/chapter13/README.md b/chapter13/README.md index 1c492468..38b512cc 100644 --- a/chapter13/README.md +++ b/chapter13/README.md @@ -1,5 +1,8 @@ # Chapter 13: References +[Previous: Chapter 12](../chapter12/README.md) | +[Next: Chapter 14](../chapter14/README.md) + Memory retains one `$mem` binding and lazy partitions. Typed initialization stores now include each field's declared type and initialization flag, while `MemMerge` preserves the other fields. Start and Return keep control in slot 0 @@ -8,9 +11,9 @@ and memory in slot 1. # Table of Contents 1. [References](#references) - - [Forward References](#forward-references) - - [Self-referential references](#self-referential-references) - - [Auto deepen forward ref types](#auto-deepen-forward-ref-types) + - [Forward References](#forward-references) + - [Self-referential references](#self-referential-references) + - [Auto deepen forward ref types](#auto-deepen-forward-ref-types) 2. [Global Code Motion Example](#global-code-motion-walkthrough) In this chapter, we add references and structs. @@ -39,7 +42,7 @@ FamilyTree? tree; // A family tree, or not ... ``` At the time of the `Person` struct definition, the `FamilyTree` struct is not yet defined. This is a forward reference. To handle this, we assume the struct will be defined later. -```java +```java Type t = TYPES.get(tname); // Assume a forward-reference type if( t == null ) { @@ -55,7 +58,7 @@ Type t = TYPES.get(tname); ``` Reference fields start out as null, doing anything with them will result in a compile time error. -```java +```java struct Person { String name; int age; @@ -63,11 +66,11 @@ struct Person { } Person p = new Person; p.tree.la = null; // Accessing unknown field 'la' from 'null' - + ``` It turns out `p.tree` is `null`, so we can't access the field `la` from it. -```java +```java // name = "tree" // mem() is the current aggregate; its tree alias selects the initializing Store. // in(3) = {ConstantNode@1651} "null" @@ -76,7 +79,7 @@ return parsePostfix(new LoadNode(name, alias, declaredType.glb(), mem(), expr).p `LoadNode::idealize` LoadNode first selects its alias through any MemMerge, then returns `st.val()` when it finds a matching Store to the same object. -```java +```java // Simple Load-after-Store on same address. if( mem() instanceof StoreNode st && ptr() == st.ptr() && _alias == st._alias ) { // Same object and field @@ -115,8 +118,8 @@ private Node newStruct(TypeStruct obj) { ``` Zooming in.... -```java -// parsing = FamilyTree? tree; +```java +// parsing = FamilyTree? tree; for( Field field : obj._fields ) { // field._type = *FamilyTree? // REMEMBER: @@ -128,7 +131,7 @@ for( Field field : obj._fields ) { In a case of a reference `field._type.makeInit()` will return a `NULLPTR`, later this is what the peephole turns into when loading the field. `p.tree` ---- +--- ```java struct N { N next; int i; } @@ -137,16 +140,16 @@ return n.next; // Value reports as null, despite field typed as not-null ``` As shown above, we explicitly allow not-null fields to be null initialized (as -of chapter13). We can't allow null to be stored into a not-null field, but we +of Chapter 13). We can't allow null to be stored into a not-null field, but we can allow a not-null field to be null (initially). This will be corrected in a later chapter. ### Self-referential references -Self-cyclic or self-referential types are types that include a reference to themsleves as part of their defintion. +Self-cyclic or self-referential types are types that include a reference to themselves as part of their definition. Consider the following code: -```java +```java struct N { N next; int i; } N n = new N; n.next = null; // <<-- Compile error, cannot store null into not-null field @@ -163,13 +166,13 @@ When `a.next` is encountered, we auto deepen the type so its fields are going to This is needed to resolve the stale type that the loop brings around. -```java +```java if( e instanceof TypeMemPtr tmp && tmp._obj._fields==null ) { e = tmp.make_from((TypeStruct) TYPES.get(tmp._obj._name)); } -``` +``` -```java +```java struct LLI { LLI? next; int i; } LLI? head = null; while( arg ) { @@ -187,7 +190,7 @@ return next.i; --- -Normal field syntax works: +Normal field syntax works: e.g. `person.tree.father = new Person;` or `person.tree.father.name = "Dad";`. @@ -218,7 +221,7 @@ Now that we have all these new features covered consider the following example: struct Person { String name; int age; - FamilyTree? tree; + FamilyTree? tree; } Person p = new Person; p.age =1; @@ -244,7 +247,7 @@ From: $ctrl to: $ctrl|.age=(19) From: $ctrl to: $ctrl|.tree=(17) ``` The control nodes are already set so the early schedule is useless. -All the nodes involed: Return, Constant, NewNode specific their control input explicitly so there is nothing to do. +All the nodes involved: Return, Constant, NewNode specify their control input explicitly so there is nothing to do. #### Late schedule: ``` @@ -253,7 +256,7 @@ From: Start to: $ctrl(18) ``` We see that the late schedule actually changes the control input of the StartNode to the $ctrl node in 2 cases. The algo that does this is: -```java +```java // Walk up from the LCA to the early, looking for best place. This is // the lowest execution frequency, approximated by least loop depth and // deepest control flow. diff --git a/chapter14/README.md b/chapter14/README.md index acd8a492..a68baa5c 100644 --- a/chapter14/README.md +++ b/chapter14/README.md @@ -1,5 +1,8 @@ # Chapter 14: Narrow types +[Previous: Chapter 13](../chapter13/README.md) | +[Next: Chapter 15](../chapter15/README.md) + Memory retains the single `$mem` binding and lazy partitions from Chapter 10b. Narrow-field stores perform this chapter's truncation before updating their alias in MemMerge. Start and Return keep control in slot 0 and memory in slot 1. @@ -7,9 +10,9 @@ alias in MemMerge. Start and Return keep control in slot 0 and memory in slot 1. # Table of Contents 1. [Narrow Word Types](#narrow-or-sub-word-types) -2. [OverFlow handling](#overflow-handling) +2. [Overflow handling](#overflow-handling) 3. [Integer ranges](#integer-ranges) -4. [Bitwise operations](#examples) +4. [Bitwise operations](#bitwise-operations) 5. [Precedence](#precedence) 6. [Type lattice](#type-implementation) 7. [Nodes](#nodes) @@ -21,7 +24,7 @@ You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linea ## Narrow or sub-word types -Narrow or sub-worded integer types refer to integer data types that occupy less memory (fewer bits) than the standard or "full-width"(Typically 32, or 64 bits) integer types provided by a system or programming language. +Narrow or sub-word integer types refer to integer data types that occupy less memory (fewer bits) than the standard or "full-width" (typically 32 or 64 bits) integer types provided by a system or programming language. As a prelude to arrays, especially arrays of bytes common in all networking @@ -32,34 +35,34 @@ extended on a load. ```java i8 x = 123456789; -if( x != 21 ) +if( x != 21 ) return false; return true; ``` -The variable `x` is limited to 8 bits signed. Assigning the vary large value +The variable `x` is limited to 8 bits signed. Assigning the very large value `123456789` (hex `0x75BCD15`) simply truncates to 8 bits yielding `21 (0x15)`. The value is sign-extended on a load. ```java i16 x = 123456789; -if( x != -13035 ) +if( x != -13035 ) return false; return true; ``` -The variable `x` is limited to 16 bits signed. Assigning the vary large value +The variable `x` is limited to 16 bits signed. Assigning the very large value `0x75BCD15` simply truncates to 16 bits yielding `0xCD15`. The value is sign-extended on a load yielding `-13035 (0xFFFF FFFF FFFF CD15)`. ```java u16 x = 123456789; -if( x != 52501 ) +if( x != 52501 ) return false; return true; ``` -The variable `x` is limited to 16 bits unsigned. Assigning the vary large value +The variable `x` is limited to 16 bits unsigned. Assigning the very large value `0x75BCD15` simply truncates to 16 bits yielding `0xCD15`. The value is zero-extended on a load yielding `52501 (0x0000 0000 0000 CD15)`. @@ -91,10 +94,10 @@ There are several cases of overflow: #### Unsigned(fixed-width) integer overflow: -```java -u8 a = 255; +```java +u8 a = 255; u8 b = a + 1; // match u8 type against expr.type -// a = 256 +// a = 256 // u8 = [0...255] return b; ``` @@ -113,7 +116,7 @@ The operands to the "bitwise AND" are the values(256) and the mask(255, max boun This is called truncating. `ZsMask:` -```java +```java // zero/sign extend. "i" is limited to either classic unsigned (min==0) or // classic signed (min=minus-power-of-2); max=power-of-2-minus-1. private Node zsMask(Node val, Type t ) { @@ -140,29 +143,29 @@ The truncation is done by the `AndNode`: if( t0._min==0 ) // Unsigned return new AndNode(val,con(t0._max)).peephole(); ``` -Since they are constants, after calling peephole it truns into`256 & 255` = 0; +Since they are constants, after calling peephole it turns into `256 & 255` = 0; Output: ``` -return 0; +return 0; ``` #### Maximum integer overflow -```java -i64 a = 9223372036854775807; +```java +i64 a = 9223372036854775807; i64 b = a + 1; return b; ``` When we are computing the addition, we make sure they don't overflow: `AddNode.overflow:` -```java +```java private static boolean overflow( long x, long y ) { if( (x ^ y ) < 0 ) return false; // unequal signs, never overflow return (x ^ (x + y)) < 0; // sum has unequal signs, so overflow } ``` `AddNode.compute` -```java +```java ... // Fold ranges like {0-1} + {2-3} into {2-4}. if( !overflow(i1._min,i2._min) && @@ -183,8 +186,8 @@ return TypeInteger.constant(i1.value()+i2.value()); // -9223372036854775808; ``` #### Adding constant ranges -```java -u8 a = 12; +```java +u8 a = 12; u8 b = 13; u8 c = 124; u8 d = a + b + c; @@ -197,30 +200,30 @@ public static TypeInteger make(boolean is_con, long con) { return make(is_con ? con : (con==0 ? Long.MAX_VALUE : Long.MIN_VALUE), is_con ? con : (con==0 ? Long.MIN_VALUE : Long.MAX_VALUE)); ``` -- This results in: +- This results in: ```java return make(con, con); ``` -`value()` is only called in constants, e.g `_min == _max;` invariants holds, then since +`value()` is only called in constants, e.g `_min == _max;` invariant holds, then since both `min_` and `max_` are equal, we can return either one. This is the same as regular additions: -```java -public long value() { assert isConstant(); return _min; } +```java +public long value() { assert isConstant(); return _min; } ``` #### Truncate(2) -```java +```java u8 a = arg; // arg & 255 u8 b = arg; // arg & 255(same as a) u8 c = a + b; // (arg&255)*2, type = TypeInteger.BOT -return c; // (((arg&255)*2)&255), type = TypeInteger.U8 +return c; // (((arg&255)*2)&255), type = TypeInteger.U8 ``` Same as before, **arg** turns into **(arg&255)**, this node is then inserted into the **GVN** table and **b** retrieves this value. -The AddNode peephole will change them into `((arg&255)*2`, and put on extra mask +The AddNode peephole will change them into `((arg&255)*2)`, and put on extra mask on the expression to keep it in the valid boundaries. @@ -238,15 +241,15 @@ And `&`, Or `|`, Xor `^`, Shift left `<<`, Shift right `>>`, Shift right zero `> | **Or** | `\|` | Performs a bitwise OR (inclusive OR) operation. | | **Xor** | `^` | Performs a bitwise XOR (exclusive OR) operation. | | **Shift Left** | `<<` | Shifts bits to the left, filling with zeros. | -| **Shift Right** | `>>` | Shifts bits to the right, any vacated bit postions are filled by replicating the value of the sign bit. | -| **Unsigned Right Shift** | `>>>` | Shifts bits to the right, any vacated bit postions are always filled with zero | +| **Shift Right** | `>>` | Shifts bits to the right, any vacated bit positions are filled by replicating the value of the sign bit. | +| **Unsigned Right Shift** | `>>>` | Shifts bits to the right, any vacated bit positions are always filled with zero | Note `>>>` is a logical shift and not an arithmetic shift. #### AndNode: ##### lhs & -1 = lhs; -```java +```java // And of -1. We do not check for (-1&x) because this will already // canonicalize to (x&-1) if( t2.isConstant() && t2 instanceof TypeInteger i && i.value()==-1 ) @@ -306,7 +309,7 @@ arg + 123 & 3 = (arg + 123) & 3 ## Type Implementation -The TypeInteger type class is +The ![Integer](../chapter10a/docs/type-integer.svg) `TypeInteger` class is reworked to support a full range of min/max values. At this time, only some power-of-2 sized ranges are exposed to the programmer but the optimizer internally supports all ranges. The MEET operation takes the min-of-mins and @@ -322,7 +325,11 @@ Example: the `i8` type has the range `[-128...127]`. Example: the `dual` of `bool` is `[1...0]` (just swap min and max). -The TypeFloat class is also reworked to support 32-bit and 64-bit sizes. +The ![Float](../docs/type-float.svg) `TypeFloat` class is also reworked to support 32-bit and 64-bit sizes. + +The integer range diagram is schematic: it shows the boolean range and its +dual as examples among the possible ranges. The other domains retain the +named structs, nullable pointers, and precise memory aliases from earlier chapters. ![Graph1](./docs/lattice.svg) @@ -350,4 +357,4 @@ slightly different `idealize()` calls. [^1]: Hacker's delight. - 4-2 Propagating Bounds through Add's and Subtract's + 4-2 Propagating Bounds through Adds and Subtracts diff --git a/chapter14/docs/lattice.gv b/chapter14/docs/lattice.gv index f16a9768..ac2f1f2e 100644 --- a/chapter14/docs/lattice.gv +++ b/chapter14/docs/lattice.gv @@ -1,202 +1,159 @@ digraph Lattice { - compound = true; - // Define nodes - splines=false; - node [shape=circle, style=filled]; - nodesep=0.6; - - TOP [label=<⊤>, fillcolor=black, fontcolor=white]; - BOT [label=<⊥>, fillcolor=black, fontcolor=white]; - - // ---------------------- - // Control - XCTRL [label=<⊤:ctrl>, fillcolor=yellow, shape=oval]; - CTRL [label=<⊥:ctrl>, fillcolor=yellow, shape=oval]; - - TOP -> XCTRL; - XCTRL -> CTRL; - CTRL -> BOT; - - // ---------------------- - // Integers - INT_TOP [label=<⊤:int>, fillcolor=lightblue, shape=oval]; - INT_BOT [label=<⊥:int>, fillcolor=lightblue, shape=oval]; - - INT_HI [label="max < min" , fillcolor=lightblue, shape=oval]; - INT_XBOOL [label="1...0", fillcolor=lightblue, shape=oval]; - INT_CON [label="constants", fillcolor=lightblue, shape=oval]; - INT_CON0 [label="0", fillcolor=lightblue]; - INT_CON1 [label="1", fillcolor=lightblue]; - INT_BOOL [label="0...1", fillcolor=lightblue,shape=oval]; - INT_LO [label="max > min" , fillcolor=lightblue, shape=oval]; - - TOP -> INT_TOP; - INT_TOP -> INT_HI; - INT_HI -> INT_XBOOL; - INT_XBOOL -> INT_CON0; - INT_XBOOL -> INT_CON1; - INT_HI -> INT_CON; - INT_CON0 -> INT_BOOL; - INT_CON1 -> INT_BOOL; - INT_BOOL -> INT_LO; - INT_CON -> INT_LO; - INT_LO -> INT_BOT; - INT_BOT -> BOT; - - INT_CON0 -> INT_CON1 -> INT_CON [style=invis]; - - // ---------------------- - // Floats - FLT_TOP [label=<⊤:flt>, fillcolor=aqua, shape=oval]; - FLT_BOT [label=<⊥:flt>, fillcolor=aqua, shape=oval]; - - FLT_CON64 [label="64b consts\n[excludes\n32b consts]" , fillcolor=aqua, shape=oval]; - FLT_CON32 [label="32b consts", fillcolor=aqua, shape=oval]; - FLT_CONPI [label="3.14159...", fillcolor=aqua, shape=oval]; - FLT_X32 [label="~f32", fillcolor=aqua]; - FLT_CON0 [label="0." , fillcolor=aqua]; - FLT_32 [label="f32" , fillcolor=aqua]; - - TOP -> FLT_TOP; - FLT_TOP -> FLT_CON64 - FLT_TOP -> FLT_CONPI - FLT_CON64 -> FLT_BOT - FLT_CONPI -> FLT_BOT - - FLT_TOP -> FLT_X32; - FLT_X32 -> FLT_CON0; - FLT_X32 -> FLT_CON32; - FLT_CON0 -> FLT_32; - FLT_CON32 -> FLT_32; - FLT_32 -> FLT_BOT - - FLT_BOT -> BOT; - - FLT_CON0 -> FLT_CON32 -> FLT_CONPI -> FLT_CON64 [style=invis]; - - - // ---------------------- - // Pointers, just a boolean nil/not and a struct - PTR [shape=none, fillcolor=none, label=< - - - -
*ptr
struct
- >]; - PTR0 [shape=none, fillcolor=none, label=< - - - -
*ptr?
struct
- >]; - - TOP -> PTR; - PTR -> PTR0; - PTR0 -> BOT; - - // ---------------------- - // Structs - STRUCT_TOP [label=<⊤:struct>, fillcolor=lightgreen, shape=oval]; - STRUCT_BOT [label=<⊥:struct>, fillcolor=lightgreen, shape=oval]; - - STRUCT_S1 [shape=none, fillcolor=none, label=< - - -
fieldint/ptr
- >]; - STRUCT_S2 [shape=none, fillcolor=none, label=< - - - -
fieldint/ptr
fieldint/ptr
- >]; - STRUCT_SN [shape=none, fillcolor=none, label=< - - - - -
fieldint/ptr
... int/ptr
fieldint/ptr
- >]; - - - TOP -> STRUCT_TOP; - STRUCT_TOP -> STRUCT_S1; - STRUCT_TOP -> STRUCT_S2; - STRUCT_TOP -> STRUCT_SN; - STRUCT_S1 -> STRUCT_BOT; - STRUCT_S2 -> STRUCT_BOT; - STRUCT_SN -> STRUCT_BOT; - STRUCT_BOT -> BOT; - - STRUCT_S1 -> STRUCT_S2 -> STRUCT_SN [style=invis]; - - // ---------------------- - // Memory - MEM_TOP [label=<⊤:mem>, fillcolor=blue, fontcolor=white, shape=oval]; - MEM_BOT [label=<⊥:mem>, fillcolor=blue, fontcolor=white, shape=oval]; - MEM_ALIAS1 [label="#1" , fillcolor=blue, fontcolor=white]; - MEM_ALIASDOTS [label="..." , fillcolor=blue, fontcolor=white, shape=oval]; - MEM_ALIASN [label="#n" , fillcolor=blue, fontcolor=white]; - - TOP -> MEM_TOP; - MEM_TOP -> MEM_ALIAS1; - MEM_TOP -> MEM_ALIASDOTS; - MEM_TOP -> MEM_ALIASN; - MEM_ALIAS1 -> MEM_BOT; - MEM_ALIASDOTS -> MEM_BOT; - MEM_ALIASN -> MEM_BOT; - MEM_BOT -> BOT; - - MEM_ALIAS1 -> MEM_ALIASDOTS -> MEM_ALIASN [style=invis]; - - // ---------------------- - // Tuples - - TUPLE_TOP [label=<⊤:tuple>, fillcolor=pink, shape=oval]; - TUPLE_BOT [label=<⊥:tuple>, fillcolor=pink, shape=oval]; - - TUPLE1 [shape=none, fillcolor=none, label=< - - - -
Tuple
type
- >]; - TUPLE2 [shape=none, fillcolor=none, label=< - - - - -
Tuple
type
type
- >]; - TUPLEN [shape=none, fillcolor=none, label=< - - - - - -
Tuple
type
...
type
- >]; - - - TOP -> TUPLE_TOP; - TUPLE_TOP -> TUPLE1; - TUPLE_TOP -> TUPLE2; - TUPLE_TOP -> TUPLEN; - TUPLE1 -> TUPLE_BOT; - TUPLE2 -> TUPLE_BOT; - TUPLEN -> TUPLE_BOT; - TUPLE_BOT -> BOT; - - // ---------------------- - // Additional customization - {rank=same; TOP;} - {rank=same; INT_TOP; FLT_TOP; XCTRL; PTR; STRUCT_TOP; MEM_TOP; TUPLE_TOP} - {rank=same; INT_CON; INT_CON0; INT_CON1; - FLT_CON32; FLT_CON64; FLT_CON0; FLT_CONPI; - STRUCT_S1; STRUCT_S2; STRUCT_SN; - MEM_ALIAS1; MEM_ALIASDOTS; MEM_ALIASN; - TUPLE1; TUPLE2; TUPLEN; + rankdir=TB; + newrank=true; + // Preserve the same-rank ordering edges through cluster layout. + remincross=false; + nodesep=0.22; + ranksep=0.65; + node [shape=ellipse, style=filled, fontname="DejaVu Sans", fontsize=13]; + edge [color="#555555", arrowsize=0.6]; + + // These arrows are lattice-order edges, not use/definition edges. + TOP [label="⊤", fillcolor=black, fontcolor=white]; + BOT [label="⊥", fillcolor=black, fontcolor=white]; + + subgraph cluster_control { + label="Control"; fontname="Arial"; color="#cccccc"; + node [fillcolor="#ffff00"]; + XCTRL [label="⊤:ctrl"]; + CTRL [label="⊥:ctrl"]; + XCTRL -> CTRL; } - {rank=same; INT_BOT; FLT_BOT; CTRL; PTR0; STRUCT_BOT; MEM_BOT; TUPLE_BOT} - {rank=same; BOT;} + + subgraph cluster_integer { + label="Integer ranges (schematic)"; fontname="Arial"; color="#cccccc"; + INT_TOP [label=<⊤:int>, fillcolor=lightblue, shape=oval]; + INT_BOT [label=<⊥:int>, fillcolor=lightblue, shape=oval]; + + INT_HI [label="max < min" , fillcolor=lightblue, shape=oval]; + INT_XBOOL [label="1...0", fillcolor=lightblue, shape=oval]; + INT_CON [label="constants", fillcolor=lightblue, shape=oval]; + INT_CON0 [label="0", fillcolor=lightblue]; + INT_CON1 [label="1", fillcolor=lightblue]; + INT_BOOL [label="0...1", fillcolor=lightblue,shape=oval]; + INT_LO [label="max > min" , fillcolor=lightblue, shape=oval]; + + INT_TOP -> INT_HI; + INT_HI -> INT_XBOOL; + INT_XBOOL -> INT_CON0; + INT_XBOOL -> INT_CON1; + INT_HI -> INT_CON; + INT_CON0 -> INT_BOOL; + INT_CON1 -> INT_BOOL; + INT_BOOL -> INT_LO; + INT_CON -> INT_LO; + INT_LO -> INT_BOT; + + INT_CON0 -> INT_CON1 -> INT_CON [style=invis]; + + {rank=same; INT_CON0; INT_CON1; INT_CON;} + } + + subgraph cluster_float { + label="Float"; fontname="Arial"; color="#cccccc"; + FLT_TOP [label=<⊤:flt>, fillcolor=aqua, shape=oval]; + FLT_BOT [label=<⊥:flt>, fillcolor=aqua, shape=oval]; + + FLT_CON64 [label="64b consts\n[excludes\n32b consts]" , fillcolor=aqua, shape=oval]; + FLT_CON32 [label="32b consts", fillcolor=aqua, shape=oval]; + FLT_CONPI [label="3.14159...", fillcolor=aqua, shape=oval]; + FLT_X32 [label="~f32", fillcolor=aqua]; + FLT_CON0 [label="0." , fillcolor=aqua]; + FLT_32 [label="f32" , fillcolor=aqua]; + + FLT_TOP -> FLT_CON64 + FLT_TOP -> FLT_CONPI + FLT_CON64 -> FLT_BOT + FLT_CONPI -> FLT_BOT + + FLT_TOP -> FLT_X32; + FLT_X32 -> FLT_CON0; + FLT_X32 -> FLT_CON32; + FLT_CON0 -> FLT_32; + FLT_CON32 -> FLT_32; + FLT_32 -> FLT_BOT + + FLT_CON0 -> FLT_CON32 -> FLT_CONPI -> FLT_CON64 [style=invis]; + + + {rank=same; FLT_CON0; FLT_CON32; FLT_CONPI; FLT_CON64;} + } + + subgraph cluster_pointer { + label="Pointer = nullability × struct type"; + fontname="Arial"; color="#cccccc"; + node [fillcolor="#008000", fontcolor=white]; + PTR_TOP [label="⊤:ptr\n[*⊤:struct]"]; + PTR_BOT [label="⊥:ptr\n[*⊥:struct?]"]; + PTR_NULL [label="null"]; + PTR_ANY [label="*⊥:struct\n[ptr any struct]"]; + PTR_PERSON [label="*Person"]; + PTR_S1 [label="*s1"]; + PTR_MORE [label="*s2, …"]; + PTR_PERSON_NIL [label="*Person?"]; + PTR_S1_NIL [label="*s1?"]; + PTR_MORE_NIL [label="*s2?, …"]; + {rank=same; PTR_PERSON; PTR_S1; PTR_MORE; PTR_NULL;} + {rank=same; PTR_ANY; PTR_PERSON_NIL; PTR_S1_NIL; PTR_MORE_NIL;} + PTR_PERSON -> PTR_S1 -> PTR_MORE -> PTR_NULL [style=invis]; + PTR_ANY -> PTR_PERSON_NIL -> PTR_S1_NIL -> PTR_MORE_NIL [style=invis]; + PTR_TOP -> {PTR_PERSON PTR_S1 PTR_MORE PTR_NULL}; + {PTR_PERSON PTR_S1 PTR_MORE} -> PTR_ANY; + PTR_PERSON -> PTR_PERSON_NIL; + PTR_S1 -> PTR_S1_NIL; + PTR_MORE -> PTR_MORE_NIL; + PTR_NULL -> {PTR_PERSON_NIL PTR_S1_NIL PTR_MORE_NIL}; + {PTR_ANY PTR_PERSON_NIL PTR_S1_NIL PTR_MORE_NIL} -> PTR_BOT; + } + + subgraph cluster_struct { + label="Struct\nnamed collection of named scalar types"; + fontname="Arial"; color="#cccccc"; + node [fillcolor="#90ee90"]; + STRUCT_TOP [label="⊤:struct\n[struct top]"]; + STRUCT_BOT [label="⊥:struct\n[struct bottom]"]; + STRUCT_PERSON [label="Person\nage: int", shape=box]; + STRUCT_S1 [label="s1\nx: int", shape=box]; + STRUCT_S2 [label="s2\nx: int, y: *s1", shape=box]; + STRUCT_MORE [label="…", shape=box]; + {rank=same; STRUCT_PERSON; STRUCT_S1; STRUCT_S2; STRUCT_MORE;} + STRUCT_PERSON -> STRUCT_S1 -> STRUCT_S2 -> STRUCT_MORE [style=invis]; + STRUCT_TOP -> {STRUCT_PERSON STRUCT_S1 STRUCT_S2 STRUCT_MORE}; + {STRUCT_PERSON STRUCT_S1 STRUCT_S2 STRUCT_MORE} -> STRUCT_BOT; + } + + subgraph cluster_memory { + label="Memory\nprecise alias slices"; fontname="Arial"; color="#cccccc"; + node [fillcolor="#00008b", fontcolor=white]; + MEM_TOP [label="⊤:mem"]; + MEM_BOT [label="⊥:mem"]; + MEM_ALIAS2 [label="MEM#2"]; + MEM_ALIAS3 [label="MEM#3"]; + MEM_MORE [label="…"]; + {rank=same; MEM_ALIAS2; MEM_ALIAS3; MEM_MORE;} + MEM_ALIAS2 -> MEM_ALIAS3 -> MEM_MORE [style=invis]; + MEM_TOP -> {MEM_ALIAS2 MEM_ALIAS3 MEM_MORE}; + {MEM_ALIAS2 MEM_ALIAS3 MEM_MORE} -> MEM_BOT; + } + + subgraph cluster_tuple { + label="Tuple\ncollection of types"; + fontname="Arial"; color="#cccccc"; + node [fillcolor="#ffc0cb"]; + TUPLE_TOP [label="⊤:tuple"]; + TUPLE_BOT [label="⊥:tuple"]; + TUPLE1 [label="(type)", shape=box]; + TUPLE2 [label="(type, type)", shape=box]; + TUPLEN [label="(type, …)", shape=box]; + {rank=same; TUPLE1; TUPLE2; TUPLEN;} + TUPLE1 -> TUPLE2 -> TUPLEN [style=invis]; + TUPLE_TOP -> {TUPLE1 TUPLE2 TUPLEN}; + {TUPLE1 TUPLE2 TUPLEN} -> TUPLE_BOT; + } + + TOP -> {XCTRL INT_TOP FLT_TOP PTR_TOP STRUCT_TOP MEM_TOP TUPLE_TOP}; + {CTRL INT_BOT FLT_BOT PTR_BOT STRUCT_BOT MEM_BOT TUPLE_BOT} -> BOT; + {rank=same; XCTRL; INT_TOP; FLT_TOP; PTR_TOP; STRUCT_TOP; MEM_TOP; TUPLE_TOP;} + {rank=same; CTRL; INT_BOT; FLT_BOT; PTR_BOT; STRUCT_BOT; MEM_BOT; TUPLE_BOT;} + XCTRL -> INT_TOP -> FLT_TOP -> PTR_TOP -> STRUCT_TOP -> MEM_TOP -> TUPLE_TOP [style=invis]; } diff --git a/chapter14/docs/lattice.svg b/chapter14/docs/lattice.svg index 99f74ed0..131b5601 100644 --- a/chapter14/docs/lattice.svg +++ b/chapter14/docs/lattice.svg @@ -1,691 +1,803 @@ - - - - - - -Lattice - - - -TOP - -⊤ - - - -XCTRL - -⊤ -:ctrl - - - -TOP->XCTRL - - - - - -INT_TOP - -⊤ -:int - - - -TOP->INT_TOP - - - - - -FLT_TOP - -⊤ -:flt - - - -TOP->FLT_TOP - - - - - -PTR - - - -*ptr - - -struct - - - -TOP->PTR - - - - - -STRUCT_TOP - -⊤ -:struct - - - -TOP->STRUCT_TOP - - - - - -MEM_TOP - -⊤ -:mem - - - -TOP->MEM_TOP - - - - - -TUPLE_TOP - -⊤ -:tuple - - - -TOP->TUPLE_TOP - - - - - -BOT - -⊥ - - - -CTRL - -⊥ -:ctrl - - - -XCTRL->CTRL - - - - - -CTRL->BOT - - - - - -INT_HI - -max < min - - - -INT_TOP->INT_HI - - - - - -INT_BOT - -⊥ -:int - - - -INT_BOT->BOT - - - - - -INT_XBOOL - -1...0 - - - -INT_HI->INT_XBOOL - - - - - -INT_CON - -constants - - - -INT_HI->INT_CON - - - - - -INT_CON0 - -0 - - - -INT_XBOOL->INT_CON0 - - - - - -INT_CON1 - -1 - - - -INT_XBOOL->INT_CON1 - - - - - -INT_LO - -max > min - - - -INT_CON->INT_LO - - - - - - -INT_BOOL - -0...1 - - - -INT_CON0->INT_BOOL - - - - - - -INT_CON1->INT_BOOL - - - - - -INT_BOOL->INT_LO - - - - - -INT_LO->INT_BOT - - - - - -FLT_CON64 - -64b consts -[excludes -32b consts] - - - -FLT_TOP->FLT_CON64 - - - - - -FLT_CONPI - -3.14159... - - - -FLT_TOP->FLT_CONPI - - - - - -FLT_X32 - -~f32 - - - -FLT_TOP->FLT_X32 - - - - - -FLT_BOT - -⊥ -:flt - - - -FLT_BOT->BOT - - - - - -FLT_CON64->FLT_BOT - - - - - -FLT_CON32 - -32b consts - - - - -FLT_32 - -f32 - - - -FLT_CON32->FLT_32 - - - - - -FLT_CONPI->FLT_BOT - - - - - - -FLT_X32->FLT_CON32 - - - - - -FLT_CON0 - -0. - - - -FLT_X32->FLT_CON0 - - - - - - -FLT_CON0->FLT_32 - - - - - -FLT_32->FLT_BOT - - - - - -PTR0 - - - -*ptr? - - -struct - - - -PTR->PTR0 - - - - - -PTR0->BOT - - - - - -STRUCT_S1 - - - -field - - - - - - - - -int/ptr - - - -STRUCT_TOP->STRUCT_S1 - - - - - -STRUCT_S2 - - - -field - - - - - - - - -int/ptr - - -field - - - - - - - - -int/ptr - - - -STRUCT_TOP->STRUCT_S2 - - - - - -STRUCT_SN - - - -field - - - - - - - - -int/ptr - - -...   - - - - - - - - -int/ptr - - -field - - - - - - - - -int/ptr - - - -STRUCT_TOP->STRUCT_SN - - - - - -STRUCT_BOT - -⊥ -:struct - - - -STRUCT_BOT->BOT - - - - - -STRUCT_S1->STRUCT_BOT - - - - - - -STRUCT_S2->STRUCT_BOT - - - - - - -STRUCT_SN->STRUCT_BOT - - - - - -MEM_ALIAS1 - -#1 - - - -MEM_TOP->MEM_ALIAS1 - - - - - -MEM_ALIASDOTS - -... - - - -MEM_TOP->MEM_ALIASDOTS - - - - - -MEM_ALIASN - -#n - - - -MEM_TOP->MEM_ALIASN - - - - - -MEM_BOT - -⊥ -:mem - - - -MEM_BOT->BOT - - - - - -MEM_ALIAS1->MEM_BOT - - - - - - -MEM_ALIASDOTS->MEM_BOT - - - - - - -MEM_ALIASN->MEM_BOT - - - - - -TUPLE1 - - - -Tuple - - -type - - - -TUPLE_TOP->TUPLE1 - - - - - -TUPLE2 - - - -Tuple - - -type - - -type - - - -TUPLE_TOP->TUPLE2 - - - - - -TUPLEN - - - -Tuple - - -type - - -... - - -type - - - -TUPLE_TOP->TUPLEN - - - - - -TUPLE_BOT - -⊥ -:tuple - - - -TUPLE_BOT->BOT - - - - - -TUPLE1->TUPLE_BOT - - - - - -TUPLE2->TUPLE_BOT - - - - - -TUPLEN->TUPLE_BOT - - - - - + + + + + + +Lattice + + +cluster_control + +Control + + +cluster_integer + +Integer ranges (schematic) + + +cluster_float + +Float + + +cluster_pointer + +Pointer = nullability × struct type + + +cluster_struct + +Struct +named collection of named scalar types + + +cluster_memory + +Memory +precise alias slices + + +cluster_tuple + +Tuple +collection of types + + + +TOP + +⊤ + + + +XCTRL + +⊤:ctrl + + + +TOP->XCTRL + + + + + +INT_TOP + +⊤ +:int + + + +TOP->INT_TOP + + + + + +FLT_TOP + +⊤ +:flt + + + +TOP->FLT_TOP + + + + + +PTR_TOP + +⊤:ptr +[*⊤:struct] + + + +TOP->PTR_TOP + + + + + +STRUCT_TOP + +⊤:struct +[struct top] + + + +TOP->STRUCT_TOP + + + + + +MEM_TOP + +⊤:mem + + + +TOP->MEM_TOP + + + + + +TUPLE_TOP + +⊤:tuple + + + +TOP->TUPLE_TOP + + + + + +BOT + +⊥ + + + +CTRL + +⊥:ctrl + + + +XCTRL->CTRL + + + + + + +CTRL->BOT + + + + + +INT_HI + +max < min + + + +INT_TOP->INT_HI + + + + + + +INT_BOT + +⊥ +:int + + + +INT_BOT->BOT + + + + + +INT_XBOOL + +1...0 + + + +INT_HI->INT_XBOOL + + + + + +INT_CON + +constants + + + +INT_HI->INT_CON + + + + + +INT_CON0 + +0 + + + +INT_XBOOL->INT_CON0 + + + + + +INT_CON1 + +1 + + + +INT_XBOOL->INT_CON1 + + + + + +INT_LO + +max > min + + + +INT_CON->INT_LO + + + + + + +INT_BOOL + +0...1 + + + +INT_CON0->INT_BOOL + + + + + + +INT_CON1->INT_BOOL + + + + + +INT_BOOL->INT_LO + + + + + +INT_LO->INT_BOT + + + + + +FLT_CON64 + +64b consts +[excludes +32b consts] + + + +FLT_TOP->FLT_CON64 + + + + + +FLT_CONPI + +3.14159... + + + +FLT_TOP->FLT_CONPI + + + + + +FLT_X32 + +~f32 + + + +FLT_TOP->FLT_X32 + + + + + + +FLT_BOT + +⊥ +:flt + + + +FLT_BOT->BOT + + + + + +FLT_CON64->FLT_BOT + + + + + +FLT_CON32 + +32b consts + + + + +FLT_32 + +f32 + + + +FLT_CON32->FLT_32 + + + + + +FLT_CONPI->FLT_BOT + + + + + + +FLT_X32->FLT_CON32 + + + + + +FLT_CON0 + +0. + + + +FLT_X32->FLT_CON0 + + + + + + +FLT_CON0->FLT_32 + + + + + +FLT_32->FLT_BOT + + + + + +PTR_NULL + +null + + + +PTR_TOP->PTR_NULL + + + + + +PTR_PERSON + +*Person + + + +PTR_TOP->PTR_PERSON + + + + + +PTR_S1 + +*s1 + + + +PTR_TOP->PTR_S1 + + + + + +PTR_MORE + +*s2, … + + + +PTR_TOP->PTR_MORE + + + + + + +PTR_BOT + +⊥:ptr +[*⊥:struct?] + + + +PTR_BOT->BOT + + + + + +PTR_PERSON_NIL + +*Person? + + + +PTR_NULL->PTR_PERSON_NIL + + + + + +PTR_S1_NIL + +*s1? + + + +PTR_NULL->PTR_S1_NIL + + + + + +PTR_MORE_NIL + +*s2?, … + + + +PTR_NULL->PTR_MORE_NIL + + + + + +PTR_ANY + +*⊥:struct +[ptr any struct] + + + +PTR_ANY->PTR_BOT + + + + + + +PTR_PERSON->PTR_ANY + + + + + + +PTR_PERSON->PTR_PERSON_NIL + + + + + +PTR_S1->PTR_ANY + + + + + + +PTR_S1->PTR_S1_NIL + + + + + + +PTR_MORE->PTR_ANY + + + + + +PTR_MORE->PTR_MORE_NIL + + + + + +PTR_PERSON_NIL->PTR_BOT + + + + + + +PTR_S1_NIL->PTR_BOT + + + + + + +PTR_MORE_NIL->PTR_BOT + + + + + +STRUCT_PERSON + +Person +age: int + + + +STRUCT_TOP->STRUCT_PERSON + + + + + +STRUCT_S1 + +s1 +x: int + + + +STRUCT_TOP->STRUCT_S1 + + + + + +STRUCT_S2 + +s2 +x: int, y: *s1 + + + +STRUCT_TOP->STRUCT_S2 + + + + + +STRUCT_MORE + +… + + + +STRUCT_TOP->STRUCT_MORE + + + + + + +STRUCT_BOT + +⊥:struct +[struct bottom] + + + +STRUCT_BOT->BOT + + + + + +STRUCT_PERSON->STRUCT_BOT + + + + + + +STRUCT_S1->STRUCT_BOT + + + + + + +STRUCT_S2->STRUCT_BOT + + + + + + +STRUCT_MORE->STRUCT_BOT + + + + + +MEM_ALIAS2 + +MEM#2 + + + +MEM_TOP->MEM_ALIAS2 + + + + + +MEM_ALIAS3 + +MEM#3 + + + +MEM_TOP->MEM_ALIAS3 + + + + + +MEM_MORE + +… + + + +MEM_TOP->MEM_MORE + + + + + + +MEM_BOT + +⊥:mem + + + +MEM_BOT->BOT + + + + + +MEM_ALIAS2->MEM_BOT + + + + + + +MEM_ALIAS3->MEM_BOT + + + + + + +MEM_MORE->MEM_BOT + + + + + +TUPLE1 + +(type) + + + +TUPLE_TOP->TUPLE1 + + + + + +TUPLE2 + +(type, type) + + + +TUPLE_TOP->TUPLE2 + + + + + +TUPLEN + +(type, …) + + + +TUPLE_TOP->TUPLEN + + + + + +TUPLE_BOT + +⊥:tuple + + + +TUPLE_BOT->BOT + + + + + +TUPLE1->TUPLE_BOT + + + + + + +TUPLE2->TUPLE_BOT + + + + + + +TUPLEN->TUPLE_BOT + + + + + diff --git a/chapter15/README.md b/chapter15/README.md index 8ab3378b..1485b04c 100644 --- a/chapter15/README.md +++ b/chapter15/README.md @@ -1,5 +1,8 @@ # Chapter 15: Arrays +[Previous: Chapter 14](../chapter14/README.md) | +[Next: Chapter 16](../chapter16/README.md) + # Table of Contents 1. [Parser changes](#parser) @@ -12,8 +15,8 @@ At long last we introduce arrays! These require more complex addressing math, -which in turn means we need to change how Loads and Stores do addressing - -with true field *offsets* instead of field *names*. This means we also +which in turn means we need to change how Loads and Stores do addressing - +with true field *offsets* instead of field *names*. This means we also will do a struct field *layout* in this chapter. Arrays are created with the standard `new int[len]` syntax, and can be any base @@ -31,7 +34,8 @@ will panic the Evaluator. - `new int[-1]; // Negative length` - `new int[1<<63]; // Too large` - `new int[3.14]; // Not an integer` - + + You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter15) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch and [compare](https://github.com/SeaOfNodes/Simple/compare/linear-chapter14...linear-chapter15) it to the previous chapter. @@ -47,7 +51,7 @@ Arrays are always created with zero/null bodies, so implicitly always allow We make a new array with much the same syntax as making a new object: `new int[99]`. The length is required and is any integer expression, so -e.g. `int[arg]` is an integer array of length `arg`. Multi-dimensional arrays +e.g. `new int[arg]` is an integer array of length `arg`. Multi-dimensional arrays only make the outer dimension; the elements themselves are all null and typed as the next lower dimension array. @@ -57,10 +61,11 @@ post-fix `#` operator; e.g. `ary#`. Example to sum an array: ```java int[] ary = new int[arg]; +int sum = 0; int i = 0; -while( i < ary# ) { - sum = sum + ary[i]; - i = i + 1; +while( i < ary# ) { + sum = sum + ary[i]; + i = i + 1; } ``` @@ -127,14 +132,14 @@ a read before allocation and a later write to an existing object. ## New Address Math -Since arrays need adressing math to index into them, Loads and Stores need a +Since arrays need addressing math to index into them, Loads and Stores need a way to compute an offset. Previously Loads and Stores only worked on structs, -and included the field name within them - thus the impicit addressing was field +and included the field name within them - thus the implicit addressing was field name (e.g. a string lookup!). New in this chapter we create a struct *layout* and compute field offsets to all structs. Loads and Stores now take an `off` instead of a field name, and the field -name is included for debugging only. +name is included for debugging only. ```java public MemOpNode(String name, int alias, Type glb, Node mem, Node ptr, Node off) { @@ -178,8 +183,8 @@ mod 8. This means the actual field offset and the field declaration order are ```java struct s { - int8 b; // log_size=0 - uint16 char; // log_size=1 + i8 b; // log_size=0 + u16 char; // log_size=1 Person p; // log_size=2 flt pi; // log_size=3 } @@ -187,9 +192,9 @@ struct s { struct s { flt pi; // offset= 0, log_size=3 Person p; // offset= 8, log_size=2 - uint16 char; // offset=12, log_size=1 - int8 b; // offset=13, log_size=0 - void pad; // offset=14, size = 2 + u16 char; // offset=12, log_size=1 + i8 b; // offset=14, log_size=0 + void pad; // offset=15, size = 1 } // size =16 ``` @@ -200,7 +205,7 @@ this could be changed at a later date to support a larger range of pointers. integer ranges. Other ranges are possible in Simple via `compute` calls, but these will never show up as base field types: - `struct S { int16 x; }` + `struct S { i16 x; }` Here `x` will have offset 0 and size 2 bytes, and `S` will be padded to size 8. @@ -221,17 +226,17 @@ This means the IR for: `x[i]` becomes `16/*base*/ + (i << 3/*scale*/)` becomes `Load(mem,x,Add(Shl(i,3),16))` - - + + `x[i+1]` becomes `16/*base*/ + ((i+1) << 3/*scale*/)` becomes `Load(mem,x,Add(Shl(i,3),24))` Notice the `idx+1` folds the `+1` into the base math. - + ## Discussion -Included in the test cases in a simple rolling sum, and a Sieve of Eratosthenes. +Included in the test cases is a simple rolling sum, and a Sieve of Eratosthenes. ```java int i=0; @@ -241,7 +246,7 @@ while( i < ary# ) { } ``` -Here we really see the lack of a `i++` operator and a `for` loop. You can +Here we really see the lack of an `i++` operator and a `for` loop. You can imagine another syntax: ```java @@ -249,6 +254,6 @@ for( int i=0; i < ary#; i++ ) ary[i] = i; ``` -that would be entirely syntatic-sugar over the existing parser, but would +that would be entirely syntactic-sugar over the existing parser, but would really help make array looping syntax clearer. There are lots of options here, which should really be the focus of another chapter! diff --git a/chapter16/README.md b/chapter16/README.md index 1c598568..663f175a 100644 --- a/chapter16/README.md +++ b/chapter16/README.md @@ -1,5 +1,8 @@ # Chapter 16: Constructors and Final fields +[Previous: Chapter 15](../chapter15/README.md) | +[Next: Chapter 17](../chapter17/README.md) + # Table of Contents 1. [Constructors](#constructors) @@ -24,12 +27,12 @@ Fields are initialized in three ways: syntax is required. ``` int x; // x is initialized to 0 -struct Ref { Ref ptr?; }; // Instances of Ref will have ptr initialized to null +struct Ref { Ref? ptr; }; // Instances of Ref will have ptr initialized to null return new Ref.ptr; // Returns a null ``` 2. The type declaration can specify an initial value. Later allocations will - start with this value. + start with this value. ``` int x = 5; // x is initialized to 5 struct Point { int x=1; int y=1; }; // Point x and y will start as 1, not 0 @@ -37,7 +40,7 @@ return new Point.x; // Returns a 1 ``` 3. The allocation can specify an initial value. - + ``` struct Point { int x=1; int y=1; }; // Point x and y will start as 1, not 0 return new Point { x=3; }.x; // Returns a 3 @@ -63,12 +66,12 @@ declaration or the allocation. Any amount of code is legal, including ``` struct Square { flt side = arg; - flt diag = arg*arg/2; - // Newtons approximation to the square root, computed in a constructor. + flt diag = arg*arg/2; + // Newton's approximation to the square root, computed in a constructor. // The actual allocation will copy in this result as the initial // value for 'diag'. while( 1 ) { - // The next-guess variable "next" is not a field in Square, + // The next-guess variable "next" is not a field in Square, // because it does not appear at the top level flt next = (side/diag + diag)/2; if( next == diag ) break; diff --git a/chapter17/README.md b/chapter17/README.md index a3a2d992..ea1fef28 100644 --- a/chapter17/README.md +++ b/chapter17/README.md @@ -1,15 +1,19 @@ # Chapter 17: Syntax Sugar +[Previous: Chapter 16](../chapter16/README.md) | +[Next: Chapter 18](../chapter18/README.md) + + +## Table of Contents 1. [Pre/Post-increment](#prepost-increment) 2. [Operator assignment](#operator-assignment) 3. [var/val](#var--val) - - [Example(1)](#example1) - - [Example(2)](#example2) 4. [Mutability](#mutability) 5. [Reference immutability](#reference-variables-with-an-initializer-are-deeply-immutable) 6. [Trinary](#trinary) 7. [For Loops](#for-loops) +8. [Memory effects](#memory-effects) ## Pre/Post-increment @@ -38,7 +42,7 @@ Assignments associate right-to-left, as in `x |= y <<= 2`. ## var & val `var` can be used in the `type` position to indicate a "variable" (mutable -value), whose type will be inferred from the required initalizing expression. +value), whose type will be inferred from the required initializing expression. `val` is the same as `var`, except it is a "value" (not mutable). @@ -51,7 +55,7 @@ nullable, so e.g. infers as -`S s? = new S;` +`S? s = new S;` ## Mutability @@ -59,7 +63,7 @@ infers as Typed primitive fields are always mutable. Typed reference fields without an initializer must be mutable to get a value. Initialized reference variables are immutable by default and can be made mutable with a leading `!`. Contrast -this with what [chapter16](https://github.com/SeaOfNodes/Simple/tree/chapter16) +this with what [Chapter 16](../chapter16/README.md) did with `!`. `var` and `val` keep their current sense and can be used to make any field mutable or immutable. Fields are always mutable during construction, but will become immutable at the end of either constructor. diff --git a/chapter18/README.md b/chapter18/README.md index 42f76227..5691059f 100644 --- a/chapter18/README.md +++ b/chapter18/README.md @@ -1,7 +1,11 @@ # Chapter 18: Functions +[Previous: Chapter 17](../chapter17/README.md) | +[Next: Chapter 19](../chapter19/README.md) + # Table of Contents + 1. [FunctionTypes](#function-and-rpc-types) 2. [Return Program Counters](#return-program-counters) 3. [Functions](#functions) @@ -24,7 +28,7 @@ Highlights of the changes: - The top-level is now a call to function `main`, and this changed most tests. - A top-level compile driver, which enforces optimization steps. - A local scheduler. -- A new evaluator which relies on at code motion, both global and local. +- A new evaluator which relies on code motion, both global and local. - A graphic animated viewer for peepholes. Functions are *not* closures in this chapter; that brings about far more @@ -43,7 +47,7 @@ constant. This generally includes e.g. recursive function pointers. A leading `{` character denotes the start of a function or function type, then a list of argument types, and an arrow `->` and the return type. -Functions variables are normal variables and assigned the same way: +Function variables are normal variables and assigned the same way: `functiontype fcn = function-typed-expr;` @@ -84,7 +88,7 @@ scope, so for now these are only used in the evaluator. ## Functions -Functions themselves using the same syntax with as function types, but filled in: +Functions themselves use the same syntax as function types, but filled in: ``` { flt x, flt y -> // Signature @@ -102,13 +106,13 @@ Used in a declaration statement: With `var`: ``` -var dist = { flt x, flt y -> sqrt(x*x*,y*y); } +var dist = { flt x, flt y -> sqrt(x*x+y*y); } ``` Functions are called in the usual way: `dist( 1.2, 2.3 ) // yields 2.59422435` -Functions can have zero arguments, in which case the `->` argument seperator is +Functions can have zero arguments, in which case the `->` argument separator is optional. This allows any section of code to be "thunked" by wrapping it in `{}`. @@ -121,7 +125,7 @@ Called: Functions are always anonymous. When finally assigned to a variable, they will pick up the variable name for debugging and display purposes, but this has no -semantics meaning. Here is a function variable referring to more than one +semantic meaning. Here is a function variable referring to more than one anonymous function; the resulting function either doubles or squares: `val fcn = arg ? { int x -> x+x; } : { int x -> x*x; };` @@ -130,9 +134,9 @@ anonymous function; the resulting function either doubles or squares: Functions can be recursive: ``` -val fact = { int n -> - n <=1 ? n : n*fact(n-1); -}; +val fact = { int n -> + n <=1 ? n : n*fact(n-1); +}; return fact(4); // Returns 4! or 24 ``` @@ -179,7 +183,7 @@ After a `Call` is a `CallEndNode`, internally abbreviated as `cend`. The `CallEnd` will take the `Call` as an input, and also every *linked* function: functions the call-site *knows* it will call. This will be expanded later to be a conservative approximation to the *Call Graph*, with each `CallEnd` -*linked* to ever function it *may* call; if a function is not linked it can not +*linked* to every function it *may* call; if a function is not linked it can not be called from here. This requires a global analysis (fast, cheap, incremental, and global), not in this chapter. So for the moment we only link exact constant functions. @@ -204,8 +208,8 @@ programs. The phases (for now) are: reports on failed null checks. - *Schedule* - Global Code Motion scheduler. After this phase, all nodes belong in some basic block, with the normal suspect CFGNodes being basic blocks. -- *LocalSched* - a local scheduler. Its completely naive, except it enforces - some required rules: Phis appear at block heads, branchs at block exits. +- *LocalSched* - a local scheduler. It's completely naive, except it enforces + some required rules: Phis appear at block heads, branches at block exits. There's room in the algorithm for a much more sophisticated list scheduler. The `Eval2` evaluator requires this information. - *RegAlloc* - Not implemented (yet). @@ -214,7 +218,7 @@ Several globals moved from the Parser to CodeGen, and probably several others ought to move here. There is a very nice `toString()` here; hovering over the `code` variable in -the debug winow will pretty-print the IR "as if" globally scheduled, and the +the debug window will pretty-print the IR "as if" globally scheduled, and the code becomes very readable. @@ -229,12 +233,13 @@ recursive calls). ## Graph Visualizer -Run as `make view`, type your program in the text box, click -outside the box and then use the arrow keys to view IR generator both forwards -and backwards. +Run `make view`, type your program in the text box, and click **Compile** +(or press **Ctrl+Enter**). Use the Left/Right arrow keys to step through graph +construction and optimization. See the [shared viewer guide](../graph/README.md). -Nodes are color coded according to type, same as the lattice diagrams. Nodes -are shaped according to node function as well. At the bottom are `ScopeNode`s, +Nodes use colors and shapes for their graph roles: control, data, memory, Phis, +and scopes. This palette is distinct from the type-lattice diagrams. The viewer +also displays `ScopeNode`s, which only exist for the Parser but are actual Nodes and have `use->def` edges into the IR. diff --git a/chapter19/README.md b/chapter19/README.md index 63929b34..ef3ee118 100644 --- a/chapter19/README.md +++ b/chapter19/README.md @@ -1,5 +1,8 @@ # Chapter 19: Instruction Selection and Portable Compilation +[Previous: Chapter 18](../chapter18/README.md) | +[Next: Chapter 20](../chapter20/README.md) + You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linear-chapter19) in a linear Git revision history on the [linear](https://github.com/SeaOfNodes/Simple/tree/linear) branch and [compare](https://github.com/SeaOfNodes/Simple/compare/linear-chapter18...linear-chapter19) it to the previous chapter. @@ -7,11 +10,11 @@ You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linea The output of Instruction Selection - the mapping from idealized Simple Nodes to machine-specific ones - is difficult to test in bulk without an execution -strategy. We won't have an execution stratgy until all three of Instruction +strategy. We won't have an execution strategy until all three of Instruction Selection, Register Allocation and Encodings are done. Hence in and around the completion of Encoding we expect to find lots of bugs in Instruction Selection and Register Allocation. We certainly hand-inspect the output and fix obvious -problems, but still lots bugs linger until we can actually run the code. +problems, but still lots of bugs linger until we can actually run the code. This means that other chapters have updates and bug-fixes to the work being described here. @@ -84,9 +87,9 @@ memory, and argument inputs. `Machines` define registers as small dense integers. The Register Allocator will use these numbers when allocating. The mappings from small integers to -machine registers is up to the porter, but there's usally an obvious +machine registers is up to the porter, but there's usually an obvious one-to-one. For the X86, RAX will be register 0, RCX register 1 and so on up -to the 16 GPRs. The XMM registers at 16 and go up to 32. Register numbers +to the 16 GPRs. The XMM register numbers start at 16 and go through 31. Register numbers must be unique; this is how the register allocator tracks them. A `RegMask` Register Mask class holds onto bitsets of allowed registers. Most @@ -102,7 +105,7 @@ really "bind up" the set of allowed registers. ## An X86_64_V2 port, with SystemV or Win64 calling conventions In the `node/cpus/x86_64_v2` directory is a `x86_64_v2.java` port to an X86 64 -V2. This port supports 16 64-bit GPRs, 32 XMM registers and the X86 flags. +V2. This port supports 16 64-bit GPRs, 16 XMM registers and the X86 flags. There is a pattern matcher for matching X86 ops from idealized Simple Sea-of-Nodes. Except for the addressing modes pattern matcher matches nearly one-for-one X86 ops from ideal nodes. @@ -141,7 +144,7 @@ Sea-of-Nodes. Currently, we are targeting `RVA23U64`. ### Normal instruction selection -Works the same way as **X86_64_V2**, since riscv doesn't have *complex* addressing modes, greedy +Works the same way as **X86_64_V2**, since riscv doesn't have *complex* addressing modes, greedy pattern matching doesn't apply to most of the cases. Ops without any special behavior simply do the lookup. ### Restricted ISA @@ -158,14 +161,14 @@ eliminating the need for a separate comparison step. E.g ``` -beq x10, x11, some_label +beq x10, x11, some_label ``` `CBranchRISC` implements this behavior. ### No R-Flags -No R-flags exist in RiSC-V. To obtain similar functionality: +No R-flags exist in RISC-V. To obtain similar functionality: We can set the value of registers based on the result of the comparison this way explicitly. ``` xor a0, a0, a1 @@ -189,10 +192,10 @@ fadd.s fa0, fa5, fa4 (No load is needed prior to `flw`) ### ABI names(registers) -In `RISC-V`, general-purpose registers (`GPRs`) range from `x0` to `x31`, and floating-point registers range +In `RISC-V`, general-purpose registers (`GPRs`) range from `x0` to `x31`, and floating-point registers range from `f0` to `f31`. -To enhance readability and align with calling conventions, RISC-V defines ABI names for registers, providing more intuitive aliases +To enhance readability and align with calling conventions, RISC-V defines ABI names for registers, providing more intuitive aliases instead of raw register numbers. @@ -211,7 +214,7 @@ instead of raw register numbers. When passing in arguments to a function, the first 8 arguments from the caller are passed in registers `a0` to `a7`. ### Load floats -Currently, floating-point constants are first loaded into an `integer GPR` before being converted into a floating-point register. +Currently, floating-point constants are first loaded into an `integer GPR` before being converted into a floating-point register. This process is rewritten in the RA stage as: @@ -219,7 +222,7 @@ This process is rewritten in the RA stage as: lui a0, 262144 fmv.w.x fa0, a0 ```` -For non-constant values, we use a broader register mask that +For non-constant values, we use a broader register mask that supports both GPRs and FPRs. This implementation can be found in: `nodes/cpus/riscv/LoadRISC`. @@ -227,4 +230,3 @@ supports both GPRs and FPRs. This implementation can be found in: - diff --git a/chapter20/README.md b/chapter20/README.md index 271653c6..f3c566e5 100644 --- a/chapter20/README.md +++ b/chapter20/README.md @@ -1,6 +1,9 @@ # Chapter 20: Graph Coloring Register Allocation -## Some Reading Material +[Previous: Chapter 19](../chapter19/README.md) | +[Next: Chapter 21](../chapter21/README.md) + +## Some Reading Material This is a Briggs-Chaitin-Click allocator, and is very similar to the one used in HotSpot's C2 allocator for the past 25 years with great success. @@ -18,17 +21,17 @@ or Chaitin in combination. Basically there was a spate of register allocation improvements in this era that made it into many high-end mainstream compilers. I've included a very old unpublished paper on speeding up graph coloring -allocators: [Interference Graph Triming](docs/ifg_trim.pdf). +allocators: [Interference Graph Trimming](docs/ifg_trim.pdf). ## Meta-Issues / Code-Dev Issues of Instruction Selection, Register Allocation and Encodings The output of Register Allocation - an allocation of registers to ops - is difficult to test in bulk without an execution strategy. We won't have an -execution stratgy until all three of Instruction Selection, Register Allocation +execution strategy until all three of Instruction Selection, Register Allocation and Encodings are done. Hence in and around the completion of Encoding we expect to find lots of bugs in Instruction Selection and Register Allocation. -We certainly hand-inspect the output and fix obvious problems, but still lots +We certainly hand-inspect the output and fix obvious problems, but still lots of bugs linger until we can actually run the code. This means that other chapters have updates and bug-fixes to the work being @@ -43,7 +46,7 @@ You can also read [this chapter](https://github.com/SeaOfNodes/Simple/tree/linea ## The Basic Theory -The reading material includes several explainations of the basic concepts, but +The reading material includes several explanations of the basic concepts, but at the risk of being redundant I'll present a short version again here. I assume you (the reader) know *why* register allocation is required: machine @@ -53,7 +56,7 @@ they need to be allocated well. Graph Coloring is one such allocation method; machine registers are treated as colors; a *live range interference graph* is built, with each *live range* requiring its own register/color. Coloring the graph ensures every live range -gets a unique register, specificially when it overlaps or *interferes* with +gets a unique register, specifically when it overlaps or *interferes* with another live range. A successful coloring ends the allocation and after some bookkeeping the @@ -82,14 +85,14 @@ Coloring proceeds in rounds until we get a coloring: which also makes fewer larger live ranges. We'll be using the disjoint Union-Find algorithm to rapidly build up live ranges in one forward pass over the program. - -- Build the Inteference Graph: every live range which is alive at the same time + +- Build the Interference Graph: every live range which is alive at the same time as any other, now *interferes* or conflicts. This is built using a LIVE-ness pass, which is a backwards pass over the CFG, and can require more than one pass according to loop nesting depth. The data structure here is generally a 2-D bitset, triangulated to cut its size in half. As part of LIVE, we'll also have a set of reaching defs per-block. - + - Color the interference graph. Nodes (live ranges) in the graph which are strictly low degree (more available registers than neighbors) are guaranteed to get a color. These can be removed from the graph - since they will @@ -117,8 +120,8 @@ Coloring proceeds in rounds until we get a coloring: Registers are the thing that Register Allocation is all about! They are represented as a small dense integer, starting up from 0, and the numbering generally follows from the hardware encodings. So for an X86_64, RAX will be -register 0, RCX register 1 and so on up to the 16 GPRs. The XMM registers at -16 and go up to 32. Register numbers must be unique; this is how the register +register 0, RCX register 1 and so on up to the 16 GPRs. The XMM register numbers start at +16 and go through 31. Register numbers must be unique; this is how the register allocator tracks them. #### Why a RegMask class and not a simple `long`? @@ -137,7 +140,7 @@ bit value directly in Java, Simple will pick up a `RegMask` class object. #### Stack Slots -One of the Click extensions is this notion of treating "stack slots" are Just +One of the Click extensions is this notion of treating "stack slots" as Just Another Register. They get colored like other registers, which in turn leads to very efficient use of the stack; C2 is known for having very small stack frames. Another benefit is callee save registers will get split preferentially @@ -208,9 +211,9 @@ allocation the `LRG._mask` field holds the set of available registers, typically all the defaults, minus various conflicts. The `LRG._adj` holds a list of adjacent neighbors as part of the larger -Interference Graph, and is only used during the Coloring phase. +Interference Graph, and is only used during the Coloring phase. [See more about graphs here.](https://en.wikipedia.org/wiki/Graph_(abstract_data_type)) -This is a "adjacency list" form of a Graph description, and is built from the +This is an "adjacency list" form of a Graph description, and is built from the IFG's 2-D collection of bits (itself a 1-D list of `BitSet`s). Graph coloring register allocation is one of the few places where changing the layout of a data structure mid-algorithm pays out. @@ -239,7 +242,7 @@ them). ### Hard-Conflicts -A live range can have a *hard confict*: conflicting register requirements, +A live range can have a *hard conflict*: conflicting register requirements, leading to no valid register choices. The obvious case is an incoming parameter fixed in e.g. `rdx` but also required as an exit value in `rax`. You can't pick both registers at once, so a split is required. During the build @@ -247,14 +250,14 @@ live ranges phase, every register constraint from every def and use are AND'd together; the `RegMask` might lose all valid registers, or remain with just a handful of register choices. -Hard-conflicts are usually found while build live ranges, and will trigger a +Hard-conflicts are usually found while building live ranges, and will trigger a round of splitting before building the interference graph or coloring. They can also be found during interference graph building, generally caused by a 1-register kill. ### Avoiding interferences -Once of the Click extensions to the Briggs-Chaitin allocator is to take +One of the Click extensions to the Briggs-Chaitin allocator is to take advantage of register constraints to lower the interference graph degree (which otherwise becomes an O(n^2) edge collection). If a live range LR1 is reduced to a single register (such as a call argument requiring `rdx`) and would @@ -279,7 +282,7 @@ e.g. a simple `fib` program: y = x; x = tmp; }; - + ``` In SoN SSA form: @@ -328,7 +331,7 @@ arbitrarily (lowest numbered register), and then we go looking for a better color. Biased coloring inspects first a sample def (if there is only one, then the One Def is inspected), and then a sample use. Inspection looks to see if "the other side" of a split is already colored; if so, and that color is -available it is choosen. If there is a split, but it is not colored - we +available it is chosen. If there is a split, but it is not colored - we recursively repeat the process on that split's other side. This is also done for the other input of two-address ops and one of a Phi node inputs. @@ -346,7 +349,7 @@ guaranteed a color. There is a conflicting tension here: Picking a live range with a large "area" (i.e. covering much of the program), and low "cost" to spill (i.e. fewer defs and uses, and outside of loops) will give a large win. A register will become free over a large part of the program -and allow coloring to success elsewhere. The normal ABI callee-save registers +and allow coloring to succeed elsewhere. The normal ABI callee-save registers are ideal in this case, defined on entry and used only on exit they cover the entire program. Also, spilling means only a single split on entry and another at exit. Spilling such live ranges basically builds a classic function @@ -362,7 +365,7 @@ outside a fast-path exit. BIG_AND_SLOW: add rsp,#12 mov [rsp+0],rbx // begin spilling callee-save registers - mov [rsp+4],r12 // + mov [rsp+4],r12 // // lots of code needing callee-save registers ``` @@ -389,7 +392,7 @@ and deciding on a splitting strategy. ### Split Self Conflict Self-conflict live ranges are discovered during the "Build the Interference -Graph" stage. If this happens we don't attempt a coloring (its nonsensical +Graph" stage. If this happens we don't attempt a coloring (it's nonsensical with self conflicts), but go straight to splitting. During the IFG building we gathered a subset of the conflicting definitions for this live range. Now we visit all those definition points and insert spills: @@ -401,8 +404,8 @@ we visit all those definition points and insert spills: - Before any use that extends a live range. This set of splits is fairly aggressive... but test cases requiring a split in -each of the listed locations are including in Chapter 20's test cases. We -cannot even attempt a color while we have self conflicts, so its important to +each of the listed locations are included in Chapter 20's test cases. We +cannot even attempt a color while we have self conflicts, so it's important to break up these live ranges quickly. This tends to over-split and the allocator leans on Biased Coloring and the final copy cleanup to remove some of the extras. Conservative coalescing will be introduced in a later chapter. @@ -443,7 +446,7 @@ into successively deeper loop nests in progressive rounds of splitting, and in the final case will split once after each def and before each use, even in the innermost loop. -The heurstic starts by discovering the min and max loop depth for all defs and +The heuristic starts by discovering the min and max loop depth for all defs and uses. If these vary, we will split *around* the outermost loop, putting in splits at the loop border and keeping an inner untouched live range that has no constraints from outside. If this fails to color, on the next round of @@ -462,7 +465,7 @@ RA uses a series of helper functions, each is fairly self-contained. after a def. Includes the work to put the split in its proper ordering in a Basic Block and do all edge maintenance. - **makeSplit** - Make a split (either clone a clonable constant, or ask the - `Machine` for a port-specific `SplitNode`. + `Machine` for a port-specific `SplitNode`). - **ldepth** - Given a min&max loop depth (compacted in a `long`), expand the loop depth range for a given node `n`. Used to decide when a def or use is "inside" a loop, which in turn is used to split around loops. @@ -475,7 +478,7 @@ A quick pass over the splits and after checking registers, we pull out the useless splits (and track the rest for "scoring" our allocation). We'll also bypass some split-after-splits, which can remove some redundant copying. -The registers remain available in the `RegAlloc` object via `alloc.regnum( Node n )` +The registers remain available in the `RegAlloc` object via `alloc.regnum( Node n )` and will be used by a following instruction encoding pass. diff --git a/chapter21/README.md b/chapter21/README.md index a2222a8f..18256cc6 100644 --- a/chapter21/README.md +++ b/chapter21/README.md @@ -1,5 +1,8 @@ # Chapter 21: Instruction Encoding and ELF +[Previous: Chapter 20](../chapter20/README.md) | +[Next: Chapter 22](../chapter22/README.md) + This chapter turns the scheduled, register-allocated graph into executable instructions. Each machine node writes its bytes; the compiler places blocks, resolves local references, and exports an ELF object for the linker. We can now diff --git a/chapter22/README.md b/chapter22/README.md index 426db34f..dfcebc40 100644 --- a/chapter22/README.md +++ b/chapter22/README.md @@ -1,5 +1,8 @@ # Chapter 22: A Hello, World! +[Previous: Chapter 21](../chapter21/README.md) | +[Next: Chapter 23](../chapter23/README.md) + It's high time for strings and printing! In this chapter we look at what it takes to make a basic string - not really a full fledged String class, that will wait for another chapter. @@ -16,7 +19,7 @@ Let's break it down. - `sys`: is Just A Variable Name. Like other variables, it is looked up in the current scope... which looks completely empty. Every Simple program now starts - with the `sys` variable in-scope. `sys` itself a normal `struct` + with the `sys` variable in-scope. `sys` itself is a normal `struct` and is defined in `src/main/smp/sys.smp`. - `sys.io.p`: lookup the `io` field in `sys` struct, which yields the `sys.io` struct; then a lookup of `p` (short for "print") in the `sys.io` struct. @@ -44,7 +47,7 @@ Simple now supports nested types - this is a name-space only change, so no new semantics - just the ability to nest type definitions. ```java -struct Outer { +struct Outer { struct Inner { int in; flt pi = 3.14; @@ -55,14 +58,14 @@ struct Outer { Any final field set in the declaration (as opposed to the constructor) is automatically a "static" field - it is final for all instances, and does not -need to be stored in each instances. Instead one copy is kept in a global +need to be stored in each instance. Instead one copy is kept in a global space (not really a *class* object yet) and loaded from there. In this example: - Instances of the `Outer` struct have a single `int` field `out`. - Instances of the `Inner` struct have a single `int` field `in`. -- There exists a `Outer.Inner.pi` field in a global space with value `3.14`. +- There exists an `Outer.Inner.pi` field in a global space with value `3.14`. The `sys` struct is another example, with nested `libc` and `io` structs at least. All the fields in these structs are all final, hence static. @@ -78,7 +81,7 @@ call: `{ i32 fd, i64 buf, u32 len -> u32 } write = "C";` Any final variable assigned as "C" will be considered defined externally. The -syntax of this might change slightly to avoid ambiguity with assign the same +syntax of this might change slightly to avoid ambiguity with assigning the same "C" string. There is no linker support for getting the correct signature or namespace; the @@ -241,9 +244,6 @@ shuffling optimizer worklists should normalize to essentially the same graph, so repeating allocation on those graphs adds little coverage. Use seed variation when investigating optimizer normalization or worklist-order failures. -Two pre-existing failures found during the review remain in the -[backport queue](../docs/chapter-backports.md): String fails during loop -analysis/scheduling at other optimizer seeds, and returning a function pointer -fails during relocation after Opto incorrectly deletes the referenced function. -Their reproductions and validation history are retained -there as separate correctness work. +The [backport record](../docs/chapter-backports.md) documents the resolved +String fall-through and returned-function retention/relocation failures, +including their reproductions and validation history. diff --git a/chapter23/README.md b/chapter23/README.md index 502387eb..debbf6dc 100644 --- a/chapter23/README.md +++ b/chapter23/README.md @@ -1,5 +1,8 @@ # Chapter 23: Methods and Revisiting Types +[Previous: Chapter 22](../chapter22/README.md) | +[Next: Chapter 24](../chapter24/README.md) + In this chapter we add *methods*, functions defined in structs which take a hidden `self` argument and can access the struct fields. Here is an `indexOf` method in a String-like class: @@ -8,7 +11,7 @@ hidden `self` argument and can access the struct fields. Here is an // A String-like class, with methods struct String { u8[~] buf; // Buffer of read-only characters - + // Return the index of the first character 'c' or -1 val indexOf = { u8 c -> // Hidden 'self' argument for( int i=0; i