composing dataflow analyses and transformations

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

Upload: thai

Post on 11-Feb-2016

31 views

Category:

Documents


0 download

DESCRIPTION

Composing Dataflow Analyses and Transformations. Sorin Lerner (University of Washington) David Grove (IBM T.J. Watson) Craig Chambers (University of Washington). const prop followed by unreachable code elimination. const prop again. Phase ordering problem. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Composing Dataflow Analyses and Transformations

Composing Dataflow Analyses and Transformations

Sorin Lerner (University of Washington)David Grove (IBM T.J. Watson)

Craig Chambers (University of Washington)

Page 2: Composing Dataflow Analyses and Transformations

x := 11;if (x == 11) { DoSomething();}else { DoSomethingElse(); x := x + 1;}y := x; // value of y?

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;DoSomething();y := 11;

const prop followedby unreachablecode elimination

const propagain

true

Page 3: Composing Dataflow Analyses and Transformations

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.

Page 4: Composing Dataflow Analyses and Transformations

Another known solution: hand writtensuper-analysis

Lose modularity:– difficult to write,

reuse, and extend such analyses

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]

MonolithicSuper-Analysis

Page 5: Composing Dataflow Analyses and Transformations

Ideally...

• ... we want to:– Write analyses modularly– Exploit mutually beneficial interactions– Have a fast compiler

• We present a framework that achieves this.

Composition Framework

Page 6: Composing Dataflow Analyses and Transformations

The key to modular composition

• Traditionally, optimizations are defined in two parts:1. A dataflow analysis.2. 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.

Page 7: Composing Dataflow Analyses and Transformations

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

Page 8: Composing Dataflow Analyses and Transformations

Flow function returning a dataflow value

y := 5

Page 9: Composing Dataflow Analyses and Transformations

Flow function returning a dataflow value

y := 5

[ ... ]

[ ..., y → 5]

PROPAGATE

Page 10: Composing Dataflow Analyses and Transformations

Flow function returning a replacement graph

y := x+2

Page 11: Composing Dataflow Analyses and Transformations

[x → 3]

Flow function returning a replacement graph

y := x+2

[x → 3]

REPLACEy := 5

Replacement

graph

Step 1: Initialize input edges with dataflow information

Page 12: Composing Dataflow Analyses and Transformations

Flow function returning a replacement graph

y := x+2y := x+2

[x [x →→ 3] 3]

y := 5

[x → 3]

PROPAGATE

[x → 3, y → 5]

Step 2: Perform recursive dataflow analysis on the replacement graph

Step 1: Initialize Step 1: Initialize input edges with input edges with dataflow dataflow informationinformation

Page 13: Composing Dataflow Analyses and Transformations

Flow function returning a replacement graph

y := x+2y := x+2

[x [x →→ 3] 3]

y := 5

[x → 3]

PROPAGATE

[x → 3, y → 5][x → 3, y → 5]

Step 2: Perform Step 2: Perform recursive dataflow recursive dataflow analysis on the analysis on the replacement replacement graphgraph

Step 1: Initialize Step 1: Initialize input edges with input edges with dataflow dataflow informationinformation

Step 3: Propagate dataflow information from output edges.

Page 14: Composing Dataflow Analyses and Transformations

Flow function returning a replacement graph

y := x+2

[x → 3]

[x → 3, y → 5]

Replacement graphs:– used to compute

outgoing dataflow information for the current statement.

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.

Page 15: Composing Dataflow Analyses and Transformations

Flow function returning a replacement graph

y := x+2

[x → 3]

[x → 3, y → 5]

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.

Page 16: Composing Dataflow Analyses and Transformations

Flow function returning a replacement graph

y := x+2

[x → 3]

[x → 3, y → 5]

Let’s assume we’ve reached a fixed point.

Page 17: Composing Dataflow Analyses and Transformations

Flow function returning a replacement graph

y := x+2

[x → 3]

[x → 3, y → 5]

y := 5

Let’s assume we’ve reached a fixed point.

Page 18: Composing Dataflow Analyses and Transformations

Flow function returning a replacement graph

y := 5

[x → 3]

[x → 3, y → 5]

Replacement graphs:– used to transform the

program once a fixed point has been reached.

Let’s assume we’ve reached a fixed point.

Page 19: Composing Dataflow Analyses and Transformations

Iterative analysis example

y := x+2

[x → 3, y → 5]

[x → 3] [x → T]

Now, let’s assume we haven’t reached a fixed point.

Page 20: Composing Dataflow Analyses and Transformations

Iterative analysis example

y := x+2

[x → 3, y → 5]

PROPAGATE

[x → 3] [x → T]

[x → T, y → T]

Now, let’s assume we haven’t reached a fixed point.

Page 21: Composing Dataflow Analyses and Transformations

Branch folding example

if (x == 11)

F T

Page 22: Composing Dataflow Analyses and Transformations

Branch folding example

