590 likes | 604 Views
This article discusses the various techniques and algorithms used in reference analysis for compiler optimization, including flow-sensitivity, context-sensitivity, and Andersen's and Steensgaard's analysis. Examples and explanations are provided to illustrate these concepts.
E N D
CMPUT680 - Winter 2006 Topic P: Reference Analysis José Nelson Amaral http://www.cs.ualberta.ca/~amaral/courses/680 CMPUT 680 - Compiler Design and Optimization
References • Ryder, Barbara G., “Dimensions of Precision in Reference Analysis of Object-Oriented Programming Languages,” Compiler Construction, pp. 126-137, Warsaw, Poland, April, 2003. • Shapiro, Marc and Horwitz, Susan, “Fast and Accurate Flow-Insensitive Points-To Analysis,” Symposium on Principles of Programming Languages, pp. 1-14, Paris, France, 1997. • Emami, Maryam, Ghiya, Rakesh, and Hendren, Laurie J., “Context-Sensitive Interprocedural Points-to Analysis in the Presence of Function Pointers,” Programming Language Design & Implementation, pp. 242-256, Orlando, FL, 1994. • Steensgaard, Bjarne, “Points-to Analysis in Almost Linear Time,” Symposium on Principles of Programming Languages, pp. 32-41, 1996. • Landi, William, and Ryder, Barbara G., “A Safe Approximate Algorithm for Interprocedural Pointer Aliasing, Programming Language Design & Implementation, pp. 235-248, 1992. CMPUT 680 - Compiler Design and Optimization
Motivation … [1] x=0; [2] *p = 1; [3] write(x); … Example of Optimization Problems: Draw a Data Dependence Graph for statements 1-3; Does definition [1] reaches statement [3]? Can the constant 0 be propagated to statement [3]? CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
Motivation … [1] x=0; [2] *p = 1; [3] write(x); … • There are three situations to consider: • pmust point to xx=1 in [3]. • pmust not point to xx=0 in [3]. • pmay point to x the compiler does not know the value of x in [3]. CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
Flow-sensitivity • Flow-sensitive analysis: takes into account the order in which statements are executed; • Flow-insensitive analysis: assumes that statements can be executed in any order; CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
Context-sensitivity • Context-sensitive analysis: takes into account the fact that a function must return to the site of the most recent call; • Context-insensitive analysis:propagates information from a call site, through the called function, and back to all call sites. • A context-insensitive analysis constructs a single approximation to a procedure’s effect on all of its callers (Ruf, PLDI95). CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
Andersen’s X Steensgaard’s Analysis • Both analysis are flow-insensitive and context-insensitive. • Both build an alias graph (Burke, Carini, Choi, Hind, LCPC94) or a storage shape graph (Chase, Wegman, Zadeck, PLDI90). • Andersen: each node can have an arbitrary number of out-edges each node represents one variable. • Steensgaard: each node has at most one out-edge each node may represent more than one variable. CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
a Andersen’s X Steensgaard’s (Example) Program: Steensgaard: a = &b; S = {(a,b)} b Andersen: S = {(a,b)} b a CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
a Andersen’s X Steensgaard’s (Example) Program: Steensgaard: a = &b; b = &c; S = {(a,b); (b,c)} b c Andersen: S = {(a,b); (b,c)} b c a CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
a Andersen’s X Steensgaard’s (Example) Program: Steensgaard: a = &b; b = &c; a = &d; S = {(a,b); (b,c)} b c Andersen: What should happen in each analysis? S = {(a,b); (b,c)} b c a CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
a Andersen’s X Steensgaard’s (Example) Program: Steensgaard: a = &b; b = &c; a = &d; S = {(a,b); (b,c); (a,d); (d,c)} (b,d) c Andersen: S = {(a,b); (b,c); (a,d)} b c a d CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
a Andersen’s X Steensgaard’s (Example) Program: Steensgaard: a = &b; b = &c; a = &d; d = &e; S = {(a,b); (b,c); (a,d); (d,c)} (b,d) c Andersen: And now? S = {(a,b); (b,c); (a,d)} b c a d CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
a Andersen’s X Steensgaard’s (Example) Program: Steensgaard: a = &b; b = &c; a = &d; d = &e; S = {(a,b); (b,c); (a,d); (d,c); (d,e); (b,e)} (b,d) (c,e) Andersen: S = {(a,b); (b,c); (a,d); (d,e)} b c a e d CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
Steensgaard’s Algorithm • Based on non-standard type-system. The “type” of a variable describes a set of locations possibly pointed-to by the variable. • At initialization, each variable is described by a different type. • Fast union-find structures are used to provide constant-time access to the type associated with a variable name. • Process each statement exactly once, joining type variables as necessary to ensure that the program is well-typed. CMPUT 680 - Compiler Design and Optimization (Steensgaard, PPL96)
Comparison of Steensgaard and Andersen • For small programs (up to 3,000 lines) both analyses are very fast. • For some large programs, Andersen’s may take a very long time (from more than 10 to more than 100 times as long as Steensgaard’s). • For 37 out of 61 programs (21 out of 25 “large” programs), Andersen’s points-to-set is less than half the size of Steengaard’s (thus Andersen’s is more precise). CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
Shapiro/Horwitz Algorithm 1 • Allows each node in the alias graph to have out-degree k (k is an input to the algorithm). • Each variable is assigned to one of k categories. Only merge nodes of variables in the same category. • Partition of variables into categories is an input for the algorithm: • All variables in one category Steensgaard • Each variable in a separate category Andersen CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
b b (b,c,d) (b,d) d c c (c,d) a a a a Shapiro/Horwitz Algorithm 1 (Example) Categories: {a, b, c, d} Program: S = {(a, b); (a,c); (a,d); (b,b); (b,c); (b,d); (c,b); (c,c); (c,d); (d,b); (d,c), (d,d)} a = &b; a = &c; a = &d c = &d Categories: {a, b} {c, d} S = {(a, b); (a,c); (a,d); (c,c); (c,d); (d,c), (d,d)} Categories: {a, c}, {b, d} S = {(a, b); (a,c); (a,d); (c,b); (c,d)} Categories: {a, b}, {c}, {d} S = {(a, b); (a,c); (a,d); (c,d)} (Shapiro/Horwitz, PPL97)
Shapiro/Horwitz Algorithm 2 • Insight: Run algorithm 1 multiple times with k categories and a different category partition each time: • True points-to relationships are found by taking the intersection of the points-to sets computed by each run. • Goal: Select a set of runs such that for every pair of variables (x, y), there is at least one run in which x and y are in different categories. CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
Shapiro/Horwitz Algorithm 2 • Solution: R = logk N runs, where N is the number of variables. • Assign each variable a unique number, in base k, in the range 0 to N-1 using R digits. • Use this encoding to select the variables categories. CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
Categories for run 1: {a,c}, {b,d} Categories for run 2: {a,b}, {c,d} Run 1: S1 = {(a, b); (a,c); (a,d); (c,b); (c,d)} Run 2: S2 = {(a, b); (a,c); (a,d); (c,c); (c,d); (d,c), (d,d)} Shapiro/Horwitz Algorithm 2 (Example) Program: The program has four variables, for k=2: a = &b; a = &c; a = &d c = &d a 00 b 01 c 10 d 11 S1 S2 = {(a, b); (a,c); (a,d); (c,d)} CMPUT 680 - Compiler Design and Optimization (Shapiro/Horwitz, PPL97)
If pdefinitely points to y at this point. Then all previous point-to relations from y are now killed. w w y p y p x z z Before the statement After the statement May X (Possible or Definite) Points-to Relations • Possible and definite points-to information can be important: p = x CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
May X (Possible or Definite) Points-to Relations • Possible and definite points-to information can be important: If qdefinitely points to y at this point. x = q Then the statement can be replaced by x=y. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Stack-based and Heap-based aliasing • Three varieties of aliases: • Aliases between variable references to the stack; • Aliases between references to the heap; • Aliases between two references to the same array. • Analysis of stack-based aliases and heap-based aliases should be decoupled. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Stack-based and Heap-based aliasing • Stack-base analysis: • A name exist for each location of interest; • Compute an approximation of the relationship between these locations; • Heap-base analysis: • There are no natural names for locations; • We don’t know how many locations will exist; • Solution: consider the entire heap a single location in the stack analysis. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
The Reference Analysis Problem Statement • The reference analysis problem is a generalization of alias analysis: • Given two references p and q, is it possible that p and q may: • point to the same memory location? • refer to the same object? • dispatch to the same method? CMPUT 680 - Compiler Design and Optimization
Alias Pairs • Sets of alias pairs (Landi & Ryder PLDI93): two variable references may be aliased if they may refer to the same memory location. q After statement p=q, the following alias pairs are created: p, q, p->next, q->next, p->next->next, q->next->next, … CMPUT 680 - Compiler Design and Optimization
Points-to Abstraction • Create an abstract representation of the stack: • Each real stack location that is involved in a points-to relationship is represented by exactly one named abstract location; • Each named abstract location represents one or more real stack locations. Real Locations Abstract Locations loci x locj y lock CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Abstract Stack Location • An abstract stack location corresponds to one of this: • The name of a local variable, global variable, or parameter. • A symbolic name that represents a location not in the scope of the procedure under analysis. • The symbolic name heap. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Definitely Points-to • An abstract location xdefinitely points to abstract location y, noted (x, y, D), for a given invocation context, if: • x and y each represent exactly one real location in that context; and • the real location corresponding to x contains the address of the real location y. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Possibly Points-to • An abstract location xpossibly points to abstract location y, noted (x, y, P), for a given invocation context, if: • It is possible that one of the real locations corresponding to x contains the address of one of the real locations represented by y. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Real Locations Abstract Locations loci x locj y Safe Approximation • Let S be the points-to set at point p. • Consider all pairs of real locations loci and locj. Let x be the abstract location of loci and y be the abstract location of locj. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Safe Approximation • S is a safe approximation at p if: • S contains (x,y,D) or (x,y,P) when locipoints to locj on all valid execution paths to p. • S contains (x,y,P) when loci points to locj in some, but not all, execution paths to p. • If S contains (x,y,D) then locimust point to locj in all paths to p. Real Locations Abstract Locations loci x ? locj y CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Safety and Precision • An approximation is unsafe if: • A real points-to relationship is not in S; • A spurious definite points-to relation is in S; • The following approximation is safe, just not very precise: • Every abstract location possibly points-to every other abstract location. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
L-locations and R-locations • Problem: Given the input points-to set Sin of an statement S, generate its output points-to set Sout. • Solution: • Compute an abstract representation of the locations represented in the left-hand side (L-locations) and in the right-hand side (R-locations) of S. • Notation: • (x,D): abstract location x is definitely in the set • (x,P): abstract location x is possibly in the set CMPUT 680 - Compiler Design and Optimization
w v y q z Sinput = {(q,y,D); (y,w,P); (y,z,P); (w,v,D)} Before the statement q = w Soutput = ? L-locations and R-locations (example) L-locations(*q) = {(x,d) | (q,x,d) S} L-locations(*q) = ? R-locations(w) = {(x,d) | (w,x,d) S} R-locations(w) = ? CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
w v y q z Sinput = {(q,y,D); (y,w,P); (y,z,P); (w,v,D)} Before the statement q = w Soutput = ? Skill = {(p,x,d) | (p,D) L-locations(*q) (p,x,d) Sinput} = ? The clause in green above is not in the original paper, but it is necessary. L-locations and R-locations (example) L-locations(*q) = {(x,d) | (q,x,d) S} L-locations(*q) = {(y,D)} R-locations(w) = {(x,d) | (w,x,d) S} R-locations(w) = {(v,D)} Schange = {(p,x,D) | (p,P) L-locations(*q) (p,x,D) Sinput} = ? Sgen = {(p,x,d1 d2) | (p,d1) L-locations(*q) (x,d2) R-locations(w)} = ? CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
w v y q z Sinput = {(q,y,D); (y,w,P); (y,z,P); (w,v,D)} Before the statement q = w Soutput = ? L-locations and R-locations (example) L-locations(*q) = {(x,d) | (q,x,d) S} L-locations(*q) = {(y,D)} R-locations(w) = {(x,d) | (w,x,d) S} R-locations(w) = {(v,D)} Skill = {(p,x,d) | (p,D) L-locations(*q) (p,x,d) Sinput} = {(y,w,P),(y,z,P)} Schange = {(p,x,D) | (p,P) L-locations(*q) (p,x,D) Sinput} = { } Sgen = {(p,x,d1 d2) | (p,d1) L-locations(*q) (x,d2) R-locations(w)} = {(y,v,D)} CMPUT 680 - Compiler Design and Optimization The clause in green above is not in the original paper, but it is necessary. (Emami, Ghiya, Hendren, PLDI 94)
w v y q z Sinput = {(q,y,D); (y,w,P); (y,z,P); (w,v,D)} Before the statement q = w Soutput = ? L-locations and R-locations (example) L-locations(*q) = {(y,D)} R-locations(w) = {(v,D)} Skill = {(y,w,P),(y,z,P)} Schange = { } Sgen = {(y,v,D)} Sinputchanged = (Sinput - Schange) {(p,x,D) Schange} = CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
w v y q z Sinput = {(q,y,D); (y,w,P); (y,z,P); (w,v,D)} Before the statement q = w Soutput = ? L-locations and R-locations (example) L-locations(*q) = {(y,D)} R-locations(w) = {(v,D)} Skill = {(y,w,P),(y,z,P)} Schange = { } Sgen = {(y,v,D)} Sinputchanged = (Sinput - Schange) {(p,x,D) Schange} = Sinput CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
w v y q z Sinput = {(q,y,D); (y,w,P); (y,z,P); (w,v,D)} Before the statement q = w Soutput = ? L-locations and R-locations (example) L-locations(*q) = {(y,D)} R-locations(w) = {(v,D)} Skill = {(y,w,P),(y,z,P)} Schange = { } Sgen = {(y,v,D)} Sinputchanged = (Sinput - Schange) {(p,x,D) Schange} = Sinput Soutput = (Sinputchanged - Skill) Sgen = ? CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
w v y q z Sinput = {(q,y,D); (y,w,P); (y,z,P); (w,v,D)} Before the statement q = w Soutput = {(q,y,D); (w,v,D); (y,v,D)} L-locations and R-locations (example) L-locations(*q) = {(y,D)} R-locations(w) = {(v,D)} w v Skill = {(y,w,P),(y,z,P)} y q Schange = { } z Sgen = {(y,v,D)} Sinputchanged = Sinput After the statement Soutput = (Sinputchanged - Skill) Sgen = ? CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Invocation Graph • Programs without recursion: Invocation graph built with a depth-first traversal of the call structure, starting with main. • Programs with recursion: Invocation structure not known at compile time. Invocation graph approximates all unrollings of recursions. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
main g g main f f f-R g f-A f-A Invocation Graph (examples) main() { … f(); } f() { g(); if (y) f(); } g() { if (e) f(); } main() { … g(); g(); } g() { … f(); … } f-A: An approximate node where a stored approximation for the function should be used (instead of an evaluation of the function call). f-R: A recursive node where a fixed-point computation must be performed. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Advantages of using an Invocation Graph • Separates inter-procedural analysis from calling contexts. • Creates places to deposit context-sensitive information for subsequent analysis. • Creates places to store IN/OUT pairs summarizing the effects of a function call. • Allows simple compositional fixed-point computations for recursions. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Callee Caller Map Process f() { … g(a); } g(x) { … } Function Analysis Unmap Process Inter-procedural Context-sensitivy analysis Special care in the Map process: • Formal parameters and global variables that are multi-level pointers. • Invisible variables: formals and globals that point to variables outside of the scope of the callee. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Callee Caller Map Process f() { … g(a); } g(x) { … } Function Analysis Unmap Process Inter-procedural Context-sensitivy analysis Solutions to the Map process: • Multi-level pointers: apply the mapping process recursively to all levels of pointer type. • Invisible variables: generate special symbolic names to represent each level of indirection of pointer variables (see paper for details). CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Approximate and Recursive Nodes • A recursive node f-R stores an input, an output, and a list of pending inputs. • The input and output pairs approximate the effect of the call to f. • The fixed-point computation generalizes the stored input and output until it summarizes all invocations of f. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Function Pointer • When a function is called through a function pointer a set of functions may be called. • Some safe approximations for this set are: • All the functions in the program. • All functions which have had their addresses taken. • The set of functions that the pointer can point to at the program point where the call is. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
A cyclic dependence • To obtain the points-to set for the function pointer, we need to perform points-to analysis. • But points-to analysis needs the invocation graph of the program because it is context sensitive and inter-procedural. • The solution is to construct the invocation graph while performing points-to analysis. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)
Handling Function Pointers • Build the invocation graph, leaving it incomplete where a function pointer call is encountered. • Perform points-to analysis using the incomplete invocation graph. • When an indirect call through a function pointer is encountered, find the set P of all functions it can point to according to current information. • Update the invocation graph to indicate that the indirect call may call any function in P. • Analyze each function fP in the context of the call --- while analyzing f assume that the function pointer definitely points to f. • Merge the output points-to sets of all functions in P. CMPUT 680 - Compiler Design and Optimization (Emami, Ghiya, Hendren, PLDI 94)