Subversion Repositories tendra.SVN

Rev

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
/**********************************************************************
32
$Author: release $
33
$Date: 1998/01/17 15:56:05 $
34
$Revision: 1.1.1.1 $
35
$Log: dump_distr.c,v $
36
 * Revision 1.1.1.1  1998/01/17  15:56:05  release
37
 * First version to be checked into rolling release.
38
 *
39
 * Revision 1.2  1995/09/12  10:59:17  currie
40
 * gcc pedanttry
41
 *
42
 * Revision 1.1  1995/04/13  09:08:06  currie
43
 * Initial revision
44
 *
45
***********************************************************************/
46
/* dump_distr.c
47
 Idea is to avoid dumping of  s-registers and register parameters
48
    if there is a simple route through a procedure which only uses the values
49
     of its parameters, constants,  globals or t-registers.
50
    Applied to rscopes  after registers have been allocated .
51
    Mechanism is to insert a new exp with name dump_tag in the
52
    appropriate place where son is exp after dump, pt is next dump starting
53
    at pt of original rscope with no and prop fields telling which regs to dump.
54
    Main proc is dump_opt; if dump_opt_flag is off then dump is placed in at highest
55
    level, dumping all the required registers.
56
 
57
*/
58
#include "config.h"
59
#include "common_types.h"
60
#include "exptypes.h"
61
#include "exp.h"
62
#include "expmacs.h"
63
#include "tags.h"
64
#include "bitsmacs.h"
65
#include "new_tags.h"
66
#include "procrectypes.h"
67
#include "common_types.h"
68
#include "shapemacs.h"
69
#include "frames.h"
70
#include "regable.h"
71
#include "dump_distr.h"
72
 
73
bool do_dump_opt = 1;		/*  may be unset by -d flag */
74
 
75
static  space zsp = {
76
  0, 0
77
};				/* long fixed, long flt */
78
 
79
void maxsp
80
    PROTO_N ( (a, b) )
81
    PROTO_T ( space * a X space b )
82
{
83
  a -> fixed |= b.fixed;
84
  a -> flt |= b.flt;
85
}
86
 
87
space suses
88
    PROTO_N ( (e, pars, incpars) )
89
    PROTO_T ( exp e X space * pars X int incpars )
90
{
91
  /* accumulate s regs used in e; pars gives bits indicating which s-regs
92
     are used for the parameters of current proc; incpars says dont ignore
93
     	pars in registers */
94
  space ans;
95
  ans = zsp;
96
  if (e == nilexp)
97
    return ans;
98
  switch (name(e)) {
99
    case name_tag: {
100
	exp id = son (e);
101
	if (name (id) == ident_tag) {
102
	  if (isglob (id) || (props (id) & inanyreg) == 0)
103
	    return ans /* global or not in register */ ;
104
	  if ((props (id) & defer_bit) != 0)
105
	    return suses (son (id), pars, incpars) /* dec does not take space */ ;
106
 
107
	  if (isparam(id) && no(id) !=0 &&
108
	      ((!incpars && props(son(id)) != 0) || no(id)==props(son(id)) ) )
109
	   /* par in original reg (perhaps destined for sreg) */
110
	  	 return ans;
111
 
112
	  if ((props(id) & infreg_bits)!=0 ) {
113
	    if (no (id) != 16 && no (id) != 0) {/* uses floating s-reg */
114
		ans.flt = 3 << ((no (id)) << 1);
115
	    }
116
	  }
117
	  else
118
	    if (no (id) != 0 && no (id) != 2) {
119
	      /* in s seg */
120
	      if (isparam(id) && props(son(id)) !=0 &&
121
	                     props(son(id)) >= incpars) return ans;
122
	      ans.fixed = 1 << (no (id));
123
	    }
124
	}
125
 
126
	break;
127
      }
128
    case case_tag:
129
      {
130
	return suses (son (e), pars, incpars);
131
      }
132
 
133
    case seq_tag: {
134
	exp t = son (son (e));
135
	ans = suses (bro (son (e)), pars, incpars);
136
	for (;;) {
137
	  maxsp (&ans, suses (t, pars,incpars));
138
	  if (last (t)) {
139
	    return ans;
140
	  }
141
	  t = bro (t);
142
	}
143
      }
144
    case 0:
145
    case goto_tag:
146
    case val_tag:
147
    case null_tag:
148
    case real_tag:
149
    case string_tag:
150
    case clear_tag:
151
    case top_tag:
152
    case env_offset_tag:
153
      {
154
	break;
155
      }
156
 
157
    case apply_general_tag: case tail_call_tag:{
158
    	maxsp(&ans, *pars);
159
    	goto default1;
160
    }
161
    case caller_tag: return suses(son(e), pars, incpars);
162
 
163
 
164
    case apply_tag: {
165
	/* proc call preserves s-regs; however must make sure that any
166
	   pars destined for s-regs get there */
167
	exp dad = father(e);
168
	if (name(dad)==res_tag && props(dad)) {
169
		/* tl recursion  - don't have to dump link or later regs */
170
		int i;
171
		exp p = bro(son(e));
172
 
173
		if (last(son(e)) || name(p)==top_tag) return ans;
174
		for(i=(incpars>4)?incpars:4; ; i++) {
175
			if (!valregable(sh(p))) i=8;
176
			maxsp(&ans, suses(p, pars, i));
177
			if(last(p)) return ans;
178
			p = bro(p);
179
		}
180
	} else 	maxsp (&ans, *pars);
181
      }				/* else cont to default */
182
 
183
    default: default1:{
184
	exp t = son (e);
185
	maxsp (&ans, suses (t, pars,incpars));
186
	while (t!=nilexp && !last (t)) {
187
	  t = bro (t);
188
	  maxsp (&ans, suses (t, pars,incpars));
189
	}
190
      }
191
      }
192
  return ans;
193
}
194
 
