dependent dynamic rules
DESCRIPTION
Slides based on Compiler Construction 2005 paper by Karina Olmos and Eelco VisserTRANSCRIPT
Composing Source-to-SourceData-Flow Transformations with
Dependent Dynamic Rewrite RulesProgram Transformation 2004–2005
Eelco Visser
Institute of Information & Computing SciencesUtrecht University,The Netherlands
March 3, 2005
Outline
1 Data-flow transformation strategies
2 Dependencies in data-flow transformation rules
3 Generic data-flow transformation strategies
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Part I
Data-Flow Transformation Strategies
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Flow-Sensitive Constant Propagation
(x := 3;y := x + 1;if foo(x) then
(y := 2 * x;x := y - 2)
else(x := y;y := 23);
z := x + y)
(x := 3;y := 4;if foo(3) then
(y := 6;x := 4)
else(x := 4;y := 23);
z := 4 + y)
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
x := 3x := 3
y := x + 1y := 4
x -> 3
if foo(x)if foo(3)
x -> 3y -> 4
y := 2 * xy := 6
x -> 3y -> 4
x := yx := 4
x -> 3y -> 4
x := y - 2x := 4
x -> 3y -> 6
x -> 4y -> 6
z := x + yz := 4 + y
x -> 4y -
y := 23y := 23
x -> 4y -> 4
x -> 4y -> 23
Strategy for Basic Constant Propagation
prop-const = PropConst <+ prop-const-assign<+ prop-const-declare <+ prop-const-let <+ prop-const-if<+ prop-const-while <+ (all(prop-const); try(EvalBinOp))
prop-const-assign =|[ x := <prop-const => e> ]|; if <is-value> ethen rules( PropConst.x : |[ x ]| -> |[ e ]| )else rules( PropConst.x :- |[ x ]| ) end
prop-const-declare =|[ var x := <prop-const => e> ]|; if <is-value> ethen rules( PropConst+x : |[ x ]| -> |[ e ]| )else rules( PropConst+x :- |[ x ]| ) end
prop-const-let =?|[ let d* in e* end ]|; {| PropConst : all(prop-const) |}
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Intersection of Rule Sets
prop-const-if =|[ if <prop-const> then <id> else <id> ]|; (|[ if <id> then <prop-const> else <id> ]|
/PropConst\ |[ if <id> then <id> else <prop-const> ]|)
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Intersection of Rule Sets
let var x := 1 var y := zvar z := 3 var a := 4
in x := x + z;a := 5;if y then(y := y + 5;z := 8)
else(x := a + 21;y := x + 1;z := a + z);
b := a + z;z := z + x end
x y z a b1 - - - -1 - 3 4 -4 - 3 4 -4 - 3 5 -
4 - 3 5 -4 - 8 5 -
26 - 3 5 -26 27 3 5 -26 27 8 5 -- - 8 5 -- - 8 5 13- - 8 5 13
let var x := 1 var y := zvar z := 3 var a := 4
in x := 4;a := 5;if y then
(y := y + 5;z := 8)
else(x := 26;y := 27;z := 8);
b := 13;z := 8 + x end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Fixed-Point Intersection of Rule Sets
let var w := 20 var x := 20var y := 20 var z := 10
in while SomethingUnknown() do(if x = 20 then w := 20 else w := 10;if y = 20 then x := 20 else x := 10;if z = 20 then y := 20 else y := 10);
w; x; y; z end
let var w := 20 var x := 20var y := 20 var z := 10
in while SomethingUnknown() do(if x = 20 then w := 20 else w := 10;if y = 20 then x := 20 else x := 10;y := 10);
w; x; y; 10 end
w x y z20 20 20 10
1 20 20 10 1020 20 - 10
2 20 - 10 1020 - - 10
3 - - 10 10- - - 10
4 - - 10 10- - - 10
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Fixed-Point Intersection of Rule Sets
prop-const-while =?|[ while e1 do e2 ]|; (/PropConst\* |[ while <prop-const> do <prop-const> ]|)
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Unreachable Code Elimination
let var x := 0 var y := 0in x := 10;
while A do(if x = 10then dosomething()else (dosomethingelse();
x := x + 1));y := x
end
let var x := 0var y := 0
in x := 10;while A dodosomething();
y := 10end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Unreachable Code Elimination
prop-const-if =|[ if <prop-const> then <id> else <id> ]|; (EvalIf; prop-const
<+ (|[ if <id> then <prop-const> else <id> ]|/PropConst\
|[ if <id> then <id> else <prop-const> ]|))
prop-const-while =?|[ while e1 do e2 ]|; (|[ while <prop-const> do <id> ]|; EvalWhile
<+ (/PropConst\*|[ while <prop-const> do <prop-const> ]|))
EvalIf : |[ if 0 then e1 else e2 ]| -> |[ e2 ]|EvalIf : |[ if i then e1 else e2 ]| -> |[ e1 ]|
where <not(eq)>(|[ i ]|, |[ 0 ]|)EvalWhile : |[ while 0 do e ]| -> |[ () ]|
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Dead Code Elimination
(x := foo(b);y := bar(h);a := c + 23;if 4 > x then
(d := b + a;g := 4 + y)
else(b := 2;a := y + 3;a := 4 + x);
print(a))
{c,b}{x,c}{x,c}{x,a}{a}{a}
{x}{x}{x}{a}
(x := foo(b);
a := c + 23;if not(4> x) then
a := 4 + x;print(a))
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Dead Code Elimination
dce = VarNeeded <+ ElimAssign <+ dce-assign<+ dce-seq <+ dce-if <+ dce-while <+ all(dce)
ElimAssign :|[ x := e ]| -> |[ () ]|where <not(Needed)> |[ x ]|
VarNeeded =?|[ x ]|; rules(Needed : |[ x ]|)
dce-assign =?|[ x := e ]|; rules(Needed :- |[ x ]|); |[ <id> := <dce> ]|
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Dead Code Elimination – Control-Flow
dce-seq =|[ (<* reverse-filter(dce; not(?|[ () ]|)) >) ]|
dce-if =(|[ if <id> then <dce> else <id> ]|
\Needed/ |[ if <id> then <id> else <dce> ]|); |[ if <dce> then <id> else <id> ]|; try(ElimIf)
dce-while =|[ while <id> do <id> ]|; (\Needed/* |[ while <dce> do <dce> ]|)
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Part II
Dependencies in Data-Flow Transformation Rules
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Copy Propagation
Replace copies x produced by assignments of the form x := y byoriginal y
a := b;c := d + a
a := b;c := d + b
First attempt using dynamic rules (wrong)
copy-prop-assign =?|[ x := y ]|;if <not(eq)>(x,y) thenrules( CopyProp.x : |[ x ]| -> |[ y ]| )
elserules( CopyProp.x :- |[ x ]| )
end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Copy Propagation
Replace copies x produced by assignments of the form x := y byoriginal y
a := b;c := d + a
a := b;c := d + b
First attempt using dynamic rules (wrong)
copy-prop-assign =?|[ x := y ]|;if <not(eq)>(x,y) thenrules( CopyProp.x : |[ x ]| -> |[ y ]| )
elserules( CopyProp.x :- |[ x ]| )
end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Problem: Insufficient Dependencies
(a := b;b := foo();c := d + a)
(a := b;b := foo();c := d + b)
Problem: rule not undefined when variable in rhs changed
Solution: undefine rule when any of its variables is modified
copy-prop-assign =?|[ x := y ]|;if <not(eq)>(x,y) thenrules( CopyProp.x : |[ x ]| -> |[ y ]| )
elserules( CopyProp.x :- |[ x ]| )
end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Problem: Insufficient Dependencies
(a := b;b := foo();c := d + a)
(a := b;b := foo();c := d + b)
Problem: rule not undefined when variable in rhs changed
Solution: undefine rule when any of its variables is modified
copy-prop-assign =?|[ x := y ]|;if <not(eq)>(x,y) thenrules( CopyProp.x : |[ x ]| -> |[ y ]| )
elserules( CopyProp.x :- |[ x ]| )
end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Problem: Free Variable Capture
let var a := bar()var b := baz()
in a := b;let var b := foo()in print(a)end
end
let var a := bar()var b := baz()
in a := b;let var b := foo()in print(b) // wrong!end
end
Problem: rule not undefined when variables become shadowed
Solution: undefine rule locally when some variable shadowed
copy-prop-assign =?|[ x := y ]|;if <not(eq)>(x,y) thenrules( CopyProp.x : |[ x ]| -> |[ y ]| )
elserules( CopyProp.x :- |[ x ]| )
end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Problem: Free Variable Capture
let var a := bar()var b := baz()
in a := b;let var b := foo()in print(a)end
end
let var a := bar()var b := baz()
in a := b;let var b := foo()in print(b) // wrong!end
end
Problem: rule not undefined when variables become shadowed
Solution: undefine rule locally when some variable shadowed
copy-prop-assign =?|[ x := y ]|;if <not(eq)>(x,y) thenrules( CopyProp.x : |[ x ]| -> |[ y ]| )
elserules( CopyProp.x :- |[ x ]| )
end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Problem: Escaping Variables (1)
let var a := bar()in let var b := foo()
in a := bend;print(a)
end
let var a := bar()in let var b := foo()
in a := bend;print(b) // wrong!
end
Problem: rule not undefined when a variable goes out of scope
Solution: (re)define rule in local scope
copy-prop-assign =?|[ x := y ]|;if <not(eq)>(x,y) thenrules( CopyProp.x : |[ x ]| -> |[ y ]| )
elserules( CopyProp.x :- |[ x ]| )
end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Problem: Escaping Variables (1)
let var a := bar()in let var b := foo()
in a := bend;print(a)
end
let var a := bar()in let var b := foo()
in a := bend;print(b) // wrong!
end
Problem: rule not undefined when a variable goes out of scope
Solution: (re)define rule in local scope
copy-prop-assign =?|[ x := y ]|;if <not(eq)>(x,y) thenrules( CopyProp.x : |[ x ]| -> |[ y ]| )
elserules( CopyProp.x :- |[ x ]| )
end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Problem: Escaping Variables (2)
let var a := bar()var c := baz()
in let var b := foo()in a := b;
a := cend;print(a)
end
let var a := bar()var c := baz()
in let var b := foo()in a := b;
a := cend;print(c) // ok!
end
Problem: definition in local scope is too restricted
Solution: (re)define rule in innermost scope of all variablesinvolved
copy-prop-assign = ?|[ x := y ]|;if <not(eq)>(x,y) thenrules( CopyProp.x : |[ x ]| -> |[ y ]| )
else rules( CopyProp.x :- |[ x ]| ) end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Problem: Escaping Variables (2)
let var a := bar()var c := baz()
in let var b := foo()in a := b;
a := cend;print(a)
end
let var a := bar()var c := baz()
in let var b := foo()in a := b;
a := cend;print(c) // ok!
end
Problem: definition in local scope is too restricted
Solution: (re)define rule in innermost scope of all variablesinvolved
copy-prop-assign = ?|[ x := y ]|;if <not(eq)>(x,y) thenrules( CopyProp.x : |[ x ]| -> |[ y ]| )
else rules( CopyProp.x :- |[ x ]| ) end
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Common-Subexpression Elimination
(x := a + b;y := a + b;z := a + c;a := 1;z := (a + c) + (a + b))
⇒(x := a + b;y := x;z := a + c;a := 1;z := (a + c) + (a + b))
Assignment
x := e
Propagation rule
|[ e ]| -> |[ x ]|
Dependencies in common-subexpression elimination
all variables in assignment x := e
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Common-Subexpression Elimination
(x := a + b;y := a + b;z := a + c;a := 1;z := (a + c) + (a + b))
⇒(x := a + b;y := x;z := a + c;a := 1;z := (a + c) + (a + b))
Assignment
x := e
Propagation rule
|[ e ]| -> |[ x ]|
Dependencies in common-subexpression elimination
all variables in assignment x := e
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Common-Subexpression Elimination
cse = cse-assign <+ (all(cse); try(ReplaceExp))
cse-assign =|[ x := <cse => e> ]|; where(<undefine-subexpressions> |[ x ]|); if <not(is-subterm(||[ x ]|))> |[ e ]| then
rules(ReplaceExp : |[ e ]| -> |[ x ]|); where(<register-subexpressions(|e)> |[ x := e ]|)
end
register-subexpressions(|e) =get-vars; map({y : ?|[ y ]|
; rules(UsedInExp :+ |[ y ]| -> e)})
undefine-subexpressions =bagof-UsedInExp; map({?e; rules(ReplaceExp :- |[ e ]|)})
get-vars = collect({?|[ x ]|})
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Dependent Dynamic Rules
Declare rule dependencies
R.lab : p1 -> p2depends on [(lab1,dep1),...,(labn,depn)]
Undefine all rules depending on dep
undefine-R(|dep)
Locally undefine all rules depending on dep
new-R(|lab, dep)
and label current scope with lab
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Copy Propagation – Assignments
copy-prop =repeat1(CopyProp)<+ copy-prop-assign<+ copy-prop-declare<+ copy-prop-let <+ copy-prop-if <+ copy-prop-while<+ all(copy-prop)
copy-prop-declare =|[ var x ta := <copy-prop => e> ]|; where( new-CopyProp(|x, x) ); where( try(<copy-prop-assign-aux> |[ x := e ]|) )
copy-prop-assign =|[ x := <copy-prop => e> ]|; where( undefine-CopyProp(|x) ); where( try(copy-prop-assign-aux) )
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Copy Propagation – Propagation Rule
copy-prop-assign-aux =? |[ x := y ]|; where( <not(eq)>(x,y) ); where( innermost-scope-CopyProp => z ); rules(
CopyProp.z : |[ x ]| -> |[ y ]|depends on [(x,x), (y,y)]
)
innermost-scope-CopyProp =get-var-names => vars; innermost-scope-CopyProp(elem-of(|vars))
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Copy Propagation – Control-Flow
copy-prop-let =|[ let <*id> in <*id> end ]|; {| CopyProp : all(copy-prop) |}
copy-prop-if =|[ if <copy-prop> then <id> else <id> ]|; ( |[ if <id> then <copy-prop> else <id> ]|
/CopyProp\ |[ if <id> then <id> else <copy-prop> ]|)
copy-prop-while =|[ while <id> do <id> ]|; (/CopyProp\* |[ while <copy-prop> do <copy-prop> ]|)
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Common-Subexpression Elimination – Assignments
cse =cse-assign <+ cse-vardec <+ cse-let <+ cse-if<+ cse-while <+ all(cse); try(CSE)
cse-vardec =|[ var x ta := <cse => e> ]|; new-CSE(|x, x); where( try(<cse-assign-aux> |[ x := e ]|) )
cse-assign =|[ x := <cse => e> ]|; undefine-CSE(|x); where(try(cse-assign-aux))
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Common-Subexpression Elimination – Propagation
cse-assign-aux =? |[ x := e ]|; where( <not(oncetd(?|[ x ]|)); pure> |[ e ]| ); where( get-var-names; map(!(<id>,<id>)) => xs ); where( innermost-scope-CSE => z ); rules( CSE.z : |[ e ]| -> |[ x ]| depends on xs )
pure =?|[ i ]| + ?|[ x ]| + |[ <bo:id>(<pure>, <pure>) ]|
innermost-scope-CSE =get-var-names => vars; innermost-scope-CSE(where(<elem>(<id>, vars)))
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Common-Subexpression Elimination – Control-Flow
cse-let =|[ let <*id> in <*id> end ]|; {| CSE : all(cse) |}
cse-if =|[ if <cse> then <id> else <id> ]|; ( |[ if <id> then <cse> else <id> ]|
/CSE\ |[ if <id> then <id> else <cse> ]|)
cse-while =|[ while <id> do <id> ]|; (/CSE\* |[ while <cse> do <cse> ]|)
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Part III
Generic Data-Flow Transformation Strategies
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Generic Data-Flow Transformation Strategies
Data-flow transformation strategies are similar
Factor out underlying strategy
Requires generalization over combinators
new-dynamic-rules(|Rs,x,x)undefine-dynamic-rules(|Rs,x)/~Rs1\~Rs2/
Allows very concise specifications for specific transformations
Combination of transformations
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Generic Strategy – Framework
forward-prop(transform, before, after | Rs1, Rs2, Rs3) =<conc>(Rs1, Rs2, Rs3) => RsSc;<conc>(Rs1, Rs2) => RsDf;letfp = prop-assign <+ prop-declare <+ prop-let
<+ prop-if <+ prop-while<+ transform(fp)<+ (before; all(fp); after)
prop-assign = ...prop-declare = ...prop-let = ...prop-if = ...prop-while = ...
in fpend
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Generic Strategy – Assignments
prop-assign =|[ <id> := <fp> ]|; (transform(fp)
<+ before; ?|[ x := e ]|; undefine-dynamic-rules(|RsDf,x); after)
prop-declare =|[ var <id> := <fp> ]|; (transform(fp)
<+ before; ?|[ var x := e ]|; new-dynamic-rules(|RsSc,x,x);after)
prop-let =?|[ let d* in e* end ]|; (transform(fp)
<+ {|~RsSc : before; all(fp); after |})
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Generic Strategy – Control Flow
prop-if =|[ if <fp> then <id> else <id> ]|; (transform(fp)
<+ before; (|[ if <id> then <fp> else <id> ]|
/~Rs1\~Rs2/ |[ if <id> then <id> else <fp> ]|); after)
prop-while =?|[ while e1 do e2 ]|; (transform(fp)
<+ before; /~Rs1\~Rs2/* |[ while <fp> do <fp> ]|; after)
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Instantation: Constant Propagation
prop-const = forward-prop(prop-const-transform, id,prop-const-after | ["PropConst"],[],[])
prop-const-transform(recur) =EvalFor <+ EvalIf; recur<+ |[ while <recur> do <id> ]|; EvalWhile
prop-const-after =try(prop-const-assign <+ prop-const-declare
<+ PropConst <+ EvalBinOp)
prop-const-assign =?|[ x := e ]|; where( <is-value> e ); rules( PropConst.x : |[ x ]| -> |[ e ]|
depends on [(x,x)] )prop-const-declare =?|[var x ta := e]|; where(<prop-const-assign>|[x := e]|)
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Instantation: Copy Propagation
copy-prop =forward-prop(no-transform,id,copy-prop-after
|["CopyProp"],[],[])
copy-prop-after =try(copy-prop-assign <+ copy-prop-declare
<+ repeat1(CopyProp))
copy-prop-declare =? |[ var x ta := e ]|; where(try(<copy-prop-assign> |[ x := e ]|))
copy-prop-assign =? |[ x := y ]|; where( <not(eq)> (x, y) ); where( get-var-dependencies => xs ); where( innermost-scope-CopyProp => z ); rules( CopyProp.z : |[ x ]| -> |[ y ]| depends on xs )
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Instantation: Common-Subexpression Elimination
cse =forward-prop(no-transform, id, cse-after|["CSE"],[],[])
cse-after =try(cse-assign <+ cse-declare <+ CSE)
cse-declare =?|[ var x := e ]|; where( <cse-assign> |[ x := e ]| )
cse-assign = ?|[ x := e ]|; where( <pure-and-not-trivial(|x)> |[ e ]| ); where( get-var-dependencies => xs ); where( innermost-scope-CSE => z ); rules( CSE.z : |[ e ]| -> |[ x ]| depends on xs )
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules
Instantation: A Super Optimizer
super-opt =forward-prop(prop-const-transform, bvr-before, bvr-after; copy-prop-after; prop-const-after; cse-after
| ["PropConst", "CopyProp", "CSE"], [], ["RenameVar"])
Combination of
constant propagation
copy propagation
common-subexpression elimination
bound variable renaming
http://www.strategoxt.org Composing Source-to-Source Data-Flow Transformations with Dependent Dynamic Rewrite Rules