Subversion Repositories tendra.SVN

Rev

Rev 2 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/**********************************************************************
32
$Author: release $
33
$Date: 1998/01/17 15:56:07 $
34
$Revision: 1.1.1.1 $
35
$Log: weights.c,v $
36
 * Revision 1.1.1.1  1998/01/17  15:56:07  release
37
 * First version to be checked into rolling release.
38
 *
39
 * Revision 1.1  1995/04/13  09:08:06  currie
40
 * Initial revision
41
 *
42
***********************************************************************/
43
/******************************************************************
44
		weights.c
45
 
46
	The main procedure here is weightsv which determines
47
the allocation of s regs. It considers which of those tags not already
48
allocated to a t reg by scan, are best put in an s register. The same
49
conditions as for t regs apply as to the suitability of the tags for registers.
50
Weights estimates the usage of each tag and hence the amount that would
51
be saved if it were held in an s reg. Thus it computes break points for
52
register allocation for later use by reg_alloc.
53
	The type weights consists of two arrays of integers. In the first
54
array each integer corresponds to a fixpnt reg and the second arrays'
55
integers correspond to floating point regs.
56
	At the end of a call of weights on an ident exp the props field
57
of the ident may still contain inreg_bits or infreg_bits, set by scan, to
58
indicate that a t reg should be used. Otherwise number of ident is set up to
59
represent the break point for allocation. A similar process occurs for
60
proc parameters which have the break value in the forweights field
61
of the parapair of the corresponding procrec. This value has three
62
meanings:
63
	1) The ident (or parameter) defines a fixpnt value and number
64
of ident (forweights of parpair) is an integer brk with the interpretation
65
that if there are at least brk fixpt s registers unallocated at this point then
66
one will be used for this tag (parameter).
67
	2) As 1 but for floating point values.
68
	3) number of ident = 100 in which case allocate value on the
69
stack, (this is obviously always available for parameters).
70
 
71
******************************************************************/
72
/* ALTERATIONS
73
	25/3/93	   scale in labst_tag in weightsv is already evaluated
74
		332: scale = fno(e)*scale -> scale = fno(e);
75
*/
76
 
77
#include "config.h"
78
#include <limits.h>
79
#include "common_types.h"
80
#include "exptypes.h"
81
#include "exp.h"
82
#include "expmacs.h"
83
#include "tags.h"
84
#include "procrectypes.h"
85
#include "bitsmacs.h"
86
#include "maxminmacs.h"
87
#include "regable.h"
88
#include "shapemacs.h"
89
#include "special.h"
90
#include "weights.h"
91
 
92
 
93
weights zeroweights =
94
{{
95
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
96
},
97
{
98
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
99
}
100
};
101
 
102
/* NB scale, throughout,  should be a float but mips cc V2.10 compiles calls and
103
		proc body inconsistently !! */
104
 
105
weights weightsv PROTO_S ((double scale, exp e));
106
 
107
weights add_weights
108
    PROTO_N ( (w1,w2) )
109
    PROTO_T ( weights * w1 X weights * w2 )
110
{
111
				/* sum of weights*/
112
  weights r;
113
  long  i;
114
  for (i = 0; i < wfixno; ++i) {
115
      (r.fix)[i] = (w1->fix)[i]+(w2->fix)[i];
116
  };
117
  for (i = 0; i < wfloatno; ++i) {
118
      (r.floating)[i] = (w1->floating)[i]+(w2->floating)[i];
119
  };
120
  return (r);
121
}
122
 
123
wp max_weights
124
    PROTO_N ( (loc, ws, fix) )
125
    PROTO_T ( double loc X weights * ws X bool fix )
