|
|
1-- $Id: tailRecursion.ppl,v 1.2 2007-01-11 21:29:59 uwe Exp $
2
3function ggt(x,y : int) : int
4 if x = y
5 then x
6 else if x > y
7 then ggt(x - y, y)
8 else tgg(x, y)
9;
10
11function tgg(x,y : int) : int
12 ggt(y, x)
13;
14
15function f(x : int) :int
16 if x >= 0
17 then
18 g(x)
19 else
20 f(x + 1)
21;
22
23function g(x : int) : int
24 if x >= 0
25 then
26 g(x - 1)
27 else
28 f(x)
29;
30
31begin
32 var i : int;
33 i := ggt(13, 8)
34end
|
|
1.text
2 loadi 13
3 loadi 8
4 pushj _ggt
5 store m[0]
6 undef
7 store m[0]
8 terminate
9_ggt:
10 entry 3
11 store l[0]
12s_ggt:
13 store l[1]
14 store l[2]
15 load l[2]
16 load l[1]
17 eqi
18 brfalse l0
19 load l[2]
20 jmp l1
21l0:
22 load l[2]
23 load l[1]
24 gti
25 brfalse l2
26 load l[2]
27 load l[1]
28 subi
29 load l[1]
30 pushj _ggt
31 jmp l3
32l2:
33 load l[2]
34 load l[1]
35 pushj _tgg
36l3:
37l1:
38e_ggt:
39 load l[0]
40 exit
41 popj
42_tgg:
43 entry 3
44 store l[0]
45s_tgg:
46 store l[1]
47 store l[2]
48 load l[1]
49 load l[2]
50 pushj _ggt
51e_tgg:
52 load l[0]
53 exit
54 popj
55_f:
56 entry 2
57 store l[0]
58s_f:
59 store l[1]
60 load l[1]
61 loadi 0
62 gei
63 brfalse l4
64 load l[1]
65 pushj _g
66 jmp l5
67l4:
68 load l[1]
69 loadi 1
70 addi
71 pushj _f
72l5:
73e_f:
74 load l[0]
75 exit
76 popj
77_g:
78 entry 2
79 store l[0]
80s_g:
81 store l[1]
82 load l[1]
83 loadi 0
84 gei
85 brfalse l6
86 load l[1]
87 loadi 1
88 subi
89 pushj _g
90 jmp l7
91l6:
92 load l[1]
93 pushj _f
94l7:
95e_g:
96 load l[0]
97 exit
98 popj
99
100.data 1
|
|
1.text
2 loadi 13
3 loadi 8
4 pushj _ggt
5 store m[0]
6 undef
7 store m[0]
8 terminate
9_ggt:
10 entry 3
11 store l[0]
12s_ggt:
13 store l[1]
14 dup
15 store l[2]
16 load l[1]
17 eqi
18 brfalse l0
19 load l[2]
20 jmp e_ggt
21l0:
22 load l[2]
23 load l[1]
24 gti
25 brfalse l2
26 load l[2]
27 load l[1]
28 subi
29 load l[1]
30 jmp s_ggt
31l2:
32 load l[2]
33 load l[1]
34 load l[0]
35 exit
36 jmp _tgg
37e_ggt:
38 load l[0]
39 exit
40 popj
41_tgg:
42 entry 3
43 store l[0]
44 store l[1]
45 store l[2]
46 load l[1]
47 load l[2]
48 load l[0]
49 exit
50 jmp _ggt
51_f:
52 entry 2
53 store l[0]
54s_f:
55 dup
56 store l[1]
57 loadi 0
58 gei
59 brfalse l4
60 load l[1]
61 load l[0]
62 exit
63 jmp _g
64l4:
65 load l[1]
66 incri
67 jmp s_f
68_g:
69 entry 2
70 store l[0]
71s_g:
72 dup
73 store l[1]
74 loadi 0
75 gei
76 brfalse l6
77 load l[1]
78 decri
79 jmp s_g
80l6:
81 load l[1]
82 load l[0]
83 exit
84 jmp _f
85
86.data 1
|
|
1.text .text
2 loadi 13 loadi 13
3 loadi 8 loadi 8
4 pushj _ggt pushj _ggt
5 store m[0] store m[0]
6 undef undef
7 store m[0] store m[0]
8 terminate terminate
9_ggt: _ggt:
10 entry 3 entry 3
11 store l[0] store l[0]
12s_ggt: s_ggt:
13 store l[1] store l[1]
14 > dup
15 store l[2] store l[2]
16 load l[2] <
17 load l[1] load l[1]
18 eqi eqi
19 brfalse l0 brfalse l0
20 load l[2] load l[2]
21 jmp l1 | jmp e_ggt
22l0: l0:
23 load l[2] load l[2]
24 load l[1] load l[1]
25 gti gti
26 brfalse l2 brfalse l2
27 load l[2] load l[2]
28 load l[1] load l[1]
29 subi subi
30 load l[1] load l[1]
31 pushj _ggt | jmp s_ggt
32 jmp l3 <
33l2: l2:
34 load l[2] load l[2]
35 load l[1] load l[1]
36 pushj _tgg | load l[0]
37l3: | exit
38l1: | jmp _tgg
39e_ggt: e_ggt:
40 load l[0] load l[0]
41 exit exit
42 popj popj
43_tgg: _tgg:
44 entry 3 entry 3
45 store l[0] store l[0]
46s_tgg: <
47 store l[1] store l[1]
48 store l[2] store l[2]
49 load l[1] load l[1]
50 load l[2] load l[2]
51 pushj _ggt <
52e_tgg: <
53 load l[0] load l[0]
54 exit exit
55 popj | jmp _ggt
56_f: _f:
57 entry 2 entry 2
58 store l[0] store l[0]
59s_f: s_f:
60 > dup
61 store l[1] store l[1]
62 load l[1] <
63 loadi 0 loadi 0
64 gei gei
65 brfalse l4 brfalse l4
66 load l[1] load l[1]
67 pushj _g <
68 jmp l5 <
69l4: <
70 load l[1] <
71 loadi 1 <
72 addi <
73 pushj _f <
74l5: <
75e_f: <
76 load l[0] load l[0]
77 exit exit
78 popj | jmp _g
79 > l4:
80 > load l[1]
81 > incri
82 > jmp s_f
83_g: _g:
84 entry 2 entry 2
85 store l[0] store l[0]
86s_g: s_g:
87 > dup
88 store l[1] store l[1]
89 load l[1] <
90 loadi 0 loadi 0
91 gei gei
92 brfalse l6 brfalse l6
93 load l[1] load l[1]
94 loadi 1 | decri
95 subi | jmp s_g
96 pushj _g <
97 jmp l7 <
98l6: l6:
99 load l[1] load l[1]
100 pushj _f <
101l7: <
102e_g: <
103 load l[0] load l[0]
104 exit exit
105 popj | jmp _f
106
107.data 1 .data 1
|
|
1-- $Id: OptimizeInstr.hs,v 1.4 2006/01/24 21:37:07 uwe Exp $
2
3module PPL.OptimizeInstr
4 ( optimizeInstr
5 )
6where
7
8import PPL.Instructions
9
10import Data.Maybe
11
12type LabSubst = [(Label, Label)]
13
14optimizeInstr :: Executable -> Executable
15optimizeInstr (is, ds)
16 = ((peephole . removeUnusedLabels . jumpChaining . optimizeTailRecursion) is, ds)
17
18jumpChaining :: Code -> Code
19jumpChaining is
20 = let
21 labTab = buildLabSubst [] is
22 is' = renameLabels labTab is
23 in
24 is'
25
26buildLabSubst :: LabSubst -> Code -> LabSubst
27
28-- real jump chaining
29buildLabSubst lt ( (Label l1)
30 : (Jump (Symb l2))
31 : is2)
32 = buildLabSubst lt1 is2
33 where
34 lt1 = insLabSubst l1 l2 lt
35
36-- labels with equal values are collapsed
37buildLabSubst lt ( (Label l1)
38 : is1@((Label l2)
39 : _))
40 = buildLabSubst lt1 is1
41 where
42 lt1 = insLabSubst l1 l2 lt
43
44-- default rules
45buildLabSubst lt (_:is1)
46 = buildLabSubst lt is1
47
48buildLabSubst lt []
49 = lt
50
51
52-- --------------------
53
54insLabSubst :: Label -> Label -> LabSubst -> LabSubst
55insLabSubst l1 l2 lt
56 = if (l2,l1) `elem` lt || l1 == l2
57 then lt
58 else (l1, l2) : lt'
59 where
60 lt' = map renameWith lt
61 renameWith (l1',l2')
62 | l2' == l1
63 = (l1', l2)
64 renameWith p
65 = p
66
67newLabName :: LabSubst -> Label -> Label
68newLabName lt l
69 = case lookup l lt of
70 Just l1 -> l1
71 Nothing -> l
72
73renameLabels :: LabSubst -> Code -> Code
74
75-- remove alias labels
76
77renameLabels lt ((Label l1) : is1)
78 | isJust (lookup l1 lt)
79 = renameLabels lt is1
80
81-- default
82renameLabels lt (i1:is)
83 = renameLab lt i1 : renameLabels lt is
84
85renameLabels _ []
86 = []
87
88renameLab :: LabSubst -> Instr -> Instr
89
90renameLab lt (Branch cond (Symb l1))
91 = Branch cond (Symb (newLabName lt l1))
92
93renameLab lt (Jump (Symb l1))
94 = Jump (Symb (newLabName lt l1))
95
96renameLab _lt i
97 = i
98
99-- --------------------
100
101usedLabels :: Code -> [Label]
102usedLabels
103 = concat . map lab
104 where
105 lab (Branch _ (Symb l)) = [l]
106 lab (Jump (Symb l)) = [l]
107 lab _ = []
108
109removeUnusedLabels :: Code -> Code
110removeUnusedLabels cs
111 = filter usedLabel cs
112 where
113 used = usedLabels cs
114
115 usedLabel (Label l@(c:_))
116 = c == '_' -- global label
117 ||
118 l `elem` used -- label is referenced in jump or branch
119 usedLabel _
120 = True
121
122-- --------------------
123
124-- peephole optimizations
125-- local instruction optimization
126
127peephole :: Code -> Code
128
129-- remove instructions following unconditional jumps
130
131peephole (i1@(Jump _l1)
132 : i2
133 : is
134 )
135 | noLabel i2
136 = peephole (i1:is)
137
138-- remove jump to following instruction
139
140peephole (Jump (Symb l1)
141 : is2@(Label l2
142 : _
143 )
144 )
145 | l1 == l2
146 = peephole is2
147
148-- remove conditional branch to following instruction
149
150peephole (Branch _ (Symb l1)
151 : is2@(Label l2
152 : _
153 )
154 )
155 | l1 == l2
156 = Pop
157 : peephole is2
158
159-- conditional branches with constants
160
161peephole (LoadI val
162 : Branch cond lab
163 : is
164 )
165 | (val /= 0) == cond
166 = peephole (Jump lab : is)
167 | otherwise
168 = peephole is
169
170-- optimize store load sequences
171
172peephole (Store a1
173 : Load a2
174 : is
175 )
176 | a1 == a2
177 = Dup
178 : peephole (Store a1 : is)
179
180-- optimize increment and decrement
181
182peephole (LoadI 1
183 : Compute OPaddi
184 : is
185 )
186 = Compute OPincri
187 : peephole is
188
189peephole (LoadI 1
190 : Compute OPsubi
191 : is
192 )
193 = Compute OPdecri
194 : peephole is
195
196peephole (Pop
197 : LoadU
198 : is
199 )
200 = peephole is
201
202-- next step
203
204peephole (i1:is1)
205 = i1 : peephole is1
206
207peephole []
208 = []
209
210-- --------------------
211
212noLabel :: Instr -> Bool
213
214noLabel (Label _) = False
215noLabel _ = True
216
217-- --------------------
218
219optimizeCalls :: LabSubst -> Code -> Code
220optimizeCalls lt cs@( Label sl
221 : Entry _
222 : Store _
223 : Label sl1
224 : cs4
225 )
226 = take 4 cs
227 ++
228 optimize1Fct cs4
229 where
230 el1 = 'e' : sl
231 el = newLabName lt el1
232
233 optimize1Fct cs'@( Exit -- function exit detected
234 : PopJ -- optimize rest
235 : rest'
236 )
237 = take 2 cs'
238 ++
239 optimizeCalls lt rest'
240
241 optimize1Fct ( PushJ fct@(Symb target)
242 : Jump (Symb l1)
243 : rest
244 )
245 -- pure tail recursion detected
246 -- subroutine call substituted
247 -- by a jump to routine start
248 | target == sl && newLabName lt l1 == el
249 = Jump (Symb sl1)
250 : optimize1Fct rest
251 -- tail recursion to another function
252 -- load return address
253 -- remove stack frame
254 -- and jump
255 | newLabName lt l1 == el
256 = Load (LocA 0)
257 : Exit
258 : Jump fct
259 : optimize1Fct rest
260
261 -- same as above for calls
262 -- directly in front of exit code
263 optimize1Fct ( PushJ fct@(Symb target)
264 : cs1@( Label l1
265 : _rest
266 )
267 )
268 | target == sl && newLabName lt l1 == el
269 = Jump (Symb sl1)
270 : optimize1Fct cs1
271
272 | newLabName lt l1 == el
273 = Load (LocA 0)
274 : Exit
275 : Jump fct
276 : optimize1Fct cs1
277
278 -- continue search for calls
279 optimize1Fct (c : cs1)
280 = c : optimize1Fct cs1
281
282 optimize1Fct []
283 = []
284
285optimizeCalls lt (c1 : cs1)
286 = c1 : optimizeCalls lt cs1
287
288optimizeCalls _ []
289 = []
290
291-- optimize tail recursion
292-- 1. step: collect all function entry end exit points
293-- 2. step: look for function calls
294
295optimizeTailRecursion :: Code -> Code
296optimizeTailRecursion cs
297 = optimizeCalls labTab cs
298 where
299 labTab = buildLabSubst [] cs
300
301-- --------------------
|
| Letzte Änderung: 14.02.2012 | © Prof. Dr. Uwe Schmidt |