Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – //branches/tendra5/src/installers/common/construct/check.c – Rev 2

Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/**********************************************************************
32
$Author: pwe $
33
$Date: 1998/03/11 11:03:19 $
34
$Revision: 1.3 $
35
$Log: check.c,v $
36
 * Revision 1.3  1998/03/11  11:03:19  pwe
37
 * DWARF optimisation info
38
 *
39
 * Revision 1.2  1998/02/11  16:56:36  pwe
40
 * corrections
41
 *
42
 * Revision 1.1.1.1  1998/01/17  15:55:46  release
43
 * First version to be checked into rolling release.
44
 *
45
 * Revision 1.41  1998/01/09  09:28:25  pwe
46
 * prep restructure
47
 *
48
 * Revision 1.40  1997/12/04  19:38:53  pwe
49
 * ANDF-DE V1.9
50
 *
51
 * Revision 1.39  1997/10/10  18:15:13  pwe
52
 * prep ANDF-DE revision
53
 *
54
 * Revision 1.38  1997/08/23  13:24:00  pwe
55
 * no invert order, and NEWDIAGS inlining
56
 *
57
 * Revision 1.37  1997/08/06  10:58:22  currie
58
 * Catch overflowed constants, PlumHall requirement
59
 *
60
 * Revision 1.36  1996/10/01  08:59:19  currie
61
 * correct chvar exceptions ADA
62
 *
63
Revision 1.35  1996/06/24 17:26:57  currie
64
PIC code with name substitution
65
 
66
Revision 1.34  1996/06/13 09:24:55  currie
67
Bitfield alignments
68
 
69
Revision 1.33  1996/06/05 15:29:48  currie
70
parameter alignment in make_cmpd
71
 
72
 * Revision 1.32  1996/02/28  11:36:18  currie
73
 * assign to promoted pars
74
 *
75
 * Revision 1.31  1996/02/21  09:39:00  currie
76
 * hppa var_callers + inlined bug
77
 *
78
 * Revision 1.30  1996/01/22  14:25:31  currie
79
 * char parameters on bigendian
80
 *
81
 * Revision 1.29  1996/01/17  10:28:06  currie
82
 * param alignment + case bigval
83
 *
84
 * Revision 1.28  1996/01/10  14:58:43  currie
85
 * BIGEND var params chars & shorts
86
 *
87
 * Revision 1.27  1995/11/29  15:30:09  currie
88
 * computed signed nat
89
 *
90
 * Revision 1.26  1995/11/01  11:29:45  currie
91
 * 32 place shifts
92
 *
93
 * Revision 1.25  1995/10/26  10:14:22  currie
94
 * solve_tag - kill_exp scope reduced
95
 *
96
 * Revision 1.24  1995/10/17  12:59:23  currie
97
 * Power tests + case + diags
98
 *
99
 * Revision 1.24  1995/10/17  12:59:23  currie
100
 * Power tests + case + diags
101
 *
102
 * Revision 1.23  1995/10/13  15:14:58  currie
103
 * case + long ints on alpha
104
 *
105
 * Revision 1.22  1995/10/12  15:52:47  currie
106
 * inlining bug
107
 *
108
 * Revision 1.21  1995/10/11  17:09:56  currie
109
 * avs errors
110
 *
111
 * Revision 1.20  1995/10/06  14:41:53  currie
112
 * Env-offset alignments + new div with ET
113
 *
114
 * Revision 1.18  1995/10/04  09:17:26  currie
115
 * CR95_371 + optimise compounds
116
 *
117
 * Revision 1.17  1995/10/03  11:44:58  currie
118
 * field(compound)
119
 *
120
 * Revision 1.16  1995/10/02  10:55:54  currie
121
 * Alpha varpars + errhandle
122
 *
123
 * Revision 1.15  1995/09/19  16:06:43  currie
124
 * isAlpha!!
125
 *
126
 * Revision 1.14  1995/09/15  13:29:00  currie
127
 * hppa + add_prefix + r_w_m complex
128
 *
129
 * Revision 1.13  1995/09/11  15:35:32  currie
130
 * caller params -ve
131
 *
132
 * Revision 1.12  1995/08/31  14:18:56  currie
133
 * mjg mods
134
 *
135
 * Revision 1.11  1995/08/29  10:45:43  currie
136
 * Various
137
 *
138
 * Revision 1.10  1995/08/15  08:25:27  currie
139
 * Shift left + trap_tag
140
 *
141
 * Revision 1.10  1995/08/15  08:25:27  currie
142
 * Shift left + trap_tag
143
 *
144
 * Revision 1.9  1995/08/09  08:59:54  currie
145
 * round bug
146
 *
147
 * Revision 1.8  1995/08/02  13:17:57  currie
148
 * Various bugs reported
149
 *
150
 * Revision 1.7  1995/07/06  09:14:00  currie
151
 * rem & VERSION
152
 *
153
 * Revision 1.6  1995/07/05  09:26:30  currie
154
 * continue wrong
155
 *
156
 * Revision 1.5  1995/07/03  13:42:36  currie
157
 * Tail call needs fp
158
 *
159
 * Revision 1.4  1995/06/26  13:04:32  currie
160
 * make_stack_limit, env_size etc
161
 *
162
 * Revision 1.3  1995/06/22  09:16:19  currie
163
 * offset_mult bug + power
164
 *
165
 * Revision 1.2  1995/05/05  08:10:45  currie
166
 * initial_value + signtures
167
 *
168
 * Revision 1.1  1995/04/06  10:44:05  currie
169
 * Initial revision
170
 *
171
***********************************************************************/
172
 
173
 
174
 
175
/*********************************************************************
176
 
177
                             check.c
178
 
179
  The routine check performs the bottom-up TDF-to-TDF optimising
180
  transformations. When a new exp is created check is applied to
181
  see if a recognised situation has arisen. check assumes that
182
  all components of this new exp have already had check applied to them.
183
  It returns 1 if it has made a change, 0 if not.
184
 
185
 
186
  hold_check holds an exp as the son of a dummy exp and then
187
  applies check. the need for this operation is explained in
188
  the overall documentation.
189
 
190
  eq_exp compares two exp for equality of effect.
191
 
192
  dochvar takes the int, i, and delivers the number which results from
193
  changing its variety to that specified by the shape, t.
194
 
195
 *********************************************************************/
196
 
197
 
198
#include "config.h"
199
#include "common_types.h"
200
#include "xalloc.h"
201
#include "expmacs.h"
202
#include "exp.h"
203
#include "tags.h"
204
#include "flpt.h"
205
#include "flags.h"
206
#include "externs.h"
207
#include "install_fns.h"
208
#include "shapemacs.h"
209
#include "check_id.h"
210
#include "me_fns.h"
211
#include "basicread.h"
212
#include "szs_als.h"
213
#include "installglob.h"
214
#include "machine.h"
215
#include "messages_c.h"
216
#include "natmacs.h"
217
#include "f64.h"
218
#include "misc_c.h"
219
#include "readglob.h"
220
#include "misc_c.h"
221
#ifdef NEWDIAGS
222
#include "dg_aux.h"
223
#endif
224
 
225
#if is80x86
226
#include "localflags.h"
227
#endif
228
 
229
#include "check.h"
230
 
231
extern shape containedshape PROTO_S ((int,int));
232
 
233
/* MACROS */
234
 
235
  /* codes for error treaments */
236
#define impossible 1
237
#define ignore 2
238
 
239
/* IDENTITIES */
240
 
241
static int  masks[33] = {
242
  0,
243
  0x1, 0x3, 0x7, 0xf,
244
  0x1f, 0x3f, 0x7f, 0xff,
245
  0x1ff, 0x3ff, 0x7ff, 0xfff,
246
  0x1fff, 0x3fff, 0x7fff, 0xffff,
247
  0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
248
  0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
249
  0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
250
  0x1fffffff, 0x3fffffff, 0x7fffffff, (int)0xffffffff
251
};
252
 
253
ntest int_inverse_ntest[] = {0, 4, 3, 2, 1, 6, 5};
254
ntest real_inverse_ntest[] = {0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
255
				 12, 11, 14, 13};
256
ntest exchange_ntest[] = {0, 3, 4, 1, 2, 5, 6, 9, 10, 7, 8, 11, 12, 13,
257
				 14};
258
 
259
#if FBASE == 10
260
static char maxdigs[] = "4294967296";
261
#endif
262
 
263
/* PROCEDURES */
264
 
265
/***********************************************************************
266
 
267
  hold_check holds an exp as the son of a dummy exp and then
268
  applies check. After checking it retcells the dummy exp.
269
 
270
 ***********************************************************************/
271
/* puts body on a hold */
272
exp hold
273
    PROTO_N ( (body) )
274
    PROTO_T ( exp body )
275
{
276
  exp body_hold = next_exp();
277
  son (body_hold) = body;
278
  bro (body) = body_hold;
279
  setlast (body);
280
  bro (body_hold) = nilexp;
281
 
282
#if diagnose_registers
283
  setname (body_hold, hold_tag);
284
#else
285
  setname (body_hold, 102);
286
#endif
287
 
288
  return (body_hold);
289
}
290
 
291
exp hold_check
292
    PROTO_N ( (r) )
293
    PROTO_T ( exp r )
294
{
295
  exp h, sn;
296
  h = hold (r);
297
  IGNORE check (r, r);
298
  sn = son (h);
299
  bro(sn) = nilexp;
300
  retcell (h);
301
  return (sn);
302
}
303
 
304
exp hold_const_check
305
    PROTO_N ( (r) )
306
    PROTO_T ( exp r )
307
{
308
  exp ans;
309
  int old = all_variables_visible;
310
  all_variables_visible = 0;
311
  ans = hold_check (r);
312
  all_variables_visible = old;
313
  return ans;
314
}
315
 
316
static exp varchange
317
    PROTO_N ( (s, e) )
318
    PROTO_T ( shape s X exp e )
319
{
320
				/* applies a change_var operation to e, to
321
				   get shape s */
322
  exp r = getexp (s, nilexp, 0, e, nilexp, 0, 0,
323
      chvar_tag);
324
  setlast(e);
325
  bro(e) = r;
326
  return (hold_check (r));
327
}
328
 
329
static int flpt_power_of_2
330
    PROTO_N ( (f) )
331
    PROTO_T ( flpt f )
332
{
333
  flt * r = &flptnos[f];
334
  unsigned short us = r -> mant[0];
335
  int i;
336
 
337
  if ((us & (us - 1)) != 0)
338
    return 0;
339
  for (i = 1; i < MANT_SIZE; i++) {
340
    if (r -> mant[i] != 0)
341
      return 0;
342
  };
343
 
344
  return 1;
345
}
346
 
347
 
348
 
349
/***********************************************************************
350
   eq_explist compares two descendant lists of exp for equality.
351
   The given values, their bro's, bro(bro)'s  etc are compared until
352
   an unequal pair is found or the end of one of the  lists (last) is
353
   found. In this case the lists are equal iff both ends have been
354
   reached.
355
 ***********************************************************************/
356
 
357
static int eq_explist
358
    PROTO_N ( (al, bl) )
359
    PROTO_T ( exp al X exp bl )
360
{
361
  if (al == nilexp && bl == nilexp)
362
    return (1);
363
  if (al == nilexp || bl == nilexp)
364
    return (0);
365
  if (!eq_exp (al, bl))
366
    return (0);
367
  if (last (al) && last (bl))
368
    return (1);
369
  if (last (al) || last (bl))
370
    return (0);
371
  return (eq_explist (bro (al), bro (bl)));
372
}
373
 
374
/***********************************************************************
375
    eq_exp compares two exp for equality of effect. If the name of either
376
    exp is in the side-effecting group (!is_a) the exp are not equal.
377
    This is a crude test, but if it says the exps are equal this is so.
378
    contvol is forbidden.
379
 ***********************************************************************/
380
 
381
int eq_exp
382
    PROTO_N ( (a, b) )
383
    PROTO_T ( exp a X exp b )
384
{
385
  if (name (a) == name (b)) {
386
    if (name (a) == name_tag)
387
      return (son (a) == son (b) && no (a) == no (b) &&
388
	  eq_shape (sh (a), sh (b)));
389
    if (!is_a (name (a)) || !eq_shape (sh (a), sh (b)) ||
390
		 name(a) == contvol_tag)
391
      return (0);
392
    if (name (a) == real_tag) {
393
      int   res = flt_cmp (flptnos[no (a)], flptnos[no (b)]);
394
      return (res == 0);
395
    };
396
    if (name(a) == val_tag)  {
397
      if (isbigval(a)) {
398
	int res;
399
	if (!isbigval(b))
400
	  return 0;
401
	res = flt_cmp (flptnos[no (a)], flptnos[no (b)]);
402
        return (res == 0);
403
      };
404
      if (isbigval(b))
405
	return 0;
406
      return (no(a) == no(b));
407
    };
408
    return (no (a) == no (b) &&
409
	eq_explist (son (a), son (b)));
410
  };
411
  return (0);
412
}
413
 
414
 
415
/**********************************************************************
416
   repbycont replaces e by the exp which loads top, ie. does nothing.
417
 **********************************************************************/
418
 
419
static void repbycont
420
    PROTO_N ( (e, has_label, scope) )
421
    PROTO_T ( exp e X bool has_label X exp scope )
422
{
423
  exp n = getexp (f_top, bro (e), (int)(last (e)), nilexp, nilexp, 0, 0, top_tag);
424
  if (has_label) {
425
    no (son (pt (e)))--;
426
    pt (e) = nilexp;
427
  };
428
#ifdef NEWDIAGS
429
  dgf(n) = dgf(e);
430
#endif
431
  replace (e, n, e);
432
  kill_exp (e, e);
433
  if (scope !=e) altered(n,scope);
434
}
435
 
436
/**********************************************************************
437
   repbygo replaces e by a goto the label.
438
 **********************************************************************/
439
 
440
static void repbygo
441
    PROTO_N ( (e, lab, scope) )
442
    PROTO_T ( exp e X exp lab X exp scope )
443
{
444
  exp g = getexp (f_bottom, nilexp, 0, nilexp, lab, 0, 0, goto_tag);
445
  exp n = getexp (f_top, g, 1, nilexp, nilexp, 0, 0, top_tag);
446
  son (g) = n;
447
  ++no (son (lab));
448
#ifdef NEWDIAGS
449
  dgf(g) = dgf(e);
450
#endif
451
  replace (e, g, e);
452
  kill_exp (e, e);
453
  if (scope !=e) altered(g,scope);
454
}
455
 
456
/**********************************************************************
457
   nos tests the exp t to see if it is a construction that can be
458
   eliminated from a sequence.  It is ignorable or has no side effect.
459
 **********************************************************************/
460
static int nos PROTO_S ((exp t));
461
 
462
static int noslist
463
    PROTO_N ( (tl) )
464
    PROTO_T ( exp tl )
465
{
466
  if (tl == nilexp)
467
    return (1);
468
  if (last (tl))
469
    return (nos (tl));
470
  return (nos (tl) && noslist (bro (tl)));
471
}
472
 
473
 
474
static int nos
475
    PROTO_N ( (t) )
476
    PROTO_T ( exp t )
477
{
478
  unsigned char n = name(t);
479
  if (n == top_tag || n == ignorable_tag)
480
    return (1);
481
  if (n == compound_tag || n == nof_tag) return noslist(son(t));
482
 
483
  return (	(is_a (n) &&
484
		 optop(t) &&
485
		 ((n == name_tag && !islastuse(t)) ||
486
		  n == val_tag ||
487
		  noslist (son (t))
488
		 )
489
		) ||
490
           	(n == ident_tag && !isenvoff(t) &&
491
		 nos (son (t)) &&
492
	     	 nos (bro (son (t)))
493
		)
494
	 );
495
}
496
 
497
 
498
 
499
/**********************************************************************
500
   check_seq carries out transformations on sequences.
501
   Statements with no effect are removed.
502
   Anything after an unconditional goto, or any other statement
503
   producing a bottom shape, is removed.
504
 
505
   No changes are propagated outside the exp "scope".
506
 **********************************************************************/
507
static int maxes [] = {0, 0, 0, 127, 255, 32767, 65535,
508
		 (int)0x7fffffff, (int)0xffffffff};
509
static int mins[] = {0, 0, 0, -128, 0, -32768, 0, (int)0xffffffff, 0};
510
static shape * us_shape[] = {&f_bottom, &f_bottom, &f_top, &ucharsh,
511
				&ucharsh,
512
				&uwordsh, &uwordsh, &ulongsh, &ulongsh};
513
 
514
static exp make_test
515
    PROTO_N ( (nt, lab, arg1, arg2, nm) )
516
    PROTO_T ( ntest nt X exp lab X exp arg1 X exp arg2 X unsigned char nm )
517
{
518
  exp r;
519
  r = getexp (f_top, nilexp, 0, arg1, lab, 0, 0, nm);
520
  fno(r) = (float)0.5;
521
  settest_number(r, (int)nt);
522
  setbro(arg1, arg2);
523
  clearlast(arg1);
524
  ++no(son(lab));
525
  setfather (r, arg2);
526
  return r;
527
}
528
 
529
static int simple
530
    PROTO_N ( (e) )
531
    PROTO_T ( exp e )
532
{
533
  if (name(e) == cont_tag && name(son(e)) == name_tag)
534
    return 1;
535
  if (name(e) == cont_tag && name(son(e)) == cont_tag &&
536
	name(son(son(e))) == name_tag)
537
    return 1;
538
  if (name(e) == cont_tag && name(son(e)) == reff_tag &&
539
	name(son(son(e))) == cont_tag &&
540
	name(son(son(son(e)))) == name_tag)
541
    return 1;
542
  if (name(e) == name_tag && !isvar(son(e)))
543
    return 1;
544
  return 0;
545
}
546
 
547
static exp tests_to_bounds
548
    PROTO_N ( (a, b) )
549
    PROTO_T ( exp a X exp b )
550
{
551
  exp x = son(a);
552
  int na = no(bro(x));
553
  int nb = no(bro(son(b)));
554
  int ntemp;
555
  ntest nta = test_number(a);
556
  ntest ntb = test_number(b);
557
  ntest nttemp;
558
  exp lab = pt(a);
559
  shape sha = sh(x);
560
 
561
  if (simple(x))
562
    return nilexp;
563
 
564
  if (nta == f_greater_than) {
565
    if (na == maxes[name(sha)])
566
      return nilexp;
567
    nta = f_greater_than_or_equal;
568
    ++na;
569
  };
570
  if (ntb == f_greater_than) {
571
    if (nb == maxes[name(sha)])
572
      return nilexp;
573
    ntb = f_greater_than_or_equal;
574
    ++nb;
575
  };
576
  if (ntb == f_greater_than_or_equal) {
577
    ntemp = na;
578
    na = nb;
579
    nb = ntemp;
580
    nttemp = nta;
581
    nta = ntb;
582
    ntb = nttemp;
583
  };
584
  if (nta != f_greater_than_or_equal)
585
    return nilexp;
586
  if (ntb != f_less_than_or_equal && ntb != f_less_than)
587
    return nilexp;
588
 
589
  if (ntb == f_less_than) {
590
    if (nb == mins[name(sha)])
591
      return nilexp;
592
    ntb = f_less_than_or_equal;
593
    --nb;
594
  };
595
 
596
  UNUSED(ntb);
597
 
598
  if (is_signed(sha)) {
599
    if (nb < na)
600
      return nilexp;
601
  }
602
  else {
603
    if ((unsigned int)nb < (unsigned int)na)
604
      return nilexp;
605
  };
606
  no(son(lab)) -= 1; /* one is removed by kill_exp below */
607
  if (na == nb) {
608
    kill_exp(b, b);
609
    return make_test(f_equal, lab, x, me_shint(sha, na), test_tag);
610
  };
611
  {
612
    exp s = hold_check(me_b2(x, me_shint(sha, na), minus_tag));
613
    exp n = me_shint(sha, nb -na);
614
    shape new_sha = *us_shape[name(sha)];
615
    sh(s) = new_sha;
616
    sh(n) = new_sha;
617
    kill_exp(b, b);
618
    return make_test(f_less_than_or_equal, lab, s, n, test_tag);
619
  };
620
}
621
 
622
static int check_seq
623
    PROTO_N ( (e, scope) )
624
    PROTO_T ( exp e X exp scope )
625
{
626
  exp z = son (e);
627
  exp t, k, kk;
628
  int changed = 0;
629
 
630
  if (name(sh(bro(son(e)))) == bothd && name(sh(e)) != bothd) {
631
    sh(e) = f_bottom;
632
    changed = 1;
633
  };
634
 
635
  while (name (sh (son (z))) == bothd || nos (son (z))) {
636
    if (name (sh (son (z))) == bothd) {
637
      if (!last (son (z))) {
638
	kk = bro (son (z));
639
	while (kk != nilexp) {
640
	  k = kk;
641
	  if (!last (k))
642
	    kk = bro (k);
643
	  else
644
	    kk = nilexp;
645
#ifdef NEWDIAGS
646
	  dg_dead_code (k, son(z));
647
#endif
648
	  kill_exp (k, k);
649
	};
650
      };
651
#ifdef NEWDIAGS
652
      if (diagnose) {
653
	dg_dead_code (bro(z), son(z));
654
	dg_whole_comp (e, son(z));
655
      }
656
#endif
657
      kill_exp (bro (z), bro (z));	/* kill dead variable refs */
658
      setfather (e, z);			/* before replace */
659
      replace (e, son (z), scope);
660
      retcell (z);
661
      retcell (e);
662
      return (1);
663
    };
664
    if (last (son (z))) {
665
#ifdef NEWDIAGS
666
      if (diagnose) {
667
	dg_rdnd_code (son(z), bro(z));
668
	dg_whole_comp (e, bro(z));
669
      }
670
#endif
671
      replace (e, bro (z), scope);
672
      kill_exp (son (z), son (z));
673
      retcell (z);
674
      retcell (e);
675
      return (1);
676
    };
677
#ifdef NEWDIAGS
678
    if (diagnose)
679
      dg_rdnd_code (son(z), bro(son(z)));
680
#endif
681
    k = son (z);
682
    son (z) = bro (son (z));
683
    kill_exp (k, k);
684
  };
685
  t = son (z);
686
  for (;;) {
687
    if (name(t) == test_tag && name(bro(son(t))) == val_tag &&
688
	  !isbigval(bro(son(t))) &&
689
	  name(sh(son(t))) <= ulonghd) {
690
      exp b;
691
      exp bnds;
692
      exp * ref;
693
      if (last(t)) {
694
	b = bro(bro(t));
695
        if (name(b) == test_tag && name(bro(son(b))) == val_tag &&
696
	    !isbigval(bro(son(b))) &&
697
	    pt(t) == pt(b) &&
698
	    eq_exp(son(t), son(b))) {
699
	  bnds = tests_to_bounds(t, b);
700
	  if (bnds == nilexp) {
701
	    if (changed)
702
	      altered(e, scope);
703
	    return 0;
704
	  };
705
	  if (t == son(z)) {
706
#ifdef NEWDIAGS
707
	    if (diagnose)
708
	      dg_whole_comp (e, bnds);
709
#endif
710
	    replace(e, bnds, scope);
711
	    retcell(e);
712
	    return 1;
713
	  };
714
	  ref = refto(father(t), t);
715
	  bro(*ref) = bro(t);
716
	  setlast(*ref);
717
	  setlast(bnds);
718
	  bro(bnds) = e;
719
	  bro(z) = bnds;
720
          return 0;
721
	}
722
	else {
723
	  if (changed)
724
	    altered(e, scope);
725
	  return 0;
726
	};
727
      };
728
      b = bro(t);
729
      if (name(b) == test_tag && name(bro(son(b))) == val_tag &&
730
	    !isbigval(bro(son(b))) &&
731
	    pt(t) == pt(b) &&
732
	    eq_exp(son(t), son(b))) {
733
	exp brob = bro(b);
734
	int lb = last(b);
735
	ref = refto(father(t), t);
736
	bnds = tests_to_bounds(t, b);
737
	if (bnds != nilexp) {
738
	  bro(bnds) = brob;
739
	  if (lb)
740
	    setlast(bnds);
741
	  else
742
	    clearlast(bnds);
743
	  *ref = bnds;
744
	  t = bnds;
745
	};
746
      };
747
    };
748
 
749
    if (last (t)) {
750
      if (changed)
751
	altered(e, scope);
752
      return 0;
753
    };
754
    if (name (sh (bro (t))) == bothd) {
755
      if (!last (bro (t))) {
756
	kk = bro (bro (t));
757
	while (kk != nilexp) {
758
	  k = kk;
759
	  if (!last (k))
760
	    kk = bro (k);
761
	  else
762
	    kk = nilexp;
763
#ifdef NEWDIAGS
764
	  if (diagnose)
765
	    dg_dead_code (k, bro(t));
766
#endif
767
	  kill_exp (k, k);
768
	};
769
      };
770
#ifdef NEWDIAGS
771
      if (diagnose)
772
	dg_dead_code (bro(z), bro(t));
773
#endif
774
      kill_exp (bro (z), bro (z));
775
      bro (z) = bro (t);
776
      setlast (bro (z));
777
      bro (bro (z)) = e;
778
      setlast (t);
779
      bro (t) = z;
780
      sh(e) = f_bottom;
781
      altered(e, scope);
782
      return 0;
783
    };
784
    if (nos (bro (t))) {
785
      if (last (bro (t))) {
786
#ifdef NEWDIAGS
787
	if (diagnose)
788
	  dg_rdnd_code (bro(t), bro(z));
789
#endif
790
	kill_exp (bro (t), bro (t));
791
	setlast (t);
792
	bro (t) = z;
793
	return 0;
794
      };
795
      k = bro (t);
796
      bro (t) = bro (bro (t));
797
#ifdef NEWDIAGS
798
      if (diagnose)
799
	dg_rdnd_code (k, bro(t));
800
#endif
801
      kill_exp (k, k);
802
      changed = 1;
803
    }
804
    else
805
      t = bro (t);
806
  }
807
  /* UNREACHED */
808
}
809
 
