Subversion Repositories tendra.SVN

Rev

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

Rev Author Line No. Line
2 7u83 1
/*
2
    		 Crown Copyright (c) 1997
3
 
4
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
12
 
13
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
15
 
16
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
19
 
20
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
22
        these conditions;
23
 
24
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
27
        it may be put.
28
*/
29
 
30
 
31
/**********************************************************************
32
$Author: release $
33
$Date: 1998/01/17 15:55:47 $
34
$Revision: 1.1.1.1 $
35
$Log: foralls.c,v $
36
 * Revision 1.1.1.1  1998/01/17  15:55:47  release
37
 * First version to be checked into rolling release.
38
 *
39
 * Revision 1.4  1997/02/18  12:56:25  currie
40
 * NEW DIAG STRUCTURE
41
 *
42
 * Revision 1.3  1996/12/19  14:28:35  currie
43
 * Foralls - using two counters
44
 *
45
Revision 1.2  1995/06/26 13:04:35  currie
46
make_stack_limit, env_size etc
47
 
48
 * Revision 1.1  1995/04/06  10:44:05  currie
49
 * Initial revision
50
 *
51
***********************************************************************/
52
 
53
 
54
 
55
#include "config.h"
56
#include "common_types.h"
57
#include "tags.h"
58
#include "expmacs.h"
59
#include "exp.h"
60
#include "check.h"
61
#include "shapemacs.h"
62
#include "check_id.h"
63
#include "install_fns.h"
64
#include "const.h"
65
#include "constmacs.h"
66
#include "flags.h"
67
#include "me_fns.h"
68
#include "basicread.h"
69
#include "xalloc.h"
70
#include "externs.h"
71
#include "foralls.h"
72
 
73
#define subvar 0x100
74
 
75
#define false 0
76
#define true  1
77
 
78
#define topsh f_top
79
 
80
#ifndef Assert
81
#if FS_STDC_HASH
82
#define Assert(x) if(!(x)) failer(#x)
83
#else
84
#define Assert(x) if(!(x)) failer("x")
85
#endif
86
#endif
87
 
88
exp * ifc_ptr_position
89
    PROTO_N ( (e) )
90
    PROTO_T ( exp e )
91
{
92
	exp * a;
93
	exp dad = father(e);
94
	if (son(dad)==e) {
95
		a = &son(dad);
96
	}
97
	else {
98
		exp sib = son(dad);
99
		while (bro(sib)!=e) { sib = bro(sib); }
100
		a = &bro(sib);
101
	}
102
	return a;
103
}
104
 
105
static exp * position
106
    PROTO_N ( (e) )
107
    PROTO_T ( exp e )
108
{
109
	exp dad = father(e);
110
	exp *res = &son(dad);
111
	while (*res != e) res = &bro(*res);
112
	return res;
113
}
114
 
115
int incr_var
116
    PROTO_N ( (e) )
117
    PROTO_T ( exp e )
118
{
119
	/* is e  var = var + val; */
120
	exp dest;
121
	exp src;
122
	if(name(e) != ass_tag) return false;
123
	dest = son(e);
124
	src = bro(dest);
125
	return (name(dest)==name_tag &&
126
                name(src)==plus_tag &&
127
                name(son(src))==name_tag &&
128
		name(bro(son(src)))==val_tag &&
129
                last(bro(son(src))) &&
130
		son(dest)==son(son(src)) &&
131
                no(dest) == no(son(src))
132
               );
133
}
134
 
135
exp alteredset = nilexp;
136
 
137
void isaltered
138
    PROTO_N ( (ld, always) )
139
    PROTO_T ( exp ld X int always )
140
{
141
	/* make copy of name!! - can be killed later */
142
	exp z ;
143
	exp nld;
144
	for (z = alteredset; z!=nilexp; z=bro(z)) {
145
	     if (son(ld)==son(son(z)) &&
146
		    (name(son(ld))!=proc_tag || no(ld) == no(son(z)) ) ){
147
		props(z) &= (prop)always;
148
		return;
149
	     }
150
	}
151
	nld = getexp(sh(ld), alteredset, 1, son(ld), nilexp,
152
                                             props(ld), no(ld), name(ld));
153
	alteredset = getexp(nilexp, alteredset, alteredset==nilexp,
154
                                                nld, nilexp, (prop)always,0,0);
155
}
156
 
157
int assign_alias;
158
int jump_out;
159
 
160
void scan_for_incr
161
    PROTO_N ( (e, piece, f) )
162
    PROTO_T ( exp e X exp piece X void (*f) PROTO_S ((exp,int)) )
