xref: /plan9-contrib/sys/src/cmd/9l/noop.c (revision fbadb1c4d4463e58337ffb1ed396c9caee5d1889)
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