810
/**********************************************************************
811
 
812
   comm_ass applies the commutative and associative laws to replace e
813
   by an improved version. op_tag is the operation involved. If
814
   the errtreat is not ignore or impossible, no change is made. C
815
   programs will always use ignore or impossible.
816
 
817
   All the arguments of sub-operations with the same op_tag (they will
818
   anyway have the same shape) are flattened into one argument list,
819
   provided that dive is 1.
820
 
821
   All the constants are combined into one, which is placed as the last
822
   constant. The parameter "one" is the unit for the given operation
823
   (0 for + , 1 for * , allones for and, 0 for or, 0 for xor) and this
824
   constant is eliminated. If the operation has a zero, "has_zero" is
825
   set and "zero" is the constant (0 for * , 0 for and, allones for or).
826
 
827
   No changes are propagated outside the exp "scope".
828
 
829
   If isreal is 1 the operation has real arguments and results, otherwise
830
   integer.
831
 
832
   fn(a, b) is applicable to exps defining constants of the correct type
833
   (integer or real) and delivers an exp defining a constant which is
834
   the result of the op_tag applied to these constants.
835
 
836
 
837
 **********************************************************************/
838
static int  f_one PROTO_S ((flpt f));
839
static int seq_distr PROTO_S ((exp e, exp scope));
840
 
841
static int comm_ass
842
    PROTO_N ( (e, op_tag, fn, one, has_zero, zero, scope, dive, isreal) )
843
    PROTO_T ( exp e X unsigned char op_tag X
844
	      void  (*fn) PROTO_S (( exp, exp, int )) X
845
	      int one X int has_zero X int zero X exp scope X
846
	      int dive X int isreal )
847
{
848
  exp t = son (e);		/* starting element */
849
  int changed = last (t);
850
  exp  cst;		/* start the accumulated constant */
851
  exp cst_u = nilexp;	/* holds exp representing one if created here */
852
  int looping;
853
 
854
  if (isreal)
855
     cst = getexp (sh (e), nilexp, 0, nilexp, nilexp, 0, one, real_tag);
856
  else  {
857
     cst = me_shint(sh(e), one);
858
     if (one == -1 && shape_size(sh(e)) == 64) {
859
	flpt f = new_flpt();
860
	flt * fp = &flptnos[f];
861
	int i;
862
	fp->sign = 1;
863
	fp->exp = 3;
864
	for (i=0; i< 4; ++i)
865
	  fp->mant[i] = 65535;
866
	no(cst) = f;
867
	setbigval(cst);
868
        cst_u = cst;
869
     };
870
  };
871
 
872
  if (!optop(e))
873
    return 0;
874
  do {				/* look to see if a change will be made */
875
    if ((name (t) == op_tag && optop(t)) || name (t) == val_tag ||
876
           name(t) == real_tag)
877
      changed = 1;
878
    looping = !last (t);
879
    t = bro (t);
880
  }
881
  while (looping);
882
 
883
  if (changed) {		/* continue if there will be a change */
884
    exp p, q;
885
    t = son (e);		/* start */
886
    q = getexp (sh (e), nilexp, 0, nilexp, nilexp, 0, 0, op_tag);
887
    seterrhandle(q, errhandle(e));
888
    /* start the result */
889
    p = q;			/* p is used to point to the current place
890
				   where the next item will be added (as
891
				   bro). */
892
    do {
893
      while (name (t) == op_tag && optop(t) && dive)
894
	t = son (t);		/* dive down same operator */
895
      if (name (t) == val_tag || name(t) == real_tag) {
896
	fn (cst, t, errhandle(e));	/* accumulate constant value */
897
#ifdef NEWDIAGS
898
	if (diagnose)
899
	  dg_detach_const (t, cst);
900
#endif
901
      }
902
      else {			/* add item at p and move p on */
903
	bro (p) = t;
904
	clearlast (p);
905
	p = bro (p);
906
      };
907
      while (last (t) && bro (t) != e)
908
	t = bro (t);		/* ascend from sub-item */
909
    }
910
    while ((last (t)) ? 0 : (t = bro (t), 1));
911
    son (q) = bro (q);		/* put q into correct form (we were using
912
				   its bro) */
913
 
914
    if (p == q) {
915
      /* no items but constant */
916
      retcell(q);
917
#ifdef NEWDIAGS
918
      if (diagnose)
919
	dg_whole_comp (e, cst);
920
#endif
921
      replace (e, cst, scope);
922
      retcell(e);
923
      return (1);
924
    };
925
 
926
    if (has_zero &&
927
         ((!isreal && no(cst) == zero && !isbigval(cst)) ||
928
          (isreal && flptnos[no(cst)].sign == 0))) {
929
      /* zero constant. Replace by a sequence of expressions delivering
930
         the zero, so as to keep side effects */
931
      exp r;
932
      setname (q, 0);		/* use q a seq holder */
933
      son (q) = bro (q);
934
      bro (p) = q;
935
      setlast (p);
936
      clearlast (q);
937
      bro (q) = cst;
938
      r = getexp (sh (e), nilexp, 0, q, nilexp, 0, 0, seq_tag);
939
#ifdef NEWDIAGS
940
      if (diagnose)
941
	dgf(r) = dgf(e);
942
#endif
943
      replace (e, hc (r, cst), scope);
944
      return (1);
945
    };
946
 
947
    if ((!isreal &&
948
		(no(cst) != one || (isbigval(cst) && cst != cst_u))) ||
949
         (isreal && cmpflpt(no(cst), one, 6))) {
950
		/* form result if there is a non-unit
951
				   constant term */
952
      bro (p) = cst;
953
      clearlast (p);
954
      p = bro (p);
955
      son (q) = bro (q);
956
      bro (p) = q;
957
      setlast (p);
958
      sh (q) = sh (e);
959
#ifdef NEWDIAGS
960
      if (diagnose)
961
	dgf(q) = dgf(e);
962
#endif
963
      replace (e, q, scope);
964
      retcell(e);
965
      return (1);
966
    };
967
 
968
#ifdef NEWDIAGS
969
    if (diagnose)
970
      dgf(e) = combine_diaginfo (dgf(e), dgf(cst));
971
#endif
972
    retcell(cst);   /* there are no constants other than unit*/
973
 
974
    if (son (q) == p) {		/* form result if single item and no
975
				   constant */
976
      sh (p) = sh (e);
977
#ifdef NEWDIAGS
978
      if (diagnose)
979
	dg_whole_comp (e, p);
980
#endif
981
      replace (e, hold_check(p), scope);
982
      retcell(e);
983
      return (1);
984
    };
985
 
986
    bro (p) = q;		/* form result if no constant and more
987
				   than one arg */
988
    setlast (p);
989
    sh (q) = sh (e);
990
#ifdef NEWDIAGS
991
    if (diagnose)
992
      dg_whole_comp (e, q);
993
#endif
994
    replace (e, q, scope);
995
    retcell(e);
996
    return (1);
997
  };
998
 
999
  return 0;	/* return from here if no change made */
1000
}
1001
 
1002
 
1003
 
1004
/* dochvar takes the int, i, and delivers
1005
   the number which results from changing
1006
   its variety to that specified by the
1007
   shape, t. */
1008
int  dochvar
1009
    PROTO_N ( (i, t) )
1010
    PROTO_T ( int i X shape t )
1011
{
1012
   if (name(t) == bitfhd) {
1013
     int m = masks[shape_size(t)];
1014
     int x  = i & m;
1015
     if (is_signed(t)) {
1016
	int sm = ((m+1)>>1) & x;
1017
	x -= (sm << 1);
1018
     }
1019
     return x;
1020
   }
1021
   switch (shape_size(t))
1022
   {
1023
    case 8:
1024
      {
1025
        if (is_signed(t))
1026
         {
1027
	   int  x = i & 0xff;
1028
	   if (x & 128)
1029
	     return (i | (~0xff));
1030
	   return (i & 0xff);
1031
         }
1032
        else
1033
         return (i & 0xff);
1034
      };
1035
    case 16:
1036
      {
1037
        if (is_signed(t))
1038
         {
1039
	   int  x = i & 0xffff;
1040
	   if (x & 32768)
1041
	     return (i | (~0xffff));
1042
	   return (i & 0xffff);
1043
         }
1044
        else
1045
         return (i & 0xffff);
1046
      };
1047
    case 32:
1048
      {
1049
        if (is_signed(t))
1050
         {
1051
	   int  x = i & (int)0xffffffff;
1052
	   if (x & (int)0x80000000)
1053
	     return (i | (~(int)0xffffffff));
1054
	   return (i & (int)0xffffffff);
1055
         }
1056
        else
1057
         return (i & (int)0xffffffff);
1058
      };
1059
    case 64:
1060
      return (i);
1061
    default:
1062
      return (i & masks[shape_size(t)]);
1063
  };
1064
}
1065
 
1066
static void dochvar_f
1067
    PROTO_N ( (xa, sha) )
1068
    PROTO_T ( flt64 * xa X shape sha )
1069
{
1070
 
1071
  if (shape_size(sha) == 64)
1072
    return;
1073
  *xa = int_to_f64(dochvar((int)xa->small, sha), is_signed(sha));
1074
  return;
1075
}
1076
 
1077
static void bigres
1078
    PROTO_N ( (a, xp) )
1079
    PROTO_T ( exp a X flt64 * xp )
1080
{
1081
  int bg;
1082
  dochvar_f(xp, sh(a));
1083
  no(a) = f64_to_flpt(*xp, is_signed(sh(a)), &bg, shape_size(sh(a)));
1084
  if (bg)
1085
    setbigval(a);
1086
  else
1087
    clearbigval(a);
1088
  return;
1089
}
1090
 
1091
static int check_size
1092
    PROTO_N ( (a, sg, sz) )
1093
    PROTO_T ( flt64 a X int sg X int sz )
1094
{
1095
  int t = (int)a.small;
1096
  if (sz > 32)
1097
    return 0;
1098
 
1099
  if (sg && (t >> 31) == a.big && (sz == 32 || (t >> (sz-1)) == a.big))
1100
    return 0;
1101
 
1102
  if (!sg && a.big == 0 && (sz == 32 || (t >> sz) == 0))
1103
    return 0;
1104
  return 1;
1105
}
1106
 
1107
 
1108
/* used as a fn parameter for comm_ass q.v. */
1109
static void fplus_fn
1110
    PROTO_N ( (ap, b, et) )
1111
    PROTO_T ( exp ap X exp b X int et )
1112
{
1113
  int a = no(ap);
1114
  int  nob = no (b);
1115
  flt resval;
1116
  int status;
1117
  UNUSED (et);
1118
 
1119
  status = flt_add (flptnos[a], flptnos[nob], &resval);
1120
  if (status == OKAY) {
1121
      flpt_round((int)f_to_nearest,
1122
		 flpt_bits((floating_variety)(name(sh(b))-shrealhd)),
1123
		 &resval);
1124
      flptnos[nob] = resval;
1125
      no(ap) = nob;
1126
    }
1127
  else
1128
    failer(ILLEGAL_FLADD);
1129
  return;
1130
}
1131
 
1132
/* used as a fn parameter for comm_ass q.v. */
1133
static void fmult_fn
1134
    PROTO_N ( (ap, b, et) )
1135
    PROTO_T ( exp ap X exp b X int et )
1136
{
1137
  int a = no(ap);
1138
  int  nob = no (b);
1139
  flt resval;
1140
  int status;
1141
  UNUSED (et);
1142
 
1143
  status = flt_mul (flptnos[a], flptnos[nob], &resval);
1144
  if (status == OKAY) {
1145
      flpt_round((int)f_to_nearest,
1146
		 flpt_bits((floating_variety)(name(sh(b))-shrealhd)),
1147
		 &resval);
1148
      flptnos[nob] = resval;
1149
      no(ap) = nob;
1150
    }
1151
  else
1152
    failer(ILLEGAL_FLMULT);
1153
  return;
1154
}
1155
 
1156
 
1157
 
1158
/* auxiliary function used for comm_ass by plus */
1159
static void plus_fn
1160
    PROTO_N ( (ap, b, et) )
1161
    PROTO_T ( exp ap X exp b X int et )
1162
{
1163
  flt64 x;
1164
  flpt fa, fb;
1165
  int sg = is_signed(sh(ap));
1166
  flt resval;
1167
  int ov;
1168
 
1169
  fa = f64_to_flt(exp_to_f64(ap), sg);
1170
  fb = f64_to_flt(exp_to_f64(b), sg);
1171
  IGNORE flt_add (flptnos[fa], flptnos[fb], &resval);
1172
		/* status cannot be wrong */
1173
  flptnos[fa] = resval;
1174
  x = flt_to_f64(fa, sg, &ov);
1175
 
1176
  if (et != f_wrap.err_code &&
1177
	(ov || constovf(b) || check_size(x, sg, shape_size(sh(ap)))))
1178
    setconstovf(ap);
1179
 
1180
/*  if (extra_checks && sg && !in_proc_def &&
1181
	(ov || (shape_size(sh(ap)) <= 32 && check_size(x, sg, 32)))) {
1182
    failer(ADD_OUT_OF_BOUNDS);
1183
    exit(EXIT_FAILURE);
1184
  };
1185
*/
1186
  flpt_ret(fa);
1187
  flpt_ret(fb);
1188
 
1189
  bigres(ap, &x);
1190
  return;
1191
}
1192
 
1193
/* subtract constant from constant */
1194
static void minus_fn
1195
    PROTO_N ( (ap, b, et) )
1196
    PROTO_T ( exp ap X exp b X int et )
1197
{
1198
  flt64 x;
1199
  flpt fa, fb;
1200
  int sg = is_signed(sh(ap));
1201
  flt resval;
1202
  int ov;
1203
 
1204
  fa = f64_to_flt(exp_to_f64(ap), sg);
1205
  fb = f64_to_flt(exp_to_f64(b), sg);
1206
  IGNORE flt_sub (flptnos[fa], flptnos[fb], &resval);
1207
		/* status cannot be wrong */
1208
  flptnos[fa] = resval;
1209
  x = flt_to_f64(fa, sg, &ov);
1210
 
1211
  if (et != f_wrap.err_code &&
1212
	(ov || constovf(b) || check_size(x, sg, shape_size(sh(ap)))))
1213
    setconstovf(ap);
1214
 
1215
/*  if (extra_checks && sg && !in_proc_def &&
1216
	(ov || (shape_size(sh(ap)) <= 32 && check_size(x, sg, 32)))) {
1217
    failer(ADD_OUT_OF_BOUNDS);
1218
    exit(EXIT_FAILURE);
1219
  };
1220
*/
1221
  flpt_ret(fa);
1222
  flpt_ret(fb);
1223
 
1224
  bigres(ap, &x);
1225
  return;
1226
}
1227
 
1228
/* negate a constant exp, b, producing int */
1229
static void  neg_fn
1230
    PROTO_N ( (b) )
1231
    PROTO_T ( exp b )
1232
{
1233
  flt64 x;
1234
  x = exp_to_f64(b);
1235
  x.big = ~x.big;
1236
  x.small = ~x.small;
1237
  if (x.small == (unsigned int)0xffffffff) {
1238
    ++x.big;
1239
  };
1240
  ++x.small;
1241
  bigres(b, &x);
1242
  return;
1243
}
1244
 
1245
/* negate a constant exp, b, producing int */
1246
static void  not_fn
1247
    PROTO_N ( (b) )
1248
    PROTO_T ( exp b )
1249
{
1250
  flt64 x;
1251
  x = exp_to_f64(b);
1252
  x.big = ~x.big;
1253
  x.small = ~x.small;
1254
  bigres(b, &x);
1255
  return;
1256
}
1257
 
1258
/* auxiliary function used for comm_ass by mult */
1259
static void mult_fn
1260
    PROTO_N ( (ap, b, et) )
1261
    PROTO_T ( exp ap X exp b X int et )
1262
{
1263
  flt64 x;
1264
  flpt fa, fb;
1265
  int sg = is_signed(sh(ap));
1266
  flt resval;
1267
  int ov;
1268
 
1269
  fa = f64_to_flt(exp_to_f64(ap), sg);
1270
  fb = f64_to_flt(exp_to_f64(b), sg);
1271
  IGNORE flt_mul (flptnos[fa], flptnos[fb], &resval);
1272
		/* status cannot be wrong */
1273
  flptnos[fa] = resval;
1274
  x = flt_to_f64(fa, sg, &ov);
1275
 
1276
  if (et != f_wrap.err_code &&
1277
	(ov || constovf(b) || check_size(x, sg, shape_size(sh(ap)))))
1278
    setconstovf(ap);
1279
 
1280
  if (sg && extra_checks &&
1281
	(ov || (shape_size(sh(ap)) <= 32 && check_size(x, sg, 32)))) {
1282
    failer(MULT_OUT_OF_BOUNDS);
1283
    exit(EXIT_FAILURE);
1284
  };
1285
 
1286
  flpt_ret(fa);
1287
  flpt_ret(fb);
1288
 
1289
  bigres(ap, &x);
1290
  return;
1291
}
1292
 
1293
/* auxiliary function used for comm_ass by and */
1294
static void and_fn
1295
    PROTO_N ( (ap, b, et) )
1296
    PROTO_T ( exp ap X exp b X int et )
1297
{
1298
  flt64 xa, xb;
1299
  UNUSED (et);
1300
  xa = exp_to_f64(ap);
1301
  xb = exp_to_f64(b);
1302
  xa.small &= xb.small;
1303
  xa.big &= xb.big;
1304
  bigres(ap, &xa);
1305
  return;
1306
}
1307
 
1308
/* auxiliary function used for comm_ass by or */
1309
static void or_fn
1310
    PROTO_N ( (ap, b, et) )
1311
    PROTO_T ( exp ap X exp b X int et )
1312
{
1313
  flt64 xa, xb;
1314
  UNUSED (et);
1315
  xa = exp_to_f64(ap);
1316
  xb = exp_to_f64(b);
1317
  xa.small |= xb.small;
1318
  xa.big |= xb.big;
1319
  bigres(ap, &xa);
1320
  return;
1321
}
1322
 
1323
/* auxiliary function used for comm_ass by xor */
1324
static void xor_fn
1325
    PROTO_N ( (ap, b, et) )
1326
    PROTO_T ( exp ap X exp b X int et )
1327
{
1328
  flt64 xa, xb;
1329
  UNUSED (et);
1330
  xa = exp_to_f64(ap);
1331
  xb = exp_to_f64(b);
1332
  xa.small ^= xb.small;
1333
  xa.big ^= xb.big;
1334
  bigres(ap, &xa);
1335
  return;
1336
}
1337
 
1338
/* not used for comm_ass */
1339
static void domaxmin
1340
    PROTO_N ( (ap, b, mx) )
1341
    PROTO_T ( exp ap X exp b X int mx )
1342
{
1343
  flt64 xa, xb;
1344
  int use_a;
1345
  xa = exp_to_f64(ap);
1346
  xb = exp_to_f64(b);
1347
  if (is_signed(sh(ap))) {
1348
    if (xa.big > xb.big)
1349
      use_a = mx;
1350
    if (xa.big < xb.big)
1351
      use_a = !mx;
1352
    if (xa.big == xb.big) {
1353
      if (xa.small >= xb.small)
1354
	use_a = mx;
1355
      else
1356
	use_a = !mx;
1357
    };
1358
  }
1359
  else {
1360
    if ((unsigned int)xa.big > (unsigned int)xb.big)
1361
      use_a = mx;
1362
    if ((unsigned int)xa.big < (unsigned int)xb.big)
1363
      use_a = !mx;
1364
    if (xa.big == xb.big) {
1365
      if (xa.small >= xb.small)
1366
	use_a = mx;
1367
      else
1368
	use_a = !mx;
1369
    };
1370
  };
1371
  SET(use_a);
1372
  if (use_a)
1373
    bigres(ap, &xa);
1374
  else
1375
    bigres(ap, &xb);
1376
  return;
1377
}
1378
 
1379
/* produce allones for integer length of shape of e. */
1380
static int  all_ones
1381
    PROTO_N ( (e) )
1382
    PROTO_T ( exp e )
1383
{
1384
  switch (shape_size(sh(e))) {
1385
    case 8:
1386
      return (0xff);
1387
    case 16:
1388
      return (0xffff);
1389
    default:
1390
      return (0xffffffff);
1391
  }
1392
}
1393
 
1394
/* obey div1 on constants */
1395
static void dodiv1
1396
    PROTO_N ( (ap, b) )
1397
    PROTO_T ( exp ap X exp b )
1398
{
1399
  flt64 x;
1400
  flpt fa, fb;
1401
  int sg = is_signed(sh(ap));
1402
  flt resval;
1403
  int ov;
1404
 
1405
  fa = f64_to_flt(exp_to_f64(ap), sg);
1406
  fb = f64_to_flt(exp_to_f64(b), sg);
1407
  IGNORE flt_div (flptnos[fa], flptnos[fb], &resval);
1408
		/* status cannot be wrong */
1409
  IGNORE flpt_round_to_integer((int)f_toward_smaller, &resval);
1410
  flptnos[fa] = resval;
1411
  x = flt_to_f64(fa, sg, &ov);
1412
 
1413
  flpt_ret(fa);
1414
  flpt_ret(fb);
1415
 
1416
  bigres(ap, &x);
1417
  return;
1418
}
1419
 
