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
/* 80x86/weights.c */
32
 
33
/**********************************************************************
34
$Author: release $
35
$Date: 1998/01/17 15:55:52 $
36
$Revision: 1.1.1.1 $
37
$Log: weights.c,v $
38
 * Revision 1.1.1.1  1998/01/17  15:55:52  release
39
 * First version to be checked into rolling release.
40
 *
41
 * Revision 1.14  1997/10/10  18:25:40  pwe
42
 * prep ANDF-DE revision
43
 *
44
 * Revision 1.13  1996/11/08  16:19:22  pwe
45
 * check_stack to check before modifying stack
46
 *
47
 * Revision 1.12  1996/05/20  14:30:45  pwe
48
 * improved 64-bit handling
49
 *
50
 * Revision 1.11  1996/05/13  12:52:10  pwe
51
 * undo premature commit
52
 *
53
 * Revision 1.9  1996/01/22  14:31:13  pwe
54
 * PIC const*const, contop top_tag & linux 64-bit ints
55
 *
56
 * Revision 1.8  1996/01/17  11:24:42  pwe
57
 * resurrect performance
58
 *
59
 * Revision 1.7  1995/09/05  16:25:14  pwe
60
 * specials and exception changes
61
 *
62
 * Revision 1.6  1995/08/04  08:29:56  pwe
63
 * 4.0 general procs implemented
64
 *
65
 * Revision 1.5  1995/05/05  12:47:32  pwe
66
 * missing bracket
67
 *
68
 * Revision 1.4  1995/05/02  13:27:42  pwe
69
 * strengthen test for no side effect
70
 *
71
 * Revision 1.3  1995/03/23  13:25:39  pwe
72
 * limit scale in deeply nested repeats
73
 *
74
 * Revision 1.2  1995/01/30  12:56:59  pwe
75
 * Ownership -> PWE, tidy banners
76
 *
77
 * Revision 1.1  1994/10/27  14:15:22  jmf
78
 * Initial revision
79
 *
80
 * Revision 1.1  1994/07/12  14:43:24  jmf
81
 * Initial revision
82
 *
83
**********************************************************************/
84
 
85
 
86
#include "config.h"
87
#include <limits.h>
88
#include "common_types.h"
89
#include "expmacs.h"
90
#include "tags.h"
91
#include "exp.h"
92
#include "shapemacs.h"
93
#include "basicread.h"
94
#include "flags.h"
95
#include "localflags.h"
96
#include "coder.h"
97
#include "weights.h"
98
 
99
 
100
/* MACROS */
101
 
102
#define max(x,y) ((x>=y) ? (x) : (y))
103
 
104
#define wno 6
105
 /* number of available registers */
106
#define wfno 7
107
 /* number of available floating point registers */
108
 
109
/* IDENTITIES */
110
 
111
float  vzeros[wno + wfno] = {
112
  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.0
113
};
114
float  vmoveregs[wno + wfno] = {	/* for the move instruction */
115
  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.0
116
};
117
float  vcmpregs[wno + wfno] = {	/* for the cmp instruction */
118
  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.0
119
};
120
 
121
float  vdivregs[wno + wfno] = {	/* for the div instruction */
122
  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.0
123
};
124
 
125
float  vapplyregs[wno + wfno] = {/* for apply */
126
  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.0
127
};
128
 
129
 
130
struct wt {
131
  float  w_weights[wno + wfno];
132
  int  booked;
133
  int  flbooked;
134
};
135
 
136
typedef struct wt   weights;
137
				/* weights[i] is the value of putting a
138
				   declaration in a register if there are
139
				   i registers available. */
140
 
141
struct wpt {
142
  weights wp_weights;
143
  int  wp_break;		/* break is the number of registers that
144
				   must be available at this point for it
145
				   to be worthwhile putting this value in
146
				   a register */
147
};
148
 
149
typedef struct wpt  wp;
150
 
151
struct elt {
152
  exp wident;
153
  struct elt *etl;
154
};
155
typedef struct elt  explist;
156
				/* list of identity declarations in force
157
				   at this point */
