Functional programming languages

Similar documents
Formal verification of an optimizing compiler

SSA, CPS, ANF: THREE APPROACHES

MPRI course 2-4 Functional programming languages Exercises

Functional programming languages

Lecture Notes on Register Allocation

ECE 5775 High-Level Digital Design Automation Fall More CFG Static Single Assignment

Register Allocation. Global Register Allocation Webs and Graph Coloring Node Splitting and Other Transformations

Intermediate representation

Intermediate representations IR #1: CPS/L 3. Code example. Advanced Compiler Construction Michel Schinz

MIT Introduction to Program Analysis and Optimization. Martin Rinard Laboratory for Computer Science Massachusetts Institute of Technology

Lecture 3 Local Optimizations, Intro to SSA

Programming Language Processor Theory

An Overview of GCC Architecture (source: wikipedia) Control-Flow Analysis and Loop Detection

A Bad Name. CS 2210: Optimization. Register Allocation. Optimization. Reaching Definitions. Dataflow Analyses 4/10/2013

Compiler Construction 2009/2010 SSA Static Single Assignment Form

CS577 Modern Language Processors. Spring 2018 Lecture Optimization

CS153: Compilers Lecture 23: Static Single Assignment Form

(just another operator) Ambiguous scalars or aggregates go into memory

Lecture 23 CIS 341: COMPILERS

A Functional Perspective on SSA Optimisation Algorithms

Intermediate Representations. Reading & Topics. Intermediate Representations CS2210

Lecture 21 CIS 341: COMPILERS

Compiler Construction 2016/2017 Loop Optimizations

CSE 501: Compiler Construction. Course outline. Goals for language implementation. Why study compilers? Models of compilation

Lecture Notes on Static Single Assignment Form

Lambda Calculus. Variables and Functions. cs3723 1

An example of optimization in LLVM. Compiler construction Step 1: Naive translation to LLVM. Step 2: Translating to SSA form (opt -mem2reg)

8. Static Single Assignment Form. Marcus Denker

6. Intermediate Representation

Compiler Optimization

IR Optimization. May 15th, Tuesday, May 14, 13

The Essence of Compiling with Continuations

Compiler Construction 2010/2011 Loop Optimizations

Static Single Assignment Form in the COINS Compiler Infrastructure

Code generation for modern processors

Concepts of programming languages

CSE Section 10 - Dataflow and Single Static Assignment - Solutions

6. Intermediate Representation!

Compiler Passes. Optimization. The Role of the Optimizer. Optimizations. The Optimizer (or Middle End) Traditional Three-pass Compiler

Code generation for modern processors

Intermediate Code Generation

Introduction to Compilers

Linear Scan Register Allocation. Kevin Millikin

Lecture Notes: Control Flow Analysis for Functional Languages

Intermediate Representation (IR)

Global Optimization. Lecture Outline. Global flow analysis. Global constant propagation. Liveness analysis. Local Optimization. Global Optimization

Control-Flow Graphs & Dataflow Analysis. CS4410: Spring 2013

CS 701. Class Meets. Instructor. Teaching Assistant. Key Dates. Charles N. Fischer. Fall Tuesdays & Thursdays, 11:00 12: Engineering Hall

Verifying Program Invariants with Refinement Types

Advanced C Programming

Sémantique des Langages de Programmation (SemLP) DM : Region Types

Data Structures and Algorithms in Compiler Optimization. Comp314 Lecture Dave Peixotto

7. Optimization! Prof. O. Nierstrasz! Lecture notes by Marcus Denker!

This test is not formatted for your answers. Submit your answers via to:

SSA-Form Register Allocation

Principles of Compiler Design

Register Allocation. Register Allocation. Local Register Allocation. Live range. Register Allocation for Loops

CSE P 501 Compilers. SSA Hal Perkins Spring UW CSE P 501 Spring 2018 V-1

Register Allocation 3/16/11. What a Smart Allocator Needs to Do. Global Register Allocation. Global Register Allocation. Outline.

Type Systems Winter Semester 2006

Lecture Notes on Static Single Assignment Form

