View
231
Download
0
Category
Preview:
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.
[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.
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
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.
Recommended