1 #include "l.h"
2
3 void
noops(void)4 noops(void)
5 {
6 Prog *p, *p1, *q, *q1;
7 int o, curframe, curbecome, maxbecome;
8
9 /*
10 * find leaf subroutines
11 * become sizes
12 * frame sizes
13 * strip NOPs
14 * expand RET
15 * expand BECOME pseudo
16 */
17
18 if(debug['v'])
19 Bprint(&bso, "%5.2f noops\n", cputime());
20 Bflush(&bso);
21
22 curframe = 0;
23 curbecome = 0;
24 maxbecome = 0;
25 curtext = 0;
26
27 q = P;
28 for(p = firstp; p != P; p = p->link) {
29
30 /* find out how much arg space is used in this TEXT */
31 if(p->to.type == D_OREG && p->to.reg == REGSP)
32 if(p->to.offset > curframe)
33 curframe = p->to.offset;
34
35 switch(p->as) {
36 case ATEXT:
37 if(curtext && curtext->from.sym) {
38 curtext->from.sym->frame = curframe;
39 curtext->from.sym->become = curbecome;
40 if(curbecome > maxbecome)
41 maxbecome = curbecome;
42 }
43 curframe = 0;
44 curbecome = 0;
45
46 p->mark |= LABEL|LEAF|SYNC;
47 if(p->link)
48 p->link->mark |= LABEL;
49 curtext = p;
50 break;
51
52 /* too hard, just leave alone */
53 case AMOVW:
54 case AMOVV:
55 if(p->to.type == D_FCREG ||
56 p->to.type == D_MREG) {
57 p->mark |= LABEL|SYNC;
58 break;
59 }
60 if(p->from.type == D_FCREG ||
61 p->from.type == D_MREG) {
62 p->mark |= LABEL|SYNC;
63 addnop(p);
64 addnop(p);
65 nop.mfrom.count += 2;
66 nop.mfrom.outof += 2;
67 break;
68 }
69 break;
70
71 /* too hard, just leave alone */
72 case ACASE:
73 case ASYSCALL:
74 case AWORD:
75 case ATLBWR:
76 case ATLBWI:
77 case ATLBP:
78 case ATLBR:
79 p->mark |= LABEL|SYNC;
80 break;
81
82 case ANOR:
83 if(p->to.type == D_REG && p->to.reg == REGZERO)
84 p->mark |= LABEL|SYNC;
85 break;
86
87 case ARET:
88 /* special form of RET is BECOME */
89 if(p->from.type == D_CONST)
90 if(p->from.offset > curbecome)
91 curbecome = p->from.offset;
92
93 if(p->link != P)
94 p->link->mark |= LABEL;
95 break;
96
97 case ANOP:
98 q1 = p->link;
99 q->link = q1; /* q is non-nop */
100 q1->mark |= p->mark;
101 continue;
102
103 case ABCASE:
104 p->mark |= LABEL|SYNC;
105 goto dstlab;
106
107 case ABGEZAL:
108 case ABLTZAL:
109 case AJAL:
110 if(curtext != P)
111 curtext->mark &= ~LEAF;
112
113 case AJMP:
114 case ABEQ:
115 case ABGEZ:
116 case ABGTZ:
117 case ABLEZ:
118 case ABLTZ:
119 case ABNE:
120 case ABFPT:
121 case ABFPF:
122 p->mark |= BRANCH;
123
124 dstlab:
125 q1 = p->cond;
126 if(q1 != P) {
127 while(q1->as == ANOP) {
128 q1 = q1->link;
129 p->cond = q1;
130 }
131 if(!(q1->mark & LEAF))
132 q1->mark |= LABEL;
133 } else
134 p->mark |= LABEL;
135 q1 = p->link;
136 if(q1 != P)
137 q1->mark |= LABEL;
138 break;
139 }
140 q = p;
141 }
142
143 if(curtext && curtext->from.sym) {
144 curtext->from.sym->frame = curframe;
145 curtext->from.sym->become = curbecome;
146 if(curbecome > maxbecome)
147 maxbecome = curbecome;
148 }
149
150 if(debug['b'])
151 print("max become = %d\n", maxbecome);
152 xdefine("ALEFbecome", STEXT, maxbecome);
153
154 curtext = 0;
155 for(p = firstp; p != P; p = p->link) {
156 switch(p->as) {
157 case ATEXT:
158 curtext = p;
159 break;
160 case AJAL:
161 if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
162 o = maxbecome - curtext->from.sym->frame;
163 if(o <= 0)
164 break;
165 /* calling a become or calling a variable */
166 if(p->to.sym == S || p->to.sym->become) {
167 curtext->to.offset += o;
168 if(debug['b']) {
169 curp = p;
170 print("%D calling %D increase %d\n",
171 &curtext->from, &p->to, o);
172 }
173 }
174 }
175 break;
176 }
177 }
178
179 for(p = firstp; p != P; p = p->link) {
180 o = p->as;
181 switch(o) {
182 case ATEXT:
183 curtext = p;
184 autosize = p->to.offset + 8;
185 if(autosize <= 8)
186 if(curtext->mark & LEAF) {
187 p->to.offset = -8;
188 autosize = 0;
189 }
190
191 q = p;
192 if(autosize) {
193 if(autosize & 7)
194 Bprint(&bso, "odd stack in: %s\n",
195 curtext->from.sym->name);
196 q = prg();
197 q->as = AADDV;
198 q->line = p->line;
199 q->from.type = D_CONST;
200 q->from.offset = -autosize;
201 q->to.type = D_REG;
202 q->to.reg = REGSP;
203
204 q->link = p->link;
205 p->link = q;
206 } else
207 if(!(curtext->mark & LEAF)) {
208 if(debug['v'])
209 Bprint(&bso, "save suppressed in: %s\n",
210 curtext->from.sym->name);
211 Bflush(&bso);
212 curtext->mark |= LEAF;
213 }
214
215 if(curtext->mark & LEAF) {
216 if(curtext->from.sym)
217 curtext->from.sym->type = SLEAF;
218 break;
219 }
220
221 q1 = prg();
222 q1->as = AMOVV;
223 q1->line = p->line;
224 q1->from.type = D_REG;
225 q1->from.reg = REGLINK;
226 q1->to.type = D_OREG;
227 q1->from.offset = 0;
228 q1->to.reg = REGSP;
229
230 q1->link = q->link;
231 q->link = q1;
232 break;
233
234 case ARET:
235 nocache(p);
236 if(p->from.type == D_CONST)
237 goto become;
238 if(curtext->mark & LEAF) {
239 if(!autosize) {
240 p->as = AJMP;
241 p->from = zprg.from;
242 p->to.type = D_OREG;
243 p->to.offset = 0;
244 p->to.reg = REGLINK;
245 p->mark |= BRANCH;
246 break;
247 }
248
249 p->as = AADDV;
250 p->from.type = D_CONST;
251 p->from.offset = autosize;
252 p->to.type = D_REG;
253 p->to.reg = REGSP;
254
255 q = prg();
256 q->as = AJMP;
257 q->line = p->line;
258 q->to.type = D_OREG;
259 q->to.offset = 0;
260 q->to.reg = REGLINK;
261 q->mark |= BRANCH;
262
263 q->link = p->link;
264 p->link = q;
265 break;
266 }
267 p->as = AMOVV;
268 p->from.type = D_OREG;
269 p->from.offset = 0;
270 p->from.reg = REGSP;
271 p->to.type = D_REG;
272 p->to.reg = 2;
273
274 q = p;
275 if(autosize) {
276 q = prg();
277 q->as = AADDV;
278 q->line = p->line;
279 q->from.type = D_CONST;
280 q->from.offset = autosize;
281 q->to.type = D_REG;
282 q->to.reg = REGSP;
283
284 q->link = p->link;
285 p->link = q;
286 }
287
288 q1 = prg();
289 q1->as = AJMP;
290 q1->line = p->line;
291 q1->to.type = D_OREG;
292 q1->to.offset = 0;
293 q1->to.reg = 2;
294 q1->mark |= BRANCH;
295
296 q1->link = q->link;
297 q->link = q1;
298 break;
299
300 become:
301 if(curtext->mark & LEAF) {
302
303 q = prg();
304 q->line = p->line;
305 q->as = AJMP;
306 q->from = zprg.from;
307 q->to = p->to;
308 q->cond = p->cond;
309 q->link = p->link;
310 q->mark |= BRANCH;
311 p->link = q;
312
313 p->as = AADDV;
314 p->from = zprg.from;
315 p->from.type = D_CONST;
316 p->from.offset = autosize;
317 p->to = zprg.to;
318 p->to.type = D_REG;
319 p->to.reg = REGSP;
320
321 break;
322 }
323 q = prg();
324 q->line = p->line;
325 q->as = AJMP;
326 q->from = zprg.from;
327 q->to = p->to;
328 q->cond = p->cond;
329 q->link = p->link;
330 q->mark |= BRANCH;
331 p->link = q;
332
333 q = prg();
334 q->line = p->line;
335 q->as = AADDV;
336 q->from.type = D_CONST;
337 q->from.offset = autosize;
338 q->to.type = D_REG;
339 q->to.reg = REGSP;
340 q->link = p->link;
341 p->link = q;
342
343 p->as = AMOVV;
344 p->from = zprg.from;
345 p->from.type = D_OREG;
346 p->from.offset = 0;
347 p->from.reg = REGSP;
348 p->to = zprg.to;
349 p->to.type = D_REG;
350 p->to.reg = REGLINK;
351
352 break;
353 }
354 }
355
356 curtext = P;
357 q = P; /* p - 1 */
358 q1 = firstp; /* top of block */
359 o = 0; /* count of instructions */
360 for(p = firstp; p != P; p = p1) {
361 p1 = p->link;
362 o++;
363 if(p->mark & NOSCHED){
364 if(q1 != p){
365 sched(q1, q);
366 }
367 for(; p != P; p = p->link){
368 if(!(p->mark & NOSCHED))
369 break;
370 q = p;
371 }
372 p1 = p;
373 q1 = p;
374 o = 0;
375 continue;
376 }
377 if(p->mark & (LABEL|SYNC)) {
378 if(q1 != p)
379 sched(q1, q);
380 q1 = p;
381 o = 1;
382 }
383 if(p->mark & (BRANCH|SYNC)) {
384 sched(q1, p);
385 q1 = p1;
386 o = 0;
387 }
388 if(o >= NSCHED) {
389 sched(q1, p);
390 q1 = p1;
391 o = 0;
392 }
393 q = p;
394 }
395 }
396
397 void
addnop(Prog * p)398 addnop(Prog *p)
399 {
400 Prog *q;
401
402 q = prg();
403 q->as = ANOR;
404 q->line = p->line;
405 q->from.type = D_REG;
406 q->from.reg = REGZERO;
407 q->to.type = D_REG;
408 q->to.reg = REGZERO;
409
410 q->link = p->link;
411 p->link = q;
412 }
413
414 void
nocache(Prog * p)415 nocache(Prog *p)
416 {
417 p->optab = 0;
418 p->from.class = 0;
419 p->to.class = 0;
420 }
421