Avoid casts from pointers to integers
[suif.git] / src / baseparsuif / dependence / dvector.cc
blob76f878cb51ec706646cd91587ff719b12db0d40c
1 /* file "dvector.cc" */
3 /* Copyright (c) 1994 Stanford University
5 All rights reserved.
7 This software is provided under the terms described in
8 the "suif_copyright.h" include file. */
10 #include <suif_copyright.h>
12 //dvector.c
13 #define _MODULE_ "libdependence.a"
14 #pragma implementation "dvector.h"
16 #include <stdio.h>
17 #include <suif1.h>
18 #include <builder.h>
19 #include <suifmath.h>
20 #include "dependence.h"
23 // dvector.c
25 // routines to create a distance vector
26 // taking as input two array instructions
29 // a1 and a2 are two memory references which have the same base array
30 // --- possibly NULL or unknown
31 // if a1 and a2 are array accesses, generate the access vectors using
32 // gcd
33 // if they are not, try to determine if they are independent, if not
34 // dependence vector is (*)
37 // interface the access vectors to the gcd program and find
38 // the distance vector
40 int Gcd(coeff, coeff **);
41 //overload int is_good_symb(access_vector *av1,access_list *symbols);
42 access_list *unite_unequals(access_list *a1, access_list *a2);
43 //overload int inline is_good_symb(access_vector *av1);
46 dvlist::dvlist(array_info *a1, array_info *a2,
47 int minnest, int valid_dim, tn_list * al, int lexpos, int flow)
49 dv_calc(a1,a2,minnest,valid_dim,al,flow);
50 if(lexpos) make_lexpos();
53 distance_vector::distance_vector(array_info *a1, array_info *a2,
54 int minnest, int valid_dim, tn_list * al,int flow)
56 dvlist *dvl=new dvlist(a1,a2,minnest,valid_dim,al,flow);
57 dvl->collapse(this);
58 delete dvl;
61 static int dim_is_ok(access_vector *a,tn_list *al)
63 if(a->too_messy)
64 return 0;
65 ass_list_iter<int> ai(&a->elts);
66 while(!ai.is_empty()) {
67 ass_list_e<int> *ae = ai.step();
68 if(ae->info != NULL && !al->lookup((tree_node *)ae->key))
69 return 0;
71 return 1;
74 static int wierd_constant_fields_same(access_vector *av1,access_vector *av2)
76 av_compare_info ans(av1,av2);
77 return ans.same_paths() && ans.same_conregs() && ans.same_memregs();
81 void dvlist::clear()
83 dvlist_iter iter(this);
84 while(!iter.is_empty()) {
85 dvlist_e * de = iter.step();
86 if(de->dv) delete de->dv;
87 remove(iter.cur_elem());
88 delete de;
90 glist::clear();
98 dvlist::dvlist(array_info *a1, array_info *a2, tn_list *al,int lexpos, int flow)
100 int valid_dim = 0;
101 array_info *ai1 = new array_info;
102 array_info *ai2 = new array_info;
103 array_info_iter aii1(a1);
104 array_info_iter aii2(a2);
105 while(!aii1.is_empty()) {
106 assert(!aii2.is_empty());
107 access_vector *av1 = aii1.step();
108 access_vector *av2 = aii2.step();
109 if(dim_is_ok(av1,al) && dim_is_ok(av2,al)) {
110 // wierd_constant_fields_same(av1,av2)) {
111 valid_dim++;
112 ai1 -> append(new access_vector(av1));
113 ai2 -> append(new access_vector(av2));
116 dv_calc(ai1,ai2,al->count(),valid_dim,al,flow);
117 if(lexpos) make_lexpos();
118 delete ai1;
119 delete ai2;
124 distance_vector::distance_vector(array_info *a1,array_info *a2,
125 tn_list *al,int flow)
127 int valid_dim = 0;
128 array_info *ai1 = new array_info;
129 array_info *ai2 = new array_info;
130 array_info_iter aii1(a1);
131 array_info_iter aii2(a2);
132 while(!aii1.is_empty()) {
133 assert(!aii2.is_empty());
134 access_vector *av1 = aii1.step();
135 access_vector *av2 = aii2.step();
136 if(dim_is_ok(av1,al) && dim_is_ok(av2,al) &&
137 wierd_constant_fields_same(av1,av2)) {
138 valid_dim++;
139 ai1 -> append(new access_vector(av1));
140 ai2 -> append(new access_vector(av2));
143 dvlist *dvl=new dvlist(ai1,ai2,al->count(),valid_dim,al,flow);
144 dvl->collapse(this);
145 delete ai1; delete ai2;
148 void dvlist::dv_calc(array_info *a1, array_info *a2,
149 int minnest, int valid_dim, tn_list * al,int flow)
151 //= printf("a1:"); a1->print();
152 //= printf("\na2:"); a2->print();
153 //= printf("\nminnest=%d, valid_dim=%d, flow=%d\n", minnest, valid_dim, flow);
154 /* assert(al);
155 tn_list_iter titer(al);
156 printf("[");
157 while(!titer.is_empty()) {
158 tree_node * tn = titer.step();
159 assert(tn->is_for());
160 printf("%s ", ((tree_for*)tn)->index());
162 printf("]\n"); */
164 array_info_iter * a1i, *a2i;
165 access_vector * av1, * av2;
166 tn_list_iter * loops;
167 tn_list_iter * loops2;
168 dependency_test *dt=new dependency_test();
169 set_dep(); // initialization
170 int DD = 2*minnest;
171 int *write_used = new int[minnest]; // which loops are used by
172 // the write, assume a1 is
173 // the write
175 valid_dim = elim_bad_symb(a1, a2); // dims with bad symbols
176 if (!valid_dim && flow) {
177 dir_array *da = new dir_array(minnest);
178 int *is_used = new int[2*minnest];
179 for (int i=0; i<minnest; i++) {
180 da->data[i].set_direction(d_star);
181 is_used[2*i] = 0;
182 is_used[2*i+1] = 0;
184 dir_list *dl = new dir_list(da);
185 dl->flow_reduce(is_used);
186 dir_array *da2;
187 while ((da2=dl->pop())) {
188 distance_vector *dv2 = new distance_vector();
189 for (int s=0; s<da2->size; s++) {
190 distance dis=da2->data[s];
191 dv2->append(dis);
193 push(new dvlist_e(dv2));
195 return;
199 access_list *symbols = find_symbs(a1,a2);
200 int num_symb = symbols->count();
201 DD += num_symb;
203 printf("\nThe two references are \n");
204 a1->print(stdout); printf("\n");
205 a2->print(stdout); printf("\n");
207 // find the bounds from al and shove into L and U
208 integer_matrix *L = new integer_matrix();
209 integer_matrix *U = new integer_matrix();
210 boolean *lb_valid = new boolean[DD+1]; // does this bound exist
211 boolean *ub_valid = new boolean[DD+1];
212 void SetLU(tn_list *, int, integer_matrix *, integer_matrix * ,boolean * ,
213 boolean *,access_list *,int,int flow=0);
214 SetLU(al,DD,L,U,lb_valid,ub_valid,symbols,num_symb,flow);
216 // throw out constant dimensions
217 a1i = new array_info_iter(a1);
218 a2i = new array_info_iter(a2);
220 int has_const_dim = 0;
221 // throw out constant dimensions
222 array_info *newa1 = new array_info();
223 array_info *newa2 = new array_info();
224 while(!a1i->is_empty()) {
225 assert(!a2i->is_empty());
226 av1=a1i->step();
227 av2=a2i->step();
228 av_compare_info avc(av1,av2);
229 // will subracting the two will create a constant
230 if (av1->elts.is_empty() && av2->elts.is_empty() &&
231 avc.same_conregs() && avc.same_memregs() &&
232 avc.same_paths()) {
233 if (av1->con != av2->con) {
234 if (minnest > 0) dt->const_test++;
235 set_indep();
236 //printf("It's independent \n");
237 return;
239 has_const_dim = 1;
240 valid_dim--;
241 } else {
242 newa1->append(av1);
243 newa2->append(av2);
246 delete a1i; delete a2i;
247 a1->clear(); a2->clear();
249 // degenerate case
250 if (valid_dim == 0) { // set all elements to star
251 if (has_const_dim && (minnest >0)) dt->const_test++;
252 distance_vector *dv = new distance_vector();
253 for (int i=0; i<minnest; i++) {
254 distance *d = new distance();
255 distance_vector_e *temp = new distance_vector_e(*d);
256 dv->push(temp);
258 push(new dvlist_e(dv));
259 //= printf("The result is1 \n"); this->print(stdout); printf("\n");
260 return;
263 a1i = new array_info_iter(newa1);
264 a2i = new array_info_iter(newa2);
266 // check which induction variables are actually used and get a count
267 int *loop_used = new int[2*minnest+num_symb];
268 void SetLoopUsed(int *,int ,int,int *, int *, array_info_iter *,
269 array_info_iter*,tn_list *,integer_matrix *,
270 integer_matrix*,int,int *);
271 SetLoopUsed(loop_used,minnest,valid_dim,lb_valid,ub_valid,
272 a1i,a2i,al,L,U,num_symb,write_used);
273 int loop1_num = 0;
274 int loop2_num = 0;
275 int i;
276 for (i=2*(minnest-1); i>=0; i-=2) {
277 if (loop_used[i+num_symb]) loop1_num++;
279 for (i=2*minnest-1; i>=0; i-=2) {
280 if (loop_used[i+num_symb]) loop2_num++;
282 int num_used = loop1_num + loop2_num;
284 // throw out unused variables from write_used
285 assert(num_used%2 == 0);
286 int i2=0;
287 for (i=0; i<num_used/2; i++) {
288 if (loop_used[2*i+num_symb] || loop_used[2*i+num_symb+1]) {
289 write_used[i2++] = write_used[i];
292 //= printf("L:\n");L->print();
293 //= printf("U:\n");U->print();
294 //= for(int x=0; x<DD+1; x++)
295 //= printf("(%d %d)", lb_valid[x], ub_valid[x]);
296 // put equations into a coeff A
297 coeff A;
298 coeff *X=new coeff;
299 int total_vars = 2*minnest+num_symb;
300 X->vars = new int[total_vars*total_vars];
301 X->constant = new int[total_vars];
302 A.n = num_used+num_symb;
303 A.m = valid_dim;
304 A.vars = new int[A.n*A.m];
305 A.constant = new int[valid_dim];
307 /* now set the A matrix, eliminating unused variables */
308 a1i = new array_info_iter(newa1);
309 a2i = new array_info_iter(newa2);
310 for (i=0; i<valid_dim; i++) {
311 av1 = a1i -> step();
312 av2 = a2i -> step();
313 assert(av1 && av2);
314 loops = new tn_list_iter(al);
315 loops2 = new tn_list_iter(al);
316 int k=2*minnest-1;
317 int j;
318 for (j=num_used-1; j>=0; j--) {
319 int j2 = j+num_symb;
320 while(!loop_used[k+num_symb]) {
321 if ((k %2) ==0) av1->val(loops->step());
322 else av2->val(loops2->step());
323 k--;
325 if ((k % 2) == 0) {
326 A.vars[j2*valid_dim+i] = av1->val(loops -> step());
327 } else {
328 A.vars[j2*valid_dim+i] = -av2->val(loops2 -> step());
330 k--;
331 //= printf("%d %d %d---\n", i, j, k); A.print();
333 delete loops; delete loops2;
334 A.constant[i] = av1->con - av2->con;
336 // add in symbolic components
337 access_list_iter temp_symb(symbols);
338 for (j=num_symb-1; j>=0; j--) {
339 assert(!temp_symb.is_empty());
340 access_list_e *e = temp_symb.step();
341 A.vars[j*valid_dim+i] = av1->conregs.val(e->var())-
342 av2->conregs.val(e->var());
343 //= printf("%d %d ---\n", i, j); A.print();
347 //eliminate unused variables for L and U
348 int olddd = DD;
349 DD = num_used+num_symb;
350 int numlow = 0; // number of lower bounds
351 int numup = 0;
352 for (i=1; i<=olddd; i++) {
353 if (loop_used[i-1]) {
354 numlow += lb_valid[i];
355 numup += ub_valid[i];
358 integer_matrix *L2 = new integer_matrix();
359 integer_matrix *U2 = new integer_matrix();
360 L2->init(num_symb+numlow+1,DD+1);
361 U2->init(num_symb+numup+1,DD+1);
362 int oldlow,oldup,newlow,newup;
363 //= printf("L:\n");L->print();
364 //= printf("U:\n");U->print();
365 oldlow = oldup = newlow = newup = 1;
366 i2 = 1;
367 for (i=1; i<=olddd; i++) {
368 if (loop_used[i-1]) {
369 lb_valid[i2] = lb_valid[i]; ub_valid[i2] = ub_valid[i];
370 int a;
371 for (a=1; a<= lb_valid[i]; a++, oldlow++, newlow++) {
372 (*L2)[newlow][0] = (*L)[oldlow][0];
373 int j2=1;
374 int j;
375 for (j=1; j<i; j++) {
376 if (loop_used[j-1]) {
377 (*L2)[newlow][j2] = (*L)[oldlow][j];
378 j2++;
382 for (a=1; a<= ub_valid[i]; a++, oldup++, newup++) {
383 (*U2)[newup][0] = (*U)[oldup][0];
384 int j2=1;
385 int j;
386 for (j=1; j<i; j++) {
387 if (loop_used[j-1]) {
388 (*U2)[newup][j2] = (*U)[oldup][j];
389 j2++;
393 i2++;
394 } else {
395 oldlow += lb_valid[i];
396 oldup += ub_valid[i];
399 delete L; delete U;
400 L = L2; U = U2;
401 //= printf("L:\n");L->print();
402 //= printf("U:\n");U->print();
403 //= A.print();
405 // check degenerate cases
406 if (minnest == 0) { // if all constants equal then set to star
407 // else set to independent
408 for (i=0; i<valid_dim; i++) {
409 if (A.constant[i] != 0) {
410 set_indep();
411 break;
414 // do Gcd
415 } else if (Gcd(A,&X)) {
416 distance_vector *dv = new distance_vector();
417 for (i=num_used/2-1; i >= 0; i--) { // once for each d_vec dim
418 int i2 = 2*i+num_symb;
419 int done = FALSE;
420 distance *d = NULL;
421 for (int j=0; j<X->n && !done; j++) {
422 if (X->vars[j*X->m+i2] !=
423 X->vars[j*X->m+i2+1]) {
424 // non constant distance vector
425 d = new distance(); // star
426 done = TRUE;
430 if (!done) {
431 int c=X->constant[i2+1]-X->constant[i2];
432 d = new distance(-c);
434 distance_vector_e *temp = new distance_vector_e(*d);
435 dv->push(temp);
438 if (dt->exact()) {
439 // convert from coefficient structure to integer_matrix needed by exact
440 integer_matrix S;
441 S.init(DD+1,DD+1);
442 for (int l=0; l<X->m; l++) {
443 assert(l+1 < (DD+1));
444 S[l+1][0] = X->constant[l];
445 for (int m=0; m<X->n; m++) {
446 assert((m+1) < (DD+1));
447 S[l+1][m+1]=X->vars[m*X->m + l];
450 // convert direction vector to dir_array needed by exact
451 dir_array *da = new dir_array(num_used/2);
452 boolean *const_dist = new boolean[num_used/2];
453 distance_vector_iter di(dv);
454 for (i=0; i<num_used/2; i++) {
455 distance d;
456 d = di.step()->d;
457 da->data[i].set_direction(d.dir());
458 const_dist[i] = d.is_const();
461 exact *ex = new exact(&S,DD,da,const_dist,L,U,
462 lb_valid,ub_valid,num_symb,flow,write_used);
463 if (ex->is_indep()) {
464 //= printf("ex makes it independent \n");
465 set_indep();
466 } else {
467 //= vvv
468 /* printf("Gcd gave ");
469 dv->print(stdout); printf("\n");
470 printf("The set of direction vectors is\n");
471 ex->directions()->print(stdout);
472 printf("\n");
474 //= ^^^
476 dir_list *dl = ex->directions();
477 if (!indep()) dl->add_unused(loop_used+num_symb,
478 2*minnest);
479 if (flow) {
480 dl->flow_reduce(loop_used+num_symb);
482 while(dl) {
483 distance_vector *dv2 =
484 new distance_vector();
485 dir_array *da = dl->data;
486 dl = dl->next;
487 distance_vector_iter iter1(dv);
488 for (int s=0; s<da->size; s++) {
489 distance dis;
490 if (loop_used[num_symb+2*s]) {
491 assert(!iter1.is_empty());
492 dis = iter1.step()->d;
493 if (!dis.is_const()) {
494 dis = da->data[s];
496 } else {
497 dis=da->data[s];
499 dv2->append(dis);
501 push(new dvlist_e(dv2));
503 delete dl;
505 delete ex;
506 } else {
507 dv->add_unused(loop_used+num_symb, 2*minnest);
508 push(new dvlist_e(dv));
510 } else {
511 set_indep();
513 delete a1i; delete a2i; delete newa1; delete newa2;
514 delete loop_used; delete L; delete U;
515 delete symbols;
516 //= printf("The result is2 \n"); this->print(stdout); printf("\n");
520 // collapse a list of direction vectors into 1
521 // by oring in the directions
522 void dvlist::collapse(distance_vector *output)
524 if (this->indep()) output->set_indep();
525 else {
526 output->set_dep();
527 int first_time=1;
528 dvlist_iter iterator(this);
529 for (; !iterator.is_empty();) {
530 distance_vector *dv = iterator.step()->dv;
531 if (first_time) {
532 first_time = 0;
533 distance_vector_iter iter1(dv);
534 while(!iter1.is_empty()) {
535 output->append(iter1.step()->d);
537 } else {
538 distance_vector_iter iter1(output);
539 distance_vector_iter iter2(dv);
540 while(!iter1.is_empty()) {
541 assert(!iter2.is_empty());
542 distance *d1 = &iter1.step()->d;
543 distance *d2 = &iter2.step()->d;
544 if (d1->is_const() && d2->is_const()) {
545 assert(d1->dist()==d2->dist());
546 } else {
547 direction newd = direction(d1->dir()|d2->dir());
548 d1->set_direction(newd);
560 // initialize a distance vector to the same as another
562 distance_vector::distance_vector(distance_vector * dv)
564 if (dv -> indep()) {
565 set_indep();
566 } else {
567 set_dep();
568 distance_vector_iter iterator(dv);
569 for(; !iterator.is_empty();) {
570 append(iterator.step()->d);
577 // print a distance vector
579 void distance_vector::print(FILE *str)
581 if (indep()) {
582 fprintf(str,"These vectors are independent \n");
583 } else {
584 fprintf(str,"( ");
585 distance_vector_iter iterator(this);
586 for(; !iterator.is_empty();) {
587 iterator.step()->d.print(str);
589 fprintf(str,")\n");
595 // print a dvlist
597 void dvlist::print(FILE *str)
599 if (indep()) {
600 fprintf(str,"These vectors are independent \n");
601 } else {
602 dvlist_iter iterator(this);
603 for(; !iterator.is_empty();) {
604 iterator.step()->dv->print(str);
610 // print a distance
611 void distance::print(FILE *str)
613 if (is_const()) {
614 fprintf(str,"%d ",dist());
615 if(dist() > 0) assert(dir() == d_lt);
616 else if(dist() == 0) assert(dir() == d_eq);
617 else assert(dir() == d_gt);
618 } else {
619 direction d=dir();
620 switch(d) {
621 case d_lt: fprintf(str,"+ "); break; // lt
622 case d_gt: fprintf(str,"- "); break; // gt
623 case d_eq: assert(0);
624 case d_le: fprintf(str,"+/0 "); break; // le
625 case d_ge: fprintf(str,"0/- "); break; // ge
626 case d_lg: fprintf(str,"+/- "); break; // lg
627 case d_star: fprintf(str,"* "); break;
634 // is distance vector 0
636 int distance_vector::is_zero()
638 if (indep()) {
639 return TRUE;
640 } else {
641 distance_vector_iter iterator(this);
642 for(; !iterator.is_empty();) {
643 if (!(iterator.step() -> is_zero())) {
644 return FALSE;
647 return TRUE;
651 /* turn leading >= into = */
652 void distance_vector::make_pos()
654 distance d;
655 distance_vector_e *dve;
656 if (indep()) {
657 return;
658 } else {
659 distance_vector_iter iterator(this);
660 for(; !iterator.is_empty();) {
661 dve = iterator.step();
662 d = dve -> d;
663 if (d.dir() == d_lt) {
664 return;
666 if (d.dir() == d_gt) {
667 return;
669 if (d.dir() == d_ge) {
670 dve -> d.set_direction(d_eq);
672 if (d.dir() == d_lg) {
673 return;
675 if (d.dir() == d_star) {
676 return;
678 if (d.dir() == d_le) {
679 return;
681 /* (d.dir() == d_eq) */
683 return;
688 // is distance vector positive
690 int distance_vector::is_pos()
692 distance d;
694 if (indep()) {
695 return FALSE;
696 } else {
697 distance_vector_iter iterator(this);
698 for(; !iterator.is_empty();) {
699 d = iterator.step() -> d;
700 if (d.dir() == d_lt) {
701 return TRUE;
703 if (d.dir() == d_gt) {
704 return FALSE;
706 if (d.dir() == d_ge) {
707 return FALSE;
709 if (d.dir() == d_lg) {
710 return FALSE;
712 if (d.dir() == d_star) {
713 return FALSE;
715 if ((d.dir() == d_le) || (d.dir() == d_eq));
717 return FALSE;
722 // is distance vector negative
724 int distance_vector::is_neg()
726 distance d;
728 if (indep()) {
729 return FALSE;
730 } else {
731 distance_vector_iter iterator(this);
732 for(; !iterator.is_empty();) {
733 d = iterator.step() -> d;
734 if (d.dir() == d_gt)
735 return TRUE;
736 if (d.dir() == d_lt)
737 return FALSE;
738 if (d.dir() == d_le)
739 return FALSE;
740 if (d.dir() == d_lg)
741 return FALSE;
742 if (d.dir() == d_star)
743 return FALSE;
744 if ((d.dir() == d_ge) || (d.dir() == d_eq));
746 return FALSE;
751 // is distance vector a star
753 int distance_vector::is_star()
755 distance d;
757 if (indep()) {
758 return FALSE;
759 } else {
760 distance_vector_iter iterator(this);
761 for(; !iterator.is_empty();) {
762 d = iterator.step() -> d;
763 if (d.is_star())
764 return TRUE;
765 if (d.dir() == d_eq);
766 else return FALSE;
768 return FALSE;
774 // return level of dependence
776 int distance_vector::level()
778 distance d;
779 int i;
781 if (indep()) {
782 return FALSE;
783 } else {
784 distance_vector_iter iterator(this);
785 for(i = 1; !iterator.is_empty(); i++) {
786 d = iterator.step() -> d;
787 if (!d.is_zero() && !d.is_star())
788 return i;
790 return i-1;
797 // return number of elements in graph
799 int distance_vector::size()
801 int i;
803 if (indep()) {
804 return 0;
805 } else {
806 distance_vector_iter iterator(this);
807 for(i = 0; !iterator.is_empty(); i++) {
808 iterator.step();
810 return i;
816 // return level of dependence
818 distance *distance_vector::thresh(int level)
820 distance d;
821 int i;
823 assert(!indep());
824 distance_vector_iter iterator(this);
825 for(i = 1; !iterator.is_empty(); i++) {
826 d = iterator.step() -> d;
827 if (i == level) {
828 return new distance(&d);
831 return(new distance(0));
836 // return level of first non-= or * dependence
837 // return 0 if all ='s or *'s
839 int distance_vector::first_not_eq()
841 distance d;
842 int i;
844 assert(!indep());
845 distance_vector_iter iterator(this);
846 for(i = 1; !iterator.is_empty(); i++) {
847 d = iterator.step() -> d;
848 if (d.is_star())
849 continue;
850 if (!d.is_zero())
851 return i;
853 return(0);
859 // return entry for level
861 distance distance_vector::entry(int level)
863 int i;
865 assert(!indep());
866 distance_vector_iter iterator(this);
867 for(i = 1; !iterator.is_empty(); i++) {
868 distance_vector_e *e = iterator.step();
869 if (i == level) {
870 return e->d;
873 assert(0);
874 return(* new distance());
877 void distance_vector::set_entry(distance dd,int level)
879 int i;
881 assert(!indep());
882 distance_vector_iter iterator(this);
883 for(i = 1; !iterator.is_empty(); i++) {
884 distance_vector_e *e = iterator.step();
885 if (i == level) {
886 e->d = dd;
887 return;
890 assert(0);
894 // negate a distance
896 void distance::negate()
898 if (is_const()) {
899 int d = dist();
900 set_distance(-d);
901 } else {
902 direction di=dir();
903 switch (di) {
904 case d_lt: set_direction(d_gt); break;
905 case d_gt: set_direction(d_lt); break;
906 case d_le: set_direction(d_ge); break;
907 case d_ge: set_direction(d_le); break;
908 default: break;
914 // negate all the distances
916 void distance_vector::negate()
918 distance * d;
920 if (indep()) {
921 return;
922 } else {
923 distance_vector_iter iterator(this);
924 for(; !iterator.is_empty();) {
925 d = &(iterator.step() -> d);
926 d->negate();
934 // check which loop variables are actually used by array statements
935 /* a variable is unused if it and its prime is not used either in the */
936 /* expression nor in a triangular loop */
937 // also check which write variables are used, assume a1 is the write
938 void SetLoopUsed(int *loop_used,int minnest,int valid_dim, int *lb_valid,
939 int *ub_valid, array_info_iter *a1i, array_info_iter *a2i,
940 tn_list *al,integer_matrix *L, integer_matrix *U,int num_symb,
941 int *write_used)
943 access_vector *av1, *av2;
944 int n=num_symb;
946 int j;
947 for (j=0; j<2*minnest; j++) loop_used[j+num_symb]=0;
948 for (j=0; j<num_symb; j++) loop_used[j] = 1;
949 for (j=0; j<minnest; j++) write_used[j] = 0;
950 for (int i=0; i<valid_dim; i++) {
951 av1 = a1i -> step();
952 av2 = a2i -> step();
953 assert(av1 && av2);
954 tn_list_iter *loops = new tn_list_iter(al);
955 for (j=2*(minnest-1); j>=0; j-=2) {
956 if (av1->val(loops->step()) != 0) {
957 loop_used[j+n]=1;
958 write_used[j/2]=1;
961 loops = new tn_list_iter(al);
962 for (j=(2*minnest)-1; j>=0; j-=2) {
963 if (av2->val(loops->step()) != 0) loop_used[j+n]=1;
965 delete loops;
968 // check unused ones in case they're used in triangular loops
969 for (j=1; j<=2*minnest; j++) {
970 if (!loop_used[j-1+n]) {
971 int ltotal = 1;
972 int utotal = 1;
973 for (int i=1; i<=2*minnest; i++) {
974 int lbounds = lb_valid[i+n];
975 int k;
976 for (k=ltotal; k<ltotal+lbounds; k++) {
977 if (lb_valid[i+n] && (*L)[k][j+n]) {
978 loop_used[j-1+n] = 1;
979 write_used[(j-1)/2] = 1;
982 ltotal += lbounds;
984 int ubounds = ub_valid[i+n];
985 for (k=utotal; k<utotal+ubounds; k++) {
986 if (ub_valid[i+n] && (*U)[k][j+n]) {
987 loop_used[j-1+n] = 1;
988 write_used[(j-1)/2] = 1;
991 utotal += ubounds;
996 // check if pair of unused is used
997 for (j=0; j<2*minnest; j+=2) {
998 if (loop_used[j+n]) loop_used[j+1+n] =1;
999 if (loop_used[j+1+n]) loop_used[j+n] =1;
1006 // use the tree_node_list and symbols to set a matrix of lower and upper bounds
1007 // symbolic variables are placed first
1009 void SetLU(tn_list *al, int DD, integer_matrix *L, integer_matrix *U,
1010 boolean *lb_valid,
1011 boolean *ub_valid, access_list *symbols, int num_symb,
1012 int flow=0)
1014 int is_good_symb(access_vector *,access_list *);
1015 int low_bounds = 0;
1016 int up_bounds = 0;
1017 // init lb_valid and ub_valid
1018 int i;
1019 for (i=0; i<=DD; i++) {
1020 lb_valid[i] = ub_valid[i] = 0;
1023 // find out how many bounds there are
1024 tn_list_iter *loops = new tn_list_iter(al);
1025 for (i= DD; i>= 1+num_symb; i-=2) { // for each loop
1026 tree_node *induct = loops->step();
1027 assert(induct->kind() == TREE_FOR);
1028 dep_for_annote * df = (dep_for_annote *)induct->peek_annote(k_dep_for_annote);
1029 assert(df);
1031 if (flow) assert(df->lb->count() <= 1);
1032 array_info_iter ai(df->lb);
1033 while (!ai.is_empty()) { // for each bound
1034 access_vector *lb = ai.step();
1035 if (is_good_symb(lb,symbols)) {
1036 low_bounds += 2;
1037 lb_valid[i]++;
1038 lb_valid[i-1]++;
1044 if (flow) assert(df->ub->count() <= 1);
1045 array_info_iter ai2(df->ub);
1046 while (!ai2.is_empty()) { // for each bound
1047 access_vector *ub = ai2.step();
1048 if (is_good_symb(ub,symbols)) {
1049 up_bounds += 2;
1050 ub_valid[i]++;
1051 ub_valid[i-1]++;
1055 L->init(low_bounds+1,DD+1);
1056 U->init(up_bounds+1,DD+1);
1058 // set bounds of induction variables
1059 delete loops;
1060 loops = new tn_list_iter(al);
1061 int uconstr = up_bounds;
1062 int lconstr = low_bounds;
1063 for (i = DD; i>=1+num_symb; i-=2) { // for each loop
1064 tree_node *induct = loops->step();
1065 dep_for_annote * df = (dep_for_annote *)induct->peek_annote(k_dep_for_annote);
1066 assert(df);
1068 array_info_iter ai(df->lb);
1069 int count = 0;
1071 while (!ai.is_empty()) {
1072 access_vector *lb = ai.step();
1073 if (is_good_symb(lb,symbols)) {
1074 count ++;
1075 (*L)[lconstr][0] = lb->con;
1076 (*L)[lconstr-lb_valid[i]][0] = lb->con;
1077 tn_list_iter temp(al);
1078 temp.set(loops->glist_iter::peek());
1079 int j;
1080 for (j=i-2;j>=1+num_symb;j-=2) {
1081 // for each induct element
1082 assert(!temp.is_empty());
1083 tree_node *element = temp.step();
1084 (*L)[lconstr][j] =
1085 (*L)[lconstr-lb_valid[i]][j-1]
1086 = lb->val(element);
1089 access_list_iter temp_symb(symbols);
1090 for (j=num_symb; j>=1; j--) {
1091 assert(!temp_symb.is_empty());
1092 access_list_e *e = temp_symb.step();
1093 (*L)[lconstr][j] =
1094 (*L)[lconstr-lb_valid[i]][j] =
1095 lb->conregs.val(e->var());
1097 lconstr --;
1101 assert(count == lb_valid[i]);
1102 lconstr -= lb_valid[i];
1103 array_info_iter ai2(df->ub);
1104 count = 0;
1105 while (!ai2.is_empty()) {
1106 access_vector *ub = ai2.step();
1107 if (is_good_symb(ub,symbols)) {
1108 count ++;
1109 (*U)[uconstr][0] = ub->con;
1110 (*U)[uconstr-ub_valid[i]][0] = ub->con;
1111 tn_list_iter temp(al);
1112 temp.set(loops->glist_iter::peek());
1113 int j;
1114 for (j=i-2;j>=1+num_symb;j-=2) {
1115 assert(!temp.is_empty());
1116 tree_node *element = temp.step();
1117 (*U)[uconstr][j] =
1118 (*U)[uconstr-ub_valid[i]][j-1]=
1119 ub->val(element);
1122 access_list_iter temp_symb(symbols);
1123 for (j=num_symb; j>=1; j--) {
1124 assert(!temp_symb.is_empty());
1125 access_list_e *e = temp_symb.step();
1126 (*U)[uconstr][j] =
1127 (*U)[uconstr-ub_valid[i]][j] =
1128 ub->conregs.val(e->var());
1130 uconstr -= 1;
1133 assert(count == ub_valid[i]);
1134 uconstr -= ub_valid[i];
1136 delete loops;
1141 // use the bit vector used to add unused components back into dvector
1142 // if not flow any unused component is a star
1143 void distance_vector::add_unused(boolean *used, int n)
1145 if (indep()) return;
1146 for (int i=0; i<n; i+=2) {
1147 if (!used[i]) {
1148 assert(!used[i+1]);
1149 this->append(*new distance()); // XXX
1150 } else {
1151 this->append(this->pop()->d);
1157 // use the bit vector used to add unused components back into dir_array
1158 // any unused component is a star
1159 void dir_list::add_unused(boolean *used, int n)
1161 assert(n%2==0);
1162 dir_list *temp = this;
1163 while (temp) {
1164 dir_array *dir = temp->data;
1165 distance *new_data = new distance[n/2];
1166 int i2=0;
1167 for (int i=0; i<n; i+=2) {
1168 if (!used[i]) {
1169 assert(!used[i+1]);
1170 new_data[i/2].set_direction(d_star);
1171 } else {
1172 new_data[i/2] = dir->data[i2];
1173 i2++;
1176 delete[] dir->data;
1177 dir->data = new_data;
1178 dir->size = n/2;
1180 temp = temp->next;
1187 // is this access vector good
1188 // it's bad if memregs or conpaths or mod_this is not nil
1189 inline int is_good_symb(access_vector *av1)
1191 return (!av1->too_messy && av1->memregs.is_empty() &&
1192 !av1->mod_this);
1195 // same as above but can only refer to symbols on list
1196 int is_good_symb(access_vector *av1,access_list *symbols)
1198 if (!is_good_symb(av1)) {
1199 return 0;
1201 access_list *temp = new access_list;
1202 temp->unite(symbols,&av1->conregs);
1203 int answer = (temp->count() == symbols->count());
1204 delete temp;
1205 return answer;
1208 // eliminate dimensions which have anything but conregs and induct vars
1209 // and where mod_this is not nil
1210 // return the number of valid dims
1211 int dvlist::elim_bad_symb(array_info *a1, array_info *a2)
1213 array_info_iter ai1(a1);
1214 array_info_iter ai2(a2);
1215 array_info newa1;
1216 array_info newa2;
1218 int valid_dim = 0;
1219 while (!ai1.is_empty() && !ai2.is_empty()) {
1220 access_vector *av1 = ai1.step();
1221 access_vector *av2 = ai2.step();
1223 if(is_good_symb(av1) && is_good_symb(av2)) {
1224 valid_dim++;
1225 newa1.append(new access_vector(av1));
1226 newa2.append(new access_vector(av2));
1229 a1->clear(); a1->glist::append(&newa1);
1230 a2->clear(); a2->glist::append(&newa2);
1231 newa1.clear(); newa2.clear();
1232 return valid_dim;
1235 // return a list of all symbols used in the array_info
1236 // only looks at conregs
1237 access_list *dvlist::find_symb(array_info *a)
1239 access_list *al = new access_list();
1240 array_info_iter *ai = new array_info_iter(a);
1241 while (!ai->is_empty()) {
1242 access_vector *av = ai->step();
1243 al->unite(&av->conregs);
1245 return al;
1248 // return a list of all symbols used in either array_info
1249 // disregard case where for the same dimension, both
1250 // sybols have the same value (ie a[n] vrs a[n])
1251 // only looks at conregs
1252 access_list *dvlist::find_symbs(array_info *a1, array_info *a2)
1254 access_list *al = new access_list();
1255 array_info_iter ai1(a1);
1256 array_info_iter ai2(a2);
1257 while(!ai1.is_empty()) {
1258 assert(!ai2.is_empty());
1259 access_list *temp = unite_unequals(&ai1.step()->conregs,&ai2.step()->conregs);
1261 al->unite(temp);
1262 delete temp;
1264 assert(ai2.is_empty());
1265 return al;
1270 // return the union of two access_lists throwing out elements with the
1271 // same value
1272 access_list *unite_unequals(access_list *a1, access_list *a2)
1274 access_list *result = new access_list();
1276 access_list_iter ai(a1);
1277 while (!ai.is_empty()) {
1278 access_list_e *e = ai.step();
1279 access_list_e *e2 = a2->search(e->var());
1280 if (!e2 || (e2->val() != e->val())) {
1281 result->enter(e->var(),e->val());
1285 access_list_iter ai2(a2);
1286 while (!ai2.is_empty()) {
1287 access_list_e *e = ai2.step();
1288 access_list_e *e2 = a1->search(e->var());
1289 if (!e2 || (e2->val() != e->val())) {
1290 result->enter(e->var(),e->val());
1293 return result;
1296 int distance_vector::operator==(distance_vector &d)
1298 distance_vector_iter ti(this),di(&d);
1299 while(!ti.is_empty() && !di.is_empty()) {
1300 if(ti.step()->d != di.step()->d)
1301 return 0;
1303 return ti.is_empty() && di.is_empty();
1306 static void insert_dvector(dvlist *l,distance_vector *d)
1308 // don't insert any duplicates ... pretty dumb
1309 dvlist_iter di(l);
1310 while(!di.is_empty()) {
1311 if(*di.step()->dv == *d) {
1312 delete d;
1313 return;
1316 l->append(new dvlist_e(d));
1319 static void lexpos_decomp(dvlist *l, distance_vector *d,
1320 boolean strict_pos=FALSE)
1322 assert(d->ind == 0);
1323 distance_vector_iter di(d);
1325 for(int i=1; !di.is_empty(); i++) {
1326 distance_vector_e *dd = di.step();
1327 switch(dd->d.dir()) {
1328 case d_lt:
1329 insert_dvector(l,d);
1330 return;
1331 case d_gt:
1332 delete d;
1333 return;
1334 case d_eq:
1335 break;
1336 case d_le:
1337 case d_star: {
1338 distance_vector *copy1 = new distance_vector(d);
1339 dd->d.set_direction(d_eq);
1340 distance ddd;
1341 ddd.set_direction(d_lt);
1342 copy1->set_entry(ddd,i);
1343 insert_dvector(l,copy1);
1345 break;
1346 case d_ge:
1347 dd->d.set_direction(d_eq);
1348 break;
1349 case d_lg:
1350 dd->d.set_direction(d_lt);
1351 insert_dvector(l,d);
1352 return;
1353 default:
1354 assert(0);
1358 // if strictly lex. positive, DO NOT include loop independent dependences
1359 if (!strict_pos)
1360 insert_dvector(l,d);
1361 else delete d;
1364 void dvlist::make_lexpos(boolean strict_pos)
1366 // make a list of dependence vectors all lexicographically positive.
1367 // actually, makes it lexpos or zero, unless strict_pos is set to TRUE.
1368 // Those who wish can remove blatantly redundant entries from list.
1370 glist l;
1371 while(!is_empty())
1372 l.append(pop());
1374 while(!l.is_empty()) {
1375 dvlist_e *de = (dvlist_e *)l.pop();
1376 lexpos_decomp(this,de->dv,strict_pos);
1377 de->dv = 0;
1378 delete de;