Pristine Ack-5.5
[Ack-5.5.git] / util / ego / sr / sr_xform.c
1 /* $Id: sr_xform.c,v 1.7 1994/06/24 10:32:33 ceriel Exp $ */
2 /*
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".
5  */
6 /* S T R E N G T H   R E D U C T I O N
7  *
8  * S R _ X F O R M . C
9  *
10  */
11
12
13
14 #include <stdio.h>
15 #include <em_mnem.h>
16 #include <em_pseu.h>
17 #include <em_spec.h>
18 #include "../share/types.h"
19 #include "sr.h"
20 #include "../share/debug.h"
21 #include "../share/global.h"
22 #include "../share/alloc.h"
23 #include "../share/def.h"
24 #include "../share/get.h"
25 #include "sr_aux.h"
26 #include "../share/lset.h"
27 #include "../share/aux.h"
28 #include "sr_xform.h"
29
30 /* Transformations on EM texts */
31
32 line_p move_pointer(tmp,dir)
33         offset tmp;
34         int    dir;
35 {
36         /* Generate EM code to load/store a pointer variable
37          * onto/from the stack, depending on dir(ection).
38          * We accept all kinds of pointer sizes.
39          */
40
41         line_p l;
42
43         l = int_line(tmp);
44         if (ps == ws) {
45                 /* pointer fits in a word */
46                 l->l_instr = (dir == LOAD ? op_lol : op_stl);
47         } else {
48                 if (ps == 2 * ws) {
49                         /* pointer fits in a double word */
50                         l->l_instr = (dir == LOAD ? op_ldl : op_sdl);
51                 } else {
52                         /* very large pointer size, generate code:
53                          * LAL tmp ; LOI/STI ps */
54                         l->l_instr = op_lal;
55                         l->l_next = newline(OPSHORT);
56                         SHORT(l->l_next) = ps;
57                         l->l_next->l_instr =
58                            (dir == LOAD ? op_loi : op_sti);
59                         PREV(l->l_next) = l;
60                 }
61         }
62         return l;
63 }
64
65
66
67 /* make_header */
68
69 STATIC copy_loops(b1,b2,except)
70         bblock_p b1,b2;
71         loop_p except;
72 {
73         /* Copy the loopset of b2 to b1, except for 'except' */
74
75         Lindex i;
76         loop_p lp;
77         for (i = Lfirst(b2->b_loops); i != (Lindex) 0;
78              i = Lnext(i,b2->b_loops)) {
79                 lp = (loop_p) Lelem(i);
80                 if (lp != except) {
81                         Ladd(lp,&b1->b_loops);
82                 }
83         }
84 }
85
86
87 STATIC lab_id label(b)
88         bblock_p b;
89 {
90         /* Find the label at the head of block b. If there is
91          * no such label yet, create one.
92          */
93
94         line_p l;
95
96         if (b->b_start && INSTR(b->b_start) == op_lab) {
97                 return INSTRLAB(b->b_start);
98         }
99         /* The block has no label yet. */
100         l = newline(OPINSTRLAB);
101         l->l_instr = op_lab;
102         INSTRLAB(l) = freshlabel();
103         if (b->b_start) {
104                 DLINK(l,b->b_start); /* doubly link them */
105         }
106         b->b_start = l;
107         return INSTRLAB(l);
108 }
109
110
111 STATIC adjust_jump(newtarg,oldtarg,c)
112         bblock_p newtarg,oldtarg,c;
113 {
114         /* If the last instruction of c is a jump to the
115          * old target, then change it into a jump to the
116          * start of the new target.
117          */
118
119         line_p l = last_instr(c);
120
121         assert(l != (line_p) 0);
122
123         if (INSTR(oldtarg->b_start) == op_lab) {
124                 /* If old target has no label, it cannot be jumped to */
125                 if (TYPE(l) == OPINSTRLAB &&
126                     INSTRLAB(l) == INSTRLAB(oldtarg->b_start)) {
127                         INSTRLAB(l) = label(newtarg);
128                 }
129         }
130
131         if (c->b_next == oldtarg && INSTR(l) != op_bra) {
132                 line_p new = newline(OPINSTRLAB);
133
134                 INSTRLAB(new) = label(newtarg);
135                 new->l_instr = op_bra;
136                 DLINK(l, new);
137         }
138 }
139
140
141 make_header(lp)
142         loop_p lp;
143 {
144         /* Make sure that the loop has a header block, i.e. a block
145          * has the loop entry block as its only successor and
146          * that dominates the loop entry block.
147          * If there is no header yet, create one.
148          */
149
150         bblock_p b,c,entry;
151         Lindex i,next;
152
153         if (lp->LP_HEADER != (bblock_p) 0) return;
154         OUTTRACE("creating a new header block",0);
155         /* The loop has no header yet. The main problem is to
156          * keep all relations (SUCC, PRED, NEXT, IDOM, LOOPS)
157          * up to date.
158          */
159         b = freshblock(); /* new block with new b_id */
160         entry = lp->lp_entry;
161
162         /* update succ/pred. Also take care that any jump from outside
163          * the loop to the entry block now goes to b.
164          */
165
166         b->b_succ = Lempty_set();
167         b->b_pred = Lempty_set();
168
169         for (i = Lfirst(entry->b_pred); i != (Lindex) 0; i = next ) {
170                 next = Lnext(i,entry->b_pred);
171                 c = (bblock_p) Lelem(i);
172                 /* c is a predecessor of the entry block */
173                 if (!Lis_elem(c,lp->LP_BLOCKS)) {
174                         /* c is outside the loop */
175                         Lremove(c,&entry->b_pred);
176                         Lremove(entry,&c->b_succ);
177                         Ladd(b,&c->b_succ);
178                         Ladd(c,&b->b_pred);
179                         adjust_jump(b,entry,c);
180                 }
181         }
182         assert(lp->LP_INSTR == 0);
183         lp->LP_INSTR = b->b_start;
184         Ladd(b,&entry->b_pred);
185         Ladd(entry,&b->b_succ);
186         /* put header block at end of procedure */
187         for (c = curproc->p_start; c->b_next != 0; c = c->b_next);
188         c->b_next = b;
189         /* b->b_next = 0; */
190         copy_loops(b,entry,lp);
191         b->b_idom = entry->b_idom;
192         entry->b_idom = b;
193         lp->LP_HEADER = b;
194 }