Subversion Repositories tendra.SVN

Rev

Rev 2 | 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: pwe $
33
$Date: 1998/03/11 11:03:20 $
34
$Revision: 1.4 $
35
$Log: check_id.c,v $
36
 * Revision 1.4  1998/03/11  11:03:20  pwe
37
 * DWARF optimisation info
38
 *
39
 * Revision 1.3  1998/02/18  11:22:09  pwe
40
 * test corrections
41
 *
42
 * Revision 1.2  1998/02/11  16:56:38  pwe
43
 * corrections
44
 *
45
 * Revision 1.1.1.1  1998/01/17  15:55:46  release
46
 * First version to be checked into rolling release.
47
 *
48
 * Revision 1.14  1998/01/09  09:28:35  pwe
49
 * prep restructure
50
 *
51
 * Revision 1.13  1997/06/02  08:44:17  currie
52
 * diags visible
53
 *
54
 * Revision 1.12  1997/03/20  17:05:10  currie
55
 * Dwarf2 diags
56
 *
57
Revision 1.11  1997/02/18 12:56:21  currie
58
NEW DIAG STRUCTURE
59
 
60
 * Revision 1.10  1995/10/19  12:11:23  currie
61
 * compound_tag
62
 *
63
 * Revision 1.9  1995/10/17  16:33:53  currie
