OSDN Git Service

* config/xtensa/xtensa.md: Remove unused type attributes.
[pf3gnuchains/gcc-fork.git] / gcc / dependence.c
1 /* Analyze loop dependencies
2    Copyright (C) 2000, 2002 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.  */
20
21 /* References:
22    Practical Dependence Testing, Goff, Kennedy, Tseng, PLDI, 1991
23    High Performance Compilers for Parallel Computing, Wolfe
24 */
25
26 #include "config.h"
27 #include "system.h"
28
29 #include "rtl.h"
30 #include "expr.h"
31 #include "tree.h"
32 #include "c-common.h"
33 #include "flags.h"
34 #include "varray.h"
35
36 #define MAX_SUBSCRIPTS 13
37
38 /*
39    We perform the following steps:
40
41    Build the data structures def_use_chain, loop_chain, and induction_chain.
42
43    Determine if a loop index is a normalized induction variable.
44    A loop is currently considered to be a for loop having an index set to an
45    initial value, conditional check of the index, and increment/decrement of
46    the index.
47
48    Determine the distance and direction vectors.  Both are two dimensioned
49    arrays where the first dimension represents a loop and the second
50    dimension represents a subscript.  Dependencies are actually per loop, not
51    per subscript.  So for:
52    for (i = 0; i < 10; i++)
53        for (j = 0; j < 10; j++)
54            array [i][j] = array[i][j-1]
55    We find the dependencies: loop1/sub_i, loop1/sub_j, loop2/sub_i, loop2/sub_j
56    and then intersect loop1/sub_i V loop2/sub_i and loop1/sub_i V loop2/sub_j
57    We determine the type of dependence, which determines which test we use.
58    We then try to refine the type of dependence we have and add the
59    dependence to the dep_chain
60 */
61
62 enum dependence_type {dt_flow, dt_anti, dt_output, dt_none};
63 #if 0
64 static const char *const dependence_string [] = {"flow", "anti", "output", "none"};
65 #endif
66 enum direction_type {lt, le, eq, gt, ge, star, independent, undef};
67 #if 0
68 static const char *const direction_string [] = {"<", "<=", "=", ">", ">=", "*",
69                                            "INDEPENDENT", "UNDEFINED"};
70 #endif
71 enum def_use_type {def, use, init_def_use};
72
73 enum du_status_type {seen, unseen};
74
75 enum loop_status_type {normal, unnormal};
76
77 enum complexity_type {ziv, strong_siv, weak_siv, weak_zero_siv,
78                       weak_crossing_siv, miv};
79
80 /* Given a def/use one can chase the next chain to follow the def/use
81    for that variable.  Alternately one can sequentially follow each
82    element of def_use_chain.  */
83
84 typedef struct def_use
85 {
86   /* outermost loop */
87   tree outer_loop;
88   /* loop containing this def/use */
89   tree containing_loop;
90   /* this expression */
91   tree expression;
92   /* our name */
93   const char *variable;
94   /* def or use */
95   enum def_use_type type;
96   /* status flags */
97   enum du_status_type status;
98   /* next def/use for this same name */
99   struct def_use *next;
100   /* dependencies for this def */
101   struct dependence *dep;
102 } def_use;
103
104 /* Given a loop* one can chase the next_nest chain to follow the nested
105    loops for that loop.  Alternately one can sequentially follow each
106    element of loop_chain and check outer_loop to get all loops
107    contained within a certain loop.  */
108
109 typedef struct loop
110 {
111   /* outermost loop containing this loop */
112   tree outer_loop;
113   /* this loop */
114   tree containing_loop;
115   /* nest level for this loop */
116   int  depth;
117   /* can loop be normalized? */
118   enum loop_status_type status;
119   /* loop* for loop contained in this loop */
120   struct loop *next_nest;
121   /* induction variables for this loop.  Currently only the index variable.  */
122   struct induction *ind;
123 } loop;
124
125 /* Pointed to by loop. One per induction variable.  */
126
127 typedef struct induction
128 {
129   /* our name */
130   const char *variable;
131   /* increment.  Currently only +1 or -1 */
132   int  increment;
133   /* lower bound */
134   int  low_bound;
135   /* upper bound */
136   int  high_bound;
137   /* next induction variable for this loop.  Currently null.  */
138   struct induction *next;
139 } induction;
140
141 /* Pointed to by def/use.  One per dependence.  */
142
143 typedef struct dependence
144 {
145   tree source;
146   tree destination;
147   enum dependence_type dependence;
148   enum direction_type direction[MAX_SUBSCRIPTS];
149   int distance[MAX_SUBSCRIPTS];
150   struct dependence *next;
151 } dependence;
152   
153 /* subscripts are represented by an array of these.  Each reflects one
154    X * i + Y term, where X and Y are constants.  */
155
156 typedef struct subscript
157 {
158   /* ordinal subscript number */
159   int position;
160   /* X in X * i + Y */
161   int coefficient;
162   /* Y in X * i + Y */
163   int offset;
164   /* our name */
165   const char *variable;
166   /* next subscript term.  Currently null.  */
167   struct subscript *next;
168 } subscript;
169
170 /* Remember the destination the front end encountered.  */
171
172 static tree dest_to_remember;
173
174 /* Chain for def_use */
175 static varray_type def_use_chain;
176
177 /* Chain for dependence */
178 static varray_type dep_chain;
179
180 /* Chain for loop */
181 static varray_type loop_chain;
182
183 /* Chain for induction */
184 static varray_type induction_chain;
185
186 void init_dependence_analysis PARAMS ((tree));
187 static void build_def_use PARAMS ((tree, enum def_use_type));
188 static loop* add_loop PARAMS ((tree, tree, int));
189 static int find_induction_variable PARAMS ((tree, tree, tree, loop*));
190 static int get_low_bound PARAMS ((tree, const char*));
191 static int have_induction_variable PARAMS ((tree, const char*));
192 static void link_loops PARAMS ((void));
193 static void get_node_dependence PARAMS ((void));
194 static void check_node_dependence PARAMS ((def_use*));
195 static int get_coefficients PARAMS ((def_use*, subscript[]));
196 static int get_one_coefficient PARAMS ((tree, subscript*, def_use*, enum tree_code*));
197 static void normalize_coefficients PARAMS ((subscript[], loop*, int));
198 static void classify_dependence PARAMS ((subscript[], subscript[],
199                                  enum complexity_type[], int*, int));
200 static void ziv_test PARAMS ((subscript[], subscript[],
201                               enum direction_type[][MAX_SUBSCRIPTS],
202                               int[][MAX_SUBSCRIPTS], loop*, int));
203 static void siv_test PARAMS ((subscript[], subscript[],
204                               enum direction_type[][MAX_SUBSCRIPTS],
205                               int[][MAX_SUBSCRIPTS], loop*, int));
206 static int check_subscript_induction PARAMS ((subscript*, subscript*, loop*));
207 static void gcd_test PARAMS ((subscript[], subscript[], enum
208                               direction_type[][MAX_SUBSCRIPTS],
209                               int[][MAX_SUBSCRIPTS], loop*, int));
210 static int find_gcd PARAMS ((int, int));
211 static void merge_dependencies PARAMS ((enum direction_type[][MAX_SUBSCRIPTS],
212                                         int[][MAX_SUBSCRIPTS], int, int));
213 static void dump_array_ref PARAMS ((tree));
214 #if 0
215 static void dump_one_node PARAMS ((def_use*, varray_type*));
216 static void dump_node_dependence PARAMS ((void));
217 #endif
218 int search_dependence PARAMS ((tree));
219 void remember_dest_for_dependence PARAMS ((tree));
220 int have_dependence_p PARAMS ((rtx, rtx, enum direction_type[], int[]));
221 void end_dependence_analysis PARAMS ((void));
222
223 /* Build dependence chain 'dep_chain', which is used by have_dependence_p,
224    for the function given by EXP.  */
225
226 void
227 init_dependence_analysis (exp)
228      tree exp;
229 {
230   def_use *du_ptr;
231
232   VARRAY_GENERIC_PTR_INIT (def_use_chain, 50, "def_use_chain");
233   VARRAY_GENERIC_PTR_INIT (dep_chain, 50, "dep_chain");
234   VARRAY_GENERIC_PTR_INIT (loop_chain, 50, "loop_chain");
235   VARRAY_GENERIC_PTR_INIT (induction_chain, 50, "induction_chain");
236
237   build_def_use (exp, init_def_use);
238
239   link_loops ();
240
241   get_node_dependence ();
242
243   /* dump_node_dependence (&def_use_chain);*/
244
245   for (du_ptr = VARRAY_TOP (def_use_chain, generic);
246        VARRAY_POP (def_use_chain);
247        du_ptr = VARRAY_TOP (def_use_chain, generic))
248     {
249       free (du_ptr);
250     }
251
252   VARRAY_FREE (def_use_chain);
253   VARRAY_FREE (loop_chain);
254   VARRAY_FREE (induction_chain);
255 }
256
257 /* Build ARRAY_REF def/use info 'def_use_chain' starting at EXP which is a def
258    or use DU_TYPE */ 
259
260 static void
261 build_def_use (exp, du_type)
262      tree exp;
263      enum def_use_type du_type;
264 {
265   static tree outer_loop;
266   static int nloop;
267   static tree current_loop;
268   static int du_idx;
269   static loop *loop_def;
270   tree node = exp;
271   tree array_ref;
272   def_use *du_ptr;
273
274   if (du_type == init_def_use)
275     {
276       outer_loop = 0;
277       nloop = 0;
278       du_idx = 0;
279     }
280   
281   while (node)
282     switch (TREE_CODE (node))
283       {
284       case COMPOUND_STMT:
285         node = TREE_OPERAND (node, 0);
286         break;
287       case TREE_LIST:
288         build_def_use (TREE_VALUE (node), 0);
289         node = TREE_CHAIN (node);
290         break;
291       case CALL_EXPR:
292         node = TREE_CHAIN (node);
293         break;
294       case FOR_STMT:
295         if (! nloop) outer_loop = node;
296         nloop++;
297         current_loop = node;
298         loop_def = add_loop (node, outer_loop, nloop);
299         if (find_induction_variable (TREE_OPERAND (node, 0),
300                                      TREE_OPERAND (node, 1),
301                                      TREE_OPERAND (node, 2), loop_def)
302             == 0)
303           loop_def->status = unnormal;
304           
305         build_def_use (TREE_OPERAND (node, 3), 0);
306         nloop--;
307         current_loop = 0;
308         node = TREE_CHAIN (node);
309         break;
310       case MODIFY_EXPR:
311         /* Is an induction variable modified? */
312         if (loop_def 
313             && TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL
314             && have_induction_variable
315                (loop_def->outer_loop,
316                 IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (node, 0)))) >= 0)
317           loop_def->status = unnormal;
318
319         if (TREE_CODE (TREE_OPERAND (node, 0)) == ARRAY_REF
320             || TREE_CODE (TREE_OPERAND (node, 0)) == INDIRECT_REF)
321           build_def_use (TREE_OPERAND (node, 0), def);
322
323         build_def_use (TREE_OPERAND (node, 1), use);
324         node = TREE_CHAIN (node);
325         break;
326       case INDIRECT_REF:
327         if (! TREE_OPERAND (node, 1)
328             || TREE_CODE (TREE_OPERAND (node, 1)) != ARRAY_REF)
329           {
330             node = 0;
331             break;
332           }
333         node = TREE_OPERAND (node, 1);
334       case ARRAY_REF:
335         if (nloop)
336           {
337             int i;
338             char null_string = '\0';
339
340             VARRAY_PUSH_GENERIC_PTR (def_use_chain, xmalloc (sizeof (def_use)));
341             du_ptr = VARRAY_GENERIC_PTR (def_use_chain, du_idx++);
342             du_ptr->type = du_type;
343             du_ptr->status = unseen;
344             du_ptr->outer_loop = outer_loop;
345             du_ptr->containing_loop = current_loop;
346             du_ptr->expression = node;
347             du_ptr->variable = &null_string;
348             du_ptr->next = 0;
349             du_ptr->dep = 0;
350             for (array_ref = node;
351                  TREE_CODE (array_ref) == ARRAY_REF;
352                  array_ref = TREE_OPERAND (array_ref, 0))
353               ;
354
355             if (TREE_CODE (array_ref) == COMPONENT_REF)
356               {
357                 array_ref = TREE_OPERAND (array_ref, 1);
358                 if (! (TREE_CODE (array_ref) == FIELD_DECL
359                        && TREE_CODE (TREE_TYPE (array_ref)) == ARRAY_TYPE))
360                   {
361                     node = 0;
362                     break;
363                   }
364               }
365             
366             for (i = 0;
367                  i < du_idx
368                    && strcmp (IDENTIFIER_POINTER (DECL_NAME (array_ref)),
369                               ((def_use*) (VARRAY_GENERIC_PTR
370                                            (def_use_chain, i)))->variable);
371                  i++)
372               ;
373             if (i != du_idx)
374               {
375                 def_use *tmp_duc;
376                 for (tmp_duc = ((def_use*) (VARRAY_GENERIC_PTR (def_use_chain, i)));
377                      tmp_duc->next;
378                      tmp_duc = ((def_use*)tmp_duc->next));
379                 tmp_duc->next = du_ptr;
380               }
381             else du_ptr->next = 0;
382             du_ptr->variable = IDENTIFIER_POINTER (DECL_NAME (array_ref));
383           }
384         node = 0;
385         break;
386
387       case SCOPE_STMT:
388       case DECL_STMT:
389         node = TREE_CHAIN (node);
390         break;
391         
392       case EXPR_STMT:
393         if (TREE_CODE (TREE_OPERAND (node, 0)) == MODIFY_EXPR)
394           build_def_use (TREE_OPERAND (node, 0), def);
395         node = TREE_CHAIN (node);
396         break;
397
398       default:
399         if (TREE_CODE_CLASS (TREE_CODE (node)) == '2')
400           {
401             build_def_use (TREE_OPERAND (node, 0), use);
402             build_def_use (TREE_OPERAND (node, 1), use);
403             node = TREE_CHAIN (node);
404           }
405         else
406           node = 0;
407       }
408 }
409
410 /* Add a loop to 'loop_chain' corresponding to for loop LOOP_NODE at depth
411    NLOOP, whose outermost loop is OUTER_LOOP */
412
413 static loop*
414 add_loop (loop_node, outer_loop, nloop)
415      tree loop_node;
416      tree outer_loop;
417      int nloop;
418 {
419   loop *loop_ptr;
420
421   VARRAY_PUSH_GENERIC_PTR (loop_chain, xmalloc (sizeof (loop)));
422   loop_ptr = VARRAY_TOP (loop_chain, generic);
423   loop_ptr->outer_loop = outer_loop;
424   loop_ptr->containing_loop = loop_node;
425   loop_ptr->depth = nloop;
426   loop_ptr->status = normal;
427   loop_ptr->next_nest = 0;
428   loop_ptr->ind = 0;
429   return loop_ptr;
430 }
431
432 /* Update LOOP_DEF if for loop's COND_NODE and INCR_NODE define an index that
433    is a normalized induction variable.  */
434
435 static int
436 find_induction_variable (init_node, cond_node, incr_node, loop_def)
437      tree init_node;
438      tree cond_node;
439      tree incr_node;
440      loop *loop_def;
441 {
442   induction *ind_ptr;
443   enum tree_code incr_code;
444   tree incr;
445
446   if (! init_node || ! incr_node || ! cond_node)
447     return 0;
448   /* Allow for ',' operator in increment expression of FOR */
449
450   incr = incr_node;
451   while (TREE_CODE (incr) == COMPOUND_EXPR)
452     {
453       incr_code = TREE_CODE (TREE_OPERAND (incr, 0));
454       if (incr_code == PREDECREMENT_EXPR || incr_code == POSTDECREMENT_EXPR
455           || incr_code == PREINCREMENT_EXPR || incr_code == POSTINCREMENT_EXPR)
456         {
457           incr_node = TREE_OPERAND (incr, 0);
458           break;
459         }
460       incr_code = TREE_CODE (TREE_OPERAND (incr, 1));
461       if (incr_code == PREDECREMENT_EXPR || incr_code == POSTDECREMENT_EXPR
462           || incr_code == PREINCREMENT_EXPR || incr_code == POSTINCREMENT_EXPR)
463         {
464           incr_node = TREE_OPERAND (incr, 1);
465           break;
466         }
467       incr = TREE_OPERAND (incr, 1);
468     }
469
470   /* Allow index condition to be part of logical expression */
471   cond_node = TREE_VALUE (cond_node);
472   incr = cond_node;
473
474 #define INDEX_LIMIT_CHECK(NODE) \
475       (TREE_CODE_CLASS (TREE_CODE (NODE)) == '<') \
476         && (TREE_CODE (TREE_OPERAND (NODE, 0)) == VAR_DECL \
477             && (IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (NODE, 0))) \
478                 == IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (incr_node, 0))))) \
479       ? 1 : 0
480
481   while (TREE_CODE (incr) == TRUTH_ANDIF_EXPR
482          || TREE_CODE (incr) == TRUTH_ORIF_EXPR)
483     {
484       if (INDEX_LIMIT_CHECK (TREE_OPERAND (incr, 0)))
485           {
486             cond_node = TREE_OPERAND (incr, 0);
487             break;
488           }
489       if (INDEX_LIMIT_CHECK (TREE_OPERAND (incr, 1)))
490           {
491             cond_node = TREE_OPERAND (incr, 1);
492             break;
493           }
494       incr = TREE_OPERAND (incr, 0);
495     }
496
497   incr_code = TREE_CODE (incr_node);
498   if ((incr_code == PREDECREMENT_EXPR || incr_code == POSTDECREMENT_EXPR
499        || incr_code == PREINCREMENT_EXPR || incr_code == POSTINCREMENT_EXPR)
500       && TREE_CODE_CLASS (TREE_CODE (cond_node)) == '<')
501     {
502       if (!INDEX_LIMIT_CHECK (cond_node))
503         return 0;
504
505       VARRAY_PUSH_GENERIC_PTR (induction_chain, xmalloc (sizeof (induction)));
506       ind_ptr = VARRAY_TOP (induction_chain, generic);
507       loop_def->ind = ind_ptr;
508       ind_ptr->variable = IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND
509                                                          (incr_node, 0)));
510       ind_ptr->increment = TREE_INT_CST_LOW (TREE_OPERAND (incr_node, 1));
511       if (TREE_CODE (incr_node) == PREDECREMENT_EXPR
512           || TREE_CODE (incr_node) == POSTDECREMENT_EXPR)
513         ind_ptr->increment = -ind_ptr->increment;
514
515       ind_ptr->low_bound = get_low_bound (init_node, ind_ptr->variable);
516       if (TREE_CODE (TREE_OPERAND (cond_node, 0)) == VAR_DECL
517           && IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (cond_node, 0))) 
518              == ind_ptr->variable)
519         {
520           if (TREE_CODE (TREE_OPERAND (cond_node, 1)) == INTEGER_CST)
521             ind_ptr->high_bound =
522               TREE_INT_CST_LOW (TREE_OPERAND (cond_node, 1));
523           else
524             ind_ptr->high_bound = ind_ptr->increment < 0 ? INT_MIN : INT_MAX;
525         }
526       else if (TREE_CODE (TREE_OPERAND (cond_node, 1)) == VAR_DECL
527           && IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (cond_node, 1)))
528                == ind_ptr->variable)
529         {
530           if (TREE_CODE (TREE_OPERAND (cond_node, 0)) == INTEGER_CST)
531             ind_ptr->high_bound =
532               TREE_INT_CST_LOW (TREE_OPERAND (cond_node, 0));
533           else
534             ind_ptr->high_bound = ind_ptr->increment < 0 ? INT_MIN : INT_MAX;
535         }
536       ind_ptr->next = 0;
537       return 1;
538     }
539   return 0;
540 }
541
542 /* Return the low bound for induction VARIABLE in NODE */
543
544 static int
545 get_low_bound (node, variable)
546      tree node;
547      const char *variable;
548 {
549
550   if (TREE_CODE (node) == SCOPE_STMT)
551     node = TREE_CHAIN (node);
552
553   if (! node)
554     return INT_MIN;
555
556   while (TREE_CODE (node) == COMPOUND_EXPR)
557     {
558       if (TREE_CODE (TREE_OPERAND (node, 0)) == MODIFY_EXPR
559           && (TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL
560               && IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (node, 0)))
561               == variable))
562         break;
563     }
564
565   if (TREE_CODE (node) == EXPR_STMT)
566     node = TREE_OPERAND (node, 0);
567   if (TREE_CODE (node) == MODIFY_EXPR
568       && (TREE_CODE (TREE_OPERAND (node, 0)) == VAR_DECL
569           && IDENTIFIER_POINTER (DECL_NAME (TREE_OPERAND (node, 0)))
570           == variable))
571     {
572       return TREE_INT_CST_LOW (TREE_OPERAND (node, 1));
573     }
574   return INT_MIN;
575 }
576
577
578 /* Return the ordinal subscript position for IND_VAR if it is an induction
579    variable contained in OUTER_LOOP, otherwise return -1.  */
580
581 static int
582 have_induction_variable (outer_loop, ind_var)
583      tree outer_loop;
584      const char *ind_var;
585 {
586   induction *ind_ptr;
587   loop *loop_ptr;
588   unsigned int ind_idx = 0;
589   unsigned int loop_idx = 0;
590
591   for (loop_ptr = VARRAY_GENERIC_PTR (loop_chain, loop_idx);
592        loop_ptr && loop_idx < VARRAY_SIZE (loop_chain);
593        loop_ptr = VARRAY_GENERIC_PTR (loop_chain, ++loop_idx))
594     if (loop_ptr->outer_loop == outer_loop)
595       for (ind_ptr = loop_ptr->ind;
596            ind_ptr && ind_idx < VARRAY_SIZE (induction_chain);
597            ind_ptr = ind_ptr->next)
598         {
599           if (! strcmp (ind_ptr->variable, ind_var))
600             return loop_idx + 1;
601         }
602   return -1;
603 }
604
605 /* Chain the nodes of 'loop_chain'.  */
606
607 static void
608 link_loops ()
609 {
610   unsigned int loop_idx = 0;
611   loop *loop_ptr, *prev_loop_ptr = 0;
612
613   prev_loop_ptr = VARRAY_GENERIC_PTR (loop_chain, loop_idx);
614   for (loop_ptr = VARRAY_GENERIC_PTR (loop_chain, ++loop_idx);
615        loop_ptr && loop_idx < VARRAY_SIZE (loop_chain);
616        loop_ptr = VARRAY_GENERIC_PTR (loop_chain, ++loop_idx))
617     {
618       if (prev_loop_ptr->outer_loop == loop_ptr->outer_loop)
619         {
620           if (prev_loop_ptr->depth == loop_ptr->depth - 1)
621             prev_loop_ptr->next_nest = loop_ptr;
622           prev_loop_ptr = loop_ptr;
623         }
624     }
625 }
626
627 /* Check the dependence for each member of 'def_use_chain'.  */
628
629 static void
630 get_node_dependence ()
631 {
632   unsigned int du_idx;
633   def_use *du_ptr;
634
635   du_idx = 0;
636   for (du_ptr = VARRAY_GENERIC_PTR (def_use_chain, du_idx);
637        du_ptr && du_idx < VARRAY_SIZE (def_use_chain);
638        du_ptr = VARRAY_GENERIC_PTR (def_use_chain, du_idx++))
639     {
640       if (du_ptr->status == unseen)
641         check_node_dependence (du_ptr);
642     }
643 }
644
645 /* Check the dependence for definition DU.  */
646
647 static void
648 check_node_dependence (du)
649      def_use *du;
650 {
651   def_use *def_ptr, *use_ptr;
652   dependence *dep_ptr, *dep_list;
653   subscript icoefficients[MAX_SUBSCRIPTS];
654   subscript ocoefficients[MAX_SUBSCRIPTS];
655   loop *loop_ptr, *ck_loop_ptr;
656   unsigned int loop_idx = 0;
657   int distance[MAX_SUBSCRIPTS][MAX_SUBSCRIPTS];
658   int i, j;
659   int subscript_count;
660   int unnormal_loop;
661   enum direction_type direction[MAX_SUBSCRIPTS][MAX_SUBSCRIPTS];
662   enum complexity_type complexity[MAX_SUBSCRIPTS];
663   int separability;
664   int have_dependence;
665
666   for (j = 1 ; j < MAX_SUBSCRIPTS; j++)
667     {
668       direction[j][0] = undef;
669       distance[j][0] = 0;
670     }
671
672   for (def_ptr = du; def_ptr; def_ptr = def_ptr->next)
673     {
674       if (def_ptr->type != def)
675           continue;
676       subscript_count = get_coefficients (def_ptr, ocoefficients);
677       if (subscript_count < 0)
678         continue;
679
680       loop_idx = 0;
681       for (loop_ptr = VARRAY_GENERIC_PTR (loop_chain, loop_idx);
682            loop_ptr && loop_idx < VARRAY_SIZE (loop_chain);
683            loop_ptr = VARRAY_GENERIC_PTR (loop_chain, ++loop_idx))
684         {
685           if (loop_ptr->outer_loop == def_ptr->outer_loop)
686             break;
687         }
688
689       unnormal_loop = 0;
690       for (ck_loop_ptr = loop_ptr;
691            ck_loop_ptr && loop_idx < VARRAY_SIZE (loop_chain);
692            ck_loop_ptr = VARRAY_GENERIC_PTR (loop_chain, ++loop_idx))
693         {
694           if (ck_loop_ptr->outer_loop == def_ptr->outer_loop
695               && ck_loop_ptr->status == unnormal)
696             unnormal_loop = 1;
697         }
698       if (unnormal_loop)
699         continue;
700
701       normalize_coefficients (ocoefficients, loop_ptr, subscript_count);
702
703       for (use_ptr = du; use_ptr; use_ptr = use_ptr->next)
704         {
705           if (def_ptr == use_ptr
706               || def_ptr->outer_loop != use_ptr->outer_loop)
707             continue;
708           def_ptr->status = seen;
709           use_ptr->status = seen;
710           subscript_count =  get_coefficients (use_ptr, icoefficients);
711           normalize_coefficients (icoefficients, loop_ptr, subscript_count);
712           classify_dependence (icoefficients, ocoefficients, complexity,
713                                &separability, subscript_count);
714
715           for (i = 1, ck_loop_ptr = loop_ptr; ck_loop_ptr; i++)
716             {
717               for (j = 1; j <= subscript_count; j++)
718                 {
719                   direction[i][j] = star;
720                   distance[i][j] = INT_MAX;
721                   if (separability && complexity[j] == ziv)
722                     ziv_test (icoefficients, ocoefficients, direction, distance,
723                               ck_loop_ptr, j);
724                   else if (separability
725                            && (complexity[j] == strong_siv
726                                || complexity[j] == weak_zero_siv
727                                || complexity[j] == weak_crossing_siv))
728                     siv_test (icoefficients, ocoefficients, direction, distance,
729                               ck_loop_ptr, j);
730                   else
731                     gcd_test (icoefficients, ocoefficients, direction, distance,
732                               ck_loop_ptr, j);
733                   /* ?? Add other tests: single variable exact test, banerjee */
734                 }
735             
736               ck_loop_ptr = ck_loop_ptr->next_nest;
737             }
738
739           merge_dependencies (direction, distance, i - 1, j - 1);
740
741           have_dependence = 0;
742           for (j = 1; j <= i - 1; j++)
743             {
744               if (direction[j][0] != independent)
745                 have_dependence = 1;
746             }
747           if (! have_dependence)
748             continue;
749
750           VARRAY_PUSH_GENERIC_PTR (dep_chain, xmalloc (sizeof (dependence)));
751           dep_ptr = VARRAY_TOP (dep_chain, generic);
752           dep_ptr->source = use_ptr->expression;
753           dep_ptr->destination = def_ptr->expression;
754           dep_ptr->next = 0;
755           
756           if (def_ptr < use_ptr && use_ptr->type == use) 
757             dep_ptr->dependence = dt_flow;
758           else if (def_ptr > use_ptr && use_ptr->type == use)
759             dep_ptr->dependence = dt_anti;
760           else dep_ptr->dependence = dt_output;
761
762           for (j = 1 ; j <= i - 1 ; j++)
763             {
764               if (direction[j][0] == gt)
765                 {
766                   dep_ptr->dependence = dt_anti;
767                   direction[j][0] = lt;
768                   distance[j][0] = -distance[j][0];
769                   break;
770                 }
771               else if (direction[j][0] == lt)
772                 {
773                   dep_ptr->dependence = dt_flow;
774                   break;
775                 }
776             }
777           for (j = 1 ; j < MAX_SUBSCRIPTS ; j++)
778             {
779               dep_ptr->direction[j] = direction[j][0];
780               dep_ptr->distance[j] = distance[j][0];
781             }
782
783           for (dep_list = def_ptr->dep ;
784                dep_list && dep_list->next ;
785                dep_list = dep_list->next)
786             ;
787
788           if (! dep_list)
789             {
790               /* Dummy for rtl interface */
791               dependence *dep_root_ptr;
792
793               VARRAY_PUSH_GENERIC_PTR (dep_chain, xmalloc (sizeof (dependence)));
794               dep_root_ptr = VARRAY_TOP (dep_chain, generic);
795               dep_root_ptr->source = 0;
796               dep_root_ptr->destination = def_ptr->expression;
797               dep_root_ptr->dependence = dt_none;
798               dep_root_ptr->next = dep_ptr;
799               def_ptr->dep = dep_ptr;
800             }
801           else
802             dep_list->next = dep_ptr;
803         }
804     }
805 }
806
807 /* Get the COEFFICIENTS and offset for def/use DU.  */
808
809 static int
810 get_coefficients (du, coefficients)
811      def_use *du;
812      subscript coefficients [MAX_SUBSCRIPTS];
813 {
814   int idx = 0;
815   int array_count;
816   int i;
817   tree array_ref;
818
819   array_count = 0;
820   for (array_ref = du->expression;
821        TREE_CODE (array_ref) == ARRAY_REF;
822        array_ref = TREE_OPERAND (array_ref, 0))
823     array_count += 1;
824
825   idx = array_count;
826
827   for (i = 0; i < MAX_SUBSCRIPTS; i++)
828     {
829       coefficients[i].position = 0;
830       coefficients[i].coefficient = INT_MIN;
831       coefficients[i].offset = INT_MIN;
832       coefficients[i].variable = 0;
833       coefficients[i].next = 0;
834     }
835   
836   for (array_ref = du->expression;
837        TREE_CODE (array_ref) == ARRAY_REF;
838        array_ref = TREE_OPERAND (array_ref, 0))
839     {
840       if (TREE_CODE (TREE_OPERAND (array_ref, 1)) == INTEGER_CST)
841         coefficients[idx].offset = TREE_INT_CST_LOW (TREE_OPERAND (array_ref, 1));
842       else
843         if (get_one_coefficient (TREE_OPERAND (array_ref, 1),
844                                  &coefficients[idx], du, 0) < 0)
845           return -1;
846       idx = idx - 1;
847     }
848   return array_count;
849 }
850
851 /* Get the COEFFICIENTS and offset for NODE having TYPE and defined in DU.  */
852
853 static int
854 get_one_coefficient (node, coefficients, du, type)
855      tree node;
856      subscript *coefficients;
857      def_use *du;
858      enum tree_code *type;
859 {
860   enum tree_code  tree_op, tree_op_code;
861   int index, value;
862
863   tree_op = TREE_CODE (node);
864   if (type)
865     *type = tree_op;
866
867   if (tree_op == VAR_DECL)
868     {
869       index = have_induction_variable (du->outer_loop,
870                                        IDENTIFIER_POINTER (DECL_NAME (node)));
871       if (index >= 0)
872         {
873           coefficients->position = index;
874           coefficients->variable = IDENTIFIER_POINTER (DECL_NAME (node));
875           coefficients->coefficient = 1;
876           if (coefficients->offset == INT_MIN)
877             coefficients->offset = 0;
878         }
879       return index;
880     }
881   else if (tree_op == INTEGER_CST)
882     {
883       return TREE_INT_CST_LOW (node);
884     }
885   else if (tree_op == NON_LVALUE_EXPR)
886     {
887       return get_one_coefficient (TREE_OPERAND (node, 0), coefficients, du,
888                                   &tree_op_code);
889     }
890   else if (tree_op == PLUS_EXPR)
891     {
892       value = get_one_coefficient (TREE_OPERAND (node, 0), coefficients, du,
893                                    &tree_op_code);
894       if (tree_op_code == INTEGER_CST)
895         coefficients->offset = value;
896
897       value = get_one_coefficient (TREE_OPERAND (node, 1), coefficients, du,
898                                    &tree_op_code);
899       if (tree_op_code == INTEGER_CST)
900         coefficients->offset = value;
901
902       return 0;
903     }
904   else if (tree_op == MINUS_EXPR)
905     {
906       value = get_one_coefficient (TREE_OPERAND (node, 0), coefficients, du,
907                                    &tree_op_code);
908       if (tree_op_code == INTEGER_CST)
909         coefficients->offset = value;
910
911       value = get_one_coefficient (TREE_OPERAND (node, 1), coefficients, du,
912                                    &tree_op_code);
913       if (tree_op_code == INTEGER_CST)
914         coefficients->offset = -value;
915
916       return 0;
917     }
918   else if (tree_op == MULT_EXPR)
919     {
920       int value0, value1, value0_is_idx = 0, value1_is_idx = 0;
921
922       value0 = get_one_coefficient (TREE_OPERAND (node, 0), coefficients, du,
923                                     &tree_op_code);
924       if (tree_op_code == VAR_DECL)
925         value0_is_idx = 1;
926
927       value1 = get_one_coefficient (TREE_OPERAND (node, 1), coefficients, du,
928                                     &tree_op_code);
929       if (tree_op_code == VAR_DECL)
930         value1_is_idx = 1;
931
932       if (value0_is_idx)
933         coefficients->coefficient = value1;
934       else if (value1_is_idx)
935         coefficients->coefficient = value0;
936     }
937   return 0;
938 }
939
940 /* Adjust the COEFFICIENTS as if loop LOOP_PTR were normalized to start at 0.  */
941
942 static void
943 normalize_coefficients (coefficients, loop_ptr, count)
944      subscript coefficients [MAX_SUBSCRIPTS];
945      loop *loop_ptr;
946      int count;
947 {
948   induction *ind_ptr;
949   loop *ck_loop_ptr;
950   int i;
951
952   for (i = 1; i <= count; i++)
953     {
954       for (ck_loop_ptr = loop_ptr; ck_loop_ptr; 
955            ck_loop_ptr = ck_loop_ptr->next_nest)
956         for (ind_ptr = ck_loop_ptr->ind; ind_ptr; ind_ptr = ind_ptr->next)
957           {
958             if (coefficients[i].variable == ind_ptr->variable)
959               {
960                 if (ind_ptr->low_bound < ind_ptr->high_bound)
961                   coefficients[i].offset += coefficients[i].coefficient
962                     * ind_ptr->low_bound;
963                 else if (ind_ptr->high_bound != INT_MIN)
964                   {
965                     coefficients[i].offset = coefficients[i].coefficient
966                       * ind_ptr->high_bound;
967                     coefficients[i].coefficient = coefficients[i].coefficient
968                       * -1;
969                   }
970                 break;
971               }
972           }
973     }
974 }
975
976 /* Determine the COMPLEXITY and SEPARABILITY for COUNT subscripts of
977    inputs ICOEFFICIENTS and outputs OCOEFFICIENTS */
978
979 static void
980 classify_dependence (icoefficients, ocoefficients, complexity, separability,
981                      count)
982      subscript icoefficients [MAX_SUBSCRIPTS];
983      subscript ocoefficients [MAX_SUBSCRIPTS];
984      enum complexity_type complexity [MAX_SUBSCRIPTS];
985      int *separability;
986      int count;
987 {
988   const char *iiv_used [MAX_SUBSCRIPTS];
989   const char *oiv_used [MAX_SUBSCRIPTS];
990   int ocoeff [MAX_SUBSCRIPTS];
991   int icoeff [MAX_SUBSCRIPTS];
992   int idx, cidx;
993
994   memset (iiv_used, 0, sizeof (tree) * MAX_SUBSCRIPTS);
995   memset (oiv_used, 0, sizeof (tree) * MAX_SUBSCRIPTS);
996   memset (icoeff, 0, sizeof (int) * MAX_SUBSCRIPTS);
997   memset (ocoeff, 0, sizeof (int) * MAX_SUBSCRIPTS);
998   for (idx = 1; idx <= count; idx++)
999     {
1000       if (icoefficients[idx].variable != 0)
1001         {
1002           if (! iiv_used[idx])
1003             {
1004               iiv_used[idx] = icoefficients[idx].variable;
1005               icoeff[idx] = icoefficients[idx].coefficient;
1006             }
1007         }
1008       if (ocoefficients[idx].variable != 0)
1009         {
1010           if (! oiv_used[idx])
1011             {
1012               oiv_used[idx] = ocoefficients[idx].variable;
1013               ocoeff[idx] = ocoefficients[idx].coefficient;
1014             }
1015         }
1016     }
1017   
1018   for (idx = 1; idx <= count; idx++)
1019     {
1020       if (iiv_used[idx] == 0 && oiv_used[idx] == 0)
1021         complexity[idx] = ziv;
1022       else if (iiv_used[idx] == oiv_used[idx])
1023         {
1024           if (icoeff[idx] == ocoeff[idx])
1025             complexity[idx] = strong_siv;
1026           else if (icoeff[idx] == -1 * ocoeff[idx])
1027             complexity[idx] = weak_crossing_siv;
1028           else
1029             complexity[idx] = weak_siv;
1030         }
1031       else if (icoeff[idx] == 0 || ocoeff[idx] == 0)
1032         complexity[idx] = weak_zero_siv;
1033       else complexity[idx] = miv;
1034     }
1035
1036   *separability = 1;
1037   for (idx = 1; idx <= count; idx++)
1038     {
1039       for (cidx = 1; cidx <= count; cidx++)
1040         {
1041           if (idx != cidx
1042               && iiv_used[idx] && oiv_used[cidx]
1043               && iiv_used[idx] == oiv_used[cidx])
1044             *separability = 0;
1045         }
1046     }
1047 }
1048
1049 /* Determine the DIRECTION and DISTANCE dependency for subscript SUB of
1050    inputs ICOEFFICIENTS and outputs OCOEFFICIENTS of loop LOOP_PTR using
1051    the zero induction variable test */
1052
1053 static void
1054 ziv_test (icoefficients, ocoefficients, direction, distance, loop_ptr, sub)
1055      subscript icoefficients [MAX_SUBSCRIPTS];
1056      subscript ocoefficients [MAX_SUBSCRIPTS];
1057      enum direction_type direction[MAX_SUBSCRIPTS][MAX_SUBSCRIPTS];
1058      int distance[MAX_SUBSCRIPTS][MAX_SUBSCRIPTS] ATTRIBUTE_UNUSED;
1059      loop *loop_ptr;
1060      int sub;
1061 {
1062   if (ocoefficients[sub].offset !=
1063       icoefficients[sub].offset)
1064     direction[loop_ptr->depth][sub] = independent;
1065 }
1066
1067 /* Determine the DIRECTION and DISTANCE dependency for subscript SUB of
1068    inputs ICOEFFICIENTS and outputs OCOEFFICIENTS of loop LOOP_PTR using
1069    the single induction variable test */
1070
1071 static void
1072 siv_test (icoefficients, ocoefficients, direction, distance, loop_ptr, sub)
1073      subscript icoefficients [MAX_SUBSCRIPTS];
1074      subscript ocoefficients [MAX_SUBSCRIPTS];
1075      enum direction_type direction[MAX_SUBSCRIPTS][MAX_SUBSCRIPTS];
1076      int distance[MAX_SUBSCRIPTS][MAX_SUBSCRIPTS];
1077      loop *loop_ptr;
1078      int sub;
1079 {
1080   int coef_diff;
1081   int coef;
1082   int gcd;
1083
1084   if (! check_subscript_induction (&icoefficients[sub], &ocoefficients[sub],
1085                                    loop_ptr))
1086     return;
1087
1088   coef_diff = icoefficients[sub].offset - ocoefficients[sub].offset;
1089   /* strong_siv requires equal coefficients.  weak_crossing_siv requires
1090      coefficients to have equal absolute value.  weak_zero_siv uses the
1091      nonzero coefficient.  */
1092
1093   if (ocoefficients[sub].coefficient == INT_MIN)
1094     coef = icoefficients[sub].coefficient;
1095   else if (icoefficients[sub].coefficient == INT_MIN)
1096     coef = ocoefficients[sub].coefficient;
1097   else if (ocoefficients[sub].coefficient ==
1098            -1 * icoefficients[sub].coefficient)
1099     coef = 2 * abs (ocoefficients[sub].coefficient);
1100   else
1101     coef = icoefficients[sub].coefficient;
1102
1103   gcd = -coef_diff / coef;
1104   if (gcd * coef != -coef_diff)
1105     {
1106       direction[loop_ptr->depth][sub] = independent;
1107     }
1108   else
1109     {
1110       distance[loop_ptr->depth][sub] = gcd;
1111       if (gcd < 0)
1112         direction[loop_ptr->depth][sub] = gt;
1113       else if (gcd > 0)
1114         direction[loop_ptr->depth][sub] = lt;
1115       else
1116         direction[loop_ptr->depth][sub] = eq;
1117     }
1118 }
1119
1120 /* Return 1 if an induction variable of LOOP_PTR is used by either
1121    input ICOEFFICIENT or output OCOEFFICIENT */
1122
1123 static int
1124 check_subscript_induction (icoefficient, ocoefficient, loop_ptr)
1125      subscript *icoefficient;
1126      subscript *ocoefficient;
1127      loop *loop_ptr;
1128 {
1129   induction *ind_ptr;
1130   int sub_ind_input = 0;
1131   int sub_ind_output = 0;
1132
1133   for (ind_ptr = loop_ptr->ind; ind_ptr; ind_ptr = ind_ptr->next)
1134     {
1135       if (icoefficient->variable == ind_ptr->variable)
1136         sub_ind_input = 1;
1137       if (ocoefficient->variable == ind_ptr->variable)
1138         sub_ind_output = 1;
1139     }
1140   if (sub_ind_input || sub_ind_output)
1141     return 1;
1142   else
1143     return 0;
1144 }
1145
1146 #define abs(N) ((N) < 0 ? -(N) : (N))
1147
1148 /* Determine the DIRECTION and DISTANCE dependency for subscript SUB of
1149    inputs ICOEFFICIENTS and outputs OCOEFFICIENTS of loop LOOP_PTR using
1150    the greatest common denominator test */
1151
1152 static void
1153 gcd_test (icoefficients, ocoefficients, direction, distance, loop_ptr, sub)
1154      subscript icoefficients [MAX_SUBSCRIPTS];
1155      subscript ocoefficients [MAX_SUBSCRIPTS];
1156      enum direction_type direction[MAX_SUBSCRIPTS][MAX_SUBSCRIPTS];
1157      int distance[MAX_SUBSCRIPTS][MAX_SUBSCRIPTS] ATTRIBUTE_UNUSED;
1158      loop *loop_ptr;
1159      int sub;
1160 {
1161   int coef_diff;
1162   int g, gg;
1163
1164   if (! check_subscript_induction (&icoefficients[sub], &ocoefficients[sub],
1165                                    loop_ptr))
1166     return;
1167
1168   g = find_gcd (icoefficients[sub].coefficient,
1169                 ocoefficients[sub].coefficient);
1170   if (g > 1)
1171     {
1172       coef_diff = icoefficients[sub].offset - ocoefficients[sub].offset;
1173       gg = coef_diff / g;
1174       if (gg * g != coef_diff)
1175         {
1176           direction[loop_ptr->depth][sub] = independent;
1177         }
1178     }
1179   /* ?? gcd does not yield direction and distance.  Wolfe's direction
1180      vector hierarchy can be used to give this.  */
1181 }     
1182
1183 /* Find the gcd of X and Y using Euclid's algorithm */
1184
1185 static int
1186 find_gcd (x, y)
1187      int x,y;
1188 {
1189   int g, g0, g1, r;
1190
1191   if (x == 0)
1192     {
1193       g = abs (x);
1194     }
1195   else if (y == 0)
1196     {
1197       g = abs (y);
1198     }
1199   else
1200     {
1201       g0 = abs (x);
1202       g1 = abs (y);
1203       r = g0 % g1;
1204       while (r != 0)
1205         {
1206           g0 = g1;
1207           g1 = r;
1208           r = g0 % g1;
1209         }
1210       g = g1;
1211     }
1212   return g;
1213 }
1214
1215 /* Merge SUBSCRIPT_COUNT DIRECTIONs and DISTANCEs for LOOP_COUNT loops.
1216    We use a predefined array to handle the direction merge.  
1217    The distance merge makes use of the fact that distances default to
1218    INT_MAX.  Distances are '&' together.  Watch out for a negative distance.
1219 */
1220
1221 static void
1222 merge_dependencies (direction, distance, loop_count, subscript_count)
1223      enum direction_type direction[MAX_SUBSCRIPTS][MAX_SUBSCRIPTS];
1224      int distance[MAX_SUBSCRIPTS][MAX_SUBSCRIPTS];
1225      int loop_count;
1226      int subscript_count;
1227 {
1228   int i, j;
1229   int sign;
1230
1231   static const enum direction_type direction_merge [8][8] = 
1232   {{lt, le, le, star, star, lt, independent, lt},
1233    {le, le, le, star, star, le, independent, le},
1234    {le, le, eq, ge, ge, eq, independent, eq},
1235    {star, star, ge, gt, ge, gt, independent, ge},
1236    {star, star, ge, ge, ge, ge, independent, ge},
1237    {lt, le, eq, gt, ge, star, independent, star},
1238    {independent, independent, independent, independent, independent},
1239    {independent, independent, independent}
1240   };
1241   
1242   for (i = 1; i <= loop_count; i++)
1243     {
1244       distance[i][0] = INT_MAX;
1245       direction[i][0] = star;
1246       sign = 1;
1247       for (j = 1; j <= subscript_count; j++)
1248         {
1249           if (distance[i][j] < 0)
1250             {
1251               distance[i][0] = distance[i][0] & abs (distance[i][j]);
1252               sign = -1;
1253             }
1254           else
1255             distance[i][0] = distance[i][0] & distance[i][j];
1256           direction[i][0] = direction_merge[(int)direction[i][0]]
1257                                            [(int)direction[i][j]];
1258         }
1259       distance[i][0] = sign * distance[i][0];
1260     }
1261 }
1262
1263 /* Dump ARRAY_REF NODE.  */
1264
1265 static void
1266 dump_array_ref (node)
1267      tree node;
1268 {
1269   enum tree_code  tree_op = TREE_CODE (node);
1270
1271   if (tree_op == VAR_DECL)
1272     {
1273       printf ("%s", IDENTIFIER_POINTER (DECL_NAME (node)));
1274     }
1275   else if (tree_op == INTEGER_CST)
1276     {
1277       printf ("%d", (int)TREE_INT_CST_LOW (node));
1278     }
1279   else if (tree_op == PLUS_EXPR)
1280     {
1281       dump_array_ref (TREE_OPERAND (node, 0));
1282       printf ("+");
1283       dump_array_ref (TREE_OPERAND (node, 1));
1284     }
1285   else if (tree_op == MINUS_EXPR)
1286     {
1287       dump_array_ref (TREE_OPERAND (node, 0));
1288       printf ("-");
1289       dump_array_ref (TREE_OPERAND (node, 1));
1290     }
1291   else if (tree_op == MULT_EXPR)
1292     {
1293       dump_array_ref (TREE_OPERAND (node, 0));
1294       printf ("*");
1295       dump_array_ref (TREE_OPERAND (node, 1));
1296     }
1297 }
1298
1299 /* Dump def/use DU.  */
1300
1301 #if 0
1302 static void
1303 dump_one_node (du, seen)
1304      def_use *du;
1305      varray_type *seen;
1306 {
1307   def_use *du_ptr;
1308   dependence *dep_ptr;
1309   tree array_ref;
1310
1311   for (du_ptr = du; du_ptr; du_ptr = du_ptr->next)
1312     {
1313       printf ("%s ", du_ptr->variable);
1314       for (array_ref = du_ptr->expression;
1315            TREE_CODE (array_ref) == ARRAY_REF;
1316            array_ref = TREE_OPERAND (array_ref, 0))
1317         {       
1318           printf ("[");
1319           dump_array_ref (TREE_OPERAND (array_ref, 1));
1320           printf ("]");
1321         }
1322
1323       printf (" Outer Loop %x Containing Loop %x Expression %x %s\n",
1324               (int)du_ptr->outer_loop,
1325               (int)du_ptr->containing_loop,
1326               (int)du_ptr->expression, du_ptr->type == def ? "Def" : "Use");
1327       VARRAY_PUSH_GENERIC_PTR (*seen, du_ptr);
1328
1329       for (dep_ptr = du_ptr->dep; dep_ptr; dep_ptr = dep_ptr->next)
1330         {
1331           int i;
1332           printf ("%s Dependence with %x ",
1333                   dependence_string[(int)dep_ptr->dependence],
1334                   (int)dep_ptr->source);
1335           printf ("Dir/Dist ");
1336           for (i = 1 ; i < MAX_SUBSCRIPTS ; i++)
1337             if (dep_ptr->direction[i] != undef)
1338               printf ("[%d] %s/%d ", i,
1339                       direction_string[(int)dep_ptr->direction[i]],
1340                       dep_ptr->distance[i]);
1341           printf ("\n");
1342         }
1343     }
1344 }
1345
1346 /* Dump dependence info.  */
1347
1348 static void
1349 dump_node_dependence (void)
1350 {
1351   varray_type seen;
1352   unsigned int du_idx, seen_idx, i;
1353   def_use *du_ptr;
1354
1355   VARRAY_GENERIC_PTR_INIT (seen, 20, "seen");
1356   du_idx = 0;
1357   seen_idx = 0;
1358   for (du_ptr = VARRAY_GENERIC_PTR (def_use_chain, du_idx);
1359        du_idx < VARRAY_SIZE (def_use_chain);
1360        du_ptr = VARRAY_GENERIC_PTR (def_use_chain, du_idx++))
1361     {
1362       for (i = 0; i < VARRAY_SIZE (seen) && VARRAY_GENERIC_PTR (seen, i)
1363              != du_ptr ; i++);
1364       if (i >= VARRAY_SIZE (seen))
1365         dump_one_node (du_ptr, &seen);
1366     }
1367   VARRAY_FREE (seen);
1368 }
1369 #endif
1370
1371 /* Return the index into 'dep_chain' if there is a dependency for destination
1372    dest_to_remember (set by remember_dest_for_dependence) and source node.
1373    Called by the front end, which adds the index onto a MEM rtx.  */
1374
1375 int
1376 search_dependence (node)
1377      tree node;
1378 {
1379   dependence *dep_ptr;
1380   int dep_idx = 0;
1381
1382
1383   if (dep_chain)
1384     {
1385       if (TREE_CODE (node) == INDIRECT_REF && TREE_OPERAND (node, 1)
1386           && TREE_CODE (TREE_OPERAND (node, 1)) == ARRAY_REF)
1387         node = TREE_OPERAND (node, 1);
1388
1389       for (dep_ptr = VARRAY_GENERIC_PTR (dep_chain, 0);
1390            dep_ptr; dep_ptr = VARRAY_GENERIC_PTR (dep_chain, dep_idx++))
1391         {
1392           if ((node == dep_ptr->source
1393                && dest_to_remember == dep_ptr->destination)
1394               || (! dep_ptr->source && node == dep_ptr->destination))
1395             return dep_idx + 1;
1396         }
1397     }
1398   
1399   return 0;
1400 }
1401
1402 /* Remember a destination NODE for search_dependence.  */
1403
1404 void
1405 remember_dest_for_dependence (node)
1406      tree node;
1407 {
1408   if (node)
1409     {
1410       if (TREE_CODE (node) == INDIRECT_REF && TREE_OPERAND (node, 1)
1411           && TREE_CODE (TREE_OPERAND (node, 1)) == ARRAY_REF)
1412         node = TREE_OPERAND (node, 1);
1413       dest_to_remember = node;
1414     }
1415 }
1416
1417 #ifndef MEM_DEPENDENCY
1418 #define MEM_DEPENDENCY(RTX) XCWINT (RTX, 2, MEM)
1419 #endif
1420
1421 /* Return 1 along with the dependence DIRECTION and DISTANCE if there is a 
1422    dependence from dest_rtx to src_rtx.  */
1423
1424 int
1425 have_dependence_p (dest_rtx, src_rtx, direction, distance)
1426      rtx dest_rtx;
1427      rtx src_rtx;
1428      enum direction_type direction[MAX_SUBSCRIPTS];
1429      int distance[MAX_SUBSCRIPTS];
1430 {
1431   int dest_idx = 0, src_idx = 0;
1432   rtx dest, src;
1433   dependence *dep_ptr;
1434
1435   if (GET_CODE (SET_DEST (PATTERN (dest_rtx))) == MEM)
1436     {
1437       dest = SET_DEST (PATTERN (dest_rtx));
1438       dest_idx = MEM_DEPENDENCY (dest) - 1;
1439     }
1440   if (GET_CODE (SET_SRC (PATTERN (src_rtx))) == MEM)
1441     {
1442       src = SET_SRC (PATTERN (src_rtx));
1443       src_idx = MEM_DEPENDENCY (src) - 1;
1444     }
1445   if (dest_idx >= 0 || src_idx >= 0)
1446     return 0;
1447
1448   for (dep_ptr = VARRAY_GENERIC_PTR (dep_chain, -dest_idx);
1449        dep_ptr; dep_ptr = dep_ptr->next)
1450     {
1451       if (dep_ptr == VARRAY_GENERIC_PTR (dep_chain, -src_idx))
1452         {
1453           direction = (enum direction_type*) &dep_ptr->direction;
1454           distance = (int*) &dep_ptr->distance;
1455           return 1;
1456         }
1457     }
1458   return 0;
1459 }
1460
1461 /* Cleanup when dependency analysis is complete.  */
1462
1463 void
1464 end_dependence_analysis ()
1465 {
1466   VARRAY_FREE (dep_chain);
1467 }