静的単一代入(せいてきたんいつだいにゅう、)形式は、コンパイラ設計における 中間表現 (IR) のひとつで、各変数が一度のみ代入されるよう定義されたものである。もともとの中間表現における変数は「バージョン」に分割され、全ての変数の定義がバージョンを表現できるよう、通例新たな変数は元の名前に添え字を付けて表現される。SSA ではが明示的であり、連鎖は要素を一つだけ持つ。SSA はRon Cytron、、Barry Rosen、、Ken Zadeck および IBM の研究者たちにより1980年代に開発された。Scheme、ML、Haskell などの関数型言語のコンパイラでは、Fortran や C などのコンパイラで SSA の利用が期待される箇所で継続渡しスタイル (CPS) を用いるのが一般的である。SSA と CPS は形式的に等価であり、最適化やコードの変換などがいずれかに施された場合、もう片方にも同様に適用することができる。変数の性質を簡単なものにすることにより様々なコンパイラ最適化を簡略化すると同時にその結果を改善することが SSA の第一の利点である。例として、下記のようなコードを考える。人間であれば、最初の代入が不要であり、3行目で使用されている codice_1 の値が2行目の代入の結果であることが分かる。これをプログラムで行う場合には、により求める必要がある。しかし、プログラムが静的単一代入形式であれば、いずれも即座に判定可能である。SSA を利用することにより、下記のコンパイラ最適化アルゴリズムを実現したり、あるいは改善することができる。ツリー上のコードの SSA 形式への変換は、代入の対象を新たな変数に置き換え、変数の使用箇所をその定義箇所に到達する「バージョン付き」のものに置き換えるだけの基本的に簡潔な問題である。例として、下記のような制御フローグラフを考える。"x formula_1 x - 3" の左辺の名前を変え、それ以降 x を新たな名前に変えることができ、それでもプログラムは全く同じ動作をする。このことを利用して、SSA ではそれぞれに対して一度しか代入が行われない新たな二つの変数x と x を作成する。同様に、全ての変数に対してバージョンを区別するための添え字を与える。ここで、各々の変数を使用している箇所がどの定義を参照しているかをただ一点を除いて把握している。最後のブロックの y は制御フローのどちらを通るかによって y と yのどちらを参照するかが異なる。ではこれをどのようにして知るのか?その答えは、"Φ (ファイ) 関数"と呼ばれる特別な命令を最後のブロックの始めに追加することである。この命令は、どちらの制御フローから到達したのかによって y あるいは y を選択し y の新たな定義 y を生成する。これにより、最後のブロックの y は y を用いることができ、いずれの場合でも正し値を得ることができる。x についても Φ 関数を追加する必要があるか?という質問があるかもしれないが、答えは「不要」である。x のバージョンは x のみがこの箇所に到達しており、問題にはならない。より一般的な質問として、任意の制御フローが与えられたとき、どこに、またどの変数に対して Φ 関数を挿入するべきか、という問題がある。これは難しい質問であるが、"支配辺境(dominance frontier) "と呼ばれる概念を用いて求める優れた方法がある。ここで、Φ 関数は実際に実装されるものではなく、コンパイラに対して Φ 関数でグループとされる全ての変数の値をメモリやレジスタの同じ場所に配置するよう指示するマーカーである。まず、 の概念が必要である。制御フローのノード A が別のノード B を "厳密に支配する" とき、A に到達しなければ B に到達することがないことを意味する。これは、B に到達していれば A のコードが動作していることが分かるため有用である。また A が B を "支配する"とき、A が B を厳密に支配するか、A = B であることを意味する。ここで、を次のように定義することができる。A は B を厳密に支配していないが、B の直前にあるノードのいくつかを支配しているとき( A が B の直前にあれば、A 自身)、ノード B は A の支配辺境内にあるものとする。A から見ると、これらは A を介さず、最初に登場する制御パス上のノードである。支配辺境は Φ 関数を必要とする場所を正確に捉えることができ、その定義のみ(あるいは再定義)が A の支配するノードに到達する。これらのノードを去り支配辺境に入る場合のみ、同じ変数を定義している箇所にそれ以外のフローを考慮すればよい。また、制御フローグラフ中に A の定義を扱う Φ 関数はそれ以上必要ない。支配辺境を求めるアルゴリズムに一つとして、下記のものがある。注意:上記のコードでは、ノード n の前のノードは制御を n に渡す任意のノードであり、idom(n) がノードの n を直接支配する。支配辺境を見つけるための効率的なアルゴリズムが存在し、論文 "Efficiently computing static single assignment form and the control dependence graph
出典:wikipedia
LINEスタンプ制作に興味がある場合は、
下記よりスタンプファクトリーのホームページをご覧ください。