Subversion Repositories tendra.SVN

Rev

Rev 5 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
6 7u83 61
/* 	$Id$	 */
2 7u83 62
 
63
#ifndef lint
6 7u83 64
static char vcid[] = "$Id$";
2 7u83 65
#endif /* lint */
66
 
67
/*
68
   weights.c
69
 
6 7u83 70
   The main procedure here is weightsv which determines the
71
   allocation of s regs. It considers which of those tags not
72
   already allocated to a t reg by scan, are best put in an s
73
   register. The same conditions as for t regs apply as to the
74
   suitability of the tags for registers.  Weights estimates the
75
   usage of each tag and hence the amount that would be saved if
2 7u83 76
   it were held in an s reg. Thus it computes break points for
6 7u83 77
   register allocation for later use by reg_alloc.  The type
78
   weights consists of two arrays of integers. In the first array
2 7u83 79
   each integer corresponds to a fixpnt reg and the second arrays'
6 7u83 80
   integers correspond to floating point regs.  At the end of a
81
   call of weights on an ident exp the props field of the ident
82
   may still contain inreg_bits or infreg_bits, set by scan, to
83
   indicate that a t reg should be used. Otherwise number of ident
84
   is set up to represent the break point for allocation. A similar
85
   process occurs for proc parameters which have the break value
86
   in the forweights field of the parapair of the corresponding
2 7u83 87
   procrec. This value has three meanings:
88
 
89
   1) The ident (or parameter) defines a fixpnt value and number
6 7u83 90
   of ident (forweights of parpair) is an integer brk with the
91
   interpretation that if there are at least brk fixpt s registers
92
   unallocated at this point then one will be used for this tag
2 7u83 93
   (parameter).
94
 
95
   2) As 1 but for floating point values.
6 7u83 96
 
97
   3) number of ident = 100 in which case allocate value on the
2 7u83 98
   stack, (this is obviously always available for parameters).
99
 
100
*/
101
 
102
/*
103
$Log: weights.c,v $
104
 * Revision 1.1.1.1  1998/01/17  15:56:01  release
105
 * First version to be checked into rolling release.
106
 *
107
 * Revision 1.4  1996/02/19  09:25:40  john
108
 * Added assertion
109
 *
110
 * Revision 1.3  1995/06/13  14:04:03  john
111
 * Cosmetic change
112
 *
113
 * Revision 1.2  1995/05/16  10:56:50  john
114
 * Changes for spec 3.1
115
 *
116
 * Revision 1.1.1.1  1995/03/23  10:39:26  john
117
 * Entered into CVS
118
 *
119
 * Revision 1.4  1995/03/23  10:17:15  john
120
 * Added sequence to tested cases
121
 *
122
*/
123
 
124
#include "config.h"
125
#include <limits.h>
126
#include "common_types.h"
127
#include "exptypes.h"
128
#include "exp.h"
129
#include "expmacs.h"
130
#include "tags.h"
131
#include "procrectypes.h"
132
#include "procrecs.h"
133
#include "bitsmacs.h"
134
#include "maxminmacs.h"
135
#include "regable.h"
136
#include "shapemacs.h"
137
#include "special.h"
138
#include "weights.h"
139
 
140
 
141
 
142
weights zeroweights =
143
{{
144
    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
145
},
146
{
147
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
148
}
149
};
150
 
6 7u83 151
weights weightsv(double scale, exp e);
2 7u83 152
 
153
weights add_weights
6 7u83 154
(weights *w1, weights *w2)
2 7u83 155
{
156
  /* sum of weights*/
157
  weights r;
158
  long  i;
159
  for (i = 0; i < wfixno; ++i) {
6 7u83 160
   (r.fix)[i] = (w1->fix)[i] + (w2->fix)[i];
2 7u83 161
  };
162
  for (i = 0; i < wfloatno; ++i) {
6 7u83 163
   (r.floating)[i] = (w1->floating)[i] + (w2->floating)[i];
2 7u83 164
  };
6 7u83 165
  return(r);
2 7u83 166
}
167
 
168
 
169
 
170
/* loc is the usage count of a tag, ws is
171
   the weights computed for the scope of
172
   the tag and fix distinguishes between
173
   fix and float. This computes the
174
   weights for the declaration and a break
175
   point for register allocation which
176
   gives the number of available regs for
177
   which it is worthwhile to allocate this
178
   tag into a reg ("regged"). This proc is
179
   the source of all non-zero weights. NB
180
   loc may be negative since using a s-reg
181
   will involve a dump and restore  */