64
 * Misplace {
65
 *
66
 * Revision 1.8  1995/10/17  12:59:28  currie
67
 * Power tests + case + diags
68
 *
69
 * Revision 1.7  1995/10/13  15:15:03  currie
70
 * case + long ints on alpha
71
 *
72
 * Revision 1.6  1995/10/06  14:41:55  currie
73
 * Env-offset alignments + new div with ET
74
 *
75
 * Revision 1.5  1995/10/04  09:17:27  currie
76
 * CR95_371 + optimise compounds
77
 *
78
 * Revision 1.4  1995/08/31  14:18:58  currie
79
 * mjg mods
80
 *
81
 * Revision 1.3  1995/08/29  10:45:45  currie
82
 * Various
83
 *
84
 * Revision 1.2  1995/06/15  08:42:07  currie
85
 * make_label + check repbtseq
86
 *
87
 * Revision 1.1  1995/04/06  10:44:05  currie
88
 * Initial revision
89
 *
90
***********************************************************************/
91
 
92
 
93
 
94
 
95
/********************************************************************
96
 
97
                        check_id.c
98
 
99
   check_id tries to apply transformations to improve identity and
100
   variable declarations.
101
 
102
   check_id delivers 1 if it makes any change, 0 otherwise.
103
 
104
   used_in delivers 0 if the identifier declared by vardec is unused in
105
   the exp piece, 1 if it is used for contents operation only, 3 if it is
106
   used otherwise.
107
 
108
   simple_const tests whether e is used as a simple constant in whole.
109
   This is true in the following circumstances only.
110
   1) e is a constant.
111
   2) e is an identity declaration(not a variable) and the declaration is
112
      external to whole.
113
   3) e is the contents of a variable, and the variable is not used
114
      in whole as the destination of an assignment, and the variable
115
      is only used (anywhere) as the destination of assignment or
116
      argument of contents (ie there is no alias for it).
117
 
118
   no_ass is true iff there are no assignments to things that might
119
   be aliased during the evaluation of whole. (beware procedure calls!)
120
 
121
 ********************************************************************/
122
#include "config.h"
123
#include "common_types.h"
124
#include "exp.h"
125
#include "expmacs.h"
126
#include "shapemacs.h"
127
#include "check.h"
128
#include "tags.h"
129
#include "externs.h"
130
#include "installglob.h"
131
#include "flags.h"
132
#include "install_fns.h"
133
#include "me_fns.h"
134
#ifdef NEWDIAGS
135
#include "dg_aux.h"
136
#endif
137
 
138
#include "check_id.h"
139
 
140
#if is68000
141
extern int check_anyway PROTO_S ( ( exp ) ) ;
142
#endif
143
 
144
/* PROCEDURES */
145
 
146
/*********************************************************************
147
   make_onearg makes up an exp with the given tag (n), shape (sha)
148
   and single argument (a).
149
 *********************************************************************/
150
 
151
exp hc
152
    PROTO_N ( (e, t) )
153
    PROTO_T ( exp e X exp t )
154
{
155
  setlast(t);
156
  bro(t) = e;
157
  return hold_check(e);
158
}
159
 
160
static exp make_onearg
161
    PROTO_N ( (n, sha, a) )
162
    PROTO_T ( unsigned char n X shape sha X exp a )
163
{
164
  exp r = getexp (sha, nilexp, 0, a, nilexp, 0, 0, n);
165
  return (hc (r, a));
166
}
167
 
168
/*********************************************************************
169
   make_twoarg makes up an exp with the given tag (n), shape (sha)
170
   and two arguments (a,b) in that order.
171
 *********************************************************************/
172
 
173
static exp make_twoarg
174
    PROTO_N ( (n, sha, a, b) )
175
    PROTO_T ( unsigned char n X shape sha X exp a X exp b )
176
{
177
  exp r = getexp (sha, nilexp, 0, a, nilexp, 0, 0, n);
178
  bro (a) = b;
179
  clearlast (a);
180
  return (hc (r, b));
181
}
182
 
183
/************************************************************************
184
   used_in delivers 0 if the identifier declared by vardec is unused in
185
   the exp piece, 1 if it is used for contents operation only, 3 if it is
186
   used otherwise.
187
 ************************************************************************/
188
 
189
int  used_in
190
    PROTO_N ( (vardec, piece) )
191
    PROTO_T ( exp vardec X exp piece )
192
{
193
  int  res = 0;
194
  exp t = pt (vardec);
195
  exp q;
196
  exp upwards = t;
197
  do {				/* test each use of the identifier */
198
    q = t;
199
    while (q != nilexp && q != piece && q != vardec && !parked(q) &&
200
	(name (q) != ident_tag || !isglob(q))) {
201
      upwards = q;
202
      q = bro (q);
203
    };
204
    /* ascend from the use until we reach either vardec or piece */
205
    if (last (upwards) && q == piece) {/* the use was in piece */
206
      res = 1;
207
      if ((last(t) || !last(bro(t)) || name(bro(bro(t))) != 0))  {
208
        if (!last(t) ||
209
          name(bro(t)) != cont_tag)
210
	res = 3;	/* the use was not contents or in diagnostics*/
211
     };
212
    };
213
    t = pt (t);
214
  }
215
  while (t != nilexp && res != 3);
216
  return (res);
217
}
218
 
219
 
220
 
221
/***********************************************************************
222
  simple_const tests whether e is used as a simple constant in whole.
223
  This is true in the following circumstances only.
224
  1) e is a constant.
225
  2) e is an identity declaration(not a variable) and the declaration is
226
     external to whole.
227
  3) e is the contents of a variable, and the variable is not used
228
     in whole as the destination of an assignment, and the variable
229
     is only used (anywhere) as the destination of assignment or
230
     argument of contents (ie there is no alias for it).
231
 
232
  no_ass is true iff there are no assignements to things that might
233
  be aliased during the evaluation of whole. (ware procedure calls!)
234
 ***********************************************************************/
235
 
236
int simple_const
237
    PROTO_N ( (whole, e, decl, no_ass) )
238
    PROTO_T ( exp whole X exp e X int decl X int no_ass )
239
{
240
  if (name (e) == val_tag || name (e) == real_tag || name (e) == null_tag)
241
    return (1);
242
  if (name (e) == name_tag && !isvar (son (e)) &&
243
      (decl || !internal_to (whole, son (e))))
244
    return (1);
245
  if (name (e) == reff_tag)
246
    e = son (e);
247
  if (name (e) == cont_tag && name (son (e)) == name_tag &&
248
      !isparam (son (son (e))) &&
249
      isvar (son (son (e)))) {
250
    exp var = son (son (e));
251
    int  u = used_in (var, whole);
252
    if (u != 3 && (iscaonly(var) || no_ass))
253
      return (1);
254
    return (0);
255
  };
256
  return (0);
257
}
258
 
259
/* replace declaration by sequence of
260
   definition and body. Done if the
261
   identifier is not used. */
262
static void repbyseq
263
    PROTO_N ( (e) )
264
    PROTO_T ( exp e )
265
{
266
  exp def = son (e);
267
  exp body = hold_check(bro (def));
268
  exp seq, s;
269
#ifdef NEWDIAGS
270
  exp t = pt (e);
271
  while (t != nilexp) {
272
    if (isdiaginfo(t))
273
      setdiscarded(t);
274
    t = pt(t);
275
  }
276
#endif
277
  if (son (def) == nilexp) {
278
#ifdef NEWDIAGS
279
    if (diagnose)
280
      dg_whole_comp (e, body);
281
#endif
282
    replace (e, body, e);
283
    retcell (def);
284
    return;
285
  };
286
  seq = getexp (f_bottom, nilexp, 0, def, nilexp, 0, 0, 0);
287
  bro (def) = seq;
288
  setlast (def);
289
  s = hold_check(make_twoarg (seq_tag, sh (body), seq, body));
290
#ifdef NEWDIAGS
291
  if (diagnose)
292
    dg_whole_comp (e, s);
293
#endif
294
  replace (e, s, e);
295
  return;
296
}
297
 
298
/************************************************************************
299
   propagate looks right and upwards from plc through the tree, looking
300
   for contents operations applied to the variable defined by vardec.
301
   The assumption is that plc made an assignment to the variable defined
302
   by vardec, and this scan looks forward from this point, marking any
303
   contents operations on that variable for later modification to use the
304
   value assigned. The variable is previously checked to make
305
   sure there is no alias for it.
306
   The scan terminates if ende is reached or when it is no longer safe
307
   to propagate the value forward. 1 is delivered if ende was reached
308
   while propagation was still safe, 0 otherwise.
309
 ************************************************************************/
310
 
311
static int propagate
312
    PROTO_N ( (vardec, ende, plc, bfirst) )
313
    PROTO_T ( exp vardec X exp ende X exp plc X int bfirst )
314
{
315
  exp p = plc;			/* starting place */
316
  int good = 1;		/* good is set to 0 when we find a place
317
				   where we must stop */
318
  int bb = bfirst;		/* if bb is 1, avoid the first up */
319
 
320
 
321
/* up ascends the tree */
322
up: if (bb)
323
    bb = 0;
324
  else {
325
    if (p == ende) {		/* finished */
326
      goto ex;
327
    }
328
    else {
329
      if (!last (p)) {
330
	p = bro (p);
331
	if (name (p) == labst_tag) {/* can't go further */
332
	  good = 0;
333
	  goto ex;
334
	};
335
      }
336
      else {
337
	if (name (bro (p)) == proc_tag ||
338
             name (bro (p)) == labst_tag ||
339
	     name (bro (p)) == condassign_tag) {
340
	  /* can't go further */
341
	  good = 0;
342
	  goto ex;
343
	}
344
	else {
345
          p = bro(p);
346
          if ((name (p) == ass_tag || name (p) == assvol_tag) &&
347
		name (son (p)) == name_tag && son (son (p)) == vardec) {
348
            good = 0;
349
            goto ex;
350
          };
351
	  goto up;
352
	};
353
      }
354
    };
355
  };
356
 
357
/* rep processes an exp */
358
rep: if (name (p) == ass_tag || name (p) == assvol_tag) {
359
    if (name (son (p)) == name_tag && son (son (p)) == vardec) {
360
      /* just process the value */
361
      p = bro(son(p));
362
      goto rep;
363
    }
364
    else {			/* assignment to something else */
365
      p = son (p);
366
      goto rep;
367
    };
368
  };
369
 
370
  if (name (p) == cont_tag) {
371
    if (name (son (p)) == name_tag && son (son (p)) == vardec) {
372
      set_propagate(p);		/* mark it */
373
      goto up;
374
    }
375
    else {
376
      p = son (p);
377
      goto rep;
378
    };
379
  };
380
 
381
  if (name (p) == name_tag || name(p) == env_offset_tag)
382
    goto up;
383
 
384
  if (name (p) == apply_tag || name(p) == apply_general_tag) {
385
    if (isglob(vardec)) {/* vardec is global */
386
      good = 0;
387
      goto ex;
388
    }
389
    else {			/* not aliased so OK */
390
      p = son (p);
391
      goto rep;
392
    };
393
  };
394
 
395
  if (name (p) == rep_tag) {
396
      good = 0;
397
      goto ex;
398
  };
399
 
400
  if (name (p) == cond_tag) {
401
    if (propagate (vardec, son (p), son (p), 1)) {
402
      good = propagate (vardec, bro(son(bro (son (p)))),
403
			 bro(son(bro (son (p)))), 1);
404
      /* if we can propagate right through the first of the cond we can go
405
         into the alt. This condition is stronger than needed. */
406
      if (good)
407
	goto up;
408
      else
409
	goto ex;
410
    }
411
    else {
412
      good = 0;
413
      goto ex;
414
    };
415
  };
416
 
417
  if (name (p) == solve_tag) {
418
    IGNORE propagate (vardec, son (p), son (p), 1);
419
    /* give up after trying the first element */
420
    good = 0;
421
    goto ex;
422
  };
423
 
424
  if (name (p) == case_tag) {
425
    if (propagate (vardec, son (p), son (p), 1))
426
      goto up;
427
    good = 0;
428
    goto ex;
429
  };
430
 
431
  if (son (p) == nilexp)
432
    goto up;
433
 
434
  p = son (p);
435
  goto rep;
436
 
437
 
438
ex: return (good);
439
}
440
 
441
/*******************************************************************
442
   change_cont looks at all the cont uses of the variable defined by
443
   vardec. If they have been marked by propagate or if force is 1,
444
   the cont(var) is replaced by val.
445
 *******************************************************************/
446
 
447
static exp change_shape
448
    PROTO_N ( (e, sha) )
449
    PROTO_T ( exp e X shape sha )
450
{
451
  if (name (e) == val_tag)
452
    no (e) = dochvar (no (e), sha);
453
  sh (e) = sha;
454
  return (e);
455
}
456
 
457
static int change_cont
458
    PROTO_N ( (vardec, val, force) )
459
    PROTO_T ( exp vardec X exp val X int force )
460
{
461
  exp t;
462
  exp bh = hold (bro (son (vardec)));
463
  int ch = 0;
464
  int go = 1;
465
  int defsize = shape_size(sh(son(vardec)));
466
  while (go) {
467
    t = pt (vardec);
468
    go = 0;
469
    while (!go && t != nilexp) {
470
      if (last (t) && name (bro (t)) == cont_tag &&
471
#ifdef NEWDIAGS
472
	  !isdiaginfo(t) &&
473
#endif
474
	  (to_propagate (bro (t)) || force)) {
475
        if (defsize == shape_size(sh(bro(t)))) {
476
	   exp p = bro (t);
477
	   exp c = change_shape (copy (val), sh (p));
478
	   kill_exp (t, son(bh));
479
	   replace (p, c, son(bh));
480
	   retcell (p);
481
	   t = pt (vardec);
482
	   ch = 1;
483
	   go = 1;
484
        }
485
        else
486
          clear_propagate(bro(t));
487
      }
488
      else
489
	t = pt (t);
490
    };
491
  };
492
  bro (son (vardec)) = son (bh);
493
  setlast (bro (son (vardec)));
494
  bro (bro (son (vardec))) = vardec;
495
  retcell (bh);
496
  return (ch);
497
}
498
 
499
/*********************************************************************
500
   checks identity and variable declarations.
501
 *********************************************************************/
502
 
503
 
504
int check_id
505
    PROTO_N ( (e, scope) )
506
    PROTO_T ( exp e X exp scope )
507
{
508
  int is_var = isvar (e);
509
  int is_vis = (all_variables_visible || isvis (e));
510
  exp def = son (e);
511
  exp body = bro (def);
512
  int looping;
513
  exp t1;
514
 
515
  if ( no (e) == 0 )
516
  {
517
    if (!isvis(e) && !isenvoff(e) && !isglob (e) && !isparam(e)) {
518
		/* the variable is not used */
519
      repbyseq (e);
520
      return (1);
521
    }
522
    else
523
     {
524
       if (isparam(e))
525
         setcaonly(e);
526
       return 0;
527
     };
528
  };
529
 
530
 
531
#if load_ptr_pars
532
  if (!is_vis && is_var && isparam(e) && no(e) > 1 &&
533
	name(sh(def)) == ptrhd
534
#if is68000
535
	&& check_anyway(e)
536
#endif
537
	) {
538
    int ch_load = 1;
539
    int sz = shape_size(sh(def));
540
    t1 = pt (e);
541
    looping = 1;
542
    do {
543
#ifdef NEWDIAGS
544
      if (!isdiaginfo(t1)) {
545
#endif
546
 
547
	if (!last (t1) && last (bro (t1)) &&
548
	    name (bro (bro (t1))) == ass_tag &&
549
	    shape_size(sh(bro(t1))) == sz) {
550
	  ;
551
	}
552
	else
553
	if (!last (t1) || name (bro (t1)) != cont_tag ||
554
	     shape_size(sh(bro(t1))) != sz)
555
	    ch_load = 0;
556
 
557
#ifdef NEWDIAGS
558
      };
559
#endif
560
	if (pt (t1) == nilexp)
561
	  looping = 0;
562
	else
563
	  t1 = pt (t1);
564
    }
565
    while (looping && ch_load);
566
 
567
    if (ch_load) {
568
      exp old_pt_list = pt(e);
569
      int old_uses = no(e);
570
      exp new_var;
571
      exp new_n;
572
      exp real_body;
573
 
574
      t1 = e;
575
      while (name(bro(son(t1))) == ident_tag && isparam(bro(son(t1))))
576
        t1 = bro(son(t1));
577
      real_body = bro(son(t1));
578
 
579
      new_n = getexp(sh(def), real_body, 0, e, nilexp, 0,
580
			 0, name_tag);
581
      new_var = getexp(sh(e), nilexp, 0, new_n, old_pt_list,
582
                          1, old_uses, ident_tag);
583
      setloadparam(new_n);
584
      setfather(new_var, real_body);
585
      pt(e) = new_n;
586
      no(e) = 1;
587
      clearvar(e);
588
      while (old_pt_list != nilexp)
589
       {
590
         son(old_pt_list) = new_var;
591
         old_pt_list = pt(old_pt_list);
592
       };
593
      new_var = hold_check(new_var);
594
 
595
      bro(son(t1)) = new_var;
596
      setfather(t1, new_var);
597
      return 1;
598
    };
599
  };
600
#endif
601
 
602
  if (!is_vis && !is_var &&
603
#if load_ptr_pars
604
	(name(def) != name_tag || !isloadparam(def)) &&
605
#endif
606
      (name (def) == val_tag ||
607
#if load_ptr_pars
608
	(name (def) == name_tag &&
609
             (!isparam(son(def)) || name(sh(def)) == ptrhd))
610
#else
611
         name (def) == name_tag
612
#endif
613
          ||
614
#if is80x86
615
	(name(def) == name_tag && isparam(son(def)) && !isvar(son(def)) &&
616
		shape_size(sh(def)) < shape_size(sh(son(son(def)))) &&
617
		name(sh(def)) <= ulonghd) ||
618
#endif
619
 
620
	( /* substitute the definitions of identity declarations into
621
             body if it seems cheaper to do so */
622
	  name (def) == reff_tag && name (son (def)) == cont_tag &&
623
	  name (son (son (def))) == name_tag &&
624
	  isvar (son (son (son (def)))) &&
625
	  !isglob (son (son (son (def)))) &&
626
	  used_in(son (son (son (def))), body) != 3
627
	) ||
628
	(
629
	  name (def) == reff_tag && name (son (def)) == name_tag &&
630
	  isvar (son (son (def))) &&
631
	  !isglob (son (son (def))) &&
632
	  used_in(son (son (def)), body) != 3
633
	) ||
634
	name (def) == null_tag ||
635
	name (def) == real_tag)) {
636
/*     identifying a constant or named value */
637
      {
638
#if !substitute_params
639
      int   do_anyway = 0;
640
#else
641
      int   do_anyway = 1;
642
#endif
643
      if (do_anyway || name (def) != name_tag ||
644
	  !isparam (son (def)) ||
645
	  isvar (son (def))) {
646
	exp bh = hold (body);
647
#ifdef NEWDIAGS
648
	dg_info dgh = dgf(def);
649
	dgf(def) = nildiag;	/* don't copy line info to all uses */
650
#endif
651
	while (pt (e) != nilexp) {
652
	  exp mem = pt (e);
653
	  exp cp;
654
	  pt (e) = pt (mem);
655
	  cp = copy (def);
656
#ifdef NEWDIAGS
657
	  if (isdiaginfo(mem))
658
	    IGNORE diaginfo_exp (cp);
659
	  else
660
	    --no (e);
661
#else
662
	  --no (e);
663
#endif
664
	  if (name (cp) == name_tag)
665
	    no (cp) += no (mem);
666
	  if (sh(cp) != sh(mem)) {
667
	    if (name(sh(cp)) <= u64hd)
668
	      cp = hold_check(me_u3(sh(mem), cp, chvar_tag));
669
	    else
670
	      sh (cp) = sh (mem);
671
	  };
672
#ifdef NEWDIAGS
673
	  if (diagnose)
674
	    dg_whole_comp (mem, cp);
675
#endif
676
	  replace (mem, cp, body);
677
	};
678
#ifdef NEWDIAGS
679
	dgf(def) = dgh;
680
#endif
681
	bro (def) = son (bh);
682
	bro (bro (def)) = e;
683
	setlast (bro (def));
684
	retcell (bh);
685
	IGNORE check (e, scope);
686
	return (1);
687
      };
688
    };
689
  };
690
 
691
  if (!is_vis && !is_var &&
692
         name(def) == reff_tag && al1(sh(def)) == 1
693
 
694
     )  {  /* also substitute identity definitions which are references
695
              to bitfields. */
696
    exp t = pt(e);
697
    int n = no(def);
698
    shape sha = sh(def);
699
    shape shb = sh(son(def));
700
    exp q, k;
701
 
702
#ifdef NEWDIAGS
703
    if (diagnose)
704
      dg_whole_comp (def, son(def));
705
#endif
706
    replace(def, son(def), son(def));
707
 
708
    while (1)
709
     {
710
       k = pt(t);
711
       q = getexp(sha, nilexp, 0, copy(t), nilexp, 0, n, reff_tag);
712
       sh(son(q)) = shb;
713
       q = hc(q, son(q));
714
       replace(t, q, q);
715
       kill_exp(t, t);
716
       if (k == nilexp)
717
         return 1;
718
       t = k;
719
     };
720
  };
721
 
722
 
723
  if (!is_vis && !is_var && name (def) == string_tag) {
724
         /* and substitute strings */
725
    exp t = pt (e);
726
    int all_chars = 1;
727
    while (1) {
728
      if (name (sh (t)) > ucharhd) {
729
	all_chars = 0;
730
	break;
731
      };
732
      if (last (t))	/* Surely this is wrong ??? */
733
	break;
734
      t = pt (t);
735
    };
736
    if (all_chars) {
737
      char *str = nostr(def);
738
 
739
      t = pt (e);
740
      while (1) {
741
	int l = (int)last (t);	/* Surely this is wrong ??? */
742
	exp n = bro (t);
743
	int  v = str[no (t) / 8];
744
	exp c;
745
        if (name (sh (t)) == ucharhd)
746
	  v = v & 0xff;
747
        c = getexp (sh (t), nilexp, 0, nilexp, nilexp, 0, v, val_tag);
748
	replace (t, c, c);
749
	kill_exp (t, t);
750
	if (l)
751
	  break;
752
	t = n;
753
      };
754
      if (no (e) == 0) {
755
	replace (e, bro (son (e)), scope);
756
	return (1);
757
      };
758
      return (0);
759
    };
760
  };
761
 
762
 
763
  if (!is_vis && !is_var &&
764
      name (body) == seq_tag && name (son (son (body))) == ass_tag &&
765
      name (bro (son (body))) == name_tag) {
766
    exp tb = bro (son (son (son (body))));
767
    if (name (tb) == name_tag && son (tb) == e &&
768
	son (bro (son (body))) == e &&
769
	last (son (son (body))) &&
770
	sh (tb) == sh (def) && sh (tb) == sh (bro (son (body)))) {
771
      /*  e=id(def, seq(ass(tz, n(e)), n(e)) -> seq(ass(tz, def),
772
         cont(tz)) */
773
      exp ass = son (son (body));
774
      exp tz = son (ass);
775
      exp r, s, c;
776
      exp cz = copy (tz);
777
      bro (tz) = def;
778
      ass = hc (ass, def);
779
      r = getexp (f_top, nilexp, 0, ass, nilexp, 0, 0, 0);
780
      setlast (ass);
781
      bro (ass) = r;
782
      s = getexp (sh (body), nilexp, 0, r, nilexp, 0, 0, seq_tag);
783
      c = getexp (sh (body), s, 1, cz, nilexp, 0, 0, cont_tag);
784
      setbro (r, hc (c, cz));
785
      replace (e, hc (s, bro (son (s))), e);
786
      return (1);
787
    };
788
  };
789
 
790
    /* look to see if we can replace variable definitions by identities.
791
       This can be done if there are only contents operations and no
792
       aliasing */
793
  if (!is_vis && is_var) {	/* variable declaration */
794
    int all_c = 1;		/* every use is a contents operation */
795
    int all_a = 1;		/* every use is an assignment operation */
796
    int not_aliased = 1;
797
    int ca = 0;		/* there is an assignment of a constant */
798
    int vardecass = 0;		/* there is an assignment of a variable
799
				   (not its contents) (lhvalue in C
800
				   terms). */
801
    exp assd_val;		/* the assigned value */
802
    int conversion = 0;
803
    int biggest_assigned_const = 0;
804
    exp tc = pt (e);
805
    int defsize = shape_size(sh(def));
806
    do {			/* scan the uses of the variable */
807
      if (last(tc) && (name(bro(tc)) == hold_tag || name(bro(tc))==hold2_tag)){
808
#ifdef NEWDIAGS
809
        if (diag_visible) {
810
#else
811
        if (diagnose) {
812
#endif
813
		setvis(e);
814
		return 0;
815
	}
816
      }
817
      else  {
818
      if (last (tc) && name (bro (tc)) == cont_tag && no(tc) == 0 &&
819
#ifdef NEWDIAGS
820
	   !isdiaginfo(tc) &&
821
#endif
822
           (name(sh(bro(tc)))<shrealhd || name(sh(bro(tc)))>doublehd ||
823
            (name(sh(def)) >= shrealhd && name(sh(def)) <= doublehd) )) {
824
	int qq = shape_size(sh(bro (tc)));
825
	all_a = 0;		/* contents op so not all assignments */
826
	if (name(father(bro(tc))) != test_tag)
827
	  conversion = -1;
828
	if ((defsize != qq) &&
829
	    (name(sh(def)) < shrealhd))
830
         {
831
#if is80x86
832
	  if (!isparam(e) || no(e) != 1) {
833
	   if (no(tc) == 0 && defsize <= 32) {
834
	    if (qq == 8)
835
	      setbyteuse(e);
836
	   }
837
	   else {
838
            all_c = 0;
839
	    not_aliased = 0;
840
	   }
841
	  }
842
#else
843
          all_c = 0;
844
	  not_aliased = 0;
845
#endif
846
         };
847
      }
848
      else {
849
	if (!last (tc) && last (bro (tc)) && no(tc) == 0 &&
850
#ifdef NEWDIAGS
851
	    !isdiaginfo(tc) &&
852
#endif
853
	    name (bro (bro (tc))) == ass_tag) {/* assignment op */
854
	  all_c = 0;		/* not all contents */
855
	  assd_val = bro (tc);
856
 
857
	  if (name(assd_val) == val_tag) {
858
	    if (no(assd_val) < 0 )
859
	      conversion = -1;
860
	    if (no(assd_val) > biggest_assigned_const)
861
	      biggest_assigned_const = no(assd_val);
862
	  }
863
	  else
864
	  if (name(assd_val) == chvar_tag &&
865
		name(sh(son(assd_val))) <= uwordhd &&
866
		is_signed(sh(son(assd_val)))) {
867
	    int sz1 = shape_size(sh(son(assd_val)));
868
	    if (conversion == 0)
869
	      conversion = sz1;
870
	    else
871
	    if (conversion != sz1)
872
	      conversion = -1;
873
	  }
874
	  else
875
	    conversion = -1;
876
 
877
	  if (defsize != shape_size(sh(assd_val)))
878
           {
879
#if is80x86
880
	    if (no(tc) == 0 && defsize <= 32) {
881
	      if (shape_size(sh(bro(tc))) == 8)
882
		setbyteuse(e);
883
	    }
884
	    else {
885
              all_a = 0;
886
	      not_aliased = 0;
887
	    };
888
#else
889
            all_a = 0;
890
	    not_aliased = 0;
891
#endif
892
           };
893
	  if (name (assd_val) == val_tag || name (assd_val) == real_tag ||
894
	      name (assd_val) == null_tag ||
895
	      (name (assd_val) == name_tag &&
896
		isglob (son (assd_val))))
897
	    ca = 1;		/* assigning a constant */
898
	  else {
899
	    if (name (assd_val) == ident_tag &&
900
		isvar (assd_val))
901
	      vardecass = 1;
902
	  };
903
	}
904
	else
905
#ifdef NEWDIAGS
906
	if (!isdiaginfo(tc))
907
#endif
908
	{
909
	  if (isreallyass(tc)) {
910
	    all_c = 0;
911
	    all_a = 0; /* so that we dont remove the proc call */
912
	  }
913
	  else {			/* something else */
914
	  exp dad = father (tc);
915
	  all_c = 0;
916
	  all_a = 0;
917
	  if (!((name (dad) == addptr_tag || name (dad) == subptr_tag) &&
918
		((!last (dad) && last (bro (dad)) &&
919
		    name (bro (bro (dad))) == ass_tag) ||
920
		  (last (dad) && name (bro (dad)) == cont_tag))) ||
921
	      (name (sh (def)) == realhd &&
922
		name (sh (bro (dad))) != realhd) ||
923
	      (name (sh (def)) == doublehd &&
924
		name (sh (bro (dad))) != doublehd))
925
	    /* not an assignment to element of array */
926
	    not_aliased = 0;
927
          else
928
            {
929
              setvis (e);
930
              uses_loc_address = 1;
931
            };
932
	  };
933
	}
934
       };
935
      };
936
      tc = pt (tc);
937
    }
938
    while (tc != nilexp);
939
    if (not_aliased || iscaonly(e))
940
      setcaonly (e);		/* set no alias flag if nothing but cont
941
				   and ass */
942
    else
943
     {
944
      setvis (e);		/* set visible flag if there is an alias
945
				*/
946
      uses_loc_address = 1;
947
     };
948
 
949
    if (all_c) {		/* if only cont operations replace by an
950
				   identity declaration and change the
951
				   uses accordingly */
952
      exp bh = hold (body);
953
      int  i,
954
            j;
955
      setid(e);
956
      tc = e;
957
      do {
958
	tc = pt (tc);
959
        if (name(bro(tc)) == cont_tag)  {
960
	  sh (tc) = sh (bro (tc));
961
#ifdef NEWDIAGS
962
	  if (diagnose)
963
	    dg_whole_comp (bro(tc), tc);
964
#endif
965
	  replace (bro (tc), tc, tc);
966
        };
967
      }
968
      while (pt (tc) != nilexp);
969
 
970
      if (no(e) < 100) {
971
        for (i = 0; i < no (e); ++i) {
972
	  tc = e;
973
	  for (j = 0; tc != nilexp && j <= i; ++j) {
974
	    tc = pt (tc);
975
#ifdef NEWDIAGS
976
	    while (tc != nilexp && isdiaginfo(tc))
977
	      tc = pt (tc);
978
#endif
979
	  }
980
	  altered (tc, son (bh));
981
        };
982
      };
983
 
984
      bro (def) = son (bh);
985
      bro (bro (def)) = e;
986
      setlast (bro (def));
987
      retcell (bh);
988
      IGNORE check (e, scope);
989
      return (1);
990
    };
991
 
992
#if is80x86 || ishppa
993
	/* look for places where we can avoid sign extending */
994
    if (not_aliased && name(sh(def)) == slonghd &&
995
	  conversion == 16 && /* not 8 because of 80x86 regs */
996
	  (biggest_assigned_const &
997
	    ((conversion == 8) ? (int)0xffffff80 : (int)0xffff8000)) == 0 &&
998
	name(def) == clear_tag) {
999
      exp temp = pt(e);
1000
      shape ish = (conversion == 8) ? scharsh : swordsh;
1001
      setse_opt(e);
1002
      while (temp != nilexp) {
1003
	exp next = pt(temp);
1004
	if (last(temp)) {
1005
	  if ((last(bro(temp)) || name(bro(bro(temp))) != val_tag) &&
1006
		name(bro(temp)) != hold_tag) {
1007
	    exp x = me_u3(slongsh, copy(bro(temp)), chvar_tag);
1008
	    sh(son(x)) = ish;
1009
	    replace(bro(temp), x, x);
1010
	    IGNORE check(father(x), father(x));
1011
	    kill_exp(bro(temp), bro(temp));
1012
	  };
1013
	}
1014
	else {
1015
	  if (name(bro(temp)) == val_tag)
1016
	    sh(bro(temp)) = ish;
1017
	  else {
1018
	    bro(son(bro(temp))) = bro(bro(temp));
1019
	    bro(temp) = son(bro(temp));
1020
#if ishppa
1021
	    sh(bro(temp)) = (conversion == 8) ? ucharsh : uwordsh;
1022
#endif
1023
	  };
1024
	};
1025
	temp = next;
1026
      };
1027
      replace(def, me_shint(slongsh, 0), def);
1028
    };
1029
#endif
1030
 
1031
    if (not_aliased && no(e) < 1000 &&
1032
         (name(sh(def)) < shrealhd || name(sh(def)) > doublehd) &&
1033
         (ca || vardecass || name (def) == val_tag ||
1034
           name (son (e)) == real_tag || name (def) == null_tag)) {
1035
      /* propagate constant assignment forward from the place where they
1036
         occur */
1037
      int  no_ass;
1038
      int chv;
1039
      if (name (def) == val_tag || name (son (e)) == real_tag ||
1040
	  name (def) == null_tag
1041
/*
1042
		 ||
1043
	  (name (def) == name_tag &&
1044
	    isglob (son (def)))
1045
*/
1046
	  ) {
1047
	do {
1048
	  body = bro (def);
1049
	  IGNORE propagate (e, e, body, 1);
1050
	}
1051
	while (change_cont (e, def, 0));
1052
      };
1053
      body = bro (def);
1054
 
1055
      do {
1056
	chv = 0;
1057
	no_ass = 0;
1058
	tc = pt (e);
1059
	while (!chv && tc != nilexp) {
1060
	  if (!last (tc) &&
1061
#ifdef NEWDIAGS
1062
	      !isdiaginfo(tc) &&
1063
#endif
1064
	      sh (bro (tc)) == sh (son (son (tc))) &&
1065
	      last (bro (tc)) &&
1066
	      name (bro (bro (tc))) == ass_tag) {
1067
	    exp var = bro (tc);
1068
	    exp va, df, bd;
1069
	    if (eq_shape (sh (bro (tc)), sh (son (e))) &&
1070
		(name (bro (tc)) == val_tag ||
1071
		  name (bro (tc)) == real_tag ||
1072
		  name (bro (tc)) == null_tag
1073
/*
1074
		 ||
1075
		  (name (bro (tc)) == name_tag &&
1076
		    isglob (son (bro (tc))))
1077
*/
1078
		 )) {
1079
	      IGNORE propagate (e, e, bro (bro (tc)), 0);
1080
	      chv = change_cont (e, bro (tc), 0);
1081
	      body = bro (def);
1082
	      ++no_ass;
1083
 
1084
	    }
1085
	    else {
1086
	      va = son (tc);
1087
	      df = son (var);
1088
 
1089
	      if (df != nilexp && (bd = bro(df)) != nilexp &&
1090
		  !isinlined(e) &&
1091
		  !isglob(va) && isvar(va) &&
1092
		  name (bd) == seq_tag &&
1093
		  name (bro (son (bd))) == cont_tag &&
1094
		  name (son (bro (son (bd)))) == name_tag &&
1095
		  son (son (bro (son (bd)))) == var &&
1096
		  isvar (var) &&
1097
		  used_in (va, bd) == 0) {
1098
		exp a = son (bro (var));
1099
		exp prev_uses, ass, seq_hold, s;
1100
		kill_exp (bro (son (bd)), body);
1101
		prev_uses = pt (va);
1102
		tc = var;
1103
		pt (va) = pt (var);
1104
		do {
1105
		  son (pt (tc)) = va;
1106
		  ++no (va);
1107
		  tc = pt (tc);
1108
		}
1109
		while (pt (tc) != nilexp);
1110
		pt (tc) = prev_uses;
1111
 
1112
		if (name (df) == clear_tag)
1113
		  ass = getexp (f_top, nilexp, 0, nilexp, nilexp,
1114
		      0, 0, top_tag);
1115
		else {
1116
		  ass = getexp (f_top, nilexp, 0, a, nilexp,
1117
		      0, 0, ass_tag);
1118
		  bro (a) = df;
1119
		  bro (df) = ass;
1120
		  setlast (df);
1121
		};
1122
		seq_hold = make_onearg (0, f_bottom, ass);
1123
		s = make_twoarg (seq_tag, f_top, seq_hold,
1124
                                  son (son (bd)));
1125
		replace (bro (var), s, body);
1126
		chv = 1;
1127
	      };
1128
	    };
1129
	  };
1130
	  tc = pt (tc);
1131
	};
1132
      } while (chv) ;
1133
 
1134
#ifdef NEWDIAGS
1135
      if (no (e) == no_ass && !isparam(e)) {
1136
	int diagonly = 1;
1137
	tc = pt (e);
1138
	while (tc != nilexp) {
1139
	  if (!isdiaginfo(tc)) {
1140
	    if (diagnose)
1141
	      dg_rem_ass (bro(bro(tc)));
1142
	    replace (bro (bro (tc)), bro (tc), bro(def));
1143
	    diagonly = 0;
1144
	  }
1145
	  tc = pt (tc);
1146
	};
1147
	if (!diagonly)
1148
	  repbyseq (e);
1149
      };
1150
#else
1151
      if (no (e) == no_ass && pt (e) != nilexp && !isparam(e)) {
1152
	tc = pt (e);
1153
	while (replace (bro (bro (tc)), bro (tc), bro(def)),
1154
	    pt (tc) != nilexp)
1155
	  tc = pt (tc);
1156
	repbyseq (e);
1157
      };
1158
#endif
1159
      return (1);
1160
    };
1161
 
1162
    if (!isparam(e) && name (def) == clear_tag &&
1163
        name (body) == seq_tag &&
1164
	name (son (son (body))) == ass_tag &&
1165
	name (son (son (son (body)))) == name_tag &&
1166
	son (son (son (son (body)))) == e &&
1167
	eq_shape (sh (def), sh (bro (son (son (son (body))))))) {
1168
      /* definition is clear and first assignment is to this variable */
1169
      exp val = bro (son (son (son (body))));/* assigned value */
1170
      if (!used_in(e, val)) {
1171
        son (e) = val;		/* put it in as initialisation */
1172
        clearlast (val);
1173
        bro (val) = body;
1174
        /* kill the use of var */
1175
        kill_exp (son (son (son (body))), son (son (son (body))));
1176
        replace (son (son (body)),
1177
	    getexp (f_top, nilexp, 0, nilexp, nilexp, 0, 0, top_tag),
1178
	    body);		/* replace assignment by void */
1179
        return (1);
1180
      };
1181
    };
1182
 
1183
#ifdef NEWDIAGS
1184
    if (all_a && !isparam(e) && !diag_visible) {
1185
#else
1186
    if (all_a && !isparam(e) && !diagnose) {
1187
#endif
1188
				/* if only assignments replace them by
1189
				   evaluating the value assigned and
1190
				   discarding it. replace the declaration
1191
				   by a sequence of definition and body */
1192
      tc = pt (e);
1193
 
1194
      while (1)
1195
       {
1196
         if (!last(tc) && name(bro(bro(tc))) == ass_tag) {
1197
#ifdef NEWDIAGS
1198
	   if (diagnose)
1199
	     dg_rem_ass (bro(bro(tc)));
1200
#endif
1201
           replace (bro (bro (tc)), bro (tc), body);
1202
	 }
1203
         tc = pt(tc);
1204
         if (tc == nilexp)
1205
           break;
1206
       };
1207
 
1208
      repbyseq (e);
1209
      return (1);
1210
    };
1211
 
1212
 
1213
  };
1214
 
1215
  if (!is_var && !is_vis && no(e) == 1 && !isparam(e) &&
1216
	name(body) == ident_tag && name(son(body)) == name_tag &&
1217
	son(son(body)) == e &&
1218
	shape_size(def) == shape_size(son(body))) {
1219
#ifdef NEWDIAGS
1220
    if (diagnose) {
1221
      exp t = pt(e);
1222
      while (t) {
1223
	if (isdiaginfo(t))
1224
	  setdiscarded(t);
1225
	t = pt(t);
1226
      }
1227
    }
1228
#endif
1229
    replace(son(body), def, def);
1230
#ifdef NEWDIAGS
1231
    if (diagnose)
1232
      dg_whole_comp (e, body);
1233
#endif
1234
    replace(e, body, scope);
1235
    return 1;
1236
  };
1237
 
1238
  if (!is_var && !is_vis && name(def) == compound_tag) {
1239
	exp c = son(def);
1240
	int nuses = no(e);
1241
	int changed = 0;
1242
	for(; ; ) {
1243
	   int n = name(bro(c));
1244
	   if (n == val_tag || n == real_tag || n == name_tag ||
1245
			 n == null_tag){
1246
	   	exp u = pt(e);
1247
		for(; nuses !=0 && u!=nilexp; ) {
1248
		    exp nextu = pt(u);
1249
#ifdef NEWDIAGS
1250
		    if (!isdiaginfo(u) && no(u)==no(c) && eq_shape(sh(u), sh(bro(c))) ) {
1251
#else
1252
		    if (no(u)==no(c) && eq_shape(sh(u), sh(bro(c))) ) {
1253
#endif
1254
			replace(u, copy(bro(c)), bro(def));
1255
			nextu = pt(u); /* it could have changed */
1256
			kill_exp(u, bro(def));
1257
			nuses--;
1258
			changed = 1;
1259
		    }
1260
		    u = nextu;
1261
		}
1262
	    }
1263
	    if (nuses ==0 || last(bro(c))) break;
1264
	    c = bro(bro(c));
1265
	}
1266
	if ((no(e)==0 || pt(e) == nilexp) && !isenvoff(e) ) {
1267
		repbyseq(e);
1268
		return 1;
1269
	}
1270
	return changed;
1271
  }
1272
  if (!is_var && !is_vis && name(def) == nof_tag) {
1273
	exp c = son(def);
1274
	int changed = 0;
1275
	int nuses = no(e);
1276
	int sz = rounder(shape_size(sh(c)), shape_align(sh(c)));
1277
	int nd = 0;
1278
	for(;; ) {
1279
	   int n = name(c);
1280
	   if (n == val_tag || n == real_tag || n == name_tag || n == null_tag){
1281
	   	exp u = pt(e);
1282
		for(; nuses!=0 && u!=nilexp; ) {
1283
		    exp nextu = pt(u);
1284
#ifdef NEWDIAGS
1285
		    if (!isdiaginfo(u) && no(u)==nd && eq_shape(sh(u), sh(c))) {
1286
#else
1287
		    if (no(u)==nd && eq_shape(sh(u), sh(c))) {
1288
#endif
1289
			replace(u, copy(c), bro(def));
1290
			nextu = pt(u); /* it could have changed */
1291
			kill_exp(u, bro(def));
1292
			nuses--;
1293
			changed = 1;
1294
		    }
1295
		    u = nextu;
1296
		}
1297
	    }
1298
    	    if (nuses==0 || last(c)) break;
1299
	    c = bro(c);
1300
	    nd+=sz;
1301
	}
1302
	if ((no(e)==0 || pt(e) == nilexp) && !isenvoff(e) ) {
1303
		repbyseq(e);
1304
		return 1;
1305
	}
1306
	return changed;
1307
  }
1308
 
1309
  return (0);
1310
}