* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / mip / regs.c
blobaf73052c6ebaae0e43386697c61a84b46aa30930
1 /* $Id: regs.c,v 1.216.2.1 2011/02/22 18:38:08 ragge Exp $ */
2 /*
3 * Copyright (c) 2005 Anders Magnusson (ragge@ludd.luth.se).
4 * All rights reserved.
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
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.
29 #include "pass2.h"
30 #include <string.h>
31 #ifdef HAVE_STRINGS_H
32 #include <strings.h>
33 #endif
34 #ifdef HAVE_STDINT_H
35 #include <stdint.h>
36 #endif
37 #include <stdlib.h>
39 #define MAXLOOP 20 /* Max number of allocation loops XXX 3 should be enough */
41 #ifndef MAX
42 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
43 #endif
46 * New-style register allocator using graph coloring.
47 * The design is based on the George and Appel paper
48 * "Iterated Register Coalescing", ACM Transactions, No 3, May 1996.
51 #define BITALLOC(ptr,all,sz) { \
52 int sz__s = BIT2BYTE(sz); ptr = all(sz__s); memset(ptr, 0, sz__s); }
54 #undef COMPERR_PERM_MOVE
55 #ifdef PCC_DEBUG
56 #define RDEBUG(x) if (rdebug) printf x
57 #define RRDEBUG(x) if (rdebug > 1) printf x
58 #define RPRINTIP(x) if (rdebug) printip(x)
59 #define RDEBUGX(x) x
60 #define UDEBUG(x) if (udebug) printf x
61 #define BDEBUG(x) if (b2debug) printf x
62 #define BBDEBUG(x) if (b2debug > 1) printf x
63 #else
64 #define RDEBUG(x)
65 #define RRDEBUG(x)
66 #define RPRINTIP(x)
67 #define RDEBUGX(x)
68 #define UDEBUG(x)
69 #define BDEBUG(x)
70 #define BBDEBUG(x)
71 #endif
73 #define VALIDREG(p) (p->n_op == REG && TESTBIT(validregs, regno(p)))
76 * Data structure overview for this implementation of graph coloring:
78 * Each temporary (called "node") is described by the type REGW.
79 * Space for all nodes is allocated initially as an array, so
80 * the nodes can be can be referenced both by the node number and
81 * by pointer.
83 * All moves are represented by the type REGM, allocated when needed.
85 * The "live" set used during graph building is represented by a bitset.
87 * Interference edges are represented by struct AdjSet, hashed and linked
88 * from index into the edgehash array.
90 * A mapping from each node to the moves it is assiciated with is
91 * maintained by an array moveList which for each node number has a linked
92 * list of MOVL types, each pointing to a REGM.
94 * Adjacency list is maintained by the adjList array, indexed by the
95 * node number. Each adjList entry points to an ADJL type, and is a
96 * single-linked list for all adjacent nodes.
98 * degree, alias and color are integer arrays indexed by node number.
102 * linked list of adjacent nodes.
104 typedef struct regw3 {
105 struct regw3 *r_next;
106 struct regw *a_temp;
107 } ADJL;
110 * Structure describing a move.
112 typedef struct regm {
113 DLIST_ENTRY(regm) link;
114 struct regw *src, *dst;
115 int queue;
116 } REGM;
118 typedef struct movlink {
119 struct movlink *next;
120 REGM *regm;
121 } MOVL;
124 * Structure describing a temporary.
126 typedef struct regw {
127 DLIST_ENTRY(regw) link;
128 ADJL *r_adjList; /* linked list of adjacent nodes */
129 int r_class; /* this nodes class */
130 int r_nclass[NUMCLASS+1]; /* count of adjacent classes */
131 struct regw *r_alias; /* aliased temporary */
132 int r_color; /* final node color */
133 struct regw *r_onlist; /* which work list this node belongs to */
134 MOVL *r_moveList; /* moves associated with this node */
135 #ifdef PCC_DEBUG
136 int nodnum; /* Debug number */
137 #endif
138 } REGW;
141 * Worklists, a node is always on exactly one of these lists.
143 static REGW precolored, simplifyWorklist, freezeWorklist, spillWorklist,
144 spilledNodes, coalescedNodes, coloredNodes, selectStack;
145 static REGW initial, *nblock;
146 static void insnwalk(NODE *p);
147 #ifdef PCC_DEBUG
148 int use_regw;
149 int nodnum = 100;
150 #define SETNUM(x) (x)->nodnum = nodnum++
151 #define ASGNUM(x) (x)->nodnum
152 #else
153 #define SETNUM(x)
154 #define ASGNUM(x)
155 #endif
157 #define ALLNEEDS (NACOUNT|NBCOUNT|NCCOUNT|NDCOUNT|NECOUNT|NFCOUNT|NGCOUNT)
159 /* XXX */
160 REGW *ablock;
162 static int tempmin, tempmax, basetemp, xbits;
164 * nsavregs is an array that matches the permregs array.
165 * Each entry in the array may have the values:
166 * 0 : register coalesced, just ignore.
167 * 1 : save register on stack
168 * If the entry is 0 but the resulting color differs from the
169 * corresponding permregs index, add moves.
170 * XXX - should be a bitfield!
172 static int *nsavregs, *ndontregs;
175 * Return the REGW struct for a temporary.
176 * If first time touched, enter into list for existing vars.
177 * Only called from sucomp().
179 static REGW *
180 newblock(NODE *p)
182 REGW *nb;
184 #ifdef PCC_DEBUG
185 if (regno(p) < tempmin || regno(p) >= tempmax)
186 comperr("temp %p(%d) outside limits (%d-%d)",
187 p, regno(p), tempmin, tempmax);
188 #endif
189 nb = &nblock[regno(p)];
190 if (nb->link.q_forw == 0) {
191 DLIST_INSERT_AFTER(&initial, nb, link);
192 #ifdef PCC_DEBUG
193 ASGNUM(nb) = regno(p);
194 RDEBUG(("Adding longtime %d for tmp %d\n",
195 nb->nodnum, regno(p)));
196 #endif
198 if (nb->r_class == 0)
199 nb->r_class = gclass(p->n_type);
200 #ifdef PCC_DEBUG
201 RDEBUG(("newblock: p %p, node %d class %d\n",
202 p, nb->nodnum, nb->r_class));
203 #endif
204 return nb;
208 * Count the number of registers needed to evaluate a tree.
209 * This is only done to find the evaluation order of the tree.
210 * While here, assign temp numbers to the registers that will
211 * be needed when the tree is evaluated.
213 * While traversing the tree, assign REGW nodes to the registers
214 * used by all instructions:
215 * - n_regw[0] is always set to the outgoing node. If the
216 * instruction is 2-op (addl r0,r1) then an implicit move
217 * is inserted just before the left (clobbered) operand.
218 * - if the instruction has needs then REGW nodes are
219 * allocated as n_regw[1] etc.
222 nsucomp(NODE *p)
224 struct optab *q;
225 int left, right;
226 int nreg, need, i, nxreg, o;
227 int nareg, nbreg, ncreg, ndreg, nereg, nfreg, ngreg;
228 REGW *w;
230 o = optype(p->n_op);
232 UDEBUG(("entering nsucomp, node %p\n", p));
234 if (TBLIDX(p->n_su) == 0) {
235 int a = 0, b;
237 p->n_regw = NULL;
238 if (o == LTYPE ) {
239 if (p->n_op == TEMP)
240 p->n_regw = newblock(p);
241 else if (p->n_op == REG)
242 p->n_regw = &ablock[regno(p)];
243 } else
244 a = nsucomp(p->n_left);
245 if (o == BITYPE) {
246 b = nsucomp(p->n_right);
247 if (b > a)
248 p->n_su |= DORIGHT;
249 a = MAX(a, b);
251 return a;
254 q = &table[TBLIDX(p->n_su)];
256 for (i = (q->needs & NACOUNT), nareg = 0; i; i -= NAREG)
257 nareg++;
258 for (i = (q->needs & NBCOUNT), nbreg = 0; i; i -= NBREG)
259 nbreg++;
260 for (i = (q->needs & NCCOUNT), ncreg = 0; i; i -= NCREG)
261 ncreg++;
262 for (i = (q->needs & NDCOUNT), ndreg = 0; i; i -= NDREG)
263 ndreg++;
264 for (i = (q->needs & NECOUNT), nereg = 0; i; i -= NEREG)
265 nereg++;
266 for (i = (q->needs & NFCOUNT), nfreg = 0; i; i -= NFREG)
267 nfreg++;
268 for (i = (q->needs & NGCOUNT), ngreg = 0; i; i -= NGREG)
269 ngreg++;
271 nxreg = nareg + nbreg + ncreg + ndreg + nereg + nfreg + ngreg;
272 nreg = nxreg;
273 if (callop(p->n_op))
274 nreg = MAX(fregs, nreg);
276 if (o == BITYPE) {
277 right = nsucomp(p->n_right);
278 } else
279 right = 0;
281 if (o != LTYPE)
282 left = nsucomp(p->n_left);
283 else
284 left = 0;
286 UDEBUG(("node %p left %d right %d\n", p, left, right));
288 if (o == BITYPE) {
289 /* Two children */
290 if (right == left) {
291 need = left + MAX(nreg, 1);
292 } else {
293 need = MAX(right, left);
294 need = MAX(need, nreg);
296 if (setorder(p) == 0) {
297 /* XXX - should take care of overlapping needs */
298 if (right > left) {
299 p->n_su |= DORIGHT;
300 } else if (right == left) {
301 /* A favor to 2-operand architectures */
302 if ((q->rewrite & RRIGHT) == 0)
303 p->n_su |= DORIGHT;
306 } else if (o != LTYPE) {
307 /* One child */
308 need = MAX(right, left) + nreg;
309 } else
310 need = nreg;
312 if (p->n_op == TEMP)
313 (void)newblock(p);
315 if (TCLASS(p->n_su) == 0 && nxreg == 0) {
316 UDEBUG(("node %p no class\n", p));
317 p->n_regw = NULL; /* may be set earlier */
318 return need;
321 #ifdef PCC_DEBUG
322 #define ADCL(n, cl) \
323 for (i = 0; i < n; i++, w++) { w->r_class = cl; \
324 DLIST_INSERT_BEFORE(&initial, w, link); SETNUM(w); \
325 UDEBUG(("Adding " #n " %d\n", w->nodnum)); \
327 #else
328 #define ADCL(n, cl) \
329 for (i = 0; i < n; i++, w++) { w->r_class = cl; \
330 DLIST_INSERT_BEFORE(&initial, w, link); SETNUM(w); \
332 #endif
334 UDEBUG(("node %p numregs %d\n", p, nxreg+1));
335 w = p->n_regw = tmpalloc(sizeof(REGW) * (nxreg+1));
336 memset(w, 0, sizeof(REGW) * (nxreg+1));
338 w->r_class = TCLASS(p->n_su);
339 if (w->r_class == 0)
340 w->r_class = gclass(p->n_type);
341 w->r_nclass[0] = o == LTYPE; /* XXX store leaf info here */
342 SETNUM(w);
343 if (w->r_class)
344 DLIST_INSERT_BEFORE(&initial, w, link);
345 #ifdef PCC_DEBUG
346 UDEBUG(("Adding short %d class %d\n", w->nodnum, w->r_class));
347 #endif
348 w++;
349 ADCL(nareg, CLASSA);
350 ADCL(nbreg, CLASSB);
351 ADCL(ncreg, CLASSC);
352 ADCL(ndreg, CLASSD);
353 ADCL(nereg, CLASSE);
354 ADCL(nfreg, CLASSF);
355 ADCL(ngreg, CLASSG);
357 if (q->rewrite & RESC1) {
358 w = p->n_regw + 1;
359 w->r_class = -1;
360 DLIST_REMOVE(w,link);
361 } else if (q->rewrite & RESC2) {
362 w = p->n_regw + 2;
363 w->r_class = -1;
364 DLIST_REMOVE(w,link);
365 } else if (q->rewrite & RESC3) {
366 w = p->n_regw + 3;
367 w->r_class = -1;
368 DLIST_REMOVE(w,link);
371 UDEBUG(("node %p return regs %d\n", p, need));
373 return need;
376 #define CLASS(x) (x)->r_class
377 #define NCLASS(x,c) (x)->r_nclass[c]
378 #define ADJLIST(x) (x)->r_adjList
379 #define ALIAS(x) (x)->r_alias
380 #define ONLIST(x) (x)->r_onlist
381 #define MOVELIST(x) (x)->r_moveList
382 #define COLOR(x) (x)->r_color
384 static bittype *live;
386 #define PUSHWLIST(w, l) DLIST_INSERT_AFTER(&l, w, link); w->r_onlist = &l
387 #define POPWLIST(l) popwlist(&l);
388 #define DELWLIST(w) DLIST_REMOVE(w, link)
389 #define WLISTEMPTY(h) DLIST_ISEMPTY(&h,link)
390 #define PUSHMLIST(w, l, q) DLIST_INSERT_AFTER(&l, w, link); w->queue = q
391 #define POPMLIST(l) popmlist(&l);
393 #define trivially_colorable(x) \
394 trivially_colorable_p((x)->r_class, (x)->r_nclass)
396 * Determine if a node is trivially colorable ("degree < K").
397 * This implementation is a dumb one, without considering speed.
399 static int
400 trivially_colorable_p(int c, int *n)
402 int r[NUMCLASS+1];
403 int i;
405 for (i = 1; i < NUMCLASS+1; i++)
406 r[i] = n[i] < regK[i] ? n[i] : regK[i];
408 #if 0
409 /* add the exclusion nodes. */
410 /* XXX can we do someything smart here? */
411 /* worst-case for exclusion nodes are better than the `worst-case' */
412 for (; excl; excl >>= 1)
413 if (excl & 1)
414 r[c]++;
415 #endif
417 i = COLORMAP(c, r);
418 if (i < 0 || i > 1)
419 comperr("trivially_colorable_p");
420 #ifdef PCC_DEBUG
421 if (rdebug > 1)
422 printf("trivially_colorable_p: n[1] %d n[2] %d n[3] %d n[4] "
423 "%d for class %d, triv %d\n", n[1], n[2], n[3], n[4], c, i);
424 #endif
425 return i;
428 static int
429 ncnt(int needs)
431 int i = 0;
433 while (needs & NACOUNT)
434 needs -= NAREG, i++;
435 while (needs & NBCOUNT)
436 needs -= NBREG, i++;
437 while (needs & NCCOUNT)
438 needs -= NCREG, i++;
439 while (needs & NDCOUNT)
440 needs -= NDREG, i++;
441 while (needs & NECOUNT)
442 needs -= NEREG, i++;
443 while (needs & NFCOUNT)
444 needs -= NFREG, i++;
445 while (needs & NGCOUNT)
446 needs -= NGREG, i++;
447 return i;
450 static REGW *
451 popwlist(REGW *l)
453 REGW *w = DLIST_NEXT(l, link);
455 DLIST_REMOVE(w, link);
456 w->r_onlist = NULL;
457 return w;
461 * Move lists, a move node is always on only one list.
463 static REGM coalescedMoves, constrainedMoves, frozenMoves,
464 worklistMoves, activeMoves;
465 enum { COAL, CONSTR, FROZEN, WLIST, ACTIVE };
467 static REGM *
468 popmlist(REGM *l)
470 REGM *w = DLIST_NEXT(l, link);
472 DLIST_REMOVE(w, link);
473 return w;
477 * About data structures used in liveness analysis:
479 * The temporaries generated in pass1 are numbered between tempmin and
480 * tempmax. Temporaries generated in pass2 are numbered above tempmax,
481 * so they are sequentially numbered.
483 * Bitfields are used for liveness. Bit arrays are allocated on the
484 * heap for the "live" variable and on the stack for the in, out, gen
485 * and killed variables. Therefore, for a temp number, the bit number must
486 * be biased with tempmin.
488 * There may be an idea to use a different data structure to store
489 * pass2 allocated temporaries, because they are very sparse.
492 #ifdef PCC_DEBUG
493 static void
494 LIVEADD(int x)
496 RDEBUG(("Liveadd: %d\n", x));
497 if (x >= MAXREGS && (x < tempmin || x >= tempmax))
498 comperr("LIVEADD: out of range");
499 if (x < MAXREGS) {
500 BITSET(live, x);
501 } else
502 BITSET(live, (x-tempmin+MAXREGS));
505 static void
506 LIVEDEL(int x)
508 RDEBUG(("Livedel: %d\n", x));
510 if (x >= MAXREGS && (x < tempmin || x >= tempmax))
511 comperr("LIVEDEL: out of range");
512 if (x < MAXREGS) {
513 BITCLEAR(live, x);
514 } else
515 BITCLEAR(live, (x-tempmin+MAXREGS));
517 #else
518 #define LIVEADD(x) \
519 (x >= MAXREGS ? BITSET(live, (x-tempmin+MAXREGS)) : BITSET(live, x))
520 #define LIVEDEL(x) \
521 (x >= MAXREGS ? BITCLEAR(live, (x-tempmin+MAXREGS)) : BITCLEAR(live, x))
522 #endif
524 static struct lives {
525 DLIST_ENTRY(lives) link;
526 REGW *var;
527 } lused, lunused;
529 static void
530 LIVEADDR(REGW *x)
532 struct lives *l;
534 #ifdef PCC_DEBUG
535 RDEBUG(("LIVEADDR: %d\n", x->nodnum));
536 DLIST_FOREACH(l, &lused, link)
537 if (l->var == x)
538 return;
539 #if 0
540 comperr("LIVEADDR: multiple %d", ASGNUM(x));
541 #endif
542 #endif
543 if (!DLIST_ISEMPTY(&lunused, link)) {
544 l = DLIST_NEXT(&lunused, link);
545 DLIST_REMOVE(l, link);
546 } else
547 l = tmpalloc(sizeof(struct lives));
549 l->var = x;
550 DLIST_INSERT_AFTER(&lused, l, link);
553 static void
554 LIVEDELR(REGW *x)
556 struct lives *l;
558 #ifdef PCC_DEBUG
559 RDEBUG(("LIVEDELR: %d\n", x->nodnum));
560 #endif
561 DLIST_FOREACH(l, &lused, link) {
562 if (l->var != x)
563 continue;
564 DLIST_REMOVE(l, link);
565 DLIST_INSERT_AFTER(&lunused, l, link);
566 return;
568 #if 0
569 comperr("LIVEDELR: %p not found", x);
570 #endif
573 #define MOVELISTADD(t, p) movelistadd(t, p)
574 #define WORKLISTMOVEADD(s,d) worklistmoveadd(s,d)
576 static void
577 movelistadd(REGW *t, REGM *p)
579 MOVL *w = tmpalloc(sizeof(MOVL));
581 w->regm = p;
582 w->next = t->r_moveList;
583 t->r_moveList = w;
586 static REGM *
587 worklistmoveadd(REGW *src, REGW *dst)
589 REGM *w = tmpalloc(sizeof(REGM));
591 DLIST_INSERT_AFTER(&worklistMoves, w, link);
592 w->src = src;
593 w->dst = dst;
594 w->queue = WLIST;
595 return w;
598 #define HASHSZ 16384
599 struct AdjSet {
600 struct AdjSet *next;
601 REGW *u, *v;
602 } *edgehash[HASHSZ];
604 /* Check if a node pair is adjacent */
605 static int
606 adjSet(REGW *u, REGW *v)
608 struct AdjSet *w;
609 REGW *t;
611 if (ONLIST(u) == &precolored) {
612 ADJL *a = ADJLIST(v);
614 * Check if any of the registers that have edges against v
615 * alias to u.
617 for (; a; a = a->r_next) {
618 if (ONLIST(a->a_temp) != &precolored)
619 continue;
620 t = a->a_temp;
621 if (interferes(t - ablock, u - ablock))
622 return 1;
625 #ifdef notdef
626 if (u > v)
627 t = v, v = u, u = t;
628 w = edgehash[((intptr_t)u+(intptr_t)v) & (HASHSZ-1)];
629 #else
630 w = edgehash[(u->nodnum+v->nodnum)& (HASHSZ-1)];
631 #endif
632 for (; w; w = w->next) {
633 if ((u == w->u && v == w->v) || (u == w->v && v == w->u))
634 return 1;
636 return 0;
639 /* Add a pair to adjset. No check for dups */
640 static void
641 adjSetadd(REGW *u, REGW *v)
643 struct AdjSet *w;
644 int x;
646 #ifdef notdef
647 if (u > v)
648 t = v, v = u, u = t;
649 x = ((intptr_t)u+(intptr_t)v) & (HASHSZ-1);
650 #else
651 x = (u->nodnum+v->nodnum)& (HASHSZ-1);
652 #endif
653 w = tmpalloc(sizeof(struct AdjSet));
654 w->u = u, w->v = v;
655 w->next = edgehash[x];
656 edgehash[x] = w;
660 * Add an interference edge between two nodes.
662 static void
663 AddEdge(REGW *u, REGW *v)
665 ADJL *x;
667 #ifdef PCC_DEBUG
668 RRDEBUG(("AddEdge: u %d v %d\n", ASGNUM(u), ASGNUM(v)));
670 #if 0
671 if (ASGNUM(u) == 0)
672 comperr("AddEdge 0");
673 #endif
674 if (CLASS(u) == 0 || CLASS(v) == 0)
675 comperr("AddEdge class == 0 (%d=%d, %d=%d)",
676 CLASS(u), ASGNUM(u), CLASS(v), ASGNUM(v));
677 #endif
679 if (u == v)
680 return;
681 if (adjSet(u, v))
682 return;
684 adjSetadd(u, v);
686 #if 0
687 if (ONLIST(u) == &precolored || ONLIST(v) == &precolored)
688 comperr("precolored node in AddEdge");
689 #endif
691 if (ONLIST(u) != &precolored) {
692 x = tmpalloc(sizeof(ADJL));
693 x->a_temp = v;
694 x->r_next = u->r_adjList;
695 u->r_adjList = x;
696 NCLASS(u, CLASS(v))++;
699 if (ONLIST(v) != &precolored) {
700 x = tmpalloc(sizeof(ADJL));
701 x->a_temp = u;
702 x->r_next = v->r_adjList;
703 v->r_adjList = x;
704 NCLASS(v, CLASS(u))++;
707 #if 0
708 RDEBUG(("AddEdge: u %d(d %d) v %d(d %d)\n", u, DEGREE(u), v, DEGREE(v)));
709 #endif
712 static int
713 MoveRelated(REGW *n)
715 MOVL *l;
716 REGM *w;
718 for (l = MOVELIST(n); l; l = l->next) {
719 w = l->regm;
720 if (w->queue == ACTIVE || w->queue == WLIST)
721 return 1;
723 return 0;
726 static void
727 MkWorklist(void)
729 REGW *w;
731 RDEBUGX(int s=0);
732 RDEBUGX(int f=0);
733 RDEBUGX(int d=0);
735 DLIST_INIT(&precolored, link);
736 DLIST_INIT(&simplifyWorklist, link);
737 DLIST_INIT(&freezeWorklist, link);
738 DLIST_INIT(&spillWorklist, link);
739 DLIST_INIT(&spilledNodes, link);
740 DLIST_INIT(&coalescedNodes, link);
741 DLIST_INIT(&coloredNodes, link);
742 DLIST_INIT(&selectStack, link);
745 * Remove all nodes from the initial list and put them on
746 * one of the worklists.
748 while (!DLIST_ISEMPTY(&initial, link)) {
749 w = DLIST_NEXT(&initial, link);
750 DLIST_REMOVE(w, link);
751 if (!trivially_colorable(w)) {
752 PUSHWLIST(w, spillWorklist);
753 RDEBUGX(s++);
754 } else if (MoveRelated(w)) {
755 PUSHWLIST(w, freezeWorklist);
756 RDEBUGX(f++);
757 } else {
758 PUSHWLIST(w, simplifyWorklist);
759 RDEBUGX(d++);
762 RDEBUG(("MkWorklist: spill %d freeze %d simplify %d\n", s,f,d));
765 static void
766 addalledges(REGW *e)
768 int i, j, k;
769 struct lives *l;
771 #ifdef PCC_DEBUG
772 RDEBUG(("addalledges for %d\n", e->nodnum));
773 #endif
775 if (e->r_class == -1)
776 return; /* unused */
778 if (ONLIST(e) != &precolored) {
779 for (i = 0; ndontregs[i] >= 0; i++)
780 AddEdge(e, &ablock[ndontregs[i]]);
783 /* First add to long-lived temps and hard regs */
784 RDEBUG(("addalledges longlived "));
785 for (i = 0; i < xbits; i += NUMBITS) {
786 if ((k = live[i/NUMBITS])) {
787 while (k) {
788 j = ffs(k)-1;
789 if (i+j < MAXREGS)
790 AddEdge(&ablock[i+j], e);
791 else
792 AddEdge(&nblock[i+j+tempmin-MAXREGS],e);
793 RRDEBUG(("%d ", i+j+tempmin));
794 k &= ~(1 << j);
797 #if NUMBITS > 32 /* XXX hack for LP64 */
798 k = (live[i/NUMBITS] >> 32);
799 while (k) {
800 j = ffs(k)-1;
801 if (i+j+32 < MAXREGS)
802 AddEdge(&ablock[i+j+32], e);
803 else
804 AddEdge(&nblock[i+j+tempmin-MAXREGS+32], e);
805 RRDEBUG(("%d ", i+j+tempmin+32));
806 k &= ~(1 << j);
808 #endif
810 RDEBUG(("done\n"));
811 /* short-lived temps */
812 RDEBUG(("addalledges shortlived "));
813 DLIST_FOREACH(l, &lused, link) {
814 #ifdef PCC_DEBUG
815 RRDEBUG(("%d ", ASGNUM(l->var)));
816 #endif
817 AddEdge(l->var, e);
819 RDEBUG(("done\n"));
823 * Add a move edge between def and use.
825 static void
826 moveadd(REGW *def, REGW *use)
828 REGM *r;
829 MOVL *w;
831 if (def == use)
832 return; /* no move to itself XXX - ``shouldn't happen'' */
833 #ifdef PCC_DEBUG
834 RDEBUG(("moveadd: def %d use %d\n", ASGNUM(def), ASGNUM(use)));
835 #endif
838 * Check if we are already on move list.
839 * XXX How can that happen ???
841 for (w = MOVELIST(def); w; w = w->next) {
842 if ((w->regm->src == def && w->regm->dst == use) ||
843 (w->regm->src == use && w->regm->dst == def))
844 return; /* already there XXX reverse? */
847 r = WORKLISTMOVEADD(use, def);
848 MOVELISTADD(def, r);
849 MOVELISTADD(use, r);
853 * Traverse arguments backwards.
854 * XXX - can this be tricked in some other way?
856 static void
857 argswalk(NODE *p)
860 if (p->n_op == CM) {
861 argswalk(p->n_left);
862 insnwalk(p->n_right);
863 } else
864 insnwalk(p);
868 * Add to (or remove from) live set variables that must not
869 * be clobbered when traversing down on the other leg for
870 * a BITYPE node.
872 static void
873 setlive(NODE *p, int set, REGW *rv)
875 if (rv != NULL) {
876 if (rv->nodnum < MAXREGS &&
877 TESTBIT(validregs, rv->nodnum) == 0)
878 return;
879 set ? LIVEADDR(rv) : LIVEDELR(rv);
880 return;
883 if (p->n_regw != NULL) {
884 if (p->n_regw->nodnum < MAXREGS &&
885 TESTBIT(validregs, p->n_regw->nodnum) == 0)
886 return;
887 set ? LIVEADDR(p->n_regw) : LIVEDELR(p->n_regw);
888 return;
891 switch (optype(p->n_op)) {
892 case LTYPE:
893 if (p->n_op == TEMP || VALIDREG(p))
894 set ? LIVEADD(regno(p)) : LIVEDEL(regno(p));
895 break;
896 case BITYPE:
897 setlive(p->n_right, set, rv);
898 /* FALLTHROUGH */
899 case UTYPE:
900 setlive(p->n_left, set, rv);
901 break;
906 * Add edges for temporary w against all temporaries that may be
907 * used simultaneously (like index registers).
909 static void
910 addedge_r(NODE *p, REGW *w)
912 RRDEBUG(("addedge_r: node %p regw %p\n", p, w));
914 if (p->n_regw != NULL) {
915 if (p->n_regw->nodnum < MAXREGS &&
916 TESTBIT(validregs, p->n_regw->nodnum) == 0)
917 return;
918 AddEdge(p->n_regw, w);
919 return;
922 if (optype(p->n_op) == BITYPE)
923 addedge_r(p->n_right, w);
924 if (optype(p->n_op) != LTYPE)
925 addedge_r(p->n_left, w);
929 * add/del parameter from live set.
931 static void
932 setxarg(NODE *p)
934 int i, ut = 0, in = 0;
935 REGW *rw;
936 int c, cw;
938 if (p->n_op == ICON && p->n_type == STRTY)
939 return;
941 RDEBUG(("setxarg %p %s\n", p, p->n_name));
942 cw = xasmcode(p->n_name);
943 if (XASMISINP(cw))
944 in = 1;
945 if (XASMISOUT(cw))
946 ut = 1;
948 c = XASMVAL(cw);
950 #ifdef MYSETXARG
951 MYSETXARG;
952 #endif
954 switch (c) {
955 case 'm':
956 case 'g':
957 /* must find all TEMPs/REGs and set them live */
958 if (p->n_left->n_op != REG && p->n_left->n_op != TEMP) {
959 insnwalk(p->n_left);
960 break;
962 /* FALLTHROUGH */
963 case 'r':
964 i = regno(p->n_left);
965 rw = p->n_left->n_op == REG ? ablock : nblock;
966 if (ut) {
967 LIVEDEL(i);
969 if (in) {
970 LIVEADD(i);
972 addalledges(&rw[i]);
973 break;
975 case 'i':
976 case 'n':
977 break;
978 default:
979 comperr("bad ixarg %s", p->n_name);
981 #ifdef MYSETXARG
982 MYSETXARG;
983 #endif
987 * Do the in-tree part of liveness analysis. (the difficult part)
989 * Walk down the tree in reversed-evaluation order (backwards).
990 * The moves and edges inserted and evaluation order for
991 * instructions when code is emitted is described here, hence
992 * this code runs the same but backwards.
994 * 2-op reclaim LEFT: eval L, move to DEST, eval R.
995 * moveadd L,DEST; addedge DEST,R
996 * 2-op reclaim LEFT DORIGHT: eval R, eval L, move to DEST.
997 * moveadd L,DEST; addedge DEST,R; addedge L,R
998 * 2-op reclaim RIGHT; eval L, eval R, move to DEST.
999 * moveadd R,DEST; addedge DEST,L; addedge L,R
1000 * 2-op reclaim RIGHT DORIGHT: eval R, move to DEST, eval L.
1001 * moveadd R,DEST; addedge DEST,L
1002 * 3-op: eval L, eval R
1003 * addedge L,R
1004 * 3-op DORIGHT: eval R, eval L
1005 * addedge L,R
1007 * Instructions with special needs are handled just like these variants,
1008 * with the exception of extra added moves and edges.
1009 * Moves to special regs are scheduled after the evaluation of both legs.
1012 static void
1013 insnwalk(NODE *p)
1015 int o = p->n_op;
1016 struct optab *q = &table[TBLIDX(p->n_su)];
1017 REGW *lr, *rr, *rv, *r, *rrv, *lrv;
1018 NODE *lp, *rp;
1019 int i, n;
1021 RDEBUG(("insnwalk %p\n", p));
1023 rv = p->n_regw;
1025 rrv = lrv = NULL;
1026 if (p->n_op == ASSIGN &&
1027 (p->n_left->n_op == TEMP || VALIDREG(p->n_left))) {
1028 lr = p->n_left->n_op == TEMP ? nblock : ablock;
1029 i = regno(p->n_left);
1030 LIVEDEL(i); /* remove assigned temp from live set */
1031 addalledges(&lr[i]);
1034 /* Add edges for the result of this node */
1035 if (rv && (q->visit & INREGS || o == TEMP || VALIDREG(p)))
1036 addalledges(rv);
1038 /* special handling of CALL operators */
1039 if (callop(o)) {
1040 if (rv)
1041 moveadd(rv, &ablock[RETREG(p->n_type)]);
1042 for (i = 0; tempregs[i] >= 0; i++)
1043 addalledges(&ablock[tempregs[i]]);
1046 /* for special return value registers add moves */
1047 if ((q->needs & NSPECIAL) && (n = rspecial(q, NRES)) >= 0) {
1048 rv = &ablock[n];
1049 moveadd(p->n_regw, rv);
1052 /* Check leaves for results in registers */
1053 lr = optype(o) != LTYPE ? p->n_left->n_regw : NULL;
1054 lp = optype(o) != LTYPE ? p->n_left : NULL;
1055 rr = optype(o) == BITYPE ? p->n_right->n_regw : NULL;
1056 rp = optype(o) == BITYPE ? p->n_right : NULL;
1058 /* simple needs */
1059 n = ncnt(q->needs);
1060 for (i = 0; i < n; i++) {
1061 #if 1
1062 static int ncl[] =
1063 { 0, NASL, NBSL, NCSL, NDSL, NESL, NFSL, NGSL };
1064 static int ncr[] =
1065 { 0, NASR, NBSR, NCSR, NDSR, NESR, NFSR, NGSR };
1066 int j;
1068 /* edges are already added */
1069 if ((r = &p->n_regw[1+i])->r_class == -1) {
1070 r = p->n_regw;
1071 } else {
1072 AddEdge(r, p->n_regw);
1073 addalledges(r);
1075 if (optype(o) != LTYPE && (q->needs & ncl[CLASS(r)]) == 0)
1076 addedge_r(p->n_left, r);
1077 if (optype(o) == BITYPE && (q->needs & ncr[CLASS(r)]) == 0)
1078 addedge_r(p->n_right, r);
1079 for (j = i + 1; j < n; j++) {
1080 if (p->n_regw[j+1].r_class == -1)
1081 continue;
1082 AddEdge(r, &p->n_regw[j+1]);
1084 #else
1085 if ((r = &p->n_regw[1+i])->r_class == -1)
1086 continue;
1087 addalledges(r);
1088 if (optype(o) != LTYPE && (q->needs & NASL) == 0)
1089 addedge_r(p->n_left, r);
1090 if (optype(o) == BITYPE && (q->needs & NASR) == 0)
1091 addedge_r(p->n_right, r);
1092 #endif
1095 /* special needs */
1096 if (q->needs & NSPECIAL) {
1097 struct rspecial *rc;
1098 for (rc = nspecial(q); rc->op; rc++) {
1099 switch (rc->op) {
1100 #define ONLY(c,s) if (c) s(c, &ablock[rc->num])
1101 case NLEFT:
1102 addalledges(&ablock[rc->num]);
1103 ONLY(lr, moveadd);
1104 break;
1105 case NOLEFT:
1106 addedge_r(p->n_left, &ablock[rc->num]);
1107 break;
1108 case NRIGHT:
1109 addalledges(&ablock[rc->num]);
1110 ONLY(rr, moveadd);
1111 break;
1112 case NORIGHT:
1113 addedge_r(p->n_right, &ablock[rc->num]);
1114 break;
1115 case NEVER:
1116 addalledges(&ablock[rc->num]);
1117 break;
1118 #undef ONLY
1123 if (o == ASSIGN) {
1124 /* avoid use of unhandled registers */
1125 if (p->n_left->n_op == REG &&
1126 !TESTBIT(validregs, regno(p->n_left)))
1127 lr = NULL;
1128 if (p->n_right->n_op == REG &&
1129 !TESTBIT(validregs, regno(p->n_right)))
1130 rr = NULL;
1131 /* needs special treatment */
1132 if (lr && rr)
1133 moveadd(lr, rr);
1134 if (lr && rv)
1135 moveadd(lr, rv);
1136 if (rr && rv)
1137 moveadd(rr, rv);
1138 } else if (callop(o)) {
1139 int *c;
1141 for (c = livecall(p); *c != -1; c++) {
1142 addalledges(ablock + *c);
1143 LIVEADD(*c);
1145 } else if (q->rewrite & (RESC1|RESC2|RESC3)) {
1146 if (lr && rr)
1147 AddEdge(lr, rr);
1148 } else if (q->rewrite & RLEFT) {
1149 if (lr && rv)
1150 moveadd(rv, lr), lrv = rv;
1151 if (rv && rp)
1152 addedge_r(rp, rv);
1153 } else if (q->rewrite & RRIGHT) {
1154 if (rr && rv)
1155 moveadd(rv, rr), rrv = rv;
1156 if (rv && lp)
1157 addedge_r(lp, rv);
1160 switch (optype(o)) {
1161 case BITYPE:
1162 if (p->n_op == ASSIGN &&
1163 (p->n_left->n_op == TEMP || p->n_left->n_op == REG)) {
1164 /* only go down right node */
1165 insnwalk(p->n_right);
1166 } else if (callop(o)) {
1167 insnwalk(p->n_left);
1168 /* Do liveness analysis on arguments (backwards) */
1169 argswalk(p->n_right);
1170 } else if ((p->n_su & DORIGHT) == 0) {
1171 setlive(p->n_left, 1, lrv);
1172 insnwalk(p->n_right);
1173 setlive(p->n_left, 0, lrv);
1174 insnwalk(p->n_left);
1175 } else {
1176 setlive(p->n_right, 1, rrv);
1177 insnwalk(p->n_left);
1178 setlive(p->n_right, 0, rrv);
1179 insnwalk(p->n_right);
1181 break;
1183 case UTYPE:
1184 insnwalk(p->n_left);
1185 break;
1187 case LTYPE:
1188 switch (o) {
1189 case REG:
1190 if (!TESTBIT(validregs, regno(p)))
1191 break; /* never add moves */
1192 /* FALLTHROUGH */
1193 case TEMP:
1194 i = regno(p);
1195 rr = (o == TEMP ? &nblock[i] : &ablock[i]);
1196 if (rv != rr) {
1197 addalledges(rr);
1198 moveadd(rv, rr);
1200 LIVEADD(i);
1201 break;
1203 case OREG: /* XXX - not yet */
1204 break;
1206 default:
1207 break;
1209 break;
1213 static bittype **gen, **killed, **in, **out;
1215 struct notspill {
1216 SLIST_ENTRY(notspill) link;
1217 int spnum;
1219 SLIST_HEAD(, notspill) nothead;
1221 static int
1222 innotspill(int n)
1224 struct notspill *nsp;
1226 SLIST_FOREACH(nsp, &nothead, link)
1227 if (nsp->spnum == n)
1228 return 1;
1229 return 0;
1232 static void
1233 addnotspill(int n)
1235 struct notspill *nsp;
1237 if (innotspill(n))
1238 return;
1239 nsp = tmpalloc(sizeof(struct notspill));
1240 nsp->spnum = n;
1241 SLIST_INSERT_LAST(&nothead, nsp, link);
1245 * Found an extended assembler node, so growel out gen/killed nodes.
1247 static void
1248 xasmionize(NODE *p, void *arg)
1250 int bb = *(int *)arg;
1251 int cw, b;
1253 if (p->n_op == ICON && p->n_type == STRTY)
1254 return; /* dummy end marker */
1256 cw = xasmcode(p->n_name);
1257 if (XASMVAL(cw) == 'n' /* || XASMVAL(cw) == 'm' */)
1258 return; /* no flow analysis */
1259 p = p->n_left;
1261 if (XASMVAL(cw) == 'g' && p->n_op != TEMP && p->n_op != REG)
1262 return; /* no flow analysis */
1264 b = regno(p);
1265 if (XASMVAL(cw) == 'r' && p->n_op == TEMP)
1266 addnotspill(b);
1267 if (XASMVAL(cw) == 'm') {
1268 if (p->n_op == UMUL && p->n_left->n_op == TEMP) {
1269 p = p->n_left;
1270 b = regno(p);
1271 addnotspill(b);
1272 } else
1273 return;
1275 #define MKTOFF(r) ((r) - tempmin + MAXREGS)
1276 if (XASMISOUT(cw)) {
1277 if (p->n_op == TEMP) {
1278 BITCLEAR(gen[bb], MKTOFF(b));
1279 BITSET(killed[bb], MKTOFF(b));
1280 } else if (p->n_op == REG) {
1281 BITCLEAR(gen[bb], b);
1282 BITSET(killed[bb], b);
1283 } else
1284 uerror("bad xasm node type %d", p->n_op);
1286 if (XASMISINP(cw)) {
1287 if (p->n_op == TEMP) {
1288 BITSET(gen[bb], MKTOFF(b));
1289 } else if (p->n_op == REG) {
1290 BITSET(gen[bb], b);
1291 } else if (optype(p->n_op) != LTYPE) {
1292 if (XASMVAL(cw) == 'r')
1293 uerror("couldn't find available register");
1294 else
1295 uerror("bad xasm node type2");
1300 #ifndef XASMCONSTREGS
1301 #define XASMCONSTREGS(x) (-1)
1302 #endif
1305 * Check that given constraints are valid.
1307 static void
1308 xasmconstr(NODE *p, void *arg)
1310 int i;
1312 if (p->n_op == ICON && p->n_type == STRTY)
1313 return; /* no constraints */
1315 if (strcmp(p->n_name, "cc") == 0 || strcmp(p->n_name, "memory") == 0)
1316 return;
1318 for (i = 0; i < MAXREGS; i++)
1319 if (strcmp(rnames[i], p->n_name) == 0) {
1320 addalledges(&ablock[i]);
1321 return;
1323 if ((i = XASMCONSTREGS(p->n_name)) < 0)
1324 comperr("unsupported xasm constraint %s", p->n_name);
1325 addalledges(&ablock[i]);
1328 #define RUP(x) (((x)+NUMBITS-1)/NUMBITS)
1329 #define SETCOPY(t,f,i,n) for (i = 0; i < RUP(n); i++) t[i] = f[i]
1330 #define SETSET(t,f,i,n) for (i = 0; i < RUP(n); i++) t[i] |= f[i]
1331 #define SETCLEAR(t,f,i,n) for (i = 0; i < RUP(n); i++) t[i] &= ~f[i]
1332 #define SETCMP(v,t,f,i,n) for (i = 0; i < RUP(n); i++) \
1333 if (t[i] != f[i]) v = 1
1334 #define SETEMPTY(t,sz) memset(t, 0, BIT2BYTE(sz))
1336 static int
1337 deldead(NODE *p, bittype *lvar)
1339 NODE *q;
1340 int ty, rv = 0;
1342 #define BNO(p) (regno(p) - tempmin+MAXREGS)
1343 if (p->n_op == TEMP)
1344 BITSET(lvar, BNO(p));
1345 if (asgop(p->n_op) && p->n_left->n_op == TEMP &&
1346 TESTBIT(lvar, BNO(p->n_left)) == 0) {
1348 * Not live, must delete the right tree at least
1349 * down to next statement with side effects.
1351 BDEBUG(("DCE deleting temp %d\n", regno(p->n_left)));
1352 nfree(p->n_left);
1353 q = p->n_right;
1354 *p = *q;
1355 nfree(q);
1356 rv = 1;
1358 ty = optype(p->n_op);
1359 if (ty != LTYPE)
1360 rv |= deldead(p->n_left, lvar);
1361 if (ty == BITYPE)
1362 rv |= deldead(p->n_right, lvar);
1363 return rv;
1367 * Do dead code elimination.
1369 static int
1370 dce(struct p2env *p2e)
1372 extern struct interpass prepole;
1373 struct basicblock *bb;
1374 struct interpass *ip;
1375 NODE *p;
1376 bittype *lvar;
1377 int i, bbnum, fix = 0;
1379 BDEBUG(("Entering DCE\n"));
1381 * Traverse over the basic blocks.
1382 * if an assignment is found that writes to a temporary
1383 * that is not live out, remove that assignment and its legs.
1385 DLIST_INIT(&prepole, qelem);
1386 BITALLOC(lvar, tmpalloc, xbits);
1387 DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
1388 bbnum = bb->bbnum;
1389 BBDEBUG(("DCE bblock %d, start %p last %p\n",
1390 bbnum, bb->first, bb->last));
1391 SETCOPY(lvar, out[bbnum], i, xbits);
1392 for (ip = bb->last; ; ip = DLIST_PREV(ip, qelem)) {
1393 if (ip->type == IP_NODE && deldead(ip->ip_node, lvar)) {
1394 if ((p = deluseless(ip->ip_node)) == NULL) {
1395 struct interpass *previp;
1396 struct basicblock *prevbb;
1398 if (ip == bb->first && ip == bb->last) {
1399 /* Remove basic block */
1400 previp = DLIST_PREV(ip, qelem);
1401 DLIST_REMOVE(ip, qelem);
1402 prevbb = DLIST_PREV(bb, bbelem);
1403 DLIST_REMOVE(bb, bbelem);
1404 bb = prevbb;
1405 } else if (ip == bb->first) {
1406 bb->first =
1407 DLIST_NEXT(ip, qelem);
1408 DLIST_REMOVE(ip, qelem);
1409 } else if (ip == bb->last) {
1410 previp = DLIST_PREV(ip, qelem);
1411 DLIST_REMOVE(ip, qelem);
1412 bb->last = previp;
1413 bb = DLIST_PREV(bb, bbelem);
1414 } else {
1415 previp = DLIST_NEXT(ip, qelem);
1416 DLIST_REMOVE(ip, qelem);
1417 ip = previp;
1418 fix++;
1419 continue;
1421 fix++;
1422 BDEBUG(("bb %d: DCE ip %p deleted\n",
1423 bbnum, ip));
1424 break;
1425 } else while (!DLIST_ISEMPTY(&prepole, qelem)) {
1427 BDEBUG(("bb %d: DCE doing ip prepend\n", bbnum));
1428 #ifdef notyet
1429 struct interpass *tipp;
1430 tipp = DLIST_NEXT(&prepole, qelem);
1431 DLIST_REMOVE(tipp, qelem);
1432 DLIST_INSERT_BEFORE(ip, tipp, qelem);
1433 if (ip == bb->first)
1434 bb->first = tipp;
1435 fix++;
1436 #else
1437 comperr("dce needs bb fixup");
1438 #endif
1439 BDEBUG(("DCE ip prepended\n"));
1441 if (ip->type == IP_NODE) {
1442 geninsn(p, FOREFF);
1443 nsucomp(p);
1444 ip->ip_node = p;
1447 if (ip == bb->first)
1448 break;
1451 BDEBUG(("DCE fix %d\n", fix));
1452 return fix;
1456 * Set/clear long term liveness for regs and temps.
1458 static void
1459 unionize(NODE *p, int bb)
1461 int i, o, ty;
1463 if ((o = p->n_op) == TEMP) {
1464 #ifdef notyet
1465 for (i = 0; i < szty(p->n_type); i++) {
1466 BITSET(gen[bb], (regno(p) - tempmin+i+MAXREGS));
1468 #else
1469 i = 0;
1470 BITSET(gen[bb], (regno(p) - tempmin+i+MAXREGS));
1471 #endif
1472 } else if (VALIDREG(p)) {
1473 BITSET(gen[bb], regno(p));
1475 if (asgop(o)) {
1476 if (p->n_left->n_op == TEMP) {
1477 int b = regno(p->n_left) - tempmin+MAXREGS;
1478 #ifdef notyet
1479 for (i = 0; i < szty(p->n_type); i++) {
1480 BITCLEAR(gen[bb], (b+i));
1481 BITSET(killed[bb], (b+i));
1483 #else
1484 i = 0;
1485 BITCLEAR(gen[bb], (b+i));
1486 BITSET(killed[bb], (b+i));
1487 #endif
1488 unionize(p->n_right, bb);
1489 return;
1490 } else if (VALIDREG(p->n_left)) {
1491 int b = regno(p->n_left);
1492 BITCLEAR(gen[bb], b);
1493 BITSET(killed[bb], b);
1494 unionize(p->n_right, bb);
1495 return;
1498 ty = optype(o);
1499 if (ty != LTYPE)
1500 unionize(p->n_left, bb);
1501 if (ty == BITYPE)
1502 unionize(p->n_right, bb);
1506 * Do variable liveness analysis. Only analyze the long-lived
1507 * variables, and save the live-on-exit temporaries in a bit-field
1508 * at the end of each basic block. This bit-field is later used
1509 * when doing short-range liveness analysis in Build().
1511 static void
1512 LivenessAnalysis(struct p2env *p2e)
1514 struct basicblock *bb;
1515 struct interpass *ip;
1516 int i, bbnum;
1519 * generate the gen-killed sets for all basic blocks.
1521 DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
1522 bbnum = bb->bbnum;
1523 for (ip = bb->last; ; ip = DLIST_PREV(ip, qelem)) {
1524 /* gen/killed is 'p', this node is 'n' */
1525 if (ip->type == IP_NODE) {
1526 if (ip->ip_node->n_op == XASM)
1527 flist(ip->ip_node->n_left,
1528 xasmionize, &bbnum);
1529 else
1530 unionize(ip->ip_node, bbnum);
1532 if (ip == bb->first)
1533 break;
1535 memcpy(in[bbnum], gen[bbnum], BIT2BYTE(xbits));
1536 #ifdef PCC_DEBUG
1537 #define PRTRG(x) printf("%d ", i < MAXREGS ? i : i + tempmin-MAXREGS)
1538 if (rdebug) {
1539 printf("basic block %d\ngen: ", bbnum);
1540 for (i = 0; i < xbits; i++)
1541 if (TESTBIT(gen[bbnum], i))
1542 PRTRG(i);
1543 printf("\nkilled: ");
1544 for (i = 0; i < xbits; i++)
1545 if (TESTBIT(killed[bbnum], i))
1546 PRTRG(i);
1547 printf("\n");
1549 #endif
1554 * Build the set of interference edges and adjacency list.
1556 static void
1557 Build(struct p2env *p2e)
1559 struct interpass *ipole = &p2e->ipole;
1560 struct basicblock bbfake;
1561 struct interpass *ip;
1562 struct basicblock *bb;
1563 bittype *saved;
1564 int i, j, again;
1566 if (xtemps == 0) {
1568 * No basic block splitup is done if not optimizing,
1569 * so fake one basic block to keep the liveness analysis
1570 * happy.
1572 p2e->nbblocks = 1;
1573 bbfake.bbnum = 0;
1574 bbfake.last = DLIST_PREV(ipole, qelem);
1575 bbfake.first = DLIST_NEXT(ipole, qelem);
1576 DLIST_INIT(&p2e->bblocks, bbelem);
1577 DLIST_INSERT_AFTER(&p2e->bblocks, &bbfake, bbelem);
1578 bbfake.ch[0] = bbfake.ch[1] = NULL;
1581 /* Just fetch space for the temporaries from stack */
1582 gen = tmpalloc(p2e->nbblocks*sizeof(bittype*));
1583 killed = tmpalloc(p2e->nbblocks*sizeof(bittype*));
1584 in = tmpalloc(p2e->nbblocks*sizeof(bittype*));
1585 out = tmpalloc(p2e->nbblocks*sizeof(bittype*));
1586 for (i = 0; i < p2e->nbblocks; i++) {
1587 BITALLOC(gen[i],tmpalloc,xbits);
1588 BITALLOC(killed[i],tmpalloc,xbits);
1589 BITALLOC(in[i],tmpalloc,xbits);
1590 BITALLOC(out[i],tmpalloc,xbits);
1592 BITALLOC(saved,tmpalloc,xbits);
1594 SLIST_INIT(&nothead);
1595 livagain:
1596 LivenessAnalysis(p2e);
1598 /* register variable temporaries are live */
1599 for (i = 0; i < NPERMREG-1; i++) {
1600 if (nsavregs[i])
1601 continue;
1602 BITSET(out[p2e->nbblocks-1], (i+MAXREGS));
1603 for (j = i+1; j < NPERMREG-1; j++) {
1604 if (nsavregs[j])
1605 continue;
1606 AddEdge(&nblock[i+tempmin], &nblock[j+tempmin]);
1610 /* do liveness analysis on basic block level */
1611 do {
1612 again = 0;
1613 /* XXX - loop should be in reversed execution-order */
1614 DLIST_FOREACH_REVERSE(bb, &p2e->bblocks, bbelem) {
1615 i = bb->bbnum;
1616 SETCOPY(saved, out[i], j, xbits);
1617 if (bb->ch[0])
1618 SETSET(out[i], in[bb->ch[0]->bblock->bbnum], j, xbits);
1619 if (bb->ch[1])
1620 SETSET(out[i], in[bb->ch[1]->bblock->bbnum], j, xbits);
1621 SETCMP(again, saved, out[i], j, xbits);
1622 SETCOPY(saved, in[i], j, xbits);
1623 SETCOPY(in[i], out[i], j, xbits);
1624 SETCLEAR(in[i], killed[i], j, xbits);
1625 SETSET(in[i], gen[i], j, xbits);
1626 SETCMP(again, saved, in[i], j, xbits);
1628 } while (again);
1630 #ifdef PCC_DEBUG
1631 if (rdebug) {
1632 DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
1633 printf("basic block %d\nin: ", bb->bbnum);
1634 for (i = 0; i < xbits; i++)
1635 if (TESTBIT(in[bb->bbnum], i))
1636 PRTRG(i);
1637 printf("\nout: ");
1638 for (i = 0; i < xbits; i++)
1639 if (TESTBIT(out[bb->bbnum], i))
1640 PRTRG(i);
1641 printf("\n");
1644 #endif
1645 if (xtemps && xdce) {
1647 * Do dead code elimination by using live out.
1648 * Ignores if any variable read from is marked volatile,
1649 * but what it should do is unspecified anyway.
1650 * Liveness Analysis should be done in optim2 instead.
1652 * This should recalculate the basic block structure.
1654 if (dce(p2e)) {
1655 /* Clear bitfields */
1656 for (i = 0; i < p2e->nbblocks; i++) {
1657 SETEMPTY(gen[i],xbits);
1658 SETEMPTY(killed[i],xbits);
1659 SETEMPTY(in[i],xbits);
1660 SETEMPTY(out[i],xbits);
1662 SETEMPTY(saved,xbits);
1663 goto livagain;
1667 DLIST_FOREACH(bb, &p2e->bblocks, bbelem) {
1668 RDEBUG(("liveadd bb %d\n", bb->bbnum));
1669 i = bb->bbnum;
1670 for (j = 0; j < xbits; j += NUMBITS)
1671 live[j/NUMBITS] = 0;
1672 SETCOPY(live, out[i], j, xbits);
1673 for (ip = bb->last; ; ip = DLIST_PREV(ip, qelem)) {
1674 if (ip->type == IP_NODE) {
1675 if (ip->ip_node->n_op == XASM) {
1676 flist(ip->ip_node->n_right,
1677 xasmconstr, 0);
1678 listf(ip->ip_node->n_left, setxarg);
1679 } else
1680 insnwalk(ip->ip_node);
1682 if (ip == bb->first)
1683 break;
1687 #ifdef PCC_DEBUG
1688 if (rdebug) {
1689 struct AdjSet *w;
1690 ADJL *x;
1691 REGW *y;
1692 MOVL *m;
1694 printf("Interference edges\n");
1695 for (i = 0; i < HASHSZ; i++) {
1696 if ((w = edgehash[i]) == NULL)
1697 continue;
1698 for (; w; w = w->next)
1699 printf("%d <-> %d\n", ASGNUM(w->u), ASGNUM(w->v));
1701 printf("Degrees\n");
1702 DLIST_FOREACH(y, &initial, link) {
1703 printf("%d (%c): trivial [%d] ", ASGNUM(y),
1704 CLASS(y)+'@', trivially_colorable(y));
1705 i = 0;
1706 for (x = ADJLIST(y); x; x = x->r_next) {
1707 if (ONLIST(x->a_temp) != &selectStack &&
1708 ONLIST(x->a_temp) != &coalescedNodes)
1709 printf("%d ", ASGNUM(x->a_temp));
1710 else
1711 printf("(%d) ", ASGNUM(x->a_temp));
1712 i++;
1714 printf(": n=%d\n", i);
1716 printf("Move nodes\n");
1717 DLIST_FOREACH(y, &initial, link) {
1718 if (MOVELIST(y) == NULL)
1719 continue;
1720 printf("%d: ", ASGNUM(y));
1721 for (m = MOVELIST(y); m; m = m->next) {
1722 REGW *yy = m->regm->src == y ?
1723 m->regm->dst : m->regm->src;
1724 printf("%d ", ASGNUM(yy));
1726 printf("\n");
1729 #endif
1733 static void
1734 EnableMoves(REGW *n)
1736 MOVL *l;
1737 REGM *m;
1739 for (l = MOVELIST(n); l; l = l->next) {
1740 m = l->regm;
1741 if (m->queue != ACTIVE)
1742 continue;
1743 DLIST_REMOVE(m, link);
1744 PUSHMLIST(m, worklistMoves, WLIST);
1748 static void
1749 EnableAdjMoves(REGW *nodes)
1751 ADJL *w;
1752 REGW *n;
1754 EnableMoves(nodes);
1755 for (w = ADJLIST(nodes); w; w = w->r_next) {
1756 n = w->a_temp;
1757 if (ONLIST(n) == &selectStack || ONLIST(n) == &coalescedNodes)
1758 continue;
1759 EnableMoves(w->a_temp);
1764 * Decrement the degree of node w for class c.
1766 static void
1767 DecrementDegree(REGW *w, int c)
1769 int wast;
1771 #ifdef PCC_DEBUG
1772 RRDEBUG(("DecrementDegree: w %d, c %d\n", ASGNUM(w), c));
1773 #endif
1775 wast = trivially_colorable(w);
1776 NCLASS(w, c)--;
1777 if (wast == trivially_colorable(w))
1778 return;
1780 EnableAdjMoves(w);
1781 DELWLIST(w);
1782 ONLIST(w) = 0;
1783 if (MoveRelated(w)) {
1784 PUSHWLIST(w, freezeWorklist);
1785 } else {
1786 PUSHWLIST(w, simplifyWorklist);
1790 static void
1791 Simplify(void)
1793 REGW *w;
1794 ADJL *l;
1796 w = POPWLIST(simplifyWorklist);
1797 PUSHWLIST(w, selectStack);
1798 #ifdef PCC_DEBUG
1799 RDEBUG(("Simplify: node %d class %d\n", ASGNUM(w), w->r_class));
1800 #endif
1802 l = w->r_adjList;
1803 for (; l; l = l->r_next) {
1804 if (ONLIST(l->a_temp) == &selectStack ||
1805 ONLIST(l->a_temp) == &coalescedNodes)
1806 continue;
1807 DecrementDegree(l->a_temp, w->r_class);
1811 static REGW *
1812 GetAlias(REGW *n)
1814 if (ONLIST(n) == &coalescedNodes)
1815 return GetAlias(ALIAS(n));
1816 return n;
1819 static int
1820 OK(REGW *t, REGW *r)
1822 #ifdef PCC_DEBUG
1823 RDEBUG(("OK: t %d CLASS(t) %d adjSet(%d,%d)=%d\n",
1824 ASGNUM(t), CLASS(t), ASGNUM(t), ASGNUM(r), adjSet(t, r)));
1826 if (rdebug > 1) {
1827 ADJL *w;
1828 int ndeg = 0;
1829 printf("OK degree: ");
1830 for (w = ADJLIST(t); w; w = w->r_next) {
1831 if (ONLIST(w->a_temp) != &selectStack &&
1832 ONLIST(w->a_temp) != &coalescedNodes)
1833 printf("%c%d ", CLASS(w->a_temp)+'@',
1834 ASGNUM(w->a_temp)), ndeg++;
1835 else
1836 printf("(%d) ", ASGNUM(w->a_temp));
1838 printf("\n");
1839 #if 0
1840 if (ndeg != DEGREE(t) && DEGREE(t) >= 0)
1841 printf("!!!ndeg %d != DEGREE(t) %d\n", ndeg, DEGREE(t));
1842 #endif
1844 #endif
1846 if (trivially_colorable(t) || ONLIST(t) == &precolored ||
1847 (adjSet(t, r) || !aliasmap(CLASS(t), COLOR(r))))/* XXX - check aliasmap */
1848 return 1;
1849 return 0;
1852 static int
1853 adjok(REGW *v, REGW *u)
1855 ADJL *w;
1856 REGW *t;
1858 RDEBUG(("adjok\n"));
1859 for (w = ADJLIST(v); w; w = w->r_next) {
1860 t = w->a_temp;
1861 if (ONLIST(t) == &selectStack || ONLIST(t) == &coalescedNodes)
1862 continue;
1863 if (OK(t, u) == 0)
1864 return 0;
1866 RDEBUG(("adjok returns OK\n"));
1867 return 1;
1871 * Do a conservative estimation of whether two temporaries can
1872 * be coalesced. This is "Briggs-style" check.
1873 * Neither u nor v is precolored when called.
1875 static int
1876 Conservative(REGW *u, REGW *v)
1878 ADJL *w, *ww;
1879 REGW *n;
1880 int xncl[NUMCLASS+1], mcl = 0, j;
1882 for (j = 0; j < NUMCLASS+1; j++)
1883 xncl[j] = 0;
1885 * Increment xncl[class] up to K for each class.
1886 * If all classes has reached K then check colorability and return.
1888 for (w = ADJLIST(u); w; w = w->r_next) {
1889 n = w->a_temp;
1890 if (ONLIST(n) == &selectStack || ONLIST(n) == &coalescedNodes)
1891 continue;
1892 if (xncl[CLASS(n)] == regK[CLASS(n)])
1893 continue;
1894 if (!trivially_colorable(n) || ONLIST(n) == &precolored)
1895 xncl[CLASS(n)]++;
1896 if (xncl[CLASS(n)] < regK[CLASS(n)])
1897 continue;
1898 if (++mcl == NUMCLASS)
1899 goto out; /* cannot get more out of it */
1901 for (w = ADJLIST(v); w; w = w->r_next) {
1902 n = w->a_temp;
1903 if (ONLIST(n) == &selectStack || ONLIST(n) == &coalescedNodes)
1904 continue;
1905 if (xncl[CLASS(n)] == regK[CLASS(n)])
1906 continue;
1907 /* ugly: have we been here already? */
1908 for (ww = ADJLIST(u); ww; ww = ww->r_next)
1909 if (ww->a_temp == n)
1910 break;
1911 if (ww)
1912 continue;
1913 if (!trivially_colorable(n) || ONLIST(n) == &precolored)
1914 xncl[CLASS(n)]++;
1915 if (xncl[CLASS(n)] < regK[CLASS(n)])
1916 continue;
1917 if (++mcl == NUMCLASS)
1918 break;
1920 out: j = trivially_colorable_p(CLASS(u), xncl);
1921 return j;
1924 static void
1925 AddWorkList(REGW *w)
1928 if (ONLIST(w) != &precolored && !MoveRelated(w) &&
1929 trivially_colorable(w)) {
1930 DELWLIST(w);
1931 PUSHWLIST(w, simplifyWorklist);
1935 static void
1936 Combine(REGW *u, REGW *v)
1938 MOVL *m;
1939 ADJL *l;
1940 REGW *t;
1942 #ifdef PCC_DEBUG
1943 RDEBUG(("Combine (%d,%d)\n", ASGNUM(u), ASGNUM(v)));
1944 #endif
1946 if (ONLIST(v) == &freezeWorklist) {
1947 DELWLIST(v);
1948 } else {
1949 DELWLIST(v);
1951 PUSHWLIST(v, coalescedNodes);
1952 ALIAS(v) = u;
1953 #ifdef PCC_DEBUG
1954 if (rdebug) {
1955 printf("adjlist(%d): ", ASGNUM(v));
1956 for (l = ADJLIST(v); l; l = l->r_next)
1957 printf("%d ", l->a_temp->nodnum);
1958 printf("\n");
1960 #endif
1961 #if 1
1963 MOVL *m0 = MOVELIST(v);
1965 for (m0 = MOVELIST(v); m0; m0 = m0->next) {
1966 for (m = MOVELIST(u); m; m = m->next)
1967 if (m->regm == m0->regm)
1968 break; /* Already on list */
1969 if (m)
1970 continue; /* already on list */
1971 MOVELISTADD(u, m0->regm);
1974 #else
1976 if ((m = MOVELIST(u))) {
1977 while (m->next)
1978 m = m->next;
1979 m->next = MOVELIST(v);
1980 } else
1981 MOVELIST(u) = MOVELIST(v);
1982 #endif
1983 EnableMoves(v);
1984 for (l = ADJLIST(v); l; l = l->r_next) {
1985 t = l->a_temp;
1986 if (ONLIST(t) == &selectStack || ONLIST(t) == &coalescedNodes)
1987 continue;
1988 /* Do not add edge if u cannot affect the colorability of t */
1989 /* XXX - check aliasmap */
1990 if (ONLIST(u) != &precolored || aliasmap(CLASS(t), COLOR(u)))
1991 AddEdge(t, u);
1992 DecrementDegree(t, CLASS(v));
1994 if (!trivially_colorable(u) && ONLIST(u) == &freezeWorklist) {
1995 DELWLIST(u);
1996 PUSHWLIST(u, spillWorklist);
1998 #ifdef PCC_DEBUG
1999 if (rdebug) {
2000 ADJL *w;
2001 printf("Combine %d class (%d): ", ASGNUM(u), CLASS(u));
2002 for (w = ADJLIST(u); w; w = w->r_next) {
2003 if (ONLIST(w->a_temp) != &selectStack &&
2004 ONLIST(w->a_temp) != &coalescedNodes)
2005 printf("%d ", ASGNUM(w->a_temp));
2006 else
2007 printf("(%d) ", ASGNUM(w->a_temp));
2009 printf("\n");
2011 #endif
2014 static void
2015 Coalesce(void)
2017 REGM *m;
2018 REGW *x, *y, *u, *v;
2020 m = POPMLIST(worklistMoves);
2021 x = GetAlias(m->src);
2022 y = GetAlias(m->dst);
2024 if (ONLIST(y) == &precolored)
2025 u = y, v = x;
2026 else
2027 u = x, v = y;
2029 #ifdef PCC_DEBUG
2030 RDEBUG(("Coalesce: src %d dst %d u %d v %d x %d y %d\n",
2031 ASGNUM(m->src), ASGNUM(m->dst), ASGNUM(u), ASGNUM(v),
2032 ASGNUM(x), ASGNUM(y)));
2033 #endif
2035 if (CLASS(m->src) != CLASS(m->dst))
2036 comperr("Coalesce: src class %d, dst class %d",
2037 CLASS(m->src), CLASS(m->dst));
2039 if (u == v) {
2040 RDEBUG(("Coalesce: u == v\n"));
2041 PUSHMLIST(m, coalescedMoves, COAL);
2042 AddWorkList(u);
2043 } else if (ONLIST(v) == &precolored || adjSet(u, v)) {
2044 RDEBUG(("Coalesce: constrainedMoves\n"));
2045 PUSHMLIST(m, constrainedMoves, CONSTR);
2046 AddWorkList(u);
2047 AddWorkList(v);
2048 } else if ((ONLIST(u) == &precolored && adjok(v, u)) ||
2049 (ONLIST(u) != &precolored && Conservative(u, v))) {
2050 RDEBUG(("Coalesce: Conservative\n"));
2051 PUSHMLIST(m, coalescedMoves, COAL);
2052 Combine(u, v);
2053 AddWorkList(u);
2054 } else {
2055 RDEBUG(("Coalesce: activeMoves\n"));
2056 PUSHMLIST(m, activeMoves, ACTIVE);
2060 static void
2061 FreezeMoves(REGW *u)
2063 MOVL *w, *o;
2064 REGM *m;
2065 REGW *z;
2066 REGW *x, *y, *v;
2068 for (w = MOVELIST(u); w; w = w->next) {
2069 m = w->regm;
2070 if (m->queue != WLIST && m->queue != ACTIVE)
2071 continue;
2072 x = m->src;
2073 y = m->dst;
2074 if (GetAlias(y) == GetAlias(u))
2075 v = GetAlias(x);
2076 else
2077 v = GetAlias(y);
2078 #ifdef PCC_DEBUG
2079 RDEBUG(("FreezeMoves: u %d (%d,%d) v %d\n",
2080 ASGNUM(u),ASGNUM(x),ASGNUM(y),ASGNUM(v)));
2081 #endif
2082 DLIST_REMOVE(m, link);
2083 PUSHMLIST(m, frozenMoves, FROZEN);
2084 if (ONLIST(v) != &freezeWorklist)
2085 continue;
2086 for (o = MOVELIST(v); o; o = o->next)
2087 if (o->regm->queue == WLIST || o->regm->queue == ACTIVE)
2088 break;
2089 if (o == NULL) {
2090 z = v;
2091 DELWLIST(z);
2092 PUSHWLIST(z, simplifyWorklist);
2097 static void
2098 Freeze(void)
2100 REGW *u;
2103 * To find out:
2104 * Check if the moves to freeze have exactly the same
2105 * interference edges. If they do, coalesce them instead, it
2106 * may free up other nodes that they interfere with.
2110 * Select nodes to freeze first by using following criteria:
2111 * - Trivially colorable
2112 * - Single or few moves to less trivial nodes.
2114 DLIST_FOREACH(u, &freezeWorklist, link) {
2115 if (u >= &nblock[tempmax] || u < &nblock[tempmin])
2116 continue; /* No short range temps */
2117 if (!trivially_colorable(u))
2118 continue; /* Prefer colorable nodes */
2119 /* Check for at most two move-related nodes */
2120 if (u->r_moveList->next && u->r_moveList->next->next)
2121 continue;
2122 /* Ok, remove node */
2123 DLIST_REMOVE(u, link);
2124 u->r_onlist = 0;
2125 break;
2127 if (u == &freezeWorklist) /* Nothing matched criteria, just take one */
2128 u = POPWLIST(freezeWorklist);
2129 PUSHWLIST(u, simplifyWorklist);
2130 #ifdef PCC_DEBUG
2131 RDEBUG(("Freeze %d\n", ASGNUM(u)));
2132 #endif
2133 FreezeMoves(u);
2136 static void
2137 SelectSpill(void)
2139 REGW *w;
2141 RDEBUG(("SelectSpill\n"));
2142 #ifdef PCC_DEBUG
2143 if (rdebug)
2144 DLIST_FOREACH(w, &spillWorklist, link)
2145 printf("SelectSpill: %d\n", ASGNUM(w));
2146 #endif
2148 /* First check if we can spill register variables */
2149 DLIST_FOREACH(w, &spillWorklist, link) {
2150 if (w >= &nblock[tempmin] && w < &nblock[basetemp])
2151 break;
2154 if (w == &spillWorklist) {
2155 /* try to find another long-range variable */
2156 DLIST_FOREACH(w, &spillWorklist, link) {
2157 if (innotspill(w - nblock))
2158 continue;
2159 if (w >= &nblock[tempmin] && w < &nblock[tempmax])
2160 break;
2164 if (w == &spillWorklist) {
2165 /* no heuristics, just fetch first element */
2166 /* but not if leaf */
2167 DLIST_FOREACH(w, &spillWorklist, link) {
2168 if (w->r_nclass[0] == 0)
2169 break;
2173 if (w == &spillWorklist) {
2174 /* Eh, only leaves :-/ Try anyway */
2175 /* May not be useable */
2176 w = DLIST_NEXT(&spillWorklist, link);
2179 DLIST_REMOVE(w, link);
2181 PUSHWLIST(w, simplifyWorklist);
2182 #ifdef PCC_DEBUG
2183 RDEBUG(("Freezing node %d\n", ASGNUM(w)));
2184 #endif
2185 FreezeMoves(w);
2189 * Set class on long-lived temporaries based on its type.
2191 static void
2192 traclass(NODE *p, void *arg)
2194 REGW *nb;
2196 if (p->n_op != TEMP)
2197 return;
2199 nb = &nblock[regno(p)];
2200 if (CLASS(nb) == 0)
2201 CLASS(nb) = gclass(p->n_type);
2204 static void
2205 paint(NODE *p, void *arg)
2207 struct optab *q;
2208 REGW *w, *ww;
2209 int i;
2211 #ifdef notyet
2212 /* XXX - trashes rewrite of trees (short) */
2213 if (!DLIST_ISEMPTY(&spilledNodes, link)) {
2214 p->n_reg = 0;
2215 return;
2217 #endif
2218 if (p->n_regw != NULL) {
2219 /* Must color all allocated regs also */
2220 ww = w = p->n_regw;
2221 q = &table[TBLIDX(p->n_su)];
2222 p->n_reg = COLOR(w);
2223 w++;
2224 if (q->needs & ALLNEEDS)
2225 for (i = 0; i < ncnt(q->needs); i++) {
2226 if (w->r_class == -1)
2227 p->n_reg |= ENCRA(COLOR(ww), i);
2228 else
2229 p->n_reg |= ENCRA(COLOR(w), i);
2230 w++;
2232 } else
2233 p->n_reg = -1;
2234 if (p->n_op == TEMP) {
2235 REGW *nb = &nblock[regno(p)];
2236 regno(p) = COLOR(nb);
2237 if (TCLASS(p->n_su) == 0)
2238 SCLASS(p->n_su, CLASS(nb));
2239 p->n_op = REG;
2240 p->n_lval = 0;
2245 * See if this node have a move that has been removed in Freeze
2246 * but as we can make use of anyway.
2248 static int
2249 colfind(int okColors, REGW *r)
2251 REGW *w;
2252 MOVL *m;
2253 int c;
2255 for (m = MOVELIST(r); m; m = m->next) {
2256 if ((w = m->regm->src) == r)
2257 w = m->regm->dst;
2258 w = GetAlias(w);
2259 if (ONLIST(w) != &coloredNodes && ONLIST(w) != &precolored)
2260 continue; /* Not yet colored */
2261 c = aliasmap(CLASS(w), COLOR(w));
2262 if ((c & okColors) == 0) {
2263 RDEBUG(("colfind: Failed coloring from %d\n", ASGNUM(w)));
2264 continue;
2266 okColors &= c;
2267 RDEBUG(("colfind: Recommend color from %d\n", ASGNUM(w)));
2268 break;
2271 return ffs(okColors)-1;
2274 static void
2275 AssignColors(struct interpass *ip)
2277 struct interpass *ip2;
2278 int okColors, c;
2279 REGW *o, *w;
2280 ADJL *x;
2282 RDEBUG(("AssignColors\n"));
2283 while (!WLISTEMPTY(selectStack)) {
2284 w = POPWLIST(selectStack);
2285 okColors = classmask(CLASS(w));
2286 #ifdef PCC_DEBUG
2287 RDEBUG(("classmask av %d, class %d: %x\n",
2288 w->nodnum, CLASS(w), okColors));
2289 #endif
2291 for (x = ADJLIST(w); x; x = x->r_next) {
2292 o = GetAlias(x->a_temp);
2293 #ifdef PCC_DEBUG
2294 RRDEBUG(("Adj(%d): %d (%d)\n",
2295 ASGNUM(w), ASGNUM(o), ASGNUM(x->a_temp)));
2296 #endif
2298 if (ONLIST(o) == &coloredNodes ||
2299 ONLIST(o) == &precolored) {
2300 c = aliasmap(CLASS(w), COLOR(o));
2301 RRDEBUG(("aliasmap in class %d by color %d: "
2302 "%x, okColors %x\n",
2303 CLASS(w), COLOR(o), c, okColors));
2305 okColors &= ~c;
2308 if (okColors == 0) {
2309 PUSHWLIST(w, spilledNodes);
2310 #ifdef PCC_DEBUG
2311 RDEBUG(("Spilling node %d\n", ASGNUM(w)));
2312 #endif
2313 } else {
2314 c = colfind(okColors, w);
2315 COLOR(w) = color2reg(c, CLASS(w));
2316 PUSHWLIST(w, coloredNodes);
2317 #ifdef PCC_DEBUG
2318 RDEBUG(("Coloring %d with %s, free %x\n",
2319 ASGNUM(w), rnames[COLOR(w)], okColors));
2320 #endif
2323 DLIST_FOREACH(w, &coalescedNodes, link) {
2324 REGW *ww = GetAlias(w);
2325 COLOR(w) = COLOR(ww);
2326 if (ONLIST(ww) == &spilledNodes) {
2327 #ifdef PCC_DEBUG
2328 RDEBUG(("coalesced node %d spilled\n", w->nodnum));
2329 #endif
2330 ww = DLIST_PREV(w, link);
2331 DLIST_REMOVE(w, link);
2332 PUSHWLIST(w, spilledNodes);
2333 w = ww;
2334 } else {
2335 #ifdef PCC_DEBUG
2336 RDEBUG(("Giving coalesced node %d color %s\n",
2337 w->nodnum, rnames[COLOR(w)]));
2338 #endif
2342 #ifdef PCC_DEBUG
2343 if (rdebug)
2344 DLIST_FOREACH(w, &coloredNodes, link)
2345 printf("%d: color %s\n", ASGNUM(w), rnames[COLOR(w)]);
2346 #endif
2347 if (DLIST_ISEMPTY(&spilledNodes, link)) {
2348 DLIST_FOREACH(ip2, ip, qelem)
2349 if (ip2->type == IP_NODE)
2350 walkf(ip2->ip_node, paint, 0);
2354 static REGW *spole;
2356 * Store all spilled nodes in memory by fetching a temporary on the stack.
2357 * Will never end up here if not optimizing.
2359 static void
2360 longtemp(NODE *p, void *arg)
2362 NODE *l, *r;
2363 REGW *w;
2365 if (p->n_op != TEMP)
2366 return;
2367 /* XXX - should have a bitmask to find temps to convert */
2368 DLIST_FOREACH(w, spole, link) {
2369 if (w != &nblock[regno(p)])
2370 continue;
2371 if (w->r_class == 0) {
2372 w->r_color = BITOOR(freetemp(szty(p->n_type)));
2373 w->r_class = 1;
2375 l = mklnode(REG, 0, FPREG, INCREF(p->n_type));
2376 r = mklnode(ICON, w->r_color, 0, INT);
2377 p->n_left = mkbinode(PLUS, l, r, INCREF(p->n_type));
2378 p->n_op = UMUL;
2379 p->n_regw = NULL;
2380 break;
2384 static struct interpass *cip;
2386 * Rewrite a tree by storing a variable in memory.
2387 * XXX - must check if basic block structure is destroyed!
2389 static void
2390 shorttemp(NODE *p, void *arg)
2392 struct interpass *nip;
2393 struct optab *q;
2394 REGW *w;
2395 NODE *l, *r;
2396 int off;
2398 /* XXX - optimize this somewhat */
2399 DLIST_FOREACH(w, spole, link) {
2400 if (w != p->n_regw)
2401 continue;
2402 /* XXX - use canaddr() */
2403 if (p->n_op == OREG || p->n_op == NAME) {
2404 DLIST_REMOVE(w, link);
2405 #ifdef PCC_DEBUG
2406 RDEBUG(("Node %d already in memory\n", ASGNUM(w)));
2407 #endif
2408 break;
2410 #ifdef PCC_DEBUG
2411 RDEBUG(("rewriting node %d\n", ASGNUM(w)));
2412 #endif
2414 off = BITOOR(freetemp(szty(p->n_type)));
2415 l = mklnode(OREG, off, FPREG, p->n_type);
2416 r = talloc();
2418 * If this is a binode which reclaim a leg, and it had
2419 * to walk down the other leg first, then it must be
2420 * split below this node instead.
2422 q = &table[TBLIDX(p->n_su)];
2423 if (optype(p->n_op) == BITYPE &&
2424 (q->rewrite & RLEFT && (p->n_su & DORIGHT) == 0) &&
2425 (TBLIDX(p->n_right->n_su) != 0)) {
2426 *r = *l;
2427 nip = ipnode(mkbinode(ASSIGN, l,
2428 p->n_left, p->n_type));
2429 p->n_left = r;
2430 } else if (optype(p->n_op) == BITYPE &&
2431 (q->rewrite & RRIGHT && (p->n_su & DORIGHT) != 0) &&
2432 (TBLIDX(p->n_left->n_su) != 0)) {
2433 *r = *l;
2434 nip = ipnode(mkbinode(ASSIGN, l,
2435 p->n_right, p->n_type));
2436 p->n_right = r;
2437 } else {
2438 *r = *p;
2439 nip = ipnode(mkbinode(ASSIGN, l, r, p->n_type));
2440 *p = *l;
2442 DLIST_INSERT_BEFORE(cip, nip, qelem);
2443 DLIST_REMOVE(w, link);
2444 break;
2449 * Change the TEMPs in the ipole list to stack variables.
2451 static void
2452 treerewrite(struct interpass *ipole, REGW *rpole)
2454 struct interpass *ip;
2456 spole = rpole;
2458 DLIST_FOREACH(ip, ipole, qelem) {
2459 if (ip->type != IP_NODE)
2460 continue;
2461 cip = ip;
2462 walkf(ip->ip_node, shorttemp, 0); /* convert temps to oregs */
2464 if (!DLIST_ISEMPTY(spole, link))
2465 comperr("treerewrite not empty");
2469 * Change the TEMPs in the ipole list to stack variables.
2471 static void
2472 leafrewrite(struct interpass *ipole, REGW *rpole)
2474 extern NODE *nodepole;
2475 extern int thisline;
2476 struct interpass *ip;
2478 spole = rpole;
2479 DLIST_FOREACH(ip, ipole, qelem) {
2480 if (ip->type != IP_NODE)
2481 continue;
2482 nodepole = ip->ip_node;
2483 thisline = ip->lineno;
2484 walkf(ip->ip_node, longtemp, 0); /* convert temps to oregs */
2486 nodepole = NIL;
2490 * Avoid copying spilled argument to new position on stack.
2492 static int
2493 temparg(struct interpass *ipole, REGW *w)
2495 struct interpass *ip;
2496 NODE *p;
2498 ip = DLIST_NEXT(ipole, qelem); /* PROLOG */
2499 while (ip->type != IP_DEFLAB)
2500 ip = DLIST_NEXT(ip, qelem);
2501 ip = DLIST_NEXT(ip, qelem); /* first NODE */
2502 for (; ip->type != IP_DEFLAB; ip = DLIST_NEXT(ip, qelem)) {
2503 if (ip->type == IP_ASM)
2504 continue;
2505 p = ip->ip_node;
2506 #ifdef notdef
2507 /* register args may already have been put on stack */
2508 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
2509 comperr("temparg");
2510 #endif
2511 if (p->n_op != ASSIGN || p->n_left->n_op != TEMP)
2512 continue; /* unknown tree */
2514 if (p->n_right->n_op != OREG)
2515 continue; /* arg in register */
2516 if (w != &nblock[regno(p->n_left)])
2517 continue;
2518 w->r_color = (int)p->n_right->n_lval;
2519 tfree(p);
2520 /* Cannot DLIST_REMOVE here, would break basic blocks */
2521 /* Make it a nothing instead */
2522 ip->type = IP_ASM;
2523 ip->ip_asm="";
2524 return 1;
2526 return 0;
2529 #define ONLYPERM 1
2530 #define LEAVES 2
2531 #define SMALL 3
2534 * Scan the whole function and search for temporaries to be stored
2535 * on-stack.
2537 * Be careful to not destroy the basic block structure in the first scan.
2539 static int
2540 RewriteProgram(struct interpass *ip)
2542 REGW shortregs, longregs, saveregs, *q;
2543 REGW *w;
2544 int rwtyp;
2546 RDEBUG(("RewriteProgram\n"));
2547 DLIST_INIT(&shortregs, link);
2548 DLIST_INIT(&longregs, link);
2549 DLIST_INIT(&saveregs, link);
2551 /* sort the temporaries in three queues, short, long and perm */
2552 while (!DLIST_ISEMPTY(&spilledNodes, link)) {
2553 w = DLIST_NEXT(&spilledNodes, link);
2554 DLIST_REMOVE(w, link);
2556 if (w >= &nblock[tempmin] && w < &nblock[basetemp]) {
2557 q = &saveregs;
2558 } else if (w >= &nblock[basetemp] && w < &nblock[tempmax]) {
2559 q = &longregs;
2560 } else
2561 q = &shortregs;
2562 DLIST_INSERT_AFTER(q, w, link);
2564 #ifdef PCC_DEBUG
2565 if (rdebug) {
2566 printf("permanent: ");
2567 DLIST_FOREACH(w, &saveregs, link)
2568 printf("%d ", ASGNUM(w));
2569 printf("\nlong-lived: ");
2570 DLIST_FOREACH(w, &longregs, link)
2571 printf("%d ", ASGNUM(w));
2572 printf("\nshort-lived: ");
2573 DLIST_FOREACH(w, &shortregs, link)
2574 printf("%d ", ASGNUM(w));
2575 printf("\n");
2577 #endif
2578 rwtyp = 0;
2580 if (!DLIST_ISEMPTY(&saveregs, link)) {
2581 rwtyp = ONLYPERM;
2582 DLIST_FOREACH(w, &saveregs, link) {
2583 int num = w - nblock - tempmin;
2584 nsavregs[num] = 1;
2587 if (!DLIST_ISEMPTY(&longregs, link)) {
2588 rwtyp = LEAVES;
2589 DLIST_FOREACH(w, &longregs, link) {
2590 w->r_class = xtemps ? temparg(ip, w) : 0;
2594 if (rwtyp == LEAVES) {
2595 leafrewrite(ip, &longregs);
2596 rwtyp = ONLYPERM;
2599 if (rwtyp == 0 && !DLIST_ISEMPTY(&shortregs, link)) {
2600 /* Must rewrite the trees */
2601 treerewrite(ip, &shortregs);
2602 #if 0
2603 if (xtemps)
2604 comperr("treerewrite");
2605 #endif
2606 rwtyp = SMALL;
2609 RDEBUG(("savregs %x rwtyp %d\n", 0, rwtyp));
2611 return rwtyp;
2614 #ifdef PCC_DEBUG
2616 * Print TEMP/REG contents in a node.
2618 void
2619 prtreg(FILE *fp, NODE *p)
2621 int i, n = p->n_su == -1 ? 0 : ncnt(table[TBLIDX(p->n_su)].needs);
2622 if (p->n_reg == -1) goto foo;
2623 if (use_regw || p->n_reg > 0x40000000 || p->n_reg < 0) {
2624 fprintf(fp, "TEMP ");
2625 if (p->n_regw != NULL) {
2626 for (i = 0; i < n+1; i++)
2627 fprintf(fp, "%d ", p->n_regw[i].nodnum);
2628 } else
2629 fprintf(fp, "<undef>");
2630 } else {
2631 foo: fprintf(fp, "REG ");
2632 if (p->n_reg != -1) {
2633 for (i = 0; i < n+1; i++) {
2634 int r = DECRA(p->n_reg, i);
2635 if (r >= MAXREGS)
2636 fprintf(fp, "<badreg> ");
2637 else
2638 fprintf(fp, "%s ", rnames[r]);
2640 } else
2641 fprintf(fp, "<undef>");
2644 #endif
2646 #ifdef notyet
2648 * Assign instructions, calculate evaluation order and
2649 * set temporary register numbers.
2651 static void
2652 insgen()
2654 geninsn(); /* instruction assignment */
2655 sucomp(); /* set evaluation order */
2656 slong(); /* set long temp types */
2657 sshort(); /* set short temp numbers */
2659 #endif
2662 * Do register allocation for trees by graph-coloring.
2664 void
2665 ngenregs(struct p2env *p2e)
2667 struct interpass *ipole = &p2e->ipole;
2668 extern NODE *nodepole;
2669 struct interpass *ip;
2670 int i, j, tbits;
2671 int uu[NPERMREG] = { -1 };
2672 int xnsavregs[NPERMREG];
2673 int beenhere = 0;
2674 TWORD type;
2676 DLIST_INIT(&lunused, link);
2677 DLIST_INIT(&lused, link);
2680 * Do some setup before doing the real thing.
2682 tempmin = p2e->ipp->ip_tmpnum;
2683 tempmax = p2e->epp->ip_tmpnum;
2686 * Allocate space for the permanent registers in the
2687 * same block as the long-lived temporaries.
2688 * These temporaries will be handled the same way as
2689 * all other variables.
2691 basetemp = tempmin;
2692 nsavregs = xnsavregs;
2693 for (i = 0; i < NPERMREG; i++)
2694 xnsavregs[i] = 0;
2695 ndontregs = uu; /* currently never avoid any regs */
2697 tempmin -= (NPERMREG-1);
2698 #ifdef notyet
2699 if (xavoidfp)
2700 dontregs |= REGBIT(FPREG);
2701 #endif
2703 #ifdef PCC_DEBUG
2704 nodnum = tempmax;
2705 #endif
2706 tbits = tempmax - tempmin; /* # of temporaries */
2707 xbits = tbits + MAXREGS; /* total size of live array */
2708 if (tbits) {
2709 nblock = tmpalloc(tbits * sizeof(REGW));
2711 nblock -= tempmin;
2712 #ifdef HAVE_C99_FORMAT
2713 RDEBUG(("nblock %p num %d size %zu\n",
2714 nblock, tbits, (size_t)(tbits * sizeof(REGW))));
2715 #endif
2717 live = tmpalloc(BIT2BYTE(xbits));
2719 /* Block for precolored nodes */
2720 ablock = tmpalloc(sizeof(REGW)*MAXREGS);
2721 memset(ablock, 0, sizeof(REGW)*MAXREGS);
2722 for (i = 0; i < MAXREGS; i++) {
2723 ablock[i].r_onlist = &precolored;
2724 ablock[i].r_class = GCLASS(i); /* XXX */
2725 ablock[i].r_color = i;
2726 #ifdef PCC_DEBUG
2727 ablock[i].nodnum = i;
2728 #endif
2730 #ifdef notyet
2731 TMPMARK();
2732 #endif
2735 recalc:
2736 onlyperm: /* XXX - should not have to redo all */
2737 memset(edgehash, 0, sizeof(edgehash));
2739 if (tbits) {
2740 memset(nblock+tempmin, 0, tbits * sizeof(REGW));
2741 #ifdef PCC_DEBUG
2742 for (i = tempmin; i < tempmax; i++)
2743 nblock[i].nodnum = i;
2744 #endif
2746 memset(live, 0, BIT2BYTE(xbits));
2747 RPRINTIP(ipole);
2748 DLIST_INIT(&initial, link);
2749 DLIST_FOREACH(ip, ipole, qelem) {
2750 extern int thisline;
2751 if (ip->type != IP_NODE)
2752 continue;
2753 nodepole = ip->ip_node;
2754 thisline = ip->lineno;
2755 if (ip->ip_node->n_op != XASM)
2756 geninsn(ip->ip_node, FOREFF);
2757 nsucomp(ip->ip_node);
2758 walkf(ip->ip_node, traclass, 0);
2760 nodepole = NIL;
2761 RDEBUG(("nsucomp allocated %d temps (%d,%d)\n",
2762 tempmax-tempmin, tempmin, tempmax));
2764 #ifdef PCC_DEBUG
2765 use_regw = 1;
2766 RPRINTIP(ipole);
2767 use_regw = 0;
2768 #endif
2769 RDEBUG(("ngenregs: numtemps %d (%d, %d)\n", tempmax-tempmin,
2770 tempmin, tempmax));
2772 DLIST_INIT(&coalescedMoves, link);
2773 DLIST_INIT(&constrainedMoves, link);
2774 DLIST_INIT(&frozenMoves, link);
2775 DLIST_INIT(&worklistMoves, link);
2776 DLIST_INIT(&activeMoves, link);
2778 /* Set class and move-related for perm regs */
2779 for (i = 0; i < (NPERMREG-1); i++) {
2780 if (nsavregs[i])
2781 continue;
2782 nblock[i+tempmin].r_class = GCLASS(permregs[i]);
2783 DLIST_INSERT_AFTER(&initial, &nblock[i+tempmin], link);
2784 moveadd(&nblock[i+tempmin], &ablock[permregs[i]]);
2785 addalledges(&nblock[i+tempmin]);
2788 Build(p2e);
2789 RDEBUG(("Build done\n"));
2790 MkWorklist();
2791 RDEBUG(("MkWorklist done\n"));
2792 do {
2793 if (!WLISTEMPTY(simplifyWorklist))
2794 Simplify();
2795 else if (!WLISTEMPTY(worklistMoves))
2796 Coalesce();
2797 else if (!WLISTEMPTY(freezeWorklist))
2798 Freeze();
2799 else if (!WLISTEMPTY(spillWorklist))
2800 SelectSpill();
2801 } while (!WLISTEMPTY(simplifyWorklist) || !WLISTEMPTY(worklistMoves) ||
2802 !WLISTEMPTY(freezeWorklist) || !WLISTEMPTY(spillWorklist));
2803 AssignColors(ipole);
2805 RDEBUG(("After AssignColors\n"));
2806 RPRINTIP(ipole);
2808 if (!WLISTEMPTY(spilledNodes)) {
2809 switch (RewriteProgram(ipole)) {
2810 case ONLYPERM:
2811 goto onlyperm;
2812 case SMALL:
2813 optimize(p2e);
2814 if (beenhere++ == MAXLOOP)
2815 comperr("cannot color graph - COLORMAP() bug?");
2816 goto recalc;
2820 /* fill in regs to save */
2821 memset(p2e->ipp->ipp_regs, 0, sizeof(p2e->ipp->ipp_regs));
2822 for (i = 0; i < NPERMREG-1; i++) {
2823 NODE *p;
2825 if (nsavregs[i]) {
2826 BITSET(p2e->ipp->ipp_regs, permregs[i]);
2827 continue; /* Spilled */
2829 if (nblock[i+tempmin].r_color == permregs[i])
2830 continue; /* Coalesced */
2832 * If the original color of this permreg is used for
2833 * coloring another register, swap them to avoid
2834 * unnecessary moves.
2836 for (j = i+1; j < NPERMREG-1; j++) {
2837 if (nblock[j+tempmin].r_color != permregs[i])
2838 continue;
2839 nblock[j+tempmin].r_color = nblock[i+tempmin].r_color;
2840 break;
2842 if (j != NPERMREG-1)
2843 continue;
2845 /* Generate reg-reg move nodes for save */
2846 type = PERMTYPE(permregs[i]);
2847 #ifdef PCC_DEBUG
2848 if (PERMTYPE(nblock[i+tempmin].r_color) != type)
2849 comperr("permreg botch");
2850 #endif
2851 p = mkbinode(ASSIGN,
2852 mklnode(REG, 0, nblock[i+tempmin].r_color, type),
2853 mklnode(REG, 0, permregs[i], type), type);
2854 p->n_reg = p->n_left->n_reg = p->n_right->n_reg = -1;
2855 p->n_left->n_su = p->n_right->n_su = 0;
2856 geninsn(p, FOREFF);
2857 ip = ipnode(p);
2858 DLIST_INSERT_AFTER(ipole->qelem.q_forw, ip, qelem);
2859 p = mkbinode(ASSIGN, mklnode(REG, 0, permregs[i], type),
2860 mklnode(REG, 0, nblock[i+tempmin].r_color, type), type);
2861 p->n_reg = p->n_left->n_reg = p->n_right->n_reg = -1;
2862 p->n_left->n_su = p->n_right->n_su = 0;
2863 geninsn(p, FOREFF);
2864 ip = ipnode(p);
2865 DLIST_INSERT_BEFORE(ipole->qelem.q_back, ip, qelem);
2867 memcpy(p2e->epp->ipp_regs, p2e->ipp->ipp_regs, sizeof(p2e->epp->ipp_regs));
2868 /* Done! */