Subversion Repositories tendra.SVN

Rev

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