1 /* $Id: optim2.c,v 1.79 2010/06/04 07:18:46 ragge Exp $ */
3 * Copyright (c) 2004 Anders Magnusson (ragge@ludd.luth.se).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
35 #define MIN(a,b) (((a)<(b))?(a):(b))
39 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
42 #define BDEBUG(x) if (b2debug) printf x
44 #define mktemp(n, t) mklnode(TEMP, 0, n, t)
46 #define CHADD(bb,c) { if (bb->ch[0] == 0) bb->ch[0] = c; \
47 else if (bb->ch[1] == 0) bb->ch[1] = c; \
48 else comperr("triple cfnodes"); }
49 #define FORCH(cn, chp) \
50 for (cn = &chp[0]; cn < &chp[2] && cn[0]; cn++)
52 /* main switch for new things not yet ready for all-day use */
53 /* #define ENABLE_NEW */
58 void saveip(struct interpass
*ip
);
59 void deljumps(struct p2env
*);
60 void optdump(struct interpass
*ip
);
61 void printip(struct interpass
*pole
);
63 static struct varinfo defsites
;
64 struct interpass
*storesave
;
66 void bblocks_build(struct p2env
*);
67 void cfg_build(struct p2env
*);
68 void cfg_dfs(struct basicblock
*bb
, unsigned int parent
,
69 struct bblockinfo
*bbinfo
);
70 void dominators(struct p2env
*);
72 ancestorwithlowestsemi(struct basicblock
*bblock
, struct bblockinfo
*bbinfo
);
73 void link(struct basicblock
*parent
, struct basicblock
*child
);
74 void computeDF(struct p2env
*, struct basicblock
*bblock
);
75 void printDF(struct p2env
*p2e
);
76 void findTemps(struct interpass
*ip
);
77 void placePhiFunctions(struct p2env
*);
78 void renamevar(struct p2env
*p2e
,struct basicblock
*bblock
);
79 void removephi(struct p2env
*p2e
);
80 void remunreach(struct p2env
*);
81 static void liveanal(struct p2env
*p2e
);
82 static void printip2(struct interpass
*);
84 /* create "proper" basic blocks, add labels where needed (so bblocks have labels) */
85 /* run before bb generate */
86 static void add_labels(struct p2env
*) ;
88 /* Perform trace scheduling, try to get rid of gotos as much as possible */
89 void TraceSchedule(struct p2env
*) ;
92 static void do_cse(struct p2env
* p2e
) ;
95 /* Walk the complete set, performing a function on each node.
96 * if type is given, apply function on only that type */
97 void WalkAll(struct p2env
* p2e
, void (*f
) (NODE
*, void*), void* arg
, int type
) ;
99 void BBLiveDead(struct basicblock
* bblock
, int what
, unsigned int variable
) ;
101 /* Fill the live/dead code */
102 void LiveDead(struct p2env
* p2e
, int what
, unsigned int variable
) ;
105 void printflowdiagram(struct p2env
*, char *);
109 optimize(struct p2env
*p2e
)
111 struct interpass
*ipole
= &p2e
->ipole
;
114 printf("initial links\n");
119 deljumps(p2e
); /* Delete redundant jumps and dead code */
129 printf("links after deljumps\n");
133 if (xssaflag
|| xtemps
) {
135 BDEBUG(("Calling cfg_build\n"));
139 printflowdiagram(p2e
, "first");
143 BDEBUG(("Calling liveanal\n"));
145 BDEBUG(("Calling dominators\n"));
147 BDEBUG(("Calling computeDF\n"));
148 computeDF(p2e
, DLIST_NEXT(&p2e
->bblocks
, bbelem
));
154 BDEBUG(("Calling placePhiFunctions\n"));
156 placePhiFunctions(p2e
);
158 BDEBUG(("Calling renamevar\n"));
160 renamevar(p2e
,DLIST_NEXT(&p2e
->bblocks
, bbelem
));
162 BDEBUG(("Calling removephi\n"));
165 printflowdiagram(p2e
, "ssa");
170 BDEBUG(("Calling remunreach\n"));
171 /* remunreach(p2e); */
174 * Recalculate basic blocks and cfg that was destroyed
177 /* first, clean up all what deljumps should have done, and more */
179 /* TODO: add the basic blocks done by the ssa code by hand.
180 * The trace scheduler should not change the order in
181 * which blocks are executed or what data is calculated.
182 * Thus, the BBlock order should remain correct.
186 bblocks_build(p2e
, &labinfo
, &bbinfo
);
187 BDEBUG(("Calling cfg_build\n"));
188 cfg_build(p2e
, &labinfo
);
192 printflowdiagram(p2e
, &labinfo
, &bbinfo
,"sched_trace");
195 printf("after tracesched\n");
202 /* Now, clean up the gotos we do not need any longer */
204 deljumps(p2e
); /* Delete redundant jumps and dead code */
207 BDEBUG(("Calling cfg_build\n"));
211 printflowdiagram(p2e
, "no_phi");
214 printf("new tree\n");
223 for (i
= NIPPREGS
; i
--; )
224 if (p2e
->epp
->ipp_regs
[i
] != 0)
225 comperr("register error");
233 * Delete unused labels, excess of labels, gotos to gotos.
234 * This routine can be made much more efficient.
236 * Layout of the statement list here (_must_ look this way!):
238 * LABEL - states beginning of function argument moves
239 * ...code to save/move arguments
240 * LABEL - states beginning of execution code
241 * ...code + labels in function in function
244 * This version of deljumps is based on the c2 implementation
245 * that were included in 2BSD.
254 struct interpass
*dlip
;
264 dumplink(struct dlnod
*dl
)
266 printf("dumplink %p\n", dl
);
267 for (; dl
; dl
= dl
->forw
) {
268 if (dl
->op
== STMT
) {
269 printf("STMT(%p)\n", dl
);
270 fwalk(dl
->dlip
->ip_node
, e2print
, 0);
271 } else if (dl
->op
== EROU
) {
272 printf("EROU(%p)\n", dl
);
274 static char *str
[] = { 0, "LABEL", "JBR", "CBR" };
275 printf("%s(%p) %d refc %d ref %p\n", str
[dl
->op
],
276 dl
, dl
->labno
, dl
->refc
, dl
->ref
);
279 printf("end dumplink\n");
284 * Create the linked list that we can work on.
287 listsetup(struct interpass
*ipole
, struct dlnod
*dl
)
289 struct interpass
*ip
= DLIST_NEXT(ipole
, qelem
);
290 struct interpass
*nip
;
291 struct dlnod
*p
, *lastp
;
295 while (ip
->type
!= IP_DEFLAB
)
296 ip
= DLIST_NEXT(ip
,qelem
);
297 ip
= DLIST_NEXT(ip
,qelem
);
298 while (ip
->type
!= IP_DEFLAB
)
299 ip
= DLIST_NEXT(ip
,qelem
);
300 /* Now ip is at the beginning */
302 ip
= DLIST_NEXT(ip
,qelem
);
305 p
= tmpalloc(sizeof(struct dlnod
));
311 p
->labno
= ip
->ip_lbl
;
319 p
->labno
= q
->n_left
->n_lval
;
323 p
->labno
= q
->n_right
->n_lval
;
326 /* remove ASSIGN to self for regs */
327 if (q
->n_left
->n_op
== REG
&&
328 q
->n_right
->n_op
== REG
&&
329 regno(q
->n_left
) == regno(q
->n_right
)) {
330 nip
= DLIST_PREV(ip
, qelem
);
332 DLIST_REMOVE(ip
, qelem
);
352 comperr("listsetup: bad ip node %d", ip
->type
);
362 static struct dlnod
*
363 nonlab(struct dlnod
*p
)
365 while (p
&& p
->op
==LABEL
)
371 iprem(struct dlnod
*p
)
373 if (p
->dlip
->type
== IP_NODE
)
374 tfree(p
->dlip
->ip_node
);
375 DLIST_REMOVE(p
->dlip
, qelem
);
379 decref(struct dlnod
*p
)
381 if (--p
->refc
<= 0) {
383 p
->back
->forw
= p
->forw
;
384 p
->forw
->back
= p
->back
;
389 setlab(struct dlnod
*p
, int labno
)
393 p
->dlip
->ip_node
->n_left
->n_lval
= labno
;
394 else if (p
->op
== CBR
) {
395 p
->dlip
->ip_node
->n_right
->n_lval
= labno
;
396 p
->dlip
->ip_node
->n_left
->n_label
= labno
;
398 comperr("setlab bad op %d", p
->op
);
402 * Label reference counting and removal of unused labels.
406 refcount(struct p2env
*p2e
, struct dlnod
*dl
)
408 struct dlnod
*p
, *lp
;
409 struct dlnod
*labhash
[LABHS
];
410 struct dlnod
**hp
, *tp
;
412 /* Clear label hash */
413 for (hp
= labhash
; hp
< &labhash
[LABHS
];)
415 /* Enter labels into hash. Later overwrites earlier */
416 for (p
= dl
->forw
; p
!=0; p
= p
->forw
)
418 labhash
[p
->labno
% LABHS
] = p
;
422 /* search for jumps to labels and fill in reference */
423 for (p
= dl
->forw
; p
!=0; p
= p
->forw
) {
424 if (p
->op
==JBR
|| p
->op
==CBR
) {
426 lp
= labhash
[p
->labno
% LABHS
];
427 if (lp
==0 || p
->labno
!=lp
->labno
)
428 for (lp
= dl
->forw
; lp
!=0; lp
= lp
->forw
) {
429 if (lp
->op
==LABEL
&& p
->labno
==lp
->labno
)
433 tp
= nonlab(lp
)->back
;
435 setlab(p
, tp
->labno
);
443 for (p
= dl
->forw
; p
!=0; p
= p
->forw
)
444 if (p
->op
==LABEL
&& p
->refc
==0 && (lp
= nonlab(p
))->op
)
450 static struct dlnod
*
451 codemove(struct dlnod
*p
)
453 struct dlnod
*p1
, *p2
, *p3
;
455 struct dlnod
*t
, *tl
;
460 if (p1
->op
!=JBR
|| (p2
= p1
->ref
)==0)
462 while (p2
->op
== LABEL
)
463 if ((p2
= p2
->back
) == 0)
473 if (p1
==p3
|| p1
->forw
==p3
|| p1
->back
==p3
)
477 p1
->dlip
->qelem
.q_back
->qelem
.q_forw
= p2
->dlip
;
480 p1
->dlip
->qelem
.q_forw
->qelem
.q_back
= p3
->dlip
;
483 p2
->back
->forw
= p3
->forw
;
484 p2
->dlip
->qelem
.q_back
->qelem
.q_forw
= p3
->forw
->dlip
;
486 p3
->forw
->back
= p2
->back
;
487 p3
->dlip
->qelem
.q_forw
->qelem
.q_back
= p2
->back
->dlip
;
490 p2
->dlip
->qelem
.q_back
= p1
->dlip
->qelem
.q_back
;
493 p3
->dlip
->qelem
.q_forw
= p1
->forw
->dlip
;
496 if (p1
->dlip
->type
== IP_NODE
)
497 tfree(p1
->dlip
->ip_node
);
506 if (p1
->forw
->op
!=LABEL
)
514 if ((p3
= p3
->forw
) == 0 || p3
==p1
|| --n
==0)
516 } while (p3
->op
!=CBR
|| p3
->labno
!=p1
->forw
->labno
);
518 if ((p1
= p1
->back
) == 0)
523 p3
->subop
= revbr
[p3
->subop
];
535 p2
= insertl(p1
->forw
);
536 p3
->labno
= p2
->labno
;
547 iterate(struct p2env
*p2e
, struct dlnod
*dl
)
549 struct dlnod
*p
, *rp
, *p1
;
551 extern size_t negrelsize
;
555 for (p
= dl
->forw
; p
!=0; p
= p
->forw
) {
556 if ((p
->op
==JBR
||p
->op
==CBR
) && p
->ref
) {
563 if (rp
->op
==JBR
&& rp
->labno
&& p
->labno
!=rp
->labno
) {
564 setlab(p
, rp
->labno
);
571 if (p
->op
==CBR
&& (p1
= p
->forw
)->op
==JBR
) {
580 while (rp
->op
==LABEL
);
584 setlab(p
, p1
->labno
);
591 i
= p
->dlip
->ip_node
->n_left
->n_op
;
592 if (i
< EQ
|| i
- EQ
>= (int)negrelsize
)
593 comperr("deljumps: unexpected op");
594 p
->dlip
->ip_node
->n_left
->n_op
= negrel
[i
- EQ
];
599 /* Removes dead code */
600 while (p
->forw
&& p
->forw
->op
!=LABEL
&&
604 decref(p
->forw
->ref
);
608 p
->forw
= p
->forw
->forw
;
612 while (rp
&& rp
->op
==LABEL
) {
614 p
->back
->forw
= p
->forw
;
615 p
->forw
->back
= p
->back
;
626 /* xjump(p); * needs tree rewrite; not yet */
633 deljumps(struct p2env
*p2e
)
635 struct interpass
*ipole
= &p2e
->ipole
;
641 memset(&dln
, 0, sizeof(dln
));
642 listsetup(ipole
, &dln
);
657 optdump(struct interpass
*ip
)
659 static char *nm
[] = { "node", "prolog", "newblk", "epilog", "locctr",
660 "deflab", "defnam", "asm" };
661 printf("type %s\n", nm
[ip
->type
-1]);
665 fwalk(ip
->ip_node
, e2print
, 0);
669 printf("label " LABFMT
"\n", ip
->ip_lbl
);
672 printf(": %s\n", ip
->ip_asm
);
678 * Build the basic blocks, algorithm 9.1, pp 529 in Compilers.
680 * Also fills the labelinfo struct with information about which bblocks
681 * that contain which label.
685 bblocks_build(struct p2env
*p2e
)
687 struct interpass
*ipole
= &p2e
->ipole
;
688 struct interpass
*ip
;
689 struct basicblock
*bb
= NULL
;
694 BDEBUG(("bblocks_build (%p, %p)\n", &p2e
->labinfo
, &p2e
->bbinfo
));
695 low
= p2e
->ipp
->ip_lblnum
;
696 high
= p2e
->epp
->ip_lblnum
;
699 * First statement is a leader.
700 * Any statement that is target of a jump is a leader.
701 * Any statement that immediately follows a jump is a leader.
703 DLIST_INIT(&p2e
->bblocks
, bbelem
);
704 DLIST_FOREACH(ip
, ipole
, qelem
) {
705 if (bb
== NULL
|| (ip
->type
== IP_EPILOG
) ||
706 (ip
->type
== IP_DEFLAB
) || (ip
->type
== IP_DEFNAM
)) {
707 bb
= tmpalloc(sizeof(struct basicblock
));
709 SLIST_INIT(&bb
->parents
);
710 bb
->ch
[0] = bb
->ch
[1] = NULL
;
719 bb
->dfchildren
= NULL
;
722 SLIST_INIT(&bb
->phi
);
724 DLIST_INSERT_BEFORE(&p2e
->bblocks
, bb
, bbelem
);
728 if ((ip
->type
== IP_NODE
) && (ip
->ip_node
->n_op
== GOTO
||
729 ip
->ip_node
->n_op
== CBRANCH
))
731 if (ip
->type
== IP_PROLOG
)
734 p2e
->nbblocks
= count
;
737 printf("Basic blocks in func: %d, low %d, high %d\n",
739 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
740 printf("bb(%d) %p: first %p last %p\n", bb
->bbnum
, bb
,
741 bb
->first
, bb
->last
);
745 p2e
->labinfo
.low
= low
;
746 p2e
->labinfo
.size
= high
- low
+ 1;
747 p2e
->labinfo
.arr
= tmpalloc(p2e
->labinfo
.size
* sizeof(struct basicblock
*));
748 for (i
= 0; i
< p2e
->labinfo
.size
; i
++) {
749 p2e
->labinfo
.arr
[i
] = NULL
;
752 p2e
->bbinfo
.size
= count
+ 1;
753 p2e
->bbinfo
.arr
= tmpalloc(p2e
->bbinfo
.size
* sizeof(struct basicblock
*));
754 for (i
= 0; i
< p2e
->bbinfo
.size
; i
++) {
755 p2e
->bbinfo
.arr
[i
] = NULL
;
758 /* Build the label table */
759 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
760 if (bb
->first
->type
== IP_DEFLAB
)
761 p2e
->labinfo
.arr
[bb
->first
->ip_lbl
- low
] = bb
;
765 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
766 printf("bblock %d\n", bb
->bbnum
);
767 for (ip
= bb
->first
; ip
!= bb
->last
;
768 ip
= DLIST_NEXT(ip
, qelem
)) {
774 printf("Label table:\n");
775 for (i
= 0; i
< p2e
->labinfo
.size
; i
++)
776 if (p2e
->labinfo
.arr
[i
])
777 printf("Label %d bblock %p\n", i
+low
,
778 p2e
->labinfo
.arr
[i
]);
783 * Build the control flow graph.
787 cfg_build(struct p2env
*p2e
)
789 /* Child and parent nodes */
790 struct cfgnode
*cnode
;
791 struct cfgnode
*pnode
;
792 struct basicblock
*bb
;
794 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
796 if (bb
->first
->type
== IP_EPILOG
) {
800 cnode
= tmpalloc(sizeof(struct cfgnode
));
801 pnode
= tmpalloc(sizeof(struct cfgnode
));
804 if ((bb
->last
->type
== IP_NODE
) &&
805 (bb
->last
->ip_node
->n_op
== GOTO
) &&
806 (bb
->last
->ip_node
->n_left
->n_op
== ICON
)) {
807 if (bb
->last
->ip_node
->n_left
->n_lval
- p2e
->labinfo
.low
>
809 comperr("Label out of range: %d, base %d",
810 bb
->last
->ip_node
->n_left
->n_lval
,
813 cnode
->bblock
= p2e
->labinfo
.arr
[bb
->last
->ip_node
->n_left
->n_lval
- p2e
->labinfo
.low
];
814 SLIST_INSERT_LAST(&cnode
->bblock
->parents
, pnode
, cfgelem
);
818 if ((bb
->last
->type
== IP_NODE
) &&
819 (bb
->last
->ip_node
->n_op
== CBRANCH
)) {
820 if (bb
->last
->ip_node
->n_right
->n_lval
- p2e
->labinfo
.low
>
822 comperr("Label out of range: %d",
823 bb
->last
->ip_node
->n_left
->n_lval
);
825 cnode
->bblock
= p2e
->labinfo
.arr
[bb
->last
->ip_node
->n_right
->n_lval
- p2e
->labinfo
.low
];
826 SLIST_INSERT_LAST(&cnode
->bblock
->parents
, pnode
, cfgelem
);
828 cnode
= tmpalloc(sizeof(struct cfgnode
));
829 pnode
= tmpalloc(sizeof(struct cfgnode
));
833 cnode
->bblock
= DLIST_NEXT(bb
, bbelem
);
834 SLIST_INSERT_LAST(&cnode
->bblock
->parents
, pnode
, cfgelem
);
840 cfg_dfs(struct basicblock
*bb
, unsigned int parent
, struct bblockinfo
*bbinfo
)
847 bb
->dfnum
= ++dfsnum
;
848 bb
->dfparent
= parent
;
849 bbinfo
->arr
[bb
->dfnum
] = bb
;
851 cfg_dfs((*cn
)->bblock
, bb
->dfnum
, bbinfo
);
852 /* Don't bring in unreachable nodes in the future */
853 bbinfo
->size
= dfsnum
+ 1;
860 int sz
= (nelem
+NUMBITS
-1)/NUMBITS
;
862 b
= tmpalloc(sz
* sizeof(bittype
));
863 memset(b
, 0, sz
* sizeof(bittype
));
868 * Algorithm 19.9, pp 414 from Appel.
872 dominators(struct p2env
*p2e
)
874 struct cfgnode
*cnode
;
875 struct basicblock
*bb
, *y
, *v
;
876 struct basicblock
*s
, *sprime
, *p
;
879 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
880 bb
->bucket
= setalloc(p2e
->bbinfo
.size
);
881 bb
->df
= setalloc(p2e
->bbinfo
.size
);
882 bb
->dfchildren
= setalloc(p2e
->bbinfo
.size
);
886 cfg_dfs(DLIST_NEXT(&p2e
->bblocks
, bbelem
), 0, &p2e
->bbinfo
);
889 struct basicblock
*bbb
;
890 struct cfgnode
*ccnode
, **cn
;
892 DLIST_FOREACH(bbb
, &p2e
->bblocks
, bbelem
) {
893 printf("Basic block %d, parents: ", bbb
->dfnum
);
894 SLIST_FOREACH(ccnode
, &bbb
->parents
, cfgelem
) {
895 printf("%d, ", ccnode
->bblock
->dfnum
);
897 printf("\nChildren: ");
899 printf("%d, ", (*cn
)->bblock
->dfnum
);
904 for(h
= p2e
->bbinfo
.size
- 1; h
> 1; h
--) {
905 bb
= p2e
->bbinfo
.arr
[h
];
906 p
= s
= p2e
->bbinfo
.arr
[bb
->dfparent
];
907 SLIST_FOREACH(cnode
, &bb
->parents
, cfgelem
) {
908 if (cnode
->bblock
->dfnum
==0)
909 continue; /* Ignore unreachable code */
911 if (cnode
->bblock
->dfnum
<= bb
->dfnum
)
912 sprime
= cnode
->bblock
;
914 sprime
= p2e
->bbinfo
.arr
[ancestorwithlowestsemi
915 (cnode
->bblock
, &p2e
->bbinfo
)->semi
];
916 if (sprime
->dfnum
< s
->dfnum
)
920 BITSET(s
->bucket
, bb
->dfnum
);
922 for (i
= 1; i
< p2e
->bbinfo
.size
; i
++) {
923 if(TESTBIT(p
->bucket
, i
)) {
924 v
= p2e
->bbinfo
.arr
[i
];
925 y
= ancestorwithlowestsemi(v
, &p2e
->bbinfo
);
926 if (y
->semi
== v
->semi
)
929 v
->samedom
= y
->dfnum
;
932 memset(p
->bucket
, 0, (p2e
->bbinfo
.size
+ 7)/8);
936 printf("Num\tSemi\tAncest\tidom\n");
937 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
938 printf("%d\t%d\t%d\t%d\n", bb
->dfnum
, bb
->semi
,
939 bb
->ancestor
, bb
->idom
);
943 for(h
= 2; h
< p2e
->bbinfo
.size
; h
++) {
944 bb
= p2e
->bbinfo
.arr
[h
];
945 if (bb
->samedom
!= 0) {
946 bb
->idom
= p2e
->bbinfo
.arr
[bb
->samedom
]->idom
;
949 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
950 if (bb
->idom
!= 0 && bb
->idom
!= bb
->dfnum
) {
951 BDEBUG(("Setting child %d of %d\n",
952 bb
->dfnum
, p2e
->bbinfo
.arr
[bb
->idom
]->dfnum
));
953 BITSET(p2e
->bbinfo
.arr
[bb
->idom
]->dfchildren
, bb
->dfnum
);
960 ancestorwithlowestsemi(struct basicblock
*bblock
, struct bblockinfo
*bbinfo
)
962 struct basicblock
*u
= bblock
;
963 struct basicblock
*v
= bblock
;
965 while (v
->ancestor
!= 0) {
966 if (bbinfo
->arr
[v
->semi
]->dfnum
<
967 bbinfo
->arr
[u
->semi
]->dfnum
)
969 v
= bbinfo
->arr
[v
->ancestor
];
975 link(struct basicblock
*parent
, struct basicblock
*child
)
977 child
->ancestor
= parent
->dfnum
;
981 computeDF(struct p2env
*p2e
, struct basicblock
*bblock
)
986 FORCH(cn
, bblock
->ch
) {
987 if ((*cn
)->bblock
->idom
!= bblock
->dfnum
)
988 BITSET(bblock
->df
, (*cn
)->bblock
->dfnum
);
990 for (h
= 1; h
< p2e
->bbinfo
.size
; h
++) {
991 if (!TESTBIT(bblock
->dfchildren
, h
))
993 computeDF(p2e
, p2e
->bbinfo
.arr
[h
]);
994 for (i
= 1; i
< p2e
->bbinfo
.size
; i
++) {
995 if (TESTBIT(p2e
->bbinfo
.arr
[h
]->df
, i
) &&
996 (p2e
->bbinfo
.arr
[i
] == bblock
||
997 (bblock
->dfnum
!= p2e
->bbinfo
.arr
[i
]->idom
)))
998 BITSET(bblock
->df
, i
);
1003 void printDF(struct p2env
*p2e
)
1005 struct basicblock
*bb
;
1008 printf("Dominance frontiers:\n");
1010 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
1011 printf("bb %d : ", bb
->dfnum
);
1013 for (i
=1; i
< p2e
->bbinfo
.size
;i
++) {
1014 if (TESTBIT(bb
->df
,i
)) {
1026 static struct basicblock
*currbb
;
1027 static struct interpass
*currip
;
1029 /* Helper function for findTemps, Find assignment nodes. */
1031 searchasg(NODE
*p
, void *arg
)
1033 struct pvarinfo
*pv
;
1035 struct varstack
*stacke
;
1037 if (p
->n_op
!= ASSIGN
)
1040 if (p
->n_left
->n_op
!= TEMP
)
1043 tempnr
=regno(p
->n_left
)-defsites
.low
;
1045 BITSET(currbb
->Aorig
, tempnr
);
1047 pv
= tmpcalloc(sizeof(struct pvarinfo
));
1048 pv
->next
= defsites
.arr
[tempnr
];
1050 pv
->n_type
= p
->n_left
->n_type
;
1052 defsites
.arr
[tempnr
] = pv
;
1055 if (SLIST_FIRST(&defsites
.stack
[tempnr
])==NULL
) {
1056 stacke
=tmpcalloc(sizeof (struct varstack
));
1058 SLIST_INSERT_FIRST(&defsites
.stack
[tempnr
],stacke
,varstackelem
);
1062 /* Walk the interpass looking for assignment nodes. */
1063 void findTemps(struct interpass
*ip
)
1065 if (ip
->type
!= IP_NODE
)
1070 walkf(ip
->ip_node
, searchasg
, 0);
1074 * Algorithm 19.6 from Appel.
1078 placePhiFunctions(struct p2env
*p2e
)
1080 struct basicblock
*bb
;
1081 struct basicblock
*y
;
1082 struct interpass
*ip
;
1083 int maxtmp
, i
, j
, k
;
1085 struct cfgnode
*cnode
;
1087 struct pvarinfo
*pv
;
1088 struct phiinfo
*phi
;
1091 bb
= DLIST_NEXT(&p2e
->bblocks
, bbelem
);
1092 defsites
.low
= ((struct interpass_prolog
*)bb
->first
)->ip_tmpnum
;
1093 bb
= DLIST_PREV(&p2e
->bblocks
, bbelem
);
1094 maxtmp
= ((struct interpass_prolog
*)bb
->first
)->ip_tmpnum
;
1095 defsites
.size
= maxtmp
- defsites
.low
+ 1;
1096 defsites
.arr
= tmpcalloc(defsites
.size
*sizeof(struct pvarinfo
*));
1097 defsites
.stack
= tmpcalloc(defsites
.size
*sizeof(SLIST_HEAD(, varstack
)));
1099 for (i
=0;i
<defsites
.size
;i
++)
1100 SLIST_INIT(&defsites
.stack
[i
]);
1102 /* Find all defsites */
1103 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
1106 bb
->Aorig
= setalloc(defsites
.size
);
1107 bb
->Aphi
= setalloc(defsites
.size
);
1109 while (ip
!= bb
->last
) {
1111 ip
= DLIST_NEXT(ip
, qelem
);
1113 /* Make sure we get the last statement in the bblock */
1117 /* For each variable */
1118 for (i
= 0; i
< defsites
.size
; i
++) {
1119 /* While W not empty */
1120 while (defsites
.arr
[i
] != NULL
) {
1121 /* Remove some node n from W */
1122 n
= defsites
.arr
[i
];
1123 defsites
.arr
[i
] = n
->next
;
1124 /* For each y in n->bb->df */
1125 for (j
= 0; j
< p2e
->bbinfo
.size
; j
++) {
1126 if (!TESTBIT(n
->bb
->df
, j
))
1129 if (TESTBIT(p2e
->bbinfo
.arr
[j
]->Aphi
, i
))
1132 y
=p2e
->bbinfo
.arr
[j
];
1135 /* Amount of predecessors for y */
1136 SLIST_FOREACH(cnode
, &y
->parents
, cfgelem
)
1138 /* Construct phi(...)
1143 SLIST_FOREACH(phi
, &y
->phi
, phielem
) {
1144 if (phi
->tmpregno
==i
+defsites
.low
)
1150 printf("Phi in %d(%d) (%p) for %d\n",
1151 y
->dfnum
,y
->bbnum
,y
,i
+defsites
.low
);
1153 /* If no live in, no phi node needed */
1155 (i
+defsites
.low
-p2e
->ipp
->ip_tmpnum
+MAXREGS
))) {
1157 printf("tmp %d bb %d unused, no phi\n",
1158 i
+defsites
.low
, y
->bbnum
);
1160 BITSET(p2e
->bbinfo
.arr
[j
]->Aphi
, i
);
1164 phi
= tmpcalloc(sizeof(struct phiinfo
));
1166 phi
->tmpregno
=i
+defsites
.low
;
1169 phi
->intmpregno
=tmpcalloc(k
*sizeof(int));
1171 SLIST_INSERT_LAST(&y
->phi
,phi
,phielem
);
1174 printf("Phi already in %d for %d\n",y
->dfnum
,i
+defsites
.low
);
1177 BITSET(p2e
->bbinfo
.arr
[j
]->Aphi
, i
);
1178 if (!TESTBIT(p2e
->bbinfo
.arr
[j
]->Aorig
, i
)) {
1179 pv
= tmpalloc(sizeof(struct pvarinfo
));
1182 pv
->next
= defsites
.arr
[i
];
1183 defsites
.arr
[i
] = pv
;
1190 /* Helper function for renamevar. */
1192 renamevarhelper(struct p2env
*p2e
,NODE
*t
,void *poplistarg
)
1194 SLIST_HEAD(, varstack
) *poplist
=poplistarg
;
1199 struct varstack
*stacke
;
1201 if (t
->n_op
== ASSIGN
&& t
->n_left
->n_op
== TEMP
) {
1202 renamevarhelper(p2e
,t
->n_right
,poplist
);
1204 tempnr
=regno(t
->n_left
)-defsites
.low
;
1206 newtempnr
=p2e
->epp
->ip_tmpnum
++;
1207 regno(t
->n_left
)=newtempnr
;
1209 stacke
=tmpcalloc(sizeof (struct varstack
));
1210 stacke
->tmpregno
=newtempnr
;
1211 SLIST_INSERT_FIRST(&defsites
.stack
[tempnr
],stacke
,varstackelem
);
1213 stacke
=tmpcalloc(sizeof (struct varstack
));
1214 stacke
->tmpregno
=tempnr
;
1215 SLIST_INSERT_FIRST(poplist
,stacke
,varstackelem
);
1217 if (t
->n_op
== TEMP
) {
1218 tempnr
=regno(t
)-defsites
.low
;
1220 if (SLIST_FIRST(&defsites
.stack
[tempnr
])!=NULL
) {
1221 x
=SLIST_FIRST(&defsites
.stack
[tempnr
])->tmpregno
;
1226 opty
= optype(t
->n_op
);
1229 renamevarhelper(p2e
, t
->n_left
,poplist
);
1231 renamevarhelper(p2e
, t
->n_right
,poplist
);
1237 renamevar(struct p2env
*p2e
,struct basicblock
*bb
)
1239 struct interpass
*ip
;
1241 SLIST_HEAD(, varstack
) poplist
;
1242 struct varstack
*stacke
;
1243 struct cfgnode
*cfgn2
, **cn
;
1244 int tmpregno
,newtmpregno
;
1245 struct phiinfo
*phi
;
1247 SLIST_INIT(&poplist
);
1249 SLIST_FOREACH(phi
,&bb
->phi
,phielem
) {
1250 tmpregno
=phi
->tmpregno
-defsites
.low
;
1252 newtmpregno
=p2e
->epp
->ip_tmpnum
++;
1253 phi
->newtmpregno
=newtmpregno
;
1255 stacke
=tmpcalloc(sizeof (struct varstack
));
1256 stacke
->tmpregno
=newtmpregno
;
1257 SLIST_INSERT_FIRST(&defsites
.stack
[tmpregno
],stacke
,varstackelem
);
1259 stacke
=tmpcalloc(sizeof (struct varstack
));
1260 stacke
->tmpregno
=tmpregno
;
1261 SLIST_INSERT_FIRST(&poplist
,stacke
,varstackelem
);
1268 if ( ip
->type
== IP_NODE
) {
1269 renamevarhelper(p2e
,ip
->ip_node
,&poplist
);
1275 ip
= DLIST_NEXT(ip
, qelem
);
1281 SLIST_FOREACH(cfgn2
, &(*cn
)->bblock
->parents
, cfgelem
) {
1282 if (cfgn2
->bblock
->dfnum
==bb
->dfnum
)
1288 SLIST_FOREACH(phi
,&(*cn
)->bblock
->phi
,phielem
) {
1289 phi
->intmpregno
[j
]=SLIST_FIRST(&defsites
.stack
[phi
->tmpregno
-defsites
.low
])->tmpregno
;
1293 for (h
= 1; h
< p2e
->bbinfo
.size
; h
++) {
1294 if (!TESTBIT(bb
->dfchildren
, h
))
1297 renamevar(p2e
,p2e
->bbinfo
.arr
[h
]);
1300 SLIST_FOREACH(stacke
,&poplist
,varstackelem
) {
1301 tmpregno
=stacke
->tmpregno
;
1303 defsites
.stack
[tmpregno
].q_forw
=defsites
.stack
[tmpregno
].q_forw
->varstackelem
.q_forw
;
1311 pred_falltrough
= 3,
1315 removephi(struct p2env
*p2e
)
1317 struct basicblock
*bb
,*bbparent
;
1318 struct cfgnode
*cfgn
;
1319 struct phiinfo
*phi
;
1321 struct interpass
*ip
;
1322 struct interpass
*pip
;
1325 enum pred_type
complex = pred_unknown
;
1330 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
1331 SLIST_FOREACH(phi
,&bb
->phi
,phielem
) {
1332 /* Look at only one, notice break at end */
1335 SLIST_FOREACH(cfgn
, &bb
->parents
, cfgelem
) {
1336 bbparent
=cfgn
->bblock
;
1340 complex = pred_unknown
;
1342 BDEBUG(("removephi: %p in %d",pip
,bb
->dfnum
));
1344 if (pip
->type
== IP_NODE
&& pip
->ip_node
->n_op
== GOTO
) {
1346 label
= (int)pip
->ip_node
->n_left
->n_lval
;
1347 complex = pred_goto
;
1348 } else if (pip
->type
== IP_NODE
&& pip
->ip_node
->n_op
== CBRANCH
) {
1349 BDEBUG((" CBRANCH "));
1350 label
= (int)pip
->ip_node
->n_right
->n_lval
;
1352 if (bb
==p2e
->labinfo
.arr
[label
- p2e
->ipp
->ip_lblnum
])
1353 complex = pred_cond
;
1355 complex = pred_falltrough
;
1357 } else if (DLIST_PREV(bb
, bbelem
) == bbparent
) {
1358 complex = pred_falltrough
;
1361 comperr("Assumption blown in rem-phi") ;
1364 BDEBUG((" Complex: %d ",complex)) ;
1368 /* gotos can only go to this place. No bounce tab needed */
1369 SLIST_FOREACH(phi
,&bb
->phi
,phielem
) {
1370 if (phi
->intmpregno
[i
]>0) {
1372 ip
= ipnode(mkbinode(ASSIGN
,
1373 mktemp(phi
->newtmpregno
, n_type
),
1374 mktemp(phi
->intmpregno
[i
],n_type
),
1376 BDEBUG(("(%p, %d -> %d) ", ip
, phi
->intmpregno
[i
], phi
->newtmpregno
));
1378 DLIST_INSERT_BEFORE((bbparent
->last
), ip
, qelem
);
1383 /* Here, we need a jump pad */
1386 ip
= tmpalloc(sizeof(struct interpass
));
1387 ip
->type
= IP_DEFLAB
;
1388 /* Line number?? ip->lineno; */
1389 ip
->ip_lbl
= newlabel
;
1390 DLIST_INSERT_BEFORE((bb
->first
), ip
, qelem
);
1392 SLIST_FOREACH(phi
,&bb
->phi
,phielem
) {
1393 if (phi
->intmpregno
[i
]>0) {
1395 ip
= ipnode(mkbinode(ASSIGN
,
1396 mktemp(phi
->newtmpregno
, n_type
),
1397 mktemp(phi
->intmpregno
[i
],n_type
),
1400 BDEBUG(("(%p, %d -> %d) ", ip
, phi
->intmpregno
[i
], phi
->newtmpregno
));
1401 DLIST_INSERT_BEFORE((bb
->first
), ip
, qelem
);
1404 /* add a jump to us */
1405 ip
= ipnode(mkunode(GOTO
, mklnode(ICON
, label
, 0, INT
), 0, INT
));
1406 DLIST_INSERT_BEFORE((bb
->first
), ip
, qelem
);
1407 pip
->ip_node
->n_right
->n_lval
=newlabel
;
1408 if (!logop(pip
->ip_node
->n_left
->n_op
))
1409 comperr("SSA not logop");
1410 pip
->ip_node
->n_left
->n_label
=newlabel
;
1412 case pred_falltrough
:
1413 if (bb
->first
->type
== IP_DEFLAB
) {
1414 label
= bb
->first
->ip_lbl
;
1415 BDEBUG(("falltrough label %d\n", label
));
1417 comperr("BBlock has no label?") ;
1421 * add a jump to us. We _will_ be, or already have, added code in between.
1422 * The code is created in the wrong order and switched at the insert, thus
1423 * comming out correctly
1426 ip
= ipnode(mkunode(GOTO
, mklnode(ICON
, label
, 0, INT
), 0, INT
));
1427 DLIST_INSERT_AFTER((bbparent
->last
), ip
, qelem
);
1429 /* Add the code to the end, add a jump to us. */
1430 SLIST_FOREACH(phi
,&bb
->phi
,phielem
) {
1431 if (phi
->intmpregno
[i
]>0) {
1433 ip
= ipnode(mkbinode(ASSIGN
,
1434 mktemp(phi
->newtmpregno
, n_type
),
1435 mktemp(phi
->intmpregno
[i
],n_type
),
1438 BDEBUG(("(%p, %d -> %d) ", ip
, phi
->intmpregno
[i
], phi
->newtmpregno
));
1439 DLIST_INSERT_AFTER((bbparent
->last
), ip
, qelem
);
1444 comperr("assumption blown, complex is %d\n", complex) ;
1456 * Remove unreachable nodes in the CFG.
1460 remunreach(struct p2env
*p2e
)
1462 struct basicblock
*bb
, *nbb
;
1463 struct interpass
*next
, *ctree
;
1465 bb
= DLIST_NEXT(&p2e
->bblocks
, bbelem
);
1466 while (bb
!= &p2e
->bblocks
) {
1467 nbb
= DLIST_NEXT(bb
, bbelem
);
1469 /* Code with dfnum 0 is unreachable */
1470 if (bb
->dfnum
!= 0) {
1475 /* Need the epilogue node for other parts of the
1476 compiler, set its label to 0 and backend will
1478 if (bb
->first
->type
== IP_EPILOG
) {
1479 bb
->first
->ip_lbl
= 0;
1487 next
= DLIST_NEXT(ctree
, qelem
);
1489 if (ctree
->type
== IP_NODE
)
1490 tfree(ctree
->ip_node
);
1491 DLIST_REMOVE(ctree
, qelem
);
1492 } while (ctree
!= bb
->last
);
1494 DLIST_REMOVE(bb
, bbelem
);
1500 printip2(struct interpass
*ip
)
1502 static char *foo
[] = {
1503 0, "NODE", "PROLOG", "STKOFF", "EPILOG", "DEFLAB", "DEFNAM", "ASM" };
1504 struct interpass_prolog
*ipplg
, *epplg
;
1507 if (ip
->type
> MAXIP
)
1508 printf("IP(%d) (%p): ", ip
->type
, ip
);
1510 printf("%s (%p): ", foo
[ip
->type
], ip
);
1512 case IP_NODE
: printf("\n");
1514 fwalk(ip
->ip_node
, e2print
, 0); break;
1517 ipplg
= (struct interpass_prolog
*)ip
;
1518 printf("%s %s regs",
1519 ipplg
->ipp_name
, ipplg
->ipp_vis
? "(local)" : "");
1520 for (i
= 0; i
< NIPPREGS
; i
++)
1521 printf("%s0x%lx", i
? ":" : " ",
1522 (long) ipplg
->ipp_regs
[i
]);
1523 printf(" autos %d mintemp %d minlbl %d\n",
1524 ipplg
->ipp_autos
, ipplg
->ip_tmpnum
, ipplg
->ip_lblnum
);
1527 epplg
= (struct interpass_prolog
*)ip
;
1528 printf("%s %s regs",
1529 epplg
->ipp_name
, epplg
->ipp_vis
? "(local)" : "");
1530 for (i
= 0; i
< NIPPREGS
; i
++)
1531 printf("%s0x%lx", i
? ":" : " ",
1532 (long) epplg
->ipp_regs
[i
]);
1533 printf(" autos %d mintemp %d minlbl %d\n",
1534 epplg
->ipp_autos
, epplg
->ip_tmpnum
, epplg
->ip_lblnum
);
1536 case IP_DEFLAB
: printf(LABFMT
"\n", ip
->ip_lbl
); break;
1537 case IP_DEFNAM
: printf("\n"); break;
1538 case IP_ASM
: printf("%s\n", ip
->ip_asm
); break;
1545 printip(struct interpass
*pole
)
1547 struct interpass
*ip
;
1549 DLIST_FOREACH(ip
, pole
, qelem
)
1554 void flownodeprint(NODE
*p
,FILE *flowdiagramfile
);
1557 flownodeprint(NODE
*p
,FILE *flowdiagramfile
)
1562 fprintf(flowdiagramfile
,"{");
1567 if (*o
=='<' || *o
=='>')
1568 fputc('\\',flowdiagramfile
);
1570 fputc(*o
,flowdiagramfile
);
1577 fprintf(flowdiagramfile
, " %s", rnames
[p
->n_rval
] );
1581 fprintf(flowdiagramfile
, " %d", regno(p
));
1586 fprintf(flowdiagramfile
, " '%s'", p
->n_name
);
1592 fprintf(flowdiagramfile
, " " );
1593 adrput(flowdiagramfile
, p
);
1600 fprintf(flowdiagramfile
, " size=%d", p
->n_stsize
);
1601 fprintf(flowdiagramfile
, " align=%d", p
->n_stalign
);
1605 opty
= optype(p
->n_op
);
1607 if (opty
!= LTYPE
) {
1608 fprintf(flowdiagramfile
,"| {");
1610 flownodeprint(p
->n_left
,flowdiagramfile
);
1612 if (opty
== BITYPE
) {
1613 fprintf(flowdiagramfile
,"|");
1614 flownodeprint(p
->n_right
,flowdiagramfile
);
1616 fprintf(flowdiagramfile
,"}");
1619 fprintf(flowdiagramfile
,"}");
1623 printflowdiagram(struct p2env
*p2e
, char *type
) {
1624 struct basicblock
*bbb
;
1625 struct cfgnode
**cn
;
1626 struct interpass
*ip
;
1627 struct interpass_prolog
*plg
;
1628 struct phiinfo
*phi
;
1633 FILE *flowdiagramfile
;
1638 bbb
=DLIST_NEXT(&p2e
->bblocks
, bbelem
);
1641 if (ip
->type
!= IP_PROLOG
)
1643 plg
= (struct interpass_prolog
*)ip
;
1647 filenamesize
=strlen(name
)+1+strlen(type
)+strlen(ext
)+1;
1648 filename
=tmpalloc(filenamesize
);
1649 snprintf(filename
,filenamesize
,"%s-%s%s",name
,type
,ext
);
1651 flowdiagramfile
=fopen(filename
,"w");
1653 fprintf(flowdiagramfile
,"digraph {\n");
1654 fprintf(flowdiagramfile
,"rankdir=LR\n");
1656 DLIST_FOREACH(bbb
, &p2e
->bblocks
, bbelem
) {
1659 fprintf(flowdiagramfile
,"bb%p [shape=record ",bbb
);
1661 if (ip
->type
==IP_PROLOG
)
1662 fprintf(flowdiagramfile
,"root ");
1664 fprintf(flowdiagramfile
,"label=\"");
1666 SLIST_FOREACH(phi
,&bbb
->phi
,phielem
) {
1667 fprintf(flowdiagramfile
,"Phi %d|",phi
->tmpregno
);
1674 flownodeprint(ip
->ip_node
,flowdiagramfile
);
1678 fprintf(flowdiagramfile
,"Label: %d", ip
->ip_lbl
);
1682 plg
= (struct interpass_prolog
*)ip
;
1684 fprintf(flowdiagramfile
,"%s %s",plg
->ipp_name
,type
);
1688 fprintf(flowdiagramfile
,"|");
1689 fprintf(flowdiagramfile
,"|");
1694 ip
= DLIST_NEXT(ip
, qelem
);
1696 fprintf(flowdiagramfile
,"\"]\n");
1698 FORCH(cn
, bbb
->ch
) {
1699 char *color
="black";
1700 struct interpass
*pip
=bbb
->last
;
1702 if (pip
->type
== IP_NODE
&& pip
->ip_node
->n_op
== CBRANCH
) {
1703 int label
= (int)pip
->ip_node
->n_right
->n_lval
;
1705 if ((*cn
)->bblock
==p2e
->labinfo
.arr
[label
- p2e
->ipp
->ip_lblnum
])
1709 fprintf(flowdiagramfile
,"bb%p -> bb%p [color=%s]\n", bbb
,(*cn
)->bblock
,color
);
1713 fprintf(flowdiagramfile
,"}\n");
1714 fclose(flowdiagramfile
);
1719 /* walk all the programm */
1720 void WalkAll(struct p2env
* p2e
, void (*f
) (NODE
*, void*), void* arg
, int type
)
1722 struct interpass
*ipole
= &p2e
->ipole
;
1723 struct interpass
*ip
;
1725 DLIST_FOREACH(ip
, ipole
, qelem
) {
1726 if (ip
->type
== IP_NODE
&& ip
->ip_node
->n_op
== type
)
1727 walkf(ip
->ip_node
, f
, arg
) ;
1730 DLIST_FOREACH(ip
, ipole
, qelem
) {
1731 if (ip
->type
== IP_NODE
)
1732 walkf(ip
->ip_node
, f
, arg
) ;
1737 static int is_goto_label(struct interpass
*g
, struct interpass
* l
)
1741 if (g
->type
!= IP_NODE
) return 0 ;
1742 if (l
->type
!= IP_DEFLAB
) return 0 ;
1743 if (g
->ip_node
->n_op
!= GOTO
) return 0 ;
1744 if (g
->ip_node
->n_left
->n_lval
!= l
->ip_lbl
) return 0 ;
1750 * iterate over the basic blocks.
1751 * In case a block has only one successor and that one has only one pred, and the link is a goto:
1752 * place the second one immediately behind the first one (in terms of nodes, means cut&resplice).
1753 * This should take care of a lot of jumps.
1754 * one problem: Cannot move the first or last basic block (prolog/epilog). This is taken care of by
1755 * moving block #1 to #2, not #2 to #1
1756 * More complex (on the back cooker;) : first coalesc the inner loops (L1 cache), then go from inside out.
1759 static unsigned long count_blocks(struct p2env
* p2e
)
1761 struct basicblock
* bb
;
1762 unsigned long count
= 0 ;
1763 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
1770 struct basicblock
* block
;
1771 unsigned long index
;
1772 unsigned long thread
;
1775 static unsigned long map_blocks(struct p2env
* p2e
, struct block_map
* map
, unsigned long count
)
1777 struct basicblock
* bb
;
1778 unsigned long indx
= 0 ;
1780 unsigned long thread
;
1781 unsigned long changes
;
1783 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
1784 map
[indx
].block
= bb
;
1785 map
[indx
].index
= indx
;
1787 /* ignore the first 2 labels, maybe up to 3 BBs */
1789 if (bb
->first
->type
== IP_DEFLAB
)
1792 map
[indx
].thread
= 1 ; /* these are "fixed" */
1794 map
[indx
].thread
= 0 ;
1803 for (indx
=0; indx
< count
; indx
++) {
1804 /* find block without trace */
1805 if (map
[indx
].thread
== 0) {
1807 struct cfgnode
**cn
;
1808 struct basicblock
*block2
= 0;
1810 unsigned long added
;
1812 BDEBUG (("new thread %ld at block %ld\n", thread
, indx
)) ;
1814 bb
= map
[indx
].block
;
1818 for (i
=0; i
< count
; i
++) {
1819 if (map
[i
].block
== bb
&& map
[i
].thread
== 0) {
1820 map
[i
].thread
= thread
;
1822 BDEBUG(("adding block %ld to trace %ld\n", i
, thread
)) ;
1828 * pick one from followers. For now (simple), pick the
1829 * one who is directly following us. If none of that exists,
1830 * this code picks the last one.
1834 block2
=(*cn
)->bblock
;
1836 if (i
+1 < count
&& map
[i
+1].block
== block2
)
1837 break ; /* pick that one */
1853 /* Last block is also a thread on it's own, and the highest one. */
1856 map[count-1].thread = thread ;
1859 printf("Threads\n");
1860 for (indx
=0; indx
< count
; indx
++) {
1861 printf("Block #%ld (lbl %d) Thread %ld\n", indx
, map
[indx
].block
->first
->ip_lbl
, map
[indx
].thread
);
1868 void TraceSchedule(struct p2env
* p2e
)
1870 struct block_map
* map
;
1871 unsigned long block_count
= count_blocks(p2e
);
1873 unsigned long threads
;
1874 struct interpass
*front
, *back
;
1876 map
= tmpalloc(block_count
* sizeof(struct block_map
));
1878 threads
= map_blocks(p2e
, map
, block_count
) ;
1880 back
= map
[0].block
->last
;
1881 for (i
=1; i
< block_count
; i
++) {
1882 /* collect the trace */
1884 unsigned long thread
= map
[i
].thread
;
1886 BDEBUG(("Thread %ld\n", thread
)) ;
1887 for (j
=i
; j
< block_count
; j
++) {
1888 if (map
[j
].thread
== thread
) {
1889 front
= map
[j
].block
->first
;
1891 BDEBUG(("Trace %ld, old BB %ld, next BB %ld\t",
1893 BDEBUG(("Label %d\n", front
->ip_lbl
)) ;
1894 DLIST_NEXT(back
, qelem
) = front
;
1895 DLIST_PREV(front
, qelem
) = back
;
1896 map
[j
].thread
= 0 ; /* done */
1897 back
= map
[j
].block
->last
;
1898 DLIST_NEXT(back
, qelem
) = 0 ;
1903 DLIST_NEXT(back
, qelem
) = &(p2e
->ipole
) ;
1904 DLIST_PREV(&p2e
->ipole
, qelem
) = back
;
1907 static void add_labels(struct p2env
* p2e
)
1909 struct interpass
*ipole
= &p2e
->ipole
;
1910 struct interpass
*ip
;
1912 DLIST_FOREACH(ip
, ipole
, qelem
) {
1913 if (ip
->type
== IP_NODE
&& ip
->ip_node
->n_op
== CBRANCH
) {
1914 struct interpass
*n
= DLIST_NEXT(ip
, qelem
);
1915 if (n
&& n
->type
!= IP_DEFLAB
) {
1916 struct interpass
* lab
;
1917 int newlabel
=getlab2() ;
1919 BDEBUG(("add_label L%d\n", newlabel
));
1921 lab
= tmpalloc(sizeof(struct interpass
));
1922 lab
->type
= IP_DEFLAB
;
1923 /* Line number?? ip->lineno; */
1924 lab
->ip_lbl
= newlabel
;
1925 DLIST_INSERT_AFTER(ip
, lab
, qelem
);
1934 NODE
* node
; /* the node */
1935 unsigned int node_num
; /* node is equal to that one */
1936 unsigned int var_num
; /* node computes this variable */
1939 static unsigned long nodes_counter
;
1940 static void node_map_count_walker(NODE
* n
, void* x
)
1945 static void do_cse(struct p2env
* p2e
)
1948 WalkAll(p2e
, node_map_count_walker
, 0, 0) ;
1949 BDEBUG(("Found %ld nodes\n", nodes_counter
)) ;
1953 #define BITALLOC(ptr,all,sz) { \
1954 int sz__s = BIT2BYTE(sz); ptr = all(sz__s); memset(ptr, 0, sz__s); }
1955 #define VALIDREG(p) (p->n_op == REG && TESTBIT(validregs, regno(p)))
1956 #define XCHECK(x) if (x < 0 || x >= xbits) printf("x out of range %d\n", x)
1957 #define RUP(x) (((x)+NUMBITS-1)/NUMBITS)
1958 #define SETCOPY(t,f,i,n) for (i = 0; i < RUP(n); i++) t[i] = f[i]
1959 #define SETSET(t,f,i,n) for (i = 0; i < RUP(n); i++) t[i] |= f[i]
1960 #define SETCLEAR(t,f,i,n) for (i = 0; i < RUP(n); i++) t[i] &= ~f[i]
1961 #define SETCMP(v,t,f,i,n) for (i = 0; i < RUP(n); i++) \
1962 if (t[i] != f[i]) v = 1
1964 static int xxx
, xbits
;
1966 * Set/clear long term liveness for regs and temps.
1969 unionize(NODE
*p
, struct basicblock
*bb
, int suboff
)
1973 if ((o
= p
->n_op
) == TEMP
|| VALIDREG(p
)) {
1976 b
= b
- suboff
+ MAXREGS
;
1981 if (p
->n_left
->n_op
== TEMP
|| VALIDREG(p
)) {
1982 int b
= regno(p
->n_left
);
1983 if (p
->n_left
->n_op
== TEMP
)
1984 b
= b
- suboff
+ MAXREGS
;
1986 BITCLEAR(bb
->gen
, b
);
1987 BITSET(bb
->killed
, b
);
1988 unionize(p
->n_right
, bb
, suboff
);
1994 unionize(p
->n_left
, bb
, suboff
);
1996 unionize(p
->n_right
, bb
, suboff
);
2000 * Found an extended assembler node, so growel out gen/killed nodes.
2003 xasmionize(NODE
*p
, void *arg
)
2005 struct basicblock
*bb
= arg
;
2008 if (p
->n_op
== ICON
&& p
->n_type
== STRTY
)
2009 return; /* dummy end marker */
2011 cw
= xasmcode(p
->n_name
);
2012 if (XASMVAL(cw
) == 'n' || XASMVAL(cw
) == 'm')
2013 return; /* no flow analysis */
2016 if (XASMVAL(cw
) == 'g' && p
->n_op
!= TEMP
&& p
->n_op
!= REG
)
2017 return; /* no flow analysis */
2021 if (XASMVAL(cw
) == 'r' && p
->n_op
== TEMP
)
2024 #define MKTOFF(r) ((r) - xxx)
2025 if (XASMISOUT(cw
)) {
2026 if (p
->n_op
== TEMP
) {
2027 BITCLEAR(bb
->gen
, MKTOFF(b
));
2028 BITSET(bb
->killed
, MKTOFF(b
));
2029 } else if (p
->n_op
== REG
) {
2030 BITCLEAR(bb
->gen
, b
);
2031 BITSET(bb
->killed
, b
);
2033 uerror("bad xasm node type %d", p
->n_op
);
2035 if (XASMISINP(cw
)) {
2036 if (p
->n_op
== TEMP
) {
2037 BITSET(bb
->gen
, MKTOFF(b
));
2038 } else if (p
->n_op
== REG
) {
2040 } else if (optype(p
->n_op
) != LTYPE
) {
2041 if (XASMVAL(cw
) == 'r')
2042 uerror("couldn't find available register");
2044 uerror("bad xasm node type2");
2050 * Do variable liveness analysis. Only analyze the long-lived
2051 * variables, and save the live-on-exit temporaries in a bit-field
2052 * at the end of each basic block. This bit-field is later used
2053 * when doing short-range liveness analysis in Build().
2056 liveanal(struct p2env
*p2e
)
2058 struct basicblock
*bb
;
2059 struct interpass
*ip
;
2061 int i
, mintemp
, again
;
2063 xbits
= p2e
->epp
->ip_tmpnum
- p2e
->ipp
->ip_tmpnum
+ MAXREGS
;
2064 mintemp
= p2e
->ipp
->ip_tmpnum
;
2066 /* Just fetch space for the temporaries from heap */
2067 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
2068 BITALLOC(bb
->gen
,tmpalloc
,xbits
);
2069 BITALLOC(bb
->killed
,tmpalloc
,xbits
);
2070 BITALLOC(bb
->in
,tmpalloc
,xbits
);
2071 BITALLOC(bb
->out
,tmpalloc
,xbits
);
2073 BITALLOC(saved
,tmpalloc
,xbits
);
2077 * generate the gen-killed sets for all basic blocks.
2079 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
2080 for (ip
= bb
->last
; ; ip
= DLIST_PREV(ip
, qelem
)) {
2081 /* gen/killed is 'p', this node is 'n' */
2082 if (ip
->type
== IP_NODE
) {
2083 if (ip
->ip_node
->n_op
== XASM
)
2084 flist(ip
->ip_node
->n_left
,
2087 unionize(ip
->ip_node
, bb
, mintemp
);
2089 if (ip
== bb
->first
)
2092 memcpy(bb
->in
, bb
->gen
, BIT2BYTE(xbits
));
2094 #define PRTRG(x) printf("%d ", i < MAXREGS ? i : i + p2e->ipp->ip_tmpnum-MAXREGS)
2096 printf("basic block %d\ngen: ", bb
->bbnum
);
2097 for (i
= 0; i
< xbits
; i
++)
2098 if (TESTBIT(bb
->gen
, i
))
2100 printf("\nkilled: ");
2101 for (i
= 0; i
< xbits
; i
++)
2102 if (TESTBIT(bb
->killed
, i
))
2108 /* do liveness analysis on basic block level */
2110 struct cfgnode
**cn
;
2114 /* XXX - loop should be in reversed execution-order */
2115 DLIST_FOREACH_REVERSE(bb
, &p2e
->bblocks
, bbelem
) {
2116 SETCOPY(saved
, bb
->out
, j
, xbits
);
2118 SETSET(bb
->out
, cn
[0]->bblock
->in
, j
, xbits
);
2120 SETCMP(again
, saved
, bb
->out
, j
, xbits
);
2121 SETCOPY(saved
, bb
->in
, j
, xbits
);
2122 SETCOPY(bb
->in
, bb
->out
, j
, xbits
);
2123 SETCLEAR(bb
->in
, bb
->killed
, j
, xbits
);
2124 SETSET(bb
->in
, bb
->gen
, j
, xbits
);
2125 SETCMP(again
, saved
, bb
->in
, j
, xbits
);
2130 DLIST_FOREACH(bb
, &p2e
->bblocks
, bbelem
) {
2132 printf("all basic block %d\nin: ", bb
->bbnum
);
2133 for (i
= 0; i
< xbits
; i
++)
2134 if (TESTBIT(bb
->in
, i
))
2137 for (i
= 0; i
< xbits
; i
++)
2138 if (TESTBIT(bb
->out
, i
))