Pristine Ack-5.5
[Ack-5.5.git] / util / ego / cs / cs_avail.c
1 /* $Id: cs_avail.c,v 1.6 1994/06/24 10:21:57 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 /* M O D U L E   F O R   A C C E S S S I N G   T H E   L I S T
7  *
8  * O F   A V A I L A B L E   E X P R E S S I O N S
9  */
10
11 #include <em_mnem.h>
12 #include "../share/types.h"
13 #include "../share/debug.h"
14 #include "../share/aux.h"
15 #include "../share/lset.h"
16 #include "../share/global.h"
17 #include "cs.h"
18 #include "cs_aux.h"
19 #include "cs_debug.h"
20 #include "cs_alloc.h"
21 #include "cs_getent.h"
22
23 avail_p avails; /* The list of available expressions. */
24
25 STATIC bool commutative(instr)
26         int instr;
27 {
28         /* Is instr a commutative operator? */
29
30         switch (instr) {
31                 case op_adf: case op_adi: case op_adu: case op_and:
32                 case op_cms: case op_ior: case op_mlf: case op_mli:
33                 case op_mlu:
34                         return TRUE;
35                 default:
36                         return FALSE;
37         }
38 }
39
40 STATIC bool same_avail(kind, avp1, avp2)
41         byte kind;
42         avail_p avp1, avp2;
43 {
44         /* Two expressions are the same if they have the same operator,
45          * the same size, and their operand(s) have the same value. 
46          * Only if the operator is commutative, the order of the operands
47          * does not matter.
48          */
49         if (avp1->av_instr != avp2->av_instr) return FALSE;
50         if (avp1->av_size != avp2->av_size) return FALSE;
51
52         switch (kind) {
53                 default:
54                         assert(FALSE);
55                         break;
56                 case EXPENSIVE_LOAD:
57                 case UNAIR_OP:
58                         return  avp1->av_operand == avp2->av_operand;
59                 case BINAIR_OP:
60                         if (commutative(avp1->av_instr & BMASK))
61                                 return  avp1->av_oleft == avp2->av_oleft &&
62                                         avp1->av_oright == avp2->av_oright
63                                         ||
64                                         avp1->av_oleft == avp2->av_oright &&
65                                         avp1->av_oright == avp2->av_oleft
66                                         ;
67                         else
68                                 return  avp1->av_oleft == avp2->av_oleft &&
69                                         avp1->av_oright == avp2->av_oright;
70                 case TERNAIR_OP:
71                         return  avp1->av_ofirst == avp2->av_ofirst &&
72                                 avp1->av_osecond == avp2->av_osecond &&
73                                 avp1->av_othird == avp2->av_othird;
74         }
75         /* NOTREACHED */
76 }
77
78 STATIC check_local(avp)
79         avail_p avp;
80 {
81         /* Check if the local in which the result of avp was stored,
82          * still holds this result. Update if not.
83          */
84         if (avp->av_saveloc == (entity_p) 0) return; /* Nothing to check. */
85
86         if (avp->av_saveloc->en_vn != avp->av_result) {
87                 OUTTRACE("save local changed value", 0);
88                 avp->av_saveloc = (entity_p) 0;
89         }
90 }
91
92 STATIC entity_p result_local(size, l)
93         offset size;
94         line_p l;
95 {
96         /* If the result of an expression of size bytes is stored into a
97          * local for which a registermessage was generated, return a pointer
98          * to this local.
99          */
100         line_p dummy;
101         entity_p enp;
102
103         if (l == (line_p) 0)
104                 return (entity_p) 0;
105
106         if (INSTR(l)==op_stl && size==ws || INSTR(l)==op_sdl && size==2*ws) {
107                 enp = getentity(l, &dummy);
108                 if (is_regvar(enp->en_loc)) {
109                         OUTTRACE("save local found, %ld(LB)", enp->en_loc);
110                         return enp;
111                 }
112         }
113
114         return (entity_p) 0;
115 }
116
117 STATIC copy_avail(kind, src, dst)
118         int kind;
119         avail_p src, dst;
120 {
121         /* Copy some attributes from src to dst. */
122
123         dst->av_instr = src->av_instr;
124         dst->av_size = src->av_size;
125
126         switch (kind) {
127                 default:
128                         assert(FALSE);
129                         break;
130                 case EXPENSIVE_LOAD:
131                 case UNAIR_OP:
132                         dst->av_operand = src->av_operand;
133                         break;
134                 case BINAIR_OP:
135                         dst->av_oleft = src->av_oleft;
136                         dst->av_oright = src->av_oright;
137                         break;
138                 case TERNAIR_OP:
139                         dst->av_ofirst = src->av_ofirst;
140                         dst->av_osecond = src->av_osecond;
141                         dst->av_othird = src->av_othird;
142                         break;
143         }
144 }
145
146 avail_p av_enter(avp, ocp, kind)
147         avail_p avp;
148         occur_p ocp;
149         int kind;
150 {
151         /* Put the available expression avp in the list,
152          * if it is not already there.
153          * Add ocp to the set of occurrences of this expression.
154          */
155         register avail_p ravp;
156         line_p last = ocp->oc_llast;
157
158         for (ravp = avails; ravp != (avail_p) 0; ravp = ravp->av_before) {
159                 if (same_avail(kind, ravp, avp)) { /* It was there. */
160                         Ladd(ocp, &ravp->av_occurs);
161                         /* Can we still use the local in which
162                          * the result was stored?
163                          */
164                         check_local(ravp);
165                         return ravp;
166                 }
167         }
168         /* A new available axpression. */
169         ravp = newavail();
170
171         /* Remember local, if any, that holds result. */
172         if (avp->av_instr != (byte) INSTR(last)) {
173                 /* Only possible when instr is the implicit AAR in 
174                  * a LAR or SAR.
175                  */
176                 ravp->av_saveloc = (entity_p) 0;
177         } else {
178                 ravp->av_saveloc = result_local(avp->av_size, last->l_next);
179         }
180         ravp->av_found = last;
181         ravp->av_result = kind == EXPENSIVE_LOAD? avp->av_operand: newvalnum();
182         copy_avail(kind, avp, ravp);
183         oldoccur(ocp);
184         ravp->av_before = avails;
185         avails = ravp;
186         return ravp;
187 }
188
189 clr_avails()
190 {
191         /* Throw away the information about the available expressions. */
192
193         register avail_p ravp, next;
194         register Lindex i;
195         register lset s;
196
197         for (ravp = avails; ravp != (avail_p) 0; ravp = next) {
198                 next = ravp->av_before;
199
200                 s = ravp->av_occurs;
201                 for (i = Lfirst(s); i != (Lindex) 0; i = Lnext(i, s)) {
202                         oldoccur(occ_elem(i));
203                 }
204                 Ldeleteset(s);
205                 oldavail(ravp);
206         }
207         avails = (avail_p) 0;
208 }