158
 
159
weights weightsv PROTO_S ( ( exp, explist * ) ) ;
160
 
161
/* VARIABLES */
162
 
163
weights zeros, moveregs, cmpregs, divregs, applyregs;
164
	/* init by init_weights */
165
 
166
 
167
 
168
 
169
/* PROCEDURES */
170
 
171
static int no_side_aux
172
    PROTO_N ( (e) )
173
    PROTO_T ( exp e )
174
{
175
  exp arg;
176
  if (name(e)==name_tag || name(e)==env_offset_tag || name(e)==top_tag || son(e)==nilexp)
177
    return 1;
178
  for (arg=son(e); ; arg=bro(arg))
179
  {
180
    if ((!is_a(name(arg)) && name(arg) != ident_tag) || !no_side_aux(arg))
181
      return 0;
182
    if (last(arg))
183
      return 1;
184
  }
185
}
186
 
187
 
188
/* test for guaranteed no side effect */
189
/* simple assignment is permitted */
190
int no_side
191
    PROTO_N ( (e) )
192
    PROTO_T ( exp e )
193
{
194
  return ((is_a (name (e)) || name (e) == test_tag || name (e) == ass_tag ||
195
	   name (e) == testbit_tag || name (e) == ident_tag)
196
	&& no_side_aux (e));
197
}
198
 
199
/* add two weight vectors */
200
weights add_weights
201
    PROTO_N ( (w1, w2) )
202
    PROTO_T ( weights w1 X weights w2 )
203
{
204
  weights r;
205
  float  wa,
206
         wb;
207
  int i;
208
  for (i = 0; i < (wno + wfno); ++i) {
209
    wa = (w1.w_weights)[i];
210
    wb = (w2.w_weights)[i];
211
    (r.w_weights)[i] = wa + wb;
212
  };
213
  r.booked = max (w1.booked, w2.booked);
214
  r.flbooked = max (w1.flbooked, w2.flbooked);
215
  return (r);
216
}
217
 
218
void init_weights
219
    PROTO_Z ()
220
{
221
		/* initialisation of constants */
222
  int  i;
223
  for (i = 0; i < (wno + wfno); ++i) {
224
    (zeros.w_weights)[i] = vzeros[i];
225
    (moveregs.w_weights)[i] = vmoveregs[i];
226
    (cmpregs.w_weights)[i] = vcmpregs[i];
227
    (divregs.w_weights)[i] = vdivregs[i];
228
    (applyregs.w_weights)[i] = vapplyregs[i];
229
  };
230
  zeros.booked = -1;
231
  moveregs.booked = 1;
232
  cmpregs.booked = 1;
233
  divregs.booked = 1;
234
  applyregs.booked = 1;
235
 
236
  zeros.flbooked = -1;
237
  moveregs.flbooked = -1;
238
  cmpregs.flbooked = -1;
239
  divregs.flbooked = -1;
240
  applyregs.flbooked = 2;
241
 
242
  return;
243
}
244
 
245
void markcall
246
    PROTO_N ( (el) )
247
    PROTO_T ( explist * el )
248
{
249
  explist * t = el;
250
  while (t != (explist *) 0) {
251
    set_intnl_call (t -> wident);
252
    t = t -> etl;
253
  };
254
}
255
 
256
/* mark all the declarations in the list
257
   of currently active declarations, to
258
   show that there is a call, movc3 etc.
259
   within their scope */
260
void markmove
261
    PROTO_N ( (el) )
262
    PROTO_T ( explist * el )
263
{
264
  explist * t = el;
265
  while (t != (explist *) 0) {
266
    set_intnl_call (t -> wident);
267
    t = t -> etl;
268
  };
269
}
270
 
271
/* mark to show reg1 may be needed */
272
void markreg1
273
    PROTO_N ( (el) )
274
    PROTO_T ( explist * el )
