fbpx
Wikipedia

Static single-assignment form

In compiler design, static single assignment form (often abbreviated as SSA form or simply SSA) is a property of an intermediate representation (IR) that requires each variable to be assigned exactly once and defined before it is used. Existing variables in the original IR are split into versions, new variables typically indicated by the original name with a subscript in textbooks, so that every definition gets its own version. In SSA form, use-def chains are explicit and each contains a single element.

One can expect to find SSA in a compiler for Fortran, C, C++,[1] or Java (Android Runtime);[2][3] whereas in functional language compilers, such as those for Scheme and ML, continuation-passing style (CPS) is generally used. SSA is formally equivalent to a well-behaved subset of CPS excluding non-local control flow, which does not occur when CPS is used as intermediate representation.[1] So optimizations and transformations formulated in terms of one immediately apply to the other.

History edit

SSA was developed in the 1980s by several researchers at IBM and Kenneth Zadeck of Brown University.[4][5] A 1986 paper introduced birthpoints, identity assignments, and variable renaming such that variables had a single static assignment.[6] A subsequent 1987 paper by Jeanne Ferrante and Ronald Citron[7] proved that the renaming done in the previous paper removes all false dependencies for scalars.[5] In 1988, Barry Rosen, Mark N. Wegman, and Kenneth Zadeck replaced the identity assignments with Φ-functions, introduced the name "static single-assignment form", and demonstrated a now-common SSA optimization.[8] The name Φ-function was chosen by Rosen to be a more publishable version of "phony function".[5] Alpern, Wegman, and Zadeck presented another optimization, but using the name "single static assignment".[9] Finally, in 1989, Rosen, Wegman, and Zadeck and (independently) Cytron and Ferrante worked on methods of computing SSA form. A few days before the submission deadline, the researchers realized they had substantially the same algorithm,[5] and a 5-author paper was the result.[10]

Benefits edit

The primary usefulness of SSA comes from how it simultaneously simplifies and improves the results of a variety of compiler optimizations, by simplifying the properties of variables. For example, consider this piece of code:

y := 1 y := 2 x := y 

Humans can see that the first assignment is not necessary, and that the value of y being used in the third line comes from the second assignment of y. A program would have to perform reaching definition analysis to determine this. But if the program is in SSA form, both of these are immediate:

y1 := 1 y2 := 2 x1 := y2

Compiler optimization algorithms that are either enabled or strongly enhanced by the use of SSA include:

  • Constant propagation – conversion of computations from runtime to compile time, e.g. treat the instruction a=3*4+5; as if it were a=17;
  • Value range propagation[11] – precompute the potential ranges a calculation could be, allowing for the creation of branch predictions in advance
  • Sparse conditional constant propagation – range-check some values, allowing tests to predict the most likely branch
  • Dead-code elimination – remove code that will have no effect on the results
  • Global value numbering – replace duplicate calculations producing the same result
  • Partial-redundancy elimination – removing duplicate calculations previously performed in some branches of the program
  • Strength reduction – replacing expensive operations by less expensive but equivalent ones, e.g. replace integer multiply or divide by powers of 2 with the potentially less expensive shift left (for multiply) or shift right (for divide).
  • Register allocation – optimize how the limited number of machine registers may be used for calculations

Converting to SSA edit

Converting ordinary code into SSA form is primarily a matter of replacing the target of each assignment with a new variable, and replacing each use of a variable with the "version" of the variable reaching that point. For example, consider the following control-flow graph:

 
An example control-flow graph, before conversion to SSA

Changing the name on the left hand side of "x   x - 3" and changing the following uses of x to that new name would leave the program unaltered. This can be exploited in SSA by creating two new variables: x1 and x2, each of which is assigned only once. Likewise, giving distinguishing subscripts to all the other variables yields:

 
An example control-flow graph, partially converted to SSA

It is clear which definition each use is referring to, except for one case: both uses of y in the bottom block could be referring to either y1 or y2, depending on which path the control flow took.

To resolve this, a special statement is inserted in the last block, called a Φ (Phi) function. This statement will generate a new definition of y called y3 by "choosing" either y1 or y2, depending on the control flow in the past.

 
An example control-flow graph, fully converted to SSA

Now, the last block can simply use y3, and the correct value will be obtained either way. A Φ function for x is not needed: only one version of x, namely x2 is reaching this place, so there is no problem (in other words, Φ(x2,x2)=x2).

Given an arbitrary control-flow graph, it can be difficult to tell where to insert Φ functions, and for which variables. This general question has an efficient solution that can be computed using a concept called dominance frontiers (see below).

Φ functions are not implemented as machine operations on most machines. A compiler can implement a Φ function by inserting "move" operations at the end of every predecessor block. In the example above, the compiler might insert a move from y1 to y3 at the end of the middle-left block and a move from y2 to y3 at the end of the middle-right block. These move operations might not end up in the final code based on the compiler's register allocation procedure. However, this approach may not work when simultaneous operations are speculatively producing inputs to a Φ function, as can happen on wide-issue machines. Typically, a wide-issue machine has a selection instruction used in such situations by the compiler to implement the Φ function.

Computing minimal SSA using dominance frontiers edit

In a control-flow graph, a node A is said to strictly dominate a different node B if it is impossible to reach B without passing through A first. In other words, if node B is reached, then it can be assumed that A has run. A is said to dominate B (or B to be dominated by A) if either A strictly dominates B or A = B.

A node which transfers control to a node A is called an immediate predecessor of A.

