10
3

More than 3 years have passed since last update.

Goのssa.htmlの変更点まとめ2018〜

Last updated at Posted at 2018-12-20

Go2 Advent Calendar 2018 20日目の記事です。
空きを見つけたので代筆させていただきます。

(2020/9/11に、Go1.15までの変更点を追記しました。)

はじめに

Goコンパイラの中間表現として採用されているSSA(Static Single Assignment)の小ネタです。

SSA(静的単一代入)についてはWikipediaが詳しいのでご覧ください。

GoコンパイラにはSSA形式が最適化パスを通してどのように変化してくのかをHTMLファイル(ssa.html)にダンプする機能があります。この記事ではssa.htmlが2018年にどのように進化していったかをコミットログから追っていきます。

ssa.htmlの作り方

$ env GOSSAFUNC=main go build

コンパイル時に環境変数GOSSAFUNCに関数名をセットすることで、ssa.htmlを生成できます。

後述しますが、2017年はGOSSAFUNCには単に関数名を指定するだけでしたが、2018年の変更で複雑な指定もできるようになりました。

変更点

では、以降でどのような変更があったかを見ていきます。変更は

  • 現在の最新安定版(Go11.4)までに入っているもの
  • まだmaster(go1.12beta1)にしか入っていないもの

に分けて見ていきます。

変更点は、ssa.htmlを生成しているcmd/compile/internal/ssa/html.goのコミットログから調べました。

今回解析対象としたコードは以下のサンプルのssa関数です。Wikipediaの例を拝借しました。

package main

import "fmt"

func ssa() {
        var w, x, y, z int

        x = 5
        x = x - 3
        if x < 3 {
                y = x * 2
                w = y
        } else {
                y = x - 3
        }
        w = x - y
        z = x + y

        fmt.Printf("%d, %d\n", w, z)
}

func main() {
        ssa()
}

1.9.2〜1.11.4の変更点

昨年末の最新版Go1.9.2と現在の最新版Go1.11.4ssa.htmlがどのくらい違うのか比べて見ましょう。

大きく違うのはいくつかの最適化パスが折りたたまれていることでしょうか。

では、順に見ていきます。

Jul 28, 2017 (1.10beta1-) Goコードの変数名が出力されるように

[dev.debug] cmd/compile: better DWARF with optimizations on

SSA形式の変数名だけでは元のコードのどの変数だったのかが分かりづらかったのですが、この変更によって対応する変数が表示されるようになりました。
この変更自体は、最適化によって失われていた変数の位置情報をコンパイラオプション-dwarflocationlistsによってデバッグ情報として付与できるようにした、
というものです。

-dwarflocationlistsオプションについては以下に少し書いてあります
https://tip.golang.org/doc/diagnostics.html#debugging

Aug 18, 2017 (1.10beta1-) (リファクタリングなのでスキップ)

cmd/compile: rename SSA Register.Name to Register.String

Oct 12, 2017 (1.10beta1-) 変数に対応する行数が表示されるように

cmd/compile: add line numbers to values & blocks in ssa.html

元のコードの行数がSSAの変数の横に括弧書きされるようになりました。

Apr 5, 2018 (go1.11beta1-) IsStmtによって行数の表示が変わるように

cmd/compile: add IsStmt breakpoint info to src.lico

Includes changes to html output for GOSSAFUNC to indicate
not-default is-a-statement with bold and not-a-statement
with strikethrough.

この変更時点ではIsStmtマークは使われていませんが、現在は例えば以下の演算で行番号がストライクアウトされます。
https://github.com/golang/go/blob/release-branch.go1.11/src/cmd/compile/internal/ssa/numberlines.go#L62

Jun 14, 2018 (go1.11beta1-) 最適化の各フェーズの列を折り畳めるように

cmd/compile: use expandable columns in ssa.html