182
wp max_weights
6 7u83 183
(double loc, weights * ws, bool fix)
2 7u83 184
{
185
 
186
  long  bk = wfixno + 1;
187
 
188
  long  i;
189
  float *w = (ws -> fix);
190
  /*  w[i] = greatest usage of (i+1) inner fixed tags  */
191
  wp res;
6 7u83 192
  float *pw = & (((res.wp_weights).fix)[0]);
2 7u83 193
  if (fix) {
194
    for (i = 0; i < wfixno; ++i) {
195
      if (i == 0) {
196
	if (loc > w[i]) {
197
	  /* this tag has higher usage than any inner one ... */
198
	  pw[i] = loc;
199
	  bk = i;		/* ... so it's regged in pref to others */
200
	}
201
	else
202
	  pw[i] = w[i];
203
      }
204
      else {
205
	if ((loc + w[i - 1]) > w[i]) {
6 7u83 206
	  /* this tag and i inner ones have higher usage than any other
2 7u83 207
	     (i+1) inner ones ... */
208
	  pw[i] = loc + w[i - 1];
209
	  if (i < bk)
210
	    bk = i;
211
	  /* ... so it and i inner ones are regged in preference to any
212
	     other (i+1) inner ones */
213
	}
214
	else
215
	  pw[i] = w[i];
216
      };
217
    };
218
 
219
    res.fix_break = bk;
220
  }
221
  else {
222
    for (i = 0; i < wfixno; ++i) {
223
      pw[i] = w[i];
224
    }
225
  }
226
 
227
  res.fix_break = bk;
228
 
229
  bk = wfloatno + 1;
230
  w = (ws -> floating);
6 7u83 231
  pw = & (((res.wp_weights).floating)[0]);
2 7u83 232
  if (!fix) {			/* same algorithm for float regs as fixed
233
				   regs */
234
    for (i = 0; i < wfloatno; ++i) {
235
      if (i == 0) {
236
	if (loc > w[i]) {
237
	  pw[i] = loc;
238
	  bk = i;
239
	}
240
	else
241
	  pw[i] = w[i];
242
      }
243
      else {
244
	if ((loc + w[i - 1]) > w[i]) {
245
	  pw[i] = loc + w[i - 1];
246
	  if (i < bk)
247
	    bk = i;
248
	}
249
	else
250
	  pw[i] = w[i];
251
      };
252
    };
253
  }
254
  else {
255
    for (i = 0; i < wfloatno; ++i) {
256
      pw[i] = w[i];
257
    }
258
  }
6 7u83 259
 
2 7u83 260
  res.float_break = bk;
261
  return res;
262
}
263
 
264
weights mult_weights
6 7u83 265
(double m, weights *ws)
2 7u83 266
{
267
  /* multiply weights by scalar - non
268
     overflowing */
269
  weights res;
6 7u83 270
  float *r = & (res.fix)[0];
2 7u83 271
  float *w = ws -> fix;
272
  long  i;
273
  for (i = 0; i < wfixno; ++i) {
6 7u83 274
      r[i] = w[i]* m;
2 7u83 275
  };
276
 
6 7u83 277
  r = & (res.floating)[0];
2 7u83 278
  w = ws -> floating;
279
  for (i = 0; i < wfloatno; ++i) {
6 7u83 280
      r[i] = w[i]* m;
2 7u83 281
  };
6 7u83 282
  return(res);
2 7u83 283
}
284
 
285
weights add_wlist
6 7u83 286
(double scale, exp re)
2 7u83 287
{
288
  weights w, w1;
289
  exp r = re;
290
  if (r == nilexp) {
291
    return zeroweights;
292
  }
293
  else
6 7u83 294
    if (last(r)) {
295
      return(weightsv(scale, r));
2 7u83 296
    }
297
    else {
6 7u83 298
      w = weightsv(scale, r);
2 7u83 299
      Assert(r != bro(r));
300
      do {
6 7u83 301
	r = bro(r);
302
	w1 = weightsv(scale, r);
303
	w = add_weights(&w, &w1);
304
      } while (!last(r));
2 7u83 305
      return w;
306
    }
307
}
308
 
309
 
310
 
