1 / 58

Composing Dataflow Analyses and Transformations

Learn about the composition framework for modularly writing and optimizing dataflow analyses, with examples and experimental validation.

bice
Download Presentation

Composing Dataflow Analyses and Transformations

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Composing Dataflow Analyses and Transformations Sorin Lerner (University of Washington) David Grove (IBM T.J. Watson) Craig Chambers (University of Washington)

  2. const prop followed by unreachable code elimination const prop again Phase ordering problem • Optimizations can interact in mutually beneficial ways, and no order exploits all of these interactions. • Classic example: constant propagation and unreachable code elimination. x := 11; DoSomething(); y := x; // value of y? x := 11; if (x == 11) { DoSomething(); } else { DoSomethingElse(); x := x + 1; } y := x; // value of y? true x := 11; DoSomething(); y := 11;

  3. One known solution: Iterate individual analyses until the results don’t change x := 11; do { if (x == 11) { DoSomething(); } else { DoSomethingElse(); x := x + 1; } } while (...) y := x; // value of y? • Compiler is slow. • In the presence of loops in the source program, might not yield best possible results.

  4. Monolithic Super-Analysis Another known solution: hand writtensuper-analysis • Examples: • conditional constant propagation [Wegman and Zadeck 91] • class analysis, splitting and inlining [Chambers and Ungar 90] • const prop and pointer analysis [Pioli and Hind 99] • Lose modularity: • difficult to write, reuse, and extend such analyses

  5. Composition Framework Ideally... • ... we want to: • Write analyses modularly • Exploit mutually beneficial interactions • Have a fast compiler • We present a framework that achieves this.

  6. The key to modular composition • Traditionally, optimizations are defined in two parts: • A dataflow analysis. • Rules for transforming the program representation after the analysis is solved. • The key insight is to merge these two parts: • Dataflow functions return either a dataflow value OR a replacement graph with which to replace the current statement.

  7. Roadmap • Several small examples that show how flow functions work • One large example that shows how modular analyses are automatically composed together • Overview of the theory behind the framework • Experimental validation

  8. Flow function returning a dataflow value y := 5

  9. Flow function returning a dataflow value [ ... ] y := 5 PROPAGATE [ ..., y → 5]

  10. Flow function returning a replacement graph y := x+2

  11. y := 5 REPLACE Flow function returning a replacement graph Step 1: Initialize input edges with dataflow information Replacement graph [x → 3] [x → 3] y := x+2

  12. y := 5 Flow function returning a replacement graph Step 2: Perform recursive dataflow analysis on the replacement graph Step 1: Initialize input edges with dataflow information [x → 3] [x → 3] y := x+2 PROPAGATE [x → 3,y → 5]

  13. y := 5 Flow function returning a replacement graph Step 2: Perform recursive dataflow analysis on the replacement graph Step 1: Initialize input edges with dataflow information [x → 3] [x → 3] y := x+2 PROPAGATE [x → 3,y → 5] [x → 3,y → 5] Step 3: Propagate dataflow information from output edges.

  14. Flow function returning a replacement graph • Replacement graphs: • used to compute outgoing dataflow information for the current statement. • a convenient way of specifying what might otherwise be a complicated flow function. • Replacement graphs: • used to compute outgoing dataflow information for the current statement. [x → 3] y := x+2 [x → 3,y → 5]

  15. Flow function returning a replacement graph • Soundness requirement: • Replacement graph must have the same concrete semantics as the original statement, but only on concrete inputs that are consistent with the current dataflow facts. [x → 3] y := x+2 [x → 3,y → 5]

  16. Flow function returning a replacement graph Let’s assume we’ve reached a fixed point. [x → 3] y := x+2 [x → 3,y → 5]

  17. Flow function returning a replacement graph Let’s assume we’ve reached a fixed point. [x → 3] y := x+2 y := 5 [x → 3,y → 5]

  18. Flow function returning a replacement graph Let’s assume we’ve reached a fixed point. • Replacement graphs: • used to transform the program once a fixed point has been reached. [x → 3] y := 5 [x → 3,y → 5]

  19. Iterative analysis example Now, let’s assume we haven’t reached a fixed point. [x → 3] [x →T] y := x+2 [x → 3,y → 5]

  20. Iterative analysis example Now, let’s assume we haven’t reached a fixed point. [x → 3] [x →T] y := x+2 PROPAGATE [x → 3,y → 5] [x →T,y →T]

  21. Branch folding example if (x == 11) F T

  22. REPLACE Branch folding example [x → 11] [x → 11] if (x == 11) F T

  23. Branch folding example [x → 11] [x → 11] if (x == 11) [x → 11] [x → 11] F T

  24. Branch folding example [x → 11] if (x == 11) [x → 11] F T

  25. Constant Propagation x := new C; do { b := x instanceof C; if (b) { x := x.foo(); } else { x := new D; } } while (...) class A { A foo() { return new A; } }; class C extends A { A foo() { return self; } }; class D extends A { }; Class Analysis Inlining Unreachable code elimination Composing several analyses

  26. x := new C merge b := x instanceof C if (b) F T x := new D x := x.foo() merge while(…)

  27. x := new C PROPAGATE PROPAGATE PROPAGATE PROPAGATE [x → {C}] [x →T] T T merge b := x instanceof C if (b) F T x := new D x := x.foo() merge while(…)

  28. x := new C PROPAGATE PROPAGATE PROPAGATE PROPAGATE PROPAGATE ([x →T], [x → {C}], T, T) [x → {C}] [x →T] T T merge b := x instanceof C if (b) F T x := new D x := x.foo() merge while(…)

  29. x := new C ([x →T], [x → {C}], T, T) merge PROPAGATE ([x →T], [x → {C}], T, T) b := x instanceof C if (b) F T x := new D x := x.foo() merge while(…)

  30. x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C PROPAGATE [x →T, b →T] if (b) F T x := new D x := x.foo() merge while(…)

  31. b := true REPLACE x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) ([x →T], [x → {C}], T, T) b := x instanceof C [x →T, b →T] if (b) F T x := new D x := x.foo() merge while(…)

  32. b := true x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T], [x → {C}], T, T) PROPAGATE if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) F T x := new D x := x.foo() merge while(…)

  33. b := true x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T], [x → {C}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) F T x := new D x := x.foo() merge while(…)

  34. x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) • Replacement graph is analyzed by composed analysis. • When one analysis chooses a replacement graph, other analyses see it immediately. • Analyses communicate implicitly through graph transformations b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) F T x := new D x := x.foo() merge while(…)

  35. REPLACE x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) σ if (b) F T x := new D x := x.foo() merge while(…)

  36. x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) σ σ if (b) F T x := new D x := x.foo() merge while(…)

  37. ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) σ σ σ if (b) σ F T x := new D x := x.foo() merge while(…)

  38. ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) σ σ if (b) σ σ F T x := new D x := x.foo() merge while(…)

  39. ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) F T x := new D x := x.foo() merge while(…)

  40. REPLACE ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) F T x := new D x := x.foo() merge while(…)

  41. ( , , , ) ( , , , ) ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) F T x := new D x := x.foo() merge while(…)

  42. ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) F T x := new D x := x.foo() merge while(…)

  43. x := C::foo(x) REPLACE ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) σ σ F T x := new D x := x.foo() merge while(…)

  44. x := C::foo(x) x := x ( , , , ) ( , , , ) REPLACE x := new C class C extends A { A foo() { return self; } } ([x →T], [x → {C}], T, T) merge σ σ ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) σ F T x := new D x := x.foo() merge while(…)

  45. x := C::foo(x) x := x ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge σ ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) σ F T x := new D x := x.foo() σ PROPAGATE merge σ while(…)

  46. x := C::foo(x) x := x ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge σ ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) σ F T x := new D x := x.foo() σ merge σ σ while(…)

  47. x := C::foo(x) ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge σ ([x →T], [x → {C}], T, T) b := x instanceof C σ σ ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) σ F T x := new D x := x.foo() merge while(…)

  48. x := C::foo(x) ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge σ ([x →T], [x → {C}], T, T) b := x instanceof C σ ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) σ F T x := new D x := x.foo() ([x →T, b → true], [x → {C}, b →{Bool}], T, T) merge while(…)

  49. ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) F T x := new D x := x.foo() ([x →T, b → true], [x → {C}, b →{Bool}], T, T) merge while(…)

  50. ( , , , ) ( , , , ) x := new C ([x →T], [x → {C}], T, T) merge ([x →T], [x → {C}], T, T) b := x instanceof C ([x →T, b → true], [x → {C}, b →{Bool}], T, T) if (b) ([x →T, b → true], [x → {C}, b →{Bool}], T, T) F T x := new D x := x.foo() ([x →T, b → true], [x → {C}, b →{Bool}], T, T) merge PROPAGATE ([x →T, b → true], [x → {C}, b →{Bool}], T , T) while(…)

More Related