1 /* $Id: bo.c,v 1.13 1994/11/29 14:53:02 ceriel Exp $ */
3 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
4 * See the copyright notice in the ACK home directory, in the file "Copyright".
6 /* B R A N C H O P T I M I Z A T I O N
17 #include "../share/types.h"
18 #include "../share/debug.h"
19 #include "../share/global.h"
20 #include "../share/files.h"
21 #include "../share/get.h"
22 #include "../share/put.h"
23 #include "../share/lset.h"
24 #include "../share/map.h"
25 #include "../share/alloc.h"
26 #include "../share/aux.h"
27 #include "../share/def.h"
28 #include "../share/go.h"
30 extern char em_flag[];
32 #define LP_BLOCKS lp_extend->lpx_ra.lpx_blocks
34 #define newbolpx() (lpext_p) newstruct(lpext_ra)
35 #define oldbolpx(x) oldstruct(lpext_ra,x)
37 STATIC int Sbo; /* #optimizations found */
39 #define DLINK(l1,l2) l1->l_next=l2; l2->l_prev=l1
41 /* This module performs some very simple branch optimizations.
43 * I) Look for pairs of basic blocks (B1,B2), such that
46 * In this case B1 and B2 can be combined into one block.
47 * This optimization is mainly succesful:
48 * 1) for switch statements in C, as the C compiler generates a branch
49 * over the entire switch.
50 * 2) for return statements, if the only way to return from a procedure
51 * is via a return statement somewhere in the middle of the procedure.
52 * II) Optimize while statements. Transformations like:
59 * are done by this optimization.
64 STATIC line_p last_code(lines,skip_pseu)
68 /* Determine the last line of a list */
72 for (l = lines; l->l_next != (line_p) 0; l = l->l_next);
74 while (l && (INSTR(l) < sp_fmnem || INSTR(l) > sp_lmnem)) l = PREV(l);
79 STATIC short cc_tab[12] =
80 {op_blt,op_zlt,op_ble,op_zle,op_beq,op_zeq,
81 op_zne,op_bne,op_zgt,op_bgt,op_zge,op_bge};
84 STATIC short rev_cond(cond)
89 for (i = 0; i < 12; i++) {
90 if (cond == cc_tab[i]) return cc_tab[11-i];
98 return rev_cond(INSTR(l)) != op_nop;
102 STATIC bo_optloop(p,b,x,bra,bcc)
110 if (b->b_start == bra) {
111 b->b_start = (line_p) 0;
113 PREV(bra)->l_next = (line_p) 0;
115 PREV(bra) = (line_p) 0;
116 bcc->l_instr = rev_cond(INSTR(bcc));
119 if (l == (line_p) 0 || INSTR(l) != op_lab) {
120 l = newline(OPINSTRLAB);
122 INSTRLAB(l) = freshlabel();
123 if (n->b_start != (line_p) 0) {
128 INSTRLAB(bcc) = INSTRLAB(l);
129 for (prevb = p->p_start; prevb != (bblock_p) 0 && prevb->b_next != x;
130 prevb = prevb->b_next);
131 if (prevb == (bblock_p) 0) {
132 p->p_start = x->b_next;
134 prevb->b_next = x->b_next;
135 l = last_instr(prevb);
136 if (l == (line_p) 0) {
137 prevb->b_start = bra;
139 if ((em_flag[INSTR(l)-sp_fmnem]&EM_FLO) == FLO_T) {
146 x->b_next = b->b_next;
152 STATIC bo_tryloop(p,loop)
160 for (i = Lfirst(loop); i != (Lindex) 0; i = Lnext(i,loop)) {
161 b = (bblock_p) Lelem(i);
162 if (b->b_next != (bblock_p) 0 && !Lis_elem(b->b_next,loop)) {
163 j = Lfirst(b->b_succ);
164 if (j != (Lindex) 0 &&
165 (bra = last_instr(b)) != (line_p) 0 &&
166 INSTR(bra) == op_bra) {
167 x = (bblock_p) Lelem(j); /* single successor */
168 if (Lis_elem(b->b_next,x->b_succ) &&
169 is_bcc((bcc = last_instr(x)))) {
170 OUTVERBOSE("branch optimization proc %d block %d\n", curproc->p_id,x->b_id);
172 bo_optloop(p,b,x,bra,bcc);
188 for (i = Lfirst(p->p_loops); i != (Lindex) 0; i = Lnext(i,p->p_loops)) {
189 lp = (loop_p) (Lelem(i));
190 bo_tryloop(p,lp->LP_BLOCKS);
194 STATIC mv_code(b1,b2)
199 l = last_code(b2->b_start,TRUE);
200 assert(INSTR(l) == op_bra);
201 DLINK(l,b1->b_start);
204 if (INSTR(x) == op_lab) {
216 if (Lnrelems(b->b_succ) == 1) {
217 s = (bblock_p) Lelem(Lfirst(b->b_succ));
218 if (b->b_start != (line_p) 0 &&
219 s->b_start != (line_p) 0 &&
220 Lnrelems(s->b_pred) == 1 &&
221 (bra = last_code(b->b_start,TRUE)) != (line_p) 0 &&
222 INSTR(bra) == op_bra &&
223 (s->b_next == (bblock_p) 0 ||
224 !Lis_elem(s->b_next,s->b_succ) ||
225 ((bra = last_code(s->b_start, TRUE)) != (line_p) 0 &&
226 (em_flag[INSTR(bra)-sp_fmnem]&EM_FLO) == FLO_T))) {
227 l = last_code(s->b_start,FALSE);
228 if (INSTR(l) == ps_end) {
229 if (PREV(l) == (line_p) 0) return;
230 PREV(l)->l_next = (line_p) 0;
231 PREV(l) = (line_p) 0;
235 OUTVERBOSE("branch optimization in proc %d, block %d",curproc->p_id,b->b_id);
237 Ldeleteset(b->b_succ);
238 b->b_succ = s->b_succ;
239 Ldeleteset(s->b_pred);
240 s->b_succ = Lempty_set();
241 s->b_pred = Lempty_set();
242 for (i = Lfirst(b->b_succ); i != (Lindex) 0;
243 i = Lnext(i,b->b_succ)) {
244 x = (bblock_p) Lelem(i);
245 Lremove(s,&x->b_pred);
247 if (x->b_idom == s) {
260 /* Allocate the extended data structures for procedure p */
265 for (pi = Lfirst(p->p_loops); pi != (Lindex) 0;
266 pi = Lnext(pi,p->p_loops)) {
267 lp = (loop_p) Lelem(pi);
268 lp->lp_extend = newbolpx();
273 STATIC loop_blocks(p)
276 /* Compute the LP_BLOCKS sets for all loops of p */
281 for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
282 for (i = Lfirst(b->b_loops); i != (Lindex) 0;
283 i = Lnext(i,b->b_loops)) {
284 Ladd(b,&(((loop_p) Lelem(i))->LP_BLOCKS));
289 STATIC bo_cleanproc(p)
292 /* Allocate the extended data structures for procedure p */
298 for (pi = Lfirst(p->p_loops); pi != (Lindex) 0;
299 pi = Lnext(pi,p->p_loops)) {
300 lp = (loop_p) Lelem(pi);
301 oldbolpx(lp->lp_extend);
310 if (IS_ENTERED_WITH_GTO(p)) return;
314 for (b = p->p_start; b != 0; b = b->b_next) {
326 go(argc,argv,no_action,bo_optimize,no_action,no_action);
327 report("branch optimizations", Sbo);