311
/*
312
   weightsv
313
 
6 7u83 314
   This procedure estimates the usage of tags and parameters to
315
   help determine whether they can advantageously be placed in
316
   s registers.  The parameter scale allows more importance to
317
   be placed on usage inside 'for' loops for example. The
318
   procedure reg_alloc in reg_alloc.c finally determines the
319
   actual choice of s reg and recodes the number field of an ident.
2 7u83 320
*/
321
weights weightsv
6 7u83 322
(double scale, exp e)
2 7u83 323
{
324
 unsigned char  n;
6 7u83 325
 tailrecurse:
326
  n = name(e);
2 7u83 327
  switch (n) {
6 7u83 328
    case name_tag:
2 7u83 329
      {
6 7u83 330
	exp s = son(e);
331
	if (name(s) == ident_tag && !isglob(s)) {
332
	  if (is_floating(name(sh(e))) && name(sh(e))!= shrealhd) {
2 7u83 333
	  	fno(s) += scale*2.0;
6 7u83 334
	  } else fno(s) += scale;
2 7u83 335
	}
336
	/* usage of tag stored in number of son of load_name (decl) */
337
	return zeroweights;
338
      }
339
 
6 7u83 340
    case ident_tag:
2 7u83 341
      {
6 7u83 342
	if (son(e)!= nilexp) {
2 7u83 343
	  weights wdef;
344
	  weights wbody;
345
	  long  noe = no (e) /* set by scan */ ;
6 7u83 346
	  if ((name(son(e)) == clear_tag) || (props(e) & defer_bit)) {
2 7u83 347
	    wdef = zeroweights;
6 7u83 348
	    fno(e) = 0.0;
2 7u83 349
	  }
350
	  else {
6 7u83 351
	    /* maybe needs a store to initialise */
352
	    if (is_floating(name(sh(son(e)))) && name(sh(son(e)))!= shrealhd) {
2 7u83 353
	  		fno(e) = scale*2.0;
6 7u83 354
	    } else fno(e) = scale;
355
	    wdef = weightsv(scale, son(e));
2 7u83 356
	  }
357
	  /* weights for initialisation of dec */
358
 
6 7u83 359
	  wbody = weightsv(scale, bro(son(e)));
2 7u83 360
	  /* weights of body of scan */
6 7u83 361
 
2 7u83 362
	  if (props (e) & defer_bit) {/* declaration will be treated
363
				   transparently in code production */
6 7u83 364
	    exp t = son(e);
2 7u83 365
	    exp s;
6 7u83 366
	    if (name(t) == val_tag || name(t) == real_tag) {
2 7u83 367
	      return wbody;
368
	    }
6 7u83 369
	    while (name(t)!= name_tag) {
370
	      t = son(t);
2 7u83 371
	    }
372
 
6 7u83 373
	    s = son(t);
374
	    if (name(s) == ident_tag && !isglob(t)) {
2 7u83 375
	      fno (s) = fno (e);	/* is this correct */
376
	    }
6 7u83 377
	    /* usage of tag stored in number of son of
2 7u83 378
	     load_name (decl) */
379
 
380
	    return wbody;
381
	  }			/* end deferred */
382
 
6 7u83 383
	  if ((props(e) & inreg_bits) == 0 && fixregable(e)) {
2 7u83 384
	    wp p;
6 7u83 385
	    p = max_weights(fno(e) - 2.0*scale , &wbody, 1);
386
	    /* usage decreased by 2 because of dump and
387
	       restore of s-reg
2 7u83 388
	    */
6 7u83 389
	    no(e) = p.fix_break;
390
	    return(add_weights(&wdef, &p.wp_weights));
2 7u83 391
	  }
6 7u83 392
	  else if ((props(e) & infreg_bits) == 0 && floatregable(e)) {
2 7u83 393
	    wp p;
6 7u83 394
	    p = max_weights(fno(e) - 2 * scale, &wbody, 0);
395
	    /* usage decreased by 4(on mips) because of dump
2 7u83 396
	       and restore of double s-reg */
6 7u83 397
	    no(e) = p.float_break;
398
	    return(add_weights(&wdef, &p.wp_weights));
2 7u83 399
	  }
400
	  else {
401
	    no (e) = noe /* restore to value given by scan */ ;
6 7u83 402
	    return add_weights(&wdef, &wbody);
2 7u83 403
	  }
6 7u83 404
	}
2 7u83 405
	else
406
	  return zeroweights;
407
      };
408
    case rep_tag: {
6 7u83 409
	e = bro(son(e));
2 7u83 410
	goto tailrecurse;
411
      }
412
 
413
    case case_tag: {
6 7u83 414
	e = son(e);
2 7u83 415
	goto tailrecurse;
416
      };
417
 
418
    case labst_tag: {
419
      scale = fno(e);
6 7u83 420
      e = bro(son(e));
2 7u83 421
      goto tailrecurse;
422
    }
423
 
424
 
425
    case val_tag:{
426
	return zeroweights;
427
      };
428
 
429
    case ncopies_tag: {
430
    	scale = no(e)*scale;
431
    	e = son(e);
432
    	goto tailrecurse;
433
    }
434
    case seq_tag: {
435
      exp l = son(son(e));
436
      exp r = bro(son(e));
437
      weights w,w1;
438
      w = weightsv(scale,l);
6 7u83 439
      while (!last(l)) {
2 7u83 440
	l = bro(l);
441
	w1 = weightsv(scale,l);
442
	w = add_weights(&w,&w1);
443
      }
444
      w1 = weightsv(scale,r);
445
      w = add_weights(&w,&w1);
446
      return w;
447
    }
6 7u83 448
 
2 7u83 449
     default: {
6 7u83 450
       if (son(e) == nilexp || n == env_offset_tag ||
2 7u83 451
	   n == general_env_offset_tag) {
452
	 return zeroweights;
453
	}
6 7u83 454
       if (last(son(e))) {
455
	 e = son(e);
2 7u83 456
	 goto tailrecurse;
457
       }
6 7u83 458
       return(add_wlist(scale, son(e)));
2 7u83 459
     }
460
    }
461
}
462
 
463
 
464
 
465
 
466