The dominance frontier of node A is the set of nodes B where A does not strictly dominate B, but does dominate some immediate predecessor of B. These are the points at which multiple control paths merge back together into a single path.

For example, in the following code:

[1] x = random() if x < 0.5 [2] result = "heads" else [3] result = "tails" end [4] print(result) 

node 1 strictly dominates 2, 3, and 4 and the immediate predecessors of node 4 are nodes 2 and 3.

Dominance frontiers define the points at which Φ functions are needed. In the above example, when control is passed to node 4, the definition of result used depends on whether control was passed from node 2 or 3. Φ functions are not needed for variables defined in a dominator, as there is only one possible definition that can apply.

There is an efficient algorithm for finding dominance frontiers of each node. This algorithm was originally described in "Efficiently Computing Static Single Assignment Form and the Control Graph" by Ron Cytron, Jeanne Ferrante, et al. in 1991.[12]

Keith D. Cooper, Timothy J. Harvey, and Ken Kennedy of Rice University describe an algorithm in their paper titled A Simple, Fast Dominance Algorithm:[13]

for each node b dominance_frontier(b) := {} for each node b if the number of immediate predecessors of b ≥ 2 for each p in immediate predecessors of b runner := p while runner ≠ idom(b) dominance_frontier(runner) := dominance_frontier(runner) ∪ { b } runner := idom(runner) 

In the code above, idom(b) is the immediate dominator of b, the unique node that strictly dominates b but does not strictly dominate any other node that strictly dominates b.

Variations that reduce the number of Φ functions edit

"Minimal" SSA inserts the minimal number of Φ functions required to ensure that each name is assigned a value exactly once and that each reference (use) of a name in the original program can still refer to a unique name. (The latter requirement is needed to ensure that the compiler can write down a name for each operand in each operation.)

However, some of these Φ functions could be dead. For this reason, minimal SSA does not necessarily produce the fewest Φ functions that are needed by a specific procedure. For some types of analysis, these Φ functions are superfluous and can cause the analysis to run less efficiently.

Pruned SSA edit

Pruned SSA form is based on a simple observation: Φ functions are only needed for variables that are "live" after the Φ function. (Here, "live" means that the value is used along some path that begins at the Φ function in question.) If a variable is not live, the result of the Φ function cannot be used and the assignment by the Φ function is dead.

Construction of pruned SSA form uses live-variable information in the Φ function insertion phase to decide whether a given Φ function is needed. If the original variable name isn't live at the Φ function insertion point, the Φ function isn't inserted.

Another possibility is to treat pruning as a dead-code elimination problem. Then, a Φ function is live only if any use in the input program will be rewritten to it, or if it will be used as an argument in another Φ function. When entering SSA form, each use is rewritten to the nearest definition that dominates it. A Φ function will then be considered live as long as it is the nearest definition that dominates at least one use, or at least one argument of a live Φ.

Semi-pruned SSA edit

Semi-pruned SSA form[14] is an attempt to reduce the number of Φ functions without incurring the relatively high cost of computing live-variable information. It is based on the following observation: if a variable is never live upon entry into a basic block, it never needs a Φ function. During SSA construction, Φ functions for any "block-local" variables are omitted.

Computing the set of block-local variables is a simpler and faster procedure than full live-variable analysis, making semi-pruned SSA form more efficient to compute than pruned SSA form. On the other hand, semi-pruned SSA form will contain more Φ functions.

Block arguments edit

Block arguments are an alternative to Φ functions that is representationally identical but in practice can be more convenient during optimization. Blocks are named and take a list of block arguments, notated as function parameters. When calling a block the block arguments are bound to specified values. Swift SIL and MLIR use block arguments.[15]

Converting out of SSA form edit

SSA form is not normally used for direct execution (although it is possible to interpret SSA[16]), and it is frequently used "on top of" another IR with which it remains in direct correspondence. This can be accomplished by "constructing" SSA as a set of functions that map between parts of the existing IR (basic blocks, instructions, operands, etc.) and its SSA counterpart. When the SSA form is no longer needed, these mapping functions may be discarded, leaving only the now-optimized IR.

Performing optimizations on SSA form usually leads to entangled SSA-Webs, meaning there are Φ instructions whose operands do not all have the same root operand. In such cases color-out algorithms are used to come out of SSA. Naive algorithms introduce a copy along each predecessor path that caused a source of different root symbol to be put in Φ than the destination of Φ. There are multiple algorithms for coming out of SSA with fewer copies, most use interference graphs or some approximation of it to do copy coalescing.[17]

Extensions edit

Extensions to SSA form can be divided into two categories.

Renaming scheme extensions alter the renaming criterion. Recall that SSA form renames each variable when it is assigned a value. Alternative schemes include static single use form (which renames each variable at each statement when it is used) and static single information form (which renames each variable when it is assigned a value, and at the post-dominance frontier).

Feature-specific extensions retain the single assignment property for variables, but incorporate new semantics to model additional features. Some feature-specific extensions model high-level programming language features like arrays, objects and aliased pointers. Other feature-specific extensions model low-level architectural features like speculation and predication.

Compilers using SSA form edit