163
{
164
	/* applies f to all (var = var + val) done  in piece with bool set if
165
			always done.
166
		where var is non-local of piece but non-global and not
167
		aliased and all other uses in piece are cont(var)
168
	   also applies altered to  named variables (name_tag) which are
169
		assigned to, either in toto or by indexing.
170
	   if there are any other assign_alias is set true
171
	*/
172
    static int everytime = true;
173
    switch (name(e)){
174
	case name_tag: case env_offset_tag: return;
175
	case ass_tag:{
176
	   exp dest = son(e);
177
	   exp src = bro(son(e));
178
	   if (name(dest)== name_tag  &&
179
               isvar(son(dest)) &&
180
               !isglob(son(dest)) &&
181
	       iscaonly(son(dest)) &&
182
               name(src) == plus_tag )
183
	       {exp la = son(src);
184
		exp ra = bro(son(src));
185
		if (last(ra) && name(ra)==val_tag &&
186
                    name(la) == cont_tag &&
187
	            name(son(la)) == name_tag &&
188
                    son(son(la))== son(dest) &&
189
	            no(dest) == no(son(la)) &&
190
                    !intnl_to(piece, son(dest)) )
191
		    {exp p = pt(son(dest)); /*uses of var */
192
		     for(; p!=nilexp; p = pt(p))
193
#ifdef NEWDIAGS
194
			{if (isdiaginfo(p) || p==dest || p == son(la) ||
195
#else
196
			{if (p==dest || p == son(la) ||
197
#endif
198
				 (last(p) && name(bro(p))==cont_tag) ||
199
				 incr_var(father(p)) ||
200
				 !intnl_to(piece, p))
201
			     {continue;}
202
			 goto tryalias;
203
		        }
204
		     f(e, everytime); return;
205
		    }
206
	      }
207
	tryalias:
208
	   if (name(dest) == name_tag && isvar(son(dest)) ) {
209
		isaltered(dest, everytime);
210
	   }
211
	   else
212
	   if (name(dest) == addptr_tag && name(son(dest))==name_tag
213
		&& isvar(son(son(dest))) ){
214
		isaltered(son(dest), everytime);
215
	   }
216
	   else
217
	   if (name(dest)==reff_tag &&
218
               name(son(dest))== addptr_tag &&
219
	       name(son(son(dest))) == name_tag &&
220
               isvar(son(son(son(dest)))) )
221
		{isaltered(son(son(dest)), everytime);}
222
	   else
223
	   if (name(dest) == name_tag &&
224
		( props(son(dest)) & 0x10) !=0 /* const in some loop */ ) {
225
		exp def = son(son(dest));
226
	   	if (name(def) == reff_tag) def = son(def);
227
	 	if (name(def) == addptr_tag && name(son(def)) == name_tag &&
228
			isvar(son(son(def))) ) {
229
			isaltered(dest, everytime);
230
		}
231
		else assign_alias = true;
232
	   }
233
	   else assign_alias = true;
234
	   scan_for_incr(dest, piece, f);
235
	   scan_for_incr(src, piece, f);
236
	   return ;
237
	}
238
 
239
	case case_tag: {
240
		scan_for_incr(son(e), piece, f);
241
		everytime = false;
242
		return;
243
	}
244
 
245
	case goto_tag: case testbit_tag:
246
	case test_tag: {
247
		int x = intnl_to(piece, pt(e));
248
		if (!x) jump_out = true;
249
		if (son(e)!=nilexp) scan_for_incr(son(e), piece, f);
250
		everytime = (everytime && !x);
251
		return;
252
	}
253
	case res_tag: {
254
		jump_out = true;
255
		scan_for_incr(son(e), piece, f);
256
		return;
257
	}
258
	case solve_tag: case rep_tag: case cond_tag: {
259
	        exp z = son(e);
260
		int et = everytime;
261
		for(;;) {
262
			scan_for_incr(z, piece, f);
263
			everytime = false;
264
			if (last(z)) break;
265
			z=bro(z);
266
		}
267
		everytime = et;
268
		return;
269
	}
270
 
271
	case apply_tag: assign_alias = true; /* and do default */
272
	default: {
273
	    exp z = son(e);
274
	    if (z==nilexp) return;
275
	    for(;;) {
276
		scan_for_incr(z, piece, f);
277
		if (last(z)) return;
278
		z = bro(z);
279
	    }
280
	}
281
    }
282
}
283
 
284
 
285
int good_val
286
    PROTO_N ( (a, piece) )
287
    PROTO_T ( exp a X exp piece )
288
{
289
	/* result ((a is name external to piece)
290
           || (a is cont(name) where all uses of name in piece is cont))
291
	*/
292
     if (name(a)==name_tag) {
293
	return (!intnl_to(piece, son(a)));
294
     }
295
     else
296
     if (name(a)==cont_tag && name(son(a))==name_tag &&
297
		!intnl_to(piece, son(son(a))) && !isvis(son(son(a)))) {
298
	exp lda = son(a);
299
	exp pa = pt(son(lda));
300
	for(; pa!=nilexp; pa = pt(pa)) {
301
#ifdef NEWDIAGS
302
	     if (isdiaginfo(pa) || pa==lda || no(pa) != no(lda) ||
303
#else
304
	     if (pa==lda || no(pa) != no(lda) ||
305
#endif
306
		   (last(pa) && name(bro(pa))==cont_tag) ||
307
			!intnl_to(piece, pa) ) continue;
308
	     break;
309
	}
310
	return (pa==nilexp);
311
     }
312
     return false;
313
}
314
 
315
int usage_in
316
    PROTO_N ( (whole, part) )
317
    PROTO_T ( exp whole X exp part )
318
{
319
  exp q = part;
320
  int res = 1;
321
  int n = (int)name(q);
322
  while (q != whole && q != nilexp &&
323
      (n != ident_tag || (props (q) & 0x40) == 0)) {
324
    q = father (q);
325
    n = (int)name(q);
326
    if(n==cond_tag || n==rep_tag || n==solve_tag) res=2;
327
  }
328
 
329
 
330
  return (q == whole)?res:0;
331
}
332
 
333
int stride;
334
/* 0 initially, -1 either no common stride or non-constant stride,
335
               otherwise contains common stride. */
336
 
337
int find_common_index
338
    PROTO_N ( (ldname, piece, f) )
339
    PROTO_T ( exp ldname X exp piece X void (*f) PROTO_S ((exp,int)) )
340
{
341
 
342
	/* applies f to all addptr(x, cont(varid)) in piece
343
			where good_index_factor(1)
344
		     and all addptr(x, mult(cont(varid), mval))
345
			where good_index_factor(mval) and
346
		     and all test(cont(varid), val -> outside piece)
347
	 	   with bool if it is done exactly once.
348
                   if different multiply facters are detected or
349
                   a multiplying factor is not good then stride is
350
                   set to -1 and the procedure returned from.
351
                stride holds the common multiplying factor, initially
352
                being 0.
353
		where x is  name external to piece
354
		or x is cont(name) where name is external to piece and
355
		    all uses in piece are cont(name) NB no alias check
356
		result is no of other uses of varid in piece
357
	*/
358
     exp p = pt(son(ldname));
359
     int otheruses = 0;
360
     for(; p!=nilexp; p = pt(p)) { /* examine each use of loop variable */
361
	int usagex;
362
#ifdef NEWDIAGS
363
	if (isdiaginfo(p)) continue;
364
#endif
365
	if (no(p)!=no(ldname)) continue;
366
	usagex = usage_in(piece, p);
367
	if (usagex==0) continue;
368
	otheruses++;
369
	if (last(p) && name(bro(p))==cont_tag ) {
370
	     exp dad = father(bro(p));
371
             if (!good_index_factor(1))
372
                {stride = -1; UNUSED(dad); UNUSED(f); return 0;}
373
	     if (name(dad) == addptr_tag &&
374
                 bro(son(dad))==bro(p) &&
375
                 last(bro(p))
376
	        ) {
377
		if(good_val(son(dad), piece))
378
                   { f(dad,usagex==1);
379
                     otheruses--;
380
                     if (stride==0) stride=1;
381
                     else if (stride>1) stride = -1; UNUSED(f); return 0;
382
                   }
383
	     }
384
	     else
385
	     if (name(dad)==offset_mult_tag &&
386
                 son(dad)==bro(p) &&
387
                 name(bro(son(dad)))==val_tag &&
388
	         last(dad)
389
                )
390
	       {exp grandad = father(dad);
391
                if (!good_index_factor(no(bro(son(dad)))/8))
392
                    {stride = -1; UNUSED(grandad); return 0;}
393
		if (name(grandad)==addptr_tag &&
394
                    bro(son(grandad)) == dad &&
395
                    last(dad))
396
		    {if(good_val(son(grandad), piece))
397
			 {f(grandad,usagex==1);
398
                          otheruses--;
399
                          if (stride==0) stride=no(bro(son(dad)))/8;
400
                          else if (stride!=no(bro(son(dad)))/8)
401
                              {stride = -1; return 0;}
402
                           /*printf("stride=%d\n",stride);*/
403
                         }
404
		    }
405
	       }
406
	     else
407
	     if ((name(dad)==test_tag || name(dad)==testbit_tag)
408
			 && piece == bro(son(pt(dad))) )
409
		{f(dad, usagex==1); otheruses--;}
410
	}
411
     }
412
      return otheruses;
413
}
414
 
415
int find_pointer_opt
416
    PROTO_N ( (ldname, piece, f) )
417
    PROTO_T ( exp ldname X exp piece X void (*f) PROTO_S ((exp,int)) )
418
{
419
 
420
	/* applies f to all addptr(x, cont(varid)) in piece
421
			where good_pointer_factor(1)
422
		     and all addptr(x, mult(cont(varid), mval))
423
			where good_pointer_factor(mval) and
424
		     and all test(cont(varid), val -> outside piece)
425
	 	   with bool if it is done exactly once.
426
		where x is  name external to piece
427
		or x is cont(name) where name is external to piece and
428
		    all uses in piece are cont(name) NB no alias check
429
		result is no of other uses of varid in piece
430
	*/
431
     exp p = pt(son(ldname));
432
     int otheruses = 0;
433
     for(; p!=nilexp; p = pt(p)) { /* examine each use of loop variable */
434
	int usagex;
435
#ifdef NEWDIAGS
436
	if (isdiaginfo(p)) continue;
437
#endif
438
	if (no(p)!=no(ldname)) continue;
439
	usagex = usage_in(piece, p);
440
	if (usagex==0) continue;
441
	otheruses++;
442
	if (last(p) && name(bro(p))==cont_tag ) {
443
	     exp dad = father(bro(p));
444
	     if (name(dad) == addptr_tag &&
445
                 bro(son(dad))==bro(p) &&
446
                 last(bro(p)) &&
447
	         good_pointer_factor(1)) {
448
		if(good_val(son(dad), piece))
449
                   { f(dad,usagex==1);
450
                     otheruses--;
451
		     if (stride==0){ stride=1;}
452
		     else
453
		     if (stride>1) {stride = -1;}
454
                   }
455
	     }
456
	     else
457
	     if (name(dad)==offset_mult_tag &&
458
                 son(dad)==bro(p) &&
459
                 simple_const(piece,bro(son(dad)),false,!assign_alias) &&
460
	         last(dad) &&
461
                 (name(bro(son(dad)))!=val_tag ||
462
                  good_pointer_factor(no(bro(son(dad)))/8)
463
                 )
464
                )
465
	       {exp grandad = father(dad);
466
		if (name(grandad)==addptr_tag &&
467
                    bro(son(grandad)) == dad &&
468
                    last(dad))
469
		    {if(good_val(son(grandad), piece))
470
			 {int n =  -1;
471
			  f(grandad,usagex==1);
472
                          otheruses--;
473
			  if (name(bro(son(dad)))==val_tag) {
474
				n = no(bro(son(dad)))/8;
475
			  }
476
			  else
477
			  if (name(bro(son(dad))) == name_tag) {
478
				exp id = son(bro(son(dad)));
479
				if (name(son(id))==val_tag) {
480
					n = no(son(id));
481
				}
482
			  }
483
 
484
			  if (stride==0) { stride = n; }
485
			  else if (stride != n) { stride = -1; }
486
                         }
487
		    }
488
	       }
489
	     else
490
	     if (name(dad)==test_tag && piece == bro(son(pt(dad))) )
491
		{f(dad, usagex==1); otheruses--;}
492
	}
493
     }
494
      return otheruses;
495
}
496
 
497
exp addptrs;
498
/* nilexp  initially */
499
	/* son = addptr exp;
500
	   pt = [holder with son = different occurence of addptr exp]**(no-1)
501
			chained through ptr
502
	   props =1 if done exactly once
503
	   other addptrs chained similarly through bro
504
	*/
505
 
506
exp tests;
507
/* nilexp initially */
508
	/* son = test
509
	   pt = [holder with son = different occurence of test]**(no-1)
510
	   props = 1 if done exactly once
511
	   other tests chained similarly through bro
512
	*/
513
 
514
void collect_loopthings
515
    PROTO_N ( (ind, everytime) )
516
    PROTO_T ( exp ind X int everytime )
517
{
518
	/* builds addptrs and tests*/
519
	exp z;
520
	exp * loopthing = (name(ind)==test_tag)? &tests: &addptrs;
521
	for(z= *loopthing; z!=nilexp; z= bro(z)) {
522
		if (eq_exp(son(z), ind)) {
523
			exp n = getexp(topsh, nilexp, 0, ind, pt(z),0,0, 0);
524
			pt(z) =n;
525
			no(z)++;
526
			props(z) &= (prop)everytime;
527
		   	return;
528
		}
529
	}
530
	*loopthing = getexp(topsh, *loopthing, *loopthing==nilexp, ind,
531
				 nilexp, (prop)everytime, 1, 0);
532
 
533
}
534
 
535
 
536
exp incrs;
537
/* nilexp initially */
538
	/* son = (v=v+val) exp;
539
	   pt = [holder with son = different occurence with same v]**(no-1)
540
			chained through pt
541
	   props = 1 if done exactly once
542
	   other (v=v+val)s chained similarly through bro
543
	*/
544
 
545
int maybe_incr
546
    PROTO_N ( (e) )
547
    PROTO_T ( exp e )
548
{
549
	exp incs = incrs;
550
	if (name(e) == cont_tag) {
551
		e = son(e);
552
	}
553
	if (name(e) != name_tag) return 1;
554
	while (incs != nilexp) {
555
		exp dest = son(son(incs));
556
		Assert(name(dest) == name_tag);
557
		if (son(dest)==son(e)) return 1;
558
		incs = bro(incs);
559
	}
560
	return 0;
561
}
562
 
563
void collect_incrs
564
    PROTO_N ( (incr, everytime) )
565
    PROTO_T ( exp incr X int everytime )
566
{
567
	/* builds incrs */
568
	exp z;
569
	for(z=incrs; z!=nilexp; z= bro(z)) {
570
		if (son(son(son(z))) == son(son(incr))
571
			&& no(son(son(z)))==no(son(incr))  ) {
572
			exp n = getexp(topsh, nilexp, 0, incr, pt(z), 0,0, 0);
573
			pt(z) =n;
574
			no(z)++;
575
			props(z) &= (prop)everytime;
576
		   	return;
577
		}
578
	}
579
 
580
	incrs = getexp(topsh, incrs, incrs==nilexp, incr,
581
				 nilexp, (prop)everytime, 1, 0);
582
 
583
}
584
 
585
 
586
/* transforms:
587
 
588
	strength reduction
589
		addptr(x, y) if x is invariant of loop
590
				ie x = simple var
591
				or x = cont(z) and z not altered in loop
592
			NB difference between invariant and not altered
593
 
594
 
595
*/
596
 
597
 
598
/* incr is only incrementer
599
   addptrset is holder of addptr
600
   loop is rep l:body
601
   exp * looppos = position(loop)
602
 
603
 
604
always construct
605
	Var X = add_ptr(x,y)
606
		replace all add_ptrs by cont(X) in addptrset and loopbpdy
607
		replace incr by {X = reff(inc)c(X); incr}
608
                                               retaining handle on incr
609
		shift looppos to body
610
 
611
	if always done and x not altered
612
		look for cont( ..reff(s) reff(s+inc) ...reff(s+n*inc) )
613
		replace loop by:
614
		   Var Ci[0..n-1] = cont(ref(s+i*inc)cont(X))
615
		   in loop with newbody:
616
			var Cn = cont(ref(s+n*inc)cont(X)) in
617
				body(reffn/Cn,  incr/{ Ci=C[i+1]; incr})
618
 
619
*/
620
 
621
static void extract_addptrs
622
    PROTO_N ( ( incr, addptrset, loop, inc, inci, cons ) )
623
    PROTO_T ( exp incr X exp addptrset X exp loop X exp inc X int inci X int cons )
624
{
625
	/* replace loop by :
626
	Var X = add_ptr(x,y) in newbody :
627
		replace all add_ptrs by cont(X) in addptrset and loopbpdy
628
		replace incr by {X = reff(inc)c(X); incr}
629
                                                 retaining handle on incr
630
		inc is in bytes.
631
 
632
	*/
633
	shape shvar = f_pointer(long_to_al(shape_align(sh(son(addptrset)))));
634
	exp id = getexp(sh(loop), bro(loop), last(loop), son(addptrset),
635
			   nilexp, 1 /*var*/, 0, ident_tag);
636
			/* setsib(son(id), loop); setdad(loop, id) later */
637
	int i;
638
	exp z = addptrset;
639
	exp * pos;
640
	exp ld, ass, reff, cont, seq, dest;
641
        exp incr_2, prod_2, neg_prod_2, mult_2;
642
	setcaonly(id);
643
	for(i=0; i<no(addptrset); i++) {
644
		/* replace addptrs by cont(ld(id)) */
645
	     exp sz = son(z) /*the addptr */;
646
	     cont = getexp(sh(son(id)), bro(sz), last(sz), nilexp, nilexp,
647
				0,0, cont_tag);
648
             ld = getexp(shvar, cont, 1, id, pt(id), 0, 0, name_tag);
649
	     pos = position(sz);
650
	     son(cont) = ld;
651
	     pt(id) = ld; no(id)++;
652
	     *pos = cont;
653
             son(z) = cont;
654
	     if (i!=0) { kill_exp(sz, nilexp); }
655
	     z = pt(z);
656
 
657
	}
658
 
659
	bro(son(id))= loop; clearlast(son(id));
660
	pos = position(loop);
661
        bro(loop) = id; setlast(loop);
662
	*pos = id;
663
if (cons || no(inc)!=0)
664
	{int mult = no(inc)*inci;
665
         if (cons) mult = inci*8;
666
         ld = getexp(shvar, nilexp, 1, id, pt(id), 0, 0, name_tag);
667
	pt(id) = ld; no(id)++;
668
	cont = getexp(sh(son(id)), nilexp, 1, ld, nilexp, 0,0, cont_tag);
669
	bro(ld) = cont;
670
	reff = getexp(sh(cont), nilexp, 1, cont, nilexp, 0, mult, reff_tag);
671
	bro(cont) = reff;
672
	dest = getexp(shvar, reff, 0, id, pt(id), 0, 0, name_tag);
673
	pt(id) = dest; no(id)++;
674
	ass = getexp(topsh, nilexp, 1, dest, nilexp, 0, 0, ass_tag);
675
	bro(reff) = ass;
676
	z = getexp(topsh, incr, 0, ass, nilexp, 0,0, 0);
677
	bro(ass) = z;
678
	seq = getexp(topsh, bro(incr), last(incr), z, nilexp, 0,0, seq_tag);
679
	pos = position(incr);
680
	bro(incr) = seq; setlast(incr);
681
	*pos = seq;}
682
 
683
else{        mult_2 = copy(inc);
684
        if (inci < 0)
685
         {incr_2 = getexp(sh(inc),nilexp,1,nilexp,nilexp,0,-inci,val_tag);
686
          bro(incr_2) = mult_2;
687
          clearlast(incr_2);
688
          neg_prod_2 = getexp(sh(inc), nilexp, 1, incr_2, nilexp,0,
689
                                                       0,offset_mult_tag);
690
          neg_prod_2 = hc(neg_prod_2,mult_2);
691
          prod_2 = getexp(sh(inc),nilexp,1,neg_prod_2,nilexp,0,0,neg_tag);
692
          bro(neg_prod_2) = prod_2;
693
         }
694
        else
695
         {incr_2 = getexp(sh(inc),nilexp,1,nilexp,nilexp,0,inci,val_tag);
696
          bro(incr_2) = mult_2;
697
          clearlast(incr_2);
698
          prod_2 = getexp(sh(inc),nilexp,0,incr_2,nilexp,0,0,offset_mult_tag);
699
          prod_2 = hc(prod_2,mult_2);
700
         }
701
        ld = getexp(shvar, nilexp, 1, id, pt(id), 0, 0, name_tag);
702
	pt(id) = ld; no(id)++;
703
	cont = getexp(sh(son(id)), nilexp, 0, ld, nilexp, 0,0, cont_tag);
704
	bro(ld) = cont;
705
	reff = getexp(sh(son(id)), nilexp, 1, cont, nilexp, 0, 0, addptr_tag);
706
        bro(cont) = prod_2;
707
	reff = hc(reff,prod_2);
708
	dest = getexp(shvar, reff, 0, id, pt(id), 0, 0, name_tag);
709
	pt(id) = dest; no(id)++;
710
	ass = getexp(topsh, nilexp, 1, dest, nilexp, 0, 0, ass_tag);
711
	bro(reff) = ass;
712
	z = getexp(topsh, incr, 0, ass, nilexp, 0,0, 0);
713
	bro(ass) = z;
714
	seq = getexp(topsh, bro(incr), last(incr), z, nilexp, 0,0, seq_tag);
715
	pos = position(incr);
716
	bro(incr) = seq; setlast(incr);
717
	*pos = seq;
718
    }
719
}
720
 
721
static void scale_loopid
722
    PROTO_N ( ( loop, addptrset, incrset) )
723
    PROTO_T ( exp loop X exp addptrset X exp incrset )
724
{
725
	/* replace loop body by :
726
	Var X = loopid*stride in newbody :
727
		replace all offset_mults by cont(X) in addptrset and loopbody
728
		replace incr by {X = c(X)+stride; incr}
729
                                                 retaining handle on incr
730
		inc is in bytes.
731
 
732
	*/
733
	exp id = getexp(sh(loop), bro(loop), last(loop), bro(son(son(addptrset))),
734
			   nilexp, 1 /*var*/, 0, ident_tag);
735
			/* setsib(son(id), loop); setdad(loop, id) later */
736
 
737
	exp * pos;
738
        exp incr = son(incrset);
739
        shape shvar = sh(son(bro(son(incr))));
740
	exp ld, ass, plus, cont, seq, dest, inc, z, next;
741
        while (addptrset != nilexp)
742
	{int i;
743
	z = addptrset;
744
        next = bro(addptrset);
745
	setcaonly(id);
746
	for(i=0; i<no(addptrset); i++) {
747
		/* replace addptrs by cont(ld(id)) */
748
	     exp sz = bro(son(son(z))) /* the offset_mult */;
749
	     cont = getexp(sh(son(id)), bro(sz), last(sz), nilexp, nilexp,
750
				0,0, cont_tag);
751
             ld = getexp(shvar, cont, 1, id, pt(id), 0, 0, name_tag);
752
	     pos = position(sz);
753
	     son(cont) = ld;
754
	     pt(id) = ld; no(id)++;
755
	     *pos = cont;
756
             bro(son(son(z))) = cont;
757
	     if (i!=0) { kill_exp(sz, nilexp); }
758
	     z = pt(z);
759
 
760
	}
761
        retcell(addptrset);
762
        addptrset = next;
763
        }
764
 
765
	bro(son(id))= loop; clearlast(son(id));
766
	pos = position(loop);
767
        bro(loop) = id; setlast(loop);
768
	*pos = id;
769
 
770
        inc = getexp(sh(son(id)),nilexp,1,nilexp,nilexp,0,
771
                  stride*8*no(bro(son(bro(son(son(incrset)))))),val_tag);
772
        ld = getexp(shvar, nilexp, 1, id, pt(id), 0, 0, name_tag);
773
	pt(id) = ld; no(id)++;
774
	cont = getexp(sh(son(id)), nilexp, 0, ld, nilexp, 0,0, cont_tag);
775
	bro(ld) = cont;
776
	plus = getexp(sh(cont), nilexp, 1, cont, nilexp, 0, 0, plus_tag);
777
	bro(cont) = inc;
778
        bro(inc) = plus;
779
	dest = getexp(shvar, plus, 0, id, pt(id), 0, 0, name_tag);
780
	pt(id) = dest; no(id)++;
781
	ass = getexp(topsh, nilexp, 1, dest, nilexp, 0, 0, ass_tag);
782
	bro(plus) = ass;
783
	z = getexp(topsh, incr, 0, ass, nilexp, 0,0, 0);
784
	bro(ass) = z;
785
	seq = getexp(topsh, bro(incr), last(incr), z, nilexp, 0,0, seq_tag);
786
	pos = position(incr);
787
	bro(incr) = seq; setlast(incr);
788
	*pos = seq;
789
}
790
 
791
 
792
exp inner_cont
793
    PROTO_N ( (loopbody, contset) )
794
    PROTO_T ( exp loopbody X exp contset )
795
{
796
 
797
/*
798
	son contset = cont(X); pt = next instance
799
	replace loopbody by Var Z = cont(X) in loopbody(cont(X)/cont(Z))
800
 
801
*/
802
 
803
	exp z = contset;
804
	exp *pos;
805
	int i;
806
	exp id = getexp(sh(loopbody), bro(loopbody), last(loopbody),
807
			     son(contset), nilexp, 1/*var*/, 0, ident_tag);
808
	setcaonly(id);
809
 
810
	for(i=0; z!=nilexp; i++) {
811
	    exp ld = getexp(sh(son(son(id))), nilexp, 1, id,
812
                                                   pt(id), 0, 0, name_tag);
813
	    exp cont = getexp(sh(son(id)), bro(son(z)), last(son(z)),
814
				               ld, nilexp, 0,0, cont_tag);
815
	    bro(ld)=cont;
816
	    pt(id) = ld; no(id)++;
817
	    pos = position(son(z));
818
	    *pos = cont;
819
	    if(i!=0) kill_exp(son(z), nilexp);
820
	    son(z) = cont;
821
	    z = pt(z);
822
	}
823
 
824
	pos = position(loopbody);
825
	bro(son(id)) = loopbody; clearlast(son(id));
826
	bro(loopbody) = id; setlast(loopbody);
827
	*pos = id;
828
	return id;
829
}
830
 
831
exp outer_cont
832
    PROTO_N ( ( loop, contset, lastid, incr) )
833
    PROTO_T ( exp loop X exp contset X exp lastid X exp incr )
834
{
835
 
836
/*
837
	son contset = cont(X); pt = next instance
838
	replace loop by Var Z = cont(x) in
839
			loop(cont(x)/cont(Z), incr/{Z=cont(lasttid); incr})
840
	returning new iddec
841
*/
842
 
843
	exp z = contset;
844
	exp seq, ld, cont, dest, ass;
845
	exp *pos;
846
	int i;
847
	exp id = getexp(sh(loop), bro(loop), last(loop), son(contset),
848
			nilexp, 1/*var*/, 0, ident_tag);
849
 	setcaonly(id);
850
	for(i=0; z!=nilexp; i++) {
851
	    ld = getexp(sh(son(son(id))), nilexp, 1, id,
852
                                                 pt(id), 0, 0, name_tag);
853
	    cont = getexp(sh(son(id)), bro(son(z)), last(son(z)),
854
				           ld, nilexp, 0,0, cont_tag);
855
	    bro(ld)=cont;
856
	    pt(id) = ld; no(id)++;
857
	    pos = position(son(z));
858
	    *pos = cont;
859
	    if(i!=0) kill_exp(son(z), nilexp);
860
	    son(z) = cont;
861
	    z = pt(z);
862
	}
863
 
864
	pos = position(loop);
865
	bro(son(id)) = loop; clearlast(son(id));
866
	bro(loop) = id; setlast(loop);
867
	*pos = id;
868
 
869
 
870
	ld = getexp(sh(son(son(id))), nilexp, 1, lastid,
871
                                            pt(lastid), 0, 0, name_tag);
872
	pt(lastid)=ld; no(lastid)++;
873
	cont = getexp(sh(son(id)), nilexp, 1, ld, nilexp, 0,0,cont_tag);
874
	bro(ld) = cont;
875
	dest = getexp(sh(son(son(id))), cont, 0, id, pt(id), 0, 0, name_tag);
876
	pt(id) = dest; no(id)++;
877
	ass = getexp(topsh, nilexp, 1, dest, nilexp, 0, 0, ass_tag);
878
	bro(cont)=ass;
879
 	z = getexp(sh(incr), incr, 0, ass, nilexp, 0,0, 0);
880
	bro(ass) = z;
881
	seq = getexp(sh(incr), bro(incr), last(incr),z, nilexp, 0,0,seq_tag);
882
	pos = position(incr);
883
	bro(incr) = seq; setlast(incr);
884
	*pos = seq;
885
 
886
	return id;
887
}
888
 
889
 
890
int unaltered
891
    PROTO_N ( ( e, assign_alias) )
892
    PROTO_T ( exp e X int assign_alias )
893
{
894
	exp z = alteredset;
895
	if (name(e) == name_tag && isvar(son(e))) {
896
	     for(; z!=nilexp; z = bro(z) ) {
897
		exp dest = son(z);
898
		Assert(name(dest)==name_tag);
899
	                  if (!isvar(son(dest)) ) {
900
			dest = son(son(dest));
901
			if (name(dest) == reff_tag) dest = son(dest);
902
			Assert(name(dest) == addptr_tag);
903
			dest = son(dest);
904
		}
905
		if (son(e) == son(dest) &&
906
			(name(son(e)) != proc_tag || no(e) == no(dest) ) ) {
907
			return false;
908
		}
909
	     }
910
	     return (iscaonly(son(e)) || !assign_alias);
911
	}
912
	return false;
913
}
914
 
915
 
916
 
917
int invariant
918
    PROTO_N ( ( e, assign_alias) )
919
    PROTO_T ( exp e X int assign_alias )
920
{
921
	return ((name(e) == name_tag  )   ||
922
		(name(e) == cont_tag && unaltered(son(e), assign_alias) )  ) ;
923
}
924
 
925
 
926
static int multiplier;	/*part of answer to weaken */
927
static int arraystep;	/*part of answer to weaken */
928
 
929
int weaken
930
    PROTO_N ( (loop, addptrset, incrset) )
931
    PROTO_T ( exp loop X exp addptrset X exp incrset )
932
{
933
	/* applies strength reduction to addptrs in addptrset and
934
		delivers the multiplying factor if suitable for unwinding
935
			otherwise 0
936
	*/
937
	exp incr = son(incrset);
938
	exp addptr = son(addptrset);
939
	int inci = no(bro(son(bro(son(incr)))));
940
	exp minc = bro(son(addptr));
941
        int simple_c = 0;
942
	int res = -1;
943
	if (name(minc)==cont_tag) {
944
		multiplier = inci;
945
		arraystep = 1;
946
                simple_c = 1;
947
	}
948
	else {
949
		arraystep = no(bro(son(minc)))>>3;
950
		multiplier = inci*arraystep;
951
	}
952
 
953
 
954
 
955
 
956
	if (!invariant(son(addptr), assign_alias) || no(incrset)!=1)
957
        return 0;
958
	if (props(addptrset) && unaltered(son(addptr), assign_alias) )
959
		res= 1;
960
 
961
	extract_addptrs(incr, addptrset, loop,
962
                                bro(son(minc)),inci,simple_c);
963
  	return res;
964
}
965
 
966
struct en{ exp e;
967
int disp;
968
};
969
 
970
int unwind
971
    PROTO_N ( (loop, contset, incr, incval) )
972
    PROTO_T ( exp loop X exp contset X exp incr X int incval )
973
{
974
	exp body = bro(son(bro(son(loop))));
975
	int i,j;
976
	exp z = contset;
977
	int n = no(contset);
978
	int insts = 0;
979
	struct en * s = (struct en*)xcalloc(n, sizeof(struct en));
980
	for(i=0; i<n; i++) {
981
	    /* sort cont([reff (disp) cont(X)) into s */
982
	    exp c = son(z);
983
	    exp w;
984
	    int n;
985
	    exp next = pt(z);
986
	    Assert(name(c)==cont_tag);
987
	    if (!last(c)) { z= next; continue; }
988
	    if (name(bro(c))==cont_tag) { n =0; w = bro(c);}
989
	    else
990
	    if (name(bro(c))==reff_tag && last(bro(c)) &&
991
			 name(bro(bro(c)))==cont_tag ) {
992
		    n= no(bro(c)); w = bro(bro(c));
993
	    }
994
            else { z= next; continue; }
995
 
996
	    son(z)= w;
997
 
998
	    for(j=0; j <insts; j++) {
999
		int d = s[j].disp;
1000
		if (d==n) break;
1001
		if ((incval>0 && d<n) || (incval <0 && d > n) ) {
1002
			/*make a hole  at jth position */
1003
			int k;
1004
			for(k=insts-1; k>=j; k--) {
1005
				s[k+1] = s[k];
1006
			}
1007
			s[j].e = nilexp;
1008
			insts++;
1009
			break;
1010
		}
1011
	    }
1012
	    if (j==insts) { /* add another */
1013
		insts++;
1014
		s[j].e = nilexp;
1015
	    };
1016
	    pt(z) = s[j].e;
1017
	    s[j].e = z;
1018
	    s[j].disp= n;
1019
	    z = next;
1020
	}
1021
	if (insts==0) return false;
1022
	z = nilexp;
1023
 
1024
	for (i = 0; i < insts; i++) {
1025
	      if (no(s[i].e) >1 ) z = inner_cont(body, s[i].e);
1026
	      for (; i < insts-1 && s[i].disp-incval*8 ==  s[i+1].disp; i++) {
1027
		if (z==nilexp) z = inner_cont(body, s[i].e);
1028
		z = outer_cont(loop, s[i+1].e, z, son(incr));
1029
	      }
1030
	      z= nilexp;
1031
	}
1032
 
1033
 
1034
	return true;
1035
}
1036
 
1037
int all_before
1038
    PROTO_N ( ( addptrset, inc, body) )
1039
    PROTO_T ( exp addptrset X exp inc X exp body )
1040
{
1041
     	exp z=inc;
1042
	exp w;
1043
     	while ( z != body) {
1044
	    exp b = bro(z);
1045
	    if (!last(z) ) {
1046
	         for (w=addptrset; w!=nilexp; w= pt(w)) {
1047
		/* son(w) is internal to body - is it in bro(z) ? ie after z*/
1048
		exp s = son(w);
1049
		while(s!=body && s !=b) s = father(s);
1050
		if (s == b) return false;
1051
	        }
1052
	    }
1053
	    z = b;
1054
	}
1055
                  return true;
1056
}
1057
 
1058
 
1059
void replace_var
1060
    PROTO_N ( (ldcpy, loop, shcont) )
1061
    PROTO_T ( exp ldcpy X exp loop X shape shcont )
1062
{
1063
	/* ld is copy of the name(id) assigned to safely in loop
1064
            (see do_one_rep)
1065
	    replace loop(id) by Var x := cont(id) in loop(x); id = cont(x) ni;
1066
	*/
1067
	exp z;
1068
	exp * pos;
1069
	exp ld = getexp(sh(ldcpy), nilexp, 1, son(ldcpy),pt(son(ldcpy)),
1070
			                props(ldcpy), no(ldcpy), name(ldcpy));
1071
	exp def = getexp(shcont, nilexp, 0, ld, nilexp, 0, 0, cont_tag);
1072
	exp varid = getexp(sh(loop), bro(loop), last(loop),
1073
                                def, nilexp, subvar |1/*var*/, 1, ident_tag);
1074
	exp ldvar = getexp(sh(ld), nilexp, 1, varid, nilexp, 0, 0, name_tag);
1075
	exp contvar = getexp(shcont, nilexp, 1, ldvar, nilexp, 0, 0,cont_tag);
1076
	exp nld = getexp(sh(ld), contvar, 0, son(ld), ld, 0, no(ld),name_tag);
1077
	exp ass = getexp(topsh, nilexp, 1, nld , nilexp, 0, 0, ass_tag);
1078
	exp seqh = getexp(topsh, ass, 0, loop, nilexp, 0, 0, 0);
1079
	exp seq = getexp(topsh, varid, 1, seqh, nilexp, 0, 0, seq_tag);
1080
	bro(ass) = seq; /*father*/
1081
	bro(contvar) = ass;/*father*/
1082
	bro(ldvar) = contvar;/*father*/
1083
	bro(ld) = def; /* father */
1084
	pt(son(ld)) = nld; no(son(ld))+=2; 	/* two new used of id */
1085
	bro(def) = seq;
1086
	pt(varid) = ldvar;
1087
	setcaonly(varid);
1088
 
1089
	/* now relpace all old uses of ld in loop by varid */
1090
	for( z = pt(ld); z != nilexp; z = pt(z)) {
1091
	      if (no(z) == no(ld) && intnl_to(loop, z) ) {
1092
/* ALTERATION #1 */
1093
		exp lu = getexp(sh(z), bro(z), last(z), varid, pt(varid), 0,
1094
					0, name_tag);
1095
		pos = position(z);
1096
		pt(varid) = lu; no(varid)++;
1097
		kill_exp(z, nilexp); /* this should not kill the def of ld! */
1098
		*pos = lu;
1099
	      }
1100
	}
1101
	pos = position(loop);
1102
	*pos = varid;
1103
	bro(loop) = seqh; setlast(loop);
1104
}
1105
 
1106
 
1107
exp limexp
1108
    PROTO_N ( ( test, ld) )
1109
    PROTO_T ( exp test X exp ld )
1110
{
1111
	exp lh = son(test);
1112
	exp rh = bro(lh);
1113
	if (name(lh) == cont_tag && name(son(lh) )== name_tag
1114
		&& son(son(lh))==son(ld) && no(son(lh))==no(ld) ) return rh;
1115
 
1116
	if (name(rh) == cont_tag && name(son(rh) )== name_tag
1117
		&& son(son(rh))==son(ld) && no(son(rh))==no(ld) ) return lh;
1118
	return nilexp;
1119
}
1120
 
1121
exp limaddptr
1122
    PROTO_N ( (arr, val, m) )
1123
    PROTO_T ( exp arr X exp val X int m )
1124
{
1125
	exp naddptr = getexp(sh(arr), nilexp, 0, copy(arr), nilexp, 0, 0,
1126
			addptr_tag);
1127
	exp z, v;
1128
        shape s;
1129
	if (m==1 ) {
1130
	    z = copy(val);
1131
	    bro(z) = naddptr; setlast(z);
1132
	}
1133
	else {
1134
            s = f_offset(al1_of(sh(naddptr)),al1_of(sh(naddptr)));
1135
	    z = getexp(s, naddptr, 1, copy(val), nilexp, 0,0,offset_mult_tag);
1136
	    v = getexp(s, z, 1, nilexp, nilexp, 0, m*8, val_tag);
1137
	    bro(son(z)) = v; clearlast(son(z));
1138
	}
1139
	bro(son(naddptr)) = z; clearlast(son(naddptr));
1140
	return naddptr;
1141
		/* a new addptr with index replaced by val - used in limdec*/
1142
}
1143
 
1144
exp limmult
1145
    PROTO_N ( (arr, val, m) )
1146
    PROTO_T ( exp arr X exp val X int m )
1147
{
1148
	exp naddptr = getexp(sh(son(arr)), nilexp, 0, copy(val), nilexp, 0, 0,
1149
			mult_tag);
1150
	exp v = getexp(sh(son(arr)), nilexp, 1, nilexp, nilexp, 0, m, val_tag);
1151
	bro(v) = naddptr;
1152
	bro(son(naddptr)) = v; clearlast(son(naddptr));
1153
	return naddptr;
1154
		/* a new addptr with index replaced by val - used in limdec*/
1155
}
1156
 
1157
exp limreff
1158
    PROTO_N ( (arr, bytedisp) )
1159
    PROTO_T ( exp arr X int bytedisp )
1160
{
1161
        if (bytedisp != 0) {
1162
	exp nreff = getexp(sh(arr), nilexp, 0, copy(arr),
1163
                                              nilexp, 0, bytedisp*8, reff_tag);
1164
	bro(son(nreff)) = nreff; setlast(son(nreff));
1165
	return nreff;
1166
        }
1167
        else return copy(arr);
1168
}
1169
 
1170
exp limconst
1171
    PROTO_N ( (arr, bytedisp) )
1172
    PROTO_T ( exp arr X int bytedisp )
1173
{
1174
	exp nreff = getexp(/*sh(son(arr))*/slongsh, nilexp, 1, nilexp,
1175
                                              nilexp, 0, bytedisp, val_tag);
1176
	UNUSED(arr);
1177
	bro(nreff) = nreff;
1178
 	return nreff;
1179
}
1180
 
1181
exp limdec
1182
    PROTO_N ( ( adec, val, mult) )
1183
    PROTO_T ( exp adec X exp val X int mult )
1184
{
1185
	exp init = son(adec);
1186
	exp bdy = bro(init);
1187
	exp ninit =  (name(val)!=val_tag) ?
1188
                      limaddptr(son(init), val, mult):
1189
                      limreff(son(init), mult*no(val)
1190
                     );
1191
	exp nb = getexp(sh(bdy), adec, 1, ninit, nilexp, 0, 0, ident_tag);
1192
	bro(ninit) = bdy; clearlast(ninit);
1193
	bro(bdy) = nb; setlast(bdy);
1194
	bro(init) = nb;
1195
	return nb; /* the declaration of the limit value */
1196
}
1197
 
1198
exp limdec2
1199
    PROTO_N ( ( adec, val, mult) )
1200
    PROTO_T ( exp adec X exp val X int mult )
1201
{
1202
	exp init = son(adec);
1203
	exp bdy = bro(init);
1204
	exp ninit =  (name(val)!=val_tag) ?
1205
                      limmult(son(init), val, mult):
1206
                      limconst(son(init), mult*no(val)
1207
                     );
1208
	exp nb = getexp(sh(bdy), adec, 1, ninit, nilexp, 0, 0, ident_tag);
1209
	bro(ninit) = bdy; clearlast(ninit);
1210
	bro(bdy) = nb; setlast(bdy);
1211
	bro(init) = nb;
1212
	return nb; /* the declaration of the limit value */
1213
}
1214
 
1215
 
1216
void remove_incr
1217
    PROTO_N ( (adec, test, incr, mult) )
1218
    PROTO_T ( exp adec X exp test X exp incr X int mult )
1219
{
1220
	exp le = limexp(test, son(incr));
1221
	exp * pos;
1222
	exp ndec = limdec(adec, le, mult);
1223
	exp lda = getexp(f_pointer(long_to_al(shape_align(sh(son(adec))))),
1224
                                   nilexp, 1, adec, pt(adec), 0, 0, name_tag);
1225
	exp clda = getexp(sh(son(adec)), nilexp, 0, lda,
1226
                                              nilexp, 0, 0, cont_tag);
1227
	exp ldn = getexp(sh(son(ndec)), nilexp, 0, ndec,
1228
                                              pt(ndec), 0, 0, name_tag);
1229
	exp ntestx = getexp(sh(test), bro(test), last(test),
1230
                       nilexp, pt(test), props(test), no(test), name(test));
1231
	bro(lda) = clda;   pt(adec) = lda; no(adec)++;
1232
	pt(ndec) = ldn; no(ndec)++;
1233
	if (last(le)) {
1234
	       son(ntestx) = clda;
1235
	       bro(clda) = ldn; clearlast(clda);
1236
	       bro(ldn) = ntestx; setlast(ldn);
1237
	}
1238
	else {
1239
	       son(ntestx) = ldn;
1240
	       bro(ldn) = clda; clearlast(ldn);
1241
	       bro(clda) = ntestx; setlast(clda);
1242
	};
1243
	pos = position(test);
1244
	*pos = ntestx;
1245
	kill_exp(test, nilexp);
1246
	setname(incr, top_tag);
1247
	kill_exp(bro(son(incr)), nilexp);
1248
	kill_exp(son(incr), nilexp);
1249
	son(incr) = nilexp;
1250
}
1251
 
1252
void remove_incr2
1253
    PROTO_N ( (adec, test, incr, mult) )
1254
    PROTO_T ( exp adec X exp test X exp incr X int mult )
1255
{
1256
	exp le = limexp(test, son(incr));
1257
	exp * pos;
1258
	exp init = son(adec);
1259
	exp bdy = bro(init);
1260
	exp ninit,ldn,ntestx,lda,clda;
1261
        if (name(le)!=val_tag && !remove_unused_index_counters)
1262
           return;
1263
	lda = getexp(f_pointer(long_to_al(shape_align(sh(son(adec))))),
1264
                                   nilexp, 1, adec, pt(adec), 0, 0, name_tag);
1265
	clda = getexp(/*sh(son(adec))*/slongsh, nilexp, 0, lda,
1266
                                              nilexp, 0, 0, cont_tag);
1267
        if  (name(le)==val_tag)
1268
             {ninit = limconst(son(init), mult*no(le));
1269
              ldn = ninit;
1270
             }
1271
        else {exp nb;
1272
              ninit =  limmult(son(init), le, mult);
1273
              nb = getexp(sh(bdy), adec, 1, ninit, nilexp, 0, 0, ident_tag);
1274
	      bro(ninit) = bdy; clearlast(ninit);
1275
	      bro(bdy) = nb; setlast(bdy);
1276
	      bro(init) = nb;
1277
              ninit = nb;
1278
              ldn = getexp(sh(son(ninit)), nilexp, 0, ninit,
1279
                                              pt(ninit), 0, 0, name_tag);
1280
              pt(ninit) = ldn; no(ninit)++;
1281
             }
1282
	ntestx = getexp(sh(test), bro(test), last(test),
1283
                       nilexp, pt(test), props(test), no(test), name(test));
1284
	bro(lda) = clda;   pt(adec) = lda; no(adec)++;
1285
	if (last(le)) {
1286
	       son(ntestx) = clda;
1287
	       bro(clda) = ldn; clearlast(clda);
1288
	       bro(ldn) = ntestx; setlast(ldn);
1289
	}
1290
	else {
1291
	       son(ntestx) = ldn;
1292
	       bro(ldn) = clda; clearlast(ldn);
1293
	       bro(clda) = ntestx; setlast(clda);
1294
	};
1295
	pos = position(test);
1296
	*pos = ntestx;
1297
	kill_exp(test, nilexp);
1298
	setname(incr, top_tag);
1299
	kill_exp(bro(son(incr)), nilexp);
1300
	kill_exp(son(incr), nilexp);
1301
	son(incr) = nilexp;
1302
}
1303
 
1304
int  use_in
1305
    PROTO_N ( (w, ld) )
1306
    PROTO_T ( exp w X exp ld )
1307
{
1308
      switch (name(w)) {
1309
	case name_tag: {
1310
	      return (son(w)==son(ld) && no(w)==no(ld) ) ;
1311
	}
1312
	case ass_tag: {
1313
	      int z = use_in(bro(son(w)), ld) ;
1314
	      if (z!=0 ) return z;
1315
	      if (name(son(w)) == name_tag &&
1316
                  son(son(w))==son(ld) &&
1317
                  no(son(w))==no(ld))
1318
 		  { return -1;}
1319
	      return use_in(son(w), ld);
1320
	}
1321
  	case goto_tag:
1322
        case case_tag:
1323
        case test_tag: case testbit_tag:
1324
        case labst_tag:{ return 1; }
1325
	default: {
1326
	     exp z = son(w);
1327
	     if (z==nilexp) return 0;
1328
	     for(;;) {
1329
		int a = use_in(z, ld);
1330
		if (a !=0 || last(z)) return a;
1331
	 	z = bro(z);
1332
	     }
1333
	}
1334
     }
1335
}
1336
 
1337
 
1338
 
1339
int suitable_test
1340
    PROTO_N ( (tests, incrld, loop) )
1341
    PROTO_T ( exp tests X exp incrld X exp loop )
1342
{
1343
	/* is test such that one can remove the increment ? */
1344
	exp t, p;
1345
	exp decx = son(incrld);
1346
	exp v;
1347
	if (tests == nilexp || no(tests)!=1 || bro(tests) != nilexp )
1348
          return 0;
1349
	t = son(tests);
1350
	v = limexp(t, incrld);
1351
	if (name(v) != val_tag && (!invariant(v, assign_alias)|| maybe_incr(v)) )
1352
          return 0;
1353
	while(t!=loop && last(t)) t= bro(t);
1354
	if (t!=loop) return 0;
1355
	while (name(t) !=proc_tag && t != decx) {
1356
	     exp b = bro(t);
1357
	     if (!last(t)) {
1358
		for (p=pt(decx); p!=nilexp; p=pt(p)) {
1359
			if (intnl_to(b, p)  && use_in(b, incrld) == 1)
1360
                           return 0;
1361
		}
1362
	     }
1363
	     t = b;
1364
	}
1365
	return 1;
1366
}
1367
 
1368
 
1369
 
1370
int do_one_rep
1371
    PROTO_N ( (loop) )
1372
    PROTO_T ( exp loop )
1373
{
1374
	exp body = bro(son(bro(son(loop))));
1375
	exp z ;
1376
	int res =0;
1377
	exp xincrs;
1378
	Assert(name(loop)==rep_tag);
1379
	incrs=nilexp; alteredset=nilexp;
1380
        assign_alias = false; jump_out = false;
1381
	scan_for_incr(body,loop, collect_incrs);
1382
	if (  !jump_out && name(sh(loop)) == tophd) {
1383
	     for (z=alteredset;   z != nilexp; z = bro(z)) {
1384
	/* look to see if var assigned to in loop can be locally declared
1385
		ie Rep f(z) => Var x := cont(z) in Rep f(x); z = cont x ni;
1386
                ? only worth while if z is global
1387
		if z is local only worthwhile if it isnt being allocated
1388
                in reg anyway
1389
	*/
1390
		exp a = son(z);
1391
 
1392
		if (name(a)==name_tag &&
1393
                   (isglob(son(a)) || !isvar(son(a)) ) &&
1394
	           (props(son(a)) & subvar) == 0 &&
1395
		   (!assign_alias || (isvar(son(a)) && iscaonly(son(a)))) &&
1396
	           !intnl_to(body, son(a)) ){
1397
		    exp p ;
1398
		    exp dc = son(a);
1399
		    shape shcont;
1400
		    int const_init = !isglob(dc) &&
1401
				      (name(son(dc)) == clear_tag ||
1402
                                       name(son(dc)) == val_tag ||
1403
				       name(son(dc)) == real_tag ||
1404
				       (name(son(dc)) == name_tag &&
1405
                                        !isvar(son(son(dc)))
1406
                                       )
1407
                                      );
1408
		    for ( p = pt(son(a)); p != nilexp; p = pt(p)) {
1409
#ifdef NEWDIAGS
1410
			int inb;
1411
			if (isdiaginfo(p)) continue;
1412
			inb = intnl_to(body,p);
1413
#else
1414
			int inb = intnl_to(body,p);
1415
#endif
1416
			if (!inb) { const_init = 0; continue; }
1417
			if (no(a) != no(p)) break;
1418
			if (last(p) && name(bro(p))==cont_tag)
1419
				{ shcont = sh(bro(p)); continue; }
1420
			if (!last(p) && last(bro(p))  &&
1421
			         name(bro(bro(p)))==ass_tag)
1422
			     	{ shcont = sh(bro(p)); continue; }
1423
			break;
1424
		    }
1425
		    if (p!=nilexp) continue;
1426
		    /* only uses of this id is cont or assign in body */
1427
		    if (!isvar(son(a)) ){
1428
			/*check to see whether underlying id is used in loop*/
1429
			exp w = son(son(a));
1430
	    		const_init = 0;
1431
			if (name(w)==reff_tag) w=son(w);
1432
			Assert(name(w)==addptr_tag);
1433
			w = pt(son(son(w))); /* uses of underlying var */
1434
			for (; w!=nilexp; w= pt(w)) {
1435
			    if (intnl_to(body, w)) break;
1436
			}
1437
			if ( w != nilexp)  continue;
1438
		    }
1439
		    if (const_init)
1440
                      { /* can reduce scope of altered variable */
1441
			exp dc= son(a);
1442
			exp bd = bro(son(dc));
1443
		        	if ( bd != loop && name(dc) == ident_tag) {
1444
			      exp brodc = bro(dc);
1445
			      int ldc = last(dc);
1446
			      exp broloop = bro(loop);
1447
			      int lloop = last(loop);
1448
			      exp * pos = position(dc);
1449
			      *pos = bd;
1450
                              	  /* replace original dec with its body... */
1451
			      bro(bd) = brodc;
1452
                              if(ldc) { setlast(bd); } else { clearlast(bd); }
1453
			      		/* ... and set  bro to that of dec */
1454
			      pos = position(loop);
1455
			      *pos = dc;	/* replace loop by dec ... */
1456
			      bro(dc) = broloop;
1457
                              if(lloop) {setlast(dc); } else {clearlast(dc); }
1458
			      		/* ... set bro to that of loop, ... */
1459
			      bro(son(dc)) = loop;
1460
                              bro(loop) = dc;
1461
                              setlast(loop);
1462
					/* ... and make loop be body of dec */
1463
			}
1464
 
1465
		    }
1466
		    else {
1467
		      SET(shcont); /* CHECK THIS: why is it set? */
1468
		      replace_var(a, loop, shcont);
1469
		    };
1470
		    res = true;
1471
		}
1472
	    }
1473
	}
1474
	xincrs = incrs;
1475
	while (xincrs!=nilexp) {
1476
	     exp incrld = son(son(xincrs));
1477
	     exp nincr = bro(xincrs);
1478
	     int ou; exp adec = nilexp;
1479
	     int elsize;
1480
	     exp incrdec = son(incrld);
1481
	     tests=nilexp; addptrs=nilexp; stride = 0;
1482
	     ou=find_common_index(incrld, body, collect_loopthings);
1483
             if (stride<1)
1484
                {exp t;
1485
		 int i; int nap = 0;
1486
		 tests=nilexp;
1487
                 addptrs=nilexp;
1488
		 stride = 0;
1489
	         ou=find_pointer_opt(incrld, body,
1490
                         collect_loopthings);
1491
		for(i=0, t=addptrs; t != nilexp; i++, t=bro(t)) {
1492
			nap += no(t);
1493
		}
1494
		if (i>=3 && i==nap) {
1495
			/* don't replace all addptrs if too many vars required
1496
			  ... */
1497
			if (stride>1) {
1498
			  /* ... but can still scale index */
1499
			  scale_loopid(loop,addptrs,xincrs);
1500
			  if (ou==2 /* only other uses besides addptr &
1501
				test are in increment */ &&
1502
                    		suitable_test(tests,son(son(xincrs)),loop)) {
1503
                      		remove_incr2(bro(loop),
1504
                                   son(tests),
1505
                                   son(xincrs),
1506
                                   stride
1507
                                  );
1508
			  }
1509
			}
1510
			ou+=nap; addptrs = nilexp;
1511
 
1512
		}
1513
	        while (addptrs != nilexp)
1514
		  {int rw = weaken(loop, addptrs, xincrs);
1515
		   exp next = bro(addptrs);
1516
		   if (rw != 0)
1517
		       {res = true;
1518
		     	adec = bro(loop); /* really father put in by weaken */
1519
			elsize = arraystep;
1520
		       }
1521
		   else {SET(elsize); ou+=no(addptrs);}
1522
		   if (rw > 0)  /* there is only one incr and it is safe to
1523
			 replace conts; however don't know whether increment
1524
			 is before uses  - could make store-exception if
1525
                         it isn't*/
1526
		    {if ( all_before(addptrs, son(xincrs), body) &&
1527
                         multiplier!=0 )
1528
                        IGNORE unwind(loop, addptrs, xincrs, multiplier);
1529
		    }
1530
		   retcell(addptrs);
1531
		   addptrs=next;
1532
	         };
1533
 
1534
	        if ( ou == 2 /* only other uses (besides addptr & test)
1535
                                              of loop var is in increment */
1536
		    && adec != nilexp && suitable_test(tests, incrld, loop)
1537
                    && multiplier!=0
1538
                    && remove_unused_counters)
1539
		  {remove_incr(adec, son(tests), son(xincrs), elsize);}
1540
 
1541
                 }
1542
             else if (stride>1)
1543
               {scale_loopid(loop,addptrs,xincrs);
1544
                if (ou==2 /* only other uses besides addptr & test are in increment */ &&
1545
                    suitable_test(tests,son(son(xincrs)),loop))
1546
                      remove_incr2(bro(loop),
1547
                                   son(tests),
1548
                                   son(xincrs),
1549
                                   stride
1550
                                  );
1551
               }
1552
 
1553
	     if(res && no(incrdec)<10 /* avoid n-squared factor */)
1554
	     		IGNORE check_id( incrdec, bro(son(incrdec)) );
1555
 
1556
	     xincrs=nincr;
1557
	}
1558
	while (incrs != nilexp){
1559
		exp z = bro(incrs);
1560
		retcell(incrs);
1561
		incrs = z;
1562
	}
1563
	while (alteredset !=nilexp)
1564
		{ exp z = bro(alteredset);
1565
		  retcell(son(alteredset));
1566
                  retcell(alteredset);
1567
                  alteredset = z; }
1568
	return res;
1569
}
1570
 
1571
void order_loops
1572
    PROTO_N ( (reps) )
1573
    PROTO_T ( exp reps )
1574
{
1575
	/* start at outer loop ?! */
1576
	if ( (props(reps) & 0x80) == 0 ){
1577
		if (bro(reps)!=nilexp) order_loops(bro(reps));
1578
		if (son(reps) != nilexp &&
1579
                    name(son(reps))==rep_tag &&
1580
                    no(reps) < max_loop_depth)
1581
		  { exp loop = son(reps);
1582
/* ALTERATION #2 - does not effect C */
1583
		    if (name(son(loop)) != top_tag) {
1584
		    	/* make loop(st,b) into seq((st), loop(make_top, b))
1585
		    		analysis assumes son(loop) = top!
1586
		    	*/
1587
		    	exp st = son(loop);
1588
		    	exp b = bro(st);
1589
		    	exp * pos = ifc_ptr_position(loop);
1590
		    	exp mt = getexp(f_top, b,0, nilexp,
1591
		    				nilexp, 0, 0, top_tag);
1592
		    	exp sl = getexp(f_top, loop, 0 ,st, nilexp, 0,0,0);
1593
		    	exp s = getexp(sh(loop), bro(loop), last(loop), sl,
1594
		    			nilexp, 0, 0, seq_tag);
1595
 
1596
		        bro(st) = sl; setlast(st);
1597
		        son(loop) = mt;
1598
		        bro(loop) = s; setlast(loop);
1599
		        *pos = s;
1600
 
1601
		    }
1602
		    IGNORE do_one_rep(loop);
1603
		  }
1604
		props(reps) |=0x80;
1605
	}
1606
}
1607
 
1608
void forall_opt
1609
    PROTO_Z ()
1610
{
1611
	exp reps =get_repeats();
1612
	while (reps != nilexp) {
1613
		order_loops(reps);
1614
		reps = pt(reps);
1615
	}
1616
  if (do_loopconsts) {
1617
    do_foralls = false;
1618
    repeat_consts ();		/* try constant extraction again */
1619
  }
1620
}