275
{
276
  explist * t = el;
277
  while (t != (explist *) 0) {
278
    set_intnl_call (t -> wident);
279
    t = t -> etl;
280
  };
281
}
282
 
283
 
284
/* work out weights for a declaration and
285
   set up the break point to put in the no
286
   field of the declaration */
287
wp max_weights
288
    PROTO_N ( (size, locp, ws, isfl) )
289
    PROTO_T ( int size X float locp X weights ws X int isfl )
290
{
291
  int  k = (size + 31) / 32;
292
  int  bk = 11;
293
  int bkset = 0;
294
  int  q;
295
  int  i;
296
  float * w = &(ws.w_weights)[(isfl) ? wno : 0];
297
  wp res;
298
  float *pw = &((res.wp_weights).w_weights)[(isfl) ? wno : 0];
299
  int  bkd = (isfl) ? ws.flbooked : ws.booked;
300
  int  lwno = (isfl) ? wfno : wno;
301
  res.wp_weights.booked = ws.booked;
302
  res.wp_weights.flbooked = ws.flbooked;
303
 
304
  for (i = 0; i < (wno + wfno); ++i)
305
    ((res.wp_weights).w_weights)[i] = (ws.w_weights)[i];
306
 
307
   {
308
    float  loc = locp * k;
309
    q = -1;
310
    for (i = 0; i < lwno; ++i) {
311
      {
312
	if (i < (k + q))
313
	  pw[i] = w[i];
314
	else {
315
	  if (i == (k + q)) {
316
	    if (loc >= w[i] && bkd <= q) {
317
	      pw[i] = loc;
318
	      bk = i + 1;
319
	      bkset = 1;
320
	    }
321
	    else
322
	      pw[i] = w[i];
323
	  }
324
	  else {
325
	    if ((loc + w[i - k]) >= w[i]) {
326
	      pw[i] = loc + w[i - k];
327
	      if (!bkset) {
328
		bk = i + 1;
329
		bkset = 1;
330
	      };
331
	    }
332
	    else
333
	      pw[i] = w[i];
334
	  };
335
	};
336
      };
337
    };
338
  };
339
 
340
 
341
  res.wp_break = bk;
342
  return (res);
343
}
344
 
345
 
346
/* see if we must use movc3?? */
347
weights try_mc3
348
    PROTO_N ( (e, ws, el) )
349
    PROTO_T ( exp e X weights ws X explist * el )
350
{
351
  int  sz = shape_size(sh(e));
352
 
353
  if (sz <= 128)
354
    return (ws);
355
 
356
  markmove (el);
357
  return (add_weights (ws, moveregs));
358
}
359
 
360
/* work out the weights for a list of exp.
361
   usemc3 is 1 if movc3 may be used. */
362
weights add_wlist
363
    PROTO_N ( (re, usemc3, el) )
364
    PROTO_T ( exp re X int usemc3 X explist * el )
365
{
366
  weights wl1, wl2;
367
  if (re == nilexp)
368
    return (zeros);
369
 
370
  wl1 = weightsv (re, el);
371
  if (usemc3)
372
    wl1 = try_mc3 (re, wl1, el);
373
 
374
  while (!last (re)) {
375
    re = bro (re);
376
    wl2 = weightsv (re, el);
377
    if (usemc3)
378
      wl1 = add_weights (wl1, try_mc3 (re, wl2, el));
379
    else
380
      wl1 = add_weights (wl1, wl2);
381
  };
382
  return (wl1);
383
}
384
 
385
 
386
 
387
/* can the value defined by e be put in a register */
388
int regable
389
    PROTO_N ( (e) )
390
    PROTO_T ( exp e )
391
{
392
  unsigned char  n;
393
  shape sha = sh (son (e));
394
  n = name (sha);
395
  if (isvis (e) || n == cpdhd || n == nofhd || n == s64hd || n == u64hd)
396
    return (0);
397
  if (all_variables_visible && isvar(e))
398
    return 0;
399
  return (1);
400
}
401
 
402
int isflsh
403
    PROTO_N ( (s) )