CITS3211 FUNCTIONAL PROGRAMMING. 14. Graph reduction

SSA Construction. Daniel Grund & Sebastian Hack. CC Winter Term 09/10. Saarland University

CS153: Compilers Lecture 17: Control Flow Graph and Data Flow Analysis

Intermediate Representations Part II

Tour of common optimizations

LR Parsing LALR Parser Generators

Static Single Information from a Functional Perspective

Scope and Introduction to Functional Languages. Review and Finish Scoping. Announcements. Assignment 3 due Thu at 11:55pm. Website has SML resources

Register Allocation in Just-in-Time Compilers: 15 Years of Linear Scan

CPSC 510 (Fall 2007, Winter 2008) Compiler Construction II

Continuation Passing Style. Continuation Passing Style

CS 6110 S14 Lecture 38 Abstract Interpretation 30 April 2014

What Compilers Can and Cannot Do. Saman Amarasinghe Fall 2009

Compiler Construction

CSE443 Compilers. Dr. Carl Alphonce 343 Davis Hall

Compilers: The goal. Safe. e : ASM

Calvin Lin The University of Texas at Austin

Abstract Interpretation Continued

CHAPTER ONE OVERVIEW. 1.1 Continuation-passing style

Static analysis and all that

Intra-procedural Data Flow Analysis Introduction

Fundamentals of Compilation

CS 406/534 Compiler Construction Putting It All Together

Compiler Optimization Intermediate Representation

Register Allocation. CS 502 Lecture 14 11/25/08

CS 132 Compiler Construction

CMSC 330: Organization of Programming Languages. Lambda Calculus

In One Slide. Outline. LR Parsing. Table Construction

LR Parsing LALR Parser Generators

JOHANNES KEPLER UNIVERSITÄT LINZ

Challenges in the back end. CS Compiler Design. Basic blocks. Compiler analysis

CS 2461: Computer Architecture 1

CSC D70: Compiler Optimization Register Allocation

Register Allocation & Liveness Analysis

Bottom-Up Parsing. Lecture 11-12

Lecture Notes on Loop-Invariant Code Motion

Chapter 2 The Language PCF

Topic I (d): Static Single Assignment Form (SSA)

Agenda. CSE P 501 Compilers. Big Picture. Compiler Organization. Intermediate Representations. IR for Code Generation. CSE P 501 Au05 N-1

Transcription:

Functional programming languages Part V: functional intermediate representations Xavier Leroy INRIA Paris-Rocquencourt MPRI 2-4, 2015 2017 X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 1 / 36 Intermediate representations in a compiler Between high-level languages and machine code, compilers generally go through one or several intermediate representations where, in particular: Expressions are decomposed in a sequence of processor-level instructions. --> x = (y + z) * (a - b) t1 = y + z; t2 = a - b; x = t1 * t2; Temporary variables (t1, t2) are introduced to hold intermediate results. These temporaries, along with program variables, can later be placed in concrete locations: processor registers or stack slots. Various optimizations can be performed over the intermediate representation. X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 2 / 36

Outline 1 A conventional IR: RTL-CFG 2 CPS as a functional IR 3 Another functional IR: A-normal forms X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 3 / 36 A conventional IR: RTL-CFG A conventional intermediate representation: RTL-CFG (Register Transfer Language with Control-Flow Graph.) A function = a set of processor-level instructions operating over variables and temporaries, e.g. x = y + z t = load(x + 8) if (t == 0) Organized in a control-flow graph: Nodes = instructions. Edge from I to J = J can execute just after I. X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 4 / 36

A conventional IR: RTL-CFG Example: some source code double average(int * tbl, int size) { double s = 0.0; int i; for (i = 0; i < size; i++) s = s + tbl[i]; return s; } X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 5 / 36 A conventional IR: RTL-CFG Example: the corresponding RTL graph s = 0.0 i = 0 if (i >= size) d = float(size) a = i << 2 e = s / f d b = load(tbl + a) return(e) c = float(b) s = s + f c i = i + 1 X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 6 / 36