195
bool sameregs
196
    PROTO_N ( (a, b) )
197
    PROTO_T ( space * a X space * b )
198
{
199
  /*  regs a <= regs b */
200
  return ((a -> fixed | b -> fixed) == b -> fixed && (a -> flt | b -> flt) == b -> flt);
201
 
202
}
203
 
204
space remd
205
    PROTO_N ( (tobd, dmpd) )
206
    PROTO_T ( space * tobd X space * dmpd )
207
{
208
  /* any regs left out of tobd after dmpd has been done */
209
  space ans;
210
  ans.fixed = tobd -> fixed & ~dmpd -> fixed;
211
  ans.flt = tobd -> flt & ~dmpd -> flt;
212
  return ans;
213
}
214
 
215
bool placedump
216
    PROTO_N ( (pe, dmpd, tobd, nds) )
217
    PROTO_T ( exp * pe X space * dmpd X space * tobd X space * nds )
218
{
219
  /* replace exp in pe by new dump with props = fixeds and no = flts to be
220
     dumped ; thread different dumps to same rsc via pt; delivers bool to
221
     say whether all sregs have been dumped */
222
  exp e = *pe;
223
  exp dflt = getexp(nilexp, nilexp, 1, nilexp,nilexp, 0, nds->flt & ~dmpd->flt, dump_tag);
224
  exp dump = getexp (sh (e), bro (e), last (e), e, dflt, 0, (nds -> fixed & ~dmpd -> fixed),
225
       dump_tag);
226
  bro (e) = dump;
227
  setlast (e);
228
  *(pe) = dump;
229
  (dmpd -> fixed) |= nds -> fixed;
230
  (dmpd -> flt) |= nds -> flt;
231
  return sameregs (tobd, dmpd);
232
}
233
 
234
 
235
 
236
 
237
exp goodcond
238
    PROTO_N ( (first, second, beforeb, pars) )
239
    PROTO_T ( exp first X exp second X space * beforeb X space * pars )
240
{
241
  /* delivers last exp in seq first after all tests (to second) ;
242
     beforeb is space upto end of tests; second only use beforeb;
243
     otherwise nilexp */
244
  exp t;
245
  space nds;
246
  int   n = no (son (second));	/* no of uses of labst second */
247
  if (name (first) != seq_tag)
248
    return nilexp;
249
  t = son (son (first));
250
  *beforeb = zsp;
251
  for (;;) {
252
    maxsp(beforeb, suses(t, pars, 0));
253
 
254
    if (name (t) == test_tag) {
255
      if (pt (t) != second)
256
	return nilexp;
257
      if (--n == 0) break;
258
    }
259
    if (last (t)) {
260
     	return nilexp;
261
    }
262
    t = bro (t);
263
  }
264
 
265
  nds = suses (second, pars, 0);
266
  if (sameregs (&nds, beforeb))
267
    return t;
268
  return nilexp;
269
}
270
 
271
bool alljumps
272
    PROTO_N ( (e, slv, nol) )
273
    PROTO_T ( exp e X exp slv X int * nol )
274
{
275
	/* all all branches to labsts of slove_tag slv in e ? */
276
     recurse:
277
	switch (name(e)) {
278
	   case case_tag: {
279
	   	exp z = bro(son(e));
280
	   	for(;;) {
281
	   		if (father(pt(z))==slv) {
282
	   			if (--(*nol)==0) return 1;
283
	   		}
284
	   		if (last(z)) { e = son(e); goto recurse; }
285
	   		z = bro(z);
286
	   	}
287
	   }
288
	   case goto_tag: case test_tag: {
289
	     	 if (father(pt(e))==slv) {
290
	     	 	if (--(*nol)==0) return 1;
291
	     	 }
292
	     	 if (name(e)== goto_tag) return 0;
293
	     	 /* and continue */
294
	   }
295
	   case name_tag: case val_tag: case float_tag: case string_tag:
296
	   	return 0;
297
	   default: {
298
	   	exp se = son(e);
299
	   	if (se==nilexp) return 0;
300
	   	for(;;) {
301
	   		if (last(se)) { e = se; goto recurse; }
302
	   		if (alljumps(se, slv, nol)) return 1;
303
	   		se = bro(se);
304
	   	}
305
	   }
306
	}
307
}
308
 
