14 |
end = struct |
end = struct |
15 |
|
|
16 |
structure IL = HighIL |
structure IL = HighIL |
17 |
structure Op = IL.Op |
structure Op = HighOps |
18 |
structure V = IL.Var |
structure V = IL.Var |
19 |
structure ST = Stats |
structure ST = Stats |
20 |
|
structure F = FieldDef |
21 |
|
|
22 |
structure Census = CensusFn (IL) |
structure Census = CensusFn (IL) |
23 |
|
|
26 |
val cntConstField = ST.newCounter "high-opt:const-field" |
val cntConstField = ST.newCounter "high-opt:const-field" |
27 |
val cntConstDiff = ST.newCounter "high-opt:const-diff" |
val cntConstDiff = ST.newCounter "high-opt:const-diff" |
28 |
val cntUnused = ST.newCounter "high-opt:unused" |
val cntUnused = ST.newCounter "high-opt:unused" |
29 |
val firstCounter = cntUnusedStmt |
val firstCounter = cntConstConvolve |
30 |
val lastCounter = cntUnusedCFun |
val lastCounter = cntUnused |
31 |
|
|
32 |
datatype binding |
datatype binding |
33 |
= Unknown |
= Unknown |
45 |
(* optimize the rhs of an assignment, returning NONE if there is no change *) |
(* optimize the rhs of an assignment, returning NONE if there is no change *) |
46 |
fun doRHS rhs = (case rhs |
fun doRHS rhs = (case rhs |
47 |
of IL.OP(Op.Convolve, [v, h]) => (case (getBinding v, getBinding h) |
of IL.OP(Op.Convolve, [v, h]) => (case (getBinding v, getBinding h) |
48 |
of ((Op.LoadImage v', []), (Op.Kernel h', [])) => ( |
of (OP(Op.LoadImage v', []), OP(Op.Kernel h', [])) => ( |
49 |
ST.tick cntConstConvolve; |
ST.tick cntConstConvolve; |
50 |
decUse v; decUse h; |
decUse v; decUse h; |
51 |
SOME(IL.Op(Op.Field(F.convolve(v', h')), []))) |
SOME(IL.OP(Op.Field(F.convolve(v', h')), []))) |
52 |
| _ => raise Fail "non-constant Convolve" |
| _ => raise Fail "non-constant Convolve" |
53 |
(* end case *)) |
(* end case *)) |
54 |
| IL.OP(Op.AddField, [f, g]) => (case (getBinding f, getBinding g) |
| IL.OP(Op.AddField, [f, g]) => (case (getBinding f, getBinding g) |
55 |
of ((Op.Field f', []), (Op.Field g', [])) => ( |
of (OP(Op.Field f', []), OP(Op.Field g', [])) => ( |
56 |
ST.tick cntConstField; |
ST.tick cntConstField; |
57 |
decUse f; decUse g; |
decUse f; decUse g; |
58 |
SOME(IL.Op(Op.Field(F.SUM(f, g)), []))) |
SOME(IL.OP(Op.Field(F.SUM(f', g')), []))) |
59 |
| _ => NONE |
| _ => NONE |
60 |
(* end case *)) |
(* end case *)) |
61 |
| IL.OP(Op.NegField, [f]) => (case (getBinding f) |
| IL.OP(Op.NegField, [f]) => (case (getBinding f) |
62 |
of (Op.Field f', []) => ( |
of OP(Op.Field f', []) => ( |
63 |
ST.tick cntConstField; |
ST.tick cntConstField; |
64 |
decUse f'; |
decUse f; |
65 |
SOME(IL.Op(Op.Field(F.neg f'), []))) |
SOME(IL.OP(Op.Field(F.neg f'), []))) |
66 |
| _ => NONE |
| _ => NONE |
67 |
(* end case *)) |
(* end case *)) |
68 |
| IL.OP(Op.DiffField, [f]) => (case (getBinding f) |
| IL.OP(Op.DiffField, [f]) => (case (getBinding f) |
69 |
of (Op.Field f', []) => ( |
of OP(Op.Field f', []) => ( |
70 |
ST.tick cntConstDiff; |
ST.tick cntConstDiff; |
71 |
decUse f'; |
decUse f; |
72 |
SOME(IL.Op(Op.Field(F.diff f'), []))) |
SOME(IL.OP(Op.Field(F.diff f'), []))) |
73 |
| _ => raise Fail "non-constant DiffField" |
| _ => raise Fail "non-constant DiffField" |
74 |
(* end case *)) |
(* end case *)) |
75 |
| _ => NONE |
| _ => NONE |
77 |
|
|
78 |
fun setBindings nodes = let |
fun setBindings nodes = let |
79 |
fun doNode (IL.JOIN{phis, ...}) = |
fun doNode (IL.JOIN{phis, ...}) = |
80 |
List.app (fn (y, _) => setBinding(y, PHI xs)) (!phis) |
List.app (fn (y, xs) => setBinding(y, PHI xs)) (!phis) |
81 |
| doNode (IL.BLOCK{body, ...}) = |
| doNode (IL.BLOCK{body, ...}) = |
82 |
List.app (fn (y, IL.OP rhs) => setBinding(y, RHS rhs) | _ => ()) (!body) |
List.app (fn (y, IL.OP rhs) => setBinding(y, OP rhs) | _ => ()) (!body) |
83 |
| doNode _ = () |
| doNode _ = () |
84 |
in |
in |
85 |
List.app doNode nodes |
List.app doNode nodes |
88 |
(* simplify expressions *) |
(* simplify expressions *) |
89 |
fun simplify nodes = let |
fun simplify nodes = let |
90 |
fun doAssign (y, rhs) = (case doRHS rhs |
fun doAssign (y, rhs) = (case doRHS rhs |
91 |
of SOME(rhs' as IL.OP t) => (setBinding(y, RHS t); (y, rhs')) |
of SOME(rhs' as IL.OP t) => (setBinding(y, OP t); (y, rhs')) |
92 |
| SOME rhs' => (setBinding(y, Unknown); (y, rhs')) |
| SOME rhs' => (setBinding(y, Unknown); (y, rhs')) |
93 |
| NONE => (y, rhs) |
| NONE => (y, rhs) |
94 |
(* end case *)) |
(* end case *)) |
95 |
fun doNode (IL.BLOCK{body, ...}) = body := List.map doAssign (!body) |
fun doNode (IL.ND{kind=IL.BLOCK{body, ...}, ...}) = body := List.map doAssign (!body) |
96 |
| doNode _ = () |
| doNode _ = () |
97 |
in |
in |
98 |
List.app doNode nodes |
List.app doNode nodes |
101 |
(* reduce the code by removing variables with use counts of 0 *) |
(* reduce the code by removing variables with use counts of 0 *) |
102 |
fun reduce nodes = let |
fun reduce nodes = let |
103 |
fun checkVar (y, _) = (useCount y > 0) orelse (ST.tick cntUnused; false) |
fun checkVar (y, _) = (useCount y > 0) orelse (ST.tick cntUnused; false) |
104 |
fun doNode (IL.JOIN{phis, ...}) = let |
fun doNode (IL.ND{kind, ...}) = (case kind |
105 |
|
of IL.JOIN{phis, ...} => let |
106 |
fun doVar (y, xs) = if (useCount y = 0) |
fun doVar (y, xs) = if (useCount y = 0) |
107 |
then ( |
then ( |
108 |
ST.tick cntUnused; |
ST.tick cntUnused; |
112 |
in |
in |
113 |
phis := List.filter doVar (!phis) |
phis := List.filter doVar (!phis) |
114 |
end |
end |
115 |
| doNode (IL.BLOCK{body, ...}) = let |
| IL.BLOCK{body, ...} => let |
116 |
(* check for unused lhs variables in reverse order *) |
(* check for unused lhs variables in reverse order *) |
117 |
fun doAssigns [] = [] |
fun doAssigns [] = [] |
118 |
| doAssigns ((y, rhs)::r) = let |
| doAssigns ((y, rhs)::r) = let |
122 |
then ( |
then ( |
123 |
ST.tick cntUnused; |
ST.tick cntUnused; |
124 |
case rhs |
case rhs |
125 |
of IL VAR x => decUse x |
of IL.VAR x => decUse x |
126 |
| IL.OP(_, xs) => List.app decUse xs |
| IL.OP(_, xs) => List.app decUse xs |
127 |
| IL.CONS xs => List.app decUse xs |
| IL.CONS xs => List.app decUse xs |
128 |
(* end case *); |
(* end case *); |
129 |
r) |
r) |
130 |
else (y. rhs)::r |
else (y, rhs)::r |
131 |
|
end |
132 |
in |
in |
133 |
body := doAssigns (!body) |
body := doAssigns (!body) |
134 |
end |
end |
135 |
| doNode _ = () |
| _ => () |
136 |
|
(* end case *)) |
137 |
in |
in |
138 |
List.app doNode (List.rev nodes) |
List.app doNode (List.rev nodes) |
139 |
end |
end |
140 |
|
|
141 |
fun clearBindings nodes = let |
fun clearBindings nodes = let |
142 |
fun doNode (IL.JOIN{phis, ...}) = |
fun doNode (IL.ND{kind, ...}) = (case kind |
143 |
List.app (fn (y, xs) => clrBinding y) (!phis) |
of IL.JOIN{phis, ...} => List.app (fn (y, xs) => clrBinding y) (!phis) |
144 |
| doNode (IL.BLOCK{body, ...}) = |
| IL.BLOCK{body, ...} => List.app (fn (y, _) => clrBinding y) (!body) |
145 |
List.app (fn (y, _) => clrBinding y) (!body) |
| _ => () |
146 |
| doNode _ = () |
(* end case *)) |
147 |
in |
in |
148 |
List.app doNode nodes |
List.app doNode nodes |
149 |
end |
end |
150 |
|
|
151 |
fun loopToFixPt f = let |
fun loopToFixPt f prog = let |
152 |
fun loop (n, prog) = let |
fun loop (n, prog) = let |
153 |
val prog = f prog |
val () = f prog |
154 |
val n' = Stats.sum{from=firstCounter, last=lastCounter} |
val n' = Stats.sum{from=firstCounter, to=lastCounter} |
155 |
in |
in |
156 |
if (n = n') then prog else loop(n', prog) |
if (n = n') then () else loop(n', prog) |
157 |
end |
end |
158 |
in |
in |
159 |
loop (Stats.sum{from=firstCounter, last=lastCounter}, prog) |
loop (Stats.sum{from=firstCounter, to=lastCounter}, prog) |
160 |
end |
end |
161 |
|
|
162 |
fun optimize (prog as IL.Program{globals, globalInit, actors}) = let |
fun optimize (prog as IL.Program{globals, globalInit, actors}) = let |