1 /* $Id: cs_kill.c,v 1.7 1994/06/24 10:22:27 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".
7 #include "../share/types.h"
8 #include "../share/debug.h"
9 #include "../share/global.h"
10 #include "../share/lset.h"
11 #include "../share/cset.h"
12 #include "../share/aux.h"
13 #include "../share/map.h"
18 #include "cs_entity.h"
20 STATIC base_valno(enp)
23 /* Return the value number of the (base) address of an indirectly
26 switch (enp->en_kind) {
35 return enp->en_arbase;
40 STATIC entity_p find_base(vn)
43 /* Vn is the valuenumber of the (base) address of an indirectly
44 * accessed entity. Return the entity that holds this address
48 register avail_p ravp;
50 for (i = Lfirst(entities); i != (Lindex) 0; i = Lnext(i, entities)) {
51 register entity_p renp = en_elem(i);
53 if (renp->en_vn == vn) {
54 switch (renp->en_kind) {
61 return find_base(renp->en_base);
66 /* We couldn't find it among the entities.
67 * Let's try the available expressions.
69 for (ravp = avails; ravp != (avail_p) 0; ravp = ravp->av_before) {
70 if (ravp->av_result == vn) {
71 if (ravp->av_instr == (byte) op_aar)
72 return find_base(ravp->av_ofirst);
73 if (ravp->av_instr == (byte) op_ads)
74 return find_base(ravp->av_oleft);
82 STATIC bool obj_overlap(op1, op2)
85 /* Op1 and op2 point to two objects in the same datablock.
86 * Obj_overlap returns whether these objects might overlap.
90 if (op1->o_off > op2->o_off) {
92 tmp = op1; op1 = op2; op2 = tmp;
94 return op1->o_size == UNKNOWN_SIZE ||
95 op1->o_off + op1->o_size > op2->o_off;
98 #define same_datablock(o1, o2) ((o1)->o_dblock == (o2)->o_dblock)
100 STATIC bool addr_local(enp)
103 /* Is enp the address of a stack item. */
105 if (enp == (entity_p) 0) return FALSE;
107 return enp->en_kind == ENALOCAL || enp->en_kind == ENALOCBASE ||
108 enp->en_kind == ENAARGBASE;
111 STATIC bool addr_external(enp)
114 /* Is enp the address of an external. */
116 return enp != (entity_p) 0 && enp->en_kind == ENAEXTERNAL;
119 STATIC kill_external(obp, indir)
123 /* A store is done via the object in obp. If this store is direct
124 * we kill directly accessed entities in the same data block only
125 * if they overlap with obp, otherwise we kill everything in the
126 * data block. Indirectly accessed entities of which it can not be
127 * proven taht they are not in the same data block, are killed in
132 OUTTRACE("kill external", 0);
133 for (i = Lfirst(entities); i != (Lindex) 0; i = Lnext(i, entities)) {
134 entity_p enp = en_elem(i);
137 switch (enp->en_kind) {
139 if (!same_datablock(enp->en_ext, obp))
141 if (!indir && !obj_overlap(enp->en_ext, obp))
143 OUTTRACE("kill %d", enp->en_vn);
144 enp->en_vn = newvalnum();
149 /* We spare its value number if we are sure
150 * that its (base) address points into the
151 * stack or into another data block.
153 base = find_base(base_valno(enp));
154 if (addr_local(base))
156 if (addr_external(base) &&
157 !same_datablock(base->en_ext, obp)
160 OUTTRACE("kill %d", enp->en_vn);
161 enp->en_vn = newvalnum();
167 STATIC bool loc_overlap(enp1, enp2)
170 /* Enp1 and enp2 point to two locals. Loc_overlap returns whether
175 assert(enp1->en_kind == ENLOCAL && enp2->en_kind == ENLOCAL);
177 if (enp1->en_loc > enp2->en_loc) {
179 tmp = enp1; enp1 = enp2; enp2 = tmp;
181 if (enp1->en_loc < 0 && enp2->en_loc >= 0)
182 return FALSE; /* Locals and parameters do not overlap. */
183 else return enp1->en_size == UNKNOWN_SIZE ||
184 enp1->en_loc + enp1->en_size > enp2->en_loc;
187 STATIC kill_local(enp, indir)
191 /* This time a store is done into an ENLOCAL. */
195 OUTTRACE("kill local", 0);
196 for (i = Lfirst(entities); i != (Lindex) 0; i = Lnext(i, entities)) {
197 entity_p rep = en_elem(i);
200 switch (rep->en_kind) {
203 /* Kill locals that might be stored into
204 * via a pointer. Note: enp not used.
206 if (!is_regvar(rep->en_loc)) {
207 OUTTRACE("kill %d", rep->en_vn);
208 rep->en_vn = newvalnum();
210 } else if (loc_overlap(rep, enp)) {
211 /* Only kill overlapping locals. */
212 OUTTRACE("kill %d", rep->en_vn);
213 rep->en_vn = newvalnum();
219 if (!is_regvar(enp->en_loc)) {
220 base = find_base(base_valno(rep));
221 if (!addr_external(base)) {
222 OUTTRACE("kill %d", rep->en_vn);
223 rep->en_vn = newvalnum();
229 if (enp->en_loc == 0 && rep->en_levels >= 1) {
230 rep->en_vn = newvalnum();
239 /* A store is done into the ENIGNMASK. */
243 OUTTRACE("kill sim", 0);
244 for (i = Lfirst(entities); i != (Lindex) 0; i = Lnext(i, entities)) {
245 register entity_p rep = en_elem(i);
247 if (rep->en_kind == ENIGNMASK) {
248 OUTTRACE("kill %d", rep->en_vn);
249 rep->en_vn = newvalnum();
250 return; /* There is only one ignoremask. */
258 /* A store will be done into enp. We must forget the values of all the
259 * entities this one may overlap with.
261 switch (enp->en_kind) {
266 kill_external(enp->en_ext, FALSE);
269 kill_local(enp, FALSE);
280 /* An indirect store is done, in an ENINDIR,
281 * an ENOFFSETTED or an ENARRELEM.
285 /* If we can find the (base) address of this entity, then we can spare
286 * the entities that are provably not pointed to by the address.
287 * We will also make use of the MES 3 pseudo's, generated by
288 * the front-end. When a MES 3 is generated for a local, this local
289 * will not be referenced indirectly.
291 if ((p = find_base(base_valno(enp))) == (entity_p) 0) {
292 kill_much(); /* Kill all entities without registermessage. */
294 switch (p->en_kind) {
296 /* An indirect store into global data. */
297 kill_external(p->en_ext, TRUE);
302 /* An indirect store into stack data. */
311 /* Kills all killable entities,
312 * except the locals for which a registermessage was generated.
316 OUTTRACE("kill much", 0);
317 for (i = Lfirst(entities); i != (Lindex) 0; i = Lnext(i, entities)) {
318 register entity_p rep = en_elem(i);
320 if (rep->en_static) continue;
321 if (rep->en_kind == ENLOCAL && is_regvar(rep->en_loc)) continue;
322 OUTTRACE("kill %d", rep->en_vn);
323 rep->en_vn = newvalnum();
327 STATIC bool bad_procflags(pp)
330 /* Return whether the flags about the procedure in pp indicate
331 * that we have little information about it. It might be that
332 * we haven't seen the text of pp, or that we have seen that pp
333 * calls a procedure which we haven't seen the text of.
335 return !(pp->p_flags1 & PF_BODYSEEN) || (pp->p_flags1 & PF_CALUNKNOWN);
338 STATIC kill_globset(s)
341 /* S is a set of global variables that might be changed.
342 * We act as if a direct store is done into each of them.
346 OUTTRACE("kill globset", 0);
347 for (i = Cfirst(s); i != (Cindex) 0; i = Cnext(i,s)) {
348 kill_external(omap[Celem(i)], FALSE);
355 /* Kill everything that might be destroyed by calling
356 * the procedure in pp.
358 if (bad_procflags(pp)) {
359 /* We don't know enough about this procedure. */
361 } else if (pp->p_change->c_flags & CF_INDIR) {
362 /* The procedure does an indirect store. */
365 /* Procedure might affect global data. */
366 kill_globset(pp->p_change->c_ext);
372 /* Kills all entities. */
376 OUTTRACE("kill all entities", 0);
377 for (i = Lfirst(entities); i != (Lindex) i; i = Lnext(i, entities)) {
378 entity_p enp = en_elem(i);
380 OUTTRACE("kill %d", enp->en_vn);
381 enp->en_vn = newvalnum();