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