1 /* file "access_vector.cc" */
3 /* Copyright (c) 1994 Stanford University
7 This software is provided under the terms described in
8 the "suif_copyright.h" include file. */
10 #include <suif_copyright.h>
12 #define _MODULE_ "libdependence.a"
13 #pragma implementation "access_vector.h"
19 #include "dependence.h"
24 // allow a[i] where i is a global
25 #define INDEX_IS_FUNKY_PATH
27 int forget_about_mod_this
= 0;
29 /************************************************************************
31 * Add value i if entry for 'v' exists. otherwise create an entry for v *
34 ************************************************************************/
35 void access_list::enter(const void *v
,int i
) // compiler bug, couldn\'t inline
37 access_list_e
*e
=search(v
);
39 int newval
= e
->info
+ i
;
47 ass_list
<int>::enter(v
, i
);
50 int av_compare_access_lists(const access_list
*av
, const access_list
*av2
)
52 // first check that all values on one list are on other
53 access_list_iter
ai(av2
);
54 while(!ai
.is_empty()) {
55 access_list_e
*e
= ai
.step();
56 access_list_e
*ave
= av
->search(e
->var());
57 assert(e
->val() != 0);
61 assert(ave
->val() != 0);
62 if(e
->val() != ave
->val()) return 0;
66 // now check that any values on av but not av2 are zero
67 access_list_iter
avi(av
);
68 while(!avi
.is_empty()) {
69 access_list_e
*e
= avi
.step();
70 if(av2
->search(e
->key
) == 0) {
71 assert(e
->val() != 0);
79 av_compare_info::av_compare_info(const access_vector
*av
,
80 const access_vector
*av2
)
84 assert(!av
->too_messy
&& !av2
->too_messy
);
85 if(av_compare_access_lists(&av
->elts
, &av2
->elts
)) flag
|= 1;
86 if(av_compare_access_lists(&av
->conregs
, &av2
->conregs
)) flag
|= 2;
87 if(av_compare_access_lists(&av
->memregs
, &av2
->memregs
)) flag
|= 4;
88 if(av
->con
== av2
->con
) flag
|= 16;
91 void print_prefix(FILE *f
,int i
,int *first
)
104 void access_vector::print(FILE *f
)
107 fprintf(f
,"<too messy>");
112 access_list_iter
ai(&elts
);
113 while(!ai
.is_empty()) {
114 access_list_e
*e
= ai
.step();
115 tree_node
*n
= (tree_node
*) e
->var();
120 print_prefix(f
,i
,&first
);
121 index
= ((tree_for
*)n
)->index();
122 fprintf(f
,"%s",index
->name());
129 while(!ai
.is_empty()) {
130 access_list_e
*e
= ai
.step();
131 var_sym
* v
= (var_sym
*) e
->var();
132 print_prefix(f
,e
->val(),&first
);
133 fprintf(f
,"%s",v
->name());
136 while(!ai
.is_empty()) {
137 access_list_e
*e
= ai
.step();
138 tree_node
*n
= (tree_node
*) e
->var();
143 print_prefix(f
,i
,&first
);
144 index
= ((tree_for
*)n
)->index();
145 fprintf(f
,"%s",index
->name());
154 fprintf(f
,"+%d",con
);
156 assert(mod_this
->kind() == TREE_FOR
);
157 fprintf(f
,"`mod by: %s'",mod_this
->index()->name());
161 access_vector::~access_vector()
165 while(!elts
.is_empty()) delete elts
.pop();
166 while(!conregs
.is_empty()) delete conregs
.pop();
167 while(!memregs
.is_empty()) delete memregs
.pop();
170 int is_const(const operand
& op
, int *val
)
172 if(!op
.is_instr()) return 0;
173 instruction
* in
= op
.instr();
175 if(in
->opcode() == io_cvt
)
176 return is_const(((in_rrr
*)in
)->src1_op(), val
);
177 if(in
->opcode() != io_ldc
) return 0;
178 immed ic
= ((in_ldc
*) in
)->value();
179 if(ic
.kind() == im_int
) *val
= ic
.integer();
180 return (ic
.kind() == im_int
);
183 tree_for
* is_index(var_sym
* v
, tree_node
*tn
)
186 for(tree_node
*n
= tn
; n
; n
= n
->parent()->parent()) {
187 if(n
->kind() == TREE_FOR
&&
188 ((tree_for
*)n
)->index() == v
)
189 return (tree_for
*) n
;
190 if(n
->parent()==NULL
) break;
195 static void put_index_info(tree_for
* fn
, /* deepest for node */
196 const operand
& op
, /* expression */
203 if(op
.kind() == OPER_SYM
) {
204 if(op
.symbol()->is_var() == 0) {
209 nf
= is_index((var_sym
*)op
.symbol(), fn
);
213 av
->add((var_sym
*)op
.symbol(), 0, factor
);
215 av
->add((var_sym
*)op
.symbol(), 0, factor
);
219 if(op
.kind() != OPER_INSTR
) {
223 instruction
* ins
= op
.instr();
224 in_rrr
*i3r
= (in_rrr
*) ins
;
225 if(ins
->format() == inf_rrr
) {
227 if(is_const(operand(ins
), &val
)) {
228 av
->con
+= val
*factor
;
231 } else if(ins
->format() == inf_ldc
) {
232 in_ldc
* ld
= (in_ldc
*)ins
;
233 if(ld
->value().is_int_const())
234 av
->con
+= ld
->value().integer() * factor
;
239 switch(ins
->opcode()) {
240 // not that io_cvt is too messy. That way we can assume that
241 // lods have the correct type, and in general it allows us
242 // to rebuild from the access vectors.
244 // io_cvt is needed in SGI64 format, so here we go.
246 put_index_info(fn
, i3r
->src1_op(), av
, factor
);
254 // could be a constant path
255 operand s1
= i3r
->src1_op();
256 if(s1
.is_instr() && s1
.instr()->opcode() == io_array
) {
258 // For a bound DO i=1, U(A(0))
259 // returning upper bound to be 0 is incorrect.
261 // all indexes had better be zero or forget it
262 in_array
*ia
= (in_array
*) s1
.instr();
265 for(i
= 0; ((unsigned)i
) < ia
->dims(); i
++) {
267 if(!is_const(ia
->index(i
), &val
) || val
)
270 if(((unsigned)i
) != ia
->dims()) {
274 ins
= s1
.instr(); // look at the base of the array.
280 put_index_info(fn
, i3r
->src1_op(), av
, -factor
);
283 put_index_info(fn
, i3r
->src1_op(), av
, factor
);
284 put_index_info(fn
, i3r
->src2_op(), av
, factor
);
287 put_index_info(fn
, i3r
->src1_op(), av
, factor
);
288 put_index_info(fn
, i3r
->src2_op(), av
, -factor
);
292 // var*const or const*var
293 if(is_const(i3r
->src1_op(), &val
))
294 put_index_info(fn
, i3r
->src2_op(), av
, factor
* val
);
295 else if(is_const(i3r
->src2_op(), &val
))
296 put_index_info(fn
, i3r
->src1_op(), av
, factor
* val
);
306 if(!is_const(i3r
->src2_op(),&val
) || (val
== 0) || factor
% val
)
309 put_index_info(fn
, i3r
->src1_op(), av
, factor
/ val
);
314 if(!is_const(i3r
->src2_op(), &val
) || val
< 0)
317 put_index_info(fn
, i3r
->src1_op(), av
, factor
<<val
);
321 put_index_info(fn
, i3r
->src1_op(), av
, factor
);
326 void access_vector::enter_als(const access_vector
*a
)
328 access_list_iter
ai(&a
->elts
);
329 while (!ai
.is_empty()){
330 access_list_e
* ae
= ai
.step();
331 elts
.enter(ae
->var(),ae
->val());
334 ai
.reset(&a
->conregs
);
335 while (!ai
.is_empty()){
336 access_list_e
* ae
= ai
.step();
337 conregs
.enter(ae
->var(),ae
->val());
340 ai
.reset(&a
->memregs
);
341 while (!ai
.is_empty()){
342 access_list_e
* ae
= ai
.step();
343 memregs
.enter(ae
->var(),ae
->val());
348 access_vector::access_vector(const access_vector
*a
): glist_e()
350 too_messy
= a
-> too_messy
;
351 mod_this
= forget_about_mod_this
? 0 : a
->mod_this
;
367 access_vector::access_vector(const access_vector
&a
): glist_e()
369 too_messy
= a
.too_messy
;
370 mod_this
= forget_about_mod_this
? 0 : a
.mod_this
;
386 access_vector::access_vector(tree_instr
*n
, int fancy
):
387 glist_e(), too_messy(0), con(0)
391 tree_for
* tf
= (tree_for
*)next_further_out(n
, TREE_FOR
);
392 put_index_info(tf
, operand(n
->instr()), this, 1);
395 !(conregs
.is_empty() && memregs
.is_empty()))
397 else if(fancy
== 1 &&
398 !(memregs
.is_empty()))
400 if(!forget_about_mod_this
)
402 //set_min_max(); // gets messed up by normalization
405 access_vector::access_vector(operand op
, tree_node
* tn
, int fancy
):
406 glist_e(), too_messy(0), con(0)
412 tree_for
* tf
= (tree_for
*)next_further_out(tn
, TREE_FOR
, TRUE
);
413 put_index_info(tf
, op
, this, 1);
416 !(conregs
.is_empty() && memregs
.is_empty()))
418 else if(fancy
== 1 &&
419 !(memregs
.is_empty()))
421 if(!forget_about_mod_this
)
424 //set_min_max(); /* gets messed up by normalization */
427 access_vector::access_vector(instruction
* inst
, int fancy
):
428 glist_e(), too_messy(0), con(0)
435 tree_for
* tf
= (tree_for
*)next_further_out(inst
->parent(), TREE_FOR
, TRUE
);
436 put_index_info(tf
, operand(inst
), this, 1);
439 !(conregs
.is_empty() && memregs
.is_empty()))
441 else if(fancy
== 1 &&
442 !(memregs
.is_empty()))
444 if(!forget_about_mod_this
)
446 //set_min_max(); /* gets messed up by normalization */
450 void array_info::print(FILE *f
)
454 array_info_iter
ai(this);
455 while(!ai
.is_empty()) {
456 if(print_comma
++) fprintf(f
,",");
462 array_info::~array_info()
464 while(!is_empty()) delete pop();
467 array_info::array_info(instruction
* ins
, int fancy
)
469 assert(ins
->opcode() == io_array
);
470 in_array
*i
= (in_array
*) ins
;
472 for(int cnt
= 0; ((unsigned)cnt
) < i
->dims(); cnt
++) {
474 av
= new access_vector(i
->index(cnt
), ins
->parent(), fancy
);
480 array_info::array_info(array_info
* ainfo
)
482 array_info_iter
iter(ainfo
);
484 while(!iter
.is_empty()) {
485 access_vector
* av
= iter
.step();
486 append(new access_vector(av
));
490 static void build_block(block
&B
, boolean
&block_empty
, binary_op bop
, block
&A
)
494 case bop_add
: B
.set(A
); break;
495 case bop_sub
: B
.set(-A
); break;
499 else B
.set(B
.dobinop(bop
,A
));
504 operand
access_vector::generate_code(tree_proc
*p
, block_symtab
* sym
)
506 // ignores the step, so if the step\'s not one, be careful!
510 block::set_proc(p
); // block::set_proc(p) didn't compile
512 boolean block_empty
= TRUE
;
514 // Only set the block to the constant value if the constant is non-zero.
520 access_list_iter
ai(&elts
);
521 while (!ai
.is_empty()) {
522 access_list_e
*ae
= ai
.step();
523 tree_for
*a
= (tree_for
*) ae
->var();
525 block
var(a
->index());
527 else if(i
== 1) build_block(B
,block_empty
,bop_add
,var
);
528 else if(i
== -1) build_block(B
,block_empty
,bop_sub
,var
);
531 build_block(B
,block_empty
,bop_add
,multi
*var
);
536 while (!ai
.is_empty()) {
537 access_list_e
*ae
= ai
.step();
538 var_sym
* v
= (var_sym
*) ae
->var();
542 else if(i
== 1) build_block(B
,block_empty
,bop_add
,var
);
543 else if(i
== -1) build_block(B
,block_empty
,bop_sub
,var
);
546 build_block(B
,block_empty
,bop_add
,multi
*var
);
551 while (!ai
.is_empty()) {
552 access_list_e
*ae
= ai
.step();
553 var_sym
* v
= (var_sym
*) ae
->var();
557 else if(i
== 1) build_block(B
,block_empty
,bop_add
,var
);
558 else if(i
== -1) build_block(B
,block_empty
,bop_sub
,var
);
561 build_block(B
,block_empty
,bop_add
,multi
*var
);
565 // If the block is still empty, then add the zero constant.
571 inst
= B
.make_instruction(); // B.make_instruction(sym)
573 inst
= B
.make_instruction();
575 return operand(inst
);
580 void access_vector::operator = (const access_vector
&a
)
582 too_messy
= a
.too_messy
;
593 while(!elts
.is_empty()) delete elts
.pop();
594 while(!conregs
.is_empty()) delete conregs
.pop();
595 while(!memregs
.is_empty()) delete memregs
.pop();
600 void access_vector::operator += (const access_vector
&a
)
626 void access_vector::operator -= (const access_vector
&a
)
631 if(min
) delete min
; min
= 0;
637 if(max
) delete max
; max
= 0;
647 access_list_iter
ai(&a
.elts
);
648 while (!ai
.is_empty()){
649 access_list_e
* ae
= ai
.step();
650 elts
.enter(ae
->var(),-ae
->val());
653 ai
.reset(&a
.conregs
);
654 while (!ai
.is_empty()){
655 access_list_e
* ae
= ai
.step();
656 conregs
.enter(ae
->var(),-ae
->val());
659 ai
.reset(&a
.memregs
);
660 while (!ai
.is_empty()){
661 access_list_e
* ae
= ai
.step();
662 memregs
.enter(ae
->var(),-ae
->val());
667 void access_vector::operator *= (int f
)
683 if(too_messy
|| f
== 1)
694 access_list_iter
ai(&elts
);
695 while (!ai
.is_empty()){
696 access_list_e
* ae
= ai
.step();
697 ae
->info
= ae
->info
* f
;
701 while (!ai
.is_empty()){
702 access_list_e
* ae
= ai
.step();
703 ae
->info
= ae
->info
* f
;
707 while (!ai
.is_empty()){
708 access_list_e
* ae
= ai
.step();
709 ae
->info
= ae
->info
* f
;
714 void access_vector::operator /= (int f
)
724 if (min
) *min
= -*min
;
725 if (max
) *max
= -*max
;
729 if (*min
% f2
== 0) *min
/= f2
;
730 else if (*min
> 0) *min
/= f2
;
731 else *min
= *min
/ f2
- 1;
734 if (*max
% f2
== 0) *max
/= f2
;
735 else if (*max
> 0) *max
= *max
/f2
+ 1;
736 else *max
= *max
/ f2
;
740 if(too_messy
|| f
== 1)
743 if(con
% f
) too_messy
++;
746 access_list_iter
ai(&elts
);
747 while (!ai
.is_empty()){
748 access_list_e
* ae
= ai
.step();
749 if((int) ae
->info
% f
) too_messy
++;
750 else ae
->info
= ae
->info
/ f
;
754 while (!ai
.is_empty()){
755 access_list_e
* ae
= ai
.step();
756 if((int) ae
->info
% f
) too_messy
++;
757 else ae
->info
= ae
->info
/ f
;
761 while (!ai
.is_empty()){
762 access_list_e
* ae
= ai
.step();
763 if((int) ae
->info
% f
) too_messy
++;
764 else ae
->info
= ae
->info
/ f
;
772 // find the innermost for loop which might assign this acceess vector
774 void access_vector::set_mod_this(tree_node
* ti
)
776 assert(forget_about_mod_this
== 0);
780 tree_for
*find_inner(tree_node
*, var_sym
*);
781 int is_ancestor(tree_node
*, tree_node
*);
783 // first find innermost for loop
784 tree_node
*inner
= (tree_node
*) ti
;
785 tree_node
*prev
= inner
;
786 while(inner
->kind() != TREE_FOR
) {
787 assert(inner
->parent());
788 inner
= inner
->parent()->parent();
789 if (!inner
) { // not inside a for loop
796 // go through all the registers
797 access_list_iter
ali(&conregs
);
798 while (!ali
.is_empty()) {
799 access_list_e
*e
= ali
.step();
800 var_sym
* sym
= (var_sym
*)e
->var();
801 tree_for
*temp
= find_inner(inner
, sym
);
803 if(!mod_this
|| is_ancestor(mod_this
, temp
)) {
809 // go through all the memory registers
811 while (!ali
.is_empty()) {
812 access_list_e
*e
= ali
.step();
813 var_sym
* sym
= (var_sym
*)e
->var();
814 tree_for
*temp
= find_inner(inner
, sym
);
816 if(!mod_this
|| is_ancestor(mod_this
,temp
)) {
822 // copout. We need to handle this case eventually ...
823 if (!memregs
.is_empty()) {
824 assert(inner
&& inner
->kind() == TREE_FOR
);
825 mod_this
= (tree_for
*) inner
;
832 // is node 1 an ancestor of node 2
833 int is_ancestor(tree_node
*node1
, tree_node
*node2
)
835 if(node2
->parent() == NULL
) return 0;
836 node2
= node2
->parent()->parent();
838 if (node2
== node1
) return 1;
839 if(node2
->parent() == NULL
) return 0;
840 node2
= node2
->parent()->parent();
846 // find the innermost for loop which might assign a register
847 tree_for
*find_inner(tree_node
*n
, var_sym
* v
)
852 if (n
->kind() == TREE_FOR
) {
853 tree_for
*tnf
= (tree_for
*)n
;
854 if (sym_modified(v
, tnf
->body(), prev
)) {
856 } else if (sym_modified(v
, tnf
->ub_list(), prev
)) {
858 } else if (sym_modified(v
, tnf
->step_list(), prev
)) {
860 } else if (sym_modified(v
, tnf
->lb_list(), prev
)) {
866 n
= (n
->parent())?n
->parent()->parent():NULL
;
873 // routines to manipulate access lists
875 // set the union of two lists
876 void access_list::unite(access_list
*a1
, access_list
*a2
)
878 access_list_iter
ai(a1
);
879 while(!ai
.is_empty()) {
880 access_list_e
*e
= ai
.step();
881 enter(e
->var(),e
->val());
883 access_list_iter
ai2(a2
);
884 while(!ai2
.is_empty()) {
885 access_list_e
*e
= ai2
.step();
886 if (!this->search(e
->var())) {
887 enter(e
->var(),e
->val());
892 // set the union of this to another list
893 void access_list::unite(access_list
*a1
)
895 access_list_iter
ai(a1
);
896 while(!ai
.is_empty()) {
897 access_list_e
*e
= ai
.step();
898 if (!this->search(e
->var())) {
899 enter(e
->var(),e
->val());
904 // set the intersection of two lists
905 void access_list::intersect(access_list
*a1
, access_list
*a2
)
907 access_list_iter
ai(a1
);
908 while(!ai
.is_empty()) {
909 access_list_e
*e
= ai
.step();
910 if (a2
->search(e
->var())){
911 enter(e
->var(),e
->val());
916 // set the intersection of this to another list
917 void access_list::intersect(access_list
*a1
)
919 access_list_iter
ai(this);
920 while(!ai
.is_empty()) {
921 access_list_e
*e
= ai
.step();
922 if (!a1
->search(e
->var())){
929 int access_list::count()
932 access_list_iter
ai(this);
933 for (cnt
=0; !ai
.is_empty(); ai
.step()) cnt
++;
937 // find the min and max of this access_vector
938 void access_vector::set_min_max()
949 if (too_messy
|| !conregs
.is_empty() ||
950 !memregs
.is_empty()) {
959 access_list_iter
ai(&elts
);
960 while(!ai
.is_empty()) {
961 access_list_e
*induct
= ai
.step();
962 int value
= induct
->val();
965 dep_for_annote
*dfa
= NULL
; // = (tree_for *) induct->var();
970 array_info_iter
ai(dfa
->lb
);
971 while (!ai
.is_empty()) {
972 access_vector
*av
= ai
.step();
973 if (!av
->too_messy
&& av
->min
) {
974 if (!formin
|| (*av
->min
< *formin
)) {
982 array_info_iter
ai2(dfa
->ub
);
983 while (!ai2
.is_empty()) {
984 access_vector
*av
= ai2
.step();
985 if (!av
->too_messy
&& av
->max
) {
986 if (!formax
|| (*av
->max
> *formax
)) {
993 int *fmin
= value
> 0 ? formin
: formax
;
994 int *fmax
= value
> 0 ? formax
: formin
;
997 *min
= *min
+ value
* *fmin
;
1003 *max
= *max
+ value
* *fmax
;