xref: /plan9/sys/src/cmd/kl/noop.c (revision 6b6b9ac8b0b103b1e30e4d019522a78c950fce74)
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 	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 AORN:
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 AUNIMP:
61 		case ATAS:
62 		case ASWAP:
63 		case ATA:
64 		case ATCC:
65 		case ATCS:
66 		case ATE:
67 		case ATG:
68 		case ATGE:
69 		case ATGU:
70 		case ATL:
71 		case ATLE:
72 		case ATLEU:
73 		case ATN:
74 		case ATNE:
75 		case ATNEG:
76 		case ATPOS:
77 		case ATVC:
78 		case ATVS:
79 		case AWORD:
80 			q = p;
81 			p->mark |= LABEL|SYNC;
82 			continue;
83 
84 		case AFABSD:
85 		case AFABSF:
86 		case AFABSX:
87 		case AFADDD:
88 		case AFADDF:
89 		case AFADDX:
90 		case AFDIVD:
91 		case AFDIVF:
92 		case AFDIVX:
93 		case AFMOVD:
94 		case AFMOVDF:
95 		case AFMOVDW:
96 		case AFMOVDX:
97 		case AFMOVF:
98 		case AFMOVFD:
99 		case AFMOVFW:
100 		case AFMOVFX:
101 		case AFMOVWD:
102 		case AFMOVWF:
103 		case AFMOVWX:
104 		case AFMOVX:
105 		case AFMOVXD:
106 		case AFMOVXF:
107 		case AFMOVXW:
108 		case AFMULD:
109 		case AFMULF:
110 		case AFMULX:
111 		case AFNEGD:
112 		case AFNEGF:
113 		case AFNEGX:
114 		case AFSQRTD:
115 		case AFSQRTF:
116 		case AFSQRTX:
117 		case AFSUBD:
118 		case AFSUBF:
119 		case AFSUBX:
120 			q = p;
121 			p->mark |= FLOAT;
122 			continue;
123 
124 		case AMUL:
125 		case ADIV:
126 		case ADIVL:
127 		case AMOD:
128 		case AMODL:
129 			q = p;
130 			if(!debug['M']) {
131 				if(prog_mul == P)
132 					initmuldiv();
133 				if(curtext != P)
134 					curtext->mark &= ~LEAF;
135 			}
136 			continue;
137 
138 		case AJMPL:
139 			if(curtext != P)
140 				curtext->mark &= ~LEAF;
141 
142 		case AJMP:
143 
144 		case ABA:
145 		case ABN:
146 		case ABE:
147 		case ABNE:
148 		case ABLE:
149 		case ABG:
150 		case ABL:
151 		case ABGE:
152 		case ABLEU:
153 		case ABGU:
154 		case ABCS:
155 		case ABCC:
156 		case ABNEG:
157 		case ABPOS:
158 		case ABVC:
159 		case ABVS:
160 
161 		case AFBN:
162 		case AFBO:
163 		case AFBE:
164 		case AFBLG:
165 		case AFBG:
166 		case AFBLE:
167 		case AFBGE:
168 		case AFBL:
169 		case AFBNE:
170 		case AFBUE:
171 		case AFBA:
172 		case AFBU:
173 		case AFBUG:
174 		case AFBULE:
175 		case AFBUGE:
176 		case AFBUL:
177 			p->mark |= BRANCH;
178 			q = p;
179 			q1 = p->cond;
180 			if(q1 != P) {
181 				while(q1->as == ANOP) {
182 					q1 = q1->link;
183 					p->cond = q1;
184 				}
185 				if(!(q1->mark & LEAF))
186 					q1->mark |= LABEL;
187 			} else
188 				p->mark |= LABEL;
189 			q1 = p->link;
190 			if(q1 != P)
191 				q1->mark |= LABEL;
192 			continue;
193 
194 		case AFCMPD:
195 		case AFCMPED:
196 		case AFCMPEF:
197 		case AFCMPEX:
198 		case AFCMPF:
199 		case AFCMPX:
200 			q = p;
201 			p->mark |= FCMP|FLOAT;
202 			continue;
203 
204 		case ARETURN:
205 			/* special form of RETURN is BECOME */
206 			if(p->from.type == D_CONST)
207 				if(p->from.offset > curbecome)
208 					curbecome = p->from.offset;
209 
210 			q = p;
211 			if(p->link != P)
212 				p->link->mark |= LABEL;
213 			continue;
214 
215 		case ANOP:
216 			q1 = p->link;
217 			q->link = q1;		/* q is non-nop */
218 			q1->mark |= p->mark;
219 			continue;
220 
221 		default:
222 			q = p;
223 			continue;
224 		}
225 	}
226 	if(curtext && curtext->from.sym) {
227 		curtext->from.sym->frame = curframe;
228 		curtext->from.sym->become = curbecome;
229 		if(curbecome > maxbecome)
230 			maxbecome = curbecome;
231 	}
232 
233 	if(debug['b'])
234 		print("max become = %d\n", maxbecome);
235 	xdefine("ALEFbecome", STEXT, maxbecome);
236 
237 	curtext = 0;
238 	for(p = firstp; p != P; p = p->link) {
239 		switch(p->as) {
240 		case ATEXT:
241 			curtext = p;
242 			break;
243 
244 		case AJMPL:
245 			if(curtext != P && curtext->from.sym != S && curtext->to.offset >= 0) {
246 				o = maxbecome - curtext->from.sym->frame;
247 				if(o <= 0)
248 					break;
249 				/* calling a become or calling a variable */
250 				if(p->to.sym == S || p->to.sym->become) {
251 					curtext->to.offset += o;
252 					if(debug['b']) {
253 						curp = p;
254 						print("%D calling %D increase %d\n",
255 							&curtext->from, &p->to, o);
256 					}
257 				}
258 			}
259 			break;
260 		}
261 	}
262 
263 	curtext = P;
264 	for(p = firstp; p != P; p = p->link) {
265 		o = p->as;
266 		switch(o) {
267 		case ATEXT:
268 			curtext = p;
269 			autosize = p->to.offset + 4;
270 			if((p->mark & LEAF) && autosize <= 4)
271 				autosize = 0;
272 			else
273 				if(autosize & 4)
274 					autosize += 4;
275 			p->to.offset = autosize - 4;
276 
277 			q = p;
278 			if(autosize) {
279 				q = prg();
280 				q->as = ASUB;
281 				q->line = p->line;
282 				q->from.type = D_CONST;
283 				q->from.offset = autosize;
284 				q->to.type = D_REG;
285 				q->to.reg = REGSP;
286 
287 				q->link = p->link;
288 				p->link = q;
289 			} else
290 			if(!(curtext->mark & LEAF)) {
291 				if(debug['v'])
292 					Bprint(&bso, "save suppressed in: %s\n",
293 						curtext->from.sym->name);
294 				curtext->mark |= LEAF;
295 			}
296 
297 			if(curtext->mark & LEAF) {
298 				if(curtext->from.sym)
299 					curtext->from.sym->type = SLEAF;
300 				break;
301 			}
302 
303 			q1 = prg();
304 			q1->as = AMOVW;
305 			q1->line = p->line;
306 			q1->from.type = D_REG;
307 			q1->from.reg = REGLINK;
308 			q1->to.type = D_OREG;
309 			q1->from.offset = 0;
310 			q1->to.reg = REGSP;
311 
312 			q1->link = q->link;
313 			q->link = q1;
314 			break;
315 
316 		case AMUL:
317 		case ADIV:
318 		case ADIVL:
319 		case AMOD:
320 		case AMODL:
321 			if(debug['M'])
322 				break;
323 			if(p->from.type != D_REG)
324 				break;
325 			if(p->to.type != D_REG)
326 				break;
327 			q1 = p;
328 
329 			/* MOV a,4(SP) */
330 			q = prg();
331 			q->link = p->link;
332 			p->link = q;
333 			p = q;
334 
335 			p->as = AMOVW;
336 			p->line = q1->line;
337 			p->from.type = D_REG;
338 			p->from.reg = q1->from.reg;
339 			p->to.type = D_OREG;
340 			p->to.reg = REGSP;
341 			p->to.offset = 4;
342 
343 			/* MOV b,REGTMP */
344 			q = prg();
345 			q->link = p->link;
346 			p->link = q;
347 			p = q;
348 
349 			p->as = AMOVW;
350 			p->line = q1->line;
351 			p->from.type = D_REG;
352 			p->from.reg = q1->reg;
353 			if(q1->reg == NREG)
354 				p->from.reg = q1->to.reg;
355 			p->to.type = D_REG;
356 			p->to.reg = REGTMP;
357 			p->to.offset = 0;
358 
359 			/* CALL appropriate */
360 			q = prg();
361 			q->link = p->link;
362 			p->link = q;
363 			p = q;
364 
365 			p->as = AJMPL;
366 			p->line = q1->line;
367 			p->to.type = D_BRANCH;
368 			p->cond = p;
369 			p->mark |= BRANCH;
370 			switch(o) {
371 			case AMUL:
372 				p->cond = prog_mul;
373 				break;
374 			case ADIV:
375 				p->cond = prog_div;
376 				break;
377 			case ADIVL:
378 				p->cond = prog_divl;
379 				break;
380 			case AMOD:
381 				p->cond = prog_mod;
382 				break;
383 			case AMODL:
384 				p->cond = prog_modl;
385 				break;
386 			}
387 
388 			/* MOV REGTMP, b */
389 			q = prg();
390 			q->link = p->link;
391 			p->link = q;
392 			p = q;
393 
394 			p->as = AMOVW;
395 			p->line = q1->line;
396 			p->from.type = D_REG;
397 			p->from.reg = REGTMP;
398 			p->from.offset = 0;
399 			p->to.type = D_REG;
400 			p->to.reg = q1->to.reg;
401 
402 			/* ADD $8,SP */
403 			q = prg();
404 			q->link = p->link;
405 			p->link = q;
406 			p = q;
407 
408 			p->as = AADD;
409 			p->from.type = D_CONST;
410 			p->from.reg = NREG;
411 			p->from.offset = 8;
412 			p->reg = NREG;
413 			p->to.type = D_REG;
414 			p->to.reg = REGSP;
415 
416 			/* SUB $8,SP */
417 			q1->as = ASUB;
418 			q1->from.type = D_CONST;
419 			q1->from.offset = 8;
420 			q1->from.reg = NREG;
421 			q1->reg = NREG;
422 			q1->to.type = D_REG;
423 			q1->to.reg = REGSP;
424 			break;
425 
426 		case ARETURN:
427 			if(p->from.type == D_CONST)
428 				goto become;
429 			if(curtext->mark & LEAF) {
430 				if(!autosize) {
431 					p->as = AJMP;
432 					p->from = zprg.from;
433 					p->to.type = D_OREG;
434 					p->to.offset = 8;
435 					p->to.reg = REGLINK;
436 					p->mark |= BRANCH;
437 					break;
438 				}
439 
440 				p->as = AADD;
441 				p->from.type = D_CONST;
442 				p->from.offset = autosize;
443 				p->to.type = D_REG;
444 				p->to.reg = REGSP;
445 
446 				q = prg();
447 				q->as = AJMP;
448 				q->line = p->line;
449 				q->to.type = D_OREG;
450 				q->to.offset = 8;
451 				q->to.reg = REGLINK;
452 				q->mark |= BRANCH;
453 
454 				q->link = p->link;
455 				p->link = q;
456 				break;
457 			}
458 
459 			p->as = AMOVW;
460 			p->from.type = D_OREG;
461 			p->from.offset = 0;
462 			p->from.reg = REGSP;
463 			p->to.type = D_REG;
464 			p->to.reg = REGRET+1;
465 
466 			q = p;
467 			if(autosize) {
468 				q = prg();
469 				q->as = AADD;
470 				q->line = p->line;
471 				q->from.type = D_CONST;
472 				q->from.offset = autosize;
473 				q->to.type = D_REG;
474 				q->to.reg = REGSP;
475 
476 				q->link = p->link;
477 				p->link = q;
478 			}
479 
480 			q1 = prg();
481 			q1->as = AJMP;
482 			q1->line = p->line;
483 			q1->to.type = D_OREG;
484 			q1->to.offset = 8;
485 			q1->to.reg = REGRET+1;
486 			q1->mark |= BRANCH;
487 
488 			q1->link = q->link;
489 			q->link = q1;
490 			break;
491 
492 		become:
493 			if(curtext->mark & LEAF) {
494 
495 				q = prg();
496 				q->line = p->line;
497 				q->as = AJMP;
498 				q->from = zprg.from;
499 				q->to = p->to;
500 				q->cond = p->cond;
501 				q->link = p->link;
502 				q->mark |= BRANCH;
503 				p->link = q;
504 
505 				p->as = AADD;
506 				p->from = zprg.from;
507 				p->from.type = D_CONST;
508 				p->from.offset = autosize;
509 				p->to = zprg.to;
510 				p->to.type = D_REG;
511 				p->to.reg = REGSP;
512 
513 				break;
514 			}
515 			q = prg();
516 			q->line = p->line;
517 			q->as = AJMP;
518 			q->from = zprg.from;
519 			q->to = p->to;
520 			q->cond = p->cond;
521 			q->mark |= BRANCH;
522 			q->link = p->link;
523 			p->link = q;
524 
525 			q = prg();
526 			q->line = p->line;
527 			q->as = AADD;
528 			q->from.type = D_CONST;
529 			q->from.offset = autosize;
530 			q->to.type = D_REG;
531 			q->to.reg = REGSP;
532 			q->link = p->link;
533 			p->link = q;
534 
535 			p->as = AMOVW;
536 			p->from = zprg.from;
537 			p->from.type = D_OREG;
538 			p->from.offset = 0;
539 			p->from.reg = REGSP;
540 			p->to = zprg.to;
541 			p->to.type = D_REG;
542 			p->to.reg = REGLINK;
543 
544 			break;
545 		}
546 	}
547 
548 	curtext = P;
549 	q = P;		/* p - 1 */
550 	q1 = firstp;	/* top of block */
551 	o = 0;		/* count of instructions */
552 	for(p = firstp; p != P; p = p1) {
553 		p1 = p->link;
554 		o++;
555 		if(p->mark & NOSCHED){
556 			if(q1 != p){
557 				sched(q1, q);
558 			}
559 			for(; p != P; p = p->link){
560 				if(!(p->mark & NOSCHED))
561 					break;
562 				q = p;
563 			}
564 			p1 = p;
565 			q1 = p;
566 			o = 0;
567 			continue;
568 		}
569 		if(p->mark & (LABEL|SYNC)) {
570 			if(q1 != p)
571 				sched(q1, q);
572 			q1 = p;
573 			o = 1;
574 		}
575 		if(p->mark & (BRANCH|SYNC)) {
576 			sched(q1, p);
577 			q1 = p1;
578 			o = 0;
579 		}
580 		if(o >= NSCHED) {
581 			sched(q1, p);
582 			q1 = p1;
583 			o = 0;
584 		}
585 		q = p;
586 	}
587 }
588 
589 void
addnop(Prog * p)590 addnop(Prog *p)
591 {
592 	Prog *q;
593 
594 	q = prg();
595 	q->as = AORN;
596 	q->line = p->line;
597 	q->from.type = D_REG;
598 	q->from.reg = REGZERO;
599 	q->to.type = D_REG;
600 	q->to.reg = REGZERO;
601 
602 	q->link = p->link;
603 	p->link = q;
604 }
605 
606 void
initmuldiv(void)607 initmuldiv(void)
608 {
609 	Sym *s1, *s2, *s3, *s4, *s5;
610 	Prog *p;
611 
612 	s1 = lookup("_mul", 0);
613 	s2 = lookup("_div", 0);
614 	s3 = lookup("_divl", 0);
615 	s4 = lookup("_mod", 0);
616 	s5 = lookup("_modl", 0);
617 	for(p = firstp; p != P; p = p->link)
618 		if(p->as == ATEXT) {
619 			if(p->from.sym == s1)
620 				prog_mul = p;
621 			if(p->from.sym == s2)
622 				prog_div = p;
623 			if(p->from.sym == s3)
624 				prog_divl = p;
625 			if(p->from.sym == s4)
626 				prog_mod = p;
627 			if(p->from.sym == s5)
628 				prog_modl = p;
629 		}
630 	if(prog_mul == P) {
631 		diag("undefined: %s", s1->name);
632 		prog_mul = curtext;
633 	}
634 	if(prog_div == P) {
635 		diag("undefined: %s", s2->name);
636 		prog_div = curtext;
637 	}
638 	if(prog_divl == P) {
639 		diag("undefined: %s", s3->name);
640 		prog_divl = curtext;
641 	}
642 	if(prog_mod == P) {
643 		diag("undefined: %s", s4->name);
644 		prog_mod = curtext;
645 	}
646 	if(prog_modl == P) {
647 		diag("undefined: %s", s5->name);
648 		prog_modl = curtext;
649 	}
650 }
651