]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/kc/peep.c
abaco: cleanup, handle image/x-icon, don't use backspace as a hotkey, and remove...
[plan9front.git] / sys / src / cmd / kc / peep.c
1 #include "gc.h"
2
3 void
4 peep(void)
5 {
6         Reg *r, *r1, *r2;
7         Prog *p, *p1;
8         int t;
9 /*
10  * complete R structure
11  */
12         t = 0;
13         for(r=firstr; r!=R; r=r1) {
14                 r1 = r->link;
15                 if(r1 == R)
16                         break;
17                 p = r->prog->link;
18                 while(p != r1->prog)
19                 switch(p->as) {
20                 default:
21                         r2 = rega();
22                         r->link = r2;
23                         r2->link = r1;
24
25                         r2->prog = p;
26                         r2->p1 = r;
27                         r->s1 = r2;
28                         r2->s1 = r1;
29                         r1->p1 = r2;
30
31                         r = r2;
32                         t++;
33
34                 case ADATA:
35                 case AGLOBL:
36                 case ANAME:
37                 case ASIGNAME:
38                         p = p->link;
39                 }
40         }
41
42 loop1:
43         t = 0;
44         for(r=firstr; r!=R; r=r->link) {
45                 p = r->prog;
46                 if(p->as == AMOVW || p->as == AFMOVF || p->as == AFMOVD)
47                 if(regtyp(&p->to)) {
48                         if(regtyp(&p->from))
49                         if(p->from.type == p->to.type) {
50                                 if(copyprop(r)) {
51                                         excise(r);
52                                         t++;
53                                 } else
54                                 if(subprop(r) && copyprop(r)) {
55                                         excise(r);
56                                         t++;
57                                 }
58                         }
59                         if(regzer(&p->from))
60                         if(p->to.type == D_REG) {
61                                 p->from.type = D_REG;
62                                 p->from.reg = 0;
63                                 if(copyprop(r)) {
64                                         excise(r);
65                                         t++;
66                                 } else
67                                 if(subprop(r) && copyprop(r)) {
68                                         excise(r);
69                                         t++;
70                                 }
71                         }
72                 }
73         }
74         if(t)
75                 goto loop1;
76         /*
77          * look for MOVB x,R; MOVB R,R
78          */
79         for(r=firstr; r!=R; r=r->link) {
80                 p = r->prog;
81                 switch(p->as) {
82                 default:
83                         continue;
84                 case AMOVH:
85                 case AMOVHU:
86                 case AMOVB:
87                 case AMOVBU:
88                         if(p->to.type != D_REG)
89                                 continue;
90                         break;
91                 }
92                 r1 = r->link;
93                 if(r1 == R)
94                         continue;
95                 p1 = r1->prog;
96                 if(p1->as != p->as)
97                         continue;
98                 if(p1->from.type != D_REG || p1->from.reg != p->to.reg)
99                         continue;
100                 if(p1->to.type != D_REG || p1->to.reg != p->to.reg)
101                         continue;
102                 excise(r1);
103         }
104 }
105
106 void
107 excise(Reg *r)
108 {
109         Prog *p;
110
111         p = r->prog;
112         p->as = ANOP;
113         p->from = zprog.from;
114         p->to = zprog.to;
115         p->reg = zprog.reg; /**/
116 }
117
118 Reg*
119 uniqp(Reg *r)
120 {
121         Reg *r1;
122
123         r1 = r->p1;
124         if(r1 == R) {
125                 r1 = r->p2;
126                 if(r1 == R || r1->p2link != R)
127                         return R;
128         } else
129                 if(r->p2 != R)
130                         return R;
131         return r1;
132 }
133
134 Reg*
135 uniqs(Reg *r)
136 {
137         Reg *r1;
138
139         r1 = r->s1;
140         if(r1 == R) {
141                 r1 = r->s2;
142                 if(r1 == R)
143                         return R;
144         } else
145                 if(r->s2 != R)
146                         return R;
147         return r1;
148 }
149
150 regzer(Adr *a)
151 {
152
153         if(a->type == D_CONST)
154                 if(a->sym == S)
155                         if(a->offset == 0)
156                                 return 1;
157         if(a->type == D_REG)
158                 if(a->reg == 0)
159                         return 1;
160         return 0;
161 }
162
163 regtyp(Adr *a)
164 {
165
166         if(a->type == D_REG) {
167                 if(a->reg != 0)
168                         return 1;
169                 return 0;
170         }
171         if(a->type == D_FREG)
172                 return 1;
173         return 0;
174 }
175
176 /*
177  * the idea is to substitute
178  * one register for another
179  * from one MOV to another
180  *      MOV     a, R0
181  *      ADD     b, R0   / no use of R1
182  *      MOV     R0, R1
183  * would be converted to
184  *      MOV     a, R1
185  *      ADD     b, R1
186  *      MOV     R1, R0
187  * hopefully, then the former or latter MOV
188  * will be eliminated by copy propagation.
189  */
190 int
191 subprop(Reg *r0)
192 {
193         Prog *p;
194         Adr *v1, *v2;
195         Reg *r;
196         int t;
197
198         p = r0->prog;
199         v1 = &p->from;
200         if(!regtyp(v1))
201                 return 0;
202         v2 = &p->to;
203         if(!regtyp(v2))
204                 return 0;
205         for(r=uniqp(r0); r!=R; r=uniqp(r)) {
206                 if(uniqs(r) == R)
207                         break;
208                 p = r->prog;
209                 switch(p->as) {
210                 case AJMPL:
211                         return 0;
212
213                 case AADD:
214                 case ASUB:
215                 case ASLL:
216                 case ASRL:
217                 case ASRA:
218                 case AOR:
219                 case AAND:
220                 case AXOR:
221                 case AMUL:
222                 case ADIV:
223                 case ADIVL:
224                 case AMOD:
225                 case AMODL:
226
227                 case AFADDD:
228                 case AFADDF:
229                 case AFSUBD:
230                 case AFSUBF:
231                 case AFMULD:
232                 case AFMULF:
233                 case AFDIVD:
234                 case AFDIVF:
235                         if(p->to.type == v1->type)
236                         if(p->to.reg == v1->reg) {
237                                 if(p->reg == NREG)
238                                         p->reg = p->to.reg;
239                                 goto gotit;
240                         }
241                         break;
242
243                 case AFMOVF:
244                 case AFMOVD:
245                 case AMOVW:
246                         if(p->to.type == v1->type)
247                         if(p->to.reg == v1->reg)
248                                 goto gotit;
249                         break;
250                 }
251                 if(copyau(&p->from, v2) ||
252                    copyau1(p, v2) ||
253                    copyau(&p->to, v2))
254                         break;
255                 if(copysub(&p->from, v1, v2, 0) ||
256                    copysub1(p, v1, v2, 0) ||
257                    copysub(&p->to, v1, v2, 0))
258                         break;
259         }
260         return 0;
261
262 gotit:
263         copysub(&p->to, v1, v2, 1);
264         if(debug['P']) {
265                 print("gotit: %D->%D\n%P", v1, v2, r->prog);
266                 if(p->from.type == v2->type)
267                         print(" excise");
268                 print("\n");
269         }
270         for(r=uniqs(r); r!=r0; r=uniqs(r)) {
271                 p = r->prog;
272                 copysub(&p->from, v1, v2, 1);
273                 copysub1(p, v1, v2, 1);
274                 copysub(&p->to, v1, v2, 1);
275                 if(debug['P'])
276                         print("%P\n", r->prog);
277         }
278         t = v1->reg;
279         v1->reg = v2->reg;
280         v2->reg = t;
281         if(debug['P'])
282                 print("%P last\n", r->prog);
283         return 1;
284 }
285
286 /*
287  * The idea is to remove redundant copies.
288  *      v1->v2  F=0
289  *      (use v2 s/v2/v1/)*
290  *      set v1  F=1
291  *      use v2  return fail
292  *      -----------------
293  *      v1->v2  F=0
294  *      (use v2 s/v2/v1/)*
295  *      set v1  F=1
296  *      set v2  return success
297  */
298 int
299 copyprop(Reg *r0)
300 {
301         Prog *p;
302         Adr *v1, *v2;
303         Reg *r;
304
305         p = r0->prog;
306         v1 = &p->from;
307         v2 = &p->to;
308         if(copyas(v1, v2))
309                 return 1;
310         for(r=firstr; r!=R; r=r->link)
311                 r->active = 0;
312         return copy1(v1, v2, r0->s1, 0);
313 }
314
315 copy1(Adr *v1, Adr *v2, Reg *r, int f)
316 {
317         int t;
318         Prog *p;
319
320         if(r->active) {
321                 if(debug['P'])
322                         print("act set; return 1\n");
323                 return 1;
324         }
325         r->active = 1;
326         if(debug['P'])
327                 print("copy %D->%D f=%d\n", v1, v2, f);
328         for(; r != R; r = r->s1) {
329                 p = r->prog;
330                 if(debug['P'])
331                         print("%P", p);
332                 if(!f && uniqp(r) == R) {
333                         f = 1;
334                         if(debug['P'])
335                                 print("; merge; f=%d", f);
336                 }
337                 t = copyu(p, v2, A);
338                 switch(t) {
339                 case 2: /* rar, cant split */
340                         if(debug['P'])
341                                 print("; %Drar; return 0\n", v2);
342                         return 0;
343
344                 case 3: /* set */
345                         if(debug['P'])
346                                 print("; %Dset; return 1\n", v2);
347                         return 1;
348
349                 case 1: /* used, substitute */
350                 case 4: /* use and set */
351                         if(f) {
352                                 if(!debug['P'])
353                                         return 0;
354                                 if(t == 4)
355                                         print("; %Dused+set and f=%d; return 0\n", v2, f);
356                                 else
357                                         print("; %Dused and f=%d; return 0\n", v2, f);
358                                 return 0;
359                         }
360                         if(copyu(p, v2, v1)) {
361                                 if(debug['P'])
362                                         print("; sub fail; return 0\n");
363                                 return 0;
364                         }
365                         if(debug['P'])
366                                 print("; sub%D/%D", v2, v1);
367                         if(t == 4) {
368                                 if(debug['P'])
369                                         print("; %Dused+set; return 1\n", v2);
370                                 return 1;
371                         }
372                         break;
373                 }
374                 if(!f) {
375                         t = copyu(p, v1, A);
376                         if(!f && (t == 2 || t == 3 || t == 4)) {
377                                 f = 1;
378                                 if(debug['P'])
379                                         print("; %Dset and !f; f=%d", v1, f);
380                         }
381                 }
382                 if(debug['P'])
383                         print("\n");
384                 if(r->s2)
385                         if(!copy1(v1, v2, r->s2, f))
386                                 return 0;
387         }
388         return 1;
389 }
390
391 /*
392  * return
393  * 1 if v only used (and substitute),
394  * 2 if read-alter-rewrite
395  * 3 if set
396  * 4 if set and used
397  * 0 otherwise (not touched)
398  */
399 int
400 copyu(Prog *p, Adr *v, Adr *s)
401 {
402
403         switch(p->as) {
404
405         default:
406                 if(debug['P'])
407                         print(" (???)");
408                 return 2;
409
410
411         case ANOP:      /* read, write */
412         case AMOVW:
413         case AMOVH:
414         case AMOVHU:
415         case AMOVB:
416         case AMOVBU:
417
418         case AFMOVF:
419         case AFMOVD:
420         case AFMOVDW:
421         case AFMOVWD:
422         case AFMOVFW:
423         case AFMOVWF:
424         case AFMOVFD:
425         case AFMOVDF:
426                 if(s != A) {
427                         if(copysub(&p->from, v, s, 1))
428                                 return 1;
429                         if(!copyas(&p->to, v))
430                                 if(copysub(&p->to, v, s, 1))
431                                         return 1;
432                         return 0;
433                 }
434                 if(copyas(&p->to, v)) {
435                         if(copyau(&p->from, v))
436                                 return 4;
437                         return 3;
438                 }
439                 if(copyau(&p->from, v))
440                         return 1;
441                 if(copyau(&p->to, v))
442                         return 1;
443                 return 0;
444
445         case AADD:      /* read read write */
446         case ASUB:
447         case ASLL:
448         case ASRL:
449         case ASRA:
450         case AOR:
451         case AAND:
452         case AXOR:
453         case AMUL:
454         case ADIV:
455         case ADIVL:
456         case AMOD:
457         case AMODL:
458
459         case AFADDF:
460         case AFADDD:
461         case AFSUBF:
462         case AFSUBD:
463         case AFMULF:
464         case AFMULD:
465         case AFDIVF:
466         case AFDIVD:
467                 if(s != A) {
468                         if(copysub(&p->from, v, s, 1))
469                                 return 1;
470                         if(copysub1(p, v, s, 1))
471                                 return 1;
472                         if(!copyas(&p->to, v))
473                                 if(copysub(&p->to, v, s, 1))
474                                         return 1;
475                         return 0;
476                 }
477                 if(copyas(&p->to, v)) {
478                         if(p->reg == NREG)
479                                 p->reg = p->to.reg;
480                         if(copyau(&p->from, v))
481                                 return 4;
482                         if(copyau1(p, v))
483                                 return 4;
484                         return 3;
485                 }
486                 if(copyau(&p->from, v))
487                         return 1;
488                 if(copyau1(p, v))
489                         return 1;
490                 if(copyau(&p->to, v))
491                         return 1;
492                 return 0;
493
494         case ABA:       /* no reference */
495         case ABCC:
496         case ABCS:
497         case ABE:
498         case ABG:
499         case ABGE:
500         case ABGU:
501         case ABL:
502         case ABLE:
503         case ABLEU:
504         case ABN:
505         case ABNE:
506         case ABNEG:
507         case ABPOS:
508         case ABVC:
509         case ABVS:
510         case AFBA:
511         case AFBE:
512         case AFBG:
513         case AFBGE:
514         case AFBL:
515         case AFBLE:
516         case AFBNE:
517         case AFBN:
518         case AFBLG:
519         case AFBO:
520         case AFBU:
521         case AFBUE:
522         case AFBUG:
523         case AFBUGE:
524         case AFBUL:
525         case AFBULE:
526                 break;
527
528         case ACMP:      /* read read */
529         case AFCMPD:
530         case AFCMPF:
531                 if(s != A) {
532                         if(copysub(&p->from, v, s, 1))
533                                 return 1;
534                         return copysub(&p->to, v, s, 1);
535                 }
536                 if(copyau(&p->from, v))
537                         return 1;
538                 if(copyau(&p->to, v))
539                         return 1;
540                 break;
541
542         case AJMP:      /* funny */
543                 if(s != A) {
544                         if(copysub(&p->to, v, s, 1))
545                                 return 1;
546                         return 0;
547                 }
548                 if(copyau(&p->to, v))
549                         return 1;
550                 return 0;
551
552         case ARETURN:   /* funny */
553                 if(v->type == D_REG)
554                         if(v->reg == REGRET)
555                                 return 2;
556                 if(v->type == D_FREG)
557                         if(v->reg == FREGRET)
558                                 return 2;
559
560         case AJMPL:     /* funny */
561                 if(v->type == D_REG) {
562                         if(v->reg <= REGEXT && v->reg > exregoffset)
563                                 return 2;
564                         if(v->reg == REGARG)
565                                 return 2;
566                 }
567                 if(v->type == D_FREG) {
568                         if(v->reg <= FREGEXT && v->reg > exfregoffset)
569                                 return 2;
570                 }
571
572                 if(s != A) {
573                         if(copysub(&p->to, v, s, 1))
574                                 return 1;
575                         return 0;
576                 }
577                 if(copyau(&p->to, v))
578                         return 4;
579                 return 3;
580
581         case ATEXT:     /* funny */
582                 if(v->type == D_REG)
583                         if(v->reg == REGARG)
584                                 return 3;
585                 return 0;
586         }
587         return 0;
588 }
589
590 int
591 a2type(Prog *p)
592 {
593
594         switch(p->as) {
595         case AADD:
596         case ASUB:
597         case ASLL:
598         case ASRL:
599         case ASRA:
600         case AOR:
601         case AAND:
602         case AXOR:
603         case AMUL:
604         case ADIV:
605         case ADIVL:
606         case AMOD:
607         case AMODL:
608                 return D_REG;
609
610         case AFADDF:
611         case AFADDD:
612         case AFSUBF:
613         case AFSUBD:
614         case AFMULF:
615         case AFMULD:
616         case AFDIVF:
617         case AFDIVD:
618                 return D_FREG;
619         }
620         return D_NONE;
621 }
622
623 /*
624  * direct reference,
625  * could be set/use depending on
626  * semantics
627  */
628 int
629 copyas(Adr *a, Adr *v)
630 {
631
632         if(regtyp(v))
633                 if(a->type == v->type)
634                 if(a->reg == v->reg)
635                         return 1;
636         return 0;
637 }
638
639 /*
640  * either direct or indirect
641  */
642 int
643 copyau(Adr *a, Adr *v)
644 {
645
646         if(copyas(a, v))
647                 return 1;
648         if(v->type == D_REG)
649                 if(a->type == D_OREG)
650                         if(v->reg == a->reg)
651                                 return 1;
652         return 0;
653 }
654
655 int
656 copyau1(Prog *p, Adr *v)
657 {
658
659         if(regtyp(v))
660                 if(p->from.type == v->type || p->to.type == v->type)
661                 if(p->reg == v->reg) {
662                         if(a2type(p) != v->type)
663                                 print("botch a2type %P\n", p);
664                         return 1;
665                 }
666         return 0;
667 }
668
669 /*
670  * substitute s for v in a
671  * return failure to substitute
672  */
673 int
674 copysub(Adr *a, Adr *v, Adr *s, int f)
675 {
676
677         if(f)
678         if(copyau(a, v))
679                 a->reg = s->reg;
680         return 0;
681 }
682
683 int
684 copysub1(Prog *p1, Adr *v, Adr *s, int f)
685 {
686
687         if(f)
688         if(copyau1(p1, v))
689                 p1->reg = s->reg;
690         return 0;
691 }