Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20040513193347

Diff

Diff from 1.2 to:

Annotations

Annotate by Age | Author | Mixed | None

Annotated File View

ragge
1.2
1 /*      $Id: optim2.c,v 1.2 2004/05/13 19:33:47 ragge Exp $     */
ragge
1.1
2 /*
3  * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "pass2.h"
30 #include "external.h"
31
32 extern int saving;
33
34 void saveip(struct interpass *ip);
35 void deljumps(void);
36 void deltemp(NODE *p);
37 void optdump(struct interpass *ip);
38
39 static SIMPLEQ_HEAD(, interpassipole = SIMPLEQ_HEAD_INITIALIZER(ipole);
40
41 static struct rsv {
42         struct rsv *next;
43         int fpoff;
44         TWORD type;
45         int use;
46 } *rsv;
47
48 static void
49 addcand(TWORD typeint offint avoid)
50 {
51         struct rsv *w = rsv;
52
53         while (w != NULL) {
54                 if (w->type == type && w->fpoff == off) {
55                         if (avoid)
56                                 w->use = -1;
57                         else if (w->use > 0)
58                                 w->use++;
59                         return;
60                 }
61                 w = w->next;
62         }
63         w = tmpalloc(sizeof(*w));
64         w->type = type;
65         w->fpoff = off;
66         w->use = avoid ? -1 : 1;
67         w->next = rsv;
68         rsv = w;
69 }
70
71 /*
72  * walk through the tree and count the number of (possible)
73  * temporary nodes.
74  */
75 static void
76 cntuse(NODE *p)
77 {
78         NODE *l = p->n_left;
79         NODE *r = p->n_right;
80
81         if (p->n_op == UMUL && l->n_op == REG && l->n_rval == FPREG) {
82                 /* found a candidate for register */
83                 addcand(p->n_type0ISVOL(p->n_qual << TSHIFT));
84         } else if (p->n_op == UMUL && l->n_op == PLUS &&
85             l->n_right->n_op == ICON && 
86              (l->n_left->n_op == REG && l->n_left->n_rval == FPREG)) {
87                 /* The same as above */
88                 addcand(p->n_typel->n_right->n_lval,
89                     ISVOL(p->n_qual << TSHIFT));
90         } else if (p->n_op == PLUS && l->n_op == REG && l->n_rval == FPREG &&
91             p->n_right->n_op == ICON) {
92                 /* Address taken of temporary, avoid register */
93                 addcand(DECREF(p->n_type), r->n_lval1);
94         } else {
95                 if (optype(p->n_op) == BITYPE)
96                         cntuse(r);
97                 if (optype(p->n_op) != LTYPE)
98                         cntuse(l);
99         }
100 }
101
102 /*
ragge
1.2
103  * Insert a node into the register stack.
104  */
105 static void
106 insert(struct rsv *wstruct rsv **savedint maxregs)
107 {
108         int ijsize;
109
110         size = szty(w->type);
111
112         /* Find reg move position */
113         for (i = 0i < maxregsi++) {
114                 if (saved[i] == NULL)
115                         continue;
116                 if (saved[i]->use > w->use)
117                         break;
118         }
119         /* Move down other regs */
120         for (j = sizej < ij++)
121                 saved[j-size] = saved[j];
122
123         /* Insert new reg pointer */
124         if (i-size >= 0) {
125                 saved[i-size] = w;
126                 for (j = i-size+1j < ij++)
127                         saved[j] = NULL;
128         }
129 }
130
131 /* Help routine to rconvert() */
132 static int
133 matches(TWORD typeint offstruct rsv **rsvint maxregs)
134 {
135         int i;
136
137         for (i = 0i < maxregsi++)
138                 if (rsv[i] && rsv[i]->type == type && rsv[i]->fpoff == off)
139                         return i;
140         return -1;
141 }
142
143 /* Help routine to rconvert() */
144 static void
145 modify(NODE *pint reg)
146 {
147         tfree(p->n_left);
148         p->n_op = REG;
149         p->n_rval = p->n_rall = reg + MINRVAR;
150         p->n_lval = 0;
151 }
152
153 /*
154  * walk through the tree and convert nodes to registers
155  */
156 static void
157 rconvert(NODE *pstruct rsv **rsvint maxregs)
158 {
159         NODE *l = p->n_left;
160         NODE *r = p->n_right;
161         int i;
162
163         if (p->n_op == UMUL && l->n_op == REG && l->n_rval == FPREG) {
164                 /* found a candidate for register */
165                 if ((i = matches(p->n_type0rsvmaxregs)) >= 0)
166                         modify(pi);
167         } else if (p->n_op == UMUL && l->n_op == PLUS &&
168             l->n_right->n_op == ICON && 
169              (l->n_left->n_op == REG && l->n_left->n_rval == FPREG)) {
170                 /* The same as above */
171                 if ((i = matches(p->n_type,
172                     l->n_right->n_lvalrsvmaxregs)) >= 0)
173                         modify(pi);
174 #if 0
175         } else if (p->n_op == PLUS && l->n_op == REG && l->n_rval == FPREG &&
176             p->n_right->n_op == ICON) {
177                 /* Address taken of temporary, avoid register */
178                 addcand(DECREF(p->n_type), r->n_lval1);
179 #endif
180         } else {
181                 if (optype(p->n_op) == BITYPE)
182                         rconvert(rrsvmaxregs);
183                 if (optype(p->n_op) != LTYPE)
184                         rconvert(lrsvmaxregs);
185         }
186 }
187
188 /*
ragge
1.1
189  * Assign non-temporary registers to variables.
190  * Cannot do it if:
191  * - address is taken of the temporary
192  * - variable is declared "volatile".
193  */
ragge
1.2
194 static int
ragge
1.1
195 asgregs(void)
196 {
197         struct interpass *ip;
ragge
1.2
198         struct rsv *w, **saved;
199         int imaxregs = MAXRVAR - MINRVAR + 1;
ragge
1.1
200
ragge
1.2
201         if (maxregs == 0)
202                 return MAXRVAR/* No register usage */
ragge
1.1
203         rsv = NULL;
204
205         /* Loop over the function to do a usage count */
206         SIMPLEQ_FOREACH(ip, &ipolesqelem) {
207                 if (ip->type != IP_NODE)
208                         continue;
209                 cntuse(ip->ip_node);
210         }
211         /* Check which nodes that shall be converted to registers */
ragge
1.2
212         saved = tmpalloc(sizeof(struct rsv *) * maxregs);
213         memset(saved0sizeof(struct rsv *) * maxregs);
ragge
1.1
214         w = rsv;
215         for (w = rsvww = w->next) {
216                 if (w->use < 0)
ragge
1.2
217                         continue/* Not allowed to be in register */
218
219                 /* XXX check here if type is allowed to be in register */
220
221                 insert(wsavedmaxregs);
ragge
1.1
222         }
223
224         /* Convert found nodes to registers */
ragge
1.2
225         SIMPLEQ_FOREACH(ip, &ipolesqelem) {
226                 if (ip->type != IP_NODE)
227                         continue;
228                 rconvert(ip->ip_nodesavedmaxregs);
229         }
230         for (i = 0i < maxregsi++)
231                 if (saved[i] != NULL)
232                         break;
233         return MINRVAR+i-1;
ragge
1.1
234 }
235
236 void
237 saveip(struct interpass *ip)
238 {
239         struct interpass *prol;
ragge
1.2
240         int regs;
ragge
1.1
241
242         SIMPLEQ_INSERT_TAIL(&ipoleipsqelem);
243
244         if (ip->type != IP_EPILOG)
245                 return;
246         saving = -1;
247
248         deljumps();     /* Delete redundant jumps and dead code */
ragge
1.2
249         regs = asgregs();       /* Assign non-temporary registers */
250
251 #ifdef PCC_DEBUG
252         if (ip->ip_regs != MAXRVAR)
253                 comperr("register error");
254 #endif
ragge
1.1
255
256         prol = SIMPLEQ_FIRST(&ipole);
257         prol->ip_auto = ip->ip_auto;
ragge
1.2
258         prol->ip_regs = ip->ip_regs = regs;
ragge
1.1
259
260 #ifdef MYOPTIM
261         myoptim(prol);
262 #endif
263
264         while ((ip = SIMPLEQ_FIRST(&ipole))) {
265                 SIMPLEQ_REMOVE_HEAD(&ipolesqelem);
266                 pass2_compile(ip);
267         }
268 }
269
270 void
271 deljumps()
272 {
273         struct interpass *ip, *n;
274         int gotone;
275
276 again:  gotone = 0;
277
278         SIMPLEQ_FOREACH(ip, &ipolesqelem) {
279                 if (ip->type == IP_EPILOG)
280                         return;
281                 if (ip->type != IP_NODE)
282                         continue;
283                 n = ip->sqelem.sqe_next;
284                 /* Check for nodes without side effects */
285                 if (ip->ip_node->n_op != GOTO)
286                         continue;
287                 switch (n->type) {
288                 case IP_NODE:
289                         tfree(n->ip_node);
290                         ip->sqelem.sqe_next = n->sqelem.sqe_next;
291                         break;
292                 case IP_DEFLAB:
293                         if (ip->ip_node->n_left->n_lval != n->ip_lbl)
294                                 continue;
295                         tfree(ip->ip_node);
296                         *ip = *n;
297                         break;
298                 default:
299                         continue;
300                 }
301                 gotone = 1;
302         }
303         if (gotone)
304                 goto again;
305 }
306
307 void
308 optdump(struct interpass *ip)
309 {
310         static char *nm[] = { "node""prolog""newblk""epilog""locctr",
311                 "deflab""defnam""asm" };
312         printf("type %s\n"nm[ip->type-1]);
313         switch (ip->type) {
314         case IP_NODE:
315                 fwalk(ip->ip_nodee2print0);
316                 break;
317         case IP_DEFLAB:
318                 printf("label " LABFMT "\n"ip->ip_lbl);
319                 break;
320         case IP_ASM:
321                 printf(": %s\n"ip->ip_asm);
322                 break;
323         }
324 }
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-10-31 23:03 +0100