58
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 followed by unreachable code elimination const prop again true

X := 11; if (x == 11) { DoSomething(); } else { DoSomethingElse(); x := x + 1; } y := x; // value of y? Phase ordering problem Optimizations can interact

  • View
    229

  • Download
    0

Embed Size (px)

Citation preview

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

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.

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

Ideally...

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

• We present a framework that achieves this.

Composition Framework

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.

Flow function returning a dataflow value

y := 5

Flow function returning a dataflow value

y := 5

[ ... ]

[ ..., y → 5]

PROPAGATE

Flow function returning a replacement graph

y := x+2

[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

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

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.

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.

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.

Flow function returning a replacement graph

y := x+2

[x → 3]

[x → 3, y → 5]

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

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.

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.

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.

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.

Branch folding example

if (x == 11)

F T

Branch folding example

if (x == 11)REPLACE

[x → 11][x → 11]

F T

Branch folding example

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

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

[x → 11]FF TT

[x → 11]

Branch folding example

if (x == 11)

[x → 11]

F T[x → 11]

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 Propagation

Class Analysis

Inlining

Unreachable code elimination

x := new C

merge

b := x instanceof C

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

merge

while(…)

if (b)

TF

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

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

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

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)

([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)

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

([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))

([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)

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)

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)

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))

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))

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)

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

( , , , )

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))

( , ,( , , , ), )

( , , , )

( , , , )( , , , )

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)

( , , , )

σ

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)

σ

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)

σREPLACE

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))

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))

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))

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)) σσ( , ,( , , , ), )

( , ,( , , , ), )

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)

([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

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)

( , , , )

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)

( , , , )

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)

x := new C

b := x instanceof C

x := x.foo()

if (b)

x := x

b := true

while(…)

merge

merge

T

x := new D

F

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

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.

Analysis followed by transformations

Integrating analysis and transformations

Composing analyses and transformations