alias analysis
play

Alias Analysis Simone Campanoni simonec@eecs.northwestern.edu - PowerPoint PPT Presentation

Alias Analysis Simone Campanoni simonec@eecs.northwestern.edu Memory alias analysis: the problem Does j depend on i ? i: (*p) = varA + 1 i: obj1.f = varA + 1 j: varB = (*q) * 2 j: varB= obj2.f * 2 Do p and q point to the same memory


  1. Alias Analysis Simone Campanoni simonec@eecs.northwestern.edu

  2. Memory alias analysis: the problem • Does j depend on i ? i: (*p) = varA + 1 i: obj1.f = varA + 1 j: varB = (*q) * 2 j: varB= obj2.f * 2 • Do p and q point to the same memory location? • Does q alias p ?

  3. Memory alias/data dependence analysis Memory Data Code alias dependence analysis analysis Aliases: { Data dependences: { (p, q, strength, location) (i1, i2, type, strength) } }

  4. Outline • Enhance CAT with alias analysis • Simple alias analysis • Alias analysis in LLVM

  5. Exploiting alias analysis in CATs • Easiest: extending the transformation • Midway: extending the analysis This is what the homework H6 is going to be about! • Hardest: writing a CAT-specific alias analysis

  6. Let’s start looking at the interaction between memory alias analysis and a code transformation you are familiar with: constant propagation … but first, let’s introduce a new concept

  7. Escape variables int x, y; void myF (int *q){ int *p; … p = &x; } myF(p); ...

  8. Constant propagation revisited int x, y; We need to know which variables escape. int *p; (think about how to do it in LLVM) … = &x; … Is x constant here? x = 5; • If p does not point to x, then x = 5 *p = 42; • Yes, only one value of x reaches this last statement • Yes, because x doesn’t “escape” and therefore only one value of x reaches this last statement • If p definitely points to x, then x = 42 y = x + 1; • If p might point to x, then we have two reaching Goal of memory definitions that reach this last statement, so x is not alias analysis: understanding constant

  9. To exploit memory alias analysis in a code transformation typically you extend the related code analyses to use the information about pointer aliases

  10. Do you remember liveness analysis? • A variable v is live at a given point of a program p if • Exist a directed path from p to an use of v and • that path does not contain any definition of v • Liveness analysis is backwards • What is the most conservative output of the analysis? (the bottom of the lattice) GEN[i] = ? KILL[i] = ? IN[i] = GEN[i] ∪ (OUT[i] – KILL[i]) OUT[ i ] = ∪ s a successor of i IN[ s ]

  11. Liveness analysis revisited How can we modify liveness analysis? int x, y; int *p; … = &x; x = 5; Is x alive here? …(no uses/definitions of x) • If p does not point to x, then *p = 42; • Yes, the value 5 stored in x there will be used later • Yes, because x doesn’t “escape” and therefore the value of x stored there will be used later yes y = x + 1; • If p definitely points to x, then no What is the most conservative • If p might point to x, then output of the analysis? yes (the bottom of the lattice)

  12. Liveness analysis revisited mayAliasVar : variable -> set<variable> mustAliasVar: variable -> set<variable> How can we modify conventional liveness analysis? GEN[i] = {v | variable v is used by i} KILL[i] = {v’ | variable v’ is defined by i} IN[i] = GEN[i] ∪ (OUT[i] – KILL[i]) OUT[ i ] = ∪ s a successor of i IN[ s ]

  13. Liveness analysis revisited mayAliasVar : variable -> set<variable> mustAliasVar: variable -> set<variable> GEN[i] = {mayAliasVar(v) U mustAliasVar(v) | variable v is used by i} KILL[i] = {mustAliasVar(v) | variable v is defined by i} IN[i] = GEN[i] ∪ (OUT[i] – KILL[i]) OUT[ i ] = ∪ s a successor of i IN[ s ]

  14. Trivial analysis: no code analysis int x, y; Trivial int *p; memory … = &x; alias Nothing must alias analysis Anything may alias everything else x = 5; …(no uses/definitions of x) *p = 42; GEN[i] = {mayAliasVar(v) U mustAliasVar(v) | v is used by i} y = x + 1; KILL[i] = {mustAliasVar(v) | v is defined by i} IN[i] = GEN[i] ∪ (OUT[i] – KILL[i]) OUT[ i ] = ∪ s a successor of i IN[ s ]

  15. Great alias analysis impact int x, y; Some compilers expose only data dependences. Great int *p; How can we compute aliases for them? memory … = &x; alias No aliases analysis x = 5; …(no uses/definitions of x) *p = 42; GEN[i] = {mayAliasVar(v) U mustAliasVar(v) | v is used by i} y = x + 1; KILL[i] = {mustAliasVar(v) | v is defined by i} 5 IN[i] = GEN[i] ∪ (OUT[i] – KILL[i]) OUT[ i ] = ∪ s a successor of i IN[ s ]

  16. Data dependences and pointer aliases int x, y; int *p; … = &x; Memory Memory Data data … alias dependences dependence analysis x = 5; analysis *p = 42; y = x + 1;

  17. Outline • Enhance CAT with alias analysis • Simple alias analysis • Alias analysis in LLVM

  18. Memory alias analysis • Assumption : no dynamic memory, pointers can point only to variables 1: p = &x ; 2: q = &y; • Goal : 3: if (…){ at each program point, compute set of (p->x) pairs 4: z = &v; if p points to variable x } 5: x++; • Approach : 6: p = q; • Based on data-flow analysis 7: print *p • May information

  19. May points-to analysis … Which variable does p point to? print *p • Data flow values: {(v, x) | v is a pointer variable and x is a variable} • Direction: forward • i: p = &x • GEN[i] = {(p, x)} KILL[i] = {(p, v) | v “escapes”} • OUT[i] = GEN[i] U (IN[i] – KILL[i]) • IN[i] = U p is a predecessor of i OUT[p] Why? • Different OUT[i] equation for different instructions • i: p = q • GEN[i] = { } KILL[i] = { } OUT[i] = {(p, z) | (q, z) ∈ IN[i]} U (IN[i] – {(p,x) for all x})

  20. Code example 1: p = &x ; GEN[1] = {(p, x)} KILL[1] = {(p, x), (p, y), (p,v)} 2: q = &y; GEN[2] = {(q, y)} KILL[2] = {(q, x), (q, y), (q,v)} GEN[3] = { } KILL[3] = { } 3: if (…){ GEN[4] = {(z, v)} KILL[4] = {(z, x), (z, y), (z, v)} 4: z = &v; GEN[5] = { } KILL[5] = { } } GEN[6] = { } KILL[6] = { } 5: x++; IN[1] = { } OUT[1] = {(p,x)} 6: p = q; IN[2] = {(p,x)} OUT[2] = {(q,y),(p,x)} IN[3] = {(q,y),(p,x)} OUT[3] = {(q,y),(p,x)} IN[4] = {(q,y),(p,x)} OUT[4] = {(z,v),(q,y),(p,x)} IN[5] = {(z,v),(q,y),(p,x)} OUT[5] = {(z,v),(q,y),(p,x)} IN[6] = {(z,v),(q,y),(p,x)} OUT[6] = {(p,y),(z,v),(q,y)}

  21. May points-to analysis • IN[i] = U p is a predecessor of i OUT[p] • i: p = &x • GEN[i] = {(p,x)} KILL[i] = {(p,v) | v “escapes”} • OUT[i] = GEN[i] U (IN[i] – KILL[i]) • i: p = q • GEN[i] = { } KILL[i] = { } OUT[i] = {(p,z) | (q,z) ∈ IN[i]} U (IN[i] – {(p,x) for all x}) • i: p = *q • GEN[i] = { } KILL[i] = { } OUT[i] = {(p,t) | (q,r) ∈ IN[i] & (r,t) ∈ IN[i]} U (IN[i] – {(p,x) for all x}) • i: *q = p ?? (1 point)

  22. Memory alias analysis: dealing with dynamically allocated memory • Each invocation of a memory allocator creates a new piece of memory p = new T(); p = malloc(10); • Simple solution: generate a new “variable” for every DFA iteration to stand for new memory for (i=0; i < 10; i++){ v[i] = new malloc(100); }

  23. Memory alias analysis: dealing with dynamically allocated memory • Each invocation of a memory allocator creates a new piece of memory p = new T(); p = malloc(10); • Simple solution: generate a new “variable” for every DFA iteration to stand for new memory • Extending our data-flow analysis OUT[i] = {(p, newVar)} U (IN[i] – {(p,x) for all x}) i: p = malloc(…) OUT[i]={(p, newVar0_i)} IN[j]={(p, newVar0_i)} j: … = *p

  24. Memory alias analysis: dealing with dynamically allocated memory • Each invocation of a memory allocator creates a new piece of memory p = new T(); p = malloc(10); • Simple solution: generate a new “variable” for every DFA iteration to stand for new memory • Extending our data-flow analysis OUT[i] = {(p, newVar)} U (IN[i] – {(p,x) for all x}) IN[z]={ (p, newVar0_i), IN[j]={ (p, newVar0_i), (q, newVar0_k)} i: p = malloc(…) k: q = malloc(…) (q, newVar0_k)}, (w, newVar0_i), z: w = phi([p,left],[q,right]) (w, newVar0_k)} j: … = *w

  25. Memory alias analysis: dealing with dynamically allocated memory • Each invocation of a memory allocator creates a new piece of memory p = new T(); p = malloc(10); • Simple solution: generate a new “variable” for every DFA iteration to stand for new memory • Extending our data-flow analysis OUT[i] = {(p, newVar)} U (IN[i] – {(p,x) for all x}) IN[j]={(p, newVar0_i), (p, newVar1_i), i: p = malloc(…) (p, newVar2_i), … j: … = *p

  26. Memory alias analysis: dealing with dynamically allocated memory • Each invocation of a memory allocator creates a new piece of memory p = new T(); p = malloc(10); • Simple solution: generate a new “variable” for every DFA iteration to stand for new memory • Extending our data-flow analysis OUT[i] = {(p, newVar)} U (IN[i] – {(p,x) for all x}) • Problem: • Domain is unbounded • Iterative data-flow analysis may not converge

  27. Memory alias analysis: dealing with dynamically allocated memory Simple solution • Create a summary “variable” for each allocation statement • Domain is now bounded • Data-flow equation i: p = new T OUT[i] = {(p,inst i )} U (IN[i] – {(p,x) for all x}) IN[j]={(p, inst i )} i: p = malloc(…) Let us look at the implication j: … = *p of this design choice

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend