• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..14-Dec-2021-

gen/H03-May-2022-26,02021,374

testdata/H14-Dec-2021-1,1371,023

README.mdH A D14-Dec-20218.1 KiB223148

TODOH A D14-Dec-2021950 2521

addressingmodes.goH A D14-Dec-202121.3 KiB461377

bench_test.goH A D14-Dec-2021531 3324

biasedsparsemap.goH A D14-Dec-20212.7 KiB11380

block.goH A D14-Dec-202111.1 KiB411247

branchelim.goH A D14-Dec-202112 KiB450320

branchelim_test.goH A D14-Dec-20215.2 KiB173148

cache.goH A D14-Dec-20212.5 KiB8256

check.goH A D14-Dec-202116.5 KiB601527

checkbce.goH A D14-Dec-2021956 3624

compile.goH A D14-Dec-202118.2 KiB605476

config.goH A D14-Dec-202111.2 KiB370302

copyelim.goH A D14-Dec-20211.8 KiB8552

copyelim_test.goH A D14-Dec-20211.3 KiB4231

critical.goH A D14-Dec-20213.2 KiB11670

cse.goH A D14-Dec-20219.4 KiB374267

cse_test.goH A D14-Dec-20214.2 KiB132108

deadcode.goH A D14-Dec-20219.6 KiB390276

deadcode_test.goH A D14-Dec-20213.5 KiB162141

deadstore.goH A D14-Dec-20219.1 KiB351251

deadstore_test.goH A D14-Dec-20214.1 KiB130105

debug.goH A D14-Dec-202151.1 KiB1,7351,222

debug_lines_test.goH A D14-Dec-20218.3 KiB259202

debug_test.goH A D14-Dec-202128.8 KiB1,024814

decompose.goH A D14-Dec-202113.4 KiB480394

dom.goH A D14-Dec-20218 KiB303202

dom_test.goH A D14-Dec-202113.3 KiB609519

expand_calls.goH A D14-Dec-202163.5 KiB1,7961,436

export_test.goH A D14-Dec-20213.2 KiB12497

flagalloc.goH A D14-Dec-20216.7 KiB270202

flags_amd64_test.sH A D14-Dec-2021533 3022

flags_arm64_test.sH A D14-Dec-2021699 3123

flags_test.goH A D14-Dec-20212.5 KiB11092

func.goH A D14-Dec-202127 KiB922729

func_test.goH A D14-Dec-202113.1 KiB485365

fuse.goH A D14-Dec-20216.5 KiB255181

fuse_branchredirect.goH A D14-Dec-20213.2 KiB11174

fuse_comparisons.goH A D14-Dec-20214.1 KiB15885

fuse_test.goH A D14-Dec-20217.2 KiB302239

html.goH A D14-Dec-202134.7 KiB1,3171,095

id.goH A D14-Dec-2021576 2917

layout.goH A D14-Dec-20214.8 KiB183123

lca.goH A D14-Dec-20213.8 KiB12885

lca_test.goH A D14-Dec-20211.7 KiB8972

likelyadjust.goH A D14-Dec-202115.2 KiB577428

location.goH A D14-Dec-20213.1 KiB11065

loopbce.goH A D14-Dec-20219.7 KiB347193

loopreschedchecks.goH A D14-Dec-202115.4 KiB501320

looprotate.goH A D14-Dec-20212.6 KiB11270

lower.goH A D14-Dec-20211.4 KiB4530

magic.goH A D14-Dec-202115.8 KiB425149

magic_test.goH A D14-Dec-20219.1 KiB411372

nilcheck.goH A D14-Dec-202111.1 KiB338216

nilcheck_test.goH A D14-Dec-202112.2 KiB435358

numberlines.goH A D14-Dec-20217.8 KiB263216

op.goH A D14-Dec-202118.7 KiB532368

opGen.goH A D14-Dec-2021946.4 KiB37,47037,417

opt.goH A D14-Dec-2021308 114

passbm_test.goH A D14-Dec-20213.1 KiB10284

phielim.goH A D14-Dec-20211.5 KiB7043

phiopt.goH A D14-Dec-20218.1 KiB324184

poset.goH A D14-Dec-202137.2 KiB1,360893

poset_test.goH A D14-Dec-202118.1 KiB801657

print.goH A D14-Dec-20213.8 KiB192161

prove.goH A D14-Dec-202138.8 KiB1,4431,002

regalloc.goH A D14-Dec-202183 KiB2,8302,003

regalloc_test.goH A D14-Dec-20216.5 KiB231195

rewrite.goH A D14-Dec-202152.8 KiB1,9501,436

rewrite386.goH A D14-Dec-2021289 KiB12,55810,880

rewrite386splitload.goH A D14-Dec-20214.1 KiB161144

rewriteAMD64.goH A D14-Dec-2021817.1 KiB35,21530,733

rewriteAMD64splitload.goH A D14-Dec-202121.4 KiB852759

rewriteARM.goH A D14-Dec-2021491.5 KiB22,04819,290

rewriteARM64.goH A D14-Dec-2021747.7 KiB30,43226,938