126
{
127
				/* loc is the usage count of a tag, ws is
128
				   the weights computed for the scope of
129
				   the tag and fix distinguishes between
130
				   fix and float. This computes the
131
				   weights for the declaration and a break
132
				   point for register allocation which
133
				   gives the number of available regs for
134
				   which it is worthwhile to allocate this
135
				   tag into a reg ("regged"). This proc is
136
				   the source of all non-zero weights. NB
137
				   loc may be negative since using a s-reg
138
				   will involve a dump and restore  */
139
  long  bk = wfixno + 1;
140
 
141
  long  i;
142
  float *w = (ws -> fix);
143
  /*  w[i] = greatest usage of (i+1) inner fixed tags  */
144
  wp res;
145
  float *pw = &(((res.wp_weights).fix)[0]);
146
  if (fix) {
147
    for (i = 0; i < wfixno; ++i) {
148
      if (i == 0) {
149
	if (loc > w[i]) {
150
	  /* this tag has higher usage than any inner one ... */
151
	  pw[i] = loc;
152
	  bk = i;		/* ... so it's regged in pref to others */
153
	}
154
	else
155
	  pw[i] = w[i];
156
      }
157
      else {
158
	if ((loc + w[i - 1]) > w[i]) {
159
	  /* this tag and i inner ones have higher usage than any other
160
	     (i+1) inner ones ... */
161
	  pw[i] = loc + w[i - 1];
162
	  if (i < bk)
163
	    bk = i;
164
	  /* ... so it and i inner ones are regged in preference to any
165
	     other (i+1) inner ones */
166
	}
167
	else
168
	  pw[i] = w[i];
169
      };
170
    };
171
 
172
    res.fix_break = bk;
173
  }
174
  else {
175
    for (i = 0; i < wfixno; ++i) {
176
      pw[i] = w[i];
177
    }
178
  }
179
 
180
  res.fix_break = bk;
181
 
182
  bk = wfloatno + 1;
183
  w = (ws -> floating);
184
  pw = &(((res.wp_weights).floating)[0]);
185
  if (!fix) {			/* same algorithm for float regs as fixed
186
				   regs */
187
    for (i = 0; i < wfloatno; ++i) {
188
      if (i == 0) {
189
	if (loc > w[i]) {
190
	  pw[i] = loc;
191
	  bk = i;
192
	}
193
	else
194
	  pw[i] = w[i];
195
      }
196
      else {
197
	if ((loc + w[i - 1]) > w[i]) {
198
	  pw[i] = loc + w[i - 1];
199
	  if (i < bk)
200
	    bk = i;
201
	}
202
	else
203
	  pw[i] = w[i];
204
      };
205
    };
206
  }
207
  else {
208
    for (i = 0; i < wfloatno; ++i) {
209
      pw[i] = w[i];
210
    }
211
  }
212
 
213
  res.float_break = bk;
214
  return res;
215
}
216
 
217
weights mult_weights
218
    PROTO_N ( (m, ws) )
219
    PROTO_T ( double m X weights * ws )
220
{
221
				/* multiply weights by scalar - non
222
				   overflowing */
223
  weights res;
224
  float *r = &(res.fix)[0];
225
  float *w = ws -> fix;
226
  long  i;
227
  for (i = 0; i < wfixno; ++i) {
228
      r[i] = w[i] * m;
229
  };
230
 
231
  r = &(res.floating)[0];
232
  w = ws -> floating;
233
  for (i = 0; i < wfloatno; ++i) {
234
      r[i] = w[i] * m;
235
  };
236
  return (res);
237
}
238
 
239
weights add_wlist
240
    PROTO_N ( (scale, re) )
241
    PROTO_T ( double scale X exp re )
242
{/* sum of  weights of list re */
243
  weights w, w1;
244
  exp r = re;
245
  if (r == nilexp) {
246
    return zeroweights;
247
  }
248
  else
249
    if (last (r)) {
250
      return (weightsv (scale, r));
251
    }
252
    else {
253
      w = weightsv (scale, r);
254
      do {
255
	r = bro (r);
256
	w1 = weightsv (scale, r);
257
	w = add_weights (&w, &w1);
258
      } while (!last (r));
259
      return w;
260
    }
261
}
262
 
263
 
264
 
265
/*****************************************************************
266
	weightsv
267
 
268
This procedure estimates the usage of tags and parameters to help
269
determine whether they can advantageously be placed in s registers.
270
The parameter scale allows more importance to be placed on usage
271
inside 'for' loops for example. The procedure reg_alloc in reg_alloc.c
272
finally determines the actual choice of s reg and recodes the number
273
field of an ident.
274
 
275
******************************************************************/
276
weights weightsv
277
    PROTO_N ( (scale, e) )
278
    PROTO_T ( double scale X exp e )