1420
/* obey div2 on constants */
1421
static void dodiv2
1422
    PROTO_N ( (ap, b) )
1423
    PROTO_T ( exp ap X exp b )
1424
{
1425
  flt64 x;
1426
  flpt fa, fb;
1427
  int sg = is_signed(sh(ap));
1428
  flt resval;
1429
  int ov;
1430
 
1431
  fa = f64_to_flt(exp_to_f64(ap), sg);
1432
  fb = f64_to_flt(exp_to_f64(b), sg);
1433
  IGNORE flt_div (flptnos[fa], flptnos[fb], &resval);
1434
		/* status cannot be wrong */
1435
 
1436
  IGNORE flpt_round_to_integer((int)f_toward_zero, &resval);
1437
 
1438
  flptnos[fa] = resval;
1439
  x = flt_to_f64(fa, sg, &ov);
1440
 
1441
  flpt_ret(fa);
1442
  flpt_ret(fb);
1443
 
1444
  bigres(ap, &x);
1445
  return;
1446
}
1447
 
1448
/* obey mod on constants */
1449
static void domod
1450
    PROTO_N ( (ap, b) )
1451
    PROTO_T ( exp ap X exp b )
1452
{
1453
  exp top = copy(ap);
1454
 
1455
  dodiv1(top, b);
1456
  mult_fn(b, top, f_wrap.err_code);
1457
  neg_fn(b);
1458
  plus_fn(ap, b, f_wrap.err_code);
1459
  return;
1460
}
1461
 
1462
/* obey rem2 on constants */
1463
static void dorem2
1464
    PROTO_N ( (ap, b) )
1465
    PROTO_T ( exp ap X exp b )
1466
{
1467
  exp top = copy(ap);
1468
 
1469
  dodiv2(top, b);
1470
  mult_fn(b, top, f_wrap.err_code);
1471
  neg_fn(b);
1472
  plus_fn(ap, b, f_wrap.err_code);
1473
  return;
1474
}
1475
 
1476
/* obey shift (places signed) on constants */
1477
static void  doshl
1478
    PROTO_N ( (e) )
1479
    PROTO_T ( exp e )
1480
{
1481
  flt64 x;
1482
  exp arg1 = son(e);
1483
  exp arg2 = bro(arg1);
1484
  int pl = no(arg2);
1485
  shape sha = sh(e);
1486
  int sg = is_signed(sha);
1487
 
1488
  sh(arg1) = sh(e);
1489
 
1490
  x = exp_to_f64(arg1);
1491
 
1492
  if (name(e) == shl_tag)  { /* shift left */
1493
    if (isbigval(arg2) || pl >= shape_size(sha)) {
1494
      no(arg1) = 0;
1495
      clearbigval(arg1);
1496
      return;
1497
    };
1498
    if (pl >= 32)  {
1499
      x.big = (int)(x.small << (pl-32));
1500
      x.small = 0;
1501
    }
1502
    else  {
1503
      x.big <<= pl;
1504
      x.big |= (int)(x.small >> (32-pl));
1505
      x.small <<= pl;
1506
    };
1507
  }
1508
  else  {  /* shift right */
1509
    if (isbigval(arg2) || pl >= shape_size(sha)) {
1510
      no(arg1) = 0;
1511
      if (sg) {
1512
	if (isbigval(arg1)) {
1513
	  if (flptnos[no(arg1)].sign == -1)
1514
	    no(arg1) = -1;
1515
	}
1516
	else
1517
	if (no(arg1) < 0)
1518
	  no(arg1) = -1;
1519
      };
1520
      clearbigval(arg1);
1521
      return;
1522
    };
1523
    if (pl >= 32) {
1524
      if (sg)  {
1525
	x.small = (unsigned int)(x.big >> (pl-32));
1526
	x.big = x.big >> 31;
1527
      }
1528
      else {
1529
	x.small = ((unsigned int)x.big) >> (pl-32);
1530
	x.big = 0;
1531
      };
1532
    }
1533
    else  {
1534
      if (sg)  {
1535
	x.small >>= pl;
1536
	x.small |= (unsigned int)(x.big << (32-pl));
1537
	x.big >>= pl;
1538
      }
1539
      else {
1540
	x.small >>= pl;
1541
	x.small |= (unsigned int)(x.big << (32-pl));
1542
	x.big = (int)(((unsigned int)x.big) >> pl);
1543
      };
1544
    };
1545
  };
1546
  bigres(arg1, &x);
1547
  return;
1548
}
1549
 
1550
 
1551
 
1552
 
1553
#if has_setcc
1554
 
1555
 /* included if target has a setcc operation, to set a bit from the
1556
    condition flags */
1557
 
1558
static exp absbool
1559
    PROTO_N ( (id) )
1560
    PROTO_T ( exp id )
1561
{
1562
				/* check if e  is (let a = 0 in
1563
				   cond(test(L)=result; a=1 | L:top); a )
1564
				   If so, return the test, otherwise
1565
				   nilexp. */
1566
  if (isvar (id) && name (son (id)) == val_tag && no (son (id)) == 0 &&
1567
	!isbigval(son(id))
1568
      && no (id) == 2) {
1569
	/* name initially 0 only used twice */
1570
    exp bdy = bro (son (id));
1571
    if (name (bdy) == seq_tag && name (bro (son (bdy))) == cont_tag &&
1572
	name (son (bro (son (bdy)))) == name_tag &&
1573
	son (son (bro (son (bdy)))) == id) {
1574
	/* one use is result  of sequence body */
1575
      exp c = son (son (bdy));
1576
#ifndef NEWDIAGS
1577
      if (name(c) == diagnose_tag)
1578
        c = son(c);
1579
#endif
1580
      if (last (c) && name (c) == cond_tag) {
1581
	/* seq is cond=c; id */
1582
	exp first = son (c);
1583
	exp second = bro (son (c));
1584
	if (no (son (second)) == 1 /* only one jump to else */ &&
1585
	    name (bro (son (second))) == top_tag
1586
	    && name (first) == seq_tag) {
1587
	  /* cond is (seq= first | L: top) */
1588
	  exp s = son (son (first));
1589
	  exp r = bro (son (first));
1590
	  if (name (r) == ass_tag && name (son (r)) == name_tag &&
1591
	      son (son (r)) == id && name (bro (son (r))) == val_tag &&
1592
		!isbigval(bro(son(r))) &&
1593
	      no (bro (son (r))) == 1 /* last of seq is id = 1 */ &&
1594
	      last (s) && name (s) == test_tag && pt (s) == second
1595
	  /* start of seq is int test jumping to second */
1596
	    )
1597
	    return s;
1598
	} /* cond is (seq= first | L: top) */
1599
      }; /* seq is cond=c; id */
1600
      if (last(c) && name(c) == condassign_tag) {
1601
	/* seq is condassign = c; id */
1602
	exp s = son (c);
1603
	exp r = bro (s);
1604
	if (name (son (r)) == name_tag &&
1605
		son (son (r)) == id && name (bro (son (r))) == val_tag &&
1606
		!isbigval(bro(son(r))) &&
1607
	      no (bro (son (r))) == 1 /* last of seq is id = 1 */)
1608
	  return s;
1609
      }; /* seq is condassign = c; id */
1610
    } /* one use is result  of sequence body */
1611
  } /* name initially 0 only used twice */
1612
  return nilexp;
1613
}
1614
#endif
1615
 
1616
 
1617
 /* distributes the operation e into a sequence, ie if e = op(seq(d ...;
1618
    c), a) produces seq(d...; op(c,a))  */
1619
static int seq_distr
1620
    PROTO_N ( (e, scope) )
1621
    PROTO_T ( exp e X exp scope )
1622
{
1623
  exp x = son(e);
1624
  exp y;
1625
  if (last(x) || (!last(x) && last(bro(x)))) {
1626
    if (name(x) == seq_tag || name(x) == ident_tag) {
1627
      exp b = bro(son(x));
1628
      exp r;
1629
      if (name(x) == ident_tag) { clearinlined(x); }
1630
      if (last(x))
1631
	r = me_u3(sh(e), copy(b), name(e));
1632
      else {
1633
#ifdef NEWDIAGS
1634
	if (diagnose)
1635
	  dg_restruct_code (x, bro(x), +1);
1636
#endif
1637
	r = me_b3(sh(e), copy(b), bro(x), name(e));
1638
      }
1639
      pt(r) = pt(e);
1640
      no(r) = no(e);
1641
      props(r) = props(e);
1642
      r = hold_check(r);
1643
      sh(x) = sh(e);
1644
      replace(b, r, r);		/* dgf preserved in copy */
1645
      kill_exp(b, b);
1646
#ifdef NEWDIAGS
1647
      if (diagnose)
1648
	dg_whole_comp (e, x);
1649
#endif
1650
      replace(e, x, scope);
1651
      return 1;
1652
    };
1653
  };
1654
  if (!last(x) && last(bro(x))) {
1655
    y = bro(x);
1656
    if (name(y) == seq_tag || name(y) == ident_tag) {
1657
      exp b = bro(son(y));
1658
      exp r;
1659
      if (name(y) == ident_tag) { clearinlined(y); }
1660
#ifdef NEWDIAGS
1661
      if (diagnose)
1662
	dg_restruct_code (y, x, -1);
1663
#endif
1664
      r = me_b3(sh(e), x, copy(b), name(e));
1665
      pt(r) = pt(e);
1666
      no(r) = no(e);
1667
      props(r) = props(e);
1668
      r = hold_check(r);
1669
      sh(y) = sh(e);
1670
      replace(b, r, r);		/* dgf preserved in copy */
1671
      kill_exp(b, b);
1672
#ifdef NEWDIAGS
1673
      if (diagnose)
1674
	dg_whole_comp (e, y);
1675
#endif
1676
      replace(e, y, scope);
1677
      return 1;
1678
    };
1679
  };
1680
  return 0;
1681
}
1682
 
1683
 /* reverses (ie. nots) test numbers */
1684
unsigned char  revtest[6] = {
1685
  4, 3, 2, 1, 6, 5
1686
};
1687
 
1688
 
1689
/* returns sign if |f|=1, otherwise 0 */
1690
static int  f_one
1691
    PROTO_N ( (f) )
1692
    PROTO_T ( flpt f )
1693
{
1694
  flt fconst;
1695
  fconst = flptnos[f];
1696
 
1697
  if (fconst.mant[0] == 1 && fconst.exp == 0) {
1698
    int   i = 1;
1699
    while (i < MANT_SIZE && fconst.mant[i] == 0)
1700
      ++i;
1701
    if (i == MANT_SIZE)
1702
      return (fconst.sign);
1703
    else
1704
      return (0);
1705
  }
1706
  else
1707
    return (0);
1708
}
1709
 
1710
 
1711
/* applies fneg */
1712
static  exp fneg
1713
    PROTO_N ( (e) )
1714
    PROTO_T ( exp e )
1715
{
1716
  exp n = getexp (sh (e), nilexp, 0, e, nilexp, 0, 0, fneg_tag);
1717
  setlast (e);
1718
  bro (e) = n;
1719
  return (n);
1720
}
1721
 
1722
 
1723
/* applies binary floating point operations */
1724
static  int check_fp2
1725
    PROTO_N ( (e, scope) )
1726
    PROTO_T ( exp e X exp scope )
1727
{
1728
  exp a1 = son (e);
1729
  exp a2 = bro (a1);
1730
  flpt f1, f2;
1731
  flt resval;
1732
  int   status;
1733
 
1734
  if (name (a1) == real_tag && name (a2) == real_tag) {
1735
    /* this will condense to a single constant */
1736
    f1 = no (a1);
1737
    f2 = no (a2);
1738
 
1739
    switch (name (e)) EXHAUSTIVE {
1740
 
1741
      case fplus_tag:
1742
	status = flt_add (flptnos[f1], flptnos[f2], &resval);
1743
	break;
1744
 
1745
      case fminus_tag:
1746
	status = flt_sub (flptnos[f1], flptnos[f2], &resval);
1747
	break;
1748
 
1749
      case fmult_tag:
1750
	status = flt_mul (flptnos[f1], flptnos[f2], &resval);
1751
	break;
1752
 
1753
      case fdiv_tag:
1754
	status = flt_div (flptnos[f1], flptnos[f2], &resval);
1755
	break;
1756
    }
1757
 
1758
    if (status == OKAY) {
1759
      flpt_round((int)f_to_nearest,
1760
		 flpt_bits((floating_variety)(name(sh(e)) - shrealhd)),
1761
		 &resval);
1762
      flptnos[f1] = resval;
1763
      flpt_ret (f2);
1764
      replace (e, a1, scope);
1765
      retcell (e);
1766
      retcell (a2);
1767
      return (1);
1768
    }
1769
    else
1770
      return (0);
1771
  }
1772
  else {			/* see if one arg is constant */
1773
    exp v_arg, c_arg;
1774
 
1775
    if (name (a1) == real_tag) {
1776
      f1 = no (a1);
1777
      c_arg = a1;
1778
      v_arg = a2;
1779
    }
1780
    else
1781
      if (name (a2) == real_tag) {
1782
	f1 = no (a2);
1783
	c_arg = a2;
1784
	v_arg = a1;
1785
      }
1786
      else
1787
	return (0);		/* no change possible */
1788
 
1789
    switch (name (e)) {
1790
 
1791
      case fplus_tag:
1792
	if (flptnos[f1].sign == 0) {
1793
	  /*  x+0  or  0+x  */
1794
	  flpt_ret (f1);
1795
	  replace (e, v_arg, scope);
1796
	  retcell (e);
1797
	  retcell (c_arg);
1798
	  return (1);
1799
	}
1800
	else
1801
	  return (0);
1802
 
1803
      case fminus_tag:
1804
	if (flptnos[f1].sign == 0) {
1805
	  /*  x-0  or  0-x  */
1806
	  flpt_ret (f1);
1807
	  if (v_arg == a2) {
1808
	    /*  0-x = -x  */
1809
	    v_arg = fneg (v_arg);
1810
	  }
1811
	  replace (e, v_arg, scope);
1812
	  retcell (e);
1813
	  retcell (c_arg);
1814
	  return (1);
1815
	}
1816
	else
1817
	  return (0);
1818
 
1819
      case fmult_tag:
1820
	if (flptnos[f1].sign == 0) {
1821
	  /*  x*0  or  0*x  */
1822
	  replace (e, c_arg, scope);
1823
	  retcell (e);
1824
	  kill_exp (v_arg, scope);
1825
	  return (1);
1826
	}
1827
	else {
1828
	  int   u = f_one (f1);
1829
	  if (u == 0)
1830
	    return (0);
1831
	  /*  x*1  or x*(-1)  or  1*x  or (-1)*x  */
1832
	  if (u == -1)
1833
	    v_arg = fneg (v_arg);
1834
	  flpt_ret (f1);
1835
	  replace (e, v_arg, scope);
1836
	  retcell (e);
1837
	  retcell (c_arg);
1838
	  return (1);
1839
	}
1840
 
1841
      case fdiv_tag:
1842
	if (flptnos[f1].sign == 0 && v_arg == a2) {
1843
	  /*  0/x  */
1844
	  replace (e, c_arg, scope);
1845
	  retcell (e);
1846
	  kill_exp (v_arg, scope);
1847
	  return (1);
1848
	}
1849
	else {
1850
	  int   u = f_one (f1);
1851
	  if (u == 0 || v_arg == a2)
1852
	    return (0);
1853
	  /*  x/1  or x/(-1)  */
1854
	  if (u == -1)
1855
	    v_arg = fneg (v_arg);
1856
	  flpt_ret (f1);
1857
	  replace (e, v_arg, scope);
1858
	  retcell (e);
1859
	  retcell (c_arg);
1860
	  return (1);
1861
	}
1862
    }
1863
  };
1864
  return (0);
1865
}
1866
 
1867
/* compares integer constants using the test given by test_no */
1868
static int docmp
1869
    PROTO_N ( (sha, test_no, c1, c2) )
1870
    PROTO_T ( shape sha X unsigned char test_no X int c1 X int c2 )
1871
{
1872
  int c;
1873
  switch (shape_size(sha)) EXHAUSTIVE {
1874
    case 8:
1875
     if (is_signed(sha))
1876
      {
1877
	int   d1 = (c1 & 0x80) ? (c1 | ~0x7f) : (c1 & 0xff);
1878
	int   d2 = (c2 & 0x80) ? (c2 | ~0x7f) : (c2 & 0xff);
1879
	switch (test_no) EXHAUSTIVE {
1880
	  case 1:
1881
	    c = (d1 > d2);
1882
	    break;
1883
	  case 2:
1884
	    c = (d1 >= d2);
1885
	    break;
1886
	  case 3:
1887
	    c = (d1 < d2);
1888
	    break;
1889
	  case 4:
1890
	    c = (d1 <= d2);
1891
	    break;
1892
	  case 5:
1893
	    c = (d1 == d2);
1894
	    break;
1895
	  case 6:
1896
	    c = (d1 != d2);
1897
	    break;
1898
	};
1899
	break;
1900
      }
1901
      else
1902
      {
1903
	unsigned char d1 = (unsigned char)(c1 & 0xff);
1904
	unsigned char d2 = (unsigned char)(c2 & 0xff);
1905
	switch (test_no) EXHAUSTIVE {
1906
	  case 1:
1907
	    c = (d1 > d2);
1908
	    break;
1909
	  case 2:
1910
	    c = (d1 >= d2);
1911
	    break;
1912
	  case 3:
1913
	    c = (d1 < d2);
1914
	    break;
1915
	  case 4:
1916
	    c = (d1 <= d2);
1917
	    break;
1918
	  case 5:
1919
	    c = (d1 == d2);
1920
	    break;
1921
	  case 6:
1922
	    c = (d1 != d2);
1923
	    break;
1924
	};
1925
	break;
1926
      };
1927
    case 16:
1928
     if (is_signed(sha))
1929
      {
1930
	int   d1 = (c1 & 0x8000) ? (c1 | ~0x7fff) : (c1 & 0xffff);
1931
	int   d2 = (c2 & 0x8000) ? (c2 | ~0x7fff) : (c2 & 0xffff);
1932
	switch (test_no) EXHAUSTIVE {
1933
	  case 1:
1934
	    c = (d1 > d2);
1935
	    break;
1936
	  case 2:
1937
	    c = (d1 >= d2);
1938
	    break;
1939
	  case 3:
1940
	    c = (d1 < d2);
1941
	    break;
1942
	  case 4:
1943
	    c = (d1 <= d2);
1944
	    break;
1945
	  case 5:
1946
	    c = (d1 == d2);
1947
	    break;
1948
	  case 6:
1949
	    c = (d1 != d2);
1950
	    break;
1951
	};
1952
	break;
1953
      }
1954
     else
1955
      {
1956
	unsigned short  d1 = (unsigned short)(c1 & 0xffff);
1957
	unsigned short  d2 = (unsigned short)(c2 & 0xffff);
1958
	switch (test_no) EXHAUSTIVE {
1959
	  case 1:
1960
	    c = (d1 > d2);
1961
	    break;
1962
	  case 2:
1963
	    c = (d1 >= d2);
1964
	    break;
1965
	  case 3:
1966
	    c = (d1 < d2);
1967
	    break;
1968
	  case 4:
1969
	    c = (d1 <= d2);
1970
	    break;
1971
	  case 5:
1972
	    c = (d1 == d2);
1973
	    break;
1974
	  case 6:
1975
	    c = (d1 != d2);
1976
	    break;
1977
	};
1978
	break;
1979
      };
1980
    case 32:
1981
     if (is_signed(sha))
1982
      {
1983
	int  d1 = c1;
1984
	int  d2 = c2;
1985
	switch (test_no) EXHAUSTIVE {
1986
	  case 1:
1987
	    c = (d1 > d2);
1988
	    break;
1989
	  case 2:
1990
	    c = (d1 >= d2);
1991
	    break;
1992
	  case 3:
1993
	    c = (d1 < d2);
1994
	    break;
1995
	  case 4:
1996
	    c = (d1 <= d2);
1997
	    break;
1998
	  case 5:
1999
	    c = (d1 == d2);
2000
	    break;
2001
	  case 6:
2002
	    c = (d1 != d2);
2003
	    break;
2004
	};
2005
	break;
2006
      }
2007
     else
2008
      {
2009
	unsigned int d1 = (unsigned int)c1;
2010
	unsigned int d2 = (unsigned int)c2;
2011
	switch (test_no) EXHAUSTIVE {
2012
	  case 1:
2013
	    c = (d1 > d2);
2014
	    break;
2015
	  case 2:
2016
	    c = (d1 >= d2);
2017
	    break;
2018
	  case 3:
2019
	    c = (d1 < d2);
2020
	    break;
2021
	  case 4:
2022
	    c = (d1 <= d2);
2023
	    break;
2024
	  case 5:
2025
	    c = (d1 == d2);
2026
	    break;
2027
	  case 6:
2028
	    c = (d1 != d2);
2029
	    break;
2030
	};
2031
	break;
2032
      };
2033
  };
2034
  return (c);
2035
}
2036
 
2037
 
2038
int docmp_f
2039
    PROTO_N ( (test_no, a, b) )
2040
    PROTO_T ( int test_no X exp a X exp b )
2041
{
2042
  shape sha = sh(a);
2043
  flt64 xa, xb;
2044
  int sg = is_signed(sha);
2045
  int eq = 0;
2046
  int less = 0;
2047
  int gr = 0;
2048
  int c;
2049
 
2050
  if (shape_size(sh(a)) <= 32)
2051
    return docmp(sha, (unsigned char)test_no, no(a), no(b));
2052
 
2053
  xa = exp_to_f64(a);
2054
  xb = exp_to_f64(b);
2055
 
2056
  if (xa.big == xb.big && xa.small == xb.small)
2057
    eq = 1;
2058
 
2059
  if (sg && !eq) {
2060
    if (xa.big < xb.big)
2061
      less = 1;
2062
    else
2063
    if (xa.big > xb.big)
2064
      gr = 1;
2065
    else {
2066
      if (xa.small < xb.small)
2067
	less = 1;
2068
      else
2069
	gr = 1;
2070
    };
2071
  }
2072
  else
2073
  if (!eq) {
2074
    if ((unsigned int)xa.big < (unsigned int)xb.big)
2075
      less = 1;
2076
    else
2077
    if ((unsigned int)xa.big > (unsigned int)xb.big)
2078
      gr = 1;
2079
    else {
2080
      if (xa.small < xb.small)
2081
	less = 1;
2082
      else
2083
	gr = 1;
2084
    };
2085
  };
2086
 
2087
  switch (test_no) EXHAUSTIVE {
2088
	  case 1:
2089
	    c = gr;
2090
	    break;
2091
	  case 2:
2092
	    c = gr | eq;
2093
	    break;
2094
	  case 3:
2095
	    c = less;
2096
	    break;
2097
	  case 4:
2098
	    c = less | eq;
2099
	    break;
2100
	  case 5:
2101
	    c = eq;
2102
	    break;
2103
	  case 6:
2104
	    c = !eq;
2105
	    break;
2106
  };
2107
  return c;
2108
}
2109
 
2110
 
2111
/* main bottom-to-top optimise routine
2112
   Optimises e. No change propagates
2113
   outside scope */
2114
int check
2115
    PROTO_N ( (e, scope) )
2116
    PROTO_T ( exp e X exp scope )