404
    PROTO_T ( shape s )
405
{
406
  unsigned char  n = name (s);
407
  return (n >= shrealhd && n <= doublehd);
408
}
409
 
410
 
411
/* Work out weights and set break points
412
   scale is the expected number of times
413
   that this operation will be done.
414
   During the scan the expected number of
415
   times use is made of something declared
416
   is computed in the no of the
417
   declaration. After the scan the break
418
   point is put into the no of the
419
   declaration */
420
weights weightsv
421
    PROTO_N ( (e, el) )
422
    PROTO_T ( exp e X explist * el )
423
{
424
  unsigned char  n = name (e);
425
  float old_scale;
426
  weights swl, bwl;
427
 
428
  switch (n) {
429
    case name_tag: {
430
	if (!isglob (son (e)))
431
	  fno (son (e)) += scale;/* add number of uses to the no field of
432
				   the declaration */
433
	return (zeros);
434
      };
435
    case make_lv_tag:
436
        return zeros;
437
    case ident_tag:
438
       {
439
	explist nel;
440
	exp t = pt (e);
441
	nel.wident = e;
442
	nel.etl = el;
443
	while (isvar (e) && !isvis (e) && t != nilexp) {
444
	  if (!(last (t) && name (bro (t)) == cont_tag) &&
445
              !(last(t) && name(bro(t)) == hold_tag) &&
446
	      !(last (bro (t)) && (name (bro (bro (t))) == ass_tag ||
447
		  name (bro (bro (t))) == assvol_tag
448
		)))
449
	    setvis (e);
450
	  t = pt (t);
451
	};
452
 
453
	if (son (e) != nilexp) {
454
	  weights wdef, wbody;
455
	  exp def = son (e);
456
	  exp body = bro (def);
457
 
458
	  if (name(sh(def)) == u64hd || name(sh(def)) == s64hd)
459
	    markreg1(el);
460
 
461
	  fno (e) = 0.0;	/* clear the accumulated value field */
462
	  wbody = weightsv (body, &nel);
463
	  /* do body (which will add to the accumulated value field */
464
	  if (regable (e)) {
465
	    wp p;
466
	    float  loc = fno (e);
467
            if (has_intnl_call(e))
468
               loc += 2.0;
469
	    p = max_weights (shape_size(sh (def)),
470
		(name (def) == name_tag && isusereg (e)) ? 1.0 : loc,
471
		wbody,
472
		isflsh (sh (def)));
473
	    if (name (def) == clear_tag)
474
	      wdef = zeros;
475
	    else {
476
	      float  sp_scale = scale;
477
	      if (!isvar (e) &&
478
		  ((name (def) == name_tag && !isvar (son (def)) &&
479
		      (!isglob (son (def))) && !isloadparam(def)
480
		    ) ||
481
		    (name (def) == cont_tag &&
482
		      name (son (def)) == name_tag &&
483
		      isvar (son (son (def))) &&
484
		      (!isglob (son (son (def)))) &&
485
 
486
		      no_side (body)))) {
487
		if (isusereg (e)) {
488
		  sp_scale = 8.0 * fno (e);
489
		}
490
		else
491
		  sp_scale = fno (e);
492
		p.wp_break = 0;
493
		p.wp_weights = wbody;
494
	      };
495
              old_scale = scale;
496
              scale = sp_scale;
497
	      wdef =
498
		weightsv (def, el);
499
	      wdef = try_mc3 (def, wdef, el);
500
              scale = old_scale;
501
	    };
502
	    no (e) = p.wp_break;/* set the break point */
503
	    return (add_weights (wdef, p.wp_weights));
504
	  };
505
 
506
	  if (name(sh(def)) == nofhd && ptno(sh(def)) == realhd &&
507
		shape_size(sh(def)) >= 640)
508
	    useful_double = 1;
509
 
510
	  if (name (def) == clear_tag)
511
	    wdef = zeros;
512
	  else {
513
	    wdef =
514
		weightsv (def, el);
515
	      wdef = try_mc3 (def, wdef, el);
516
	  };
517
	  no (e) = 16;
518
	  return (add_weights (wdef, wbody));
519
	};
520
	return (zeros);
521
      };
522
    case labst_tag: {
523
	explist nel;
524
	weights wbody;
525
	nel.wident = e;
526
	nel.etl = el;
527
	old_scale = scale;
528
	wbody = weightsv (bro (son (e)), &nel);
529
	scale = old_scale;
530
	return (wbody);
531
      };
532
    case rep_tag: {
533
	swl = weightsv (son (e), el);
534
 
535
        old_scale = scale;
536
 
537
        if (scale < 1e30)
538
		scale = 20*scale;
539
 
540
	bwl = weightsv (bro (son (e)), el);
541
        scale = old_scale;
542
 
543
	return (add_weights (swl, bwl));
544
      };
545
    case cond_tag:  {
546
        old_scale = scale;
547
 
548
        scale = 0.5*scale;
549
        swl = weightsv (son (e), el);
550
	bwl = weightsv (bro (son (e)), el);
551
 
552
        scale = old_scale;
553
 
554
	return (add_weights (swl, bwl));
555
      };
556
    case case_tag:
557
      return (weightsv (son (e), el));
558
 
559
    case compound_tag:
560
      return (add_wlist (son (e), 1, el));
561
      /* may use movc3 for component */
562
 
563
    case res_tag:
564
    case untidy_return_tag:
565
      return (weightsv (son (e), el));
566
 
567
    case asm_tag:
568
    case apply_tag:
569
    case apply_general_tag:
570
    case tail_call_tag:
571
      {
572
        if (name(sh(e)) != bothd && !builtinproc(e))
573
	  markcall (el);
574
	return (add_weights (add_wlist (son (e), 0, el),
575
	      applyregs));
576
      };
577
 
578
    case ass_tag:
579
    case assvol_tag: {
580
      /* may use movc3 for assigned value */
581
      unsigned char shn = name (sh (bro (son (e))));
582
      weights temp;
583
      temp = weightsv (bro (son (e)), el);
584
      if (shn == u64hd || shn == s64hd)
585
	markreg1 (el);
586
      return (add_weights (weightsv (son (e), el),
587
	    try_mc3 (bro (son (e)), temp, el)
588
	  )
589
	);
590
      };
591
    case proc_tag:
592
    case general_proc_tag: {
593
	IGNORE weightsv (son (e), (explist *) 0);
594
	return (zeros);
595
      };
596
    case movecont_tag:
597
      if (isnooverlap(e))
598
        return (add_weights (add_wlist (son (e), 0, el), moveregs));
599
      else {
600
        markcall(el);
601
        return (add_wlist (son (e), 0, el));
602
      };
603
    case val_tag:
604
    case real_tag:
605
    case env_offset_tag:
606
      return (zeros);
607
 
608
    case test_tag:
609
     {weights wlarg;
610
      if (name(sh(son(e))) == s64hd || name(sh(son(e))) == u64hd)
611
	markreg1 (el);				/* use of reg0 can include reg1 */
612
      wlarg = add_wlist (son (e), 0, el);
613
      return (wlarg);
614
     };
615
    case prof_tag:
616
      scale = no(e);
617
      return zeros;
618
 
619
    case alloca_tag:
620
     {if (checkalloc(e))
621
	markreg1 (el);
622
      return (add_wlist (son (e), 0, el));
623
     };
624
 
625
    default:
626
      if (sh(e) != nilexp &&
627
		(name(sh(e)) == s64hd || name(sh(e)) == u64hd))
628
	markreg1 (el);				/* use of reg0 can include reg1 */
629
      return (add_wlist (son (e), 1, el));
630
  };
631
}
632
 
633
void comp_weights
634
    PROTO_N ( (e) )
635
    PROTO_T ( exp e )
636
{
637
  scale = 1.0;
638
  IGNORE weightsv (e, (explist *) 0);
639
  return;
640
}