309
bool goodsolve
310
    PROTO_N ( (e) )
311
    PROTO_T ( exp e )
312
{
313
	exp m = bro(son(e));
314
	int nol;
315
	for(nol=0;;nol++) {
316
		if (no(son(m))!=1) return 0; /* more than one branch to labst */
317
		if (last(m)) break;
318
		m = bro(m);
319
	}
320
	return alljumps(son(e), e, &nol);
321
}
322
 
323
static int  notregs;
324
static int  notfregs;
325
 /* use to make sure of enough t-regs which are not par regs; I reuse any
326
    par registers whose pars are put in s-regs as t-regs  */
327
 
328
void pushdumps
329
    PROTO_N ( (pe, dmpd, tobd, pars) )
330
    PROTO_T ( exp * pe X space * dmpd X space * tobd X space * pars )
331
{
332
 
333
  /* tries to delay the dumps of the s-regs as late as possible
334
     ; pe is the place in the tree to insert any dump found
335
     necessary in this recursion; dmpd gives the sregs already dumped and
336
     tobd is all which may have to be dumped; pars give the registers
337
     containing the initial position of any parameters */
338
 
339
  space nds;
340
  exp e = *(pe);
341
  exp *arg;
342
 
343
  switch (name (e)) {
344
    case ident_tag: {
345
	nds = suses (son (e), pars,0);
346
	if ((props (e) & inanyreg) != 0 && no (e) == 0) {
347
	  /*  This definition will be allocated into a t-reg so make sure
348
	     of enough t-regs which are not par regs; I reuse any par
349
	     registers whose pars are put in s-regs as t-regs  */
350
	  if (is_floating (name (sh (son (e))))) {
351
	    if (notfregs-- < 0) {
352
	      nds = remd (tobd, dmpd);
353
	      placedump ( pe, dmpd, tobd, &nds);
354
	      return;
355
	    }
356
	  }
357
	  else {
358
	    if (notregs-- < 0) {
359
	      nds = remd (tobd, dmpd);
360
	      placedump ( pe, dmpd, tobd, &nds);
361
	      return;
362
	    }
363
	  }
364
	}
365
 
366
	if (name (son (e)) != clear_tag ||
367
	      (isparam(e) && props(son(e))==0 /* ie initially on stack */)  ) {
368
	  /* id could be in s-reg; find from use */
369
	  maxsp (&nds, suses (pt (e), pars, 0));
370
	}
371
	if (sameregs (&nds, dmpd) ||
372
	    !placedump ( pe, dmpd, tobd, &nds)) {
373
	  /* not all regs have been dumped - continue with body */
374
	  arg = &bro(son (e));
375
	  pushdumps ( arg, dmpd, tobd, pars);
376
	}
377
	return;
378
      }
379
 
380
    case seq_tag: {
381
	exp prev;
382
	exp list = son (son (e));
383
	if (last(list) ) {
384
	   nds = suses(bro(son(e)), pars, 8);
385
	   if (nds.fixed==0 && nds.flt==0) {
386
	   	/* seq consists of two exps with last not using regs */
387
	   	pushdumps(&son(son(e)), dmpd, tobd, pars);
388
	   	return;
389
	   }
390
	}
391
	nds = suses (list, pars, 0);
392
	if (!sameregs (&nds, dmpd)) {
393
				/* first statement uses undumped s-regs */
394
	  if (placedump ( pe, dmpd, tobd, &nds)) {
395
	    return;
396
	  }
397
	}
398
	prev = list;
399
	while (!last (list)) {
400
	  prev = list;
401
	  list = bro (list);
402
	  nds = suses (list, pars, 0);
403
	  if (!sameregs (&nds, dmpd)) {
404
	    /* uses undumped s-regs; construct new seq as result of this
405
	       one .... */
406
	    exp s_hold = getexp (sh (e), bro (son (e)), 0, list, nilexp, 0, 0,
407
		name (son (e)));
408
	    exp seq = getexp (sh (e), e, 1, s_hold, nilexp, 0, 0, seq_tag);
409
 
410
	    bro (prev) = son (e);
411
	    setlast (prev);
412
	    bro (son (e)) = seq;
413
	    bro (bro (s_hold)) = seq;
414
	    while (!last (list)) {
415
	      list = bro (list);
416
	    }
417
	    bro (list) = s_hold;
418
	    /* .... and continue with new result */
419
	    arg = &bro(son (e));
420
	    if (!placedump ( arg, dmpd, tobd, &nds)) {
421
	      pushdumps ( arg, dmpd, tobd, pars);
422
	    }
423
	    return;
424
	  }
425
	}
426
	/* no new s-regs used - carry on with result */
427
	arg = &bro(son (e));
428
	pushdumps ( arg, dmpd, tobd, pars);
429
	return;
430
      }
431
 
432
    case cond_tag: {
433
	exp first = son (e);
434
	exp second = bro (first);
435
	exp t;
436
	bool same;
437
	space beforeb;
438
	nds = suses (first, pars, 0);
439
 
440
	same = sameregs (&nds, dmpd);
441
 
442
	if (!same && (t = goodcond (first, second, &beforeb, pars)) != nilexp) {
443
	  /* worth looking further  into first part */
444
	  if (!sameregs(&beforeb, dmpd) ) {
445
	  	if (placedump ( pe, dmpd, tobd, &beforeb)) {
446
	    	 return;
447
	  	}
448
	  }
449
	  if (!last (t)) {
450
	    exp seq_hold =
451
	      getexp (sh (first), bro (son (first)), 0, bro (t), nilexp, 0, 0,
452
		name (son (first)));
453
	    exp new =
454
	      getexp (sh (first), first, 1, seq_hold, nilexp, 0, 0, seq_tag);
455
	    exp x = son (seq_hold);
456
	    while (!last (x)) {
457
	      x = bro (x);
458
	    }
459
	    bro (x) = seq_hold;	/* set dad son seq_hold */
460
 
461
	    bro (bro (seq_hold)) = new;
462
	    setlast (bro (seq_hold));/* set dad of seq_hold */
463
	    bro (son (first)) = new;
464
	    setlast (t);
465
	    bro (t) = son (first);
466
	    /* first is now (t; (rest of first)) */
467
	  }
468
	  arg = &bro(son (first));
469
	  pushdumps ( arg, dmpd, tobd, pars);
470
	  return;
471
 
472
	}
473
	if (!same) {		/* new s-regs used in first part */
474
	  if (placedump ( pe, dmpd, tobd, &nds)) {
475
	    return;
476
	  }
477
	}
478
	arg = &bro(son (e));
479
	pushdumps ( arg, dmpd, tobd, pars);
480
	return;
481
      }
482
 
483
/*    case diag_tag:
484
    case fscope_tag:
485
    case cscope_tag: {
486
	arg= &son(e);
487
	pushdumps ( arg, dmpd, tobd, pars);
488
	return;
489
      }
490
*/
491
    case labst_tag: {		/* can only arrive here from cond */
492
	arg = &bro(son (e));
493
	pushdumps ( arg, dmpd, tobd, pars);
494
	return;
495
      }
496
 
497
    case solve_tag: {
498
    	if (goodsolve(e)) {
499
    		exp m = bro(son(e));
500
    		space old_dmpd;
501
    		nds = suses(son(e), pars, 0);
502
    		if (!sameregs(&nds, dmpd)) {
503
    			if (placedump(pe, dmpd,tobd, &nds) ) return;
504
    		}
505
    		old_dmpd = *dmpd;
506
    		for(;;) {
507
    			pushdumps(&bro(son(m)), dmpd, tobd, pars);
508
    			if (last(m)) return;
509
    			m = bro(m);
510
    			*dmpd = old_dmpd;
511
    		}
512
    	} /* else continue ... */
513
 
514
    }
515
 
516
    default: {
517
    	nds = suses(e, pars, 0);
518
    	if (!sameregs(&nds, dmpd)) {
519
		placedump ( pe, dmpd, tobd, &nds);
520
	}
521
      }
522
  }
523
 
524
}
525
 
526
 
527
void dump_opt
528
    PROTO_N ( (rscope, tobd, pars) )
529
    PROTO_T ( exp rscope X space * tobd X space * pars )
530
{
531
  /* rscope is proc-tag exp;  tobd is set of s-regs to be dumped; pars is
532
     subset of tobd which will be used as  parameters of proc */
533
  exp  * arg;
534
  space dmpd;
535
  dmpd = zsp;			/* those regs already dumped */
536
  arg = &son(rscope);
537
 
538
  notregs = 10;
539
  notfregs = 8;			/* no of t-regs != par regs */
540
  if (!do_dump_opt || No_S || sameregs (tobd, &dmpd) ||
541
  	name(rscope)!=proc_tag) {
542
    placedump ( arg, &dmpd, tobd, tobd);
543
  }
544
  else {
545
    pushdumps ( arg, &dmpd, tobd, pars);
546
  }
547
  return;
548
}