SSA form is a relatively recent development in the compiler community. As such, many older compilers only use SSA form for some part of the compilation or optimization process, but most do not rely on it. Examples of compilers that rely heavily on SSA form include:

  • The ETH Oberon-2 compiler was one of the first public projects to incorporate "GSA", a variant of SSA.
  • The LLVM Compiler Infrastructure uses SSA form for all scalar register values (everything except memory) in its primary code representation. SSA form is only eliminated once register allocation occurs, late in the compile process (often at link time).
  • The Open64 compiler uses SSA form in its global scalar optimizer, though the code is brought into SSA form before and taken out of SSA form afterwards. Open64 uses extensions to SSA form to represent memory in SSA form as well as scalar values.
  • Since the version 4 (released in April 2005) GCC, the GNU Compiler Collection, makes extensive use of SSA. The frontends generate "GENERIC" code that is then converted into "GIMPLE" code by the "gimplifier". High-level optimizations are then applied on the SSA form of "GIMPLE". The resulting optimized intermediate code is then translated into RTL, on which low-level optimizations are applied. The architecture-specific backends finally turn RTL into assembly language.
  • IBM's open source adaptive Java virtual machine, Jikes RVM, uses extended Array SSA, an extension of SSA that allows analysis of scalars, arrays, and object fields in a unified framework. Extended Array SSA analysis is only enabled at the maximum optimization level, which is applied to the most frequently executed portions of code.
  • In 2002, researchers modified IBM's JikesRVM (named Jalapeño at the time) to run both standard Java bytecode and a typesafe SSA (SafeTSA) bytecode class files, and demonstrated significant performance benefits to using the SSA bytecode.
  • Oracle's HotSpot Java Virtual Machine uses an SSA-based intermediate language in its JIT compiler.[18]
  • Microsoft Visual C++ compiler backend available in Microsoft Visual Studio 2015 Update 3 uses SSA[19]
  • Mono uses SSA in its JIT compiler called Mini.
  • jackcc is an open-source compiler for the academic instruction set Jackal 3.0. It uses a simple 3-operand code with SSA for its intermediate representation. As an interesting variant, it replaces Φ functions with a so-called SAME instruction, which instructs the register allocator to place the two live ranges into the same physical register.
  • Although not a compiler, the Boomerang decompiler uses SSA form in its internal representation. SSA is used to simplify expression propagation, identifying parameters and returns, preservation analysis, and more.
  • Portable.NET uses SSA in its JIT compiler.
  • libFirm a completely graph based SSA intermediate representation for compilers. libFirm uses SSA form for all scalar register values until code generation by use of an SSA-aware register allocator.
  • The Illinois Concert Compiler circa 1994[20] used a variant of SSA called SSU (Static Single Use) which renames each variable when it is assigned a value, and in each conditional context in which that variable is used; essentially the static single information form mentioned above. The SSU form is documented in John Plevyak's Ph.D Thesis.
  • The COINS compiler uses SSA form optimizations as explained .
  • The Mozilla Firefox SpiderMonkey JavaScript engine uses SSA-based IR.[21]
  • The Chromium V8 JavaScript engine implements SSA in its Crankshaft compiler infrastructure as announced in December 2010
  • PyPy uses a linear SSA representation for traces in its JIT compiler.
  • Android's Dalvik virtual machine uses SSA in its JIT compiler.
  • Android's new optimizing compiler for the Android Runtime uses SSA for its IR.
  • The Standard ML compiler MLton uses SSA in one of its intermediate languages.
  • LuaJIT makes heavy use of SSA-based optimizations.[22]
  • The PHP and Hack compiler HHVM uses SSA in its IR.[23]
  • Reservoir Labs' R-Stream compiler supports non-SSA (quad list), SSA and SSI (Static Single Information[24]) forms.[25]
  • Go (1.7: for x86-64 architecture only; 1.8: for all supported architectures).[26][27]
  • SPIR-V, the shading language standard for the Vulkan graphics API and kernel language for OpenCL compute API, is an SSA representation.[28]
  • Various Mesa drivers via NIR, an SSA representation for shading languages.[29]
  • WebKit uses SSA in its JIT compilers.[30][31]
  • Swift defines its own SSA form above LLVM IR, called SIL (Swift Intermediate Language).[32][33]
  • Erlang rewrote their compiler in OTP 22.0 to "internally use an intermediate representation based on Static Single Assignment (SSA)." With plans for further optimizations built on top of SSA in future releases.[34]

References edit

