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

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-amd64/src/installers/common/construct/check.c – Rev 6

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