1 /* $Id: ud.c,v 1.9 1994/06/24 10:33:08 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 /* U S E - D E F I N I T I O N A N A L Y S I S */
10 #include "../share/types.h"
12 #include "../share/debug.h"
13 #include "../share/global.h"
14 #include "../share/lset.h"
15 #include "../share/cset.h"
16 #include "../share/def.h"
17 #include "../share/files.h"
18 #include "../share/map.h"
19 #include "../share/get.h"
20 #include "../share/put.h"
21 #include "../share/alloc.h"
22 #include "../share/aux.h"
23 #include "../share/init_glob.h"
24 #include "../share/locals.h"
25 #include "../share/go.h"
30 /* core allocation macros */
31 #define newudbx() (bext_p) newstruct(bext_ud)
32 #define oldudbx(x) oldstruct(bext_ud,x)
39 cond_p globl_cond_tab,local_cond_tab;
41 STATIC cond_p getcondtab(f)
49 for (i = 0; i < l; i++) {
50 fscanf(f,"%hd %hd %hd",&tab[i].mc_cond,&tab[i].mc_tval,
53 assert(tab[l-1].mc_cond == DEFAULT);
64 while(getc(f) != '\n');
66 if (strcmp(s,"%%UD") == 0)break;
68 globl_cond_tab = getcondtab(f);
69 local_cond_tab = getcondtab(f);
74 STATIC bool test_cond(cond,val)
82 return val >= -128 && val < 128;
89 STATIC short map_value(tab,val,time)
90 struct cond_tab tab[];
96 for (p = &tab[0]; ; p++) {
97 if (test_cond(p->mc_cond,val)) {
98 return (time ? p->mc_tval : p->mc_sval);
104 STATIC init_root(root)
107 /* Initialise the IN OUT sets of the entry block of the
108 * current procedure. Global variables and parameters
109 * already have a value at this point, although we do
110 * not know which value. Therefor, implicit definitions
111 * to all global variables and parameters are
117 for (v = 1; v <= nrglobals; v++) {
118 Cadd(IMPLICIT_DEF(GLOB_TO_VARNR(v)), &IN(root));
120 for (v = 1; v <= nrlocals; v++) {
121 if (locals[v]->lc_off >= 0) {
122 Cadd(IMPLICIT_DEF(LOC_TO_VARNR(v)),&IN(root));
125 /* OUT(root) = IN(root) - KILL(root) + GEN(root) */
126 Ccopy_set(IN(root),&OUT(root));
127 Csubtract(KILL(root),&OUT(root));
128 Cjoin(GEN(root),&OUT(root));
134 STATIC unite_outs(bbset,setp)
138 /* Take the union of OUT(b), for all b in bbset,
139 * and put the result in setp.
145 for (i = Lfirst(bbset); i != (Lindex) 0; i = Lnext(i,bbset)) {
146 Cjoin(OUT((bblock_p) Lelem(i)), setp);
152 STATIC solve_equations(p)
155 /* Solve the data flow equations for reaching
156 * definitions of procedure p.
157 * These equations are:
158 * (1) OUT(b) = IN(b) - KILL(b) + GEN(b)
159 * (2) IN(b) = OUT(p1) + .. + OUT(pn) ;
160 * where PRED(b) = {p1, .. , pn}
161 * We use the iterative algorithm of Aho&Ullman to
162 * solve the equations.
169 /* initializations */
170 newin = Cempty_set(nrdefs);
171 for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
172 IN(b) = Cempty_set(nrdefs);
173 OUT(b) = Cempty_set(nrdefs);
174 Ccopy_set(GEN(b), &OUT(b));
176 init_root(p->p_start);
177 /* Global variables and parameters have already a value
178 * at the procedure entry block.
184 for (b = p->p_start->b_next; b != (bblock_p) 0; b = b->b_next) {
185 unite_outs(b->b_pred, &newin);
186 /* newin = OUT(p1) + .. + OUT(pn) */
187 if (!Cequal(newin,IN(b))) {
189 Ccopy_set(newin, &IN(b));
190 Ccopy_set(IN(b), &OUT(b));
191 Csubtract(KILL(b), &OUT(b));
192 Cjoin(GEN(b), &OUT(b));
196 for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
205 short global_addr_cost()
207 return add_timespace(map_value(globl_cond_tab,(offset) 0,TRUE),
208 map_value(globl_cond_tab,(offset) 0,FALSE));
211 short local_addr_cost(off)
214 return add_timespace(map_value(local_cond_tab,off,TRUE),
215 map_value(local_cond_tab,off,FALSE));
220 STATIC bool fold_is_desirable(old,new)
223 /* See if it is desirable to replace the variable used by the
224 * EM instruction 'old' by the variable used by 'new'.
225 * We do not replace 'cheaply addressable variables' by 'expensively
226 * addressable variables'. E.g. if we're optimizing object code size,
227 * we do not replace a local variable by a global variable on a VAX,
228 * because the former occupies 1 or 2 bytes and the latter occupies
230 * If 2 local variables are equally expensive to address, we replace
231 * the first one by the second only if the first one is used at
232 * least as many times as the second one.
235 local_p oldloc,newloc;
236 short old_cost,new_cost,nr;
239 if (TYPE(old) == OPOBJECT) {
240 /* old variable is a global variable */
241 return TYPE(new) != OPOBJECT &&
242 global_addr_cost() >=
243 local_addr_cost(off_set(new));
245 find_local(off_set(old),&nr,&ok);
248 old_cost = local_addr_cost(off_set(old));
249 if (TYPE(new) == OPOBJECT) {
250 return oldloc->lc_score == 2 || /* old var. can be eliminated */
251 old_cost > global_addr_cost();
253 find_local(off_set(new),&nr,&ok);
256 new_cost = local_addr_cost(off_set(new));
257 return old_cost > new_cost ||
258 (old_cost == new_cost && oldloc->lc_score < newloc->lc_score);
264 /*********** TRACING ROUTINES ***********/
270 printf("LOCAL-TABLE (%d)\n\n",nrlocals);
271 for (i = 1; i <= nrlocals; i++) {
273 printf("LOCAL %d\n",i);
274 printf(" offset= %ld\n",lc->lc_off);
275 printf(" size= %d\n",lc->lc_size);
276 printf(" flags= %d\n",lc->lc_flags);
285 printf("GLOBALS (%d)\n\n",nrglobals);
286 printf("ID GLOBNR\n");
287 for (d = fdblock; d != (dblock_p) 0; d = d->d_next) {
288 for (obj = d->d_objlist; obj != (obj_p) 0; obj = obj->o_next) {
289 if (obj->o_globnr != 0) {
290 printf("%d %d\n", obj->o_id,obj->o_globnr);
296 extern char em_mnem[];
303 printf("DEF TABLE\n\n");
304 for (i = 1; i <= nrexpldefs; i++) {
306 printf("%d %s ",EXPL_TO_DEFNR(i),
307 &em_mnem[(INSTR(l)-sp_fmnem)*4]);
310 printf("%d\n",SHORT(l));
313 printf("%ld\n",OFFSET(l));
316 printf("%d\n",OBJ(l)->o_id);
332 printf("%s(%d) = {",name,k);
333 for (i = 1; i <= n; i++) {
347 for (b = p->p_start; b != 0; b = b->b_next) {
350 pr_set("GEN",n,GEN(b),nrdefs);
351 pr_set("KILL",n,KILL(b),nrdefs);
352 pr_set("IN ",n,IN(b),nrdefs);
353 pr_set("OUT",n,OUT(b),nrdefs);
354 pr_set("CHGVARS",n,CHGVARS(b),nrvars);
362 printf("\nCOPY TABLE\n\n");
363 for (i = 1; i <= nrdefs; i++) {
364 if (def_to_copynr[i] != 0) {
365 printf("%d %d\n",i,def_to_copynr[i]);
376 for (b = p->p_start; b != 0; b = b->b_next) {
379 pr_set("CGEN",n,C_GEN(b),nrcopies);
380 pr_set("CKILL",n,C_KILL(b),nrcopies);
381 pr_set("CIN ",n,C_IN(b),nrcopies);
382 pr_set("COUT",n,C_OUT(b),nrcopies);
386 /*********** END TRACING ********/
390 STATIC ud_analysis(p)
393 /* Perform use-definition analysis on procedure p */
395 make_localtab(p); /* See for which local we'll keep ud-info */
399 nrvars = nrglobals + nrlocals;
400 make_defs(p); /* Make a table of all useful definitions in p */
404 nrdefs = nrexpldefs + nrvars; /* number of definitions */
405 gen_sets(p); /* compute GEN(b), for every basic block b */
406 kill_sets(p); /* compute KILL(b), for every basic block b */
407 solve_equations(p); /* solve data flow equations for p */
420 oldmap(defs,nrexpldefs);
421 for (p = &locals[1]; p <= &locals[nrlocals]; p++) {
424 oldmap(locals,nrlocals);
425 for (v = &vardefs[1]; v <= &vardefs[nrvars]; v++) {
428 oldmap(vardefs,nrvars);
433 STATIC bool try_optim(l,b)
437 /* Try copy propagation and constant propagation */
444 if (is_use(l) && (def = unique_def(l,b,&defnr)) != (line_p) 0) {
446 if (value_retained(def,defnr,l,b) &&
447 fold_is_desirable(l,PREV(def))) {
448 fold_var(l,PREV(def),b);
449 OUTVERBOSE("vp:variable folded in proc %d",
455 if (value_known(def,&val)) {
457 OUTVERBOSE("vp:value folded in proc %d",
472 /* Apply value propagation to procedure p */
479 /* If a statement like A := B is folded to A := constant,
480 * new opportunities for constant folding may arise,
481 * e.g. the value of A might be statically known too now.
486 for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
487 for (l = b->b_start; l != (line_p) 0; l = next) {
489 if (try_optim(l,b)) {
495 oldmap(copies,nrcopies);
496 oldtable(def_to_copynr,nrdefs);
503 /* Allocate extended data structures for Use Definition analysis */
507 for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
508 b->b_extend = newudbx();
516 /* Deallocate extended data structures for Use Definition analysis */
520 for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
523 Cdeleteset(C_GEN(b));
524 Cdeleteset(C_KILL(b));
526 Cdeleteset(C_OUT(b));
527 Cdeleteset(CHGVARS(b));
528 oldudbx(b->b_extend);
536 if (IS_ENTERED_WITH_GTO(p)) return;
538 locals = (local_p *) 0;
539 vardefs = (cset *) 0;
547 value_propagation(p);
556 go(argc,argv,init_globals,ud_optimize,ud_machinit,no_action);
557 report("values folded",Svalue);
558 report("variables folded",Svariable);