]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/6c/sgen.c
14e5f3c7e289de940f42d3d4e371803ef28a8505
[plan9front.git] / sys / src / cmd / 6c / sgen.c
1 #include "gc.h"
2
3 void
4 noretval(int n)
5 {
6
7         if(n & 1) {
8                 gins(ANOP, Z, Z);
9                 p->to.type = REGRET;
10         }
11         if(n & 2) {
12                 gins(ANOP, Z, Z);
13                 p->to.type = FREGRET;
14         }
15 }
16
17 /* welcome to commute */
18 static void
19 commute(Node *n)
20 {
21         Node *l, *r;
22
23         l = n->left;
24         r = n->right;
25         if(r->complex > l->complex) {
26                 n->left = r;
27                 n->right = l;
28         }
29 }
30
31 void
32 indexshift(Node *n)
33 {
34         int g;
35
36         if(!typechlpv[n->type->etype])
37                 return;
38         simplifyshift(n);
39         if(n->op == OASHL && n->right->op == OCONST){
40                 g = vconst(n->right);
41                 if(g >= 0 && g <= 3)
42                         n->addable = 7;
43         }
44 }
45
46 /*
47  *      calculate addressability as follows
48  *              NAME ==> 10/11          name+value(SB/SP)
49  *              REGISTER ==> 12         register
50  *              CONST ==> 20            $value
51  *              *(20) ==> 21            value
52  *              &(10) ==> 13            $name+value(SB)
53  *              &(11) ==> 1             $name+value(SP)
54  *              (13) + (20) ==> 13      fold constants
55  *              (1) + (20) ==> 1        fold constants
56  *              *(13) ==> 10            back to name
57  *              *(1) ==> 11             back to name
58  *
59  *              (20) * (X) ==> 7        multiplier in indexing
60  *              (X,7) + (13,1) ==> 8    adder in indexing (addresses)
61  *              (8) ==> &9(OINDEX)      index, almost addressable
62  *
63  *      calculate complexity (number of registers)
64  */
65 void
66 xcom(Node *n)
67 {
68         Node *l, *r;
69         int g;
70
71         if(n == Z)
72                 return;
73         l = n->left;
74         r = n->right;
75         n->complex = 0;
76         n->addable = 0;
77         switch(n->op) {
78         case OCONST:
79                 n->addable = 20;
80                 break;
81
82         case ONAME:
83                 n->addable = 10;
84                 if(n->class == CPARAM || n->class == CAUTO)
85                         n->addable = 11;
86                 break;
87
88         case OREGISTER:
89                 n->addable = 12;
90                 break;
91
92         case OINDREG:
93                 n->addable = 12;
94                 break;
95
96         case OADDR:
97                 xcom(l);
98                 if(l->addable == 10)
99                         n->addable = 13;
100                 else
101                 if(l->addable == 11)
102                         n->addable = 1;
103                 break;
104
105         case OADD:
106                 xcom(l);
107                 xcom(r);
108                 if(n->type->etype != TIND)
109                         break;
110
111                 switch(r->addable) {
112                 case 20:
113                         switch(l->addable) {
114                         case 1:
115                         case 13:
116                         commadd:
117                                 l->type = n->type;
118                                 *n = *l;
119                                 l = new(0, Z, Z);
120                                 *l = *(n->left);
121                                 l->xoffset += r->vconst;
122                                 n->left = l;
123                                 goto brk;
124                         }
125                         break;
126
127                 case 1:
128                 case 13:
129                 case 10:
130                 case 11:
131                         /* l is the base, r is the index */
132                         if(l->addable != 20)
133                                 n->addable = 8;
134                         break;
135                 }
136                 switch(l->addable) {
137                 case 20:
138                         switch(r->addable) {
139                         case 13:
140                         case 1:
141                                 r = n->left;
142                                 l = n->right;
143                                 n->left = l;
144                                 n->right = r;
145                                 goto commadd;
146                         }
147                         break;
148
149                 case 13:
150                 case 1:
151                 case 10:
152                 case 11:
153                         /* r is the base, l is the index */
154                         if(r->addable != 20)
155                                 n->addable = 8;
156                         break;
157                 }
158                 if(n->addable == 8 && !side(n)) {
159                         indx(n);
160                         l = new1(OINDEX, idx.basetree, idx.regtree);
161                         l->scale = idx.scale;
162                         l->addable = 9;
163                         l->complex = l->right->complex;
164                         l->type = l->left->type;
165                         n->op = OADDR;
166                         n->left = l;
167                         n->right = Z;
168                         n->addable = 8;
169                         break;
170                 }
171                 break;
172
173         case OINDEX:
174                 xcom(l);
175                 xcom(r);
176                 n->addable = 9;
177                 break;
178
179         case OIND:
180                 xcom(l);
181                 if(l->op == OADDR) {
182                         l = l->left;
183                         l->type = n->type;
184                         *n = *l;
185                         return;
186                 }
187                 switch(l->addable) {
188                 case 20:
189                         n->addable = 21;
190                         break;
191                 case 1:
192                         n->addable = 11;
193                         break;
194                 case 13:
195                         n->addable = 10;
196                         break;
197                 }
198                 break;
199
200         case OASHL:
201                 xcom(l);
202                 xcom(r);
203                 indexshift(n);
204                 break;
205
206         case OMUL:
207         case OLMUL:
208                 xcom(l);
209                 xcom(r);
210                 g = vlog(l);
211                 if(g >= 0) {
212                         n->left = r;
213                         n->right = l;
214                         r = n->right;
215                 }
216                 g = vlog(r);
217                 if(g >= 0) {
218                         n->op = OASHL;
219                         r->vconst = g;
220                         r->type = types[TINT];
221                         indexshift(n);
222                         break;
223                 }
224                 commute(n);
225                 break;
226
227         case OASLDIV:
228                 xcom(l);
229                 xcom(r);
230                 g = vlog(r);
231                 if(g >= 0) {
232                         n->op = OASLSHR;
233                         r->vconst = g;
234                         r->type = types[TINT];
235                 }
236                 break;
237
238         case OLDIV:
239                 xcom(l);
240                 xcom(r);
241                 g = vlog(r);
242                 if(g >= 0) {
243                         n->op = OLSHR;
244                         r->vconst = g;
245                         r->type = types[TINT];
246                         indexshift(n);
247                         break;
248                 }
249                 break;
250
251         case OASLMOD:
252                 xcom(l);
253                 xcom(r);
254                 g = vlog(r);
255                 if(g >= 0) {
256                         n->op = OASAND;
257                         r->vconst--;
258                 }
259                 break;
260
261         case OLMOD:
262                 xcom(l);
263                 xcom(r);
264                 g = vlog(r);
265                 if(g >= 0) {
266                         n->op = OAND;
267                         r->vconst--;
268                 }
269                 break;
270
271         case OASMUL:
272         case OASLMUL:
273                 xcom(l);
274                 xcom(r);
275                 g = vlog(r);
276                 if(g >= 0) {
277                         n->op = OASASHL;
278                         r->vconst = g;
279                 }
280                 break;
281
282         case OLSHR:
283         case OASHR:
284                 xcom(l);
285                 xcom(r);
286                 indexshift(n);
287                 break;
288
289         case OOR:
290                 xcom(l);
291                 xcom(r);
292                 rolor(n);
293                 break;
294
295         default:
296                 if(l != Z)
297                         xcom(l);
298                 if(r != Z)
299                         xcom(r);
300                 break;
301         }
302 brk:
303         if(n->addable >= 10)
304                 return;
305         l = n->left;
306         r = n->right;
307         if(l != Z)
308                 n->complex = l->complex;
309         if(r != Z) {
310                 if(r->complex == n->complex)
311                         n->complex = r->complex+1;
312                 else
313                 if(r->complex > n->complex)
314                         n->complex = r->complex;
315         }
316         if(n->complex == 0)
317                 n->complex++;
318
319         switch(n->op) {
320
321         case OFUNC:
322                 n->complex = FNX;
323                 break;
324
325         case OCAST:
326                 if(l->type->etype == TUVLONG && typefd[n->type->etype])
327                         n->complex += 2;
328                 break;
329
330         case OLMOD:
331         case OMOD:
332         case OLMUL:
333         case OLDIV:
334         case OMUL:
335         case ODIV:
336         case OASLMUL:
337         case OASLDIV:
338         case OASLMOD:
339         case OASMUL:
340         case OASDIV:
341         case OASMOD:
342                 if(r->complex >= l->complex) {
343                         n->complex = l->complex + 3;
344                         if(r->complex > n->complex)
345                                 n->complex = r->complex;
346                 } else {
347                         n->complex = r->complex + 3;
348                         if(l->complex > n->complex)
349                                 n->complex = l->complex;
350                 }
351                 break;
352
353         case OROL:
354         case OLSHR:
355         case OASHL:
356         case OASHR:
357         case OASLSHR:
358         case OASASHL:
359         case OASASHR:
360                 if(r->complex >= l->complex) {
361                         n->complex = l->complex + 2;
362                         if(r->complex > n->complex)
363                                 n->complex = r->complex;
364                 } else {
365                         n->complex = r->complex + 2;
366                         if(l->complex > n->complex)
367                                 n->complex = l->complex;
368                 }
369                 break;
370
371         case OADD:
372         case OXOR:
373         case OAND:
374         case OOR:
375                 /*
376                  * immediate operators, make const on right
377                  */
378                 if(l->op == OCONST) {
379                         n->left = r;
380                         n->right = l;
381                 }
382                 break;
383
384         case OEQ:
385         case ONE:
386         case OLE:
387         case OLT:
388         case OGE:
389         case OGT:
390         case OHI:
391         case OHS:
392         case OLO:
393         case OLS:
394                 /*
395                  * compare operators, make const on left
396                  */
397                 if(r->op == OCONST) {
398                         n->left = r;
399                         n->right = l;
400                         n->op = invrel[relindex(n->op)];
401                 }
402                 break;
403         }
404 }
405
406 void
407 indx(Node *n)
408 {
409         Node *l, *r;
410
411         if(debug['x'])
412                 prtree(n, "indx");
413
414         l = n->left;
415         r = n->right;
416         if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
417                 n->right = l;
418                 n->left = r;
419                 l = r;
420                 r = n->right;
421         }
422         if(l->addable != 7) {
423                 idx.regtree = l;
424                 idx.scale = 1;
425         } else
426         if(l->right->addable == 20) {
427                 idx.regtree = l->left;
428                 idx.scale = 1 << l->right->vconst;
429         } else
430         if(l->left->addable == 20) {
431                 idx.regtree = l->right;
432                 idx.scale = 1 << l->left->vconst;
433         } else
434                 diag(n, "bad index");
435
436         idx.basetree = r;
437         if(debug['x']) {
438                 print("scale = %d\n", idx.scale);
439                 prtree(idx.regtree, "index");
440                 prtree(idx.basetree, "base");
441         }
442 }