if (x == 11)REPLACE

[x → 11][x → 11]

F T

Page 23: Composing Dataflow Analyses and Transformations

Branch folding example

if (x == 11)if (x == 11)

[x [x →→ 11] 11] [x → 11]

[x → 11]FF TT [x → 11]

Page 24: Composing Dataflow Analyses and Transformations

Branch folding example

if (x == 11)

[x → 11]

F T [x → 11]

Page 25: Composing Dataflow Analyses and Transformations

Composing several analyses

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 {};

Constant PropagationClass Analysis

Inlining

Unreachable code elimination

Page 26: Composing Dataflow Analyses and Transformations

x := new C

merge

b := x instanceof C

x := new D x := x.foo()

merge

while(…)

if (b)

TF

Page 27: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)

PROPAGATE

while(…)

PROPAGATE PROPAGATE

[x → T] [x → {C}] T

merge

merge

TF

PROPAGATE

T

Page 28: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)

PROPAGATE

while(…)

PROPAGATE PROPAGATE

[x → T] [x → {C}] T([x → T], [x → {C}], T, T)

merge

merge

PROPAGATE

TF

T

PROPAGATE

Page 29: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)

PROPAGATE

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

while(…)

merge

merge

TF

Page 30: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)

while(…)

PROPAGATE

[x → T, b → T]

merge

merge

TF

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

Page 31: Composing Dataflow Analyses and Transformations

([x → T], [x → {C}], T, T)

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)

([x → T], [x → {C}], T, T)

REPLACE

b := true

while(…)

[x → T, b → T]

merge

merge

TF

([x → T], [x → {C}], T, T)

Page 32: Composing Dataflow Analyses and Transformations

x := new Cx := new C

b := x instanceof Cb := x instanceof C

x := new Dx := new D x := x.foo()x := x.foo()

if (b)if (b)

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

b := true

([x → T], [x → {C}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

PROPAGATE

while(…)while(…)

mergemerge

mergemerge

TTFF

Page 33: Composing Dataflow Analyses and Transformations

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

x := new Cx := new C

b := x instanceof Cb := x instanceof C

x := new Dx := new D x := x.foo()x := x.foo()

if (b)if (b)b := true

([x → T], [x → {C}], T, T)

while(…)while(…)

mergemerge

mergemerge

TTFF

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

Page 34: Composing Dataflow Analyses and Transformations

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)

• 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

while(…)

merge

merge

TF

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

Page 35: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

REPLACE

σ

while(…)

merge

merge

TF

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

Page 36: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T) σσ

while(…)

merge

merge

TF

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

Page 37: Composing Dataflow Analyses and Transformations

x := new Cx := new C

b := x instanceof Cb := x instanceof C

x := new Dx := new D x := x.foo()x := x.foo()

if (b)if (b)

([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT)) σσσσ σ

σ

while(…)while(…)

mergemerge

mergemerge

TTFF( , , , )

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

Page 38: Composing Dataflow Analyses and Transformations

x := new Cx := new C

b := x instanceof Cb := x instanceof C

x := new Dx := new D x := x.foo()x := x.foo()

if (b)if (b)

σ

σσ

while(…)while(…)

mergemerge

mergemerge

TTFF

([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT)) σσ

( , , , )( , , , )

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

Page 39: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

while(…)

merge

merge

TF

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

( , , , )

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

Page 40: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

while(…)

merge

merge

TF

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

( , , , )

REPLACE

( , , , )

Page 41: Composing Dataflow Analyses and Transformations

x := new Cx := new C

b := x instanceof Cb := x instanceof C

x := new Dx := new D x := x.foo()x := x.foo()

if (b)if (b)

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT))

while(…)while(…)

mergemerge

mergemerge

TTFF

([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT))

( , ,( , , , ), )

( , , , )

( , , , )( , , , )

Page 42: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

while(…)

merge

merge

TF

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

( , , , )

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

( , , , )

Page 43: Composing Dataflow Analyses and Transformations

σ

x := new C

b := x instanceof C

x := new D x := x.foo()

if (b)([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

REPLACE

x := C::foo(x)

while(…)

merge

merge

T( , , , )

( , , , )

F

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

σ

Page 44: Composing Dataflow Analyses and Transformations

x := new Cx := new C

b := x instanceof Cb := x instanceof C

x := new Dx := new D x := x.foo()x := x.foo()

if (b)if (b)([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT))

x := C::foo(x)

σREPLA

CE

x := x

σ

class C extends A { A foo() { return self; }}

while(…)while(…)

mergemerge

mergemerge

FF TT σσ( , ,( , , , ), )

( , ,( , , , ), )

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT))

Page 45: Composing Dataflow Analyses and Transformations

x := new Cx := new C

b := x instanceof Cb := x instanceof C

x := new Dx := new D x := x.foo()x := x.foo()

if (b)if (b)

x := C::foo(x)x := C::foo(x)

σσ

