Abstract Interpretation Continued

Slides:



Advertisements
Similar presentations
Continuing Abstract Interpretation We have seen: 1.How to compile abstract syntax trees into control-flow graphs 2.Lattices, as structures that describe.
Advertisements

Chapter 16 Java Virtual Machine. To compile a java program in Simple.java, enter javac Simple.java javac outputs Simple.class, a file that contains bytecode.
Register Usage Keep as many values in registers as possible Register assignment Register allocation Popular techniques – Local vs. global – Graph coloring.
P3 / 2004 Register Allocation. Kostis Sagonas 2 Spring 2004 Outline What is register allocation Webs Interference Graphs Graph coloring Spilling Live-Range.
Register allocation Morgensen, Torben. "Register Allocation." Basics of Compiler Design. pp from (
Idea of Register Allocation x = m[0]; y = m[1]; xy = x*y; z = m[2]; yz = y*z; xz = x*z; r = xy + yz; m[3] = r + xz x y z xy yz xz r {} {x} {x,y} {y,x,xy}
Coalescing Register Allocation CS153: Compilers Greg Morrisett.
Register Allocation Mooly Sagiv Schrierber Wed 10:00-12:00 html://
COMPILERS Register Allocation hussein suleman uct csc305w 2004.
Data-Flow Analysis Framework Domain – What kind of solution is the analysis looking for? Ex. Variables have not yet been defined – Algorithm assigns a.
Stanford University CS243 Winter 2006 Wei Li 1 Register Allocation.
Register Allocation CS 671 March 27, CS 671 – Spring Register Allocation - Motivation Consider adding two numbers together: Advantages: Fewer.
Program Representations. Representing programs Goals.
CPSC 388 – Compiler Design and Construction
Chapter 8 Runtime Support. How program structures are implemented in a computer memory? The evolution of programming language design has led to the creation.
CS 153 Design of Operating Systems Spring 2015
Common Sub-expression Elim Want to compute when an expression is available in a var Domain:
1 CS 201 Compiler Construction Lecture 12 Global Register Allocation.
Prof. Bodik CS 164 Lecture 171 Register Allocation Lecture 19.
Run time vs. Compile time
Register Allocation (via graph coloring)
Data Flow Analysis Compiler Design October 5, 2004 These slides live on the Web. I obtained them from Jeff Foster and he said that he obtained.
U NIVERSITY OF M ASSACHUSETTS, A MHERST Department of Computer Science Emery Berger University of Massachusetts, Amherst Advanced Compilers CMPSCI 710.
Register Allocation (via graph coloring). Lecture Outline Memory Hierarchy Management Register Allocation –Register interference graph –Graph coloring.
1 Liveness analysis and Register Allocation Cheng-Chia Chen.
Recap from last time: live variables x := 5 y := x + 2 x := x + 1 y := x y...
Direction of analysis Although constraints are not directional, flow functions are All flow functions we have seen so far are in the forward direction.
4/29/09Prof. Hilfinger CS164 Lecture 381 Register Allocation Lecture 28 (from notes by G. Necula and R. Bodik)
Precision Going back to constant prop, in what cases would we lose precision?
Abstract Interpretation (Cousot, Cousot 1977) also known as Data-Flow Analysis.
Compiler Construction Lecture 17 Mapping Variables to Memory.
Compiler Construction Lecture 16 Data-Flow Analysis.
IT253: Computer Organization Lecture 4: Instruction Set Architecture Tonga Institute of Higher Education.
U NIVERSITY OF D ELAWARE C OMPUTER & I NFORMATION S CIENCES D EPARTMENT Optimizing Compilers CISC 673 Spring 2009 Register Allocation John Cavazos University.
More Examples of Abstract Interpretation Register Allocation.
2/22/2016© Hal Perkins & UW CSEP-1 CSE P 501 – Compilers Register Allocation Hal Perkins Winter 2008.
LECTURE 13 Names, Scopes, and Bindings: Memory Management Schemes.
1 Liveness analysis and Register Allocation Cheng-Chia Chen.
Memory Management Chapter 5 Advanced Operating System.
Single Static Assignment Intermediate Representation (or SSA IR) Many examples and pictures taken from Wikipedia.
More Code Generation and Optimization Pat Morin COMP 3002.
Global Register Allocation Based on
Virtualization Virtualize hardware resources through abstraction CPU
Segmentation COMP 755.
Names and Attributes Names are a key programming language feature
Mooly Sagiv html://
CSE 120 Principles of Operating
The compilation process
Run-time organization
Register Allocation Noam Rinetzky Text book:
Chapter 8: Main Memory.
Optimizing Malloc and Free
Virtual Memory Hardware
CSE 451: Operating Systems Autumn 2005 Memory Management
Data Flow Analysis Compiler Design
Memory management Explain how memory is managed in a typical modern computer system (virtual memory, paging and segmentation should be described.
UNIT V Run Time Environments.
Lecture 16: Register Allocation
Static Single Assignment
CSE 451: Operating Systems Autumn 2003 Lecture 9 Memory Management
CSE 451: Operating Systems Autumn 2003 Lecture 9 Memory Management
Lecture 7: Flexible Address Translation
Compiler Construction
Lecture 17: Register Allocation via Graph Colouring
Fall Compiler Principles Lecture 13: Summary
COMP755 Advanced Operating Systems
(via graph coloring and spilling)
Abstract Interpretation: Analysis Domain (D) Lattices
CS 201 Compiler Construction
Presentation transcript:

Abstract Interpretation Continued

Height of Lattice: Length of Max. Chain size=14 ∞ T T height=2 size =∞ … -2 -1 1 2 … 

Chain of Length n A set of elements x0,x1 ,..., xn in D that are linearly ordered, that is x0 < x1 < ... < xn A lattice can have many chains. Its height is the maximum n for all the chains If there is no upper bound on lengths of chains, we say lattice has infinite height Any monotonic sequence of distinct elements has length at most equal to lattice height including sequence occuring during analysis! such sequences are always monotonic

In constant propagation, each value can change only twice  1 -1 -2 2 height=2 size =∞ … consider value for x before assignment Initially:  changes 1st time to: 1 change 2nd time to: T total changes: two (height) x = 1 n = 1000 while (x < n) { x = x + 2 } Total number of changes bounded by: height∙|Nodes| ∙|Vars| var facts : Map[Nodes,Map[VarNames,Element]]

Exercise B32 – the set of all 32-bit integers What is the upper bound for number of changes in the entire analysis for: 3 variables, 7 program points for these two analyses: constant propagation for constants from B32 The following domain D: D = {} U { [a,b] | a,b B32 , a ≤ b}

Height of B32 D = {} U { [a,b] | a,b B32 , a ≤ b} One possible chain of maximal length:  … [MinInt,MaxInt]

Initialization Analysis first initialization uninitialized initialized

What does javac say to this: class Test { static void test(int p) { int n; p = p - 1; if (p > 0) { n = 100; } while (n != 0) { System.out.println(n); n = n - p; Test.java:8: variable n might not have been initialized while (n > 0) { ^ 1 error

Program that compiles in java class Test { static void test(int p) { int n; p = p - 1; if (p > 0) { n = 100; } else { n = -100; while (n != 0) { System.out.println(n); n = n - p; We would like variables to be initialized on all execution paths. Otherwise, the program execution could be undesirably affected by the value that was in the variable initially. We can enforce such check using initialization analysis.

What does javac say to this? static void test(int p) { int n; p = p - 1; if (p > 0) { n = 100; } System.out.println(“Hello!”); while (n != 0) { System.out.println(n); n = n - p;

Initialization Analysis class Test { static void test(int p) { int n; p = p - 1; if (p > 0) { n = 100; } else { n = -100; while (n != 0) { System.out.println(n); n = n - p; T indicates presence of flow from states where variable was not initialized: If variable is possibly uninitialized, we use T Otherwise (initialized, or unreachable):  If var occurs anywhere but left-hand side of assignment and has value T, report error

Sketch of Initialization Analysis Domain: for each variable, for each program point: D = {,T} At program entry, local variables: T ; parameters:  At other program points: each variable:  An assignment x = e sets variable x to  lub (join, ) of any value with T gives T uninitialized values are contagious along paths  value for x means there is definitely no possibility for accessing uninitialized value of x

Run initialization analysis Ex.1 int n; p = p - 1; if (p > 0) { n = 100; } while (n != 0) { n = n - p;

Run initialization analysis Ex.2 int n; p = p - 1; if (p > 0) { n = 100; } n = n - p;

Liveness Analysis Variable is dead if its current value will not be used in the future. If there are no uses before it is reassigned or the execution ends, then the variable is surely dead at a given point. first initialization last use live live dead dead dead

What is Written and What Read x = y + x if (x > y) Example: Purpose: Register allocation: find good way to decide which variable should go to which register at what point in time.

How Transfer Functions Look

Initialization: Forward Analysis while (there was change) pick edge (v1,statmt,v2) from CFG such that facts(v1) has changed facts(v2)=facts(v2) join transferFun(statmt, facts(v1)) } Liveness: Backward Analysis while (there was change) pick edge (v1,statmt,v2) from CFG such that facts(v2) has changed facts(v1)=facts(v1) join transferFun(statmt, facts(v2)) }

Example x = m[0] y = m[1] xy = x * y z = m[2] yz = y*z xz = x*z res1 = xy + yz m[3] = res1 + xz

Register Machines Better for most purposes than stack machines closer to modern CPUs (RISC architecture) closer to control-flow graphs simpler than stack machine (but register set is finite) Examples: ARM architecture RISC V: http://riscv.org/ Directly Addressable RAM large - GB, slow even with cache A few fast registers R0,R1,…,R31

Basic Instructions of Register Machines Ri  Mem[Rj] load Mem[Rj] Ri store Ri  Rj * Rk compute: for an operation * Efficient register machine code uses as few loads and stores as possible.

State Mapped to Register Machine Both dynamically allocated heap and stack expand heap need not be contiguous; can request more memory from the OS if needed stack grows downwards Heap is more general: Can allocate, read/write, and deallocate, in any order Garbage Collector does deallocation automatically Must be able to find free space among used one, group free blocks into larger ones (compaction),… Stack is more efficient: allocation is simple: increment, decrement top of stack pointer (SP) is often a register if stack grows towards smaller addresses: to allocate N bytes on stack (push): SP := SP - N to deallocate N bytes on stack (pop): SP := SP + N 1 GB Stack SP free memory 10MB Heap Constants 50kb Static Globals Exact picture may depend on hardware and OS

Stack Machine vs General Register Machine Code Naïve Correct Translation JVM: Register Machine: i32.mul R1  Mem[SP] SP = SP + 4 R2  Mem[SP] R2  R1 * R2 Mem[SP]  R2

Register Allocation

How many variables? x,y,z,xy,xz,res1 Do we need 6 distinct registers if we wish to avoid load and stores? x = m[0] y = m[1] xy = x * y z = m[2] yz = y*z xz = x*z res1 = xy + yz m[3] = res1 + xz 7 variables: x,y,z,xy,yz,xz,res1 x = m[0] y = m[1] xy = x * y z = m[2] yz = y*z y = x*z // reuse y x = xy + yz // reuse x m[3] = x + y can do it with 5 only!

Idea of Register Allocation program: x = m[0]; y = m[1]; xy = x*y; z = m[2]; yz = y*z; xz = x*z; r = xy + yz; m[3] = r + xz live variable analysis result: {} {x} {x,y} {y,x,xy} {y,z,x,xy} {x,z,xy,yz} {xy,yz,xz} {r,xz} {} x y z xy yz xz r

Color Variables Avoid Overlap of Same Colors program: x = m[0]; y = m[1]; xy = x*y; z = m[2]; yz = y*z; xz = x*z; r = xy + yz; m[3] = r + xz live variable analysis result: {} {x} {x,y} {y,x,xy} {y,z,x,xy} {x,z,xy,yz} {xy,yz,xz} {r,xz} {} x y z xy yz xz r R1 R2 R3 R4 Each color denotes a register 4 registers are enough for this program

Color Variables Avoid Overlap of Same Colors program: x = m[0]; y = m[1]; xy = x*y; z = m[2]; yz = y*z; xz = x*z; r = xy + yz; m[3] = r + xz live variable analysis result: {} {x} {x,y} {y,x,xy} {y,z,x,xy} {x,z,xy,yz} {xy,yz,xz} {r,xz} {} x y z xy yz xz r R1 R2 R3 R4 x y yz z xz xy r Each color denotes a register 4 registers are enough for this 7-variable program

How to assign colors to variables? program: x = m[0]; y = m[1]; xy = x*y; z = m[2]; yz = y*z; xz = x*z; r = xy + yz; m[3] = r + xz live variable analysis result: {} {x} {x,y} {y,x,xy} {y,z,x,xy} {x,z,xy,yz} {xy,yz,xz} {r,xz} {} x y z xy yz xz r For each pair of variables determine if their lifetime overlaps = there is a point at which they are both alive. Construct interference graph y yz x z xz xy r

Edges between members of each set program: x = m[0]; y = m[1]; xy = x*y; z = m[2]; yz = y*z; xz = x*z; r = xy + yz; m[3] = r + xz live variable analysis result: {} {x} {x,y} {y,x,xy} {y,z,x,xy} {x,z,xy,yz} {xy,yz,xz} {r,xz} {} x y z xy yz xz r For each pair of variables determine if their lifetime overlaps = there is a point at which they are both alive. Construct interference graph y yz x z xz xy r

Final interference graph program: x = m[0]; y = m[1]; xy = x*y; z = m[2]; yz = y*z; xz = x*z; r = xy + yz; m[3] = r + xz live variable analysis result: {} {x} {x,y} {y,x,xy} {y,z,x,xy} {x,z,xy,yz} {xy,yz,xz} {r,xz} {} x y z xy yz xz r For each pair of variables determine if their lifetime overlaps = there is a point at which they are both alive. Construct interference graph y yz x z xz xy r

Coloring interference graph program: x = m[0]; y = m[1]; xy = x*y; z = m[2]; yz = y*z; xz = x*z; r = xy + yz; m[3] = r + xz live variable analysis result: {} {x} {x,y} {y,x,xy} {y,z,x,xy} {x,z,xy,yz} {xy,yz,xz} {r,xz} {} x y z xy yz xz r Need to assign colors (register numbers) to nodes such that: if there is an edge between nodes, then those nodes have different colors.  standard graph vertex coloring problem y:2 yz:2 x:1 z:3 xz:3 xy:4 r:4

Idea of Graph Coloring Register Interference Graph (RIG): indicates whether there exists a point of time where both variables are live look at the sets of live variables at all progrma points after running live-variable analysis if two variables occur together, draw an edge we aim to assign different registers to such these variables finding assignment of variables to K registers: corresponds to coloring graph using K colors

All we need to do is solve graph coloring problem y yz x z xz xy r NP hard In practice, we have heuristics that work for typical graphs If we cannot fit it all variables into registers, perform a spill: store variable into memory and load later when needed

Heuristic for Coloring with K Colors Simplify: If there is a node with less than K neighbors, we will always be able to color it! So we can remove such node from the graph (if it exists, otherwise remove other node) This reduces graph size. It is useful, even though incomplete (e.g. planar can be colored by at most 4 colors, yet can have nodes with many neighbors) y yz x z xz xy r y yz x z xy y yz x z xz xy y x z xy y z xy y z z

Heuristic for Coloring with K Colors Select Assign colors backwards, adding nodes that were removed If the node was removed because it had <K neighbors, we will always find a color if there are multiple possibilities, we can choose any color y:2 yz:2 x:1 z:3 xz:3 xy:4 r:4 y:2 yz:2 x:1 z:3 xz:3 xy:4 y:2 yz:2 x:1 z:3 xy:4 y:2 x:1 z:3 xy:4 y:2 z:3 xy:4 y:2 z:3 z:3

Use Computed Registers y:2 yz:2 x:1 z:3 xz:3 xy:4 r:4 x = m[0] y = m[1] xy = x * y z = m[2] yz = y*z xz = x*z r = xy + yz m[3] = res1 + xz R1 = m[0] R2 = m[1] R4 = R1*R2 R3 = m[2] R2 = R2*R3 R3 = R1*R3 R4 = R4 + R2 m[3] = R4 + R3

Summary of Heuristic for Coloring Simplify (forward, safe): If there is a node with less than K neighbors, we will always be able to color it! so we can remove it from the graph Potential Spill (forward, speculative): If every node has K or more neighbors, we still remove one of them we mark it as node for potential spilling. Then remove it and continue Select (backward): Assign colors backwards, adding nodes that were removed If we find a node that was spilled, we check if we are lucky, that we can color it. if yes, continue if not, insert instructions to save and load values from memory (actual spill). Restart with new graph (a graph is now easier to color as we killed a variable)

Conservative Coalescing Suppose variables tmp1 and tmp2 are both assigned to the same register R and the program has an instruction: tmp2 = tmp1 which moves the value of tmp1 into tmp2. This instruction then becomes R = R which can be simply omitted! How to force a register allocator to assign tmp1 and tmp2 to same register? merge the nodes for tmp1 and tmp2 in the interference graph! this is called coalescing But: if we coalesce non-interfering nodes when there are assignments, then our graph may become more difficult to color, and we may in fact need more registers! Conservative coalescing: coalesce only if merged node of tmp1 and tmp2 will have a small degree so that we are sure that we will be able to color it (e.g. resulting node has degree < K)

Run Register Allocation Ex.3 use 4 registers, coallesce j=i i = 0 s = s + i i = i + b j = i s = s + j + b j = j + 1

Run Register Allocation Ex.3 use 3 registers, coallesce j=i {s,b} i = 0 {s,i,b} s = s + i i = i + b j = i {s,j,b} s = s + j + b {j} j = j + 1 {} s i j b coalesce s:1 i,j:2 b:3 s i,j b color

Run Register Allocation Ex.3 use 4 registers, coallesce j=i i,j:2 b:3 i = 0 s = s + i i = i + b j = i // puf! s = s + j + b j = j + 1 R2 = 0 R1 = R1 + R2 R2 = R2 + R3 R1 = R1 + R2 + R3 R2 = R2 + 1