Pristine Ack-5.5
[Ack-5.5.git] / util / ego / ud / ud_const.c
1 /* $Id: ud_const.c,v 1.6 1994/06/24 10:33:20 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 /* C O N S T A N T   P R O P A G A T I O N */
7
8 #include <em_mnem.h>
9 #include <em_pseu.h>
10 #include <em_spec.h>
11 #include "../share/types.h"
12 #include "ud.h"
13 #include "../share/debug.h"
14 #include "../share/global.h"
15 #include "../share/alloc.h"
16 #include "../share/lset.h"
17 #include "../share/cset.h"
18 #include "../share/def.h"
19 #include "../share/aux.h"
20 #include "../share/locals.h"
21 #include "ud_defs.h"
22 #include "ud_const.h"
23 #include "ud_aux.h"
24
25
26 #define IS_REG(v)       (locals[TO_LOCAL(v)]->lc_flags & LCF_REG)
27 #define CALLS_UNKNOWN(p) (p->p_flags1 & (byte) PF_CALUNKNOWN)
28
29
30 bool is_use(l)
31         line_p l;
32 {
33         /* See if 'l' is a use of a variable */
34
35         switch(INSTR(l)) {
36                  case op_lde:
37                  case op_ldl:
38                  case op_loe:
39                  case op_lol:
40                         return TRUE;
41                 default:
42                         return FALSE;
43         }
44         /* NOTREACHED  */
45 }
46
47
48
49
50 bool value_known(def,val_out)
51         line_p def;
52         offset *val_out;
53 {
54         /* See if the value stored by definition 'def'
55          * is known statically (i.e. is a constant).
56          */
57
58         short sz1, sz2;
59         offset v;
60         line_p l;
61
62         sz1 = ws;
63         switch(INSTR(def)) {
64                 case op_inl:
65                 case op_ine:
66                 case op_del:
67                 case op_dee:
68                         return FALSE;
69                 case op_zrl:
70                 case op_zre:
71                         v = (offset) 0;
72                         break;
73                 case op_sdl:
74                 case op_sde:
75                         sz1 += ws;
76                         /* fall through ... */
77                 case op_stl:
78                 case op_ste:
79                         l = PREV(def);
80                         if (l == (line_p) 0) return FALSE;
81                         sz2 = ws;
82                         switch(INSTR(l)) {
83                                 case op_zer:
84                                         if (SHORT(l) >= sz1) {
85                                                 v = (offset) 0;
86                                                 break;
87                                         }
88                                         return FALSE;
89                                 case op_ldc:
90                                         sz2 += ws;
91                                         /* fall through ...*/
92                                 case op_loc:
93                                         if (sz1 == sz2) {
94                                                 v = off_set(l);
95                                                 break;
96                                         }
97                                         /* fall through ... */
98                                 default:
99                                         return FALSE;
100                         }
101                         break;
102                 default:
103                         assert(FALSE);
104         }
105         *val_out = v;
106         return TRUE;
107 }
108
109
110
111
112 bool affected(use,v,l)
113         line_p use,l;
114         short  v;
115 {
116         /* See if the variable referenced by 'use' may be
117          * changed by instruction l, which is either a cal, cai or
118          * an indirect assignment.
119          */
120
121         if (INSTR(l) == op_cal &&
122             TYPE(use) == OPOBJECT &&
123             BODY_KNOWN(PROC(l)) &&
124             !CALLS_UNKNOWN(PROC(l)) &&
125             !CHANGE_INDIR(PROC(l))) {
126                 return Cis_elem(OBJ(use)->o_id,PROC(l)->p_change->c_ext);
127         }
128         return TYPE(use) == OPOBJECT || !IS_REG(v);
129 }
130
131
132
133
134 STATIC search_backwards(use,v,found,def)
135         line_p use, *def;
136         short v;
137         bool *found;
138 {
139         /* Search backwards in the current basic block,
140          * starting at 'use', trying to find a definition
141          * of the variable referenced by 'use', whose variable
142          * number is v. If the definition found is an
143          * implicit one, return 0 as def.
144          */
145
146         register line_p l;
147
148         for (l = PREV(use); l != (line_p) 0; l = PREV(l)) {
149                 if (does_expl_def(l) && same_var(use,l)) {
150                         *found = TRUE;
151                         *def = l;
152                         return;
153                 }
154                 if (does_impl_def(l) && affected(use,v,l)) {
155                         *found = TRUE;
156                         *def = (line_p) 0;
157                         return;
158                 }
159         }
160         *found = FALSE;
161 }
162
163
164
165
166 STATIC short outer_def(vdefs,in)
167         cset vdefs, in;
168 {
169         /* See if there is a unique definition of variable
170          * v reaching the beginning of block b.
171          * 'vdefs' is vardefs[v], 'in' is IN(b).
172          */
173
174         short n,defnr = 0;
175         Cindex i;
176
177         for (i = Cfirst(vdefs); i != (Cindex) 0; i = Cnext(i,vdefs)) {
178                 n = Celem(i);
179                 if (Cis_elem(EXPL_TO_DEFNR(n),in)) {
180                         if (defnr != 0) return  0;
181                         /* If there was already a def., there's no unique one */
182                         defnr = n;
183                 }
184         }
185         return defnr;
186 }
187
188
189
190
191 line_p unique_def(use,b,defnr_out)
192         line_p use;
193         bblock_p b;
194         short *defnr_out;
195 {
196         /* See if there is one unique explicit definition
197          * of the variable used by 'use', that reaches 'use'.
198          */
199
200         short v;
201         bool found;
202         line_p def =  (line_p) 0;
203
204         *defnr_out = 0;
205         var_nr(use,&v,&found);
206         if (found) {
207                 /* We do maintain ud-info for this variable.
208                  * See if there is a previous explicit definition
209                  * in the current basic block.
210                  */
211                 search_backwards(use,v,&found,&def);
212                 if (!found && !Cis_elem(IMPLICIT_DEF(v),IN(b))) {
213                         /* See if there is a unique explicit definition
214                          * outside the current block, reaching the
215                          * beginning of the current block.
216                          */
217                         *defnr_out = outer_def(vardefs[v],IN(b));
218                         def = (*defnr_out == 0 ? (line_p) 0 : defs[*defnr_out]);
219                 }
220         }
221         return def;
222 }
223
224
225
226 fold_const(l,b,val)
227         line_p l;
228         bblock_p b;
229         offset val;
230 {
231         /* Perform the substitutions required for constant folding */
232
233         line_p n;
234
235         n = int_line(val);
236         switch(INSTR(l)) {
237                 case op_lol:
238                 case op_loe:
239                         n->l_instr = op_loc;
240                         break;
241                 case op_ldl:
242                 case op_lde:
243                         n->l_instr = op_ldc;
244                         break;
245                 default:
246                         assert (FALSE);
247         }
248         repl_line(l,n,b);
249 }