x := x

σ

σPROPAGATE

while(…)while(…)

mergemerge

mergemerge

FF TT([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT)) σσ( , ,( , , , ), )

( , ,( , , , ), )

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT))

Page 46: Composing Dataflow Analyses and Transformations

x := new Cx := new C

b := x instanceof Cb := x instanceof C

x := new Dx := new D x := x.foo()x := x.foo()

if (b)if (b)

x := C::foo(x)x := C::foo(x)

σσ

x := x

σ

σσ

while(…)while(…)

mergemerge

mergemerge

FF TT([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT)) σσ( , ,( , , , ), )

( , ,( , , , ), )

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT))

Page 47: Composing Dataflow Analyses and Transformations

x := new Cx := new C

b := x instanceof Cb := x instanceof C

x := new Dx := new D x := x.foo()x := x.foo()

if (b)if (b)

x := C::foo(x)

σ

σσ

while(…)while(…)

mergemerge

mergemerge

FF TT

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT))

([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT)) σσ( , ,( , , , ), )

( , ,( , , , ), )

Page 48: Composing Dataflow Analyses and Transformations

x := new Cx := new C

b := x instanceof Cb := x instanceof C

x := new Dx := new D x := x.foo()x := x.foo()

if (b)if (b)

x := C::foo(x)

σ

σ

while(…)while(…)

mergemerge

mergemerge

FF TT([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT)) σσ( , ,( , , , ), )

( , ,( , , , ), )

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ TT], [x ], [x →→ {C}], {C}], TT, , TT))

([x ([x →→ T, T, b b →→ true], true],

[x [x →→ {C}, b {C}, b →→ {Bool}], {Bool}], TT, , TT))

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

Page 49: Composing Dataflow Analyses and Transformations

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

x := new C

b := x instanceof C

x := x.foo()

if (b)

while(…)

merge

merge

T([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

( , , , )

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

( , , , )

x := new D

F

Page 50: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := x.foo()

if (b)

PROPAGATE([x → T, b → true],

[x → {C}, b → {Bool}], T , T)

while(…)

merge

merge

T

x := new D

F

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

( , , , )

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

( , , , )

Page 51: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := x.foo()

if (b)

PROPAGATE

([x → T], [x → {C}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

while(…)

merge

merge

T

x := new D

F

([x → T, b → true],

[x → {C}, b → {Bool}], T , T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

( , , , )

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

( , , , )

Page 52: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := x.foo()

if (b)

while(…)

merge

merge

T

x := new D

F

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T , T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

([x → T, b → true],

[x → {C}, b → {Bool}], T, T)

( , , , )

([x → T], [x → {C}], T, T)

([x → T], [x → {C}], T, T)

( , , , )

([x → T], [x → {C}], T, T)

Page 53: Composing Dataflow Analyses and Transformations

x := new C

b := x instanceof C

x := x.foo()

if (b)

x := x

b := true

while(…)

merge

merge

T

x := new D

F

Page 54: Composing Dataflow Analyses and Transformations

x := new C

b := true

x := x

x := new C;do { b := x instanceof C; if (b) { x := x.foo(); } else { x := new D; }} while (...)

x := new C;do { b := true; x := x;} while (...)while(…)

merge

merge

Page 55: Composing Dataflow Analyses and Transformations

x := new C;do { b := x instanceof C; if (b) { x := x.foo(); } else { x := new D; }} while (...)

x := new C;do { b := true; x := x;} while (...)

•Analyses are defined modularly and separately.

•Combining them achieves the results of a monolithic analysis.

• If the analyses were run separately in any order any number of times, no optimizations could be performed.

Page 56: Composing Dataflow Analyses and Transformations

Theoretical foundation

• Definition: used abstract interpretation to define precisely how the framework composes analyses.

• Soundness theorem: if the individual analyses are sound, the composed analysis is sound.

• Termination theorem: composed analyses are guaranteed to terminate, under reasonable conditions.

• Precision theorem: if the composed flow function is monotonic, the composed analysis is guaranteed to produce results as precise as running the individual analyses in sequence, any number of times, in any order.

Page 57: Composing Dataflow Analyses and Transformations

Experimental validation

• Implemented and used our framework in the Vortex and Whirlwind compilers for 5+ years.– composed: class analysis, splitting, inlining, const

prop, CSE, removal of redundant loads and stores, symbolic assertion prop

• Compiled a range of big programs in Vortex.– largest benchmark: Vortex compiler with ~60,000 lines

• Our framework vs. iteration:– compiles at least 5 times faster

• Our framework vs. monolithic super-analysis:– same precision– compiles at most 20% slower

Page 58: Composing Dataflow Analyses and Transformations

Conclusions

• We developed and implemented a new approach for defining dataflow analyses.

• Our approach allows analyses to be written modularly:– easier to write and reuse analyses.

• Our approach allows analyses to be automatically combined into a monolithic analysis.