A conventional IR: RTL-CFG Classic optimizations over RTL Many classic optimizations can be performed on the RTL form. Constant propagation a = 1 a = 1 b = 2 --> b = 2 c = a + b c = 3 d = x - a d = x + (-1) Dead code elimination (if a unused later) a = 1 nop b = 2 --> b = 2 c = 3 c = 3 X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 7 / 36 A conventional IR: RTL-CFG Common subexpression elimination c = a c = a d = a + b --> d = a + b e = c + b e = d Hoisting of loop-invariant computations L: c = a + b c = a + b... --> L:...... -> L... -> L Induction variable elimination i = 0 i = 0 L: a = i * 4 --> b = p b = p + a L:...... b = b + 4 i = i + 1 -> L i = i + 1 -> L... and much more. (See e.g. Steven Muchnick, Advanced Compiler Design and Implementation, Morgan Kaufmann Publishers.) X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 8 / 36

A conventional IR: RTL-CFG RTL optimizations and dataflow analysis Problem: it is not obvious to see where these optimizations apply, because 1 A given variable or temporary can be defined several times. (Unavoidable if the source language is imperative.) 2 The CFG is not a structured representation of control. n = 1 n = 2 n is 2 n is 1 n statically unknown n = n + 1 n statically unknown X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 9 / 36 A conventional IR: RTL-CFG RTL optimizations and dataflow analysis Solution: use static analyses to determine opportunities for optimization, e.g. dataflow analyses (a simple case of abstract interpretation). Example: for constant propagation, use the abstract lattice a := N n = 1 n = 2 ñ = 2 ñ = 1 n = n + 1 ñ = ñ = X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 10 / 36

A conventional IR: RTL-CFG Single Static Assignment (SSA) SSA is a variant of RTL where every variable is the result of only one instruction. For straight-line codes: just rename variables to avoid accidental reuse. Not SSA y = x * 4 y = y + 1 if (y > 0) SSA y = x * 4 y = y + 1 if (y > 0) X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 11 / 36 Phi nodes A conventional IR: RTL-CFG For join points and loops in the control-flow graph: introduce φ instructions to merge multiple definitions of a variable. Not SSA x =... x =... SSA x1 =... x2 =... x3 = φ(x1,x2) use x use x3 Informal semantics: x = φ(x 1,..., x n ) assigns x = x i when entered from the i-th predecessor node. X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 12 / 36

A conventional IR: RTL-CFG Why SSA? SSA simplifies dataflow analysis: a given variable has the same abstract value at every point where the variable is defined. n1 = 1 n2 = 2 n3 = φ(n1,n2) n4 = φ(n2,n5) n5 = n4 + 1 We have n1 = 1 and n2 = 2 and n3 = n4 = n5 = everywhere. X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 13 / 36 Outline CPS as a functional IR 1 A conventional IR: RTL-CFG 2 CPS as a functional IR 3 Another functional IR: A-normal forms X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 14 / 36

CPS as a functional IR CPS as a functional IR CPS terms share many features of intermediate representations. In particular, expressions are decomposed in individual operations and intermediate results are named. Example: source term let x = (y + z) (a b) in.... CPS RTL (y + z) (λt. t = y + z; (a - b) (λu. u = a - b; (t * u) (λx. x = t * u;...)))... (We write for reverse function application: a b = b a.) X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 15 / 36 CPS as a functional IR CPS as a functional IR Likewise, let-bound continuations correspond to join points in a control-flow graph. Applying such a continuation corresponds to a φ node in SSA form. Example: source term let x = (if c then y + 1 else z + 2) in... let k = λx... in if c then k(y+1) else k(z+2) x1 = y+1 x2 = z+2 x = φ(x1,x2) X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 16 / 36

