1 #include "l.h"
2
3 void
noops(void)4 noops(void)
5 {
6 Prog *p, *p1, *q, *q1;
7 int o, mov, aoffset, 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 q = P;
27 for(p = firstp; p != P; p = p->link) {
28
29 /* find out how much arg space is used in this TEXT */
30 if(p->to.type == D_OREG && p->to.reg == REGSP)
31 if(p->to.offset > curframe)
32 curframe = p->to.offset;
33
34 switch(p->as) {
35 /* too hard, just leave alone */
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 q = p;
47 p->mark |= LABEL|LEAF|SYNC;
48 if(p->link)
49 p->link->mark |= LABEL;
50 curtext = p;
51 break;
52
53 case ANOR:
54 q = p;
55 if(p->to.type == D_REG)
56 if(p->to.reg == REGZERO)
57 p->mark |= LABEL|SYNC;
58 break;
59
60 case ALWAR:
61 case ASTWCCC:
62 case AECIWX:
63 case AECOWX:
64 case AEIEIO:
65 case AICBI:
66 case AISYNC:
67 case ATLBIE:
68 case ATLBIEL:
69 case ASLBIA:
70 case ASLBIE:
71 case ASLBMFEE:
72 case ASLBMFEV:
73 case ASLBMTE:
74 case ADCBF:
75 case ADCBI:
76 case ADCBST:
77 case ADCBT:
78 case ADCBTST:
79 case ADCBZ:
80 case ASYNC:
81 case ATLBSYNC:
82 case APTESYNC:
83 case ATW:
84 case AWORD:
85 case ARFI:
86 case ARFCI:
87 case ARFID:
88 case AHRFID:
89 q = p;
90 p->mark |= LABEL|SYNC;
91 continue;
92
93 case AMOVW:
94 case AMOVWZ:
95 case AMOVD:
96 q = p;
97 switch(p->from.type) {
98 case D_MSR:
99 case D_SPR:
100 case D_FPSCR:
101 case D_CREG:
102 case D_DCR:
103 p->mark |= LABEL|SYNC;
104 }
105 switch(p->to.type) {
106 case D_MSR:
107 case D_SPR:
108 case D_FPSCR:
109 case D_CREG:
110 case D_DCR:
111 p->mark |= LABEL|SYNC;
112 }
113 continue;
114
115 case AFABS:
116 case AFABSCC:
117 case AFADD:
118 case AFADDCC:
119 case AFCTIW:
120 case AFCTIWCC:
121 case AFCTIWZ:
122 case AFCTIWZCC:
123 case AFDIV:
124 case AFDIVCC:
125 case AFMADD:
126 case AFMADDCC:
127 case AFMOVD:
128 case AFMOVDU:
129 /* case AFMOVDS: */
130 case AFMOVS:
131 case AFMOVSU:
132 /* case AFMOVSD: */
133 case AFMSUB:
134 case AFMSUBCC:
135 case AFMUL:
136 case AFMULCC:
137 case AFNABS:
138 case AFNABSCC:
139 case AFNEG:
140 case AFNEGCC:
141 case AFNMADD:
142 case AFNMADDCC:
143 case AFNMSUB:
144 case AFNMSUBCC:
145 case AFRSP:
146 case AFRSPCC:
147 case AFSUB:
148 case AFSUBCC:
149 q = p;
150 p->mark |= FLOAT;
151 continue;
152
153 case ABL:
154 case ABCL:
155 if(curtext != P)
156 curtext->mark &= ~LEAF;
157
158 case ABC:
159 case ABEQ:
160 case ABGE:
161 case ABGT:
162 case ABLE:
163 case ABLT:
164 case ABNE:
165 case ABR:
166 case ABVC:
167 case ABVS:
168
169 p->mark |= BRANCH;
170 q = p;
171 q1 = p->cond;
172 if(q1 != P) {
173 while(q1->as == ANOP) {
174 q1 = q1->link;
175 p->cond = q1;
176 }
177 if(!(q1->mark & LEAF))
178 q1->mark |= LABEL;
179 } else
180 p->mark |= LABEL;
181 q1 = p->link;
182 if(q1 != P)
183 q1->mark |= LABEL;
184 continue;
185
186 case AFCMPO:
187 case AFCMPU:
188 q = p;
189 p->mark |= FCMP|FLOAT;
190 continue;
191
192 case ARETURN:
193 /* special form of RETURN is BECOME */
194 if(p->from.type == D_CONST)
195 if(p->from.offset > curbecome)
196 curbecome = p->from.offset;
197
198 q = p;
199 if(p->link != P)
200 p->link->mark |= LABEL;
201 continue;
202
203 case ANOP:
204 q1 = p->link;
205 q->link = q1; /* q is non-nop */
206 q1->mark |= p->mark;
207 continue;
208
209 default:
210 q = p;
211 continue;
212 }
213 }
214 if(curtext && curtext->from.sym) {
215 curtext->from.sym->frame = curframe;
216 curtext->from.sym->become = curbecome;
217 if(curbecome > maxbecome)
218 maxbecome = curbecome;
219 }
220
221 if(debug['b'])
222 print("max become = %d\n", maxbecome);
223 xdefine("ALEFbecome", STEXT, maxbecome);
224
225 curtext = 0;
226 for(p = firstp; p != P; p = p->link) {
227 switch(p->as) {
228 case ATEXT:
229 curtext = p;
230 break;
231
232 case ABL: /* ABCL? */
233 if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
234 o = maxbecome - curtext->from.sym->frame;
235 if(o <= 0)
236 break;
237 /* calling a become or calling a variable */
238 if(p->to.sym == S || p->to.sym->become) {
239 curtext->to.offset += o;
240 if(debug['b']) {
241 curp = p;
242 print("%D calling %D increase %d\n",
243 &curtext->from, &p->to, o);
244 }
245 }
246 }
247 break;
248 }
249 }
250
251 curtext = P;
252 for(p = firstp; p != P; p = p->link) {
253 o = p->as;
254 switch(o) {
255 case ATEXT:
256 mov = AMOVD;
257 aoffset = 0;
258 curtext = p;
259 autosize = p->to.offset + 8;
260 if((p->mark & LEAF) && autosize <= 8)
261 autosize = 0;
262 else
263 if(autosize & 4)
264 autosize += 4;
265 p->to.offset = autosize - 8;
266
267 q = p;
268 if(autosize) {
269 /* use MOVDU to adjust R1 when saving R31, if autosize is small */
270 if(!(curtext->mark & LEAF) && autosize >= -BIG && autosize <= BIG) {
271 mov = AMOVDU;
272 aoffset = -autosize;
273 } else {
274 q = prg();
275 q->as = AADD;
276 q->line = p->line;
277 q->from.type = D_CONST;
278 q->from.offset = -autosize;
279 q->to.type = D_REG;
280 q->to.reg = REGSP;
281
282 q->link = p->link;
283 p->link = q;
284 }
285 } else
286 if(!(curtext->mark & LEAF)) {
287 if(debug['v'])
288 Bprint(&bso, "save suppressed in: %s\n",
289 curtext->from.sym->name);
290 curtext->mark |= LEAF;
291 }
292
293 if(curtext->mark & LEAF) {
294 if(curtext->from.sym)
295 curtext->from.sym->type = SLEAF;
296 break;
297 }
298
299 q1 = prg();
300 q1->as = mov;
301 q1->line = p->line;
302 q1->from.type = D_REG;
303 q1->from.reg = REGTMP;
304 q1->to.type = D_OREG;
305 q1->to.offset = aoffset;
306 q1->to.reg = REGSP;
307
308 q1->link = q->link;
309 q->link = q1;
310
311 q1 = prg();
312 q1->as = AMOVD;
313 q1->line = p->line;
314 q1->from.type = D_SPR;
315 q1->from.offset = D_LR;
316 q1->to.type = D_REG;
317 q1->to.reg = REGTMP;
318
319 q1->link = q->link;
320 q->link = q1;
321 break;
322
323 case ARETURN:
324 if(p->from.type == D_CONST)
325 goto become;
326 if(curtext->mark & LEAF) {
327 if(!autosize) {
328 p->as = ABR;
329 p->from = zprg.from;
330 p->to.type = D_SPR;
331 p->to.offset = D_LR;
332 p->mark |= BRANCH;
333 break;
334 }
335
336 p->as = AADD;
337 p->from.type = D_CONST;
338 p->from.offset = autosize;
339 p->to.type = D_REG;
340 p->to.reg = REGSP;
341
342 q = prg();
343 q->as = ABR;
344 q->line = p->line;
345 q->to.type = D_SPR;
346 q->to.offset = D_LR;
347 q->mark |= BRANCH;
348
349 q->link = p->link;
350 p->link = q;
351 break;
352 }
353
354 p->as = AMOVD;
355 p->from.type = D_OREG;
356 p->from.offset = 0;
357 p->from.reg = REGSP;
358 p->to.type = D_REG;
359 p->to.reg = REGTMP;
360
361 q = prg();
362 q->as = AMOVD;
363 q->line = p->line;
364 q->from.type = D_REG;
365 q->from.reg = REGTMP;
366 q->to.type = D_SPR;
367 q->to.offset = D_LR;
368
369 q->link = p->link;
370 p->link = q;
371 p = q;
372
373 if(autosize) {
374 q = prg();
375 q->as = AADD;
376 q->line = p->line;
377 q->from.type = D_CONST;
378 q->from.offset = autosize;
379 q->to.type = D_REG;
380 q->to.reg = REGSP;
381
382 q->link = p->link;
383 p->link = q;
384 }
385
386 q1 = prg();
387 q1->as = ABR;
388 q1->line = p->line;
389 q1->to.type = D_SPR;
390 q1->to.offset = D_LR;
391 q1->mark |= BRANCH;
392
393 q1->link = q->link;
394 q->link = q1;
395 break;
396
397 become:
398 if(curtext->mark & LEAF) {
399
400 q = prg();
401 q->line = p->line;
402 q->as = ABR;
403 q->from = zprg.from;
404 q->to = p->to;
405 q->cond = p->cond;
406 q->link = p->link;
407 q->mark |= BRANCH;
408 p->link = q;
409
410 p->as = AADD;
411 p->from = zprg.from;
412 p->from.type = D_CONST;
413 p->from.offset = autosize;
414 p->to = zprg.to;
415 p->to.type = D_REG;
416 p->to.reg = REGSP;
417
418 break;
419 }
420 q = prg();
421 q->line = p->line;
422 q->as = ABR;
423 q->from = zprg.from;
424 q->to = p->to;
425 q->cond = p->cond;
426 q->mark |= BRANCH;
427 q->link = p->link;
428 p->link = q;
429
430 q = prg();
431 q->line = p->line;
432 q->as = AADD;
433 q->from.type = D_CONST;
434 q->from.offset = autosize;
435 q->to.type = D_REG;
436 q->to.reg = REGSP;
437 q->link = p->link;
438 p->link = q;
439
440 q = prg();
441 q->line = p->line;
442 q->as = AMOVD;
443 q->line = p->line;
444 q->from.type = D_REG;
445 q->from.reg = REGTMP;
446 q->to.type = D_SPR;
447 q->to.offset = D_LR;
448 q->link = p->link;
449 p->link = q;
450
451 p->as = AMOVD;
452 p->from = zprg.from;
453 p->from.type = D_OREG;
454 p->from.offset = 0;
455 p->from.reg = REGSP;
456 p->to = zprg.to;
457 p->to.type = D_REG;
458 p->to.reg = REGTMP;
459
460 break;
461 }
462 }
463
464 if(debug['Q'] == 0)
465 return;
466
467 curtext = P;
468 q = P; /* p - 1 */
469 q1 = firstp; /* top of block */
470 o = 0; /* count of instructions */
471 for(p = firstp; p != P; p = p1) {
472 p1 = p->link;
473 o++;
474 if(p->mark & NOSCHED){
475 if(q1 != p){
476 sched(q1, q);
477 }
478 for(; p != P; p = p->link){
479 if(!(p->mark & NOSCHED))
480 break;
481 q = p;
482 }
483 p1 = p;
484 q1 = p;
485 o = 0;
486 continue;
487 }
488 if(p->mark & (LABEL|SYNC)) {
489 if(q1 != p)
490 sched(q1, q);
491 q1 = p;
492 o = 1;
493 }
494 if(p->mark & (BRANCH|SYNC)) {
495 sched(q1, p);
496 q1 = p1;
497 o = 0;
498 }
499 if(o >= NSCHED) {
500 sched(q1, p);
501 q1 = p1;
502 o = 0;
503 }
504 q = p;
505 }
506 }
507
508 void
addnop(Prog * p)509 addnop(Prog *p)
510 {
511 Prog *q;
512
513 q = prg();
514 q->as = AOR;
515 q->line = p->line;
516 q->from.type = D_REG;
517 q->from.reg = REGZERO;
518 q->to.type = D_REG;
519 q->to.reg = REGZERO;
520
521 q->link = p->link;
522 p->link = q;
523 }
524