デフォルトでは以下の名前で始まるパスが最初から広がっており(html.go#L297)、それ以外は折りたたまれるようになりました。パス名の辺りをクリックすることで畳んだり広げたりできます。

  • "start"
  • "deadcode"
  • "opt"
  • "lower"
  • "late deadcode"
  • "regalloc"
  • "genssa"

Jun 16, 2018 (go1.11beta1-) 選択した時の色の種類が増えました

cmd/compile: add more color choices to ssa.html

ブロックや各行を選択するたびに別の色でハイライトされますが、この色が5色ほど増えました。

1.12以降の変更点

まだmasterブランチにしか入ってませんが、かなり変更が入っていますので紹介しておきます。全て@ysmolskyさんによるものです。

Go1.11.4と最新リリースのGo1.12beta1でssa.htmlがどのくらい違うのか比べて見ましょう。

ソースコードやAST、そしてCFG(Control Flow Graph)が追加されています。

では、1つずつ見ていきます。

Aug 23, 2018 Goの元のソースコードがssa.htmlに含まれるように

cmd/compile: display Go code for a function in ssa.html

今まではSSA形式に変換されてからの変遷でしたが、元のソースコードと対応づけて表示できるようになりました。

Aug 23, 2018 ssa.htmlの出力パスが標準出力に表示されるように

cmd/compile: clean the output of GOSSAFUNC

この変更は、GOSSAFUNCをつけたときに標準出力に表示される大量のデバッグプリントを抑制するためのものです。従来のようにデバッグプリントが必要な時はGOSSAFUNC=Foo+のように関数名の後ろに+をつければよいです。ssa.htmlの内容に変化はありませんが、html.goの中ではssa.htmlの出力パスを表示するよう変更になりました。

Aug 23, 2018 ソースコードにインライン展開後のソースが追加

cmd/compile: add sources for inlined functions to ssa.html

インライン展開された関数がソースコードの列に追加されるようになりました。

Aug 25, 2018 ソースコードとSSAの間にASTの列が追加

cmd/compile: display AST IR in ssa.html

ソースコードとSSAの間にAST(Abstract Syntax Tree)の列が入りました。ソースコード⇔AST⇔SSA間も対応づけてハイライトされます。

Sep 19, 2018 [bug fix]

cmd/compile/internal/ssa: fix a == a to a == b

Goのソースコードの列の関数の順序の計算が間違ってました。

Oct 17, 2018 タブ幅を狭く

cmd/compile: make tabs narrow in src column of ssa.html

Goのソースコードのインデントのタブ幅を狭くしました。

Oct 25, 2018 ヘッダの高さを控えめに

cmd/compile: reduce the size of header in ssa.html

関数名とヘルプで上部領域が埋まってたので調整したようです。
毎日見ていると、この高さが気になるのでしょう。

Nov 21, 2018 各フェーズのCFGを表示できるように

cmd/compile: add control flow graphs to ssa.html

大きめの機能が入りました。各フェーズにCFG(Control Flow Graph)を表示できるようになりました。コミットログにも書かれていますが、関数名の後ろに次の指定をすることでCFGが生成されます。

:*            - dump CFG for every phase
:lower        - just the lower phase
:lower-layout - lower through layout
:w,x-y        - phases w and x through y

サンプルはこちらでも確認できます。

実行には、graphviz(dotコマンド)が必要です。SVG出力したものがssa.htmlに埋め込まれています。SSAの各ブロックを選択するとそれ対応してCFGのノードがハイライトされます。反対にノードを選択すると対応するブロックが選択されます。

細かい話ですが、先ほど紹介した「Aug 23, 2018 ssa.htmlの出力パスが標準出力に表示されるように」で末尾に「+」を追加するとデバッグプリントが表示されるのは、この形式になっても有効です。

# 全フェーズでCFGを生成、デバッグプリントも表示
$ env GOSSAFUNC=ssa:*+ go build main.go

Nov 22, 2018 ↑の手直し

cmd/compile: fix TestFormats by using valid formats

Nov 24, 2018 ブロックが畳めるように

cmd/compile: make ssa blocks collapsable in ssa.html

小さいですが各ブロックの右上に-ボタンが追加されました。押すとブロックを畳めます。

まとめ

2018年に導入されたssa.htmlへの変更点をまとめました。主に次の変更点がありました。

  • 元のソースコードとの対応づけ強化
  • CFG表示
  • 最適化パスやブロックの折りたたみ
  • 色数増加

go1.12がリリースされた際にはお試しください。

それでは良いお年を。

追記

2019年以降の変更点も気が向いた時に調べてまとめていきます。

2019年以降変更点

Go1.13/1.14では大きな変更点はありません。

Feb 27, 2019 (go1.13beta1)

all: fix typos as reported by 'misspell'
コメントのタイポの修正です。

Oct 2, 2019 (go1.14beta1)

cmd/compile: allow multiple SSA block control values

block control value を複数指定できるようになりました。IBM S/390等のアーキテクチャでは、compare(比較)とbranch(分岐)を一度に行う命令があり、その対応のためにcontrol value (分岐に使われる値) を2つに拡張しました。

このコミットの後、次のようなコミットがされています。
cmd/compile: add SSA rules for s390x compare-and-branch instructions

ssa.htmlとしての変更点としてはあまりありませんが、S/390アーキテクチャ向けにビルドすると複数のcontrol valueが使われていることが分かります。

2020年以降変更点

Go1.15では、ダークモード(黒背景)、フェーズ結合が導入されました。

Mar 1, 2020 (go1.15beta1)

cmd/compile: add a dark mode to ssa html generation which can be toggled
ダークモード切替機能を追加しました。

https://github.com/golang/go/issues/34325
を受けての対応です。白い背景だと夜見るのが辛いそうです。それに対して、Rob Pikeがコメントしてました。

Mar 11, 2020 (go1.15beta1)

cmd/compile: improve CFG size in ssa.html

CFGのサイズを改良しました。Go1.14は左に寄ってましたが、Go1.15から左右に余白ができました。

Mar 28, 2020 (go1.15beta1)

cmd/compile: add dark mode functionality to CFGs in the ssa.html output
CFGにもダークモード適用されて欲しいよねと。

Apr 1, 2020 (go1.15beta1)

cmd/compile: combine ssa.html columns with identical contents
phaseが大量にあるのでどれが効いているのか分かり辛かったのですが、phaseに変化のない場合は列が結合される様になりました。

Apr 6, 2020 (go1.15beta1)

cmd/compile: refactor around HTMLWriter removing logger in favor of Func
リファクタリングです。

Apr 6, 2020 (go1.15beta1)

cmd/compile: restore missing columns in ssa.html
最後のカラム(phase)だけ結合できていなかったので直しました。

Apr 6, 2020 (go1.15beta1)

cmd/compile: print block auxint value in HTML output
https://github.com/golang/go/issues/38250

cmd/compile: allow multiple SSA block control valuesで対応した、control valueに即値が指定された場合、表示される様になりました。

Apr 24, 2020 (go1.15beta1)

cmd/compile: fix misalignment in sources column of generated ssa.html
一番左の列のsourceの行番号の位置がコードとずれていたので直しました。

ssa.htmlの変遷

各バージョンでの変更点をまとめます。各バージョンのリンクはそのバージョンのssa.htmlのサンプルです。

Go Version 主な変更点
Go1.9.2 -
Go1.11.4 変数名表示、Phase折り畳み、色数増加
Go1.12beta1 Goのソース(インライン展開含む)、AST列追加、CFG(Control Flw Graph)追加
Go1.13 変更なし
Go1.14 compare-and-branch対応
Go1.15 ダークモード(黒背景)導入、変化のないPhase(列)は結合

変更履歴

日付 変更点
2018/12/20 初版、Go1.12までの変更点をまとめ
2020/09/11 Go1.15までの変更点を追記
10
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
3