Enhancing Functional Language Compilers through Contification and Dominator Analysis
280 likes | 465 Vues
This paper explores the innovative technique of contification for functional programming, aimed at optimizing compilers by transforming function calls into local control-flow transfers. Traditional optimizations often rely on intraprocedural control-flow information, whereas functional languages typically exhibit interprocedural control flow. By applying contification, we can expose intraprocedural control flow, enabling compiler optimizations. We present a framework for analyzing and transforming call graphs, ensuring safety and efficiency in the compilation process. The findings indicate that contification improves runtime performance while being computationally efficient.
Enhancing Functional Language Compilers through Contification and Dominator Analysis
E N D
Presentation Transcript
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