280 likes | 291 Views
Contification is a technique used in functional language compilers to turn function calls into local control flow transfers, improving running times. This article explains the concept of contification and its benefits.
E N D
Contification Using Dominators Matthew Fluet Cornell University Stephen Weeks InterTrust STAR Lab
Motivation • use traditional optimizations in functional-language compilers • traditional optimizations require intraprocedural control-flow information • in functional languages, most control-flow information is interprocedural • contification: a technique for turning function calls into local control-flow transfers interprocedural intraprocedural
main() main() main() even(x) if x = 0 even(x) if x = 0 even(x) if x = 0 even(x) if x = 0 even(x) if x = 0 k k ret(true) odd(x-1) ret(true) k(true) ret(true) ret(true) odd(x-1) odd(x-1) odd(x-1) odd(x-1) l() k(even(3)) l() even(3) l() k(even(3)) k k odd(y) if y = 0 odd(y) if y = 0 odd(y) if y = 0 odd(y) if y = 0 odd(y) if y = 0 k(z) ... k(z) ... k(z) ... ret(false) ret(false) k(false) ret(false) ret(false) even(y-1) even(y-1) even(y-1) even(y-1) even(y-1) An Example
MLton • a whole-program optimizing compiler for Standard ML SML defunctorize polymorphic, higher-order IL monomorphise simply-typed, higher-order IL closure convert optimize simply-typed, first-order IL generate code native x86
Contification • when a function g is contified within a function f • intraprocedural control-flow is exposed • g will share the same stack frame as f • invocations of g can be optimized • goal: contify as many functions as possible • components of contification • analysis: what functions are contified and where • transformation: single-pass rewrite of the program
k m f g k f f g g Contification Analysis I • represent a program by its call graph • functions m, f, g, h and continuations k, l • a distinguished main function m • nontail calls • tail calls
Contification Analysis II • an analysis maps functions to abstract return locations Return = {?} Cont Func A Analysis = Func Return • A(g) = fg always returns to function fg is contified in the body of f • A(g) = kg always returns to continuation kg is contified where k is defined and g is transformed to transfer control to k • A(g) = ?g is not contified in the transformed program
k f f g g Safety • safety ensures a well-defined and correct transformation • an analysis A is safe if the following hold • A(m) =? • if then A(g) {k, ?} • if then A(g) {f, A(f), ?}
? ? m k1 k2 ? ? f f ? f ? g1 g2 l ? ? l l h1 h2 The Acall and Acont Analyses • Acall– a simple syntactic analysis • Acont– a least fixed-point analysis [Reppy 2001]
? m k1 k2 m k1 k2 l f f h2 g1 g2 l g1 g2 h1 h2 Call Graph h1 Graph G The Adom Analysis I • build a directed graph G, similar to the call graph Node = Return = {?} Cont Func • each edge (l, f) indicates that f returns to location l • if l = ?, then f has no return location
? ? ? m m k1 f k1 k2 k2 l f f f g1 h1 g2 h2 f l Dominator Tree D g1 g2 l h1 h2 Call Graph The Adom Analysis II • build the dominator tree D of G • l dominates f if f always returns to l in any execution of the program • define Adom(f) to be the dominator of f closest to ? • if the immediate dominator of f is ?, then Adom(f) = ?
The Adom Analysis III • Theorem: Adom is safe. • Theorem: Adom is maximal. • for all safe analyses B and all functions f,if B(f) ?, then Adom(f) ?
Compile-time Performance • three rounds of contification in the optimizing cycle • contification quiesces after two rounds • contification takes less than 4% of total compile time • typically less than one second, with a maximum of 13 seconds
Run-time Performance • anomalies • contification may disable size-based inlining • MLton’s optimizer evolved around Acall
Conclusions • a simple, yet general, framework for expressing contification analyses • single transformation • safety condition • maximality criterion • contification is efficient and improves running times Got MLton? You should. http://www.sourcelight.com/MLton
Related Transformations • Local CPS conversion [Reppy 2001] • analyzes a module in isolation • operates over a higher-order IL • escaping functions with unknown control-flow cause imprecision • requires local CPS conversion to apply transformation • Lambda dropping [Danvy and Schultz 2000] • does not approximate the returns of a function • does not change calls from tail to nontail, or vice versa • Loop headers [Appel 1994] • transformation local to a particular function • relies on inlining to expose new control-flow
References • A. W. Appel. Loop headers in -calculus or CPS. Lisp and Symbolic Computation, 7:337-343, 1994. • O. Danvy and U. P. Schultz. Lambda-dropping: Transforming recursive equations into programs with block structure. Theoretical Computer Science, 248(1-2):243-287, 2000. • J. Reppy. Local CPS conversion in a direct-style compiler. In Workshop on Continuations, pages 1-5, Jan. 2001.
m m k k k1 k2 f f g g1 h Comparison to Inlining • no substitution of actual arguments for function parameters • no duplication of code
? k f k m f g The Acall Analysis • intuition: a function f has one return location if • there is exactly one call to f from outside its body; and • there are only tail calls to f within its body • a simple syntactic analysis • original contification analysis used in MLton
? m k k ? ? f g ? h But… • f, g, and h always return to continuation k • but, the call analysis fails to contify any of the functions
? fm k k k k f g k h The Acont Analysis • intuition: a function f returns to continuation k if • all nontail calls to f use k; and • all tail callers of f also return to k • a least fixed point ties the recursion • based on a similar analysis in Moby [Reppy 2001]
?? fm k1 k2 ?? f f? f? g1 g2 ?? h But… • g1, g2, and h all return to function f • but, the call analysis fails to contify h • and, the continuation analysis fails to contify any function
Root m k1 k2 m k1 f k2 l f g1 h1 g2 h2 g1 g2 g3 g3 l Dominator Tree D h1 h2 Call Graph The Adom Analysis IV • setting Adom(f) equal to the immediate dominator of f violates safety • Adom(h1) = f {g3, A(g3), ?} = {g3, g2, ?}
even(x) if x = 0 ret(true) odd(x-1) An Example I
main() even(x) if x = 0 k ret(true) odd(x-1) l() k(even(3)) odd(y) if y = 0 k(z) ... ret(false) even(y-1) An Example II
main() even(x) if x = 0 ret(true) odd(x-1) l() k(even(3)) k odd(y) if y = 0 k(z) ... ret(false) even(y-1) An Example III
main() main() even(x) if x = 0 even(x) if x = 0 even(x) if x = 0 k ret(true) odd(x-1) ret(true) k(true) odd(x-1) odd(x-1) l() k(even(3)) l() even(3) k odd(y) if y = 0 odd(y) if y = 0 odd(y) if y = 0 k(z) ... k(z) ... ret(false) ret(false) k(false) even(y-1) even(y-1) even(y-1) An Example IV