xref: /inferno-os/utils/ql/noop.c (revision 2b69dba5038ffd0b59cf30a4c44bce549e5097f8)
1 #include	"l.h"
2 
3 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
499 addnop(Prog *p)
500 {
501 	Prog *q;
502 
503 	q = prg();
504 	q->as = AOR;
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