1 /* $Id: ra_items.c,v 1.7 1994/06/24 10:27:44 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 /* R E G I S T E R A L L O C A T I O N
15 #include "../share/types.h"
16 #include "../share/debug.h"
17 #include "../share/def.h"
18 #include "../share/global.h"
19 #include "../share/lset.h"
20 #include "../share/aux.h"
21 #include "../share/alloc.h"
28 /* Maps EM mnemonics onto item types, e.g. op_lol -> LOCALVAR, op_ldc->DCONST,
29 * generated from em_mmen.h and itemtab.src files.
32 #define SMALL_CONSTANT(c) (c >= 0 && c <= 8)
33 /* prevent small constants from being put in a register */
41 for (t = 0; t < NRITEMTYPES;t++) {
42 items[t] = (item_p) 0;
55 if (instr < sp_fmnem || instr > sp_lmnem) return NO_ITEM;
56 t = itemtab[instr - sp_fmnem].id_type;
57 if (t == CONST && SMALL_CONSTANT(off_set(l))) return NO_ITEM;
66 return item_type(l) != NO_ITEM;
70 item_p item_of(off,items)
76 for (x = items[LOCALVAR]; x != (item_p) 0; x = x->it_next) {
77 if (off == x->i_t.it_off) {
78 if (!x->it_desirable) break;
79 /* don't put this item in reg */
92 item->it_type = item_type(l);
93 item->it_desirable = TRUE;
94 switch(item->it_type) {
96 item->i_t.it_obj = OBJ(l);
99 item->i_t.it_proc = PROC(l);
102 item->i_t.it_off = off_set(l);
108 STATIC bool desirable(l)
111 /* See if it is really desirable to put the item of line l
112 * in a register. We do not put an item in a register if it
113 * is used as 'address of array descriptor' of an array
117 if (l->l_next != (line_p) 0) {
118 switch(INSTR(l->l_next)) {
130 STATIC int cmp_items(a,b)
133 /* This routine defines the <, = and > relations between items,
134 * used to sort them for fast lookup.
141 assert(b->it_type == GLOBL_ADDR);
142 n1 = (offset) a->i_t.it_obj->o_id;
143 n2 = (offset) b->i_t.it_obj->o_id;
146 assert(b->it_type == PROC_ADDR);
147 n1 = (offset) a->i_t.it_proc->p_id;
148 n2 = (offset) b->i_t.it_proc->p_id;
154 return (n1 == n2 ? 0 : (n1 > n2 ? 1 : -1));
162 return cmp_items(a,b) == 0;
166 STATIC bool lt_item(a,b)
169 return cmp_items(a,b) == -1;
176 * Build a list of all items used in the current procedure. An item
177 * is anything that can be put in a register (a local variable, a constant,
178 * the address of a local or global variable).
179 * For each type of item we use a sorted list containing all items of
180 * that type found so far.
181 * A local variable is only considered to be an item if there is a
182 * register message for it (indicating it is never accessed indirectly).
183 * For each item, we keep track of all places where it is used
184 * (either fetched or stored into). The usage of a local variable is also
185 * considered to be a usage of its address.
190 static item_p items[NRITEMTYPES]; /* items[i] points to the list of type i */
194 STATIC short reg_type(item)
197 /* See which type of register the item should best be assigned to */
199 switch(item->it_type) {
201 return regv_type(item->i_t.it_off);
202 /* use type mentioned in reg. message for local */
210 default: assert(FALSE);
217 STATIC short item_size(item)
220 /* Determine the size of the item (in bytes) */
222 switch(item->it_type) {
224 return regv_size(item->i_t.it_off);
225 /* use size mentioned in reg. message for local */
229 return ps; /* pointer size */
231 return ws; /* word size */
233 return 2 * ws; /* 2 * word size */
234 default: assert(FALSE);
241 STATIC init_item(a,b)
244 a->it_type = b->it_type;
247 a->i_t.it_obj = b->i_t.it_obj;
250 a->i_t.it_proc = b->i_t.it_proc;
253 a->i_t.it_off = b->i_t.it_off;
255 a->it_usage = Lempty_set();
256 a->it_regtype = reg_type(b);
257 a->it_size = item_size(b);
258 a->it_desirable = b->it_desirable;
263 STATIC add_item(item,t,items)
268 /* See if there was already a list element for item. In any
269 * case record the fact that item is used at 't'.
272 register item_p x, *q;
274 q = &items[item->it_type]; /* each type has its own list */
275 for (x = *q; x != (item_p) 0; x = *q) {
276 if (same_item(x,item)) {
278 if (!item->it_desirable) {
279 x->it_desirable = FALSE;
281 Ladd(t,&x->it_usage);
284 if (lt_item(item,x)) break;
287 /* not found, allocate new item; q points to it_next field of
288 * the item after which the new item should be put.
294 Ladd(t,&x->it_usage);
299 STATIC add_usage(l,b,items)
304 /* An item is used at line l. Add it to the list of items.
305 * A local variable is only considered to be an item, if
306 * there is a register message for it; else its address
307 * is also considered to be an item.
310 struct item thisitem;
312 fill_item(&thisitem,l); /* fill in some fields */
314 thisitem.it_desirable = FALSE; /* don't put item in reg. */
316 if (thisitem.it_type == LOCALVAR && !is_regvar(thisitem.i_t.it_off)) {
317 /* Use address of local instead of local itself */
318 thisitem.it_type = LOCAL_ADDR;
319 thisitem.it_regtype = reg_pointer;
321 add_item(&thisitem,cons_time(l,b),items);
326 build_itemlist(p,items,nrinstr_out)
331 /* Make a list of all items used in procedure p.
332 * An item is anything that can be put in a register,
333 * such as a local variable, a constant etc.
334 * As a side effect, determine the number of instructions of p.
342 for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
343 for (l = b->b_start; l != (line_p) 0; l = l->l_next) {
345 add_usage(l,b,items);