Notes edit

  1. ^ a b Kelsey, Richard A. (1995). "A correspondence between continuation passing style and static single assignment form" (PDF). Papers from the 1995 ACM SIGPLAN workshop on Intermediate representations. pp. 13–22. doi:10.1145/202529.202532. ISBN 0897917545. S2CID 6207179.
  2. ^ Rogers, Ian (2020). "Efficient global register allocation". arXiv:2011.05608 [cs.PL].
  3. ^ The Evolution of ART - Google I/O 2016. Google. 25 May 2016. Event occurs at 3m47s.
  4. ^ Rastello & Tichadou 2022, sec. 1.4.
  5. ^ a b c d Zadeck, Kenneth (April 2009). The Development of Static Single Assignment Form (PDF). Static Single-Assignment Form Seminar. Autrans, France.
  6. ^ Cytron, Ron; Lowry, Andy; Zadeck, F. Kenneth (1986). "Code motion of control structures in high-level languages". Proceedings of the 13th ACM SIGACT-SIGPLAN Symposium on Principles of Programming Languages - POPL '86: 70–85. doi:10.1145/512644.512651. S2CID 9099471.
  7. ^ Cytron, Ronald Kaplan; Ferrante, Jeanne. What's in a name? Or, the value of renaming for parallelism detection and storage allocation. International Conference on Parallel Processing, ICPP'87 1987. pp. 19–27.
  8. ^ Barry Rosen; Mark N. Wegman; F. Kenneth Zadeck (1988). "Global value numbers and redundant computations" (PDF). Proceedings of the 15th ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages.
  9. ^ Alpern, B.; Wegman, M. N.; Zadeck, F. K. (1988). "Detecting equality of variables in programs". Proceedings of the 15th ACM SIGPLAN-SIGACT symposium on Principles of programming languages - POPL '88. pp. 1–11. doi:10.1145/73560.73561. ISBN 0897912527. S2CID 18384941.
  10. ^ Cytron, Ron; Ferrante, Jeanne; Rosen, Barry K.; Wegman, Mark N. & Zadeck, F. Kenneth (1991). "Efficiently computing static single assignment form and the control dependence graph" (PDF). ACM Transactions on Programming Languages and Systems. 13 (4): 451–490. CiteSeerX 10.1.1.100.6361. doi:10.1145/115372.115320. S2CID 13243943.
  11. ^ value range propagation
  12. ^ Cytron, Ron; Ferrante, Jeanne; Rosen, Barry K.; Wegman, Mark N.; Zadeck, F. Kenneth (1 October 1991). "Efficiently computing static single assignment form and the control dependence graph". ACM Transactions on Programming Languages and Systems. 13 (4): 451–490. doi:10.1145/115372.115320. S2CID 13243943.
  13. ^ Cooper, Keith D.; Harvey, Timothy J.; Kennedy, Ken (2001). (PDF) (Technical report). Rice University, CS Technical Report 06-33870. Archived from the original (PDF) on 2022-03-26.
  14. ^ Briggs, Preston; Cooper, Keith D.; Harvey, Timothy J.; Simpson, L. Taylor (1998). (PDF) (Technical report). Archived from the original (PDF) on 2010-06-07.
  15. ^ "Block Arguments vs PHI nodes - MLIR Rationale". mlir.llvm.org. Retrieved 4 March 2022.
  16. ^ von Ronne, Jeffery; Ning Wang; Michael Franz (2004). "Interpreting programs in static single assignment form". Proceedings of the 2004 workshop on Interpreters, virtual machines and emulators - IVME '04. p. 23. doi:10.1145/1059579.1059585. ISBN 1581139098. S2CID 451410.
  17. ^ Boissinot, Benoit; Darte, Alain; Rastello, Fabrice; Dinechin, Benoît Dupont de; Guillon, Christophe (2008). "Revisiting Out-of-SSA Translation for Correctness, Code Quality, and Efficiency". HAL-Inria Cs.DS: 14.
  18. ^ "The Java HotSpot Performance Engine Architecture". Oracle Corporation.
  19. ^ "Introducing a new, advanced Visual C++ code optimizer". 4 May 2016.
  20. ^ . Archived from the original on 2014-03-13.
  21. ^ "IonMonkey Overview".,
  22. ^ "Bytecode Optimizations". the LuaJIT project.
  23. ^ "HipHop Intermediate Representation (HHIR)". GitHub. 30 October 2021.
  24. ^ Ananian, C. Scott; Rinard, Martin (1999). Static Single Information Form (PDF) (Technical report). CiteSeerX 10.1.1.1.9976.
  25. ^ Encyclopedia of Parallel Computing.
  26. ^ "Go 1.7 Release Notes - The Go Programming Language". golang.org. Retrieved 2016-08-17.
  27. ^ "Go 1.8 Release Notes - The Go Programming Language". golang.org. Retrieved 2017-02-17.
  28. ^ "SPIR-V spec" (PDF).
  29. ^ Ekstrand, Jason (16 December 2014). "Reintroducing NIR, a new IR for mesa".
  30. ^ "Introducing the WebKit FTL JIT". 13 May 2014.
  31. ^ "Introducing the B3 JIT Compiler". 15 February 2016.
  32. ^ "Swift Intermediate Language (GitHub)". GitHub. 30 October 2021.
  33. ^ "Swift's High-Level IR: A Case Study of Complementing LLVM IR with Language-Specific Optimization, LLVM Developers Meetup 10/2015". YouTube. Archived from the original on 2021-12-21.
  34. ^ "OTP 22.0 Release Notes".

General references edit

  • Rastello, Fabrice; Tichadou, Florent Bouchez, eds. (2022). SSA-based compiler design (PDF). Cham. doi:10.1007/978-3-030-80515-9. ISBN 978-3-030-80515-9. S2CID 63274602.{{cite book}}: CS1 maint: location missing publisher (link)
  • Appel, Andrew W. (1999). Modern Compiler Implementation in ML. Cambridge University Press. ISBN 978-0-521-58274-2. Also available in Java (ISBN 0-521-82060-X, 2002) and C (ISBN 0-521-60765-5, 1998) versions.
  • Cooper, Keith D. & Torczon, Linda (2003). Engineering a Compiler. Morgan Kaufmann. ISBN 978-1-55860-698-2.
  • Muchnick, Steven S. (1997). Advanced Compiler Design and Implementation. Morgan Kaufmann. ISBN 978-1-55860-320-2.
  • Kelsey, Richard A. (March 1995). "A Correspondence between Continuation Passing Style and Static Single Assignment Form". ACM SIGPLAN Notices. 30 (3): 13–22. doi:10.1145/202530.202532.
  • Appel, Andrew W. (April 1998). "SSA is Functional Programming". ACM SIGPLAN Notices. 33 (4): 17–20. doi:10.1145/278283.278285. S2CID 207227209.
  • Pop, Sebastian (2006). "The SSA Representation Framework: Semantics, Analyses and GCC Implementation" (PDF). {{cite journal}}: Cite journal requires |journal= (help)
  • Matthias Braun; Sebastian Buchwald; Sebastian Hack; Roland Leißa; Christoph Mallon; Andreas Zwinkau (2013), "Simple and Efficient Construction of Static Single Assignment Form", Compiler Construction, Lecture Notes in Computer Science, vol. 7791, Springer Berlin Heidelberg, pp. 102–122, doi:10.1007/978-3-642-37051-9_6, ISBN 978-3-642-37050-2, retrieved 24 March 2013