2117
{
2118
  if (is_a (name (e))) {/* main op non-side effect */
2119
    unsigned char n = name(e);
2120
    if (son(e) != nilexp && n != name_tag && n != env_offset_tag &&
2121
	n != general_env_offset_tag &&
2122
	n != proc_tag && n != general_proc_tag) {
2123
      exp temp = son(e);
2124
      while (1) {
2125
        if (name(sh(temp)) == bothd) {
2126
		/* unordered; temp can be first, iwc all siblings unreachable */
2127
#ifdef NEWDIAGS
2128
	  if (diagnose) {
2129
	    exp sib = son(e);
2130
	    for (;;) {
2131
	      if (sib != temp)
2132
		dg_dead_code (sib, temp);
2133
	      if (last(sib))
2134
		break;
2135
	      sib = bro(sib);
2136
	    }
2137
	    dg_whole_comp (e, temp);
2138
	  }
2139
#endif
2140
	  replace(e, temp, scope);
2141
	  retcell(e);
2142
	  return 1;
2143
        };
2144
        if (last(temp))
2145
	  break;
2146
        temp = bro(temp);
2147
      }
2148
    }
2149
 
2150
    switch (name (e)) {
2151
      case component_tag:
2152
        {
2153
          exp v = son(e);
2154
          exp a = bro(v);
2155
 
2156
          if (name(a) == val_tag)
2157
            {
2158
             exp res;
2159
             if (no(a) == 0 && shape_size(sh(v)) == shape_size(sh(e))
2160
#if dont_unpad_apply
2161
                     && name(v) != apply_tag
2162
#endif
2163
                            ) { /* remove the operation if the offset
2164
                                     is zero and the size is the same.
2165
                                     This typically happens in selecting
2166
                                     from a union if the component has
2167
                                     the maximum size in the union */
2168
                 sh(v) = sh(e);
2169
#ifdef NEWDIAGS
2170
		 if (diagnose)
2171
		   dg_whole_comp (e, v);
2172
#endif
2173
                 replace(e, v, scope);
2174
                 retcell(a);
2175
                 retcell(e);
2176
                 return 1;
2177
               };
2178
 
2179
                  /* otherwise use field_tag */
2180
 
2181
             res = getexp(sh(e), nilexp, 0, v, nilexp,
2182
                               0, no(a), field_tag);
2183
             setfather(res, son(res));
2184
#ifdef NEWDIAGS
2185
	     dgf(res) = dgf(e);
2186
#endif
2187
             replace(e, hold_check(res), scope);
2188
             retcell(e);
2189
             retcell(a);
2190
             return 1;
2191
            };
2192
          if (name(v) == cont_tag) /* replace selecting from contents
2193
                                      by taking contents of reff selection
2194
                                   */
2195
            {
2196
              exp ap = hold_check(f_add_to_ptr(son(v), a));
2197
              ap = hold_check(f_contents(sh(e), ap));
2198
#ifdef NEWDIAGS
2199
	      if (diagnose) {
2200
		dg_whole_comp (v, ap);
2201
		dg_whole_comp (e, ap);
2202
	      }
2203
#endif
2204
              replace(e, ap, scope);
2205
              retcell(v);
2206
              retcell(e);
2207
              return 1;
2208
            };
2209
          {  /* always  remove component_tag: use a declaration */
2210
            exp var = me_startid(sh(e), v, 1);
2211
            exp ap, c;
2212
            exp ob;
2213
            ob = me_obtain(var);
2214
            ap = hold_check(f_add_to_ptr(ob, a));
2215
            c = hold_check(f_contents(sh(e), ap));
2216
            var = me_complete_id(var, c);
2217
#ifdef NEWDIAGS
2218
	    if (diagnose)
2219
	      dg_whole_comp (e, var);
2220
#endif
2221
            replace(e, var, scope);
2222
            retcell(e);
2223
            return 1;
2224
          };
2225
        };
2226
      case offset_pad_tag:
2227
        if (name(son(e)) == val_tag && !isbigval(son(e)))
2228
          {
2229
                /* constant evaluation */
2230
            int al = al2(sh(e));
2231
	    if (al == 0)
2232
	      al = 1;
2233
	    if (al2_of(sh(e))->al.sh_hd > nofhd)
2234
			al = shape_align(f_pointer(al2_of(sh(e))));
2235
#if ishppa
2236
	    if ((al1_of(sh(e))->al.al_val.al_frame & 4)!=0) {
2237
		no(son(e)) = -rounder(-no(son(e)),al);
2238
	    }
2239
	    else
2240
 
2241
#endif
2242
            no(son(e)) = rounder(no(son(e)), al);
2243
            sh(son(e)) = sh(e);
2244
#ifdef NEWDIAGS
2245
	    if (diagnose)
2246
	      dg_whole_comp (e, son(e));
2247
#endif
2248
            replace(e, son(e), scope);
2249
            retcell(e);
2250
            return 1;
2251
          };
2252
        return 0;
2253
      case offset_add_tag:
2254
	{
2255
 
2256
	  if (name (son (e)) == val_tag &&
2257
	      name (bro (son (e))) == val_tag &&
2258
		!isbigval(son(e)) && !isbigval(bro(son(e)))) {
2259
	    /* both arguments constant */
2260
            int n;
2261
            exp a = son(e);
2262
            exp b = bro(a);
2263
 
2264
            n = no(a) + no(b);
2265
 
2266
	    no (a) = n;
2267
	    sh (a) = sh (e);
2268
	    retcell (b);
2269
	    replace (e, a, scope);
2270
	    retcell (e);
2271
	    return (1);
2272
	  };
2273
	  return 0;
2274
        };
2275
      case offset_subtract_tag:
2276
	{
2277
	  if (name (son (e)) == val_tag &&
2278
	      name (bro (son (e))) == val_tag &&
2279
		!isbigval(son(e)) && !isbigval(bro(son(e)))) {
2280
	    /* both arguments constant */
2281
	    no (son (e)) -= no(bro(son(e)));
2282
	    sh (son (e)) = sh (e);
2283
	    retcell (bro (son (e)));
2284
	    replace (e, son (e), scope);
2285
	    retcell (e);
2286
	    return (1);
2287
	  };
2288
	  return 0;
2289
	};
2290
      case offset_negate_tag:
2291
	{
2292
	  if (name (son (e)) == val_tag && !isbigval(son(e))) {
2293
	    /* argument constant */
2294
	    no (son (e)) = - no(son(e));
2295
	    sh (son (e)) = sh (e);
2296
#ifdef NEWDIAGS
2297
	    if (diagnose)
2298
	      dg_whole_comp (e, son(e));
2299
#endif
2300
	    replace (e, son (e), scope);
2301
	    retcell (e);
2302
	    return (1);
2303
	  };
2304
	  return 0;
2305
	};
2306
      case offset_max_tag:
2307
	{
2308
	  if (name (son (e)) == val_tag &&
2309
	      name (bro (son (e))) == val_tag &&
2310
		!isbigval(son(e)) && !isbigval(bro(son(e)))) {
2311
	    /* both arguments constant */
2312
            int n1 = no(son(e));
2313
            int n2 = no(bro(son(e)));
2314
	    no (son (e)) = (n1 > n2) ? n1 : n2;
2315
	    sh (son (e)) = sh (e);
2316
	    retcell (bro (son (e)));
2317
	    replace (e, son (e), scope);
2318
	    retcell (e);
2319
	    return (1);
2320
	  };
2321
	  return 0;
2322
	};
2323
      case offset_mult_tag:
2324
	{
2325
	  if (name (son (e)) == val_tag &&
2326
	      name (bro (son (e))) == val_tag &&
2327
		!isbigval(son(e)) && !isbigval(bro(son(e)))) {
2328
	    /* both arguments constant */
2329
            int n1 = no(son(e));
2330
            int n2 = no(bro(son(e)));
2331
	    no (son (e)) = n1 * n2;
2332
	    sh (son (e)) = sh (e);
2333
	    retcell (bro (son (e)));
2334
	    replace (e, son (e), scope);
2335
	    retcell (e);
2336
	    return (1);
2337
	  };
2338
          if (name(son(e)) == val_tag && !isbigval(son(e))&&
2339
		 no(son(e)) == 1)
2340
            {  /* multiply by 1 */
2341
              sh(bro(son(e))) = sh(e);
2342
              replace(e, bro(son(e)), scope);
2343
              retcell(e);
2344
              return (1);
2345
            };
2346
          if (name(son(e)) == val_tag && !isbigval(son(e)) &&					no(son(e)) == 0)
2347
            {  /* multiply by 0 - replace by sequence - side-effects!*/
2348
	      exp_list el;
2349
	      el.start = bro(son(e));
2350
	      el.end = bro(son(e));
2351
	      el.number = 1;
2352
              sh(son(e)) = sh(e);
2353
              replace(e, f_sequence(el, son(e)), scope);
2354
              retcell(e);
2355
              return (1);
2356
            };
2357
 
2358
          if (name(bro(son(e))) == val_tag &&
2359
               name(son(e)) == plus_tag)
2360
            {  /* distribute offset_mult over plus (giving
2361
                  offset_adds) */
2362
              exp pl = son(e);  /* the plus operation */
2363
              exp b = bro(pl);  /* the offset constant */
2364
              exp x = son(pl);  /* the first plus operand */
2365
	      exp bx = bro(x);
2366
              exp res = hold_check(me_b3(sh(e), x, copy(b),
2367
					 offset_mult_tag));
2368
	      exp temp;
2369
	      while (bx != pl) {
2370
		x = bx;
2371
	        bx = bro(x);
2372
		temp = hold_check(me_b3(sh(e), x, copy(b),
2373
					 offset_mult_tag));
2374
		res = hold_check(me_b3(sh(e), res, temp, offset_add_tag));
2375
	      };
2376
	      retcell(b);
2377
              replace(e, res, scope);
2378
              retcell(e);
2379
              return 1;
2380
            };
2381
	  return 0;
2382
	};
2383
      case offset_div_by_int_tag:
2384
      case offset_div_tag:
2385
	{
2386
	  if (name (son (e)) == val_tag &&
2387
	      name (bro (son (e))) == val_tag &&
2388
		!isbigval(son(e)) && !isbigval(bro(son(e)))) {
2389
	    /* both arguments constant */
2390
            int n1 = no(son(e));
2391
            int n2 = no(bro(son(e)));
2392
	    no (son (e)) = n1 / n2;
2393
	    sh (son (e)) = sh (e);
2394
	    retcell (bro (son (e)));
2395
	    replace (e, son (e), scope);
2396
	    retcell (e);
2397
	    return (1);
2398
	  };
2399
	  return 0;
2400
	};
2401
#if has_setcc
2402
      case absbool_tag:
2403
	{
2404
	  exp arg1 = son(e);
2405
	  exp arg2 = bro(arg1);
2406
	  ntest nt = test_number(e);
2407
	  if ((name (arg1) == val_tag || name (arg1) == null_tag) &&
2408
	      (name (arg2) == val_tag ||
2409
		name (arg2) == null_tag)) {
2410
	    /* argument constant */
2411
	    no (arg1) = docmp_f ((int)nt, arg1, arg2);
2412
	    setname (arg1, val_tag);
2413
	    sh (arg1) = sh (e);
2414
	    clearbigval(arg1);
2415
	    retcell (arg2);
2416
	    replace (e, arg1, scope);
2417
	    retcell (e);
2418
	    return (1);
2419
	  };
2420
	  if (name(arg1) == val_tag || name(arg1) == real_tag ||
2421
		name(arg1) == null_tag) {
2422
		/* constant argument always second */
2423
	    son(e) = arg2;
2424
	    bro(arg2) = arg1;
2425
	    bro(arg1) = e;
2426
	    setlast(arg1);
2427
	    clearlast(arg2);
2428
	    nt = exchange_ntest[nt];
2429
	    settest_number(e, nt);
2430
	  };
2431
	  return 0;
2432
	};
2433
#endif
2434
      case plus_tag: 		/* apply commutative and associative laws
2435
				*/
2436
#if is80x86
2437
	{
2438
	  exp arg1 = son(e);
2439
	  exp arg2 = bro(arg1);
2440
	  if (!optop(e))
2441
	    return 0;
2442
	  if (name(arg1) == val_tag && name(arg2) == val_tag)
2443
	    {
2444
	      plus_fn(arg1, arg2, errhandle(e));
2445
	      sh(arg1) = sh(e);
2446
#ifdef NEWDIAGS
2447
	      if (diagnose) {
2448
		if (dgf(arg1))
2449
		  dg_detach_const (arg1, e);
2450
		if (dgf(arg2))
2451
		  dg_detach_const (arg2, e);
2452
		dgf(arg1) = dgf(e);
2453
	      }
2454
#endif
2455
	      replace(e, arg1, scope);
2456
	      retcell(e);
2457
	      return 1;
2458
	    };
2459
	  if (name(arg1) == val_tag)
2460
	    {
2461
	      exp q = hold_check(f_plus(f_impossible, arg2, arg1));
2462
#ifdef NEWDIAGS
2463
	      if (diagnose)
2464
		dg_whole_comp (e, q);
2465
#endif
2466
	      replace(e, q, scope);
2467
	      retcell(e);
2468
	      return 1;
2469
	    };
2470
	  if (name(arg2) == plus_tag && name(bro(son(arg2))) == val_tag &&
2471
		optop(arg2))
2472
	    {
2473
	      exp con = bro(son(arg2));
2474
	      exp x = hold_check(f_plus(f_impossible,
2475
				      hold_check(f_plus(f_impossible, arg1,
2476
						   son(arg2))),
2477
				      con));
2478
#ifdef NEWDIAGS
2479
	      if (diagnose)
2480
		dg_whole_comp (e, x);
2481
#endif
2482
	      replace(e, x, scope);
2483
	      retcell(e);
2484
	      return 1;
2485
	    };
2486
	  if (name(arg1) == plus_tag && name(bro(son(arg1))) == val_tag &&
2487
		optop(arg1))
2488
	    {
2489
	      exp x = hold_check(f_plus(f_impossible,
2490
					son(arg1),
2491
					hold_check(f_plus(f_impossible,
2492
							  arg2,
2493
						       bro(son(arg1))))));
2494
#ifdef NEWDIAGS
2495
	      if (diagnose)
2496
		dg_whole_comp (e, x);
2497
#endif
2498
	      replace(e, x, scope);
2499
	      retcell(e);
2500
	      return 1;
2501
	    };
2502
	  if (name(arg2) == plus_tag && name(arg1) != plus_tag &&
2503
		optop(arg2))
2504
	    {
2505
	      exp t = bro(son(arg2));
2506
	      exp x = hold_check(f_plus(f_impossible,
2507
				hold_check(f_plus(f_impossible, arg1,
2508
						  son(arg2))),
2509
				t));
2510
#ifdef NEWDIAGS
2511
	      if (diagnose)
2512
		dg_whole_comp (e, x);
2513
#endif
2514
	      replace(e, x, scope);
2515
	      retcell(e);
2516
	      return 1;
2517
	    };
2518
 
2519
	  return seq_distr(e, scope);
2520
	};
2521
#else
2522
	return (comm_ass (e, plus_tag, plus_fn,
2523
	      0, 0, 0, scope, 1, 0));
2524
#endif
2525
      case fplus_tag: 		/* apply zero, unit and constant
2526
                                   evaluation.
2527
                                   NB dive MUST be false, because
2528
                                   floating point is not really
2529
                                   commutative and associative
2530
				*/
2531
	return (comm_ass (e, fplus_tag, fplus_fn,
2532
	      fzero_no, 0, 0, scope, 0, 1));
2533
      case addptr_tag:
2534
	{
2535
	  if ((name (son (e)) == null_tag ||
2536
	       name (son (e)) == val_tag) && !isbigval(son(e)) &&
2537
		no (son (e)) == 0) {
2538
	    if (name (bro (son (e))) == val_tag &&
2539
		!isbigval(bro(son(e))) &&
2540
                al2(sh(bro(son(e)))) > 1) { /* constant evaluation */
2541
	      sh (bro (son (e))) = sh (e);
2542
	      no (bro (son (e))) /= 8;
2543
#ifdef NEWDIAGS
2544
	      if (diagnose)
2545
		dg_whole_comp (e, bro(son(e)));
2546
#endif
2547
	      replace (e, bro (son (e)), scope);
2548
	      retcell (son (e));
2549
	      retcell (e);
2550
	      return (1);
2551
	    };
2552
	  };
2553
#if isAlpha
2554
	{ exp ptr = son(e);
2555
	  exp off = bro(ptr);
2556
	  if ((al1_of(sh(off))->al.al_val.al_frame & 4) != 0 &&
2557
		!is_floating(al2_of(sh(off))->al.sh_hd)) {
2558
		exp r = getexp (sh(ptr), off, 0, ptr, nilexp,
2559
				0, 6*64, reff_tag);
2560
		sh(off) = f_offset(al1_of(sh(off)), long_to_al(al2(sh(off))));
2561
		bro(ptr)=r; setlast(ptr);
2562
		son(e) = r;
2563
	  }
2564
	}
2565
 
2566
#endif
2567
	  if (name (bro (son (e))) == val_tag &&
2568
		 !isbigval(bro (son (e)))) {
2569
	    /* replace addptr(x, const) by refffield operation */
2570
	    exp p = son (e);
2571
	    int  k = no (bro (p));
2572
	    exp r;
2573
	    r = getexp (sh (e), nilexp, 0, p, nilexp,
2574
		0, k, reff_tag);
2575
#ifdef NEWDIAGS
2576
	    dgf(r) = dgf(e);
2577
#endif
2578
	    replace (e, hc (r, p), scope);
2579
	    retcell (e);
2580
	    return (1);
2581
	  };
2582
	  if (name (son (e)) == reff_tag &&
2583
                shape_size(sh(e)) == 32) {
2584
	    /* replace addptr(reff[n](a), b) by reff[n](addptr(a, b)) */
2585
	    exp p = son (son (e));
2586
	    exp a = bro (son (e));
2587
	    exp ap1 = getexp (sh (e), nilexp, 0, p, nilexp,
2588
		0, 0, addptr_tag);
2589
	    exp ap, r;
2590
	    bro (p) = a;
2591
	    clearlast (p);
2592
#if NEWDIAGS
2593
	    if (diagnose)
2594
	      dg_whole_comp (son(e), p);
2595
#endif
2596
	    ap = hc (ap1, a);
2597
	    r = hc (getexp (sh (e), nilexp, 0, ap, nilexp,
2598
			0, no (son (e)), reff_tag),
2599
		   ap);
2600
#if NEWDIAGS
2601
	    if (diagnose)
2602
	      dg_whole_comp (e, r);
2603
#endif
2604
	    replace (e, r, scope);
2605
	    retcell (son (e));
2606
	    retcell (e);
2607
	    return (1);
2608
	  };
2609
          if (name(bro(son(e))) == offset_add_tag)
2610
           {
2611
             exp p = son(e);
2612
             exp a = son(bro(p));
2613
             exp c = bro(a);
2614
             if (name(c) == val_tag && !isbigval(c)) {
2615
               exp ap =
2616
                 hold_check(me_b3(f_pointer(long_to_al(al2(sh(a)))),
2617
                                   p, a, addptr_tag));
2618
               exp r = getexp(sh(e), nilexp, 0, ap, nilexp, 0,
2619
                             no(c), reff_tag);
2620
               setfather(r, ap);
2621
#ifdef NEWDIAGS
2622
	       dgf(r) = dgf(e);
2623
#endif
2624
               replace(e, hold_check(r), scope);
2625
               retcell(e);
2626
               return 1;
2627
	     };
2628
	     if (al1(sh(p)) == al2(sh(c)))  {
2629
	       exp inner, outer;
2630
	       inner = hold_check(me_b3(sh(e), p, a, addptr_tag));
2631
#ifdef NEWDIAGS
2632
	       if (diagnose)
2633
		 dg_whole_comp (bro(p), inner);
2634
#endif
2635
	       outer = hold_check(me_b3(sh(e), inner, c, addptr_tag));
2636
#ifdef NEWDIAGS
2637
	       if (diagnose)
2638
		 dg_whole_comp (e, outer);
2639
			/* also represent movement of c !!!!!!!!!!!!!!!!!!!!!!!!! */
2640
#endif
2641
	       replace(e, outer, scope);
2642
	       retcell(e);
2643
	       return 1;
2644
	     };
2645
           };
2646
	  return 0;
2647
	};
2648
      case chvar_tag: {
2649
#ifdef value_of_null
2650
	  if (name(son(e))==null_tag) {
2651
	    setname(son(e), val_tag);
2652
	    no(son(e))= value_of_null;
2653
	    clearbigval(son(e));
2654
	    sh (son (e)) = sh(e);
2655
#ifdef NEWDIAGS
2656
 	    if (diagnose)
2657
	      dg_whole_comp (e, son(e));
2658
#endif
2659
	    replace (e, son (e), scope);
2660
	    retcell (e);
2661
	    return (1);
2662
	  };
2663
#endif
2664
	  if (name (son (e)) == val_tag && optop(e)) {
2665
	    /* evaluate chvar(const) */
2666
	    int bg;
2667
	    flt64 x;
2668
	    shape sha = sh(e);
2669
	    x = exp_to_f64(son(e));
2670
/*
2671
#if has64bits
2672
  int sg = is_signed(sha);
2673
  if (extra_checks && sg && !in_proc_def &&
2674
	shape_size(sha) <= 32 && check_size(x, sg, 32)) {
2675
    failer("Change_variety out of range");
2676
    exit(EXIT_FAILURE);
2677
  };
2678
#endif
2679
*/
2680
	    dochvar_f (&x, sha);
2681
	    no(son(e)) = f64_to_flpt(x, is_signed(sha), &bg,
2682
					 shape_size(sha));
2683
	    if (bg)
2684
	      setbigval(son(e));
2685
	    else
2686
	      clearbigval(son(e));
2687
	    sh (son (e)) = sha;
2688
#ifdef NEWDIAGS
2689
 	    if (diagnose)
2690
	      dg_whole_comp (e, son(e));
2691
#endif
2692
	    replace (e, son (e), scope);
2693
	    retcell (e);
2694
	    return (1);
2695
	  };
2696
	  if (eq_shape (sh (e),  sh (son (e)))) {
2697
	    /* replace identity chvar by argument */
2698
#ifdef NEWDIAGS
2699
 	    if (diagnose)
2700
	      dg_whole_comp (e, son(e));
2701
#endif
2702
	    replace (e, son (e), scope);
2703
	    retcell (e);
2704
	    return (1);
2705
	  };
2706
	  if (name(son(e)) == chvar_tag &&
2707
		 shape_size(sh(e)) == shape_size(sh(son(son(e)))) &&
2708
		 name(sh(son(e))) == bitfhd) {
2709
	    exp res = hold_check(me_u3(sh(e), son(son(e)), chvar_tag));
2710
	    replace(e, res, scope);
2711
	    retcell(e);
2712
	    return 1;
2713
	  };
2714
	  if (name(son(e)) == chvar_tag && !is_signed(sh(e)) &&
2715
		shape_size(sh(e)) == shape_size(sh(son(e)))) {
2716
	    replace(e, hold_check(me_u3(sh(e), son(son(e)), chvar_tag)),
2717
			scope);
2718
	    retcell(e);
2719
	    return 1;
2720
	  };
2721
	  if (name(son(e)) == chvar_tag && !is_signed(sh(e)) &&
2722
		shape_size(sh(e)) < shape_size(sh(son(e))) &&
2723
		shape_size(sh(e)) == shape_size(sh(son(son(e))))) {
2724
	    replace(e, hold_check(me_u3(sh(e), son(son(e)), chvar_tag)),
2725
			scope);
2726
	    retcell(e);
2727
	    return 1;
2728
	  };
2729
#if little_end & has_byte_regs
2730
	  /* only for little enders which have byte registers */
2731
	  if ((shape_size(sh(e)) <= shape_size(sh(son(e)))) && optop(e) &&
2732
	      (name (son (e)) == name_tag ||
2733
		name (son (e)) == cont_tag ||
2734
		name (son (e)) == cond_tag
2735
	      )) {
2736
	    /* if the chvar operation never needs any action for a little
2737
	       end machine, eliminate it */
2738
#if is80x86
2739
	    if (shape_size(sh(e)) == 8) {
2740
	      if (name (son (e)) == name_tag)
2741
		setvis(son(son(e)));
2742
	      if (name (son (e)) == cont_tag &&
2743
			name(son(son(e))) == name_tag )
2744
		setvis(son(son(son(e))));
2745
	    };
2746
#endif
2747
	    sh (son (e)) = sh (e);
2748
	    replace (e, son (e), scope);
2749
		/* should this retcell(e) ? */
2750
	    return (1);
2751
	  };
2752
	  /* only for little enders which have byte registers */
2753
	  if (name (son (e)) == chvar_tag &&
2754
	      shape_size(sh(e)) <= shape_size(sh (son (e)))) {
2755
	    /* if the chvar operation never needs any action for a little
2756
	       end machine, eliminate it */
2757
	    exp w;
2758
	    sh (son (e)) = sh (e);
2759
	    w = hold (son (e));
2760
	    IGNORE check (son (w), son (w));
2761
	    replace (e, son (w), scope);
2762
	    retcell (e);
2763
	    retcell (w);
2764
	    return (1);
2765
	  };
2766
#endif
2767
#if little_end & has_byte_ops
2768
	  /* only for little enders with byte and short operations */
2769
	  if (shape_size(sh(e)) <= shape_size(sh (son (e))) && optop(e) &&
2770
		name(sh(e)) != bitfhd &&
2771
	       (name (son (e)) == plus_tag ||
2772
		name (son (e)) == minus_tag ||
2773
		name (son (e)) == and_tag ||
2774
		name (son (e)) == or_tag ||
2775
		name (son (e)) == neg_tag
2776
	      )
2777
	    ) {
2778
	    /* replace chvar(op(a ...)) by op(chvar(a)...) if the
2779
	       changevar requires no action on a little end machine */
2780
#if only_lengthen_ops
2781
	      exp p = son (e);
2782
	      exp r;
2783
	      exp a = son (p);
2784
	      exp n = bro (a);
2785
	      int l = (int)last (a);
2786
 
2787
/*
2788
	      if (shape_size(sh(e)) >= 16)
2789
*/
2790
	  /* this is to avoid allocating bytes to edi/esi in 80386 !!! bad
2791
	  */
2792
#endif
2793
	    {
2794
	      exp sha = sh (e);
2795
	      exp t = varchange (sha, a);
2796
	      exp q = t;
2797
 
2798
	      while (!l) {
2799
	        l = (int)last (n);
2800
	        a = n;
2801
	        n = bro (n);
2802
	        setbro (q, varchange (sha, a));
2803
	        clearlast (q);
2804
	        q = bro (q);
2805
	      };
2806
 
2807
	      r = getexp (sha, nilexp, 0, t, pt (p), 0, no (p),
2808
		  name (p));
2809
              seterrhandle(r, errhandle(e));
2810
	      replace (e, hc (r, q), scope);
2811
	      retcell (e);
2812
	      return (1);
2813
	    };
2814
	  };
2815
#endif
2816
	  if (name (son (e)) == ident_tag && isvar (son (e))) {
2817
	    /* distribute chvar into variable declaration of simple form
2818
	    */
2819
	    exp vardec = son (e);
2820
	    exp def = son (vardec);
2821
	    exp body = bro (def);
2822
	    exp res;
2823
	    bool go = 1;
2824
	    exp t, u, v;
2825
	    if (name (body) != seq_tag)
2826
	      return (0);
2827
	    res = bro (son (body));
2828
	    if (name (res) != cont_tag || name (son (res)) != name_tag ||
2829
		son (son (res)) != vardec)
2830
	      return (0);
2831
	    t = pt (vardec);
2832
	    while (t != nilexp && go) {
2833
	      if (t == son (res) || (!last (t) &&
2834
		    name (bro (bro (t))) == ass_tag))
2835
		t = pt (t);
2836
	      else
2837
		go = 0;
2838
	    };
2839
	    if (!go)
2840
	      return (0);
2841
	    if (name(def) == clear_tag) {
2842
	      u = copy(def);
2843
	      sh(u) = sh(e);
2844
	    }
2845
	    else
2846
	      u = varchange (sh (e), copy (def));
2847
	    replace (def, u, u);
2848
	    kill_exp (def, def);
2849
	    sh (res) = sh (e);
2850
	    sh (body) = sh(e);
2851
	    t = pt (vardec);
2852
	    while (t != nilexp) {
2853
	      if (t != son (res)) {
2854
		v = bro (t);
2855
		u = varchange (sh (e), copy (v));
2856
		replace (v, u, u);
2857
		kill_exp (v, def);
2858
	      };
2859
	      t = pt (t);
2860
	    };
2861
	    sh (vardec) = sh (e);
2862
	    replace (e, vardec, scope);
2863
	    retcell (e);
2864
	    return (1);
2865
	  };
2866
	  return 0;
2867
	};
2868
      case bitf_to_int_tag:
2869
        {
2870
	  if (newcode) {
2871
	    exp temp = son(e);
2872
	    int szbf = shape_size(sh(temp));
2873
	    shape sha;
2874
	    int sg = is_signed(sh(temp));
2875
	    int s;
2876
 
2877
	    if (szbf <= 8)
2878
	      sha = (sg) ? scharsh : ucharsh;
2879
	    else
2880
	    if (szbf <= 16)
2881
	      sha = (sg) ? swordsh : uwordsh;
2882
	    else
2883
	    if (szbf <= 32)
2884
	      sha = (sg) ? slongsh : ulongsh;
2885
	    else
2886
	      sha = (sg) ? s64sh : u64sh;
2887
 
2888
	    if (name(sh(temp)) == bitfhd && name(temp) == chvar_tag) {
2889
	      exp st = son(temp);
2890
	      int n = name(st);
2891
	      if ((n == cont_tag && szbf == shape_size(sh(st))) ||
2892
		  ( n==and_tag && name(bro(son(st)))== val_tag &&
2893
			no(bro(son(st))) == (1<<szbf)-1 ) ||
2894
		  ( n==shr_tag && name(bro(son(st)))== val_tag &&
2895
			no(bro(son(st))) == shape_size(sh(st))-szbf)  ) {
2896
		/* arises from bfcont_tag */
2897
	        replace(e, hold_check(me_u3(sh(e), st, chvar_tag)),
2898
		      scope);
2899
	        retcell(e);
2900
	        retcell(temp);
2901
	        return 1;
2902
	      }
2903
	    };
2904
 
2905
 
2906
	    sh(temp) = sha;
2907
 
2908
	    if (sg) {
2909
#if isAlpha
2910
	      s = shape_size(s64sh) - szbf;
2911
	      if (s != 0) {
2912
		temp = hold_check(me_u3(s64sh, temp, chvar_tag));
2913
	        temp =
2914
		    hold_check(me_b3(s64sh, temp,
2915
				 me_shint(s64sh, s), shl_tag));
2916
	        temp =
2917
		    hold_check(me_b3(s64sh, temp,
2918
				 me_shint(s64sh, s), shr_tag));
2919
	      };
2920
#else
2921
	      s = shape_size(sha) - szbf;
2922
	      if (s != 0) {
2923
	        temp =
2924
		  hold_check(me_b3(sha, temp, me_shint(sha, s),
2925
				 shl_tag));
2926
	        temp =
2927
		    hold_check(me_b3(sha, temp, me_shint(sha, s),
2928
				 shr_tag));
2929
	      };
2930
#endif
2931
	    }
2932
	    else {
2933
	        int mask = (szbf == 32) ? -1 : (1 << szbf) - 1;
2934
	        temp = hold_check(me_b3(sha, temp,
2935
				 me_shint(sha, mask), and_tag));
2936
	    };
2937
 
2938
	    replace(e, hold_check(me_u3(sh(e), temp, chvar_tag)), scope);
2939
	    retcell(e);
2940
	    return 1;
2941
	  };
2942
          return 0;
2943
        };
2944
      case int_to_bitf_tag:
2945
        {
2946
	  if (newcode) {
2947
	    exp temp = son(e);
2948
	    shape sha = sh(temp);
2949
	    int szbf = shape_size(sh(e));
2950
	    int sg = is_signed(sh(e));
2951
 
2952
	    if (shape_size(sh(son(e))) < szbf) {
2953
 
2954
	      if (szbf <= 32)
2955
	        sha = (sg) ? slongsh : ulongsh;
2956
	      else
2957
	        sha = (sg) ? s64sh : u64sh;
2958
 
2959
	      temp = hold_check(me_u3(sha, temp, chvar_tag));
2960
	    }
2961
	    else {
2962
	      UNUSED(sha);
2963
	    };
2964
	    temp = hold_check(me_u3(sh(e), temp, chvar_tag));
2965
	    replace(e, temp, scope);
2966
	    retcell(e);
2967
            return 1;
2968
	  };
2969
	  return 0;
2970
        };
2971
      case minptr_tag:
2972
	{
2973
          exp s = son(e);
2974
          exp b = bro(s);
2975
	  if (name (s) == val_tag &&
2976
	      name (b) == null_tag) {
2977
	    sh (s) = sh (e);
2978
	    no(s) -= no(b);
2979
	    no (s) *= 8;
2980
	    replace (e, s, scope);
2981
	    retcell (e);
2982
	    return (1);
2983
	  };
2984
	  if (name (s) == val_tag &&
2985
	      name (b) == val_tag) {/* both constants */
2986
	    sh (s) = sh (e);
2987
	    no (s) -= no (bro (son (e)));
2988
	    no (s) *= 8;
2989
	    replace (e, s, scope);
2990
	    retcell (e);
2991
	    return (1);
2992
	  };
2993
	  if (name(b) == null_tag && no(b) == 0) {
2994
	    sh (s) = sh (e);
2995
	    replace(e, s, scope);
2996
	    retcell(e);
2997
	    return 1;
2998
	  };
2999
	  if (name(s) == name_tag && name(b) == name_tag &&
3000
	       son(s) == son(b)) {
3001
            int n = no(s) - no(b);
3002
	    exp r;
3003
	    r = getexp(sh(e), nilexp, 0, nilexp, nilexp,
3004
			 0, n, val_tag);
3005
	    kill_exp(s, s);
3006
	    kill_exp(b, b);
3007
	    replace(e, r, scope);
3008
	    retcell(e);
3009
	    return 1;
3010
          };
3011
	  return 0;
3012
	};
3013
      case minus_tag: {
3014
	  exp z, a2, r;
3015
	  exp arg1 = son(e);
3016
	  exp arg2 = bro(arg1);
3017
          if (!optop(e))
3018
            return 0;
3019
	  if (name(arg1) == val_tag && name(arg2) == val_tag)
3020
	    {
3021
	      minus_fn(arg1, arg2, errhandle(e));
3022
	      sh(arg1) = sh(e);
3023
	      replace(e, arg1, scope);
3024
	      retcell(e);
3025
	      return 1;
3026
	    };
3027
	  /* replace a-b by a+(-b) */
3028
	  z = getexp (sh (e), nilexp, 0, bro (son (e)), pt(e),
3029
	      0, 0,
3030
	      neg_tag);
3031
          seterrhandle(z, errhandle(e));
3032
	  a2 = hc (z, bro (son (e)));
3033
	  r = getexp (sh (e), nilexp, 0, son (e), pt(e),
3034
	      0, 0, plus_tag);
3035
          seterrhandle(r, errhandle(e));
3036
#ifdef NEWDIAGS
3037
	  dgf(r) = dgf(e);
3038
#endif
3039
	  bro (son (e)) = a2;
3040
	  replace (e, hc (r, a2), scope);
3041
	  retcell (e);
3042
	  return (1);
3043
	};
3044
      case mult_tag: {
3045
          if (!optop(e))
3046
            return 0;
3047
	  if (name (bro (son (e))) == val_tag &&
3048
	      last (bro (son (e))) &&
3049
	      name (son (e)) == plus_tag &&
3050
	      name (bro (son (son (e)))) == val_tag) {
3051
	    /* replace mult(plus(a,const1), const2) by  plus(mult(a,
3052
	       const2), const1*const2) */
3053
	    int  k = no (bro (son (e))) * no (bro (son (son (e))));
3054
            exp ke = me_shint(sh(e), k);
3055
	    exp m = getexp (sh (e), nilexp, 0, son (son (e)),
3056
		nilexp, 0, 0, mult_tag);
3057
	    exp m1, pa;
3058
	    setbro (son (m), copy (bro (son (e))));
3059
	    clearlast (son (m));
3060
	    m1 = hc (m, bro (son (m)));
3061
	    pa = getexp (sh (e), nilexp, 0, m1, nilexp, 0, 0, plus_tag);
3062
	    bro (m1) = ke;
3063
	    clearlast (m1);
3064
	    replace (e, hc (pa, ke), scope);
3065
	    retcell (e);
3066
	    return (1);
3067
	  };
3068
 
3069
	  /* apply commutative and associative laws */
3070
#if is80x86
3071
	  return (comm_ass (e, mult_tag, mult_fn,
3072
		1, 1, 0, scope, 0, 0));
3073
#else
3074
	  return (comm_ass (e, mult_tag, mult_fn,
3075
		1, 1, 0, scope, 1, 0));
3076
#endif
3077
	};
3078
      case subptr_tag: {
3079
	  /* replace subptr(a, b) by addptr(a, (-b)) */
3080
	  exp z = getexp (sh (e), nilexp, 0, bro (son (e)), nilexp,
3081
	      0, 0, neg_tag);
3082
	  exp a2 = hc (z, bro (son (e)));
3083
	  exp r = getexp (sh (e), nilexp, 0, son (e), nilexp, 0,
3084
	      0, addptr_tag);
3085
	  bro (son (e)) = a2;
3086
#ifdef NEWDIAGS
3087
	  if (diagnose)
3088
	    dgf(r) = dgf(e);
3089
#endif
3090
	  replace (e, hc (r, a2), scope);
3091
	  retcell (e);
3092
	  return (1);
3093
	};
3094
      case neg_tag: {
3095
          if (!optop(e))
3096
            return 0;
3097
	  if (name (son (e)) == val_tag) {/* eval for const */
3098
	    neg_fn (son (e));
3099
	    sh(son(e)) = sh(e);
3100
#ifdef NEWDIAGS
3101
	    if (diagnose)
3102
	      dg_whole_comp (e, son(e));
3103
#endif
3104
	    replace (e, son (e), scope);
3105
	    retcell (e);
3106
	    return (1);
3107
	  };
3108
	  if (name (son (e)) == neg_tag &&
3109
	      optop(e) && optop (son (e))) {
3110
	    /* replace --a by a if errtreat is impossible or ignore */
3111
	    sh(son(son(e))) = sh(e);
3112
#ifdef NEWDIAGS
3113
	    if (diagnose) {
3114
	      dg_whole_comp (son(e), son(son(e)));
3115
	      dg_whole_comp (e, son(son(e)));
3116
	    }
3117
#endif
3118
	    replace (e, son (son (e)), scope);
3119
	    retcell (son (e));
3120
	    retcell (e);
3121
	    return (1);
3122
	  };
3123
	  if (name (son (e)) == plus_tag &&
3124
	      optop(e) &&
3125
	      optop (son (e))) {
3126
	    /* replace negate(plus(a,b ..)) by plus(negate(a), negate(b)
3127
	       ..)) */
3128
	    exp r = getexp (sh (e), nilexp, 0, nilexp, nilexp,
3129
		0,
3130
		0, plus_tag);
3131
	    exp t = son (son (e));
3132
	    exp p = r;
3133
	    int lst;
3134
	    do {
3135
	      exp q = hold (getexp (sh (e), nilexp, 0, t,
3136
		    nilexp, 0, 0, neg_tag));
3137
	      exp next = bro (t);
3138
	      lst = (int)last (t);
3139
	      bro (t) = son (q);
3140
	      setlast (t);
3141
	      IGNORE check (son (q), scope);
3142
	      bro (p) = son (q);
3143
	      retcell (q);
3144
	      p = bro (p);
3145
	      clearlast (p);
3146
	      t = next;
3147
	    }
3148
	    while (!lst);
3149
	    son (r) = bro (r);
3150
#ifdef NEWDIAGS
3151
	    if (diagnose)
3152
	      dg_whole_comp (e, r);
3153
#endif
3154
	    replace (e, hc (r, p), scope);
3155
	    retcell (e);
3156
	    return (1);
3157
	  };
3158
	  return 0;
3159
	};
3160
      case shl_tag:
3161
      case shr_tag: {
3162
	  if (name (bro (son (e))) == val_tag && no (bro (son (e))) == 0) {
3163
	    /* remove zero place shift */
3164
	    sh(son(e)) = sh(e);
3165
	    replace (e, son (e), scope);
3166
	    retcell (e);
3167
	    return (1);
3168
	  };
3169
	  if (name (son (e)) == val_tag &&
3170
	      name (bro (son (e))) == val_tag) {
3171
	    /* evaluate if both args constant */
3172
	    doshl(e);
3173
	    sh(son(e)) = sh(e);
3174
	    replace (e, son (e), scope);
3175
	    retcell (e);
3176
	    return (1);
3177
	  };
3178
#if ismips
3179
	  if (name(bro (son (e))) == val_tag &&
3180
		no (bro (son (e))) == shape_size(sh(e)) ) {
3181
		exp s1 = copy(e);
3182
		no(bro (son (s1)))--;
3183
		if (name(e)==shl_tag) {
3184
			s1 = f_shift_left(f_continue, s1,
3185
					 me_shint(sh(bro(son(e))), 1));
3186
		}
3187
		else {
3188
			s1 = f_shift_right(s1, me_shint(sh(bro(son(e))), 1));
3189
		}
3190
		replace(e, s1, scope);
3191
		kill_exp(e, scope);
3192
		return 1;
3193
	  }
3194
#endif
3195
#if has_neg_shift
3196
	  /* only use if the shift left and shift right operations are
3197
	     performed by the same instruction, distinguished by the sign
3198
	     of the number of places */
3199
	  if (name (e) == shr_tag) {
3200
	    exp places = bro (son (e));
3201
	    exp r;
3202
	    exp neg = getexp (sh (places), nilexp, 0, places, nilexp, 0,
3203
		0, neg_tag);
3204
	    neg = hc (neg, places);
3205
	    r = getexp (sh (e), nilexp, 0, son (e), nilexp, 0, 0, shl_tag);
3206
	    bro (son (e)) = neg;
3207
	    r = hc (r, neg);
3208
	    replace (e, r, scope);
3209
	    retcell (e);
3210
	    return (1);
3211
	  };
3212
#endif
3213
	  if (name(e) == shr_tag && name(son(e)) == shl_tag &&
3214
		name(bro(son(e))) == val_tag) {
3215
	    exp arg1 = son(e);
3216
	    int r = no(bro(arg1));
3217
	    if (name(son(arg1)) == shr_tag &&
3218
		 name(bro(son(arg1))) == val_tag) {
3219
	      exp arg11 = son(arg1);
3220
	      int q = no(bro(arg11));
3221
	      if (r >= q && name(bro(son(arg11))) == val_tag) {
3222
		exp x = son(arg11);
3223
		int p = no(bro(x));
3224
		if (q >= p) {
3225
		  exp temp = hold_check(me_b3(sh(arg1), x,
3226
				 me_shint(sh(arg1), q - p), shl_tag));
3227
		  replace(son(e), temp, temp);
3228
		  /* DELIBERATE FALL THROUGH */
3229
		};
3230
	      };
3231
	    }
3232
	    else {
3233
	      if (name(bro(son(arg1))) == val_tag) {
3234
		int q = no(bro(son(arg1)));
3235
		int se = shape_size(sh(e));
3236
		if ( q == r && (q == (se - 16) || q == (se-8)) &&
3237
			is_signed(sh(arg1))) {
3238
		  shape sc = (q == se-16) ? swordsh : scharsh;
3239
		  exp temp1 = me_u3(sc, son(arg1), chvar_tag);
3240
		  exp temp2 = me_u3(sh(e), temp1, chvar_tag);
3241
		  replace(e, hold_check(temp2), scope);
3242
		  retcell(e);
3243
		  return 1;
3244
		};
3245
	      };
3246
	    };
3247
	  };
3248
	  if (name(e) == shl_tag && name(son(e)) == and_tag &&
3249
		 name(bro(son(e))) == val_tag) {
3250
	    exp arg1 = son(e);
3251
	    exp arg2 = bro(arg1); /* left_places */
3252
	    if (name(arg1) == and_tag &&
3253
		 name(bro(son(arg1))) == val_tag) {
3254
	      exp arg11 = son(arg1);
3255
	      exp arg12 = bro(arg11); /* mask */
3256
	      if (name(arg11) == shr_tag &&
3257
		 name(bro(son(arg11))) == val_tag) {
3258
		exp arg111 = son(arg11);
3259
		exp arg112 = bro(arg111); /* right places */
3260
		shape sha = sh(e);
3261
		{
3262
		  exp a = hold_check(me_b3(sha, arg111,
3263
				me_shint(sha,
3264
					 no(arg12) << no(arg112)),
3265
				 and_tag));
3266
		  exp res;
3267
		  if (no(arg2) >= no(arg112))
3268
		    res = me_b3(sha, a,
3269
			 me_shint(sha, no(arg2) - no(arg112)), shl_tag);
3270
		  else
3271
		    res = me_b3(sha, a,
3272
			 me_shint(sha, no(arg112) - no(arg2)), shr_tag);
3273
		  replace(e, hold_check(res), scope);
3274
		  retcell(e);
3275
		  return 1;
3276
		};
3277
	      };
3278
	    };
3279
	  };
3280
	  return seq_distr(e, scope);
3281
	};
3282
      case mod_tag:
3283
	{
3284
	  if (name (son (e)) == val_tag &&
3285
	      name (bro (son (e))) == val_tag) {
3286
	    /* evaluate if both args constant */
3287
	    if (is_signed(sh(e)) && no(bro(son(e)))== -1) {
3288
		replace(e, me_shint(sh(e), 0), scope);
3289
		retcell (e);
3290
	      	return (1);
3291
	    }
3292
	    if (no (bro (son (e))) != 0) {
3293
	      domod (son(e), bro(son(e)));
3294
	      sh(son(e)) = sh(e);
3295
	      replace (e, son(e), scope);
3296
	      retcell (e);
3297
	      return (1);
3298
	    };
3299
	  };
3300
	  return 0;
3301
	};
3302
      case rem0_tag:
3303
      case rem2_tag:
3304
	{
3305
	  if (name (son (e)) == val_tag &&
3306
	      name (bro (son (e))) == val_tag) {
3307
	    /* evaluate if both args constant */
3308
 
3309
	    /* some compilers get the rem2 wrong */
3310
	    if (is_signed(sh(e)) && no(bro(son(e)))== -1) {
3311
		replace(e, me_shint(sh(e), 0), scope);
3312
		retcell (e);
3313
	      	return (1);
3314
	    }
3315
	    if (no (bro (son (e))) != 0) {
3316
	      dorem2 (son(e), bro(son(e)));
3317
	      sh(son(e)) = sh(e);
3318
	      replace (e, son(e), scope);
3319
	      retcell (e);
3320
	      return (1);
3321
	    };
3322
	  };
3323
	  return 0;
3324
	};
3325
      case div1_tag:
3326
	{
3327
	  if (name (bro (son (e))) == val_tag && no (bro (son (e))) == 1) {
3328
	    /* remove divide by 1 */
3329
	    sh(son(e)) = sh(e);
3330
	    replace (e, son (e), scope);
3331
	    retcell (e);
3332
	    return (1);
3333
	  };
3334
	  if (optop(e) && name (son (e)) == val_tag &&
3335
	      name (bro (son (e))) == val_tag &&
3336
              no(bro(son(e))) != 0) {
3337
	    /* evaluate if both args constant */
3338
	      dodiv1 (son(e), bro(son(e)));
3339
	      sh(son(e)) = sh(e);
3340
	      replace (e, son(e), scope);
3341
	      retcell (e);
3342
	      return (1);
3343
	  };
3344
	  return 0;
3345
	};
3346
      case div0_tag:
3347
      case div2_tag:
3348
	{
3349
	  if (name (bro (son (e))) == val_tag && no (bro (son (e))) == 1) {
3350
	    /* remove divide by 1 */
3351
	    sh(son(e)) = sh(e);
3352
	    replace (e, son (e), scope);
3353
	    retcell (e);
3354
	    return (1);
3355
	  };
3356
	  if (optop(e) && name (son (e)) == val_tag &&
3357
	      name (bro (son (e))) == val_tag &&
3358
              no(bro(son(e))) != 0) {
3359
	    /* evaluate if both args constant */
3360
	      dodiv2 (son(e), bro(son(e)));
3361
	      sh(son(e)) = sh(e);
3362
	      replace (e, son(e), scope);
3363
	      retcell (e);
3364
	      return (1);
3365
	  };
3366
	  return 0;
3367
	};
3368
      case max_tag:
3369
      case min_tag:
3370
	{
3371
	  exp arg1 = son(e);
3372
	  exp arg2 = bro(arg1);
3373
	  if (name(arg1) == val_tag && name(arg2) == val_tag) {
3374
	    domaxmin(arg1, arg2, name(e) == max_tag);
3375
	    replace(e, son(e), scope);
3376
	    retcell(e);
3377
	    return 1;
3378
	  };
3379
	  return 0;
3380
	};
3381
      case chfl_tag: {
3382
          if (!optop(e))
3383
            return 0;
3384
	  if (name (sh (e)) == name (sh (son (e)))) {
3385
	    /* eliminate redundant chfl */
3386
	    sh (son (e)) = sh (e);
3387
	    replace (e, son (e), scope);
3388
	    retcell (e);
3389
	    return (1);
3390
	  };
3391
#if FBASE == 10
3392
	  if (name (son (e)) == real_tag &&
3393
		 name(sh(e)) < name(sh(son(e)))) {
3394
	    sh (son (e)) = sh (e);
3395
	    replace (e, son (e), scope);
3396
	    retcell (e);
3397
	    return (1);
3398
	  };
3399
#else
3400
	  if (name (son (e)) == real_tag) {
3401
	    if (name(sh(e)) < name(sh(son(e)))) {
3402
	      flpt_round((int)f_to_nearest,
3403
			 flpt_bits((floating_variety)(name(sh(e)) -
3404
					 shrealhd)),
3405
			  &flptnos[no(son(e))]);
3406
	    };
3407
	    sh (son (e)) = sh (e);
3408
	    replace (e, son (e), scope);
3409
	    retcell (e);
3410
	    return (1);
3411
	  };
3412
#endif
3413
	  if (name (son (e)) == chfl_tag &&
3414
	      name (sh (son (son (e)))) == name (sh (e)) &&
3415
	      name (sh (e)) < name (sh (son (e)))) {
3416
	    /* chfl(flsh1, chfl(flsh2, exp of shape flsh1)) to internal
3417
	       exp iff flsh2 includes flsh1 */
3418
	    sh(son(son(e))) = sh(e);
3419
	    replace (e, son (son (e)), scope);
3420
	    retcell (son (e));
3421
	    retcell (e);
3422
	    return (1);
3423
	  };
3424
	  return 0;
3425
	};
3426
      case round_tag:
3427
	{
3428
          if (!optop(e))
3429
            return 0;
3430
 
3431
#if FBASE == 10
3432
	  if (name (son (e)) == real_tag) {
3433
	    /* apply if arg constant */
3434
	    flpt f = no (son (e));
3435
            exp iexp = me_shint(sh(e), 0);
3436
 
3437
	    int   i,
3438
	          val = 0;
3439
	    flt res;
3440
	    if (round_number (e) == f_to_nearest)
3441
	      flt_round (flptnos[f], &res);
3442
	    else
3443
	      flt_trunc (flptnos[f], &res);
3444
 
3445
	    for (i = 0; i <= res.exp; ++i)
3446
	      val = (10 * val + res.mant[i]);
3447
	    no (iexp) = val * res.sign;
3448
	    replace (e, iexp, scope);
3449
	    kill_exp (e, scope);
3450
	    return (1);
3451
	  };
3452
#else
3453
	  if (name (son (e)) == real_tag) {
3454
	    /* apply if arg constant */
3455
	    flpt f = no (son (e));
3456
	    flt64 x;
3457
	    int ov, pr;
3458
	    int sg = is_signed(sh(e));
3459
            exp iexp;
3460
	    IGNORE flpt_round_to_integer(round_number(e), &flptnos[f]);
3461
	    x = flt_to_f64(f, sg, &ov);
3462
            iexp = me_shint(sh(e), f64_to_flpt(x, sg, &pr,
3463
					 shape_size(sh(e))));
3464
	    if (pr)
3465
	      setbigval(iexp);
3466
	    replace (e, iexp, scope);
3467
	    kill_exp (e, scope);
3468
	    return (1);
3469
	  };
3470
#endif
3471
 
3472
	  return 0;
3473
	};
3474
      case float_tag:
3475
	{
3476
          if (!optop(e))
3477
            return 0;
3478
 
3479
#if FBASE == 10
3480
	  if (name (son (e)) == val_tag) {
3481
	    /* apply if arg constant */
3482
	    shape sha = sh (son (e));
3483
	    int  k = no (son (e));
3484
	    int  sz = shape_size(sha);
3485
 
3486
            if (PIC_code)
3487
              proc_externs = 1;
3488
 
3489
	    if (sz == 8)
3490
	      no(son(e)) = floatrep(k & 0xff);
3491
	    else
3492
	    if (sz == 16)
3493
	      no(son(e)) = floatrep(k & 0xffff);
3494
	    else  {
3495
		/* watch out for 64bits */
3496
	      no (son (e)) = floatrep (k);
3497
	      if (shape_size(sh(son(e))) == 32 && !is_signed(sh(son(e)))
3498
			 && (k & 0x80000000) != 0) {
3499
	        flt flongmaxr;
3500
	        int   i;
3501
	        flt r;
3502
	        flongmaxr.sign = 1;
3503
	        flongmaxr.exp = 9;
3504
	        for (i = 0; i < MANT_SIZE; i++) {
3505
		  (flongmaxr.mant)[i] = (i < 10) ?
3506
                        (maxdigs[i] - '0') : 0;
3507
	        };
3508
	        flt_add (flptnos[no (son (e))], flongmaxr, &r);
3509
	        flptnos[no (son (e))] = r;
3510
	      };
3511
	    };
3512
 
3513
	    flpt_round((int)f_to_nearest,
3514
		flpt_bits((floating_variety)(name(sh(e))-shrealhd)),
3515
			&flptnos[no(son(e))]);
3516
	    setname (son (e), real_tag);
3517
	    sh (son (e)) = sh (e);
3518
	    replace (e, son (e), scope);
3519
	    retcell (e);
3520
	    return (1);
3521
	  };
3522
#else
3523
	  if (name (son (e)) == val_tag) {
3524
	    /* apply if arg constant */
3525
	    exp arg = son(e);
3526
	    shape sha = sh (arg);
3527
	    int  k = no (arg);
3528
	    int  sz = shape_size(sha);
3529
	    int sg = is_signed(sha);
3530
 
3531
            if (PIC_code)
3532
              proc_externs = 1;
3533
 
3534
	    if (sz == 8) {
3535
	      k = k & 0xff;
3536
	      if (sg && k >= 0x80)
3537
		k = (k | (int)0xffffff00);
3538
	      no(arg) = floatrep(k);
3539
	    }
3540
	    else
3541
	    if (sz == 16) {
3542
	      k = k & 0xffff;
3543
	      if (sg && k >= 0x8000)
3544
		k = (k | (int)0xffff0000);
3545
	      no(arg) = floatrep(k);
3546
	    }
3547
	    else
3548
	    if (sz == 32)  {
3549
		/* watch out for 64bits */
3550
	      if (sg)
3551
	        no(arg) = floatrep(k);
3552
	      else
3553
	        no(arg) = floatrep_unsigned(uno(arg));
3554
			/* use unsigned selector for k */
3555
	    }
3556
	    else {
3557
	      if (!isbigval(arg))
3558
		no(arg) = f64_to_flt(exp_to_f64(arg), is_signed(sha));
3559
	      clearbigval(arg);
3560
	    };
3561
 
3562
 
3563
	    flpt_round((int)f_to_nearest,
3564
		flpt_bits((floating_variety)(name(sh(e))-shrealhd)),
3565
			&flptnos[no(arg)]);
3566
	    setname (arg, real_tag);
3567
	    sh (arg) = sh (e);
3568
	    replace (e, arg, scope);
3569
	    retcell (e);
3570
	    return (1);
3571
	  };
3572
#endif
3573
	  return 0;
3574
	};
3575
      case fmult_tag:  		/* apply zero, unit and constant
3576
                                   evaluation.
3577
                                   NB dive MUST be false, because
3578
                                   floating point is not really
3579
                                   commutative and associative
3580
				*/
3581
 
3582
	  return (comm_ass (e, fmult_tag, fmult_fn,
3583
		fone_no, 1, fzero_no, scope, 0, 1));
3584
      case fminus_tag:
3585
          if (!optop(e))
3586
            return 0;
3587
	  if (check_fp2 (e, scope))  /* constant evaluation */
3588
            return 1;
3589
          return 0;
3590
      case fdiv_tag:
3591
          if (!optop(e))
3592
            return 0;
3593
	  if (check_fp2 (e, scope))  /* constant evaluation */
3594
            return 1;
3595
	  if (name(bro(son(e))) == real_tag &&
3596
             flptnos[no(bro(son(e)))].sign != 0 &&
3597
		(!strict_fl_div || flpt_power_of_2(no(bro(son(e)))))) {
3598
	    shape sha = sh(e);
3599
	    exp one;
3600
	    exp temp;
3601
	    flpt f = new_flpt ();
3602
 
3603
	    flt_copy (flptnos[fone_no], &flptnos[f]);
3604
	    one = getexp (sha, nilexp, 0, nilexp, nilexp,
3605
				 0, f, real_tag);
3606
	    temp = hold_check(me_b3(sha, one, bro(son(e)), fdiv_tag));
3607
	    temp = hold_check(me_b3(sha, son(e), temp, fmult_tag));
3608
	    seterrhandle(temp, errhandle(e));
3609
	    replace(e, temp, scope);
3610
	    retcell(e);
3611
	    return 1;
3612
	  };
3613
          return 0;
3614
      case fneg_tag:
3615
	{
3616
          if (!optop(e))
3617
            return 0;
3618
	  if (name (son (e)) == real_tag) {
3619
	    /* apply if arg constant */
3620
	    int  fn = no (son (e));
3621
	    flptnos[fn].sign = -flptnos[fn].sign;
3622
	    replace (e, son (e), scope);
3623
	    retcell (e);
3624
	    return (1);
3625
	  }
3626
	  else
3627
	    if (name (son (e)) == fneg_tag) {
3628
	      /* --a = a (should check ignore overflow) */
3629
	      replace (e, son (son (e)), scope);
3630
	      retcell (son (e));
3631
	      retcell (e);
3632
	      return (1);
3633
	    }
3634
	  return 0;
3635
	};
3636
      case fabs_tag:
3637
	if (name (son (e)) == real_tag) {
3638
	  /* apply if arg constant */
3639
	  int  fn = no (son (e));
3640
	  if (flptnos[fn].sign == -1)
3641
	     flptnos[fn].sign = 1;
3642
	  replace (e, son (e), scope);
3643
	  retcell (e);
3644
	  return (1);
3645
	};
3646
	return 0;
3647
      case and_tag:
3648
#if has_byte_ops
3649
	if (name(bro(son(e))) == val_tag &&
3650
	    no(bro(son(e))) == 0xff &&
3651
	    name(son(e)) == shr_tag &&
3652
	    name(son(son(e))) == cont_tag
3653
	    ) {
3654
	  exp a1 = bro(son(son(e)));
3655
	  if (name(a1) == val_tag && !isbigval(a1) &&
3656
	      (no(a1) & 0x7) == 0) {
3657
	    exp t = son(son(son(e)));
3658
	    exp r = me_u3(sh(t), t, reff_tag);
3659
	    exp c, v;
3660
#if little_end
3661
	    no(r) = no(a1);
3662
#else
3663
	    no(r) = shape_size(sh(e)) - no(a1) - 8;
3664
#endif
3665
	    r = hold_check(r);
3666
	    c = hold_check(me_u3(ucharsh, r, cont_tag));
3667
	    v = hold_check(me_u3(sh(e), c, chvar_tag));
3668
	    replace(e, v, scope);
3669
	    retcell(e);
3670
	    return 1;
3671
	  };
3672
	};
3673
#endif
3674
	if (name(son(e)) == and_tag && name(bro(son(e))) == val_tag &&
3675
		name(bro(son(son(e)))) == val_tag
3676
		&& !isbigval(bro(son(e))) && !isbigval(bro(son(son(e))))) {
3677
	  int mask = no(bro(son(e))) & no(bro(son(son(e))));
3678
	  exp res = hold_check(me_b3(sh(e), son(son(e)),
3679
				me_shint(sh(e), mask), and_tag));
3680
	  replace(e, res, scope);
3681
	  retcell(e);
3682
	  return 1;
3683
	};
3684
	if (name(son(e)) == shr_tag && name(bro(son(e))) == val_tag &&
3685
		!isbigval(bro(son(e)))) {
3686
	  exp arg1 = son(e);
3687
	  exp arg2 = bro(arg1); /* mask */
3688
	  int m = no(arg2);
3689
	  int sz = shape_size(sh(arg1));
3690
	  if (m > 0 && name(bro(son(arg1))) == val_tag &&
3691
		!isbigval(bro(son(arg1))) &&
3692
		m <= ((1 << (sz - no(bro(son(arg1))))) - 1)) {
3693
	    exp arg11 = son(arg1);
3694
	    exp arg12 = bro(arg11); /* right shift places */
3695
	    if (name(arg11) == shl_tag &&
3696
		 name(bro(son(arg11))) == val_tag &&
3697
		!isbigval(bro(son(arg11)))) {
3698
	      exp arg111 = son(arg11);
3699
	      exp arg112 = bro(arg111); /* left shift places */
3700
	      if (no(arg112) <= no(arg12)) {
3701
		exp res = hold_check(me_b3(sh(arg1), arg111,
3702
			      me_shint(sh(arg1), no(arg12) - no(arg112)),
3703
			    shr_tag));
3704
		replace(arg1, res, res);
3705
		return check(e, scope);
3706
	      };
3707
	    };
3708
	  };
3709
	};
3710
	/* apply commutative and associative laws */
3711
	return (comm_ass (e, and_tag, and_fn, all_ones (son(e)),
3712
	      1, 0, scope, 1, 0));
3713
      case or_tag:
3714
	/* apply commutative and associative laws */
3715
	if (name(son(e)) == and_tag &&
3716
		name(bro(son(e))) == val_tag &&
3717
		!isbigval(bro(son(e))) &&
3718
		name(bro(son(son(e))))) {
3719
	  exp arg1 = son(e);
3720
	  int q = no(bro(arg1));
3721
	  exp arg11 = son(arg1);
3722
	  int p = no(bro(arg11));
3723
	  if ((q | p) == (int)0xffffffff) {
3724
	    exp res = me_b3(sh(e), arg11, bro(arg1), or_tag);
3725
	    replace(e, hold_check(res), scope);
3726
	    retcell(e);
3727
	    return 1;
3728
	  };
3729
	};
3730
	return (comm_ass (e, or_tag, or_fn, 0, shape_size(sh(e)) <= 32,
3731
		 all_ones (son(e)),
3732
	         scope, 1, 0));
3733
      case xor_tag:
3734
	/* apply commutative and associative laws */
3735
	return (comm_ass (e, xor_tag, xor_fn, 0, 0,
3736
	      0, scope, 1, 0));
3737
      case not_tag: {
3738
	  if (name (son (e)) == val_tag) {/* eval for const */
3739
	    not_fn (son (e));
3740
	    sh(son(e)) = sh(e);
3741
	    replace (e, son (e), scope);
3742
	    retcell (e);
3743
	    return (1);
3744
	  };
3745
	  if (name (son (e)) == not_tag) {/* not(not(x)) -> x */
3746
	    sh(son(son(e))) = sh(e);
3747
	    replace (e, son (son (e)), scope);
3748
	    retcell (son (e));
3749
	    retcell (e);
3750
	    return (1);
3751
	  };
3752
	  return 0;
3753
	};
3754
     case cont_tag:
3755
#ifdef promote_pars
3756
	{ int x = al1_of(sh(son(e)))->al.sh_hd;
3757
 
3758
	  if (x >= scharhd && x <= uwordhd && !little_end) {
3759
		int disp = shape_size(ulongsh)-((x>=swordhd)?16:8);
3760
		exp r = getexp(f_pointer(f_alignment(sh(e))), nilexp,
3761
					 1, son(e), nilexp, 0, disp, reff_tag);
3762
		bro(son(r)) = r;
3763
		son(e) = hold_check(r);
3764
		bro(son(e)) = e; setlast(son(e));
3765
		return 1;
3766
	  }
3767
	}
3768
#endif
3769
 
3770
#ifndef NEWDIAGS
3771
        if (name(son(e)) == diagnose_tag)
3772
          {
3773
            exp diag = son(e);
3774
            exp p = son(diag);
3775
            exp r = getexp(sh(e), nilexp, 0, p, nilexp, 0,
3776
				 0, cont_tag);
3777
            exp d;
3778
            r = hc(r, p);
3779
            d = getexp(sh(e), nilexp, 0, r, pt(diag), props(diag),
3780
                        no(diag), diagnose_tag);
3781
            setfather(d, r);
3782
            replace(e, d, scope);
3783
            retcell(son(e));
3784
            retcell(e);
3785
            return 1;
3786
          };
3787
#endif
3788
        return 0;
3789
    case field_tag:
3790
      if (name(son(e)) == compound_tag && nos (son(e))) {
3791
	exp s = son(son(e));
3792
	for(;;) {
3793
		if ( no(s)==no(e)
3794
			&& eq_shape(sh(e), sh(bro(s)))) {
3795
		   replace(e, copy(bro(s)), scope);
3796
		   kill_exp(e, scope);
3797
		   return 1;
3798
		}
3799
		if (last(bro(s))) break;
3800
		s = bro(bro(s));
3801
	}
3802
      }
3803
      if (name(son(e)) == nof_tag && nos (son(e))
3804
		&& eq_shape(sh(e), sh(son(son(e)))) ) {
3805
	exp s = son(son(e));
3806
	int sz = rounder(shape_size(sh(s)), shape_align(sh(s)));
3807
	int n = 0;
3808
	for(; no(e)<=n; n+=sz) {
3809
		if (no(e)==n) {
3810
			replace(e, copy(s), scope);
3811
			kill_exp(e, scope);
3812
		        return 1;
3813
		}
3814
		if (last(s)) break;
3815
		s = bro(s);
3816
	}
3817
      }
3818
 
3819
      if (name (son (e)) == name_tag) {
3820
	/* replace field on name by name with offset in no */
3821
	no (son (e)) += no (e);
3822
	sh (son (e)) = sh (e);
3823
	replace (e, son (e), scope);
3824
	retcell (e);
3825
	return (1);
3826
      };
3827
      if (name (son (e)) == cont_tag) {
3828
	/* replace field[n](cont(x)) by cont(reff[n](x)) */
3829
	exp arg = son (son (e));
3830
	exp rf1 = getexp (sh (arg), nilexp, 0, arg, nilexp, 0,
3831
	    no (e), reff_tag);
3832
	exp rf = hc (rf1, arg);
3833
	exp c = getexp (sh (e), nilexp, 0, rf, nilexp, 0, 0, cont_tag);
3834
	replace (e, hc (c, rf), scope);
3835
	retcell (son (e));
3836
	retcell (e);
3837
	return (1);
3838
      };
3839
      if (name(son(e)) == ident_tag && isvar(son(e)) &&
3840
           name(son(son(e))) == clear_tag &&
3841
	   name(bro(son(son(e)))) == seq_tag) {
3842
	exp var = son(e);
3843
	exp sq = bro(son(var));
3844
	if (name(bro(son(sq))) == cont_tag &&
3845
	    name(son(bro(son(sq)))) == name_tag &&
3846
	    son(son(bro(son(sq)))) == var) {
3847
	  int count = 0;
3848
	  int good = 0;
3849
	  exp p = son(son(sq));
3850
	  exp q;
3851
	  exp res;
3852
	  while (p != son(sq)) {
3853
	    if (name(p) != ass_tag || name(son(p)) != name_tag ||
3854
	        son(son(p)) != var)
3855
	      return 0;
3856
	    ++count;
3857
	    if (no(son(p)) == no(e))
3858
	      good = 1;
3859
	    p = bro(p);
3860
	  }
3861
	  if ((count+1) != no(var) || !good)
3862
	    return 0;
3863
	  p = son(son(sq));
3864
	  while (p != son(sq)) {
3865
	    q = bro(p);
3866
	    if (no(son(p)) == no(e)) {
3867
	      exp tp = f_make_top();
3868
	      res = bro(son(p));
3869
	      replace(p, tp, tp);
3870
	    }
3871
	    else {
3872
	      exp w = bro(son(p));
3873
	      replace(p, w, w);
3874
	    }
3875
	    p = q;
3876
	  }
3877
	  SET(res);
3878
	  replace(bro(son(sq)), res, res);
3879
	  replace(e, hold_check(sq), scope);
3880
	  return 1;
3881
	}
3882
	return 0;
3883
      }
3884
      return (0);
3885
    case reff_tag:
3886
      if (name (son (e)) == name_tag &&
3887
	  isvar (son (son (e))) && al1(sh(e)) > 1) {
3888
	/* replace reff on name of var by name with offset in no */
3889
	no (son (e)) += no (e);
3890
	sh (son (e)) = sh (e);
3891
#ifdef NEWDIAGS
3892
	if (diagnose)
3893
	  dg_whole_comp (e, son(e));
3894
#endif
3895
	replace (e, son (e), scope);
3896
	retcell (e);
3897
	return (1);
3898
      };
3899
 
3900
      if (name (son (e)) == val_tag) {
3901
	no (son (e)) += (no (e) / 8);
3902
	sh (son (e)) = sh (e);
3903
#ifdef NEWDIAGS
3904
	if (diagnose)
3905
	  dg_whole_comp (e, son(e));
3906
#endif
3907
	replace (e, son (e), scope);
3908
	retcell (e);
3909
	return (1);
3910
      };
3911
 
3912
#if !temp_mips
3913
      /* confirm mips doesnt need this */
3914
      if (name (son (e)) == reff_tag) {
3915
	/* combine reff selections */
3916
	sh (son (e)) = sh (e);
3917
	no (son (e)) += no (e);
3918
#ifdef NEWDIAGS
3919
	if (diagnose)
3920
	  dg_whole_comp (e, son(e));
3921
#endif
3922
	replace (e, son (e), scope);
3923
	retcell (e);
3924
	return (1);
3925
      };
3926
#endif
3927
 
3928
#if remove_zero_offsets
3929
      if (no(e) == 0 && al1(sh(e)) > 1)
3930
       {
3931
          sh(son(e)) = sh(e);
3932
#ifdef NEWDIAGS
3933
	  if (diagnose)
3934
	    dg_whole_comp (e, son(e));
3935
#endif
3936
          replace(e, son(e), scope);
3937
          retcell(e);
3938
          return 1;
3939
       };
3940
#endif
3941
 
3942
        return (0);
3943
      case bfcont_tag:
3944
      case bfcontvol_tag:
3945
	{
3946
	  exp p = son(e);
3947
	  int bsz = shape_size(sh(e));
3948
	  int rsz = al1(sh(p));
3949
	  int rsh;
3950
	  int sg = is_signed(sh(e));
3951
	  int off = no(e);
3952
	  exp ref;
3953
	  exp cont;
3954
	  exp eshift;
3955
	  shape ptr_sha;
3956
	  shape msh;
3957
	  int temp = off + bsz - 1;
3958
 
3959
	  if (rsz>BF_STORE_UNIT) rsz = BF_STORE_UNIT;
3960
 
3961
	  if (((off/8) == (temp/8)) &&
3962
		(bsz == 8 &&
3963
		    ((little_end && (off%8 == 0)) ||
3964
		      (!little_end && ((8 - (off % 8) - bsz) == 0))))) {
3965
	    rsz = 8;
3966
	  }
3967
	  else
3968
	  if (((off/16) == (temp/16)) &&
3969
	        (bsz == 16 &&
3970
		   ((little_end && (off%16 == 0)) ||
3971
		     (!little_end && ((16 - (off % 16) - bsz) == 0))))) {
3972
	    rsz = 16;
3973
	  }
3974
#if isAlpha
3975
	  else
3976
	  if (((off/32) == (temp/32)) &&
3977
	      (!sg || (al1(sh(p)) < 64) ||
3978
	        (bsz == 32 &&
3979
		   ((little_end && (off%32 == 0)) ||
3980
		     (!little_end && ((32 - (off % 32) - bsz) == 0)))))) {
3981
	    rsz = 32;
3982
	  }
3983
#endif
3984
	  else {
3985
		/* all of bitfield must be within same integer variety */
3986
		while ((off/rsz) != (temp/rsz)) { rsz = rsz<<1; }
3987
	  }
3988
 
3989
 
3990
	  msh = containedshape(rsz, sg);
3991
	  ptr_sha = f_pointer(long_to_al(rsz));
3992
	  if ((off / rsz) != 0) {
3993
	    ref = me_u3(ptr_sha, p, reff_tag);
3994
	    no(ref) = (off / rsz) * rsz;
3995
	    ref = hold_check(ref);
3996
	  }
3997
	  else
3998
	    ref = p;
3999
#if little_end
4000
	  rsh = off % rsz;
4001
#else
4002
	  rsh = rsz - (off % rsz) - bsz;
4003
#endif
4004
	  cont = me_u3(msh, ref,
4005
			(name(e) == bfcont_tag)
4006
			  ? (unsigned char)cont_tag
4007
			  : (unsigned char)contvol_tag);
4008
	  if (rsh==0 && !sg && bsz != rsz) {
4009
	      eshift = me_b3(msh, cont,
4010
				 me_shint(slongsh, (1<<bsz)-1), and_tag);
4011
          }
4012
	  else {
4013
	    if (rsz - bsz - rsh != 0) {
4014
		cont = me_b3(msh, cont, me_shint(slongsh,rsz - bsz - rsh),
4015
					shl_tag);
4016
	    }
4017
 
4018
	    if (rsz - bsz != 0)
4019
	       eshift = me_b3(msh, cont, me_shint(slongsh, rsz-bsz),
4020
				shr_tag);
4021
	    else
4022
	    eshift = cont;
4023
	  }
4024
	  eshift = me_u3(sh(e), eshift, chvar_tag);
4025
 
4026
	  replace(e, eshift , scope);
4027
	  retcell(e);
4028
	  return 1;
4029
	};
4030
      case abs_tag:
4031
	if (name (son (e)) == val_tag) {
4032
	  if (is_signed(sh(e)) &&
4033
	  	((isbigval(son(e)) && flptnos[no(son(e))].sign) ||
4034
		 (!isbigval(son(e)) && no(son(e)) < 0))) {/* eval for const */
4035
	    if (!optop(e)) return 0;
4036
	    neg_fn (son (e));
4037
	  }
4038
	  sh(son(e)) = sh(e);
4039
#ifdef NEWDIAGS
4040
	  if (diagnose)
4041
	    dg_whole_comp (e, son(e));
4042
#endif
4043
	  replace (e, son (e), scope);
4044
	  retcell (e);
4045
	  return (1);
4046
	};
4047
	return 0;
4048
      case fmax_tag:
4049
       case fmin_tag:
4050
	{
4051
	  bool fmin = (name(e)==fmin_tag);
4052
	  exp arg1 = son(e);
4053
	  exp arg2 = bro(arg1);
4054
	  exp id1 = me_startid(sh(arg1),arg1,0);/* identify arg1 */
4055
	  exp id2 = me_startid(sh(arg2),arg2,0);/* identify arg2 */
4056
	  exp seq;
4057
	  exp cond;
4058
	  exp zero;
4059
	  exp lab;
4060
	  exp clear;
4061
	  exp test;
4062
 
4063
	  clear = getexp(f_bottom,nilexp,0,nilexp,nilexp,0,0,clear_tag);
4064
	  lab = me_b3(sh(arg2),clear,me_obtain(id2),labst_tag);
4065
	  test = me_q2(no_nat_option,
4066
		       f_impossible,
4067
		       fmin?f_less_than:f_greater_than,
4068
		       &lab,
4069
		       me_obtain(id1),
4070
		       me_obtain(id2),
4071
		       test_tag);
4072
	  zero = me_u3(sh(test),test,0);
4073
	  seq = me_b3(sh(arg1),zero,me_obtain(id1),seq_tag);
4074
	  cond = me_b3(sh(arg1),seq,lab,cond_tag);
4075
	  id2 = me_complete_id(id2,cond);
4076
	  id1 = me_complete_id(id1,id2);
4077
	  replace(e,id1,scope);
4078
	  retcell(e);
4079
	  return 1;
4080
	}
4081
      case name_tag: {
4082
	  exp s = son(e);
4083
	  if (!isvar(s) && isglob(s) && son(s) != nilexp
4084
		&& name(sh(e)) == name(sh(son(s)))
4085
		&& (name(son(s)) == val_tag || name(son(s))==real_tag)) {
4086
		exp c = copy(son(s));
4087
		replace(e,c,scope);
4088
		kill_exp(e,scope);
4089
		return 1;
4090
	   }
4091
	   else return 0;
4092
 
4093
      }
4094
      case fpower_tag:
4095
      case imag_tag:
4096
      case make_complex_tag:
4097
	return 0;
4098
      case rotl_tag:
4099
      case rotr_tag:
4100
      case env_offset_tag:
4101
      case general_env_offset_tag:
4102
      case proc_tag:
4103
      case general_proc_tag:
4104
      case top_tag:
4105
      case val_tag:
4106
      case real_tag:
4107
      case current_env_tag:
4108
      case make_lv_tag:
4109
      case clear_tag:
4110
      case null_tag:
4111
      case string_tag:
4112
      case power_tag:
4113
      case contvol_tag:
4114
        return 0;
4115
      default:
4116
        return 0;
4117
    };
4118
  };
4119
 
4120
 
4121
  switch (name (e)) {		/* side effecting ops */
4122
    case compound_tag:
4123
      {
4124
       exp bse = bro(son(e));
4125
       unsigned char shn = name(sh(bse));
4126
       if (last(bse) && name(son(e)) == val_tag &&
4127
             no(son(e)) == 0 &&
4128
              shape_size(sh(e)) == shape_size(sh(bse)) &&
4129
              shn != prokhd && (shn < shrealhd || shn > doublehd)
4130
#if dont_unpad_apply
4131
                 && name(bse) != apply_tag
4132
#endif
4133
          )
4134
        {  /* remove the creation of a compound if it consists of a
4135
              single value of the same size and provided that the
4136
              component is not real (because it might be in the wrong
4137
              place. */
4138
          if (name(bse) == name_tag && isvar(son(bse)) &&
4139
                !isglob(son(bse)) &&
4140
                name(sh(son(son(bse)))) >= shrealhd &&
4141
                name(sh(son(son(bse)))) <= doublehd)  {
4142
            setvis(son(bse));
4143
            props(e) = (prop)(props(e) & ~0x08);
4144
          };
4145
          sh(bse) = sh(e);
4146
#ifdef NEWDIAGS
4147
	  if (diagnose)
4148
	    dg_whole_comp (e, bse);
4149
#endif
4150
          replace(e, bse, scope);
4151
          retcell(son(e));
4152
          retcell(e);
4153
          return 1;
4154
        };
4155
       };
4156
#if replace_compound
4157
      if (in_proc_def)
4158
      {  /* Provided that the exp is inside a procedure definition we
4159
            always remove compound creation and replace it by a
4160
            variable declaration for the compound, assignments to
4161
            the components, and deliver the compound. */
4162
        shape she = sh(e);
4163
        exp var = me_start_clearvar(she, she);
4164
        exp cont = getexp(she, nilexp, 0, nilexp, nilexp, 0, 0, cont_tag);
4165
        exp_list el;
4166
        exp obt;
4167
        exp t = son(e);
4168
        exp seq;
4169
        obt = me_obtain(var);
4170
        son(cont) = obt;
4171
        setfather(cont, obt);
4172
        el = new_exp_list(0);
4173
 
4174
        while (1)
4175
         {
4176
           exp q = bro(t);  /* expression being assigned */
4177
           exp n = bro(q);
4178
           int end = (int)last(q);
4179
           exp ass, p, ap;
4180
           p = me_obtain(var);
4181
	   if (name(sh(q)) != bitfhd || !newcode) {
4182
             ap = hold_check(f_add_to_ptr(p, t));  /* destination */
4183
             ass = hold_check(f_assign(ap, q));
4184
	   }
4185
	   else {
4186
	     ass = hold_check(f_bitfield_assign(p, t, q));
4187
	   };
4188
           el = add_exp_list(el, ass, 0);
4189
           if (end)
4190
             break;
4191
           t = n;
4192
         };
4193
        seq = f_sequence(el, cont);
4194
#ifdef NEWDIAGS
4195
	if (diagnose)
4196
	  dg_whole_comp (e, var);
4197
#endif
4198
        replace(e, me_complete_id(var, seq), scope);
4199
        retcell(e);
4200
        return 1;
4201
      };
4202
#endif
4203
      return 0;
4204
#ifndef NEWDIAGS
4205
    case diagnose_tag:
4206
#endif
4207
    case prof_tag:
4208
      return 0;
4209
    case ident_tag:
4210
      if (name(sh(son(e))) == bothd)
4211
        {
4212
         exp s = son(e);
4213
         exp b = bro(s);
4214
#ifdef NEWDIAGS
4215
	 if (diagnose) {
4216
	   dg_dead_code (b, s);
4217
	   dg_whole_comp (e, s);
4218
	 }
4219
#endif
4220
         kill_exp(b, b);
4221
         replace(e, s, scope);
4222
         retcell(e);
4223
         return 1;
4224
        };
4225
#if has_setcc
4226
      /* use if target has setcc instruction */
4227
      if (!is80x86 || is80586) {
4228
	exp abst = absbool (e);
4229
	if (abst != nilexp &&
4230
		(!is80x86 || name(sh(son(abst))) <= u64hd)) {
4231
	  /* check if we can use setcc */
4232
	  exp a = copy (abst);
4233
	  setname (a, absbool_tag);
4234
	  pt (a) = nilexp;
4235
	  sh (a) = sh (e);
4236
#ifdef NEWDIAGS
4237
	  if (diagnose)
4238
	    dg_whole_comp (e, a);
4239
#endif
4240
	  replace (e, a, a);
4241
	  kill_exp (e, e);
4242
	  return (0);
4243
	};
4244
      };
4245
#endif
4246
      if (name(sh(bro(son(e)))) != name(sh(e))) {
4247
		sh(e) = sh(bro(son(e)));
4248
		IGNORE check_id(e,scope);
4249
		return 1;
4250
      }
4251
      return (check_id (e, scope));/* see check_id.c */
4252
    case seq_tag:
4253
      if (son (son (e)) == nilexp) {/* remove empty seq */
4254
        exp s = son(e);
4255
	sh(bro(s)) = sh(e);	/* unless bottom ???????????????????????????? */
4256
 
4257
#ifdef NEWDIAGS
4258
	if (diagnose)
4259
	  dg_whole_comp (e, bro(s));
4260
#endif
4261
	replace (e, bro (s), scope);
4262
        retcell(s);
4263
	return (1);
4264
      };
4265
      return (check_seq (e, scope));
4266
    case cond_tag:
4267
      if (no (son (bro (son (e)))) == 0) {
4268
	/* remove inaccessible statements */
4269
	exp bs = bro(son(e));
4270
#ifdef NEWDIAGS
4271
	if (diagnose) {
4272
	  dg_dead_code (bro(son(bs)), son(e));
4273
	  dg_whole_comp (e, son(e));
4274
	}
4275
#endif
4276
	replace (e, son (e), scope);
4277
	kill_exp(bs, scope);
4278
	retcell(e);
4279
	return (1);
4280
      };
4281
      if (name (son (e)) == goto_tag &&
4282
	  pt (son (e)) == bro (son (e))) {
4283
	/* replace cond which has first a simple goto to the alt by the
4284
	   alt (removing the label) */
4285
	exp x = bro (son (bro (son (e))));
4286
#ifdef NEWDIAGS
4287
	if (diagnose) {
4288
	  dg_rdnd_code (son(e), x);
4289
	  dg_whole_comp (e, x);
4290
	}
4291
#endif
4292
	replace (e, x, scope);
4293
        retcell(son (bro (son (e))));
4294
	retcell(bro (son (e)));
4295
        if (son(son(e)) != nilexp) { retcell(son(son(e))); }
4296
        retcell(son(e));
4297
        retcell(e);
4298
	return (1);
4299
      };
4300
 
4301
      if (name (son (e)) == seq_tag && no (son (bro (son (e)))) == 1 &&
4302
	  name (bro (son (son (e)))) == goto_tag) {
4303
	/* is e = cond(seq(..;goto m), l: x) and is only 1 use of l */
4304
	exp t = son (son (son (e)));
4305
	while (!last (t))
4306
	  t = bro (t);
4307
#ifndef NEWDIAGS
4308
        if (name(t) == diagnose_tag)
4309
          t = son(t);
4310
#endif
4311
	if ((name (t) == test_tag || name (t) == testbit_tag) &&
4312
	    pt (t) == bro (son (e)) && test_number(t) <= 6) {
4313
	  /* look at last element of sequence before goto m to see if it
4314
	     is a conditional jump to l. If so reverse the test, make it
4315
	     jump to m and remove the goto */
4316
 
4317
	  settest_number (t, revtest[test_number (t) - 1]);
4318
	  pt (t) = pt (bro (son (son (e))));
4319
	  sh (son (e)) = sh (bro (son (bro (son (e)))));
4320
	  replace (bro (son (son (e))),
4321
	      bro (son (bro (son (e)))),
4322
	      son (e));
4323
	  replace (e, son (e), scope);
4324
	  retcell (e);
4325
	  return (1);
4326
	};
4327
 
4328
      };
4329
#if maxmin_implemented
4330
      {
4331
	exp t;
4332
	int bl = is_maxop(e, &t);
4333
	int ismax = 0;
4334
	int ismin = 0;
4335
	ntest nt;
4336
	if (bl) {
4337
	  nt = test_number(t);
4338
	  if (nt == f_greater_than || nt == f_greater_than_or_equal) {
4339
	    ismax = 1;
4340
	  };
4341
	  if (nt == f_less_than || nt == f_less_than_or_equal)
4342
	    ismin = 1;
4343
	}
4344
	else {
4345
	  bl = is_minop(e, &t);
4346
	  if (bl) {
4347
	    nt = test_number(t);
4348
	    if (nt == f_greater_than || nt == f_greater_than_or_equal)
4349
	      ismin = 1;
4350
	    if (nt == f_less_than || nt == f_less_than_or_equal)
4351
	      ismax = 1;
4352
	  };
4353
	};
4354
	if (ismax || ismin) {
4355
	  exp tq = me_b2(copy(son(t)), copy(bro(son(t))),
4356
			 (ismax)
4357
			   ? (unsigned char)max_tag
4358
			   : (unsigned char)min_tag);
4359
	  replace(e, hold_check(tq), scope);
4360
	  kill_exp(e, e);
4361
	  return 1;
4362
	};
4363
      };
4364
#endif
4365
 
4366
#if condassign_implemented
4367
      {
4368
	exp to_test;
4369
	exp to_ass;
4370
 
4371
	if (is_condassign(e, &to_test, &to_ass) &&
4372
	       is_floating(name(sh(son(to_test)))) ==
4373
		 is_floating(name(sh(bro(son(to_ass)))))) {
4374
	  exp res = me_b3(sh(e), to_test, to_ass, condassign_tag);
4375
	  replace(e, res, scope);
4376
	  retcell(e);
4377
	  return 1;
4378
	};
4379
      };
4380
#endif
4381
 
4382
      if (name(bro(son(bro(son(e))))) == top_tag) {
4383
        exp first = son(e);
4384
	exp alt = bro(first);
4385
	int in_repeat = 0;
4386
	if (crt_repeat != nilexp && (int)(props(crt_repeat)) == 1)
4387
	  in_repeat = 1;
4388
        if (take_out_of_line(first, alt, in_repeat, 1.0)) {
4389
	  exp t = son(son(first));
4390
	  exp tst = (is_tester(t, 0)) ? t : bro(son(t));
4391
	  if (no(tst) == 1000)
4392
	    no(tst) = 25;
4393
	}
4394
      }
4395
      return (0);
4396
#if condassign_implemented
4397
    case condassign_tag:
4398
      if (name(bro(son(e))) != ass_tag &&
4399
	  (name(son(e)) == test_tag || name(son(e)) == testbit_tag)) {
4400
	exp sqz = me_b3(f_top, son(son(e)), bro(son(son(e))), 0);
4401
	exp sq = me_b3(sh(e), sqz, bro(son(e)), seq_tag);
4402
	replace(e, hold_check(sq), scope);
4403
	retcell(e);
4404
	return 1;
4405
      };
4406
      if (name(son(e)) == goto_tag) {
4407
	replace(e, getexp(f_top, nilexp, 0, nilexp,
4408
			  nilexp, 0, 0, top_tag),
4409
	        scope);
4410
	retcell(e);
4411
	return 1;
4412
      };
4413
      if (name(son(e)) == top_tag) {
4414
	replace(e, bro(son(e)), scope);
4415
	retcell(e);
4416
	return 1;
4417
      };
4418
#endif
4419
    case goto_tag: case return_to_label_tag: case trap_tag:
4420
      return (0);
4421
    case ass_tag:
4422
#if 0
4423
      if (0 && redo_structfns && !reg_result(sh(bro(son(e)))) &&
4424
          name (bro (son (e))) == ident_tag &&
4425
	  isvar (bro (son (e)))) {  /* prepare to replace the assignment
4426
                                       of structure results of procedures.
4427
                                       If it decides to do so it will
4428
                                       put the destination in as the first
4429
                                       parameter of the procedure */
4430
	exp id = bro (son (e));
4431
	exp def = son (id);
4432
	exp body = bro (def);
4433
	if (name (def) == clear_tag && name (body) == seq_tag) {
4434
	  if (name (son (son (body))) == apply_tag &&
4435
	      last (son (son (body))) &&
4436
	      name (bro (son (body))) == cont_tag &&
4437
	      name (son (bro (son (body)))) == name_tag &&
4438
	      son (son (bro (son (body)))) == id) {
4439
	    exp ap = son (son (body));
4440
	    exp p1 = bro (son (ap));
4441
	    if (name (p1) == name_tag && son (p1) == id &&
4442
		last (ap)) {
4443
	      /* this is the assignment of a struct result of a proc */
4444
	      exp p2 = bro (son (ap));
4445
	      exp se = son(e);
4446
	      if (last(p2))
4447
		setlast (se);
4448
              bro(se) = bro(p2);
4449
              bro(son(ap)) = se;
4450
	      if (name(se) == name_tag && isvar(son(se)) &&
4451
		  !isglob(son(se)) &&
4452
		   shape_size(sh(id)) == shape_size(sh(son(son(se)))))
4453
		setreallyass(se);
4454
	      replace (e, ap, scope);
4455
	      return (1);
4456
	    };
4457
	  };
4458
	};
4459
      };
4460
#endif
4461
#ifdef promote_pars
4462
	{ int x = al1_of(sh(son(e)))->al.sh_hd;
4463
 
4464
	  if (x >= scharhd && x <= uwordhd && !little_end) {
4465
	        exp b = bro(son(e));
4466
		int disp = shape_size(ulongsh)-((x>=swordhd)?16:8);
4467
		exp r = getexp(f_pointer(f_alignment(sh(b))), nilexp,
4468
					 1, son(e), nilexp, 0, disp, reff_tag);
4469
		bro(son(r)) = r; setlast(son(r));
4470
		r = hold_check(r);
4471
		bro(r) = b; clearlast(r);
4472
		son(e) = r;
4473
		return 1;
4474
	  }
4475
	}
4476
#endif
4477
      return (seq_distr (e, scope));
4478
    case testbit_tag:
4479
      {
4480
	exp arg1 = son(e);
4481
	exp arg2 = bro(arg1);
4482
	if (name (arg1) == val_tag && name (arg2) == val_tag &&
4483
		!isbigval(arg1) && !isbigval(arg2)) {
4484
	  /* evaluate if args constant */
4485
	  int  k = no (arg1) & no (arg2);
4486
	  if ((k != 0 && test_number (e) == 5) ||
4487
                   (k == 0 && test_number (e) == 6))
4488
	    repbygo (e, pt (e), scope);
4489
	  else
4490
	    repbycont (e, 1, scope);
4491
	  return (1);
4492
	};
4493
	if (name(arg1) == shr_tag && name(arg2) == val_tag &&
4494
		name(bro(son(arg1))) == val_tag &&
4495
		!isbigval(arg2) && !isbigval(bro(son(arg1)))) {
4496
	  exp x = son(arg1);
4497
	  exp nsh = bro(x);
4498
	  int places = no(nsh);
4499
	  exp res;
4500
	  sh(x) = sh(arg2);
4501
	  res = me_b3(sh(e), x, me_shint(sh(arg2), no(arg2) << places),
4502
				testbit_tag);
4503
	  no(res) = no(e);
4504
	  pt(res) = pt(e);
4505
	  settest_number(res, test_number(e));
4506
	  replace(e, hold_check(res), scope);
4507
	  retcell(e);
4508
	  return 1;
4509
	};
4510
	return (0);
4511
      };
4512
    case test_tag: {
4513
	exp arg1, arg2;
4514
	int  n;
4515
	int bl;
4516
        unsigned char nt = test_number(e);
4517
	arg1 = son (e);
4518
	arg2 = bro (arg1);
4519
 
4520
        if (flpt_always_comparable ||
4521
             (name(sh(arg1)) < shrealhd || name(sh(arg1)) > doublehd)) {
4522
          switch (nt) {
4523
            case 7: nt = f_greater_than;
4524
		    break;
4525
            case 8: nt = f_greater_than_or_equal;
4526
		    break;
4527
            case 9: nt = f_less_than;
4528
		    break;
4529
            case 10: nt = f_less_than_or_equal;
4530
		     break;
4531
            case 11: nt = f_not_equal;
4532
		     break;
4533
            case 12: nt = f_equal;
4534
		     break;
4535
            case 13: repbycont (e, 1, scope);
4536
		     return 1;
4537
            case 14: repbygo (e, pt (e), scope);
4538
		     return 1;
4539
	    default: break;
4540
          };
4541
        };
4542
 
4543
	settest_number(e, nt);
4544
 
4545
		/* evaluate constant expressions */
4546
 
4547
	if ((name (arg1) == val_tag || name (arg1) == null_tag) &&
4548
	    (name (arg2) == val_tag || name (arg2) == null_tag)) {
4549
	  /* see if we know which way to jump and replace by unconditional
4550
	     goto or nop. For integers. */
4551
	  int c = docmp_f ((int)test_number (e), arg1, arg2);
4552
 
4553
	  if (c)
4554
	    repbycont (e, 1, scope);
4555
	  else
4556
	    repbygo (e, pt (e), scope);
4557
	  return (1);
4558
	};
4559
        if (test_number (e) >= 5 &&
4560
            ((name(arg1) == null_tag && no(arg1) == 0 &&
4561
		name(arg2) == name_tag &&
4562
		isvar(son(arg2))) ||
4563
            (name(arg2) == null_tag && no(arg2) == 0 &&
4564
		name(arg1) == name_tag &&
4565
		isvar(son(arg1)))))  {
4566
		/* if we are comparing null with a variable we
4567
		   know the way to jump. */
4568
          if (test_number(e) == 6)
4569
             repbycont(e, 1, scope);
4570
          else
4571
             repbygo(e, pt(e), scope);
4572
          return 1;
4573
        };
4574
	if (name (arg1) == real_tag && name (arg2) == real_tag &&
4575
	     test_number(e) <= 6) {
4576
	  /* similar for reals */
4577
	  if (cmpflpt (no (arg1), no (arg2), (int)(test_number (e))))
4578
	    repbycont (e, 1, scope);
4579
	  else
4580
	    repbygo (e, pt (e), scope);
4581
	  return (1);
4582
	};
4583
 
4584
		/* end of constant expression evaluation */
4585
 
4586
	if (name(arg1) == val_tag || name(arg1) == real_tag ||
4587
		name(arg1) == null_tag) {
4588
		/* constant argument always second */
4589
	  son(e) = arg2;
4590
	  bro(arg2) = arg1;
4591
	  bro(arg1) = e;
4592
	  setlast(arg1);
4593
	  clearlast(arg2);
4594
	  arg2 = arg1;
4595
	  arg1 = son(e);
4596
	  nt = exchange_ntest[nt];
4597
	  settest_number(e, nt);
4598
	};
4599
 
4600
	if (name (arg1) == chvar_tag && name (arg2) == chvar_tag &&
4601
	    name (sh (son (arg1))) == name (sh (son (arg2))) &&
4602
	    shape_size (sh (son (arg1))) <= shape_size (sh (arg1)) &&
4603
 
4604
#if only_lengthen_ops
4605
	    shape_size(sh (arg1)) >= 16 &&
4606
#endif
4607
	    (is_signed(sh (son (arg1))) == is_signed(sh (arg1)))
4608
	  ) {
4609
	  exp ee;
4610
#if is80x86 || ishppa
4611
	/* optimise if both args are result of sign extension removal */
4612
	    if ((test_number(e) == f_equal ||
4613
			 test_number(e) == f_not_equal) &&
4614
		name(sh(arg1)) == slonghd &&
4615
		name(son(arg1)) == cont_tag &&
4616
		name(son(arg2)) == cont_tag &&
4617
		shape_size(sh (son(arg1))) == 16 &&
4618
		name(son(son(arg1))) == name_tag &&
4619
		name(son(son(arg2))) == name_tag) {
4620
	      exp dec1 = son(son(son(arg1)));
4621
	      exp dec2 = son(son(son(arg2)));
4622
	      if (isse_opt(dec1) && isse_opt(dec2)) {
4623
		son(e) = son(arg1);
4624
		sh(son(arg1)) = slongsh;
4625
		clearlast(son(arg1));
4626
		bro(son(arg1)) = son(arg2);
4627
		sh(son(arg2)) = slongsh;
4628
		setlast(son(arg2));
4629
		bro(son(arg2)) = e;
4630
		return 0;
4631
	      };
4632
	    };
4633
#endif
4634
	  /* arrange to do test in smallest size integers by removing
4635
	     chvar and altering shape of test args */
4636
	  ee = copyexp (e);
4637
	  son (ee) = son (arg1);
4638
	  bro (son (arg1)) = son (arg2);
4639
	  clearlast (son (arg1));
4640
	  replace (e, hc (ee, bro (son (ee))), scope);
4641
	  retcell (arg1);
4642
	  retcell (arg2);
4643
	  retcell (e);
4644
	  return (1);
4645
	};
4646
#if little_end & has_byte_ops
4647
	/* only for little enders with byte and short operations */
4648
	if (name (arg2) == val_tag && !isbigval(arg2) && no (arg2) == 0 &&
4649
	    name (arg1) == and_tag &&
4650
	    test_number (e) >= 5) {
4651
	  /* e = test(val, and(a,b)) and test is == or != */
4652
	  exp r, t, q;
4653
	  if (last (bro (son (arg1)))) {
4654
	    if (name (son (arg1)) == chvar_tag &&
4655
		name (bro (son (arg1))) == val_tag) {
4656
	      /* e = test(val, and(chvar(x),val)) */
4657
	      exp v = bro (son (arg1));
4658
	      sh (v) = sh (son (son (arg1)));
4659
	      son (arg1) = son (son (arg1));
4660
	      clearlast (son (arg1));
4661
	      bro (son (arg1)) = v;
4662
	    };
4663
	    r = getexp (f_top, nilexp, 0, son (arg1), pt (e), 0,
4664
		0, testbit_tag);
4665
	    no(r) = no(e);
4666
            settest_number(r, test_number(e));
4667
	    replace (e, hc (r, bro (son (r))), scope);
4668
	    retcell (e);
4669
	    return (1);
4670
	  };
4671
 
4672
	  t = son (arg1);
4673
	  while (!last (bro (t)))
4674
	    t = bro (t);
4675
	  q = bro (t);
4676
	  setlast (t);
4677
	  bro (t) = arg1;
4678
	  r = getexp (f_top, nilexp, 0, q, pt (e), 0,
4679
	      0, testbit_tag);
4680
	  no(r) = no(e);
4681
          settest_number(r, test_number(e));
4682
	  clearlast (q);
4683
	  bro (q) = arg1;
4684
	  setlast (arg1);
4685
	  bro (arg1) = r;
4686
	  replace (e, r, scope);
4687
	  retcell (e);
4688
	  return (1);
4689
	};
4690
	/* use if little end machine */
4691
	if (
4692
	    name (arg2) == val_tag && !isbigval(arg2) &&
4693
	    ((name (arg1) == chvar_tag &&
4694
	      name (sh (arg1)) > name (sh (son (arg1))) &&
4695
	      is_signed (sh (arg1)) == is_signed (sh (son (arg1)))) ||
4696
	    (name (arg1) == bitf_to_int_tag &&
4697
	      name (son (arg1)) == cont_tag &&
4698
	      (shape_size(sh (son (arg1))) == 8 ||
4699
                   shape_size(sh (son (arg1))) == 16) &&
4700
	      name (son (son (arg1))) == reff_tag &&
4701
	      (no (son (son (arg1))) & 7) == 0
4702
	    ))
4703
	  ) {
4704
	  /* e = test(chvar(x), val) and chvar lengthens */
4705
	  n = no (arg2);
4706
	  switch (shape_size(sh (son (arg1)))) {
4707
	    case 8:
4708
             if (is_signed(sh(son(arg1)))) {
4709
	      bl = (n >= -128) & (n <= 127);
4710
	      break;
4711
              }
4712
	     else {
4713
	      bl = (n >= 0) & (n <= 255);
4714
	      break;
4715
             };
4716
	    case 16:
4717
             if (is_signed(sh(son(arg1)))) {
4718
	      bl = (n >= -32768) & (n <= 32767);
4719
	      break;
4720
             }
4721
	     else
4722
              {
4723
	      bl = (n >= 0) & (n <= 65536);
4724
	      break;
4725
              };
4726
	    default:
4727
	      bl = 0;
4728
	      break;
4729
	  };
4730
	  if (bl) {
4731
	    exp ee = copyexp (e);
4732
	    son (ee) = son (arg1);
4733
	    bro (son (arg1)) = arg2;
4734
	    clearlast (son (arg1));
4735
	    sh (arg2) = sh (son (arg1));
4736
	    replace (e, hc (ee, bro (son (ee))), scope);
4737
	    retcell (arg1);
4738
	    retcell (e);
4739
	    return (1);
4740
	  };
4741
	  return (0);
4742
	};
4743
 
4744
        if (name(arg2) == val_tag && !isbigval(arg2) && no(arg2) == 0 &&
4745
            test_number (e) >= 5 &&
4746
            name(arg1) == bitf_to_int_tag && shape_size(sh(arg1)) == 32 &&
4747
            name(son(arg1)) == cont_tag &&
4748
            name(son(son(arg1))) == reff_tag)  {
4749
          exp rf = son(son(arg1));
4750
 
4751
          if (al1(sh(son(rf))) >=32)  {
4752
            int pos = no(rf) % 32;
4753
            exp c = son(arg1);
4754
            int nbits = shape_size(sh(c));
4755
            exp r;
4756
 
4757
            no(rf) -= pos;
4758
            sh(rf) = getshape(0, const_al32, const_al32, PTR_ALIGN,
4759
				 PTR_SZ, ptrhd);
4760
            sh(c) = slongsh;
4761
 
4762
            if (no(rf) == 0)
4763
              {
4764
                sh(son(rf)) = sh(rf);
4765
                son(c) = son(rf);
4766
                setfather(c, son(c));
4767
              };
4768
 
4769
            sh(arg2) = slongsh;
4770
            no(arg2) = ~(-(1 << nbits)) << pos;
4771
 
4772
	    r = getexp (f_top, nilexp, 0, c, pt (e), 0,
4773
		0, testbit_tag);
4774
	    no(r) = no(e);
4775
            settest_number(r, test_number(e));
4776
            clearlast(c);
4777
            bro(c) = arg2;
4778
            replace(e, hc(r, arg2), scope);
4779
            retcell(e);
4780
            return 1;
4781
          };
4782
        };
4783
 
4784
	if (name(arg1) == shr_tag && name(arg2) == val_tag &&
4785
		no(arg2) == 0 && nt >= 5) {
4786
	  exp arg11 = son(arg1);
4787
	  exp arg12 = bro(arg11); /* no of places shifted right */
4788
	  if (name(arg11) == shl_tag && name(arg12) == val_tag) {
4789
	    exp arg111 = son(arg11);
4790
	    exp arg112 = bro(arg111); /* no places shifted left */
4791
	    if (name(arg112) == val_tag && no(arg112) <= no(arg12)) {
4792
 
4793
	      int n2 = no(arg12);  /* right shift */
4794
	      int n12 = no(arg112); /* left shift */
4795
	      int sz = shape_size(sh(arg1));
4796
	      int mask = ((1 << (sz - n2)) - 1) << (n2 - n12);
4797
	      exp res = me_b3(sh(arg1), arg111,
4798
				 me_shint(sh(arg1), mask), and_tag);
4799
	      res = hold_check(res);
4800
	      replace(arg1, res, res);
4801
	      return check(e, scope);
4802
	    };
4803
	  };
4804
	};
4805
 
4806
	if (name(arg1) == chvar_tag && name(arg2) == val_tag &&
4807
		!isbigval(arg2) &&
4808
		shape_size(sh(arg1)) > shape_size(sh(son(arg1))) &&
4809
		name(son(arg1)) == cont_tag &&
4810
		(name(son(son(arg1))) != name_tag ||
4811
		    !isvar(son(son(son(arg1)))))) {
4812
	  exp q = son(arg1);
4813
	  shape sha = sh(q);
4814
	  int shsz = shape_size(sha);
4815
	  int n = no(arg2);
4816
	  if (n >= 0 &&
4817
		is_signed(sha) == is_signed(sh(arg1)) &&
4818
		 ((shsz == 16 && n <= 32768) ||
4819
			(shsz == 8 && n <= 128))) {
4820
	    sh(arg2) = sha;
4821
	    son(e) = q;
4822
	    clearlast(q);
4823
	    bro(q) = arg2;
4824
	    retcell(arg1);
4825
	    return 1;
4826
	  };
4827
	};
4828
 
4829
 
4830
#endif
4831
	return (seq_distr (e, scope));
4832
      };
4833
    case solve_tag: {		/* eliminate dead code */
4834
	exp t = son (e);
4835
	exp q;
4836
	int changed = 0;
4837
	int looping;
4838
 
4839
	if (last (t)) {
4840
#ifdef NEWDIAGS
4841
	  if (diagnose)
4842
	    dg_whole_comp (e, t);
4843
#endif
4844
	  replace (e, copy(t), scope);
4845
	  kill_exp(e, e);
4846
	  return (1);
4847
	};
4848
 
4849
	if (name(t) == goto_tag && no(son(pt(t))) == 1) {
4850
	  exp lab = pt(t);
4851
	  q = bro(t);
4852
	  while (q != e) {
4853
	    if (q == lab)
4854
	      break;
4855
	    q = bro(q);
4856
	  };
4857
	  if (q != e) {
4858
	    exp rep = copy(bro(son(lab)));
4859
#ifdef NEWDIAGS
4860
	/* note copy, in case original is removed !!!!!!!!!!!!!!!!!!!!!!!!!!! */
4861
#endif
4862
	    replace(t, rep, rep);
4863
	    kill_exp(t, t);
4864
	    t = rep;
4865
	  };
4866
	};
4867
 
4868
	do {
4869
	  if (no (son (bro (t))) == 0) {
4870
	    changed = 1;
4871
	    q = bro (t);
4872
	    bro (t) = bro (q);
4873
	    if (last (q))
4874
	      setlast (t);
4875
	    else
4876
	      clearlast (t);
4877
#ifdef NEWDIAGS
4878
	    if (diagnose)
4879
	      dg_dead_code (bro(son(q)), t);
4880
#endif
4881
	    kill_exp (q, q);
4882
	    looping = !last(t);
4883
	  }
4884
	  else {
4885
	    looping = !last (bro (t));
4886
	    t = bro (t);
4887
	  };
4888
	}
4889
	while (looping);
4890
 
4891
	if (last (son (e))) {
4892
#ifdef NEWDIAGS
4893
	  if (diagnose)
4894
	    dg_whole_comp (e, son(e));
4895
#endif
4896
	  replace (e, copy(son (e)), scope);
4897
	  kill_exp(e,e);
4898
	  return (1);
4899
	};
4900
 
4901
	if (changed)
4902
	  return (1);
4903
	return (0);
4904
      };
4905
    case case_tag:
4906
      if (name (son (e)) == val_tag ) {
4907
	/* if we know the case argument select the right case branch and
4908
	   replace by goto. Knock on effect will be to eliminate dead
4909
	   code. */
4910
	exp  n = son (e);
4911
	int changed = 0;
4912
	exp t = son (e);
4913
	exp z;
4914
	do {
4915
	  exp  up;
4916
	  t = bro (t);
4917
	  if (son (t) == nilexp)
4918
	    up = t;
4919
	  else
4920
	    up = son (t);
4921
 
4922
	  if (docmp_f((int)f_less_than_or_equal, t, n) &&
4923
		docmp_f((int)f_less_than_or_equal, n, up)) {
4924
	    changed = 1;
4925
	    z = pt(t);
4926
	  }
4927
/*	  else
4928
	    --no (son (pt (t)));
4929
*/
4930
	}
4931
	while (!last (t));
4932
 
4933
	if (!changed)
4934
	  repbycont (e, 0, scope);
4935
	else {
4936
	  SET(z);
4937
	  repbygo (e, z, scope);
4938
	};
4939
	return (1);
4940
      };
4941
      return (0);
4942
    case rep_tag:
4943
    case apply_general_tag:
4944
    case set_stack_limit_tag:
4945
    case give_stack_limit_tag:
4946
    case env_size_tag:
4947
    case apply_tag:
4948
    case res_tag:
4949
    case goto_lv_tag:
4950
    case assvol_tag:
4951
    case local_free_all_tag:
4952
    case local_free_tag:
4953
    case last_local_tag:
4954
    case long_jump_tag:
4955
    case movecont_tag:
4956
      return (0);
4957
    case alloca_tag:
4958
      if (name(son(e)) == chvar_tag && name(sh(son(son(e)))) == ulonghd) {
4959
	replace(son(e), son(son(e)), son(e));
4960
      };
4961
      return (0);
4962
    case nof_tag:
4963
    case labst_tag:
4964
      return 0;
4965
    case concatnof_tag:
4966
	{
4967
	  exp a1 = son (e);
4968
	  exp a2 = bro (a1);
4969
          exp r;
4970
          nat n;
4971
	  if (name (a1) == string_tag &&
4972
	      name (a2) == string_tag) {
4973
	    /* apply if args constant */
4974
	    char *s1 = nostr(son(e));
4975
	    char *s2 = nostr(bro(son(e)));
4976
	    /* note NOT zero termination convention !! */
4977
	    int  sz1,
4978
	          sz2,
4979
	          i;
4980
	    char * newstr;
4981
	    char * p2;
4982
	    shape newsh;
4983
	    sz1 = shape_size(sh(son(e)))/8;
4984
	    sz2 = shape_size(sh(bro (son (e))))/8;
4985
	    newstr = (char *) xcalloc ( (sz1 + sz2), sizeof (char));
4986
	    p2 = &newstr[sz1];
4987
            nat_issmall(n) = 1;
4988
            natint(n) = sz1+sz2;
4989
	    newsh = f_nof (n, scharsh);
4990
	    for (i = 0; i < sz1; ++i)
4991
	      newstr[i] = s1[i];
4992
	    for (i = 0; i < sz2; ++i)
4993
	      p2[i] = s2[i];
4994
            r = getexp (newsh, nilexp, 0, nilexp,
4995
		     nilexp, 0, 0, string_tag);
4996
            nostr(r) = newstr;
4997
	    replace (e, r, scope);
4998
	    kill_exp (e, scope);
4999
	    return (1);
5000
	  };
5001
	  return 0;
5002
	};
5003
    case ncopies_tag:
5004
    case ignorable_tag:
5005
	return 0;
5006
    case bfass_tag:
5007
    case bfassvol_tag:
5008
	{
5009
	  exp p = son(e);
5010
	  exp val = bro(p);
5011
	  int bsz = shape_size(sh(val));
5012
	  int rsz;
5013
	  int rsh;
5014
	  int sg = is_signed(sh(val));
5015
	  int posmask;
5016
	  int negmask;
5017
	  int off = no(e);
5018
	  exp ref;
5019
	  exp cont;
5020
	  exp eshift;
5021
	  exp res;
5022
	  exp id;
5023
	  exp idval;
5024
	  shape ptr_sha;
5025
	  shape msh;
5026
	  int temp = off + bsz - 1;
5027
 
5028
	  if (((off/8) == (temp/8)) && bsz<=8
5029
#if 0
5030
		(bsz == 8 &&
5031
		    ((little_end && (off%8 == 0)) ||
5032
		      (!little_end && ((8 - (off % 8) - bsz) == 0))))
5033
#endif
5034
	        ) {
5035
	    rsz = 8;
5036
	    if (sg)
5037
	      msh = scharsh;
5038
	    else
5039
	      msh = ucharsh;
5040
	  }
5041
	  else
5042
	  if (((off/16) == (temp/16)) && bsz <= 16
5043
#if 0
5044
	        (bsz == 16 &&
5045
		   ((little_end && (off%16 == 0)) ||
5046
		     (!little_end && ((16 - (off % 16) - bsz) == 0))))
5047
#endif
5048
              ) {
5049
	    rsz = 16;
5050
	    if (sg)
5051
	      msh = swordsh;
5052
	    else
5053
	      msh = uwordsh;
5054
	  }
5055
	  else
5056
	  if ((off/32) == (temp/32)) {
5057
	    rsz = 32;
5058
	    if (sg)
5059
	      msh = slongsh;
5060
	    else
5061
	      msh = ulongsh;
5062
	  }
5063
	  else {
5064
	    rsz = 64;
5065
	    if (sg)
5066
	      msh = s64sh;
5067
	    else
5068
	      msh = u64sh;
5069
	  };
5070
	  ptr_sha = f_pointer(long_to_al(rsz));
5071
 
5072
	  if ((off / rsz) != 0) {
5073
	    ref = me_u3(ptr_sha, p, reff_tag);
5074
	    no(ref) = (off / rsz) * rsz;
5075
	    ref = hold_check(ref);
5076
	  }
5077
	  else
5078
	    ref = p;
5079
	  id = me_startid(f_top, ref, 0);
5080
#if little_end
5081
	  rsh = off % rsz;
5082
#else
5083
	  rsh = rsz - (off % rsz) - bsz;
5084
#endif
5085
	  posmask = (bsz == 32) ? -1 : (1 << bsz) -1;
5086
	  negmask = ~(posmask << rsh);
5087
	  cont = me_u3(msh, me_obtain(id),
5088
		        (name(e) == bfass_tag)
5089
			  ? (unsigned char)cont_tag
5090
			  : (unsigned char)contvol_tag);
5091
	  val = hold_check(me_u3(msh, val, chvar_tag));
5092
	  val = hold_check(me_b3(msh, val,
5093
				 me_shint(msh, posmask), and_tag));
5094
	  if (rsh != 0)
5095
	    eshift =
5096
	     hold_check(me_b3(msh, val, me_shint(slongsh, rsh), shl_tag));
5097
	  else {
5098
	    eshift = val;
5099
	    sh(eshift) = msh;
5100
	  };
5101
	  idval = me_startid(f_top, eshift, 0);
5102
 
5103
	  if (rsz != bsz) {
5104
	    cont = me_b3(msh, cont, me_shint(msh, negmask), and_tag);
5105
	    cont = hold_check(me_b3(msh, cont, me_obtain(idval), or_tag));
5106
	  }
5107
	  else {
5108
	    kill_exp(cont, cont);
5109
	    cont = me_obtain(idval);
5110
	  };
5111
	  res = me_b3(f_top, me_obtain(id), cont,
5112
		      (name(e) == bfass_tag)
5113
		        ? (unsigned char)ass_tag
5114
			: (unsigned char)assvol_tag);
5115
	  res = hold_check(me_complete_id(idval, res));
5116
	  replace(e, hold_check(me_complete_id(id, res)), scope);
5117
	  retcell(e);
5118
	  return 1;
5119
	};
5120
    default:
5121
      return (0);
5122
  }
5123
}