]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/kl/noop.c
merge
[plan9front.git] / sys / src / cmd / kl / noop.c
1 #include        "l.h"
2
3 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
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
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 }