rewriteCond_test.goH A D14-Dec-202110.6 KiB598458

rewriteMIPS.goH A D14-Dec-2021174.4 KiB7,5596,649

rewriteMIPS64.goH A D14-Dec-2021195.5 KiB8,1227,175

rewritePPC64.goH A D14-Dec-2021425.3 KiB18,42116,200

rewriteRISCV64.goH A D14-Dec-2021158.8 KiB6,7005,971

rewriteS390X.goH A D14-Dec-2021433.4 KiB17,91615,625

rewriteWasm.goH A D14-Dec-2021109.9 KiB4,9104,361

rewrite_test.goH A D14-Dec-20216.9 KiB221190

rewritedec.goH A D14-Dec-202110.2 KiB430377

rewritedec64.goH A D14-Dec-202163.8 KiB2,4632,215

rewritegeneric.goH A D14-Dec-2021609.2 KiB25,60723,022

schedule.goH A D14-Dec-202115.2 KiB525367

schedule_test.goH A D14-Dec-20212.9 KiB10288

shift_test.goH A D14-Dec-20214 KiB10883

shortcircuit.goH A D14-Dec-202112.7 KiB514258

shortcircuit_test.goH A D14-Dec-20211.3 KiB5444

sizeof_test.goH A D14-Dec-2021855 4029

softfloat.goH A D14-Dec-20212 KiB8170

sparsemap.goH A D14-Dec-20212 KiB9468

sparseset.goH A D14-Dec-20211.5 KiB8056

sparsetree.goH A D14-Dec-20218 KiB242115

stackalloc.goH A D14-Dec-202112.8 KiB473350

stackframe.goH A D14-Dec-2021290 114

stmtlines_test.goH A D14-Dec-20213 KiB142126

tighten.goH A D14-Dec-20214.3 KiB166118

trim.goH A D14-Dec-20214.2 KiB173119

tuple.goH A D14-Dec-20212 KiB7248

value.goH A D14-Dec-202115.2 KiB560413

writebarrier.goH A D14-Dec-202119 KiB666502

writebarrier_test.goH A D14-Dec-20211.7 KiB5743

xposmap.goH A D14-Dec-20213.3 KiB11778

zcse.goH A D14-Dec-20212.1 KiB8057

zeroextension_test.goH A D14-Dec-20211.7 KiB3526

README.md