External links edit

  • Bosscher, Steven; and Novillo, Diego. GCC gets a new Optimizer Framework. An article about GCC's use of SSA and how it improves over older IRs.
  • The SSA Bibliography. Extensive catalogue of SSA research papers.
  • Zadeck, F. Kenneth. "The Development of Static Single Assignment Form", December 2007 talk on the origins of SSA.

static, single, assignment, form, compiler, design, static, single, assignment, form, often, abbreviated, form, simply, property, intermediate, representation, that, requires, each, variable, assigned, exactly, once, defined, before, used, existing, variables,. In compiler design static single assignment form often abbreviated as SSA form or simply SSA is a property of an intermediate representation IR that requires each variable to be assigned exactly once and defined before it is used Existing variables in the original IR are split into versions new variables typically indicated by the original name with a subscript in textbooks so that every definition gets its own version In SSA form use def chains are explicit and each contains a single element One can expect to find SSA in a compiler for Fortran C C 1 or Java Android Runtime 2 3 whereas in functional language compilers such as those for Scheme and ML continuation passing style CPS is generally used SSA is formally equivalent to a well behaved subset of CPS excluding non local control flow which does not occur when CPS is used as intermediate representation 1 So optimizations and transformations formulated in terms of one immediately apply to the other Contents 1 History 2 Benefits 3 Converting to SSA 3 1 Computing minimal SSA using dominance frontiers 4 Variations that reduce the number of F functions 4 1 Pruned SSA 4 2 Semi pruned SSA 4 3 Block arguments 5 Converting out of SSA form 6 Extensions 7 Compilers using SSA form 8 References 8 1 Notes 8 2 General references 9 External linksHistory editSSA was developed in the 1980s by several researchers at IBM and Kenneth Zadeck of Brown University 4 5 A 1986 paper introduced birthpoints identity assignments and variable renaming such that variables had a single static assignment 6 A subsequent 1987 paper by Jeanne Ferrante and Ronald Citron 7 proved that the renaming done in the previous paper removes all false dependencies for scalars 5 In 1988 Barry Rosen Mark N Wegman and Kenneth Zadeck replaced the identity assignments with F functions introduced the name static single assignment form and demonstrated a now common SSA optimization 8 The name F function was chosen by Rosen to be a more publishable version of phony function 5 Alpern Wegman and Zadeck presented another optimization but using the name single static assignment 9 Finally in 1989 Rosen Wegman and Zadeck and independently Cytron and Ferrante worked on methods of computing SSA form A few days before the submission deadline the researchers realized they had substantially the same algorithm 5 and a 5 author paper was the result 10 Benefits editThe primary usefulness of SSA comes from how it simultaneously simplifies and improves the results of a variety of compiler optimizations by simplifying the properties of variables For example consider this piece of code y 1 y 2 x y Humans can see that the first assignment is not necessary and that the value of y being used in the third line comes from the second assignment of y A program would have to perform reaching definition analysis to determine this But if the program is in SSA form both of these are immediate y1 1 y2 2 x1 y2 Compiler optimization algorithms that are either enabled or strongly enhanced by the use of SSA include Constant propagation conversion of computations from runtime to compile time e g treat the instruction a 3 4 5 as if it were a 17 Value range propagation 11 precompute the potential ranges a calculation could be allowing for the creation of branch predictions in advance Sparse conditional constant propagation range check some values allowing tests to predict the most likely branch Dead code elimination remove code that will have no effect on the results Global value numbering replace duplicate calculations producing the same result Partial redundancy elimination removing duplicate calculations previously performed in some branches of the program Strength reduction replacing expensive operations by less expensive but equivalent ones e g replace integer multiply or divide by powers of 2 with the potentially less expensive shift left for multiply or shift right for divide Register allocation optimize how the limited number of machine registers may be used for calculationsConverting to SSA editConverting ordinary code into SSA form is primarily a matter of replacing the target of each assignment with a new variable and replacing each use of a variable with the version of the variable reaching that point For example consider the following control flow graph nbsp An example control flow graph before conversion to SSAChanging the name on the left hand side of x displaystyle leftarrow nbsp x 3 and changing the following uses of x to that new name would leave the program unaltered This can be exploited in SSA by creating two new variables x1 and x2 each of which is assigned only once Likewise giving distinguishing subscripts to all the other variables yields nbsp An example control flow graph partially converted to SSAIt is clear which definition each use is referring to except for one case both uses of y in the bottom block could be referring to either y1 or y2 depending on which path the control flow took To resolve this a special statement is inserted in the last block called a F Phi function This statement will generate a new definition of y called y3 by choosing either y1 or y2 depending on the control flow in the past nbsp An example control flow graph fully converted to SSANow the last block can simply use y3 and the correct value will be obtained either way A F function for x is not needed only one version of x namely x2 is reaching this place so there is no problem in other words F x2 x2 x2 Given an arbitrary control flow graph it can be difficult to tell where to insert F functions and for which variables This general question has an efficient solution that can be computed using a concept called dominance frontiers see below F functions are not implemented as machine operations on most machines A compiler can implement a F function by inserting move operations at the end of every predecessor block In the example above the compiler might insert a move from y1 to y3 at the end of the middle left block and a move from y2 to y3 at the end of the middle right block These move operations might not end up in the final code based on the compiler s register allocation procedure However this approach may not work when simultaneous operations are speculatively producing inputs to a F function as can happen on wide issue machines Typically a wide issue machine has a selection instruction used in such situations by the compiler to implement the F function Computing minimal SSA using dominance frontiers edit In a control flow graph a node A is said to strictly dominate a different node B if it is impossible to reach B without passing through A first In other words if node B is reached then it can be assumed that A has run A is said to dominate B or B to be dominated by A if either A strictly dominates B or A B A node which transfers control to a node A is called an immediate predecessor of A The dominance frontier of node A is the set of nodes B where A does not strictly dominate B but does dominate some immediate predecessor of B These are the points at which multiple control paths merge back together into a single path For example in the following code 1 x random if x lt 0 5 2 result heads else 3 result tails end 4 print result node 1 strictly dominates 2 3 and 4 and the immediate predecessors of node 4 are nodes 2 and 3 Dominance frontiers define the points at which F functions are needed In the above example when control is passed to node 4 the definition of result used depends on whether control was passed from node 2 or 3 F functions are not needed for variables defined in a dominator as there is only one possible definition that can apply There is an efficient algorithm for finding dominance frontiers of each node This algorithm was originally described in Efficiently Computing Static Single Assignment Form and the Control Graph by Ron Cytron Jeanne Ferrante et al in 1991 12 Keith D Cooper Timothy J Harvey and Ken Kennedy of Rice University describe an algorithm in their paper titled A Simple Fast Dominance Algorithm 13 for each node b dominance frontier b for each node b if the number of immediate predecessors of b 2 for each p in immediate predecessors of b runner p while runner idom b dominance frontier runner dominance frontier runner b runner idom runner In the code above idom b is the immediate dominator of b the unique node that strictly dominates b but does not strictly dominate any other node that strictly dominates b Variations that reduce the number of F functions edit Minimal SSA inserts the minimal number of F functions required to ensure that each name is assigned a value exactly once and that each reference use of a name in the original program can still refer to a unique name The latter requirement is needed to ensure that the compiler can write down a name for each operand in each operation However some of these F functions could be dead For this reason minimal SSA does not necessarily produce the fewest F functions that are needed by a specific procedure For some types of analysis these F functions are superfluous and can cause the analysis to run less efficiently Pruned SSA edit Pruned SSA form is based on a simple observation F functions are only needed for variables that are live after the F function Here live means that the value is used along some path that begins at the F function in question If a variable is not live the result of the F function cannot be used and the assignment by the F function is dead Construction of pruned SSA form uses live variable information in the F function insertion phase to decide whether a given F function is needed If the original variable name isn t live at the F function insertion point the F function isn t inserted Another possibility is to treat pruning as a dead code elimination problem Then a F function is live only if any use in the input program will be rewritten to it or if it will be used as an argument in another F function When entering SSA form each use is rewritten to the nearest definition that dominates it A F function will then be considered live as long as it is the nearest definition that dominates at least one use or at least one argument of a live F Semi pruned SSA edit Semi pruned SSA form 14 is an attempt to reduce the number of F functions without incurring the relatively high cost of computing live variable information It is based on the following observation if a variable is never live upon entry into a basic block it never needs a F function During SSA construction F functions for any block local variables are omitted Computing the set of block local variables is a simpler and faster procedure than full live variable analysis making semi pruned SSA form more efficient to compute than pruned SSA form On the other hand semi pruned SSA form will contain more F functions Block arguments edit Block arguments are an alternative to F functions that is representationally identical but in practice can be more convenient during optimization Blocks are named and take a list of block arguments notated as function parameters When calling a block the block arguments are bound to specified values Swift SIL and MLIR use block arguments 15 Converting out of SSA form editSSA form is not normally used for direct execution although it is possible to interpret SSA 16 and it is frequently used on top of another IR with which it remains in direct correspondence This can be accomplished by constructing SSA as a set of functions that map between parts of the existing IR basic blocks instructions operands etc and its SSA counterpart When the SSA form is no longer needed these mapping functions may be discarded leaving only the now optimized IR Performing optimizations on SSA form usually leads to entangled SSA Webs meaning there are F instructions whose operands do not all have the same root operand In such cases color out algorithms are used to come out of SSA Naive algorithms introduce a copy along each predecessor path that caused a source of different root symbol to be put in F than the destination of F There are multiple algorithms for coming out of SSA with fewer copies most use interference graphs or some approximation of it to do copy coalescing 17 Extensions editExtensions to SSA form can be divided into two categories Renaming scheme extensions alter the renaming criterion Recall that SSA form renames each variable when it is assigned a value Alternative schemes include static single use form which renames each variable at each statement when it is used and static single information form which renames each variable when it is assigned a value and at the post dominance frontier Feature specific extensions retain the single assignment property for variables but incorporate new semantics to model additional features Some feature specific extensions model high level programming language features like arrays objects and aliased pointers Other feature specific extensions model low level architectural features like speculation and predication Compilers using SSA form editThis section may contain excessive or irrelevant examples Please help improve the article by adding descriptive text and removing less pertinent examples August 2018 SSA form is a relatively recent development in the compiler community As such many older compilers only use SSA form for some part of the compilation or optimization process but most do not rely on it Examples of compilers that rely heavily on SSA form include The ETH Oberon 2 compiler was one of the first public projects to incorporate GSA a variant of SSA The LLVM Compiler Infrastructure uses SSA form for all scalar register values everything except memory in its primary code representation SSA form is only eliminated once register allocation occurs late in the compile process often at link time The Open64 compiler uses SSA form in its global scalar optimizer though the code is brought into SSA form before and taken out of SSA form afterwards Open64 uses extensions to SSA form to represent memory in SSA form as well as scalar values Since the version 4 released in April 2005 GCC the GNU Compiler Collection makes extensive use of SSA The frontends generate GENERIC code that is then converted into GIMPLE code by the gimplifier High level optimizations are then applied on the SSA form of GIMPLE The resulting optimized intermediate code is then translated into RTL on which low level optimizations are applied The architecture specific backends finally turn RTL into assembly language IBM s open source adaptive Java virtual machine Jikes RVM uses extended Array SSA an extension of SSA that allows analysis of scalars arrays and object fields in a unified framework Extended Array SSA analysis is only enabled at the maximum optimization level which is applied to the most frequently executed portions of code In 2002 researchers modified IBM s JikesRVM named Jalapeno at the time to run both standard Java bytecode and a typesafe SSA SafeTSA bytecode class files and demonstrated significant performance benefits to using the SSA bytecode Oracle s HotSpot Java Virtual Machine uses an SSA based intermediate language in its JIT compiler 18 Microsoft Visual C compiler backend available in Microsoft Visual Studio 2015 Update 3 uses SSA 19 Mono uses SSA in its JIT compiler called Mini jackcc is an open source compiler for the academic instruction set Jackal 3 0 It uses a simple 3 operand code with SSA for its intermediate representation As an interesting variant it replaces F functions with a so called SAME instruction which instructs the register allocator to place the two live ranges into the same physical register Although not a compiler the Boomerang decompiler uses SSA form in its internal representation SSA is used to simplify expression propagation identifying parameters and returns preservation analysis and more Portable NET uses SSA in its JIT compiler libFirm a completely graph based SSA intermediate representation for compilers libFirm uses SSA form for all scalar register values until code generation by use of an SSA aware register allocator The Illinois Concert Compiler circa 1994 20 used a variant of SSA called SSU Static Single Use which renames each variable when it is assigned a value and in each conditional context in which that variable is used essentially the static single information form mentioned above The SSU form is documented in John Plevyak s Ph D Thesis The COINS compiler uses SSA form optimizations as explained here The Mozilla Firefox SpiderMonkey JavaScript engine uses SSA based IR 21 The Chromium V8 JavaScript engine implements SSA in its Crankshaft compiler infrastructure as announced in December 2010 PyPy uses a linear SSA representation for traces in its JIT compiler Android s Dalvik virtual machine uses SSA in its JIT compiler Android s new optimizing compiler for the Android Runtime uses SSA for its IR The Standard ML compiler MLton uses SSA in one of its intermediate languages LuaJIT makes heavy use of SSA based optimizations 22 The PHP and Hack compiler HHVM uses SSA in its IR 23 Reservoir Labs R Stream compiler supports non SSA quad list SSA and SSI Static Single Information 24 forms 25 Go 1 7 for x86 64 architecture only 1 8 for all supported architectures 26 27 SPIR V the shading language standard for the Vulkan graphics API and kernel language for OpenCL compute API is an SSA representation 28 Various Mesa drivers via NIR an SSA representation for shading languages 29 WebKit uses SSA in its JIT compilers 30 31 Swift defines its own SSA form above LLVM IR called SIL Swift Intermediate Language 32 33 Erlang rewrote their compiler in OTP 22 0 to internally use an intermediate representation based on Static Single Assignment SSA With plans for further optimizations built on top of SSA in future releases 34 References editNotes edit a b Kelsey Richard A 1995 A correspondence between continuation passing style and static single assignment form PDF Papers from the 1995 ACM SIGPLAN workshop on Intermediate representations pp 13 22 doi 10 1145 202529 202532 ISBN 0897917545 S2CID 6207179 Rogers Ian 2020 Efficient global register allocation arXiv 2011 05608 cs PL The Evolution of ART Google I O 2016 Google 25 May 2016 Event occurs at 3m47s Rastello amp Tichadou 2022 sec 1 4 a b c d Zadeck Kenneth April 2009 The Development of Static Single Assignment Form PDF Static Single Assignment Form Seminar Autrans France Cytron Ron Lowry Andy Zadeck F Kenneth 1986 Code motion of control structures in high level languages Proceedings of the 13th ACM SIGACT SIGPLAN Symposium on Principles of Programming Languages POPL 86 70 85 doi 10 1145 512644 512651 S2CID 9099471 Cytron Ronald Kaplan Ferrante Jeanne What s in a name Or the value of renaming for parallelism detection and storage allocation International Conference on Parallel Processing ICPP 87 1987 pp 19 27 Barry Rosen Mark N Wegman F Kenneth Zadeck 1988 Global value numbers and redundant computations PDF Proceedings of the 15th ACM SIGPLAN SIGACT Symposium on Principles of Programming Languages Alpern B Wegman M N Zadeck F K 1988 Detecting equality of variables in programs Proceedings of the 15th ACM SIGPLAN SIGACT symposium on Principles of programming languages POPL 88 pp 1 11 doi 10 1145 73560 73561 ISBN 0897912527 S2CID 18384941 Cytron Ron Ferrante Jeanne Rosen Barry K Wegman Mark N amp Zadeck F Kenneth 1991 Efficiently computing static single assignment form and the control dependence graph PDF ACM Transactions on Programming Languages and Systems 13 4 451 490 CiteSeerX 10 1 1 100 6361 doi 10 1145 115372 115320 S2CID 13243943 value range propagation Cytron Ron Ferrante Jeanne Rosen Barry K Wegman Mark N Zadeck F Kenneth 1 October 1991 Efficiently computing static single assignment form and the control dependence graph ACM Transactions on Programming Languages and Systems 13 4 451 490 doi 10 1145 115372 115320 S2CID 13243943 Cooper Keith D Harvey Timothy J Kennedy Ken 2001 A Simple Fast Dominance Algorithm PDF Technical report Rice University CS Technical Report 06 33870 Archived from the original PDF on 2022 03 26 Briggs Preston Cooper Keith D Harvey Timothy J Simpson L Taylor 1998 Practical Improvements to the Construction and Destruction of Static Single Assignment Form PDF Technical report Archived from the original PDF on 2010 06 07 Block Arguments vs PHI nodes MLIR Rationale mlir llvm org Retrieved 4 March 2022 von Ronne Jeffery Ning Wang Michael Franz 2004 Interpreting programs in static single assignment form Proceedings of the 2004 workshop on Interpreters virtual machines and emulators IVME 04 p 23 doi 10 1145 1059579 1059585 ISBN 1581139098 S2CID 451410 Boissinot Benoit Darte Alain Rastello Fabrice Dinechin Benoit Dupont de Guillon Christophe 2008 Revisiting Out of SSA Translation for Correctness Code Quality and Efficiency HAL Inria Cs DS 14 The Java HotSpot Performance Engine Architecture Oracle Corporation Introducing a new advanced Visual C code optimizer 4 May 2016 Illinois Concert Project Archived from the original on 2014 03 13 IonMonkey Overview Bytecode Optimizations the LuaJIT project HipHop Intermediate Representation HHIR GitHub 30 October 2021 Ananian C Scott Rinard Martin 1999 Static Single Information Form PDF Technical report CiteSeerX 10 1 1 1 9976 Encyclopedia of Parallel Computing Go 1 7 Release Notes The Go Programming Language golang org Retrieved 2016 08 17 Go 1 8 Release Notes The Go Programming Language golang org Retrieved 2017 02 17 SPIR V spec PDF Ekstrand Jason 16 December 2014 Reintroducing NIR a new IR for mesa Introducing the WebKit FTL JIT 13 May 2014 Introducing the B3 JIT Compiler 15 February 2016 Swift Intermediate Language GitHub GitHub 30 October 2021 Swift s High Level IR A Case Study of Complementing LLVM IR with Language Specific Optimization LLVM Developers Meetup 10 2015 YouTube Archived from the original on 2021 12 21 OTP 22 0 Release Notes General references edit Rastello Fabrice Tichadou Florent Bouchez eds 2022 SSA based compiler design PDF Cham doi 10 1007 978 3 030 80515 9 ISBN 978 3 030 80515 9 S2CID 63274602 a href Template Cite book html title Template Cite book cite book a CS1 maint location missing publisher link Appel Andrew W 1999 Modern Compiler Implementation in ML Cambridge University Press ISBN 978 0 521 58274 2 Also available in Java ISBN 0 521 82060 X 2002 and C ISBN 0 521 60765 5 1998 versions Cooper Keith D amp Torczon Linda 2003 Engineering a Compiler Morgan Kaufmann ISBN 978 1 55860 698 2 Muchnick Steven S 1997 Advanced Compiler Design and Implementation Morgan Kaufmann ISBN 978 1 55860 320 2 Kelsey Richard A March 1995 A Correspondence between Continuation Passing Style and Static Single Assignment Form ACM SIGPLAN Notices 30 3 13 22 doi 10 1145 202530 202532 Appel Andrew W April 1998 SSA is Functional Programming ACM SIGPLAN Notices 33 4 17 20 doi 10 1145 278283 278285 S2CID 207227209 Pop Sebastian 2006 The SSA Representation Framework Semantics Analyses and GCC Implementation PDF a href Template Cite journal html title Template Cite journal cite journal a Cite journal requires journal help Matthias Braun Sebastian Buchwald Sebastian Hack Roland Leissa Christoph Mallon Andreas Zwinkau 2013 Simple and Efficient Construction of Static Single Assignment Form Compiler Construction Lecture Notes in Computer Science vol 7791 Springer Berlin Heidelberg pp 102 122 doi 10 1007 978 3 642 37051 9 6 ISBN 978 3 642 37050 2 retrieved 24 March 2013External links editBosscher Steven and Novillo Diego GCC gets a new Optimizer Framework An article about GCC s use of SSA and how it improves over older IRs The SSA Bibliography Extensive catalogue of SSA research papers Zadeck F Kenneth The Development of Static Single Assignment Form December 2007 talk on the origins of SSA Retrieved from https en wikipedia org w index php title Static single assignment form amp oldid 1209495970, wikipedia, wiki, book, books, library,

article

, read, download, free, free download, mp3, video, mp4, 3gp, jpg, jpeg, gif, png, picture, music, song, movie, book, game, games.