CPS as a functional IR Optimizations on CPS terms When expressed over CPS terms, many classic optimizations boil down to β-reduction, or arithmetic reductions, or variants thereof. Example: constant propagation β and arithmetic reduction. 1 (λx.... x + 1... x + y...)... 2... 1 + y... Example: common subexpression elimination inverse β (a + b) (λx. (a + b) (λx.... --->... (a + b) (λy. x (λy....... X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 17 / 36 Back to direct style CPS as a functional IR To support stack-allocation of activation records, several functional compilers perform an inverse CPS transformation after CPS optimization, to recover direct-style (DS) function calls. DS Source CPS transf. inverse CPS transf. CPS administrative reductions optimizing reductions X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 18 / 36

CPS as a functional IR The inverse CPS transformation (Sabry and Felleisen, LFP 1992) Grammar of CPS terms after administrative normalization: Terms: Values: P ::= k W let x = W in P W 1 W 2 k W 1 W 2 (λk.p) W ::= N x λx.λk.p Inverse CPS transformation: U(k W ) = W U(let x = W in P) = let x = W in U(P) U(W 1 W 2 k) = W 1 W 2 (tail application) U(W 1 W 2 (λx.p)) = let x = W 1 W 2 in P (non-tail application) with N = N and x = x and λx.λk.p = λx.u(p) X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 19 / 36 The origin of ANF CPS as a functional IR (Flanagan, Sabry, Felleisen, The essence of compiling with continuations, PLDI 1993.) In 1993, Flanagan, Sabry and Felleisen showed that this detour through CPS can be avoided, and indeed is unnecessary in the following formal sense: DS Source ANF conversion ANF optimizing reductions CPS transf. inverse CPS transf. inverse CPS transf. CPS administrative reductions optimizing reductions ANF stands for administrative normal form, and is the direct-style sub-language that is the target of inv-cps-transf adm-red CPS-transf. X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 20 / 36

Another functional IR: A-normal forms Outline 1 A conventional IR: RTL-CFG 2 CPS as a functional IR 3 Another functional IR: A-normal forms X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 21 / 36 Syntax of ANF Another functional IR: A-normal forms Atom: a ::= x N λ x.b Computation: c ::= a 1 op a 2 arithmetic a( a) function application C( a) datatype constructor closure(a, a) closure constructor Body: b ::= c tail computation let x = c in b sequencing if a then b 1 else b 2 conditional match a with... p i b i... pattern-matching X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 22 / 36

Another functional IR: A-normal forms ANF as a CFG let x = a + b in if (x >= a) then x else 0 x = a + b if (x >= a) return x return 0 X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 23 / 36 Conversion to ANF Another functional IR: A-normal forms Step 1: perform monadic conversion. Example 1 Source term: 1 + (if x >= 0 then f (x) else 0) Monadic conversion: bind (if x >= 0 then f(x) else ret 0) (λt. 1 + t) X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 24 / 36

Another functional IR: A-normal forms Conversion to ANF Step 2: interpret the result in the Identity monad: ret a a bind a (λx.b) let x = a in b Example 2 Source term: 1 + (if x >= 0 then f (x) else 0) Monadic conversion + identity monad: let t = if x >= 0 then f(x) else ret 0 in 1 + t Result is in so-called Monadic Intermediate Form, but not yet in ANF. X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 25 / 36 Another functional IR: A-normal forms Conversion to ANF Step 3: flatten the nesting of let, if and match. let x = (let y = a in b) in c let y = a in let x = b in c (if y not free in c) let x = (if a then b else c) in d if a then (let x = b in d) else (let x = c in d) let x = (match a with... p i b i...) in c match a with... p i let x = b i in c... match (match a with... p i b i...) with... q j c j... match a with... p i (match b i with... q j c j...)... Example 3 if x >= 0 then let t = f(x) in 1 + t else let t = 0 in 1 + t X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 26 / 36

Another functional IR: A-normal forms Tail duplication, and how to avoid it Note that possibly large terms can be duplicated: if (if a then b else c) then d else e if a then (if b then d else e) else (if c then d else e) This can be avoided by using auxiliary functions: ( SSA φ nodes) if (if a then b else c) then d else e let f (x) = if x then d else e in if a then f (b) else f (c) a a b c b c d e d e d e X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 27 / 36 Another functional IR: A-normal forms Optimizations on ANF terms As in the case of CPS, classic optimizations boil down to β-reduction or arithmetic reductions over ANF terms. Example: constant propagation β and arithmetic reduction. let x = 1 in... x + 1... x + y...... 2... 1 + y... Example: common subexpression elimination inverse β let x = a + b in let x = a + b in... -->... let y = a + b in let y = x in...... X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 28 / 36

Another functional IR: A-normal forms Register allocation The register allocation problem: place every variable in hardware registers or stack locations, maximizing the use of hardware registers. Naive approach: Assign the N hardware registers to the N most used variables; assign stack slots to the other variables. Finer approach: Notice that the same hardware register can be assigned to several distinct variables, provided they are never used simultaneously. Example 4 if... then (let x =... in...) else (let y =... in...) x and y can share a register. X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 29 / 36 Another functional IR: A-normal forms Register allocation on ANF On functional intermediate representations like ANF, register allocation boils down to α-conversion. The register allocation problem, revisited: rename variables, using hardware registers or stack locations as new names, in such a way that (Correctness) the renamed term is α-equivalent to the original; (Efficiency) hardware registers are used as much as possible. Example 5 if... then (let x =... in...) else (let y =... in...) can be α-converted to if... then (let R1 =... in...) else (let R1 =... in...) X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 30 / 36

Another functional IR: A-normal forms The interference graph An undirected graph, Nodes: names of variables Edges: between any two variables that cannot be renamed to the same location, as this would violate α-equivalence. Constructing the interference graph: at each point where a variable x is bound, add edges with all other variables that occur free in the continuation of this binding. let x = c in b add edges between x and all y FV (b) \ {x} match a with... C(x 1,..., x n ) b... add edges between x i and all y FV (b) \ {x i }. X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 31 / 36 Another functional IR: A-normal forms Example of an interference graph let s = 0.0 in let i = 0 in let rec f(s,i) = if (ri < size) then let a = i*4 in let b = load(tbl+a) in let c = float(b) in let s = s +f c in let i = i + 1 in f(s,i) else let d = float(size) in s /f d in f(s,i) a s b i c size tbl d X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 32 / 36

Another functional IR: A-normal forms Register allocation by graph coloring Correct register allocations correspond to colorings of the interference graph: each node should be assigned a color (= a register or stack location) so that adjacent nodes have different colors. If the interference graph can be colored with at most N colors (where N is the number of hardware register), we obtain a perfect register allocation. Otherwise, the coloring is a good starting point to determine which variables go into registers. (A. Appel, Modern compiler implementation in ML, Cambridge University Press, chapter 11.) X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 33 / 36 Another functional IR: A-normal forms Register allocation by graph coloring Any undirected graph is the interference graph of a CFG perfect register allocation on RTL-CFG is NP-complete. The interference graphs for SSA graphs and ANF terms are chordal perfect register allocation in polynomial time. (F. Pereira and J. Palsberg, Register allocation via coloring of chordal graphs, APLAS 2005.) X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 34 / 36

Another functional IR: A-normal forms Register allocation by graph coloring Why perfect and not just perfect? Two auxiliary problems remain hard (as in NP-hard) even on chordal graphs: 1 Spilling: when not enough registers, choose which variables to spill to stack slots, and insert appropriate stack-reg moves around uses of these variables. 2 Coalescing: try to give the same color to two variables when doing so suppresses a move instruction, e.g. let f x =... in... f y... f z... (Optimal: assign the same register to x, y and z.) X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 35 / 36 Another functional IR: A-normal forms Some uses of functional intermediate representations Production-quality compilers: Gambit (for Scheme, using CPS) Standard ML of New Jersey (for SML, using CPS) MLton (for SML, using CPS) MLj and SML.net (for SML, using Monadic Intermediate Form) Simple formally-verified compilers for mini-ml: by A. Chlipala (using CPS) by Z. Dargaye (using Monadic Intermediate Form) Functional intermediate representations as path of least resistance towards formally-verified functional compilers? X. Leroy (INRIA) Functional programming languages MPRI 2-4, 2015 2017 36 / 36