1<!---
2// Copyright 2018 The Go Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5-->
6
7## Introduction to the Go compiler's SSA backend
8
9This package contains the compiler's Static Single Assignment form component. If
10you're not familiar with SSA, its [Wikipedia
11article](https://en.wikipedia.org/wiki/Static_single_assignment_form) is a good
12starting point.
13
14It is recommended that you first read [cmd/compile/README.md](../../README.md)
15if you are not familiar with the Go compiler already. That document gives an
16overview of the compiler, and explains what is SSA's part and purpose in it.
17
18### Key concepts
19
20The names described below may be loosely related to their Go counterparts, but
21note that they are not equivalent. For example, a Go block statement has a
22variable scope, yet SSA has no notion of variables nor variable scopes.
23
24It may also be surprising that values and blocks are named after their unique
25sequential IDs. They rarely correspond to named entities in the original code,
26such as variables or function parameters. The sequential IDs also allow the
27compiler to avoid maps, and it is always possible to track back the values to Go
28code using debug and position information.
29
30#### Values
31
32Values are the basic building blocks of SSA. Per SSA's very definition, a
33value is defined exactly once, but it may be used any number of times. A value
34mainly consists of a unique identifier, an operator, a type, and some arguments.
35
36An operator or `Op` describes the operation that computes the value. The
37semantics of each operator can be found in `gen/*Ops.go`. For example, `OpAdd8`
38takes two value arguments holding 8-bit integers and results in their addition.
39Here is a possible SSA representation of the addition of two `uint8` values:
40
41	// var c uint8 = a + b
42	v4 = Add8 <uint8> v2 v3
43
44A value's type will usually be a Go type. For example, the value in the example
45above has a `uint8` type, and a constant boolean value will have a `bool` type.
46However, certain types don't come from Go and are special; below we will cover
47`memory`, the most common of them.
48
49See [value.go](value.go) for more information.
50
51#### Memory types
52
53`memory` represents the global memory state. An `Op` that takes a memory
54argument depends on that memory state, and an `Op` which has the memory type
55impacts the state of memory. This ensures that memory operations are kept in the
56right order. For example:
57
58	// *a = 3
59	// *b = *a
60	v10 = Store <mem> {int} v6 v8 v1
61	v14 = Store <mem> {int} v7 v8 v10
62
63Here, `Store` stores its second argument (of type `int`) into the first argument
64(of type `*int`). The last argument is the memory state; since the second store
65depends on the memory value defined by the first store, the two stores cannot be
66reordered.
67
68See [cmd/compile/internal/types/type.go](../types/type.go) for more information.
69
70#### Blocks
71
72A block represents a basic block in the control flow graph of a function. It is,
73essentially, a list of values that define the operation of this block. Besides
74the list of values, blocks mainly consist of a unique identifier, a kind, and a
75list of successor blocks.
76
77The simplest kind is a `plain` block; it simply hands the control flow to
78another block, thus its successors list contains one block.
79
80Another common block kind is the `exit` block. These have a final value, called
81control value, which must return a memory state. This is necessary for functions
82to return some values, for example - the caller needs some memory state to
83depend on, to ensure that it receives those return values correctly.
84
85The last important block kind we will mention is the `if` block. It has a single
86control value that must be a boolean value, and it has exactly two successor
87blocks. The control flow is handed to the first successor if the bool is true,
88and to the second otherwise.
89
90Here is a sample if-else control flow represented with basic blocks:
91
92	// func(b bool) int {
93	// 	if b {
94	// 		return 2
95	// 	}
96	// 	return 3
97	// }
98	b1:
99	  v1 = InitMem <mem>
100	  v2 = SP <uintptr>
101	  v5 = Addr <*int> {~r1} v2
102	  v6 = Arg <bool> {b}
103	  v8 = Const64 <int> [2]
104	  v12 = Const64 <int> [3]
105	  If v6 -> b2 b3
106	b2: <- b1
107	  v10 = VarDef <mem> {~r1} v1
108	  v11 = Store <mem> {int} v5 v8 v10
109	  Ret v11
110	b3: <- b1
111	  v14 = VarDef <mem> {~r1} v1
112	  v15 = Store <mem> {int} v5 v12 v14
113	  Ret v15
114
115<!---
116TODO: can we come up with a shorter example that still shows the control flow?
117-->
118
119See [block.go](block.go) for more information.
120
121#### Functions
122
123A function represents a function declaration along with its body. It mainly
124consists of a name, a type (its signature), a list of blocks that form its body,
125and the entry block within said list.
126
127When a function is called, the control flow is handed to its entry block. If the
128function terminates, the control flow will eventually reach an exit block, thus
129ending the function call.
130
131Note that a function may have zero or multiple exit blocks, just like a Go
132function can have any number of return points, but it must have exactly one
133entry point block.
134
135Also note that some SSA functions are autogenerated, such as the hash functions
136for each type used as a map key.
137
138For example, this is what an empty function can look like in SSA, with a single
139exit block that returns an uninteresting memory state:
140
141	foo func()
142	  b1:
143	    v1 = InitMem <mem>
144	    Ret v1
145
146See [func.go](func.go) for more information.
147
148### Compiler passes
149
150Having a program in SSA form is not very useful on its own. Its advantage lies
151in how easy it is to write optimizations that modify the program to make it
152better. The way the Go compiler accomplishes this is via a list of passes.
153
154Each pass transforms a SSA function in some way. For example, a dead code
155elimination pass will remove blocks and values that it can prove will never be
156executed, and a nil check elimination pass will remove nil checks which it can
157prove to be redundant.
158
159Compiler passes work on one function at a time, and by default run sequentially
160and exactly once.
161
162The `lower` pass is special; it converts the SSA representation from being
163machine-independent to being machine-dependent. That is, some abstract operators
164are replaced with their non-generic counterparts, potentially reducing or
165increasing the final number of values.
166
167<!---
168TODO: Probably explain here why the ordering of the passes matters, and why some
169passes like deadstore have multiple variants at different stages.
170-->
171
172See the `passes` list defined in [compile.go](compile.go) for more information.
173
174### Playing with SSA
175
176A good way to see and get used to the compiler's SSA in action is via
177`GOSSAFUNC`. For example, to see func `Foo`'s initial SSA form and final
178generated assembly, one can run:
179
180	GOSSAFUNC=Foo go build
181
182The generated `ssa.html` file will also contain the SSA func at each of the
183compile passes, making it easy to see what each pass does to a particular
184program. You can also click on values and blocks to highlight them, to help
185follow the control flow and values.
186
187The value specified in GOSSAFUNC can also be a package-qualified function
188name, e.g.
189
190	GOSSAFUNC=blah.Foo go build
191
192This will match any function named "Foo" within a package whose final
193suffix is "blah" (e.g. something/blah.Foo, anotherthing/extra/blah.Foo).
194
195If non-HTML dumps are needed, append a "+" to the GOSSAFUNC value
196and dumps will be written to stdout:
197
198	GOSSAFUNC=Bar+ go build
199
200<!---
201TODO: need more ideas for this section
202-->
203
204### Hacking on SSA
205
206While most compiler passes are implemented directly in Go code, some others are
207code generated. This is currently done via rewrite rules, which have their own
208syntax and are maintained in `gen/*.rules`. Simpler optimizations can be written
209easily and quickly this way, but rewrite rules are not suitable for more complex
210optimizations.
211
212To read more on rewrite rules, have a look at the top comments in
213[gen/generic.rules](gen/generic.rules) and [gen/rulegen.go](gen/rulegen.go).
214
215Similarly, the code to manage operators is also code generated from
216`gen/*Ops.go`, as it is easier to maintain a few tables than a lot of code.
217After changing the rules or operators, see [gen/README](gen/README) for
218instructions on how to generate the Go code again.
219
220<!---
221TODO: more tips and info could likely go here
222-->
223