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