279
{
280
 unsigned char  n;
281
tailrecurse:
282
  n = name (e);
283
  switch (n) {
284
    case name_tag:
285
      {
286
	exp s = son (e);
287
 
288
	if (name (s) == ident_tag && !isglob (s)) {
289
	  if (is_floating(name(sh(e))) && name(sh(e)) != shrealhd) {
290
	  	fno(s) += scale*2.0;
291
	  } else fno (s) += scale;
292
	}
293
	/* usage of tag stored in number of son of load_name (decl) */
294
	return zeroweights;
295
      };
296
 
297
    case ident_tag:
298
      {
299
	if (son (e) != nilexp) {
300
	  weights wdef;
301
	  weights wbody;
302
	  long  noe = no (e) /* set by scan */ ;
303
 
304
	  if (name (son (e)) == clear_tag || props (e) & defer_bit) {
305
	    wdef = zeroweights;
306
	    fno(e)= 0.0;
307
	  }
308
	  else {
309
	    /* maybe needs a store to initialise */
310
	    if (is_floating(name(sh(son(e)))) && name(sh(son(e))) != shrealhd) {
311
	  		fno(e) = scale*2.0;
312
	    } else fno (e) = scale;
313
	    wdef = weightsv (scale, son (e));
314
	  }
315
	  /* weights for initialisation of dec */
316
 
317
	  wbody = weightsv (scale, bro (son (e)));
318
	  /* weights of body of scan */
319
 
320
	  if (props (e) & defer_bit) {/* declaration will be treated
321
				   transparently in code production */
322
	    exp t = son (e);
323
	    exp s;
324
	    if (name (t) == val_tag || name(t) == real_tag) {
325
	      return wbody;
326
	    }
327
	    while (name (t) != name_tag) {
328
	      t = son (t);
329
	    }
330
 
331
	    s = son (t);
332
	    if (name (s) == ident_tag && !isglob (t)) {
333
	      fno (s) += fno (e);
334
	    }
335
	    /* usage of tag stored in number of son of load_name (decl) */
336
 
337
	    return wbody;
338
	  }			/* end deferred */
339
 
340
	  if ((props (e) & inreg_bits) == 0 && fixregable (e)) {
341
	    wp p;
342
	    p = max_weights (fno (e) - 2.0*scale , &wbody, 1);
343
	    /* usage decreased by 2 because of dump and restore of s-reg
344
	    */
345
	    no (e) = p.fix_break;
346
	    return (add_weights (&wdef, &p.wp_weights));
347
	  }
348
	  else
349
	    if ((props (e) & infreg_bits) == 0 && floatregable (e)) {
350
	      wp p;
351
	      p = max_weights (fno (e) - 4 * scale, &wbody, 0);
352
	      /* usage decreased by 4 because of dump and restore of
353
	         double s-reg */
354
	      no (e) = p.float_break;
355
	      return (add_weights (&wdef, &p.wp_weights));
356
	    }
357
	    else {
358
	      no (e) = noe /* restore to value given by scan */ ;
359
	      return add_weights (&wdef, &wbody);
360
	    }
361
	}
362
	else
363
	  return zeroweights;
364
      };
365
    case rep_tag: {
366
	e = bro (son (e));
367
	goto tailrecurse;
368
      }
369
 
370
    case case_tag: {
371
	e = son (e);
372
	goto tailrecurse;
373
      };
374
 
375
    case labst_tag:
376
      { scale = fno(e);
377
	e = bro (son (e));
378
	goto tailrecurse;
379
      }
380
 
381
 
382
    case val_tag:{
383
	return zeroweights;
384
      };
385
 
386
    case ncopies_tag: {
387
    	scale = no(e)*scale;
388
    	e = son(e);
389
    	goto tailrecurse;
390
    }
391
 
392
    case seq_tag:  {
393
	exp l = son(son(e));
394
	exp r = bro(son(e));
395
	weights w, w1;
396
        w = weightsv(scale, l);
397
	while(!last(l)) {
398
		l = bro(l);
399
		w1 = weightsv(scale, l);
400
		w = add_weights(&w, &w1);
401
	}
402
	w1 = weightsv(scale, r);
403
	w = add_weights(&w, &w1);
404
        return w;
405
   }
406
 
407
 
408
    default: {
409
	if (son (e) == nilexp || n == env_offset_tag
410
		|| n == general_env_offset_tag ) {
411
	  return zeroweights;
412
	}
413
	if (last (son (e))) {
414
	  e = son (e);
415
	  goto tailrecurse;
416
	}
417
	return (add_wlist (scale, son (e)));
418
      }
419
  }
420
}