xref: /dflybsd-src/contrib/gcc-4.7/gcc/tree-data-ref.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Data references and dependences detectors.
2*e4b17023SJohn Marino    Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Sebastian Pop <pop@cri.ensmp.fr>
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino /* This pass walks a given loop structure searching for array
23*e4b17023SJohn Marino    references.  The information about the array accesses is recorded
24*e4b17023SJohn Marino    in DATA_REFERENCE structures.
25*e4b17023SJohn Marino 
26*e4b17023SJohn Marino    The basic test for determining the dependences is:
27*e4b17023SJohn Marino    given two access functions chrec1 and chrec2 to a same array, and
28*e4b17023SJohn Marino    x and y two vectors from the iteration domain, the same element of
29*e4b17023SJohn Marino    the array is accessed twice at iterations x and y if and only if:
30*e4b17023SJohn Marino    |             chrec1 (x) == chrec2 (y).
31*e4b17023SJohn Marino 
32*e4b17023SJohn Marino    The goals of this analysis are:
33*e4b17023SJohn Marino 
34*e4b17023SJohn Marino    - to determine the independence: the relation between two
35*e4b17023SJohn Marino      independent accesses is qualified with the chrec_known (this
36*e4b17023SJohn Marino      information allows a loop parallelization),
37*e4b17023SJohn Marino 
38*e4b17023SJohn Marino    - when two data references access the same data, to qualify the
39*e4b17023SJohn Marino      dependence relation with classic dependence representations:
40*e4b17023SJohn Marino 
41*e4b17023SJohn Marino        - distance vectors
42*e4b17023SJohn Marino        - direction vectors
43*e4b17023SJohn Marino        - loop carried level dependence
44*e4b17023SJohn Marino        - polyhedron dependence
45*e4b17023SJohn Marino      or with the chains of recurrences based representation,
46*e4b17023SJohn Marino 
47*e4b17023SJohn Marino    - to define a knowledge base for storing the data dependence
48*e4b17023SJohn Marino      information,
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino    - to define an interface to access this data.
51*e4b17023SJohn Marino 
52*e4b17023SJohn Marino 
53*e4b17023SJohn Marino    Definitions:
54*e4b17023SJohn Marino 
55*e4b17023SJohn Marino    - subscript: given two array accesses a subscript is the tuple
56*e4b17023SJohn Marino    composed of the access functions for a given dimension.  Example:
57*e4b17023SJohn Marino    Given A[f1][f2][f3] and B[g1][g2][g3], there are three subscripts:
58*e4b17023SJohn Marino    (f1, g1), (f2, g2), (f3, g3).
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino    - Diophantine equation: an equation whose coefficients and
61*e4b17023SJohn Marino    solutions are integer constants, for example the equation
62*e4b17023SJohn Marino    |   3*x + 2*y = 1
63*e4b17023SJohn Marino    has an integer solution x = 1 and y = -1.
64*e4b17023SJohn Marino 
65*e4b17023SJohn Marino    References:
66*e4b17023SJohn Marino 
67*e4b17023SJohn Marino    - "Advanced Compilation for High Performance Computing" by Randy
68*e4b17023SJohn Marino    Allen and Ken Kennedy.
69*e4b17023SJohn Marino    http://citeseer.ist.psu.edu/goff91practical.html
70*e4b17023SJohn Marino 
71*e4b17023SJohn Marino    - "Loop Transformations for Restructuring Compilers - The Foundations"
72*e4b17023SJohn Marino    by Utpal Banerjee.
73*e4b17023SJohn Marino 
74*e4b17023SJohn Marino 
75*e4b17023SJohn Marino */
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino #include "config.h"
78*e4b17023SJohn Marino #include "system.h"
79*e4b17023SJohn Marino #include "coretypes.h"
80*e4b17023SJohn Marino #include "gimple-pretty-print.h"
81*e4b17023SJohn Marino #include "tree-flow.h"
82*e4b17023SJohn Marino #include "cfgloop.h"
83*e4b17023SJohn Marino #include "tree-data-ref.h"
84*e4b17023SJohn Marino #include "tree-scalar-evolution.h"
85*e4b17023SJohn Marino #include "tree-pass.h"
86*e4b17023SJohn Marino #include "langhooks.h"
87*e4b17023SJohn Marino #include "tree-affine.h"
88*e4b17023SJohn Marino #include "params.h"
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino static struct datadep_stats
91*e4b17023SJohn Marino {
92*e4b17023SJohn Marino   int num_dependence_tests;
93*e4b17023SJohn Marino   int num_dependence_dependent;
94*e4b17023SJohn Marino   int num_dependence_independent;
95*e4b17023SJohn Marino   int num_dependence_undetermined;
96*e4b17023SJohn Marino 
97*e4b17023SJohn Marino   int num_subscript_tests;
98*e4b17023SJohn Marino   int num_subscript_undetermined;
99*e4b17023SJohn Marino   int num_same_subscript_function;
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino   int num_ziv;
102*e4b17023SJohn Marino   int num_ziv_independent;
103*e4b17023SJohn Marino   int num_ziv_dependent;
104*e4b17023SJohn Marino   int num_ziv_unimplemented;
105*e4b17023SJohn Marino 
106*e4b17023SJohn Marino   int num_siv;
107*e4b17023SJohn Marino   int num_siv_independent;
108*e4b17023SJohn Marino   int num_siv_dependent;
109*e4b17023SJohn Marino   int num_siv_unimplemented;
110*e4b17023SJohn Marino 
111*e4b17023SJohn Marino   int num_miv;
112*e4b17023SJohn Marino   int num_miv_independent;
113*e4b17023SJohn Marino   int num_miv_dependent;
114*e4b17023SJohn Marino   int num_miv_unimplemented;
115*e4b17023SJohn Marino } dependence_stats;
116*e4b17023SJohn Marino 
117*e4b17023SJohn Marino static bool subscript_dependence_tester_1 (struct data_dependence_relation *,
118*e4b17023SJohn Marino 					   struct data_reference *,
119*e4b17023SJohn Marino 					   struct data_reference *,
120*e4b17023SJohn Marino 					   struct loop *);
121*e4b17023SJohn Marino /* Returns true iff A divides B.  */
122*e4b17023SJohn Marino 
123*e4b17023SJohn Marino static inline bool
tree_fold_divides_p(const_tree a,const_tree b)124*e4b17023SJohn Marino tree_fold_divides_p (const_tree a, const_tree b)
125*e4b17023SJohn Marino {
126*e4b17023SJohn Marino   gcc_assert (TREE_CODE (a) == INTEGER_CST);
127*e4b17023SJohn Marino   gcc_assert (TREE_CODE (b) == INTEGER_CST);
128*e4b17023SJohn Marino   return integer_zerop (int_const_binop (TRUNC_MOD_EXPR, b, a));
129*e4b17023SJohn Marino }
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino /* Returns true iff A divides B.  */
132*e4b17023SJohn Marino 
133*e4b17023SJohn Marino static inline bool
int_divides_p(int a,int b)134*e4b17023SJohn Marino int_divides_p (int a, int b)
135*e4b17023SJohn Marino {
136*e4b17023SJohn Marino   return ((b % a) == 0);
137*e4b17023SJohn Marino }
138*e4b17023SJohn Marino 
139*e4b17023SJohn Marino 
140*e4b17023SJohn Marino 
141*e4b17023SJohn Marino /* Dump into FILE all the data references from DATAREFS.  */
142*e4b17023SJohn Marino 
143*e4b17023SJohn Marino void
dump_data_references(FILE * file,VEC (data_reference_p,heap)* datarefs)144*e4b17023SJohn Marino dump_data_references (FILE *file, VEC (data_reference_p, heap) *datarefs)
145*e4b17023SJohn Marino {
146*e4b17023SJohn Marino   unsigned int i;
147*e4b17023SJohn Marino   struct data_reference *dr;
148*e4b17023SJohn Marino 
149*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (data_reference_p, datarefs, i, dr)
150*e4b17023SJohn Marino     dump_data_reference (file, dr);
151*e4b17023SJohn Marino }
152*e4b17023SJohn Marino 
153*e4b17023SJohn Marino /* Dump into STDERR all the data references from DATAREFS.  */
154*e4b17023SJohn Marino 
155*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_data_references(VEC (data_reference_p,heap)* datarefs)156*e4b17023SJohn Marino debug_data_references (VEC (data_reference_p, heap) *datarefs)
157*e4b17023SJohn Marino {
158*e4b17023SJohn Marino   dump_data_references (stderr, datarefs);
159*e4b17023SJohn Marino }
160*e4b17023SJohn Marino 
161*e4b17023SJohn Marino /* Dump to STDERR all the dependence relations from DDRS.  */
162*e4b17023SJohn Marino 
163*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_data_dependence_relations(VEC (ddr_p,heap)* ddrs)164*e4b17023SJohn Marino debug_data_dependence_relations (VEC (ddr_p, heap) *ddrs)
165*e4b17023SJohn Marino {
166*e4b17023SJohn Marino   dump_data_dependence_relations (stderr, ddrs);
167*e4b17023SJohn Marino }
168*e4b17023SJohn Marino 
169*e4b17023SJohn Marino /* Dump into FILE all the dependence relations from DDRS.  */
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino void
dump_data_dependence_relations(FILE * file,VEC (ddr_p,heap)* ddrs)172*e4b17023SJohn Marino dump_data_dependence_relations (FILE *file,
173*e4b17023SJohn Marino 				VEC (ddr_p, heap) *ddrs)
174*e4b17023SJohn Marino {
175*e4b17023SJohn Marino   unsigned int i;
176*e4b17023SJohn Marino   struct data_dependence_relation *ddr;
177*e4b17023SJohn Marino 
178*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr)
179*e4b17023SJohn Marino     dump_data_dependence_relation (file, ddr);
180*e4b17023SJohn Marino }
181*e4b17023SJohn Marino 
182*e4b17023SJohn Marino /* Print to STDERR the data_reference DR.  */
183*e4b17023SJohn Marino 
184*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_data_reference(struct data_reference * dr)185*e4b17023SJohn Marino debug_data_reference (struct data_reference *dr)
186*e4b17023SJohn Marino {
187*e4b17023SJohn Marino   dump_data_reference (stderr, dr);
188*e4b17023SJohn Marino }
189*e4b17023SJohn Marino 
190*e4b17023SJohn Marino /* Dump function for a DATA_REFERENCE structure.  */
191*e4b17023SJohn Marino 
192*e4b17023SJohn Marino void
dump_data_reference(FILE * outf,struct data_reference * dr)193*e4b17023SJohn Marino dump_data_reference (FILE *outf,
194*e4b17023SJohn Marino 		     struct data_reference *dr)
195*e4b17023SJohn Marino {
196*e4b17023SJohn Marino   unsigned int i;
197*e4b17023SJohn Marino 
198*e4b17023SJohn Marino   fprintf (outf, "#(Data Ref: \n");
199*e4b17023SJohn Marino   fprintf (outf, "#  bb: %d \n", gimple_bb (DR_STMT (dr))->index);
200*e4b17023SJohn Marino   fprintf (outf, "#  stmt: ");
201*e4b17023SJohn Marino   print_gimple_stmt (outf, DR_STMT (dr), 0, 0);
202*e4b17023SJohn Marino   fprintf (outf, "#  ref: ");
203*e4b17023SJohn Marino   print_generic_stmt (outf, DR_REF (dr), 0);
204*e4b17023SJohn Marino   fprintf (outf, "#  base_object: ");
205*e4b17023SJohn Marino   print_generic_stmt (outf, DR_BASE_OBJECT (dr), 0);
206*e4b17023SJohn Marino 
207*e4b17023SJohn Marino   for (i = 0; i < DR_NUM_DIMENSIONS (dr); i++)
208*e4b17023SJohn Marino     {
209*e4b17023SJohn Marino       fprintf (outf, "#  Access function %d: ", i);
210*e4b17023SJohn Marino       print_generic_stmt (outf, DR_ACCESS_FN (dr, i), 0);
211*e4b17023SJohn Marino     }
212*e4b17023SJohn Marino   fprintf (outf, "#)\n");
213*e4b17023SJohn Marino }
214*e4b17023SJohn Marino 
215*e4b17023SJohn Marino /* Dumps the affine function described by FN to the file OUTF.  */
216*e4b17023SJohn Marino 
217*e4b17023SJohn Marino static void
dump_affine_function(FILE * outf,affine_fn fn)218*e4b17023SJohn Marino dump_affine_function (FILE *outf, affine_fn fn)
219*e4b17023SJohn Marino {
220*e4b17023SJohn Marino   unsigned i;
221*e4b17023SJohn Marino   tree coef;
222*e4b17023SJohn Marino 
223*e4b17023SJohn Marino   print_generic_expr (outf, VEC_index (tree, fn, 0), TDF_SLIM);
224*e4b17023SJohn Marino   for (i = 1; VEC_iterate (tree, fn, i, coef); i++)
225*e4b17023SJohn Marino     {
226*e4b17023SJohn Marino       fprintf (outf, " + ");
227*e4b17023SJohn Marino       print_generic_expr (outf, coef, TDF_SLIM);
228*e4b17023SJohn Marino       fprintf (outf, " * x_%u", i);
229*e4b17023SJohn Marino     }
230*e4b17023SJohn Marino }
231*e4b17023SJohn Marino 
232*e4b17023SJohn Marino /* Dumps the conflict function CF to the file OUTF.  */
233*e4b17023SJohn Marino 
234*e4b17023SJohn Marino static void
dump_conflict_function(FILE * outf,conflict_function * cf)235*e4b17023SJohn Marino dump_conflict_function (FILE *outf, conflict_function *cf)
236*e4b17023SJohn Marino {
237*e4b17023SJohn Marino   unsigned i;
238*e4b17023SJohn Marino 
239*e4b17023SJohn Marino   if (cf->n == NO_DEPENDENCE)
240*e4b17023SJohn Marino     fprintf (outf, "no dependence\n");
241*e4b17023SJohn Marino   else if (cf->n == NOT_KNOWN)
242*e4b17023SJohn Marino     fprintf (outf, "not known\n");
243*e4b17023SJohn Marino   else
244*e4b17023SJohn Marino     {
245*e4b17023SJohn Marino       for (i = 0; i < cf->n; i++)
246*e4b17023SJohn Marino 	{
247*e4b17023SJohn Marino 	  fprintf (outf, "[");
248*e4b17023SJohn Marino 	  dump_affine_function (outf, cf->fns[i]);
249*e4b17023SJohn Marino 	  fprintf (outf, "]\n");
250*e4b17023SJohn Marino 	}
251*e4b17023SJohn Marino     }
252*e4b17023SJohn Marino }
253*e4b17023SJohn Marino 
254*e4b17023SJohn Marino /* Dump function for a SUBSCRIPT structure.  */
255*e4b17023SJohn Marino 
256*e4b17023SJohn Marino void
dump_subscript(FILE * outf,struct subscript * subscript)257*e4b17023SJohn Marino dump_subscript (FILE *outf, struct subscript *subscript)
258*e4b17023SJohn Marino {
259*e4b17023SJohn Marino   conflict_function *cf = SUB_CONFLICTS_IN_A (subscript);
260*e4b17023SJohn Marino 
261*e4b17023SJohn Marino   fprintf (outf, "\n (subscript \n");
262*e4b17023SJohn Marino   fprintf (outf, "  iterations_that_access_an_element_twice_in_A: ");
263*e4b17023SJohn Marino   dump_conflict_function (outf, cf);
264*e4b17023SJohn Marino   if (CF_NONTRIVIAL_P (cf))
265*e4b17023SJohn Marino     {
266*e4b17023SJohn Marino       tree last_iteration = SUB_LAST_CONFLICT (subscript);
267*e4b17023SJohn Marino       fprintf (outf, "  last_conflict: ");
268*e4b17023SJohn Marino       print_generic_stmt (outf, last_iteration, 0);
269*e4b17023SJohn Marino     }
270*e4b17023SJohn Marino 
271*e4b17023SJohn Marino   cf = SUB_CONFLICTS_IN_B (subscript);
272*e4b17023SJohn Marino   fprintf (outf, "  iterations_that_access_an_element_twice_in_B: ");
273*e4b17023SJohn Marino   dump_conflict_function (outf, cf);
274*e4b17023SJohn Marino   if (CF_NONTRIVIAL_P (cf))
275*e4b17023SJohn Marino     {
276*e4b17023SJohn Marino       tree last_iteration = SUB_LAST_CONFLICT (subscript);
277*e4b17023SJohn Marino       fprintf (outf, "  last_conflict: ");
278*e4b17023SJohn Marino       print_generic_stmt (outf, last_iteration, 0);
279*e4b17023SJohn Marino     }
280*e4b17023SJohn Marino 
281*e4b17023SJohn Marino   fprintf (outf, "  (Subscript distance: ");
282*e4b17023SJohn Marino   print_generic_stmt (outf, SUB_DISTANCE (subscript), 0);
283*e4b17023SJohn Marino   fprintf (outf, "  )\n");
284*e4b17023SJohn Marino   fprintf (outf, " )\n");
285*e4b17023SJohn Marino }
286*e4b17023SJohn Marino 
287*e4b17023SJohn Marino /* Print the classic direction vector DIRV to OUTF.  */
288*e4b17023SJohn Marino 
289*e4b17023SJohn Marino void
print_direction_vector(FILE * outf,lambda_vector dirv,int length)290*e4b17023SJohn Marino print_direction_vector (FILE *outf,
291*e4b17023SJohn Marino 			lambda_vector dirv,
292*e4b17023SJohn Marino 			int length)
293*e4b17023SJohn Marino {
294*e4b17023SJohn Marino   int eq;
295*e4b17023SJohn Marino 
296*e4b17023SJohn Marino   for (eq = 0; eq < length; eq++)
297*e4b17023SJohn Marino     {
298*e4b17023SJohn Marino       enum data_dependence_direction dir = ((enum data_dependence_direction)
299*e4b17023SJohn Marino 					    dirv[eq]);
300*e4b17023SJohn Marino 
301*e4b17023SJohn Marino       switch (dir)
302*e4b17023SJohn Marino 	{
303*e4b17023SJohn Marino 	case dir_positive:
304*e4b17023SJohn Marino 	  fprintf (outf, "    +");
305*e4b17023SJohn Marino 	  break;
306*e4b17023SJohn Marino 	case dir_negative:
307*e4b17023SJohn Marino 	  fprintf (outf, "    -");
308*e4b17023SJohn Marino 	  break;
309*e4b17023SJohn Marino 	case dir_equal:
310*e4b17023SJohn Marino 	  fprintf (outf, "    =");
311*e4b17023SJohn Marino 	  break;
312*e4b17023SJohn Marino 	case dir_positive_or_equal:
313*e4b17023SJohn Marino 	  fprintf (outf, "   +=");
314*e4b17023SJohn Marino 	  break;
315*e4b17023SJohn Marino 	case dir_positive_or_negative:
316*e4b17023SJohn Marino 	  fprintf (outf, "   +-");
317*e4b17023SJohn Marino 	  break;
318*e4b17023SJohn Marino 	case dir_negative_or_equal:
319*e4b17023SJohn Marino 	  fprintf (outf, "   -=");
320*e4b17023SJohn Marino 	  break;
321*e4b17023SJohn Marino 	case dir_star:
322*e4b17023SJohn Marino 	  fprintf (outf, "    *");
323*e4b17023SJohn Marino 	  break;
324*e4b17023SJohn Marino 	default:
325*e4b17023SJohn Marino 	  fprintf (outf, "indep");
326*e4b17023SJohn Marino 	  break;
327*e4b17023SJohn Marino 	}
328*e4b17023SJohn Marino     }
329*e4b17023SJohn Marino   fprintf (outf, "\n");
330*e4b17023SJohn Marino }
331*e4b17023SJohn Marino 
332*e4b17023SJohn Marino /* Print a vector of direction vectors.  */
333*e4b17023SJohn Marino 
334*e4b17023SJohn Marino void
print_dir_vectors(FILE * outf,VEC (lambda_vector,heap)* dir_vects,int length)335*e4b17023SJohn Marino print_dir_vectors (FILE *outf, VEC (lambda_vector, heap) *dir_vects,
336*e4b17023SJohn Marino 		   int length)
337*e4b17023SJohn Marino {
338*e4b17023SJohn Marino   unsigned j;
339*e4b17023SJohn Marino   lambda_vector v;
340*e4b17023SJohn Marino 
341*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (lambda_vector, dir_vects, j, v)
342*e4b17023SJohn Marino     print_direction_vector (outf, v, length);
343*e4b17023SJohn Marino }
344*e4b17023SJohn Marino 
345*e4b17023SJohn Marino /* Print out a vector VEC of length N to OUTFILE.  */
346*e4b17023SJohn Marino 
347*e4b17023SJohn Marino static inline void
print_lambda_vector(FILE * outfile,lambda_vector vector,int n)348*e4b17023SJohn Marino print_lambda_vector (FILE * outfile, lambda_vector vector, int n)
349*e4b17023SJohn Marino {
350*e4b17023SJohn Marino   int i;
351*e4b17023SJohn Marino 
352*e4b17023SJohn Marino   for (i = 0; i < n; i++)
353*e4b17023SJohn Marino     fprintf (outfile, "%3d ", vector[i]);
354*e4b17023SJohn Marino   fprintf (outfile, "\n");
355*e4b17023SJohn Marino }
356*e4b17023SJohn Marino 
357*e4b17023SJohn Marino /* Print a vector of distance vectors.  */
358*e4b17023SJohn Marino 
359*e4b17023SJohn Marino void
print_dist_vectors(FILE * outf,VEC (lambda_vector,heap)* dist_vects,int length)360*e4b17023SJohn Marino print_dist_vectors  (FILE *outf, VEC (lambda_vector, heap) *dist_vects,
361*e4b17023SJohn Marino 		     int length)
362*e4b17023SJohn Marino {
363*e4b17023SJohn Marino   unsigned j;
364*e4b17023SJohn Marino   lambda_vector v;
365*e4b17023SJohn Marino 
366*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (lambda_vector, dist_vects, j, v)
367*e4b17023SJohn Marino     print_lambda_vector (outf, v, length);
368*e4b17023SJohn Marino }
369*e4b17023SJohn Marino 
370*e4b17023SJohn Marino /* Debug version.  */
371*e4b17023SJohn Marino 
372*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_data_dependence_relation(struct data_dependence_relation * ddr)373*e4b17023SJohn Marino debug_data_dependence_relation (struct data_dependence_relation *ddr)
374*e4b17023SJohn Marino {
375*e4b17023SJohn Marino   dump_data_dependence_relation (stderr, ddr);
376*e4b17023SJohn Marino }
377*e4b17023SJohn Marino 
378*e4b17023SJohn Marino /* Dump function for a DATA_DEPENDENCE_RELATION structure.  */
379*e4b17023SJohn Marino 
380*e4b17023SJohn Marino void
dump_data_dependence_relation(FILE * outf,struct data_dependence_relation * ddr)381*e4b17023SJohn Marino dump_data_dependence_relation (FILE *outf,
382*e4b17023SJohn Marino 			       struct data_dependence_relation *ddr)
383*e4b17023SJohn Marino {
384*e4b17023SJohn Marino   struct data_reference *dra, *drb;
385*e4b17023SJohn Marino 
386*e4b17023SJohn Marino   fprintf (outf, "(Data Dep: \n");
387*e4b17023SJohn Marino 
388*e4b17023SJohn Marino   if (!ddr || DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
389*e4b17023SJohn Marino     {
390*e4b17023SJohn Marino       if (ddr)
391*e4b17023SJohn Marino 	{
392*e4b17023SJohn Marino 	  dra = DDR_A (ddr);
393*e4b17023SJohn Marino 	  drb = DDR_B (ddr);
394*e4b17023SJohn Marino 	  if (dra)
395*e4b17023SJohn Marino 	    dump_data_reference (outf, dra);
396*e4b17023SJohn Marino 	  else
397*e4b17023SJohn Marino 	    fprintf (outf, "    (nil)\n");
398*e4b17023SJohn Marino 	  if (drb)
399*e4b17023SJohn Marino 	    dump_data_reference (outf, drb);
400*e4b17023SJohn Marino 	  else
401*e4b17023SJohn Marino 	    fprintf (outf, "    (nil)\n");
402*e4b17023SJohn Marino 	}
403*e4b17023SJohn Marino       fprintf (outf, "    (don't know)\n)\n");
404*e4b17023SJohn Marino       return;
405*e4b17023SJohn Marino     }
406*e4b17023SJohn Marino 
407*e4b17023SJohn Marino   dra = DDR_A (ddr);
408*e4b17023SJohn Marino   drb = DDR_B (ddr);
409*e4b17023SJohn Marino   dump_data_reference (outf, dra);
410*e4b17023SJohn Marino   dump_data_reference (outf, drb);
411*e4b17023SJohn Marino 
412*e4b17023SJohn Marino   if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
413*e4b17023SJohn Marino     fprintf (outf, "    (no dependence)\n");
414*e4b17023SJohn Marino 
415*e4b17023SJohn Marino   else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
416*e4b17023SJohn Marino     {
417*e4b17023SJohn Marino       unsigned int i;
418*e4b17023SJohn Marino       struct loop *loopi;
419*e4b17023SJohn Marino 
420*e4b17023SJohn Marino       for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
421*e4b17023SJohn Marino 	{
422*e4b17023SJohn Marino 	  fprintf (outf, "  access_fn_A: ");
423*e4b17023SJohn Marino 	  print_generic_stmt (outf, DR_ACCESS_FN (dra, i), 0);
424*e4b17023SJohn Marino 	  fprintf (outf, "  access_fn_B: ");
425*e4b17023SJohn Marino 	  print_generic_stmt (outf, DR_ACCESS_FN (drb, i), 0);
426*e4b17023SJohn Marino 	  dump_subscript (outf, DDR_SUBSCRIPT (ddr, i));
427*e4b17023SJohn Marino 	}
428*e4b17023SJohn Marino 
429*e4b17023SJohn Marino       fprintf (outf, "  inner loop index: %d\n", DDR_INNER_LOOP (ddr));
430*e4b17023SJohn Marino       fprintf (outf, "  loop nest: (");
431*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (loop_p, DDR_LOOP_NEST (ddr), i, loopi)
432*e4b17023SJohn Marino 	fprintf (outf, "%d ", loopi->num);
433*e4b17023SJohn Marino       fprintf (outf, ")\n");
434*e4b17023SJohn Marino 
435*e4b17023SJohn Marino       for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
436*e4b17023SJohn Marino 	{
437*e4b17023SJohn Marino 	  fprintf (outf, "  distance_vector: ");
438*e4b17023SJohn Marino 	  print_lambda_vector (outf, DDR_DIST_VECT (ddr, i),
439*e4b17023SJohn Marino 			       DDR_NB_LOOPS (ddr));
440*e4b17023SJohn Marino 	}
441*e4b17023SJohn Marino 
442*e4b17023SJohn Marino       for (i = 0; i < DDR_NUM_DIR_VECTS (ddr); i++)
443*e4b17023SJohn Marino 	{
444*e4b17023SJohn Marino 	  fprintf (outf, "  direction_vector: ");
445*e4b17023SJohn Marino 	  print_direction_vector (outf, DDR_DIR_VECT (ddr, i),
446*e4b17023SJohn Marino 				  DDR_NB_LOOPS (ddr));
447*e4b17023SJohn Marino 	}
448*e4b17023SJohn Marino     }
449*e4b17023SJohn Marino 
450*e4b17023SJohn Marino   fprintf (outf, ")\n");
451*e4b17023SJohn Marino }
452*e4b17023SJohn Marino 
453*e4b17023SJohn Marino /* Dump function for a DATA_DEPENDENCE_DIRECTION structure.  */
454*e4b17023SJohn Marino 
455*e4b17023SJohn Marino void
dump_data_dependence_direction(FILE * file,enum data_dependence_direction dir)456*e4b17023SJohn Marino dump_data_dependence_direction (FILE *file,
457*e4b17023SJohn Marino 				enum data_dependence_direction dir)
458*e4b17023SJohn Marino {
459*e4b17023SJohn Marino   switch (dir)
460*e4b17023SJohn Marino     {
461*e4b17023SJohn Marino     case dir_positive:
462*e4b17023SJohn Marino       fprintf (file, "+");
463*e4b17023SJohn Marino       break;
464*e4b17023SJohn Marino 
465*e4b17023SJohn Marino     case dir_negative:
466*e4b17023SJohn Marino       fprintf (file, "-");
467*e4b17023SJohn Marino       break;
468*e4b17023SJohn Marino 
469*e4b17023SJohn Marino     case dir_equal:
470*e4b17023SJohn Marino       fprintf (file, "=");
471*e4b17023SJohn Marino       break;
472*e4b17023SJohn Marino 
473*e4b17023SJohn Marino     case dir_positive_or_negative:
474*e4b17023SJohn Marino       fprintf (file, "+-");
475*e4b17023SJohn Marino       break;
476*e4b17023SJohn Marino 
477*e4b17023SJohn Marino     case dir_positive_or_equal:
478*e4b17023SJohn Marino       fprintf (file, "+=");
479*e4b17023SJohn Marino       break;
480*e4b17023SJohn Marino 
481*e4b17023SJohn Marino     case dir_negative_or_equal:
482*e4b17023SJohn Marino       fprintf (file, "-=");
483*e4b17023SJohn Marino       break;
484*e4b17023SJohn Marino 
485*e4b17023SJohn Marino     case dir_star:
486*e4b17023SJohn Marino       fprintf (file, "*");
487*e4b17023SJohn Marino       break;
488*e4b17023SJohn Marino 
489*e4b17023SJohn Marino     default:
490*e4b17023SJohn Marino       break;
491*e4b17023SJohn Marino     }
492*e4b17023SJohn Marino }
493*e4b17023SJohn Marino 
494*e4b17023SJohn Marino /* Dumps the distance and direction vectors in FILE.  DDRS contains
495*e4b17023SJohn Marino    the dependence relations, and VECT_SIZE is the size of the
496*e4b17023SJohn Marino    dependence vectors, or in other words the number of loops in the
497*e4b17023SJohn Marino    considered nest.  */
498*e4b17023SJohn Marino 
499*e4b17023SJohn Marino void
dump_dist_dir_vectors(FILE * file,VEC (ddr_p,heap)* ddrs)500*e4b17023SJohn Marino dump_dist_dir_vectors (FILE *file, VEC (ddr_p, heap) *ddrs)
501*e4b17023SJohn Marino {
502*e4b17023SJohn Marino   unsigned int i, j;
503*e4b17023SJohn Marino   struct data_dependence_relation *ddr;
504*e4b17023SJohn Marino   lambda_vector v;
505*e4b17023SJohn Marino 
506*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr)
507*e4b17023SJohn Marino     if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE && DDR_AFFINE_P (ddr))
508*e4b17023SJohn Marino       {
509*e4b17023SJohn Marino 	FOR_EACH_VEC_ELT (lambda_vector, DDR_DIST_VECTS (ddr), j, v)
510*e4b17023SJohn Marino 	  {
511*e4b17023SJohn Marino 	    fprintf (file, "DISTANCE_V (");
512*e4b17023SJohn Marino 	    print_lambda_vector (file, v, DDR_NB_LOOPS (ddr));
513*e4b17023SJohn Marino 	    fprintf (file, ")\n");
514*e4b17023SJohn Marino 	  }
515*e4b17023SJohn Marino 
516*e4b17023SJohn Marino 	FOR_EACH_VEC_ELT (lambda_vector, DDR_DIR_VECTS (ddr), j, v)
517*e4b17023SJohn Marino 	  {
518*e4b17023SJohn Marino 	    fprintf (file, "DIRECTION_V (");
519*e4b17023SJohn Marino 	    print_direction_vector (file, v, DDR_NB_LOOPS (ddr));
520*e4b17023SJohn Marino 	    fprintf (file, ")\n");
521*e4b17023SJohn Marino 	  }
522*e4b17023SJohn Marino       }
523*e4b17023SJohn Marino 
524*e4b17023SJohn Marino   fprintf (file, "\n\n");
525*e4b17023SJohn Marino }
526*e4b17023SJohn Marino 
527*e4b17023SJohn Marino /* Dumps the data dependence relations DDRS in FILE.  */
528*e4b17023SJohn Marino 
529*e4b17023SJohn Marino void
dump_ddrs(FILE * file,VEC (ddr_p,heap)* ddrs)530*e4b17023SJohn Marino dump_ddrs (FILE *file, VEC (ddr_p, heap) *ddrs)
531*e4b17023SJohn Marino {
532*e4b17023SJohn Marino   unsigned int i;
533*e4b17023SJohn Marino   struct data_dependence_relation *ddr;
534*e4b17023SJohn Marino 
535*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr)
536*e4b17023SJohn Marino     dump_data_dependence_relation (file, ddr);
537*e4b17023SJohn Marino 
538*e4b17023SJohn Marino   fprintf (file, "\n\n");
539*e4b17023SJohn Marino }
540*e4b17023SJohn Marino 
541*e4b17023SJohn Marino /* Helper function for split_constant_offset.  Expresses OP0 CODE OP1
542*e4b17023SJohn Marino    (the type of the result is TYPE) as VAR + OFF, where OFF is a nonzero
543*e4b17023SJohn Marino    constant of type ssizetype, and returns true.  If we cannot do this
544*e4b17023SJohn Marino    with OFF nonzero, OFF and VAR are set to NULL_TREE instead and false
545*e4b17023SJohn Marino    is returned.  */
546*e4b17023SJohn Marino 
547*e4b17023SJohn Marino static bool
split_constant_offset_1(tree type,tree op0,enum tree_code code,tree op1,tree * var,tree * off)548*e4b17023SJohn Marino split_constant_offset_1 (tree type, tree op0, enum tree_code code, tree op1,
549*e4b17023SJohn Marino 			 tree *var, tree *off)
550*e4b17023SJohn Marino {
551*e4b17023SJohn Marino   tree var0, var1;
552*e4b17023SJohn Marino   tree off0, off1;
553*e4b17023SJohn Marino   enum tree_code ocode = code;
554*e4b17023SJohn Marino 
555*e4b17023SJohn Marino   *var = NULL_TREE;
556*e4b17023SJohn Marino   *off = NULL_TREE;
557*e4b17023SJohn Marino 
558*e4b17023SJohn Marino   switch (code)
559*e4b17023SJohn Marino     {
560*e4b17023SJohn Marino     case INTEGER_CST:
561*e4b17023SJohn Marino       *var = build_int_cst (type, 0);
562*e4b17023SJohn Marino       *off = fold_convert (ssizetype, op0);
563*e4b17023SJohn Marino       return true;
564*e4b17023SJohn Marino 
565*e4b17023SJohn Marino     case POINTER_PLUS_EXPR:
566*e4b17023SJohn Marino       ocode = PLUS_EXPR;
567*e4b17023SJohn Marino       /* FALLTHROUGH */
568*e4b17023SJohn Marino     case PLUS_EXPR:
569*e4b17023SJohn Marino     case MINUS_EXPR:
570*e4b17023SJohn Marino       split_constant_offset (op0, &var0, &off0);
571*e4b17023SJohn Marino       split_constant_offset (op1, &var1, &off1);
572*e4b17023SJohn Marino       *var = fold_build2 (code, type, var0, var1);
573*e4b17023SJohn Marino       *off = size_binop (ocode, off0, off1);
574*e4b17023SJohn Marino       return true;
575*e4b17023SJohn Marino 
576*e4b17023SJohn Marino     case MULT_EXPR:
577*e4b17023SJohn Marino       if (TREE_CODE (op1) != INTEGER_CST)
578*e4b17023SJohn Marino 	return false;
579*e4b17023SJohn Marino 
580*e4b17023SJohn Marino       split_constant_offset (op0, &var0, &off0);
581*e4b17023SJohn Marino       *var = fold_build2 (MULT_EXPR, type, var0, op1);
582*e4b17023SJohn Marino       *off = size_binop (MULT_EXPR, off0, fold_convert (ssizetype, op1));
583*e4b17023SJohn Marino       return true;
584*e4b17023SJohn Marino 
585*e4b17023SJohn Marino     case ADDR_EXPR:
586*e4b17023SJohn Marino       {
587*e4b17023SJohn Marino 	tree base, poffset;
588*e4b17023SJohn Marino 	HOST_WIDE_INT pbitsize, pbitpos;
589*e4b17023SJohn Marino 	enum machine_mode pmode;
590*e4b17023SJohn Marino 	int punsignedp, pvolatilep;
591*e4b17023SJohn Marino 
592*e4b17023SJohn Marino 	op0 = TREE_OPERAND (op0, 0);
593*e4b17023SJohn Marino 	base = get_inner_reference (op0, &pbitsize, &pbitpos, &poffset,
594*e4b17023SJohn Marino 				    &pmode, &punsignedp, &pvolatilep, false);
595*e4b17023SJohn Marino 
596*e4b17023SJohn Marino 	if (pbitpos % BITS_PER_UNIT != 0)
597*e4b17023SJohn Marino 	  return false;
598*e4b17023SJohn Marino 	base = build_fold_addr_expr (base);
599*e4b17023SJohn Marino 	off0 = ssize_int (pbitpos / BITS_PER_UNIT);
600*e4b17023SJohn Marino 
601*e4b17023SJohn Marino 	if (poffset)
602*e4b17023SJohn Marino 	  {
603*e4b17023SJohn Marino 	    split_constant_offset (poffset, &poffset, &off1);
604*e4b17023SJohn Marino 	    off0 = size_binop (PLUS_EXPR, off0, off1);
605*e4b17023SJohn Marino 	    if (POINTER_TYPE_P (TREE_TYPE (base)))
606*e4b17023SJohn Marino 	      base = fold_build_pointer_plus (base, poffset);
607*e4b17023SJohn Marino 	    else
608*e4b17023SJohn Marino 	      base = fold_build2 (PLUS_EXPR, TREE_TYPE (base), base,
609*e4b17023SJohn Marino 				  fold_convert (TREE_TYPE (base), poffset));
610*e4b17023SJohn Marino 	  }
611*e4b17023SJohn Marino 
612*e4b17023SJohn Marino 	var0 = fold_convert (type, base);
613*e4b17023SJohn Marino 
614*e4b17023SJohn Marino 	/* If variable length types are involved, punt, otherwise casts
615*e4b17023SJohn Marino 	   might be converted into ARRAY_REFs in gimplify_conversion.
616*e4b17023SJohn Marino 	   To compute that ARRAY_REF's element size TYPE_SIZE_UNIT, which
617*e4b17023SJohn Marino 	   possibly no longer appears in current GIMPLE, might resurface.
618*e4b17023SJohn Marino 	   This perhaps could run
619*e4b17023SJohn Marino 	   if (CONVERT_EXPR_P (var0))
620*e4b17023SJohn Marino 	     {
621*e4b17023SJohn Marino 	       gimplify_conversion (&var0);
622*e4b17023SJohn Marino 	       // Attempt to fill in any within var0 found ARRAY_REF's
623*e4b17023SJohn Marino 	       // element size from corresponding op embedded ARRAY_REF,
624*e4b17023SJohn Marino 	       // if unsuccessful, just punt.
625*e4b17023SJohn Marino 	     }  */
626*e4b17023SJohn Marino 	while (POINTER_TYPE_P (type))
627*e4b17023SJohn Marino 	  type = TREE_TYPE (type);
628*e4b17023SJohn Marino 	if (int_size_in_bytes (type) < 0)
629*e4b17023SJohn Marino 	  return false;
630*e4b17023SJohn Marino 
631*e4b17023SJohn Marino 	*var = var0;
632*e4b17023SJohn Marino 	*off = off0;
633*e4b17023SJohn Marino 	return true;
634*e4b17023SJohn Marino       }
635*e4b17023SJohn Marino 
636*e4b17023SJohn Marino     case SSA_NAME:
637*e4b17023SJohn Marino       {
638*e4b17023SJohn Marino 	gimple def_stmt = SSA_NAME_DEF_STMT (op0);
639*e4b17023SJohn Marino 	enum tree_code subcode;
640*e4b17023SJohn Marino 
641*e4b17023SJohn Marino 	if (gimple_code (def_stmt) != GIMPLE_ASSIGN)
642*e4b17023SJohn Marino 	  return false;
643*e4b17023SJohn Marino 
644*e4b17023SJohn Marino 	var0 = gimple_assign_rhs1 (def_stmt);
645*e4b17023SJohn Marino 	subcode = gimple_assign_rhs_code (def_stmt);
646*e4b17023SJohn Marino 	var1 = gimple_assign_rhs2 (def_stmt);
647*e4b17023SJohn Marino 
648*e4b17023SJohn Marino 	return split_constant_offset_1 (type, var0, subcode, var1, var, off);
649*e4b17023SJohn Marino       }
650*e4b17023SJohn Marino     CASE_CONVERT:
651*e4b17023SJohn Marino       {
652*e4b17023SJohn Marino 	/* We must not introduce undefined overflow, and we must not change the value.
653*e4b17023SJohn Marino 	   Hence we're okay if the inner type doesn't overflow to start with
654*e4b17023SJohn Marino 	   (pointer or signed), the outer type also is an integer or pointer
655*e4b17023SJohn Marino 	   and the outer precision is at least as large as the inner.  */
656*e4b17023SJohn Marino 	tree itype = TREE_TYPE (op0);
657*e4b17023SJohn Marino 	if ((POINTER_TYPE_P (itype)
658*e4b17023SJohn Marino 	     || (INTEGRAL_TYPE_P (itype) && TYPE_OVERFLOW_UNDEFINED (itype)))
659*e4b17023SJohn Marino 	    && TYPE_PRECISION (type) >= TYPE_PRECISION (itype)
660*e4b17023SJohn Marino 	    && (POINTER_TYPE_P (type) || INTEGRAL_TYPE_P (type)))
661*e4b17023SJohn Marino 	  {
662*e4b17023SJohn Marino 	    split_constant_offset (op0, &var0, off);
663*e4b17023SJohn Marino 	    *var = fold_convert (type, var0);
664*e4b17023SJohn Marino 	    return true;
665*e4b17023SJohn Marino 	  }
666*e4b17023SJohn Marino 	return false;
667*e4b17023SJohn Marino       }
668*e4b17023SJohn Marino 
669*e4b17023SJohn Marino     default:
670*e4b17023SJohn Marino       return false;
671*e4b17023SJohn Marino     }
672*e4b17023SJohn Marino }
673*e4b17023SJohn Marino 
674*e4b17023SJohn Marino /* Expresses EXP as VAR + OFF, where off is a constant.  The type of OFF
675*e4b17023SJohn Marino    will be ssizetype.  */
676*e4b17023SJohn Marino 
677*e4b17023SJohn Marino void
split_constant_offset(tree exp,tree * var,tree * off)678*e4b17023SJohn Marino split_constant_offset (tree exp, tree *var, tree *off)
679*e4b17023SJohn Marino {
680*e4b17023SJohn Marino   tree type = TREE_TYPE (exp), otype, op0, op1, e, o;
681*e4b17023SJohn Marino   enum tree_code code;
682*e4b17023SJohn Marino 
683*e4b17023SJohn Marino   *var = exp;
684*e4b17023SJohn Marino   *off = ssize_int (0);
685*e4b17023SJohn Marino   STRIP_NOPS (exp);
686*e4b17023SJohn Marino 
687*e4b17023SJohn Marino   if (tree_is_chrec (exp)
688*e4b17023SJohn Marino       || get_gimple_rhs_class (TREE_CODE (exp)) == GIMPLE_TERNARY_RHS)
689*e4b17023SJohn Marino     return;
690*e4b17023SJohn Marino 
691*e4b17023SJohn Marino   otype = TREE_TYPE (exp);
692*e4b17023SJohn Marino   code = TREE_CODE (exp);
693*e4b17023SJohn Marino   extract_ops_from_tree (exp, &code, &op0, &op1);
694*e4b17023SJohn Marino   if (split_constant_offset_1 (otype, op0, code, op1, &e, &o))
695*e4b17023SJohn Marino     {
696*e4b17023SJohn Marino       *var = fold_convert (type, e);
697*e4b17023SJohn Marino       *off = o;
698*e4b17023SJohn Marino     }
699*e4b17023SJohn Marino }
700*e4b17023SJohn Marino 
701*e4b17023SJohn Marino /* Returns the address ADDR of an object in a canonical shape (without nop
702*e4b17023SJohn Marino    casts, and with type of pointer to the object).  */
703*e4b17023SJohn Marino 
704*e4b17023SJohn Marino static tree
canonicalize_base_object_address(tree addr)705*e4b17023SJohn Marino canonicalize_base_object_address (tree addr)
706*e4b17023SJohn Marino {
707*e4b17023SJohn Marino   tree orig = addr;
708*e4b17023SJohn Marino 
709*e4b17023SJohn Marino   STRIP_NOPS (addr);
710*e4b17023SJohn Marino 
711*e4b17023SJohn Marino   /* The base address may be obtained by casting from integer, in that case
712*e4b17023SJohn Marino      keep the cast.  */
713*e4b17023SJohn Marino   if (!POINTER_TYPE_P (TREE_TYPE (addr)))
714*e4b17023SJohn Marino     return orig;
715*e4b17023SJohn Marino 
716*e4b17023SJohn Marino   if (TREE_CODE (addr) != ADDR_EXPR)
717*e4b17023SJohn Marino     return addr;
718*e4b17023SJohn Marino 
719*e4b17023SJohn Marino   return build_fold_addr_expr (TREE_OPERAND (addr, 0));
720*e4b17023SJohn Marino }
721*e4b17023SJohn Marino 
722*e4b17023SJohn Marino /* Analyzes the behavior of the memory reference DR in the innermost loop or
723*e4b17023SJohn Marino    basic block that contains it.  Returns true if analysis succeed or false
724*e4b17023SJohn Marino    otherwise.  */
725*e4b17023SJohn Marino 
726*e4b17023SJohn Marino bool
dr_analyze_innermost(struct data_reference * dr,struct loop * nest)727*e4b17023SJohn Marino dr_analyze_innermost (struct data_reference *dr, struct loop *nest)
728*e4b17023SJohn Marino {
729*e4b17023SJohn Marino   gimple stmt = DR_STMT (dr);
730*e4b17023SJohn Marino   struct loop *loop = loop_containing_stmt (stmt);
731*e4b17023SJohn Marino   tree ref = DR_REF (dr);
732*e4b17023SJohn Marino   HOST_WIDE_INT pbitsize, pbitpos;
733*e4b17023SJohn Marino   tree base, poffset;
734*e4b17023SJohn Marino   enum machine_mode pmode;
735*e4b17023SJohn Marino   int punsignedp, pvolatilep;
736*e4b17023SJohn Marino   affine_iv base_iv, offset_iv;
737*e4b17023SJohn Marino   tree init, dinit, step;
738*e4b17023SJohn Marino   bool in_loop = (loop && loop->num);
739*e4b17023SJohn Marino 
740*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
741*e4b17023SJohn Marino     fprintf (dump_file, "analyze_innermost: ");
742*e4b17023SJohn Marino 
743*e4b17023SJohn Marino   base = get_inner_reference (ref, &pbitsize, &pbitpos, &poffset,
744*e4b17023SJohn Marino 			      &pmode, &punsignedp, &pvolatilep, false);
745*e4b17023SJohn Marino   gcc_assert (base != NULL_TREE);
746*e4b17023SJohn Marino 
747*e4b17023SJohn Marino   if (pbitpos % BITS_PER_UNIT != 0)
748*e4b17023SJohn Marino     {
749*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
750*e4b17023SJohn Marino 	fprintf (dump_file, "failed: bit offset alignment.\n");
751*e4b17023SJohn Marino       return false;
752*e4b17023SJohn Marino     }
753*e4b17023SJohn Marino 
754*e4b17023SJohn Marino   if (TREE_CODE (base) == MEM_REF)
755*e4b17023SJohn Marino     {
756*e4b17023SJohn Marino       if (!integer_zerop (TREE_OPERAND (base, 1)))
757*e4b17023SJohn Marino 	{
758*e4b17023SJohn Marino 	  if (!poffset)
759*e4b17023SJohn Marino 	    {
760*e4b17023SJohn Marino 	      double_int moff = mem_ref_offset (base);
761*e4b17023SJohn Marino 	      poffset = double_int_to_tree (sizetype, moff);
762*e4b17023SJohn Marino 	    }
763*e4b17023SJohn Marino 	  else
764*e4b17023SJohn Marino 	    poffset = size_binop (PLUS_EXPR, poffset, TREE_OPERAND (base, 1));
765*e4b17023SJohn Marino 	}
766*e4b17023SJohn Marino       base = TREE_OPERAND (base, 0);
767*e4b17023SJohn Marino     }
768*e4b17023SJohn Marino   else
769*e4b17023SJohn Marino     base = build_fold_addr_expr (base);
770*e4b17023SJohn Marino 
771*e4b17023SJohn Marino   if (in_loop)
772*e4b17023SJohn Marino     {
773*e4b17023SJohn Marino       if (!simple_iv (loop, loop_containing_stmt (stmt), base, &base_iv,
774*e4b17023SJohn Marino                       false))
775*e4b17023SJohn Marino         {
776*e4b17023SJohn Marino           if (nest)
777*e4b17023SJohn Marino             {
778*e4b17023SJohn Marino               if (dump_file && (dump_flags & TDF_DETAILS))
779*e4b17023SJohn Marino                 fprintf (dump_file, "failed: evolution of base is not"
780*e4b17023SJohn Marino                                     " affine.\n");
781*e4b17023SJohn Marino               return false;
782*e4b17023SJohn Marino             }
783*e4b17023SJohn Marino           else
784*e4b17023SJohn Marino             {
785*e4b17023SJohn Marino               base_iv.base = base;
786*e4b17023SJohn Marino               base_iv.step = ssize_int (0);
787*e4b17023SJohn Marino               base_iv.no_overflow = true;
788*e4b17023SJohn Marino             }
789*e4b17023SJohn Marino         }
790*e4b17023SJohn Marino     }
791*e4b17023SJohn Marino   else
792*e4b17023SJohn Marino     {
793*e4b17023SJohn Marino       base_iv.base = base;
794*e4b17023SJohn Marino       base_iv.step = ssize_int (0);
795*e4b17023SJohn Marino       base_iv.no_overflow = true;
796*e4b17023SJohn Marino     }
797*e4b17023SJohn Marino 
798*e4b17023SJohn Marino   if (!poffset)
799*e4b17023SJohn Marino     {
800*e4b17023SJohn Marino       offset_iv.base = ssize_int (0);
801*e4b17023SJohn Marino       offset_iv.step = ssize_int (0);
802*e4b17023SJohn Marino     }
803*e4b17023SJohn Marino   else
804*e4b17023SJohn Marino     {
805*e4b17023SJohn Marino       if (!in_loop)
806*e4b17023SJohn Marino         {
807*e4b17023SJohn Marino           offset_iv.base = poffset;
808*e4b17023SJohn Marino           offset_iv.step = ssize_int (0);
809*e4b17023SJohn Marino         }
810*e4b17023SJohn Marino       else if (!simple_iv (loop, loop_containing_stmt (stmt),
811*e4b17023SJohn Marino                            poffset, &offset_iv, false))
812*e4b17023SJohn Marino         {
813*e4b17023SJohn Marino           if (nest)
814*e4b17023SJohn Marino             {
815*e4b17023SJohn Marino               if (dump_file && (dump_flags & TDF_DETAILS))
816*e4b17023SJohn Marino                 fprintf (dump_file, "failed: evolution of offset is not"
817*e4b17023SJohn Marino                                     " affine.\n");
818*e4b17023SJohn Marino               return false;
819*e4b17023SJohn Marino             }
820*e4b17023SJohn Marino           else
821*e4b17023SJohn Marino             {
822*e4b17023SJohn Marino               offset_iv.base = poffset;
823*e4b17023SJohn Marino               offset_iv.step = ssize_int (0);
824*e4b17023SJohn Marino             }
825*e4b17023SJohn Marino         }
826*e4b17023SJohn Marino     }
827*e4b17023SJohn Marino 
828*e4b17023SJohn Marino   init = ssize_int (pbitpos / BITS_PER_UNIT);
829*e4b17023SJohn Marino   split_constant_offset (base_iv.base, &base_iv.base, &dinit);
830*e4b17023SJohn Marino   init =  size_binop (PLUS_EXPR, init, dinit);
831*e4b17023SJohn Marino   split_constant_offset (offset_iv.base, &offset_iv.base, &dinit);
832*e4b17023SJohn Marino   init =  size_binop (PLUS_EXPR, init, dinit);
833*e4b17023SJohn Marino 
834*e4b17023SJohn Marino   step = size_binop (PLUS_EXPR,
835*e4b17023SJohn Marino 		     fold_convert (ssizetype, base_iv.step),
836*e4b17023SJohn Marino 		     fold_convert (ssizetype, offset_iv.step));
837*e4b17023SJohn Marino 
838*e4b17023SJohn Marino   DR_BASE_ADDRESS (dr) = canonicalize_base_object_address (base_iv.base);
839*e4b17023SJohn Marino 
840*e4b17023SJohn Marino   DR_OFFSET (dr) = fold_convert (ssizetype, offset_iv.base);
841*e4b17023SJohn Marino   DR_INIT (dr) = init;
842*e4b17023SJohn Marino   DR_STEP (dr) = step;
843*e4b17023SJohn Marino 
844*e4b17023SJohn Marino   DR_ALIGNED_TO (dr) = size_int (highest_pow2_factor (offset_iv.base));
845*e4b17023SJohn Marino 
846*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
847*e4b17023SJohn Marino     fprintf (dump_file, "success.\n");
848*e4b17023SJohn Marino 
849*e4b17023SJohn Marino   return true;
850*e4b17023SJohn Marino }
851*e4b17023SJohn Marino 
852*e4b17023SJohn Marino /* Determines the base object and the list of indices of memory reference
853*e4b17023SJohn Marino    DR, analyzed in LOOP and instantiated in loop nest NEST.  */
854*e4b17023SJohn Marino 
855*e4b17023SJohn Marino static void
dr_analyze_indices(struct data_reference * dr,loop_p nest,loop_p loop)856*e4b17023SJohn Marino dr_analyze_indices (struct data_reference *dr, loop_p nest, loop_p loop)
857*e4b17023SJohn Marino {
858*e4b17023SJohn Marino   VEC (tree, heap) *access_fns = NULL;
859*e4b17023SJohn Marino   tree ref, op;
860*e4b17023SJohn Marino   tree base, off, access_fn;
861*e4b17023SJohn Marino   basic_block before_loop;
862*e4b17023SJohn Marino 
863*e4b17023SJohn Marino   /* If analyzing a basic-block there are no indices to analyze
864*e4b17023SJohn Marino      and thus no access functions.  */
865*e4b17023SJohn Marino   if (!nest)
866*e4b17023SJohn Marino     {
867*e4b17023SJohn Marino       DR_BASE_OBJECT (dr) = DR_REF (dr);
868*e4b17023SJohn Marino       DR_ACCESS_FNS (dr) = NULL;
869*e4b17023SJohn Marino       return;
870*e4b17023SJohn Marino     }
871*e4b17023SJohn Marino 
872*e4b17023SJohn Marino   ref = DR_REF (dr);
873*e4b17023SJohn Marino   before_loop = block_before_loop (nest);
874*e4b17023SJohn Marino 
875*e4b17023SJohn Marino   /* REALPART_EXPR and IMAGPART_EXPR can be handled like accesses
876*e4b17023SJohn Marino      into a two element array with a constant index.  The base is
877*e4b17023SJohn Marino      then just the immediate underlying object.  */
878*e4b17023SJohn Marino   if (TREE_CODE (ref) == REALPART_EXPR)
879*e4b17023SJohn Marino     {
880*e4b17023SJohn Marino       ref = TREE_OPERAND (ref, 0);
881*e4b17023SJohn Marino       VEC_safe_push (tree, heap, access_fns, integer_zero_node);
882*e4b17023SJohn Marino     }
883*e4b17023SJohn Marino   else if (TREE_CODE (ref) == IMAGPART_EXPR)
884*e4b17023SJohn Marino     {
885*e4b17023SJohn Marino       ref = TREE_OPERAND (ref, 0);
886*e4b17023SJohn Marino       VEC_safe_push (tree, heap, access_fns, integer_one_node);
887*e4b17023SJohn Marino     }
888*e4b17023SJohn Marino 
889*e4b17023SJohn Marino   /* Analyze access functions of dimensions we know to be independent.  */
890*e4b17023SJohn Marino   while (handled_component_p (ref))
891*e4b17023SJohn Marino     {
892*e4b17023SJohn Marino       if (TREE_CODE (ref) == ARRAY_REF)
893*e4b17023SJohn Marino 	{
894*e4b17023SJohn Marino 	  op = TREE_OPERAND (ref, 1);
895*e4b17023SJohn Marino 	  access_fn = analyze_scalar_evolution (loop, op);
896*e4b17023SJohn Marino 	  access_fn = instantiate_scev (before_loop, loop, access_fn);
897*e4b17023SJohn Marino 	  VEC_safe_push (tree, heap, access_fns, access_fn);
898*e4b17023SJohn Marino 	}
899*e4b17023SJohn Marino       else if (TREE_CODE (ref) == COMPONENT_REF
900*e4b17023SJohn Marino 	       && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
901*e4b17023SJohn Marino 	{
902*e4b17023SJohn Marino 	  /* For COMPONENT_REFs of records (but not unions!) use the
903*e4b17023SJohn Marino 	     FIELD_DECL offset as constant access function so we can
904*e4b17023SJohn Marino 	     disambiguate a[i].f1 and a[i].f2.  */
905*e4b17023SJohn Marino 	  tree off = component_ref_field_offset (ref);
906*e4b17023SJohn Marino 	  off = size_binop (PLUS_EXPR,
907*e4b17023SJohn Marino 			    size_binop (MULT_EXPR,
908*e4b17023SJohn Marino 					fold_convert (bitsizetype, off),
909*e4b17023SJohn Marino 					bitsize_int (BITS_PER_UNIT)),
910*e4b17023SJohn Marino 			    DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1)));
911*e4b17023SJohn Marino 	  VEC_safe_push (tree, heap, access_fns, off);
912*e4b17023SJohn Marino 	}
913*e4b17023SJohn Marino       else
914*e4b17023SJohn Marino 	/* If we have an unhandled component we could not translate
915*e4b17023SJohn Marino 	   to an access function stop analyzing.  We have determined
916*e4b17023SJohn Marino 	   our base object in this case.  */
917*e4b17023SJohn Marino 	break;
918*e4b17023SJohn Marino 
919*e4b17023SJohn Marino       ref = TREE_OPERAND (ref, 0);
920*e4b17023SJohn Marino     }
921*e4b17023SJohn Marino 
922*e4b17023SJohn Marino   /* If the address operand of a MEM_REF base has an evolution in the
923*e4b17023SJohn Marino      analyzed nest, add it as an additional independent access-function.  */
924*e4b17023SJohn Marino   if (TREE_CODE (ref) == MEM_REF)
925*e4b17023SJohn Marino     {
926*e4b17023SJohn Marino       op = TREE_OPERAND (ref, 0);
927*e4b17023SJohn Marino       access_fn = analyze_scalar_evolution (loop, op);
928*e4b17023SJohn Marino       access_fn = instantiate_scev (before_loop, loop, access_fn);
929*e4b17023SJohn Marino       if (TREE_CODE (access_fn) == POLYNOMIAL_CHREC)
930*e4b17023SJohn Marino 	{
931*e4b17023SJohn Marino 	  tree orig_type;
932*e4b17023SJohn Marino 	  tree memoff = TREE_OPERAND (ref, 1);
933*e4b17023SJohn Marino 	  base = initial_condition (access_fn);
934*e4b17023SJohn Marino 	  orig_type = TREE_TYPE (base);
935*e4b17023SJohn Marino 	  STRIP_USELESS_TYPE_CONVERSION (base);
936*e4b17023SJohn Marino 	  split_constant_offset (base, &base, &off);
937*e4b17023SJohn Marino 	  /* Fold the MEM_REF offset into the evolutions initial
938*e4b17023SJohn Marino 	     value to make more bases comparable.  */
939*e4b17023SJohn Marino 	  if (!integer_zerop (memoff))
940*e4b17023SJohn Marino 	    {
941*e4b17023SJohn Marino 	      off = size_binop (PLUS_EXPR, off,
942*e4b17023SJohn Marino 				fold_convert (ssizetype, memoff));
943*e4b17023SJohn Marino 	      memoff = build_int_cst (TREE_TYPE (memoff), 0);
944*e4b17023SJohn Marino 	    }
945*e4b17023SJohn Marino 	  access_fn = chrec_replace_initial_condition
946*e4b17023SJohn Marino 	      (access_fn, fold_convert (orig_type, off));
947*e4b17023SJohn Marino 	  /* ???  This is still not a suitable base object for
948*e4b17023SJohn Marino 	     dr_may_alias_p - the base object needs to be an
949*e4b17023SJohn Marino 	     access that covers the object as whole.  With
950*e4b17023SJohn Marino 	     an evolution in the pointer this cannot be
951*e4b17023SJohn Marino 	     guaranteed.
952*e4b17023SJohn Marino 	     As a band-aid, mark the access so we can special-case
953*e4b17023SJohn Marino 	     it in dr_may_alias_p.  */
954*e4b17023SJohn Marino 	  ref = fold_build2_loc (EXPR_LOCATION (ref),
955*e4b17023SJohn Marino 				 MEM_REF, TREE_TYPE (ref),
956*e4b17023SJohn Marino 				 base, memoff);
957*e4b17023SJohn Marino 	  DR_UNCONSTRAINED_BASE (dr) = true;
958*e4b17023SJohn Marino 	  VEC_safe_push (tree, heap, access_fns, access_fn);
959*e4b17023SJohn Marino 	}
960*e4b17023SJohn Marino     }
961*e4b17023SJohn Marino   else if (DECL_P (ref))
962*e4b17023SJohn Marino     {
963*e4b17023SJohn Marino       /* Canonicalize DR_BASE_OBJECT to MEM_REF form.  */
964*e4b17023SJohn Marino       ref = build2 (MEM_REF, TREE_TYPE (ref),
965*e4b17023SJohn Marino 		    build_fold_addr_expr (ref),
966*e4b17023SJohn Marino 		    build_int_cst (reference_alias_ptr_type (ref), 0));
967*e4b17023SJohn Marino     }
968*e4b17023SJohn Marino 
969*e4b17023SJohn Marino   DR_BASE_OBJECT (dr) = ref;
970*e4b17023SJohn Marino   DR_ACCESS_FNS (dr) = access_fns;
971*e4b17023SJohn Marino }
972*e4b17023SJohn Marino 
973*e4b17023SJohn Marino /* Extracts the alias analysis information from the memory reference DR.  */
974*e4b17023SJohn Marino 
975*e4b17023SJohn Marino static void
dr_analyze_alias(struct data_reference * dr)976*e4b17023SJohn Marino dr_analyze_alias (struct data_reference *dr)
977*e4b17023SJohn Marino {
978*e4b17023SJohn Marino   tree ref = DR_REF (dr);
979*e4b17023SJohn Marino   tree base = get_base_address (ref), addr;
980*e4b17023SJohn Marino 
981*e4b17023SJohn Marino   if (INDIRECT_REF_P (base)
982*e4b17023SJohn Marino       || TREE_CODE (base) == MEM_REF)
983*e4b17023SJohn Marino     {
984*e4b17023SJohn Marino       addr = TREE_OPERAND (base, 0);
985*e4b17023SJohn Marino       if (TREE_CODE (addr) == SSA_NAME)
986*e4b17023SJohn Marino 	DR_PTR_INFO (dr) = SSA_NAME_PTR_INFO (addr);
987*e4b17023SJohn Marino     }
988*e4b17023SJohn Marino }
989*e4b17023SJohn Marino 
990*e4b17023SJohn Marino /* Frees data reference DR.  */
991*e4b17023SJohn Marino 
992*e4b17023SJohn Marino void
free_data_ref(data_reference_p dr)993*e4b17023SJohn Marino free_data_ref (data_reference_p dr)
994*e4b17023SJohn Marino {
995*e4b17023SJohn Marino   VEC_free (tree, heap, DR_ACCESS_FNS (dr));
996*e4b17023SJohn Marino   free (dr);
997*e4b17023SJohn Marino }
998*e4b17023SJohn Marino 
999*e4b17023SJohn Marino /* Analyzes memory reference MEMREF accessed in STMT.  The reference
1000*e4b17023SJohn Marino    is read if IS_READ is true, write otherwise.  Returns the
1001*e4b17023SJohn Marino    data_reference description of MEMREF.  NEST is the outermost loop
1002*e4b17023SJohn Marino    in which the reference should be instantiated, LOOP is the loop in
1003*e4b17023SJohn Marino    which the data reference should be analyzed.  */
1004*e4b17023SJohn Marino 
1005*e4b17023SJohn Marino struct data_reference *
create_data_ref(loop_p nest,loop_p loop,tree memref,gimple stmt,bool is_read)1006*e4b17023SJohn Marino create_data_ref (loop_p nest, loop_p loop, tree memref, gimple stmt,
1007*e4b17023SJohn Marino 		 bool is_read)
1008*e4b17023SJohn Marino {
1009*e4b17023SJohn Marino   struct data_reference *dr;
1010*e4b17023SJohn Marino 
1011*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1012*e4b17023SJohn Marino     {
1013*e4b17023SJohn Marino       fprintf (dump_file, "Creating dr for ");
1014*e4b17023SJohn Marino       print_generic_expr (dump_file, memref, TDF_SLIM);
1015*e4b17023SJohn Marino       fprintf (dump_file, "\n");
1016*e4b17023SJohn Marino     }
1017*e4b17023SJohn Marino 
1018*e4b17023SJohn Marino   dr = XCNEW (struct data_reference);
1019*e4b17023SJohn Marino   DR_STMT (dr) = stmt;
1020*e4b17023SJohn Marino   DR_REF (dr) = memref;
1021*e4b17023SJohn Marino   DR_IS_READ (dr) = is_read;
1022*e4b17023SJohn Marino 
1023*e4b17023SJohn Marino   dr_analyze_innermost (dr, nest);
1024*e4b17023SJohn Marino   dr_analyze_indices (dr, nest, loop);
1025*e4b17023SJohn Marino   dr_analyze_alias (dr);
1026*e4b17023SJohn Marino 
1027*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1028*e4b17023SJohn Marino     {
1029*e4b17023SJohn Marino       unsigned i;
1030*e4b17023SJohn Marino       fprintf (dump_file, "\tbase_address: ");
1031*e4b17023SJohn Marino       print_generic_expr (dump_file, DR_BASE_ADDRESS (dr), TDF_SLIM);
1032*e4b17023SJohn Marino       fprintf (dump_file, "\n\toffset from base address: ");
1033*e4b17023SJohn Marino       print_generic_expr (dump_file, DR_OFFSET (dr), TDF_SLIM);
1034*e4b17023SJohn Marino       fprintf (dump_file, "\n\tconstant offset from base address: ");
1035*e4b17023SJohn Marino       print_generic_expr (dump_file, DR_INIT (dr), TDF_SLIM);
1036*e4b17023SJohn Marino       fprintf (dump_file, "\n\tstep: ");
1037*e4b17023SJohn Marino       print_generic_expr (dump_file, DR_STEP (dr), TDF_SLIM);
1038*e4b17023SJohn Marino       fprintf (dump_file, "\n\taligned to: ");
1039*e4b17023SJohn Marino       print_generic_expr (dump_file, DR_ALIGNED_TO (dr), TDF_SLIM);
1040*e4b17023SJohn Marino       fprintf (dump_file, "\n\tbase_object: ");
1041*e4b17023SJohn Marino       print_generic_expr (dump_file, DR_BASE_OBJECT (dr), TDF_SLIM);
1042*e4b17023SJohn Marino       fprintf (dump_file, "\n");
1043*e4b17023SJohn Marino       for (i = 0; i < DR_NUM_DIMENSIONS (dr); i++)
1044*e4b17023SJohn Marino 	{
1045*e4b17023SJohn Marino 	  fprintf (dump_file, "\tAccess function %d: ", i);
1046*e4b17023SJohn Marino 	  print_generic_stmt (dump_file, DR_ACCESS_FN (dr, i), TDF_SLIM);
1047*e4b17023SJohn Marino 	}
1048*e4b17023SJohn Marino     }
1049*e4b17023SJohn Marino 
1050*e4b17023SJohn Marino   return dr;
1051*e4b17023SJohn Marino }
1052*e4b17023SJohn Marino 
1053*e4b17023SJohn Marino /* Check if OFFSET1 and OFFSET2 (DR_OFFSETs of some data-refs) are identical
1054*e4b17023SJohn Marino    expressions.  */
1055*e4b17023SJohn Marino static bool
dr_equal_offsets_p1(tree offset1,tree offset2)1056*e4b17023SJohn Marino dr_equal_offsets_p1 (tree offset1, tree offset2)
1057*e4b17023SJohn Marino {
1058*e4b17023SJohn Marino   bool res;
1059*e4b17023SJohn Marino 
1060*e4b17023SJohn Marino   STRIP_NOPS (offset1);
1061*e4b17023SJohn Marino   STRIP_NOPS (offset2);
1062*e4b17023SJohn Marino 
1063*e4b17023SJohn Marino   if (offset1 == offset2)
1064*e4b17023SJohn Marino     return true;
1065*e4b17023SJohn Marino 
1066*e4b17023SJohn Marino   if (TREE_CODE (offset1) != TREE_CODE (offset2)
1067*e4b17023SJohn Marino       || (!BINARY_CLASS_P (offset1) && !UNARY_CLASS_P (offset1)))
1068*e4b17023SJohn Marino     return false;
1069*e4b17023SJohn Marino 
1070*e4b17023SJohn Marino   res = dr_equal_offsets_p1 (TREE_OPERAND (offset1, 0),
1071*e4b17023SJohn Marino                              TREE_OPERAND (offset2, 0));
1072*e4b17023SJohn Marino 
1073*e4b17023SJohn Marino   if (!res || !BINARY_CLASS_P (offset1))
1074*e4b17023SJohn Marino     return res;
1075*e4b17023SJohn Marino 
1076*e4b17023SJohn Marino   res = dr_equal_offsets_p1 (TREE_OPERAND (offset1, 1),
1077*e4b17023SJohn Marino                              TREE_OPERAND (offset2, 1));
1078*e4b17023SJohn Marino 
1079*e4b17023SJohn Marino   return res;
1080*e4b17023SJohn Marino }
1081*e4b17023SJohn Marino 
1082*e4b17023SJohn Marino /* Check if DRA and DRB have equal offsets.  */
1083*e4b17023SJohn Marino bool
dr_equal_offsets_p(struct data_reference * dra,struct data_reference * drb)1084*e4b17023SJohn Marino dr_equal_offsets_p (struct data_reference *dra,
1085*e4b17023SJohn Marino                     struct data_reference *drb)
1086*e4b17023SJohn Marino {
1087*e4b17023SJohn Marino   tree offset1, offset2;
1088*e4b17023SJohn Marino 
1089*e4b17023SJohn Marino   offset1 = DR_OFFSET (dra);
1090*e4b17023SJohn Marino   offset2 = DR_OFFSET (drb);
1091*e4b17023SJohn Marino 
1092*e4b17023SJohn Marino   return dr_equal_offsets_p1 (offset1, offset2);
1093*e4b17023SJohn Marino }
1094*e4b17023SJohn Marino 
1095*e4b17023SJohn Marino /* Returns true if FNA == FNB.  */
1096*e4b17023SJohn Marino 
1097*e4b17023SJohn Marino static bool
affine_function_equal_p(affine_fn fna,affine_fn fnb)1098*e4b17023SJohn Marino affine_function_equal_p (affine_fn fna, affine_fn fnb)
1099*e4b17023SJohn Marino {
1100*e4b17023SJohn Marino   unsigned i, n = VEC_length (tree, fna);
1101*e4b17023SJohn Marino 
1102*e4b17023SJohn Marino   if (n != VEC_length (tree, fnb))
1103*e4b17023SJohn Marino     return false;
1104*e4b17023SJohn Marino 
1105*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1106*e4b17023SJohn Marino     if (!operand_equal_p (VEC_index (tree, fna, i),
1107*e4b17023SJohn Marino 			  VEC_index (tree, fnb, i), 0))
1108*e4b17023SJohn Marino       return false;
1109*e4b17023SJohn Marino 
1110*e4b17023SJohn Marino   return true;
1111*e4b17023SJohn Marino }
1112*e4b17023SJohn Marino 
1113*e4b17023SJohn Marino /* If all the functions in CF are the same, returns one of them,
1114*e4b17023SJohn Marino    otherwise returns NULL.  */
1115*e4b17023SJohn Marino 
1116*e4b17023SJohn Marino static affine_fn
common_affine_function(conflict_function * cf)1117*e4b17023SJohn Marino common_affine_function (conflict_function *cf)
1118*e4b17023SJohn Marino {
1119*e4b17023SJohn Marino   unsigned i;
1120*e4b17023SJohn Marino   affine_fn comm;
1121*e4b17023SJohn Marino 
1122*e4b17023SJohn Marino   if (!CF_NONTRIVIAL_P (cf))
1123*e4b17023SJohn Marino     return NULL;
1124*e4b17023SJohn Marino 
1125*e4b17023SJohn Marino   comm = cf->fns[0];
1126*e4b17023SJohn Marino 
1127*e4b17023SJohn Marino   for (i = 1; i < cf->n; i++)
1128*e4b17023SJohn Marino     if (!affine_function_equal_p (comm, cf->fns[i]))
1129*e4b17023SJohn Marino       return NULL;
1130*e4b17023SJohn Marino 
1131*e4b17023SJohn Marino   return comm;
1132*e4b17023SJohn Marino }
1133*e4b17023SJohn Marino 
1134*e4b17023SJohn Marino /* Returns the base of the affine function FN.  */
1135*e4b17023SJohn Marino 
1136*e4b17023SJohn Marino static tree
affine_function_base(affine_fn fn)1137*e4b17023SJohn Marino affine_function_base (affine_fn fn)
1138*e4b17023SJohn Marino {
1139*e4b17023SJohn Marino   return VEC_index (tree, fn, 0);
1140*e4b17023SJohn Marino }
1141*e4b17023SJohn Marino 
1142*e4b17023SJohn Marino /* Returns true if FN is a constant.  */
1143*e4b17023SJohn Marino 
1144*e4b17023SJohn Marino static bool
affine_function_constant_p(affine_fn fn)1145*e4b17023SJohn Marino affine_function_constant_p (affine_fn fn)
1146*e4b17023SJohn Marino {
1147*e4b17023SJohn Marino   unsigned i;
1148*e4b17023SJohn Marino   tree coef;
1149*e4b17023SJohn Marino 
1150*e4b17023SJohn Marino   for (i = 1; VEC_iterate (tree, fn, i, coef); i++)
1151*e4b17023SJohn Marino     if (!integer_zerop (coef))
1152*e4b17023SJohn Marino       return false;
1153*e4b17023SJohn Marino 
1154*e4b17023SJohn Marino   return true;
1155*e4b17023SJohn Marino }
1156*e4b17023SJohn Marino 
1157*e4b17023SJohn Marino /* Returns true if FN is the zero constant function.  */
1158*e4b17023SJohn Marino 
1159*e4b17023SJohn Marino static bool
affine_function_zero_p(affine_fn fn)1160*e4b17023SJohn Marino affine_function_zero_p (affine_fn fn)
1161*e4b17023SJohn Marino {
1162*e4b17023SJohn Marino   return (integer_zerop (affine_function_base (fn))
1163*e4b17023SJohn Marino 	  && affine_function_constant_p (fn));
1164*e4b17023SJohn Marino }
1165*e4b17023SJohn Marino 
1166*e4b17023SJohn Marino /* Returns a signed integer type with the largest precision from TA
1167*e4b17023SJohn Marino    and TB.  */
1168*e4b17023SJohn Marino 
1169*e4b17023SJohn Marino static tree
signed_type_for_types(tree ta,tree tb)1170*e4b17023SJohn Marino signed_type_for_types (tree ta, tree tb)
1171*e4b17023SJohn Marino {
1172*e4b17023SJohn Marino   if (TYPE_PRECISION (ta) > TYPE_PRECISION (tb))
1173*e4b17023SJohn Marino     return signed_type_for (ta);
1174*e4b17023SJohn Marino   else
1175*e4b17023SJohn Marino     return signed_type_for (tb);
1176*e4b17023SJohn Marino }
1177*e4b17023SJohn Marino 
1178*e4b17023SJohn Marino /* Applies operation OP on affine functions FNA and FNB, and returns the
1179*e4b17023SJohn Marino    result.  */
1180*e4b17023SJohn Marino 
1181*e4b17023SJohn Marino static affine_fn
affine_fn_op(enum tree_code op,affine_fn fna,affine_fn fnb)1182*e4b17023SJohn Marino affine_fn_op (enum tree_code op, affine_fn fna, affine_fn fnb)
1183*e4b17023SJohn Marino {
1184*e4b17023SJohn Marino   unsigned i, n, m;
1185*e4b17023SJohn Marino   affine_fn ret;
1186*e4b17023SJohn Marino   tree coef;
1187*e4b17023SJohn Marino 
1188*e4b17023SJohn Marino   if (VEC_length (tree, fnb) > VEC_length (tree, fna))
1189*e4b17023SJohn Marino     {
1190*e4b17023SJohn Marino       n = VEC_length (tree, fna);
1191*e4b17023SJohn Marino       m = VEC_length (tree, fnb);
1192*e4b17023SJohn Marino     }
1193*e4b17023SJohn Marino   else
1194*e4b17023SJohn Marino     {
1195*e4b17023SJohn Marino       n = VEC_length (tree, fnb);
1196*e4b17023SJohn Marino       m = VEC_length (tree, fna);
1197*e4b17023SJohn Marino     }
1198*e4b17023SJohn Marino 
1199*e4b17023SJohn Marino   ret = VEC_alloc (tree, heap, m);
1200*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1201*e4b17023SJohn Marino     {
1202*e4b17023SJohn Marino       tree type = signed_type_for_types (TREE_TYPE (VEC_index (tree, fna, i)),
1203*e4b17023SJohn Marino 					 TREE_TYPE (VEC_index (tree, fnb, i)));
1204*e4b17023SJohn Marino 
1205*e4b17023SJohn Marino       VEC_quick_push (tree, ret,
1206*e4b17023SJohn Marino 		      fold_build2 (op, type,
1207*e4b17023SJohn Marino 				   VEC_index (tree, fna, i),
1208*e4b17023SJohn Marino 				   VEC_index (tree, fnb, i)));
1209*e4b17023SJohn Marino     }
1210*e4b17023SJohn Marino 
1211*e4b17023SJohn Marino   for (; VEC_iterate (tree, fna, i, coef); i++)
1212*e4b17023SJohn Marino     VEC_quick_push (tree, ret,
1213*e4b17023SJohn Marino 		    fold_build2 (op, signed_type_for (TREE_TYPE (coef)),
1214*e4b17023SJohn Marino 				 coef, integer_zero_node));
1215*e4b17023SJohn Marino   for (; VEC_iterate (tree, fnb, i, coef); i++)
1216*e4b17023SJohn Marino     VEC_quick_push (tree, ret,
1217*e4b17023SJohn Marino 		    fold_build2 (op, signed_type_for (TREE_TYPE (coef)),
1218*e4b17023SJohn Marino 				 integer_zero_node, coef));
1219*e4b17023SJohn Marino 
1220*e4b17023SJohn Marino   return ret;
1221*e4b17023SJohn Marino }
1222*e4b17023SJohn Marino 
1223*e4b17023SJohn Marino /* Returns the sum of affine functions FNA and FNB.  */
1224*e4b17023SJohn Marino 
1225*e4b17023SJohn Marino static affine_fn
affine_fn_plus(affine_fn fna,affine_fn fnb)1226*e4b17023SJohn Marino affine_fn_plus (affine_fn fna, affine_fn fnb)
1227*e4b17023SJohn Marino {
1228*e4b17023SJohn Marino   return affine_fn_op (PLUS_EXPR, fna, fnb);
1229*e4b17023SJohn Marino }
1230*e4b17023SJohn Marino 
1231*e4b17023SJohn Marino /* Returns the difference of affine functions FNA and FNB.  */
1232*e4b17023SJohn Marino 
1233*e4b17023SJohn Marino static affine_fn
affine_fn_minus(affine_fn fna,affine_fn fnb)1234*e4b17023SJohn Marino affine_fn_minus (affine_fn fna, affine_fn fnb)
1235*e4b17023SJohn Marino {
1236*e4b17023SJohn Marino   return affine_fn_op (MINUS_EXPR, fna, fnb);
1237*e4b17023SJohn Marino }
1238*e4b17023SJohn Marino 
1239*e4b17023SJohn Marino /* Frees affine function FN.  */
1240*e4b17023SJohn Marino 
1241*e4b17023SJohn Marino static void
affine_fn_free(affine_fn fn)1242*e4b17023SJohn Marino affine_fn_free (affine_fn fn)
1243*e4b17023SJohn Marino {
1244*e4b17023SJohn Marino   VEC_free (tree, heap, fn);
1245*e4b17023SJohn Marino }
1246*e4b17023SJohn Marino 
1247*e4b17023SJohn Marino /* Determine for each subscript in the data dependence relation DDR
1248*e4b17023SJohn Marino    the distance.  */
1249*e4b17023SJohn Marino 
1250*e4b17023SJohn Marino static void
compute_subscript_distance(struct data_dependence_relation * ddr)1251*e4b17023SJohn Marino compute_subscript_distance (struct data_dependence_relation *ddr)
1252*e4b17023SJohn Marino {
1253*e4b17023SJohn Marino   conflict_function *cf_a, *cf_b;
1254*e4b17023SJohn Marino   affine_fn fn_a, fn_b, diff;
1255*e4b17023SJohn Marino 
1256*e4b17023SJohn Marino   if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
1257*e4b17023SJohn Marino     {
1258*e4b17023SJohn Marino       unsigned int i;
1259*e4b17023SJohn Marino 
1260*e4b17023SJohn Marino       for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
1261*e4b17023SJohn Marino  	{
1262*e4b17023SJohn Marino  	  struct subscript *subscript;
1263*e4b17023SJohn Marino 
1264*e4b17023SJohn Marino  	  subscript = DDR_SUBSCRIPT (ddr, i);
1265*e4b17023SJohn Marino  	  cf_a = SUB_CONFLICTS_IN_A (subscript);
1266*e4b17023SJohn Marino  	  cf_b = SUB_CONFLICTS_IN_B (subscript);
1267*e4b17023SJohn Marino 
1268*e4b17023SJohn Marino 	  fn_a = common_affine_function (cf_a);
1269*e4b17023SJohn Marino 	  fn_b = common_affine_function (cf_b);
1270*e4b17023SJohn Marino 	  if (!fn_a || !fn_b)
1271*e4b17023SJohn Marino 	    {
1272*e4b17023SJohn Marino 	      SUB_DISTANCE (subscript) = chrec_dont_know;
1273*e4b17023SJohn Marino 	      return;
1274*e4b17023SJohn Marino 	    }
1275*e4b17023SJohn Marino 	  diff = affine_fn_minus (fn_a, fn_b);
1276*e4b17023SJohn Marino 
1277*e4b17023SJohn Marino  	  if (affine_function_constant_p (diff))
1278*e4b17023SJohn Marino  	    SUB_DISTANCE (subscript) = affine_function_base (diff);
1279*e4b17023SJohn Marino  	  else
1280*e4b17023SJohn Marino  	    SUB_DISTANCE (subscript) = chrec_dont_know;
1281*e4b17023SJohn Marino 
1282*e4b17023SJohn Marino 	  affine_fn_free (diff);
1283*e4b17023SJohn Marino  	}
1284*e4b17023SJohn Marino     }
1285*e4b17023SJohn Marino }
1286*e4b17023SJohn Marino 
1287*e4b17023SJohn Marino /* Returns the conflict function for "unknown".  */
1288*e4b17023SJohn Marino 
1289*e4b17023SJohn Marino static conflict_function *
conflict_fn_not_known(void)1290*e4b17023SJohn Marino conflict_fn_not_known (void)
1291*e4b17023SJohn Marino {
1292*e4b17023SJohn Marino   conflict_function *fn = XCNEW (conflict_function);
1293*e4b17023SJohn Marino   fn->n = NOT_KNOWN;
1294*e4b17023SJohn Marino 
1295*e4b17023SJohn Marino   return fn;
1296*e4b17023SJohn Marino }
1297*e4b17023SJohn Marino 
1298*e4b17023SJohn Marino /* Returns the conflict function for "independent".  */
1299*e4b17023SJohn Marino 
1300*e4b17023SJohn Marino static conflict_function *
conflict_fn_no_dependence(void)1301*e4b17023SJohn Marino conflict_fn_no_dependence (void)
1302*e4b17023SJohn Marino {
1303*e4b17023SJohn Marino   conflict_function *fn = XCNEW (conflict_function);
1304*e4b17023SJohn Marino   fn->n = NO_DEPENDENCE;
1305*e4b17023SJohn Marino 
1306*e4b17023SJohn Marino   return fn;
1307*e4b17023SJohn Marino }
1308*e4b17023SJohn Marino 
1309*e4b17023SJohn Marino /* Returns true if the address of OBJ is invariant in LOOP.  */
1310*e4b17023SJohn Marino 
1311*e4b17023SJohn Marino static bool
object_address_invariant_in_loop_p(const struct loop * loop,const_tree obj)1312*e4b17023SJohn Marino object_address_invariant_in_loop_p (const struct loop *loop, const_tree obj)
1313*e4b17023SJohn Marino {
1314*e4b17023SJohn Marino   while (handled_component_p (obj))
1315*e4b17023SJohn Marino     {
1316*e4b17023SJohn Marino       if (TREE_CODE (obj) == ARRAY_REF)
1317*e4b17023SJohn Marino 	{
1318*e4b17023SJohn Marino 	  /* Index of the ARRAY_REF was zeroed in analyze_indices, thus we only
1319*e4b17023SJohn Marino 	     need to check the stride and the lower bound of the reference.  */
1320*e4b17023SJohn Marino 	  if (chrec_contains_symbols_defined_in_loop (TREE_OPERAND (obj, 2),
1321*e4b17023SJohn Marino 						      loop->num)
1322*e4b17023SJohn Marino 	      || chrec_contains_symbols_defined_in_loop (TREE_OPERAND (obj, 3),
1323*e4b17023SJohn Marino 							 loop->num))
1324*e4b17023SJohn Marino 	    return false;
1325*e4b17023SJohn Marino 	}
1326*e4b17023SJohn Marino       else if (TREE_CODE (obj) == COMPONENT_REF)
1327*e4b17023SJohn Marino 	{
1328*e4b17023SJohn Marino 	  if (chrec_contains_symbols_defined_in_loop (TREE_OPERAND (obj, 2),
1329*e4b17023SJohn Marino 						      loop->num))
1330*e4b17023SJohn Marino 	    return false;
1331*e4b17023SJohn Marino 	}
1332*e4b17023SJohn Marino       obj = TREE_OPERAND (obj, 0);
1333*e4b17023SJohn Marino     }
1334*e4b17023SJohn Marino 
1335*e4b17023SJohn Marino   if (!INDIRECT_REF_P (obj)
1336*e4b17023SJohn Marino       && TREE_CODE (obj) != MEM_REF)
1337*e4b17023SJohn Marino     return true;
1338*e4b17023SJohn Marino 
1339*e4b17023SJohn Marino   return !chrec_contains_symbols_defined_in_loop (TREE_OPERAND (obj, 0),
1340*e4b17023SJohn Marino 						  loop->num);
1341*e4b17023SJohn Marino }
1342*e4b17023SJohn Marino 
1343*e4b17023SJohn Marino /* Returns false if we can prove that data references A and B do not alias,
1344*e4b17023SJohn Marino    true otherwise.  If LOOP_NEST is false no cross-iteration aliases are
1345*e4b17023SJohn Marino    considered.  */
1346*e4b17023SJohn Marino 
1347*e4b17023SJohn Marino bool
dr_may_alias_p(const struct data_reference * a,const struct data_reference * b,bool loop_nest)1348*e4b17023SJohn Marino dr_may_alias_p (const struct data_reference *a, const struct data_reference *b,
1349*e4b17023SJohn Marino 		bool loop_nest)
1350*e4b17023SJohn Marino {
1351*e4b17023SJohn Marino   tree addr_a = DR_BASE_OBJECT (a);
1352*e4b17023SJohn Marino   tree addr_b = DR_BASE_OBJECT (b);
1353*e4b17023SJohn Marino 
1354*e4b17023SJohn Marino   /* If we are not processing a loop nest but scalar code we
1355*e4b17023SJohn Marino      do not need to care about possible cross-iteration dependences
1356*e4b17023SJohn Marino      and thus can process the full original reference.  Do so,
1357*e4b17023SJohn Marino      similar to how loop invariant motion applies extra offset-based
1358*e4b17023SJohn Marino      disambiguation.  */
1359*e4b17023SJohn Marino   if (!loop_nest)
1360*e4b17023SJohn Marino     {
1361*e4b17023SJohn Marino       aff_tree off1, off2;
1362*e4b17023SJohn Marino       double_int size1, size2;
1363*e4b17023SJohn Marino       get_inner_reference_aff (DR_REF (a), &off1, &size1);
1364*e4b17023SJohn Marino       get_inner_reference_aff (DR_REF (b), &off2, &size2);
1365*e4b17023SJohn Marino       aff_combination_scale (&off1, double_int_minus_one);
1366*e4b17023SJohn Marino       aff_combination_add (&off2, &off1);
1367*e4b17023SJohn Marino       if (aff_comb_cannot_overlap_p (&off2, size1, size2))
1368*e4b17023SJohn Marino 	return false;
1369*e4b17023SJohn Marino     }
1370*e4b17023SJohn Marino 
1371*e4b17023SJohn Marino   /* If we had an evolution in a MEM_REF BASE_OBJECT we do not know
1372*e4b17023SJohn Marino      the size of the base-object.  So we cannot do any offset/overlap
1373*e4b17023SJohn Marino      based analysis but have to rely on points-to information only.  */
1374*e4b17023SJohn Marino   if (TREE_CODE (addr_a) == MEM_REF
1375*e4b17023SJohn Marino       && DR_UNCONSTRAINED_BASE (a))
1376*e4b17023SJohn Marino     {
1377*e4b17023SJohn Marino       if (TREE_CODE (addr_b) == MEM_REF
1378*e4b17023SJohn Marino 	  && DR_UNCONSTRAINED_BASE (b))
1379*e4b17023SJohn Marino 	return ptr_derefs_may_alias_p (TREE_OPERAND (addr_a, 0),
1380*e4b17023SJohn Marino 				       TREE_OPERAND (addr_b, 0));
1381*e4b17023SJohn Marino       else
1382*e4b17023SJohn Marino 	return ptr_derefs_may_alias_p (TREE_OPERAND (addr_a, 0),
1383*e4b17023SJohn Marino 				       build_fold_addr_expr (addr_b));
1384*e4b17023SJohn Marino     }
1385*e4b17023SJohn Marino   else if (TREE_CODE (addr_b) == MEM_REF
1386*e4b17023SJohn Marino 	   && DR_UNCONSTRAINED_BASE (b))
1387*e4b17023SJohn Marino     return ptr_derefs_may_alias_p (build_fold_addr_expr (addr_a),
1388*e4b17023SJohn Marino 				   TREE_OPERAND (addr_b, 0));
1389*e4b17023SJohn Marino 
1390*e4b17023SJohn Marino   /* Otherwise DR_BASE_OBJECT is an access that covers the whole object
1391*e4b17023SJohn Marino      that is being subsetted in the loop nest.  */
1392*e4b17023SJohn Marino   if (DR_IS_WRITE (a) && DR_IS_WRITE (b))
1393*e4b17023SJohn Marino     return refs_output_dependent_p (addr_a, addr_b);
1394*e4b17023SJohn Marino   else if (DR_IS_READ (a) && DR_IS_WRITE (b))
1395*e4b17023SJohn Marino     return refs_anti_dependent_p (addr_a, addr_b);
1396*e4b17023SJohn Marino   return refs_may_alias_p (addr_a, addr_b);
1397*e4b17023SJohn Marino }
1398*e4b17023SJohn Marino 
1399*e4b17023SJohn Marino /* Initialize a data dependence relation between data accesses A and
1400*e4b17023SJohn Marino    B.  NB_LOOPS is the number of loops surrounding the references: the
1401*e4b17023SJohn Marino    size of the classic distance/direction vectors.  */
1402*e4b17023SJohn Marino 
1403*e4b17023SJohn Marino struct data_dependence_relation *
initialize_data_dependence_relation(struct data_reference * a,struct data_reference * b,VEC (loop_p,heap)* loop_nest)1404*e4b17023SJohn Marino initialize_data_dependence_relation (struct data_reference *a,
1405*e4b17023SJohn Marino 				     struct data_reference *b,
1406*e4b17023SJohn Marino  				     VEC (loop_p, heap) *loop_nest)
1407*e4b17023SJohn Marino {
1408*e4b17023SJohn Marino   struct data_dependence_relation *res;
1409*e4b17023SJohn Marino   unsigned int i;
1410*e4b17023SJohn Marino 
1411*e4b17023SJohn Marino   res = XNEW (struct data_dependence_relation);
1412*e4b17023SJohn Marino   DDR_A (res) = a;
1413*e4b17023SJohn Marino   DDR_B (res) = b;
1414*e4b17023SJohn Marino   DDR_LOOP_NEST (res) = NULL;
1415*e4b17023SJohn Marino   DDR_REVERSED_P (res) = false;
1416*e4b17023SJohn Marino   DDR_SUBSCRIPTS (res) = NULL;
1417*e4b17023SJohn Marino   DDR_DIR_VECTS (res) = NULL;
1418*e4b17023SJohn Marino   DDR_DIST_VECTS (res) = NULL;
1419*e4b17023SJohn Marino 
1420*e4b17023SJohn Marino   if (a == NULL || b == NULL)
1421*e4b17023SJohn Marino     {
1422*e4b17023SJohn Marino       DDR_ARE_DEPENDENT (res) = chrec_dont_know;
1423*e4b17023SJohn Marino       return res;
1424*e4b17023SJohn Marino     }
1425*e4b17023SJohn Marino 
1426*e4b17023SJohn Marino   /* If the data references do not alias, then they are independent.  */
1427*e4b17023SJohn Marino   if (!dr_may_alias_p (a, b, loop_nest != NULL))
1428*e4b17023SJohn Marino     {
1429*e4b17023SJohn Marino       DDR_ARE_DEPENDENT (res) = chrec_known;
1430*e4b17023SJohn Marino       return res;
1431*e4b17023SJohn Marino     }
1432*e4b17023SJohn Marino 
1433*e4b17023SJohn Marino   /* The case where the references are exactly the same.  */
1434*e4b17023SJohn Marino   if (operand_equal_p (DR_REF (a), DR_REF (b), 0))
1435*e4b17023SJohn Marino     {
1436*e4b17023SJohn Marino      if (loop_nest
1437*e4b17023SJohn Marino         && !object_address_invariant_in_loop_p (VEC_index (loop_p, loop_nest, 0),
1438*e4b17023SJohn Marino        					        DR_BASE_OBJECT (a)))
1439*e4b17023SJohn Marino       {
1440*e4b17023SJohn Marino         DDR_ARE_DEPENDENT (res) = chrec_dont_know;
1441*e4b17023SJohn Marino         return res;
1442*e4b17023SJohn Marino       }
1443*e4b17023SJohn Marino       DDR_AFFINE_P (res) = true;
1444*e4b17023SJohn Marino       DDR_ARE_DEPENDENT (res) = NULL_TREE;
1445*e4b17023SJohn Marino       DDR_SUBSCRIPTS (res) = VEC_alloc (subscript_p, heap, DR_NUM_DIMENSIONS (a));
1446*e4b17023SJohn Marino       DDR_LOOP_NEST (res) = loop_nest;
1447*e4b17023SJohn Marino       DDR_INNER_LOOP (res) = 0;
1448*e4b17023SJohn Marino       DDR_SELF_REFERENCE (res) = true;
1449*e4b17023SJohn Marino       for (i = 0; i < DR_NUM_DIMENSIONS (a); i++)
1450*e4b17023SJohn Marino        {
1451*e4b17023SJohn Marino          struct subscript *subscript;
1452*e4b17023SJohn Marino 
1453*e4b17023SJohn Marino          subscript = XNEW (struct subscript);
1454*e4b17023SJohn Marino          SUB_CONFLICTS_IN_A (subscript) = conflict_fn_not_known ();
1455*e4b17023SJohn Marino          SUB_CONFLICTS_IN_B (subscript) = conflict_fn_not_known ();
1456*e4b17023SJohn Marino          SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
1457*e4b17023SJohn Marino          SUB_DISTANCE (subscript) = chrec_dont_know;
1458*e4b17023SJohn Marino          VEC_safe_push (subscript_p, heap, DDR_SUBSCRIPTS (res), subscript);
1459*e4b17023SJohn Marino        }
1460*e4b17023SJohn Marino       return res;
1461*e4b17023SJohn Marino     }
1462*e4b17023SJohn Marino 
1463*e4b17023SJohn Marino   /* If the references do not access the same object, we do not know
1464*e4b17023SJohn Marino      whether they alias or not.  */
1465*e4b17023SJohn Marino   if (!operand_equal_p (DR_BASE_OBJECT (a), DR_BASE_OBJECT (b), 0))
1466*e4b17023SJohn Marino     {
1467*e4b17023SJohn Marino       DDR_ARE_DEPENDENT (res) = chrec_dont_know;
1468*e4b17023SJohn Marino       return res;
1469*e4b17023SJohn Marino     }
1470*e4b17023SJohn Marino 
1471*e4b17023SJohn Marino   /* If the base of the object is not invariant in the loop nest, we cannot
1472*e4b17023SJohn Marino      analyze it.  TODO -- in fact, it would suffice to record that there may
1473*e4b17023SJohn Marino      be arbitrary dependences in the loops where the base object varies.  */
1474*e4b17023SJohn Marino   if (loop_nest
1475*e4b17023SJohn Marino       && !object_address_invariant_in_loop_p (VEC_index (loop_p, loop_nest, 0),
1476*e4b17023SJohn Marino      					      DR_BASE_OBJECT (a)))
1477*e4b17023SJohn Marino     {
1478*e4b17023SJohn Marino       DDR_ARE_DEPENDENT (res) = chrec_dont_know;
1479*e4b17023SJohn Marino       return res;
1480*e4b17023SJohn Marino     }
1481*e4b17023SJohn Marino 
1482*e4b17023SJohn Marino   /* If the number of dimensions of the access to not agree we can have
1483*e4b17023SJohn Marino      a pointer access to a component of the array element type and an
1484*e4b17023SJohn Marino      array access while the base-objects are still the same.  Punt.  */
1485*e4b17023SJohn Marino   if (DR_NUM_DIMENSIONS (a) != DR_NUM_DIMENSIONS (b))
1486*e4b17023SJohn Marino     {
1487*e4b17023SJohn Marino       DDR_ARE_DEPENDENT (res) = chrec_dont_know;
1488*e4b17023SJohn Marino       return res;
1489*e4b17023SJohn Marino     }
1490*e4b17023SJohn Marino 
1491*e4b17023SJohn Marino   DDR_AFFINE_P (res) = true;
1492*e4b17023SJohn Marino   DDR_ARE_DEPENDENT (res) = NULL_TREE;
1493*e4b17023SJohn Marino   DDR_SUBSCRIPTS (res) = VEC_alloc (subscript_p, heap, DR_NUM_DIMENSIONS (a));
1494*e4b17023SJohn Marino   DDR_LOOP_NEST (res) = loop_nest;
1495*e4b17023SJohn Marino   DDR_INNER_LOOP (res) = 0;
1496*e4b17023SJohn Marino   DDR_SELF_REFERENCE (res) = false;
1497*e4b17023SJohn Marino 
1498*e4b17023SJohn Marino   for (i = 0; i < DR_NUM_DIMENSIONS (a); i++)
1499*e4b17023SJohn Marino     {
1500*e4b17023SJohn Marino       struct subscript *subscript;
1501*e4b17023SJohn Marino 
1502*e4b17023SJohn Marino       subscript = XNEW (struct subscript);
1503*e4b17023SJohn Marino       SUB_CONFLICTS_IN_A (subscript) = conflict_fn_not_known ();
1504*e4b17023SJohn Marino       SUB_CONFLICTS_IN_B (subscript) = conflict_fn_not_known ();
1505*e4b17023SJohn Marino       SUB_LAST_CONFLICT (subscript) = chrec_dont_know;
1506*e4b17023SJohn Marino       SUB_DISTANCE (subscript) = chrec_dont_know;
1507*e4b17023SJohn Marino       VEC_safe_push (subscript_p, heap, DDR_SUBSCRIPTS (res), subscript);
1508*e4b17023SJohn Marino     }
1509*e4b17023SJohn Marino 
1510*e4b17023SJohn Marino   return res;
1511*e4b17023SJohn Marino }
1512*e4b17023SJohn Marino 
1513*e4b17023SJohn Marino /* Frees memory used by the conflict function F.  */
1514*e4b17023SJohn Marino 
1515*e4b17023SJohn Marino static void
free_conflict_function(conflict_function * f)1516*e4b17023SJohn Marino free_conflict_function (conflict_function *f)
1517*e4b17023SJohn Marino {
1518*e4b17023SJohn Marino   unsigned i;
1519*e4b17023SJohn Marino 
1520*e4b17023SJohn Marino   if (CF_NONTRIVIAL_P (f))
1521*e4b17023SJohn Marino     {
1522*e4b17023SJohn Marino       for (i = 0; i < f->n; i++)
1523*e4b17023SJohn Marino 	affine_fn_free (f->fns[i]);
1524*e4b17023SJohn Marino     }
1525*e4b17023SJohn Marino   free (f);
1526*e4b17023SJohn Marino }
1527*e4b17023SJohn Marino 
1528*e4b17023SJohn Marino /* Frees memory used by SUBSCRIPTS.  */
1529*e4b17023SJohn Marino 
1530*e4b17023SJohn Marino static void
free_subscripts(VEC (subscript_p,heap)* subscripts)1531*e4b17023SJohn Marino free_subscripts (VEC (subscript_p, heap) *subscripts)
1532*e4b17023SJohn Marino {
1533*e4b17023SJohn Marino   unsigned i;
1534*e4b17023SJohn Marino   subscript_p s;
1535*e4b17023SJohn Marino 
1536*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (subscript_p, subscripts, i, s)
1537*e4b17023SJohn Marino     {
1538*e4b17023SJohn Marino       free_conflict_function (s->conflicting_iterations_in_a);
1539*e4b17023SJohn Marino       free_conflict_function (s->conflicting_iterations_in_b);
1540*e4b17023SJohn Marino       free (s);
1541*e4b17023SJohn Marino     }
1542*e4b17023SJohn Marino   VEC_free (subscript_p, heap, subscripts);
1543*e4b17023SJohn Marino }
1544*e4b17023SJohn Marino 
1545*e4b17023SJohn Marino /* Set DDR_ARE_DEPENDENT to CHREC and finalize the subscript overlap
1546*e4b17023SJohn Marino    description.  */
1547*e4b17023SJohn Marino 
1548*e4b17023SJohn Marino static inline void
finalize_ddr_dependent(struct data_dependence_relation * ddr,tree chrec)1549*e4b17023SJohn Marino finalize_ddr_dependent (struct data_dependence_relation *ddr,
1550*e4b17023SJohn Marino 			tree chrec)
1551*e4b17023SJohn Marino {
1552*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1553*e4b17023SJohn Marino     {
1554*e4b17023SJohn Marino       fprintf (dump_file, "(dependence classified: ");
1555*e4b17023SJohn Marino       print_generic_expr (dump_file, chrec, 0);
1556*e4b17023SJohn Marino       fprintf (dump_file, ")\n");
1557*e4b17023SJohn Marino     }
1558*e4b17023SJohn Marino 
1559*e4b17023SJohn Marino   DDR_ARE_DEPENDENT (ddr) = chrec;
1560*e4b17023SJohn Marino   free_subscripts (DDR_SUBSCRIPTS (ddr));
1561*e4b17023SJohn Marino   DDR_SUBSCRIPTS (ddr) = NULL;
1562*e4b17023SJohn Marino }
1563*e4b17023SJohn Marino 
1564*e4b17023SJohn Marino /* The dependence relation DDR cannot be represented by a distance
1565*e4b17023SJohn Marino    vector.  */
1566*e4b17023SJohn Marino 
1567*e4b17023SJohn Marino static inline void
non_affine_dependence_relation(struct data_dependence_relation * ddr)1568*e4b17023SJohn Marino non_affine_dependence_relation (struct data_dependence_relation *ddr)
1569*e4b17023SJohn Marino {
1570*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1571*e4b17023SJohn Marino     fprintf (dump_file, "(Dependence relation cannot be represented by distance vector.) \n");
1572*e4b17023SJohn Marino 
1573*e4b17023SJohn Marino   DDR_AFFINE_P (ddr) = false;
1574*e4b17023SJohn Marino }
1575*e4b17023SJohn Marino 
1576*e4b17023SJohn Marino 
1577*e4b17023SJohn Marino 
1578*e4b17023SJohn Marino /* This section contains the classic Banerjee tests.  */
1579*e4b17023SJohn Marino 
1580*e4b17023SJohn Marino /* Returns true iff CHREC_A and CHREC_B are not dependent on any index
1581*e4b17023SJohn Marino    variables, i.e., if the ZIV (Zero Index Variable) test is true.  */
1582*e4b17023SJohn Marino 
1583*e4b17023SJohn Marino static inline bool
ziv_subscript_p(const_tree chrec_a,const_tree chrec_b)1584*e4b17023SJohn Marino ziv_subscript_p (const_tree chrec_a, const_tree chrec_b)
1585*e4b17023SJohn Marino {
1586*e4b17023SJohn Marino   return (evolution_function_is_constant_p (chrec_a)
1587*e4b17023SJohn Marino 	  && evolution_function_is_constant_p (chrec_b));
1588*e4b17023SJohn Marino }
1589*e4b17023SJohn Marino 
1590*e4b17023SJohn Marino /* Returns true iff CHREC_A and CHREC_B are dependent on an index
1591*e4b17023SJohn Marino    variable, i.e., if the SIV (Single Index Variable) test is true.  */
1592*e4b17023SJohn Marino 
1593*e4b17023SJohn Marino static bool
siv_subscript_p(const_tree chrec_a,const_tree chrec_b)1594*e4b17023SJohn Marino siv_subscript_p (const_tree chrec_a, const_tree chrec_b)
1595*e4b17023SJohn Marino {
1596*e4b17023SJohn Marino   if ((evolution_function_is_constant_p (chrec_a)
1597*e4b17023SJohn Marino        && evolution_function_is_univariate_p (chrec_b))
1598*e4b17023SJohn Marino       || (evolution_function_is_constant_p (chrec_b)
1599*e4b17023SJohn Marino 	  && evolution_function_is_univariate_p (chrec_a)))
1600*e4b17023SJohn Marino     return true;
1601*e4b17023SJohn Marino 
1602*e4b17023SJohn Marino   if (evolution_function_is_univariate_p (chrec_a)
1603*e4b17023SJohn Marino       && evolution_function_is_univariate_p (chrec_b))
1604*e4b17023SJohn Marino     {
1605*e4b17023SJohn Marino       switch (TREE_CODE (chrec_a))
1606*e4b17023SJohn Marino 	{
1607*e4b17023SJohn Marino 	case POLYNOMIAL_CHREC:
1608*e4b17023SJohn Marino 	  switch (TREE_CODE (chrec_b))
1609*e4b17023SJohn Marino 	    {
1610*e4b17023SJohn Marino 	    case POLYNOMIAL_CHREC:
1611*e4b17023SJohn Marino 	      if (CHREC_VARIABLE (chrec_a) != CHREC_VARIABLE (chrec_b))
1612*e4b17023SJohn Marino 		return false;
1613*e4b17023SJohn Marino 
1614*e4b17023SJohn Marino 	    default:
1615*e4b17023SJohn Marino 	      return true;
1616*e4b17023SJohn Marino 	    }
1617*e4b17023SJohn Marino 
1618*e4b17023SJohn Marino 	default:
1619*e4b17023SJohn Marino 	  return true;
1620*e4b17023SJohn Marino 	}
1621*e4b17023SJohn Marino     }
1622*e4b17023SJohn Marino 
1623*e4b17023SJohn Marino   return false;
1624*e4b17023SJohn Marino }
1625*e4b17023SJohn Marino 
1626*e4b17023SJohn Marino /* Creates a conflict function with N dimensions.  The affine functions
1627*e4b17023SJohn Marino    in each dimension follow.  */
1628*e4b17023SJohn Marino 
1629*e4b17023SJohn Marino static conflict_function *
conflict_fn(unsigned n,...)1630*e4b17023SJohn Marino conflict_fn (unsigned n, ...)
1631*e4b17023SJohn Marino {
1632*e4b17023SJohn Marino   unsigned i;
1633*e4b17023SJohn Marino   conflict_function *ret = XCNEW (conflict_function);
1634*e4b17023SJohn Marino   va_list ap;
1635*e4b17023SJohn Marino 
1636*e4b17023SJohn Marino   gcc_assert (0 < n && n <= MAX_DIM);
1637*e4b17023SJohn Marino   va_start(ap, n);
1638*e4b17023SJohn Marino 
1639*e4b17023SJohn Marino   ret->n = n;
1640*e4b17023SJohn Marino   for (i = 0; i < n; i++)
1641*e4b17023SJohn Marino     ret->fns[i] = va_arg (ap, affine_fn);
1642*e4b17023SJohn Marino   va_end(ap);
1643*e4b17023SJohn Marino 
1644*e4b17023SJohn Marino   return ret;
1645*e4b17023SJohn Marino }
1646*e4b17023SJohn Marino 
1647*e4b17023SJohn Marino /* Returns constant affine function with value CST.  */
1648*e4b17023SJohn Marino 
1649*e4b17023SJohn Marino static affine_fn
affine_fn_cst(tree cst)1650*e4b17023SJohn Marino affine_fn_cst (tree cst)
1651*e4b17023SJohn Marino {
1652*e4b17023SJohn Marino   affine_fn fn = VEC_alloc (tree, heap, 1);
1653*e4b17023SJohn Marino   VEC_quick_push (tree, fn, cst);
1654*e4b17023SJohn Marino   return fn;
1655*e4b17023SJohn Marino }
1656*e4b17023SJohn Marino 
1657*e4b17023SJohn Marino /* Returns affine function with single variable, CST + COEF * x_DIM.  */
1658*e4b17023SJohn Marino 
1659*e4b17023SJohn Marino static affine_fn
affine_fn_univar(tree cst,unsigned dim,tree coef)1660*e4b17023SJohn Marino affine_fn_univar (tree cst, unsigned dim, tree coef)
1661*e4b17023SJohn Marino {
1662*e4b17023SJohn Marino   affine_fn fn = VEC_alloc (tree, heap, dim + 1);
1663*e4b17023SJohn Marino   unsigned i;
1664*e4b17023SJohn Marino 
1665*e4b17023SJohn Marino   gcc_assert (dim > 0);
1666*e4b17023SJohn Marino   VEC_quick_push (tree, fn, cst);
1667*e4b17023SJohn Marino   for (i = 1; i < dim; i++)
1668*e4b17023SJohn Marino     VEC_quick_push (tree, fn, integer_zero_node);
1669*e4b17023SJohn Marino   VEC_quick_push (tree, fn, coef);
1670*e4b17023SJohn Marino   return fn;
1671*e4b17023SJohn Marino }
1672*e4b17023SJohn Marino 
1673*e4b17023SJohn Marino /* Analyze a ZIV (Zero Index Variable) subscript.  *OVERLAPS_A and
1674*e4b17023SJohn Marino    *OVERLAPS_B are initialized to the functions that describe the
1675*e4b17023SJohn Marino    relation between the elements accessed twice by CHREC_A and
1676*e4b17023SJohn Marino    CHREC_B.  For k >= 0, the following property is verified:
1677*e4b17023SJohn Marino 
1678*e4b17023SJohn Marino    CHREC_A (*OVERLAPS_A (k)) = CHREC_B (*OVERLAPS_B (k)).  */
1679*e4b17023SJohn Marino 
1680*e4b17023SJohn Marino static void
analyze_ziv_subscript(tree chrec_a,tree chrec_b,conflict_function ** overlaps_a,conflict_function ** overlaps_b,tree * last_conflicts)1681*e4b17023SJohn Marino analyze_ziv_subscript (tree chrec_a,
1682*e4b17023SJohn Marino 		       tree chrec_b,
1683*e4b17023SJohn Marino 		       conflict_function **overlaps_a,
1684*e4b17023SJohn Marino 		       conflict_function **overlaps_b,
1685*e4b17023SJohn Marino 		       tree *last_conflicts)
1686*e4b17023SJohn Marino {
1687*e4b17023SJohn Marino   tree type, difference;
1688*e4b17023SJohn Marino   dependence_stats.num_ziv++;
1689*e4b17023SJohn Marino 
1690*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1691*e4b17023SJohn Marino     fprintf (dump_file, "(analyze_ziv_subscript \n");
1692*e4b17023SJohn Marino 
1693*e4b17023SJohn Marino   type = signed_type_for_types (TREE_TYPE (chrec_a), TREE_TYPE (chrec_b));
1694*e4b17023SJohn Marino   chrec_a = chrec_convert (type, chrec_a, NULL);
1695*e4b17023SJohn Marino   chrec_b = chrec_convert (type, chrec_b, NULL);
1696*e4b17023SJohn Marino   difference = chrec_fold_minus (type, chrec_a, chrec_b);
1697*e4b17023SJohn Marino 
1698*e4b17023SJohn Marino   switch (TREE_CODE (difference))
1699*e4b17023SJohn Marino     {
1700*e4b17023SJohn Marino     case INTEGER_CST:
1701*e4b17023SJohn Marino       if (integer_zerop (difference))
1702*e4b17023SJohn Marino 	{
1703*e4b17023SJohn Marino 	  /* The difference is equal to zero: the accessed index
1704*e4b17023SJohn Marino 	     overlaps for each iteration in the loop.  */
1705*e4b17023SJohn Marino 	  *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
1706*e4b17023SJohn Marino 	  *overlaps_b = conflict_fn (1, affine_fn_cst (integer_zero_node));
1707*e4b17023SJohn Marino 	  *last_conflicts = chrec_dont_know;
1708*e4b17023SJohn Marino 	  dependence_stats.num_ziv_dependent++;
1709*e4b17023SJohn Marino 	}
1710*e4b17023SJohn Marino       else
1711*e4b17023SJohn Marino 	{
1712*e4b17023SJohn Marino 	  /* The accesses do not overlap.  */
1713*e4b17023SJohn Marino 	  *overlaps_a = conflict_fn_no_dependence ();
1714*e4b17023SJohn Marino 	  *overlaps_b = conflict_fn_no_dependence ();
1715*e4b17023SJohn Marino 	  *last_conflicts = integer_zero_node;
1716*e4b17023SJohn Marino 	  dependence_stats.num_ziv_independent++;
1717*e4b17023SJohn Marino 	}
1718*e4b17023SJohn Marino       break;
1719*e4b17023SJohn Marino 
1720*e4b17023SJohn Marino     default:
1721*e4b17023SJohn Marino       /* We're not sure whether the indexes overlap.  For the moment,
1722*e4b17023SJohn Marino 	 conservatively answer "don't know".  */
1723*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1724*e4b17023SJohn Marino 	fprintf (dump_file, "ziv test failed: difference is non-integer.\n");
1725*e4b17023SJohn Marino 
1726*e4b17023SJohn Marino       *overlaps_a = conflict_fn_not_known ();
1727*e4b17023SJohn Marino       *overlaps_b = conflict_fn_not_known ();
1728*e4b17023SJohn Marino       *last_conflicts = chrec_dont_know;
1729*e4b17023SJohn Marino       dependence_stats.num_ziv_unimplemented++;
1730*e4b17023SJohn Marino       break;
1731*e4b17023SJohn Marino     }
1732*e4b17023SJohn Marino 
1733*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
1734*e4b17023SJohn Marino     fprintf (dump_file, ")\n");
1735*e4b17023SJohn Marino }
1736*e4b17023SJohn Marino 
1737*e4b17023SJohn Marino /* Similar to max_stmt_executions_int, but returns the bound as a tree,
1738*e4b17023SJohn Marino    and only if it fits to the int type.  If this is not the case, or the
1739*e4b17023SJohn Marino    bound  on the number of iterations of LOOP could not be derived, returns
1740*e4b17023SJohn Marino    chrec_dont_know.  */
1741*e4b17023SJohn Marino 
1742*e4b17023SJohn Marino static tree
max_stmt_executions_tree(struct loop * loop)1743*e4b17023SJohn Marino max_stmt_executions_tree (struct loop *loop)
1744*e4b17023SJohn Marino {
1745*e4b17023SJohn Marino   double_int nit;
1746*e4b17023SJohn Marino 
1747*e4b17023SJohn Marino   if (!max_stmt_executions (loop, true, &nit))
1748*e4b17023SJohn Marino     return chrec_dont_know;
1749*e4b17023SJohn Marino 
1750*e4b17023SJohn Marino   if (!double_int_fits_to_tree_p (unsigned_type_node, nit))
1751*e4b17023SJohn Marino     return chrec_dont_know;
1752*e4b17023SJohn Marino 
1753*e4b17023SJohn Marino   return double_int_to_tree (unsigned_type_node, nit);
1754*e4b17023SJohn Marino }
1755*e4b17023SJohn Marino 
1756*e4b17023SJohn Marino /* Determine whether the CHREC is always positive/negative.  If the expression
1757*e4b17023SJohn Marino    cannot be statically analyzed, return false, otherwise set the answer into
1758*e4b17023SJohn Marino    VALUE.  */
1759*e4b17023SJohn Marino 
1760*e4b17023SJohn Marino static bool
chrec_is_positive(tree chrec,bool * value)1761*e4b17023SJohn Marino chrec_is_positive (tree chrec, bool *value)
1762*e4b17023SJohn Marino {
1763*e4b17023SJohn Marino   bool value0, value1, value2;
1764*e4b17023SJohn Marino   tree end_value, nb_iter;
1765*e4b17023SJohn Marino 
1766*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
1767*e4b17023SJohn Marino     {
1768*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
1769*e4b17023SJohn Marino       if (!chrec_is_positive (CHREC_LEFT (chrec), &value0)
1770*e4b17023SJohn Marino 	  || !chrec_is_positive (CHREC_RIGHT (chrec), &value1))
1771*e4b17023SJohn Marino 	return false;
1772*e4b17023SJohn Marino 
1773*e4b17023SJohn Marino       /* FIXME -- overflows.  */
1774*e4b17023SJohn Marino       if (value0 == value1)
1775*e4b17023SJohn Marino 	{
1776*e4b17023SJohn Marino 	  *value = value0;
1777*e4b17023SJohn Marino 	  return true;
1778*e4b17023SJohn Marino 	}
1779*e4b17023SJohn Marino 
1780*e4b17023SJohn Marino       /* Otherwise the chrec is under the form: "{-197, +, 2}_1",
1781*e4b17023SJohn Marino 	 and the proof consists in showing that the sign never
1782*e4b17023SJohn Marino 	 changes during the execution of the loop, from 0 to
1783*e4b17023SJohn Marino 	 loop->nb_iterations.  */
1784*e4b17023SJohn Marino       if (!evolution_function_is_affine_p (chrec))
1785*e4b17023SJohn Marino 	return false;
1786*e4b17023SJohn Marino 
1787*e4b17023SJohn Marino       nb_iter = number_of_latch_executions (get_chrec_loop (chrec));
1788*e4b17023SJohn Marino       if (chrec_contains_undetermined (nb_iter))
1789*e4b17023SJohn Marino 	return false;
1790*e4b17023SJohn Marino 
1791*e4b17023SJohn Marino #if 0
1792*e4b17023SJohn Marino       /* TODO -- If the test is after the exit, we may decrease the number of
1793*e4b17023SJohn Marino 	 iterations by one.  */
1794*e4b17023SJohn Marino       if (after_exit)
1795*e4b17023SJohn Marino 	nb_iter = chrec_fold_minus (type, nb_iter, build_int_cst (type, 1));
1796*e4b17023SJohn Marino #endif
1797*e4b17023SJohn Marino 
1798*e4b17023SJohn Marino       end_value = chrec_apply (CHREC_VARIABLE (chrec), chrec, nb_iter);
1799*e4b17023SJohn Marino 
1800*e4b17023SJohn Marino       if (!chrec_is_positive (end_value, &value2))
1801*e4b17023SJohn Marino 	return false;
1802*e4b17023SJohn Marino 
1803*e4b17023SJohn Marino       *value = value0;
1804*e4b17023SJohn Marino       return value0 == value1;
1805*e4b17023SJohn Marino 
1806*e4b17023SJohn Marino     case INTEGER_CST:
1807*e4b17023SJohn Marino       switch (tree_int_cst_sgn (chrec))
1808*e4b17023SJohn Marino 	{
1809*e4b17023SJohn Marino 	case -1:
1810*e4b17023SJohn Marino 	  *value = false;
1811*e4b17023SJohn Marino 	  break;
1812*e4b17023SJohn Marino 	case 1:
1813*e4b17023SJohn Marino 	  *value = true;
1814*e4b17023SJohn Marino 	  break;
1815*e4b17023SJohn Marino 	default:
1816*e4b17023SJohn Marino 	  return false;
1817*e4b17023SJohn Marino 	}
1818*e4b17023SJohn Marino       return true;
1819*e4b17023SJohn Marino 
1820*e4b17023SJohn Marino     default:
1821*e4b17023SJohn Marino       return false;
1822*e4b17023SJohn Marino     }
1823*e4b17023SJohn Marino }
1824*e4b17023SJohn Marino 
1825*e4b17023SJohn Marino 
1826*e4b17023SJohn Marino /* Analyze a SIV (Single Index Variable) subscript where CHREC_A is a
1827*e4b17023SJohn Marino    constant, and CHREC_B is an affine function.  *OVERLAPS_A and
1828*e4b17023SJohn Marino    *OVERLAPS_B are initialized to the functions that describe the
1829*e4b17023SJohn Marino    relation between the elements accessed twice by CHREC_A and
1830*e4b17023SJohn Marino    CHREC_B.  For k >= 0, the following property is verified:
1831*e4b17023SJohn Marino 
1832*e4b17023SJohn Marino    CHREC_A (*OVERLAPS_A (k)) = CHREC_B (*OVERLAPS_B (k)).  */
1833*e4b17023SJohn Marino 
1834*e4b17023SJohn Marino static void
analyze_siv_subscript_cst_affine(tree chrec_a,tree chrec_b,conflict_function ** overlaps_a,conflict_function ** overlaps_b,tree * last_conflicts)1835*e4b17023SJohn Marino analyze_siv_subscript_cst_affine (tree chrec_a,
1836*e4b17023SJohn Marino 				  tree chrec_b,
1837*e4b17023SJohn Marino 				  conflict_function **overlaps_a,
1838*e4b17023SJohn Marino 				  conflict_function **overlaps_b,
1839*e4b17023SJohn Marino 				  tree *last_conflicts)
1840*e4b17023SJohn Marino {
1841*e4b17023SJohn Marino   bool value0, value1, value2;
1842*e4b17023SJohn Marino   tree type, difference, tmp;
1843*e4b17023SJohn Marino 
1844*e4b17023SJohn Marino   type = signed_type_for_types (TREE_TYPE (chrec_a), TREE_TYPE (chrec_b));
1845*e4b17023SJohn Marino   chrec_a = chrec_convert (type, chrec_a, NULL);
1846*e4b17023SJohn Marino   chrec_b = chrec_convert (type, chrec_b, NULL);
1847*e4b17023SJohn Marino   difference = chrec_fold_minus (type, initial_condition (chrec_b), chrec_a);
1848*e4b17023SJohn Marino 
1849*e4b17023SJohn Marino   /* Special case overlap in the first iteration.  */
1850*e4b17023SJohn Marino   if (integer_zerop (difference))
1851*e4b17023SJohn Marino     {
1852*e4b17023SJohn Marino       *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
1853*e4b17023SJohn Marino       *overlaps_b = conflict_fn (1, affine_fn_cst (integer_zero_node));
1854*e4b17023SJohn Marino       *last_conflicts = integer_one_node;
1855*e4b17023SJohn Marino       return;
1856*e4b17023SJohn Marino     }
1857*e4b17023SJohn Marino 
1858*e4b17023SJohn Marino   if (!chrec_is_positive (initial_condition (difference), &value0))
1859*e4b17023SJohn Marino     {
1860*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
1861*e4b17023SJohn Marino 	fprintf (dump_file, "siv test failed: chrec is not positive.\n");
1862*e4b17023SJohn Marino 
1863*e4b17023SJohn Marino       dependence_stats.num_siv_unimplemented++;
1864*e4b17023SJohn Marino       *overlaps_a = conflict_fn_not_known ();
1865*e4b17023SJohn Marino       *overlaps_b = conflict_fn_not_known ();
1866*e4b17023SJohn Marino       *last_conflicts = chrec_dont_know;
1867*e4b17023SJohn Marino       return;
1868*e4b17023SJohn Marino     }
1869*e4b17023SJohn Marino   else
1870*e4b17023SJohn Marino     {
1871*e4b17023SJohn Marino       if (value0 == false)
1872*e4b17023SJohn Marino 	{
1873*e4b17023SJohn Marino 	  if (!chrec_is_positive (CHREC_RIGHT (chrec_b), &value1))
1874*e4b17023SJohn Marino 	    {
1875*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
1876*e4b17023SJohn Marino 		fprintf (dump_file, "siv test failed: chrec not positive.\n");
1877*e4b17023SJohn Marino 
1878*e4b17023SJohn Marino 	      *overlaps_a = conflict_fn_not_known ();
1879*e4b17023SJohn Marino 	      *overlaps_b = conflict_fn_not_known ();
1880*e4b17023SJohn Marino 	      *last_conflicts = chrec_dont_know;
1881*e4b17023SJohn Marino 	      dependence_stats.num_siv_unimplemented++;
1882*e4b17023SJohn Marino 	      return;
1883*e4b17023SJohn Marino 	    }
1884*e4b17023SJohn Marino 	  else
1885*e4b17023SJohn Marino 	    {
1886*e4b17023SJohn Marino 	      if (value1 == true)
1887*e4b17023SJohn Marino 		{
1888*e4b17023SJohn Marino 		  /* Example:
1889*e4b17023SJohn Marino 		     chrec_a = 12
1890*e4b17023SJohn Marino 		     chrec_b = {10, +, 1}
1891*e4b17023SJohn Marino 		  */
1892*e4b17023SJohn Marino 
1893*e4b17023SJohn Marino 		  if (tree_fold_divides_p (CHREC_RIGHT (chrec_b), difference))
1894*e4b17023SJohn Marino 		    {
1895*e4b17023SJohn Marino 		      HOST_WIDE_INT numiter;
1896*e4b17023SJohn Marino 		      struct loop *loop = get_chrec_loop (chrec_b);
1897*e4b17023SJohn Marino 
1898*e4b17023SJohn Marino 		      *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
1899*e4b17023SJohn Marino 		      tmp = fold_build2 (EXACT_DIV_EXPR, type,
1900*e4b17023SJohn Marino 					 fold_build1 (ABS_EXPR, type, difference),
1901*e4b17023SJohn Marino 					 CHREC_RIGHT (chrec_b));
1902*e4b17023SJohn Marino 		      *overlaps_b = conflict_fn (1, affine_fn_cst (tmp));
1903*e4b17023SJohn Marino 		      *last_conflicts = integer_one_node;
1904*e4b17023SJohn Marino 
1905*e4b17023SJohn Marino 
1906*e4b17023SJohn Marino 		      /* Perform weak-zero siv test to see if overlap is
1907*e4b17023SJohn Marino 			 outside the loop bounds.  */
1908*e4b17023SJohn Marino 		      numiter = max_stmt_executions_int (loop, true);
1909*e4b17023SJohn Marino 
1910*e4b17023SJohn Marino 		      if (numiter >= 0
1911*e4b17023SJohn Marino 			  && compare_tree_int (tmp, numiter) > 0)
1912*e4b17023SJohn Marino 			{
1913*e4b17023SJohn Marino 			  free_conflict_function (*overlaps_a);
1914*e4b17023SJohn Marino 			  free_conflict_function (*overlaps_b);
1915*e4b17023SJohn Marino 			  *overlaps_a = conflict_fn_no_dependence ();
1916*e4b17023SJohn Marino 			  *overlaps_b = conflict_fn_no_dependence ();
1917*e4b17023SJohn Marino 			  *last_conflicts = integer_zero_node;
1918*e4b17023SJohn Marino 			  dependence_stats.num_siv_independent++;
1919*e4b17023SJohn Marino 			  return;
1920*e4b17023SJohn Marino 			}
1921*e4b17023SJohn Marino 		      dependence_stats.num_siv_dependent++;
1922*e4b17023SJohn Marino 		      return;
1923*e4b17023SJohn Marino 		    }
1924*e4b17023SJohn Marino 
1925*e4b17023SJohn Marino 		  /* When the step does not divide the difference, there are
1926*e4b17023SJohn Marino 		     no overlaps.  */
1927*e4b17023SJohn Marino 		  else
1928*e4b17023SJohn Marino 		    {
1929*e4b17023SJohn Marino 		      *overlaps_a = conflict_fn_no_dependence ();
1930*e4b17023SJohn Marino 		      *overlaps_b = conflict_fn_no_dependence ();
1931*e4b17023SJohn Marino 		      *last_conflicts = integer_zero_node;
1932*e4b17023SJohn Marino 		      dependence_stats.num_siv_independent++;
1933*e4b17023SJohn Marino 		      return;
1934*e4b17023SJohn Marino 		    }
1935*e4b17023SJohn Marino 		}
1936*e4b17023SJohn Marino 
1937*e4b17023SJohn Marino 	      else
1938*e4b17023SJohn Marino 		{
1939*e4b17023SJohn Marino 		  /* Example:
1940*e4b17023SJohn Marino 		     chrec_a = 12
1941*e4b17023SJohn Marino 		     chrec_b = {10, +, -1}
1942*e4b17023SJohn Marino 
1943*e4b17023SJohn Marino 		     In this case, chrec_a will not overlap with chrec_b.  */
1944*e4b17023SJohn Marino 		  *overlaps_a = conflict_fn_no_dependence ();
1945*e4b17023SJohn Marino 		  *overlaps_b = conflict_fn_no_dependence ();
1946*e4b17023SJohn Marino 		  *last_conflicts = integer_zero_node;
1947*e4b17023SJohn Marino 		  dependence_stats.num_siv_independent++;
1948*e4b17023SJohn Marino 		  return;
1949*e4b17023SJohn Marino 		}
1950*e4b17023SJohn Marino 	    }
1951*e4b17023SJohn Marino 	}
1952*e4b17023SJohn Marino       else
1953*e4b17023SJohn Marino 	{
1954*e4b17023SJohn Marino 	  if (!chrec_is_positive (CHREC_RIGHT (chrec_b), &value2))
1955*e4b17023SJohn Marino 	    {
1956*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
1957*e4b17023SJohn Marino 		fprintf (dump_file, "siv test failed: chrec not positive.\n");
1958*e4b17023SJohn Marino 
1959*e4b17023SJohn Marino 	      *overlaps_a = conflict_fn_not_known ();
1960*e4b17023SJohn Marino 	      *overlaps_b = conflict_fn_not_known ();
1961*e4b17023SJohn Marino 	      *last_conflicts = chrec_dont_know;
1962*e4b17023SJohn Marino 	      dependence_stats.num_siv_unimplemented++;
1963*e4b17023SJohn Marino 	      return;
1964*e4b17023SJohn Marino 	    }
1965*e4b17023SJohn Marino 	  else
1966*e4b17023SJohn Marino 	    {
1967*e4b17023SJohn Marino 	      if (value2 == false)
1968*e4b17023SJohn Marino 		{
1969*e4b17023SJohn Marino 		  /* Example:
1970*e4b17023SJohn Marino 		     chrec_a = 3
1971*e4b17023SJohn Marino 		     chrec_b = {10, +, -1}
1972*e4b17023SJohn Marino 		  */
1973*e4b17023SJohn Marino 		  if (tree_fold_divides_p (CHREC_RIGHT (chrec_b), difference))
1974*e4b17023SJohn Marino 		    {
1975*e4b17023SJohn Marino 		      HOST_WIDE_INT numiter;
1976*e4b17023SJohn Marino 		      struct loop *loop = get_chrec_loop (chrec_b);
1977*e4b17023SJohn Marino 
1978*e4b17023SJohn Marino 		      *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
1979*e4b17023SJohn Marino 		      tmp = fold_build2 (EXACT_DIV_EXPR, type, difference,
1980*e4b17023SJohn Marino 					 CHREC_RIGHT (chrec_b));
1981*e4b17023SJohn Marino 		      *overlaps_b = conflict_fn (1, affine_fn_cst (tmp));
1982*e4b17023SJohn Marino 		      *last_conflicts = integer_one_node;
1983*e4b17023SJohn Marino 
1984*e4b17023SJohn Marino 		      /* Perform weak-zero siv test to see if overlap is
1985*e4b17023SJohn Marino 			 outside the loop bounds.  */
1986*e4b17023SJohn Marino 		      numiter = max_stmt_executions_int (loop, true);
1987*e4b17023SJohn Marino 
1988*e4b17023SJohn Marino 		      if (numiter >= 0
1989*e4b17023SJohn Marino 			  && compare_tree_int (tmp, numiter) > 0)
1990*e4b17023SJohn Marino 			{
1991*e4b17023SJohn Marino 			  free_conflict_function (*overlaps_a);
1992*e4b17023SJohn Marino 			  free_conflict_function (*overlaps_b);
1993*e4b17023SJohn Marino 			  *overlaps_a = conflict_fn_no_dependence ();
1994*e4b17023SJohn Marino 			  *overlaps_b = conflict_fn_no_dependence ();
1995*e4b17023SJohn Marino 			  *last_conflicts = integer_zero_node;
1996*e4b17023SJohn Marino 			  dependence_stats.num_siv_independent++;
1997*e4b17023SJohn Marino 			  return;
1998*e4b17023SJohn Marino 			}
1999*e4b17023SJohn Marino 		      dependence_stats.num_siv_dependent++;
2000*e4b17023SJohn Marino 		      return;
2001*e4b17023SJohn Marino 		    }
2002*e4b17023SJohn Marino 
2003*e4b17023SJohn Marino 		  /* When the step does not divide the difference, there
2004*e4b17023SJohn Marino 		     are no overlaps.  */
2005*e4b17023SJohn Marino 		  else
2006*e4b17023SJohn Marino 		    {
2007*e4b17023SJohn Marino 		      *overlaps_a = conflict_fn_no_dependence ();
2008*e4b17023SJohn Marino 		      *overlaps_b = conflict_fn_no_dependence ();
2009*e4b17023SJohn Marino 		      *last_conflicts = integer_zero_node;
2010*e4b17023SJohn Marino 		      dependence_stats.num_siv_independent++;
2011*e4b17023SJohn Marino 		      return;
2012*e4b17023SJohn Marino 		    }
2013*e4b17023SJohn Marino 		}
2014*e4b17023SJohn Marino 	      else
2015*e4b17023SJohn Marino 		{
2016*e4b17023SJohn Marino 		  /* Example:
2017*e4b17023SJohn Marino 		     chrec_a = 3
2018*e4b17023SJohn Marino 		     chrec_b = {4, +, 1}
2019*e4b17023SJohn Marino 
2020*e4b17023SJohn Marino 		     In this case, chrec_a will not overlap with chrec_b.  */
2021*e4b17023SJohn Marino 		  *overlaps_a = conflict_fn_no_dependence ();
2022*e4b17023SJohn Marino 		  *overlaps_b = conflict_fn_no_dependence ();
2023*e4b17023SJohn Marino 		  *last_conflicts = integer_zero_node;
2024*e4b17023SJohn Marino 		  dependence_stats.num_siv_independent++;
2025*e4b17023SJohn Marino 		  return;
2026*e4b17023SJohn Marino 		}
2027*e4b17023SJohn Marino 	    }
2028*e4b17023SJohn Marino 	}
2029*e4b17023SJohn Marino     }
2030*e4b17023SJohn Marino }
2031*e4b17023SJohn Marino 
2032*e4b17023SJohn Marino /* Helper recursive function for initializing the matrix A.  Returns
2033*e4b17023SJohn Marino    the initial value of CHREC.  */
2034*e4b17023SJohn Marino 
2035*e4b17023SJohn Marino static tree
initialize_matrix_A(lambda_matrix A,tree chrec,unsigned index,int mult)2036*e4b17023SJohn Marino initialize_matrix_A (lambda_matrix A, tree chrec, unsigned index, int mult)
2037*e4b17023SJohn Marino {
2038*e4b17023SJohn Marino   gcc_assert (chrec);
2039*e4b17023SJohn Marino 
2040*e4b17023SJohn Marino   switch (TREE_CODE (chrec))
2041*e4b17023SJohn Marino     {
2042*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
2043*e4b17023SJohn Marino       gcc_assert (TREE_CODE (CHREC_RIGHT (chrec)) == INTEGER_CST);
2044*e4b17023SJohn Marino 
2045*e4b17023SJohn Marino       A[index][0] = mult * int_cst_value (CHREC_RIGHT (chrec));
2046*e4b17023SJohn Marino       return initialize_matrix_A (A, CHREC_LEFT (chrec), index + 1, mult);
2047*e4b17023SJohn Marino 
2048*e4b17023SJohn Marino     case PLUS_EXPR:
2049*e4b17023SJohn Marino     case MULT_EXPR:
2050*e4b17023SJohn Marino     case MINUS_EXPR:
2051*e4b17023SJohn Marino       {
2052*e4b17023SJohn Marino 	tree op0 = initialize_matrix_A (A, TREE_OPERAND (chrec, 0), index, mult);
2053*e4b17023SJohn Marino 	tree op1 = initialize_matrix_A (A, TREE_OPERAND (chrec, 1), index, mult);
2054*e4b17023SJohn Marino 
2055*e4b17023SJohn Marino 	return chrec_fold_op (TREE_CODE (chrec), chrec_type (chrec), op0, op1);
2056*e4b17023SJohn Marino       }
2057*e4b17023SJohn Marino 
2058*e4b17023SJohn Marino     case NOP_EXPR:
2059*e4b17023SJohn Marino       {
2060*e4b17023SJohn Marino 	tree op = initialize_matrix_A (A, TREE_OPERAND (chrec, 0), index, mult);
2061*e4b17023SJohn Marino 	return chrec_convert (chrec_type (chrec), op, NULL);
2062*e4b17023SJohn Marino       }
2063*e4b17023SJohn Marino 
2064*e4b17023SJohn Marino     case BIT_NOT_EXPR:
2065*e4b17023SJohn Marino       {
2066*e4b17023SJohn Marino 	/* Handle ~X as -1 - X.  */
2067*e4b17023SJohn Marino 	tree op = initialize_matrix_A (A, TREE_OPERAND (chrec, 0), index, mult);
2068*e4b17023SJohn Marino 	return chrec_fold_op (MINUS_EXPR, chrec_type (chrec),
2069*e4b17023SJohn Marino 			      build_int_cst (TREE_TYPE (chrec), -1), op);
2070*e4b17023SJohn Marino       }
2071*e4b17023SJohn Marino 
2072*e4b17023SJohn Marino     case INTEGER_CST:
2073*e4b17023SJohn Marino       return chrec;
2074*e4b17023SJohn Marino 
2075*e4b17023SJohn Marino     default:
2076*e4b17023SJohn Marino       gcc_unreachable ();
2077*e4b17023SJohn Marino       return NULL_TREE;
2078*e4b17023SJohn Marino     }
2079*e4b17023SJohn Marino }
2080*e4b17023SJohn Marino 
2081*e4b17023SJohn Marino #define FLOOR_DIV(x,y) ((x) / (y))
2082*e4b17023SJohn Marino 
2083*e4b17023SJohn Marino /* Solves the special case of the Diophantine equation:
2084*e4b17023SJohn Marino    | {0, +, STEP_A}_x (OVERLAPS_A) = {0, +, STEP_B}_y (OVERLAPS_B)
2085*e4b17023SJohn Marino 
2086*e4b17023SJohn Marino    Computes the descriptions OVERLAPS_A and OVERLAPS_B.  NITER is the
2087*e4b17023SJohn Marino    number of iterations that loops X and Y run.  The overlaps will be
2088*e4b17023SJohn Marino    constructed as evolutions in dimension DIM.  */
2089*e4b17023SJohn Marino 
2090*e4b17023SJohn Marino static void
compute_overlap_steps_for_affine_univar(int niter,int step_a,int step_b,affine_fn * overlaps_a,affine_fn * overlaps_b,tree * last_conflicts,int dim)2091*e4b17023SJohn Marino compute_overlap_steps_for_affine_univar (int niter, int step_a, int step_b,
2092*e4b17023SJohn Marino 					 affine_fn *overlaps_a,
2093*e4b17023SJohn Marino 					 affine_fn *overlaps_b,
2094*e4b17023SJohn Marino 					 tree *last_conflicts, int dim)
2095*e4b17023SJohn Marino {
2096*e4b17023SJohn Marino   if (((step_a > 0 && step_b > 0)
2097*e4b17023SJohn Marino        || (step_a < 0 && step_b < 0)))
2098*e4b17023SJohn Marino     {
2099*e4b17023SJohn Marino       int step_overlaps_a, step_overlaps_b;
2100*e4b17023SJohn Marino       int gcd_steps_a_b, last_conflict, tau2;
2101*e4b17023SJohn Marino 
2102*e4b17023SJohn Marino       gcd_steps_a_b = gcd (step_a, step_b);
2103*e4b17023SJohn Marino       step_overlaps_a = step_b / gcd_steps_a_b;
2104*e4b17023SJohn Marino       step_overlaps_b = step_a / gcd_steps_a_b;
2105*e4b17023SJohn Marino 
2106*e4b17023SJohn Marino       if (niter > 0)
2107*e4b17023SJohn Marino 	{
2108*e4b17023SJohn Marino 	  tau2 = FLOOR_DIV (niter, step_overlaps_a);
2109*e4b17023SJohn Marino 	  tau2 = MIN (tau2, FLOOR_DIV (niter, step_overlaps_b));
2110*e4b17023SJohn Marino 	  last_conflict = tau2;
2111*e4b17023SJohn Marino 	  *last_conflicts = build_int_cst (NULL_TREE, last_conflict);
2112*e4b17023SJohn Marino 	}
2113*e4b17023SJohn Marino       else
2114*e4b17023SJohn Marino 	*last_conflicts = chrec_dont_know;
2115*e4b17023SJohn Marino 
2116*e4b17023SJohn Marino       *overlaps_a = affine_fn_univar (integer_zero_node, dim,
2117*e4b17023SJohn Marino 				      build_int_cst (NULL_TREE,
2118*e4b17023SJohn Marino 						     step_overlaps_a));
2119*e4b17023SJohn Marino       *overlaps_b = affine_fn_univar (integer_zero_node, dim,
2120*e4b17023SJohn Marino 				      build_int_cst (NULL_TREE,
2121*e4b17023SJohn Marino 						     step_overlaps_b));
2122*e4b17023SJohn Marino     }
2123*e4b17023SJohn Marino 
2124*e4b17023SJohn Marino   else
2125*e4b17023SJohn Marino     {
2126*e4b17023SJohn Marino       *overlaps_a = affine_fn_cst (integer_zero_node);
2127*e4b17023SJohn Marino       *overlaps_b = affine_fn_cst (integer_zero_node);
2128*e4b17023SJohn Marino       *last_conflicts = integer_zero_node;
2129*e4b17023SJohn Marino     }
2130*e4b17023SJohn Marino }
2131*e4b17023SJohn Marino 
2132*e4b17023SJohn Marino /* Solves the special case of a Diophantine equation where CHREC_A is
2133*e4b17023SJohn Marino    an affine bivariate function, and CHREC_B is an affine univariate
2134*e4b17023SJohn Marino    function.  For example,
2135*e4b17023SJohn Marino 
2136*e4b17023SJohn Marino    | {{0, +, 1}_x, +, 1335}_y = {0, +, 1336}_z
2137*e4b17023SJohn Marino 
2138*e4b17023SJohn Marino    has the following overlapping functions:
2139*e4b17023SJohn Marino 
2140*e4b17023SJohn Marino    | x (t, u, v) = {{0, +, 1336}_t, +, 1}_v
2141*e4b17023SJohn Marino    | y (t, u, v) = {{0, +, 1336}_u, +, 1}_v
2142*e4b17023SJohn Marino    | z (t, u, v) = {{{0, +, 1}_t, +, 1335}_u, +, 1}_v
2143*e4b17023SJohn Marino 
2144*e4b17023SJohn Marino    FORNOW: This is a specialized implementation for a case occurring in
2145*e4b17023SJohn Marino    a common benchmark.  Implement the general algorithm.  */
2146*e4b17023SJohn Marino 
2147*e4b17023SJohn Marino static void
compute_overlap_steps_for_affine_1_2(tree chrec_a,tree chrec_b,conflict_function ** overlaps_a,conflict_function ** overlaps_b,tree * last_conflicts)2148*e4b17023SJohn Marino compute_overlap_steps_for_affine_1_2 (tree chrec_a, tree chrec_b,
2149*e4b17023SJohn Marino 				      conflict_function **overlaps_a,
2150*e4b17023SJohn Marino 				      conflict_function **overlaps_b,
2151*e4b17023SJohn Marino 				      tree *last_conflicts)
2152*e4b17023SJohn Marino {
2153*e4b17023SJohn Marino   bool xz_p, yz_p, xyz_p;
2154*e4b17023SJohn Marino   int step_x, step_y, step_z;
2155*e4b17023SJohn Marino   HOST_WIDE_INT niter_x, niter_y, niter_z, niter;
2156*e4b17023SJohn Marino   affine_fn overlaps_a_xz, overlaps_b_xz;
2157*e4b17023SJohn Marino   affine_fn overlaps_a_yz, overlaps_b_yz;
2158*e4b17023SJohn Marino   affine_fn overlaps_a_xyz, overlaps_b_xyz;
2159*e4b17023SJohn Marino   affine_fn ova1, ova2, ovb;
2160*e4b17023SJohn Marino   tree last_conflicts_xz, last_conflicts_yz, last_conflicts_xyz;
2161*e4b17023SJohn Marino 
2162*e4b17023SJohn Marino   step_x = int_cst_value (CHREC_RIGHT (CHREC_LEFT (chrec_a)));
2163*e4b17023SJohn Marino   step_y = int_cst_value (CHREC_RIGHT (chrec_a));
2164*e4b17023SJohn Marino   step_z = int_cst_value (CHREC_RIGHT (chrec_b));
2165*e4b17023SJohn Marino 
2166*e4b17023SJohn Marino   niter_x =
2167*e4b17023SJohn Marino     max_stmt_executions_int (get_chrec_loop (CHREC_LEFT (chrec_a)), true);
2168*e4b17023SJohn Marino   niter_y = max_stmt_executions_int (get_chrec_loop (chrec_a), true);
2169*e4b17023SJohn Marino   niter_z = max_stmt_executions_int (get_chrec_loop (chrec_b), true);
2170*e4b17023SJohn Marino 
2171*e4b17023SJohn Marino   if (niter_x < 0 || niter_y < 0 || niter_z < 0)
2172*e4b17023SJohn Marino     {
2173*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2174*e4b17023SJohn Marino 	fprintf (dump_file, "overlap steps test failed: no iteration counts.\n");
2175*e4b17023SJohn Marino 
2176*e4b17023SJohn Marino       *overlaps_a = conflict_fn_not_known ();
2177*e4b17023SJohn Marino       *overlaps_b = conflict_fn_not_known ();
2178*e4b17023SJohn Marino       *last_conflicts = chrec_dont_know;
2179*e4b17023SJohn Marino       return;
2180*e4b17023SJohn Marino     }
2181*e4b17023SJohn Marino 
2182*e4b17023SJohn Marino   niter = MIN (niter_x, niter_z);
2183*e4b17023SJohn Marino   compute_overlap_steps_for_affine_univar (niter, step_x, step_z,
2184*e4b17023SJohn Marino 					   &overlaps_a_xz,
2185*e4b17023SJohn Marino 					   &overlaps_b_xz,
2186*e4b17023SJohn Marino 					   &last_conflicts_xz, 1);
2187*e4b17023SJohn Marino   niter = MIN (niter_y, niter_z);
2188*e4b17023SJohn Marino   compute_overlap_steps_for_affine_univar (niter, step_y, step_z,
2189*e4b17023SJohn Marino 					   &overlaps_a_yz,
2190*e4b17023SJohn Marino 					   &overlaps_b_yz,
2191*e4b17023SJohn Marino 					   &last_conflicts_yz, 2);
2192*e4b17023SJohn Marino   niter = MIN (niter_x, niter_z);
2193*e4b17023SJohn Marino   niter = MIN (niter_y, niter);
2194*e4b17023SJohn Marino   compute_overlap_steps_for_affine_univar (niter, step_x + step_y, step_z,
2195*e4b17023SJohn Marino 					   &overlaps_a_xyz,
2196*e4b17023SJohn Marino 					   &overlaps_b_xyz,
2197*e4b17023SJohn Marino 					   &last_conflicts_xyz, 3);
2198*e4b17023SJohn Marino 
2199*e4b17023SJohn Marino   xz_p = !integer_zerop (last_conflicts_xz);
2200*e4b17023SJohn Marino   yz_p = !integer_zerop (last_conflicts_yz);
2201*e4b17023SJohn Marino   xyz_p = !integer_zerop (last_conflicts_xyz);
2202*e4b17023SJohn Marino 
2203*e4b17023SJohn Marino   if (xz_p || yz_p || xyz_p)
2204*e4b17023SJohn Marino     {
2205*e4b17023SJohn Marino       ova1 = affine_fn_cst (integer_zero_node);
2206*e4b17023SJohn Marino       ova2 = affine_fn_cst (integer_zero_node);
2207*e4b17023SJohn Marino       ovb = affine_fn_cst (integer_zero_node);
2208*e4b17023SJohn Marino       if (xz_p)
2209*e4b17023SJohn Marino 	{
2210*e4b17023SJohn Marino 	  affine_fn t0 = ova1;
2211*e4b17023SJohn Marino 	  affine_fn t2 = ovb;
2212*e4b17023SJohn Marino 
2213*e4b17023SJohn Marino 	  ova1 = affine_fn_plus (ova1, overlaps_a_xz);
2214*e4b17023SJohn Marino 	  ovb = affine_fn_plus (ovb, overlaps_b_xz);
2215*e4b17023SJohn Marino 	  affine_fn_free (t0);
2216*e4b17023SJohn Marino 	  affine_fn_free (t2);
2217*e4b17023SJohn Marino 	  *last_conflicts = last_conflicts_xz;
2218*e4b17023SJohn Marino 	}
2219*e4b17023SJohn Marino       if (yz_p)
2220*e4b17023SJohn Marino 	{
2221*e4b17023SJohn Marino 	  affine_fn t0 = ova2;
2222*e4b17023SJohn Marino 	  affine_fn t2 = ovb;
2223*e4b17023SJohn Marino 
2224*e4b17023SJohn Marino 	  ova2 = affine_fn_plus (ova2, overlaps_a_yz);
2225*e4b17023SJohn Marino 	  ovb = affine_fn_plus (ovb, overlaps_b_yz);
2226*e4b17023SJohn Marino 	  affine_fn_free (t0);
2227*e4b17023SJohn Marino 	  affine_fn_free (t2);
2228*e4b17023SJohn Marino 	  *last_conflicts = last_conflicts_yz;
2229*e4b17023SJohn Marino 	}
2230*e4b17023SJohn Marino       if (xyz_p)
2231*e4b17023SJohn Marino 	{
2232*e4b17023SJohn Marino 	  affine_fn t0 = ova1;
2233*e4b17023SJohn Marino 	  affine_fn t2 = ova2;
2234*e4b17023SJohn Marino 	  affine_fn t4 = ovb;
2235*e4b17023SJohn Marino 
2236*e4b17023SJohn Marino 	  ova1 = affine_fn_plus (ova1, overlaps_a_xyz);
2237*e4b17023SJohn Marino 	  ova2 = affine_fn_plus (ova2, overlaps_a_xyz);
2238*e4b17023SJohn Marino 	  ovb = affine_fn_plus (ovb, overlaps_b_xyz);
2239*e4b17023SJohn Marino 	  affine_fn_free (t0);
2240*e4b17023SJohn Marino 	  affine_fn_free (t2);
2241*e4b17023SJohn Marino 	  affine_fn_free (t4);
2242*e4b17023SJohn Marino 	  *last_conflicts = last_conflicts_xyz;
2243*e4b17023SJohn Marino 	}
2244*e4b17023SJohn Marino       *overlaps_a = conflict_fn (2, ova1, ova2);
2245*e4b17023SJohn Marino       *overlaps_b = conflict_fn (1, ovb);
2246*e4b17023SJohn Marino     }
2247*e4b17023SJohn Marino   else
2248*e4b17023SJohn Marino     {
2249*e4b17023SJohn Marino       *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
2250*e4b17023SJohn Marino       *overlaps_b = conflict_fn (1, affine_fn_cst (integer_zero_node));
2251*e4b17023SJohn Marino       *last_conflicts = integer_zero_node;
2252*e4b17023SJohn Marino     }
2253*e4b17023SJohn Marino 
2254*e4b17023SJohn Marino   affine_fn_free (overlaps_a_xz);
2255*e4b17023SJohn Marino   affine_fn_free (overlaps_b_xz);
2256*e4b17023SJohn Marino   affine_fn_free (overlaps_a_yz);
2257*e4b17023SJohn Marino   affine_fn_free (overlaps_b_yz);
2258*e4b17023SJohn Marino   affine_fn_free (overlaps_a_xyz);
2259*e4b17023SJohn Marino   affine_fn_free (overlaps_b_xyz);
2260*e4b17023SJohn Marino }
2261*e4b17023SJohn Marino 
2262*e4b17023SJohn Marino /* Copy the elements of vector VEC1 with length SIZE to VEC2.  */
2263*e4b17023SJohn Marino 
2264*e4b17023SJohn Marino static void
lambda_vector_copy(lambda_vector vec1,lambda_vector vec2,int size)2265*e4b17023SJohn Marino lambda_vector_copy (lambda_vector vec1, lambda_vector vec2,
2266*e4b17023SJohn Marino 		    int size)
2267*e4b17023SJohn Marino {
2268*e4b17023SJohn Marino   memcpy (vec2, vec1, size * sizeof (*vec1));
2269*e4b17023SJohn Marino }
2270*e4b17023SJohn Marino 
2271*e4b17023SJohn Marino /* Copy the elements of M x N matrix MAT1 to MAT2.  */
2272*e4b17023SJohn Marino 
2273*e4b17023SJohn Marino static void
lambda_matrix_copy(lambda_matrix mat1,lambda_matrix mat2,int m,int n)2274*e4b17023SJohn Marino lambda_matrix_copy (lambda_matrix mat1, lambda_matrix mat2,
2275*e4b17023SJohn Marino 		    int m, int n)
2276*e4b17023SJohn Marino {
2277*e4b17023SJohn Marino   int i;
2278*e4b17023SJohn Marino 
2279*e4b17023SJohn Marino   for (i = 0; i < m; i++)
2280*e4b17023SJohn Marino     lambda_vector_copy (mat1[i], mat2[i], n);
2281*e4b17023SJohn Marino }
2282*e4b17023SJohn Marino 
2283*e4b17023SJohn Marino /* Store the N x N identity matrix in MAT.  */
2284*e4b17023SJohn Marino 
2285*e4b17023SJohn Marino static void
lambda_matrix_id(lambda_matrix mat,int size)2286*e4b17023SJohn Marino lambda_matrix_id (lambda_matrix mat, int size)
2287*e4b17023SJohn Marino {
2288*e4b17023SJohn Marino   int i, j;
2289*e4b17023SJohn Marino 
2290*e4b17023SJohn Marino   for (i = 0; i < size; i++)
2291*e4b17023SJohn Marino     for (j = 0; j < size; j++)
2292*e4b17023SJohn Marino       mat[i][j] = (i == j) ? 1 : 0;
2293*e4b17023SJohn Marino }
2294*e4b17023SJohn Marino 
2295*e4b17023SJohn Marino /* Return the first nonzero element of vector VEC1 between START and N.
2296*e4b17023SJohn Marino    We must have START <= N.   Returns N if VEC1 is the zero vector.  */
2297*e4b17023SJohn Marino 
2298*e4b17023SJohn Marino static int
lambda_vector_first_nz(lambda_vector vec1,int n,int start)2299*e4b17023SJohn Marino lambda_vector_first_nz (lambda_vector vec1, int n, int start)
2300*e4b17023SJohn Marino {
2301*e4b17023SJohn Marino   int j = start;
2302*e4b17023SJohn Marino   while (j < n && vec1[j] == 0)
2303*e4b17023SJohn Marino     j++;
2304*e4b17023SJohn Marino   return j;
2305*e4b17023SJohn Marino }
2306*e4b17023SJohn Marino 
2307*e4b17023SJohn Marino /* Add a multiple of row R1 of matrix MAT with N columns to row R2:
2308*e4b17023SJohn Marino    R2 = R2 + CONST1 * R1.  */
2309*e4b17023SJohn Marino 
2310*e4b17023SJohn Marino static void
lambda_matrix_row_add(lambda_matrix mat,int n,int r1,int r2,int const1)2311*e4b17023SJohn Marino lambda_matrix_row_add (lambda_matrix mat, int n, int r1, int r2, int const1)
2312*e4b17023SJohn Marino {
2313*e4b17023SJohn Marino   int i;
2314*e4b17023SJohn Marino 
2315*e4b17023SJohn Marino   if (const1 == 0)
2316*e4b17023SJohn Marino     return;
2317*e4b17023SJohn Marino 
2318*e4b17023SJohn Marino   for (i = 0; i < n; i++)
2319*e4b17023SJohn Marino     mat[r2][i] += const1 * mat[r1][i];
2320*e4b17023SJohn Marino }
2321*e4b17023SJohn Marino 
2322*e4b17023SJohn Marino /* Swap rows R1 and R2 in matrix MAT.  */
2323*e4b17023SJohn Marino 
2324*e4b17023SJohn Marino static void
lambda_matrix_row_exchange(lambda_matrix mat,int r1,int r2)2325*e4b17023SJohn Marino lambda_matrix_row_exchange (lambda_matrix mat, int r1, int r2)
2326*e4b17023SJohn Marino {
2327*e4b17023SJohn Marino   lambda_vector row;
2328*e4b17023SJohn Marino 
2329*e4b17023SJohn Marino   row = mat[r1];
2330*e4b17023SJohn Marino   mat[r1] = mat[r2];
2331*e4b17023SJohn Marino   mat[r2] = row;
2332*e4b17023SJohn Marino }
2333*e4b17023SJohn Marino 
2334*e4b17023SJohn Marino /* Multiply vector VEC1 of length SIZE by a constant CONST1,
2335*e4b17023SJohn Marino    and store the result in VEC2.  */
2336*e4b17023SJohn Marino 
2337*e4b17023SJohn Marino static void
lambda_vector_mult_const(lambda_vector vec1,lambda_vector vec2,int size,int const1)2338*e4b17023SJohn Marino lambda_vector_mult_const (lambda_vector vec1, lambda_vector vec2,
2339*e4b17023SJohn Marino 			  int size, int const1)
2340*e4b17023SJohn Marino {
2341*e4b17023SJohn Marino   int i;
2342*e4b17023SJohn Marino 
2343*e4b17023SJohn Marino   if (const1 == 0)
2344*e4b17023SJohn Marino     lambda_vector_clear (vec2, size);
2345*e4b17023SJohn Marino   else
2346*e4b17023SJohn Marino     for (i = 0; i < size; i++)
2347*e4b17023SJohn Marino       vec2[i] = const1 * vec1[i];
2348*e4b17023SJohn Marino }
2349*e4b17023SJohn Marino 
2350*e4b17023SJohn Marino /* Negate vector VEC1 with length SIZE and store it in VEC2.  */
2351*e4b17023SJohn Marino 
2352*e4b17023SJohn Marino static void
lambda_vector_negate(lambda_vector vec1,lambda_vector vec2,int size)2353*e4b17023SJohn Marino lambda_vector_negate (lambda_vector vec1, lambda_vector vec2,
2354*e4b17023SJohn Marino 		      int size)
2355*e4b17023SJohn Marino {
2356*e4b17023SJohn Marino   lambda_vector_mult_const (vec1, vec2, size, -1);
2357*e4b17023SJohn Marino }
2358*e4b17023SJohn Marino 
2359*e4b17023SJohn Marino /* Negate row R1 of matrix MAT which has N columns.  */
2360*e4b17023SJohn Marino 
2361*e4b17023SJohn Marino static void
lambda_matrix_row_negate(lambda_matrix mat,int n,int r1)2362*e4b17023SJohn Marino lambda_matrix_row_negate (lambda_matrix mat, int n, int r1)
2363*e4b17023SJohn Marino {
2364*e4b17023SJohn Marino   lambda_vector_negate (mat[r1], mat[r1], n);
2365*e4b17023SJohn Marino }
2366*e4b17023SJohn Marino 
2367*e4b17023SJohn Marino /* Return true if two vectors are equal.  */
2368*e4b17023SJohn Marino 
2369*e4b17023SJohn Marino static bool
lambda_vector_equal(lambda_vector vec1,lambda_vector vec2,int size)2370*e4b17023SJohn Marino lambda_vector_equal (lambda_vector vec1, lambda_vector vec2, int size)
2371*e4b17023SJohn Marino {
2372*e4b17023SJohn Marino   int i;
2373*e4b17023SJohn Marino   for (i = 0; i < size; i++)
2374*e4b17023SJohn Marino     if (vec1[i] != vec2[i])
2375*e4b17023SJohn Marino       return false;
2376*e4b17023SJohn Marino   return true;
2377*e4b17023SJohn Marino }
2378*e4b17023SJohn Marino 
2379*e4b17023SJohn Marino /* Given an M x N integer matrix A, this function determines an M x
2380*e4b17023SJohn Marino    M unimodular matrix U, and an M x N echelon matrix S such that
2381*e4b17023SJohn Marino    "U.A = S".  This decomposition is also known as "right Hermite".
2382*e4b17023SJohn Marino 
2383*e4b17023SJohn Marino    Ref: Algorithm 2.1 page 33 in "Loop Transformations for
2384*e4b17023SJohn Marino    Restructuring Compilers" Utpal Banerjee.  */
2385*e4b17023SJohn Marino 
2386*e4b17023SJohn Marino static void
lambda_matrix_right_hermite(lambda_matrix A,int m,int n,lambda_matrix S,lambda_matrix U)2387*e4b17023SJohn Marino lambda_matrix_right_hermite (lambda_matrix A, int m, int n,
2388*e4b17023SJohn Marino 			     lambda_matrix S, lambda_matrix U)
2389*e4b17023SJohn Marino {
2390*e4b17023SJohn Marino   int i, j, i0 = 0;
2391*e4b17023SJohn Marino 
2392*e4b17023SJohn Marino   lambda_matrix_copy (A, S, m, n);
2393*e4b17023SJohn Marino   lambda_matrix_id (U, m);
2394*e4b17023SJohn Marino 
2395*e4b17023SJohn Marino   for (j = 0; j < n; j++)
2396*e4b17023SJohn Marino     {
2397*e4b17023SJohn Marino       if (lambda_vector_first_nz (S[j], m, i0) < m)
2398*e4b17023SJohn Marino 	{
2399*e4b17023SJohn Marino 	  ++i0;
2400*e4b17023SJohn Marino 	  for (i = m - 1; i >= i0; i--)
2401*e4b17023SJohn Marino 	    {
2402*e4b17023SJohn Marino 	      while (S[i][j] != 0)
2403*e4b17023SJohn Marino 		{
2404*e4b17023SJohn Marino 		  int sigma, factor, a, b;
2405*e4b17023SJohn Marino 
2406*e4b17023SJohn Marino 		  a = S[i-1][j];
2407*e4b17023SJohn Marino 		  b = S[i][j];
2408*e4b17023SJohn Marino 		  sigma = (a * b < 0) ? -1: 1;
2409*e4b17023SJohn Marino 		  a = abs (a);
2410*e4b17023SJohn Marino 		  b = abs (b);
2411*e4b17023SJohn Marino 		  factor = sigma * (a / b);
2412*e4b17023SJohn Marino 
2413*e4b17023SJohn Marino 		  lambda_matrix_row_add (S, n, i, i-1, -factor);
2414*e4b17023SJohn Marino 		  lambda_matrix_row_exchange (S, i, i-1);
2415*e4b17023SJohn Marino 
2416*e4b17023SJohn Marino 		  lambda_matrix_row_add (U, m, i, i-1, -factor);
2417*e4b17023SJohn Marino 		  lambda_matrix_row_exchange (U, i, i-1);
2418*e4b17023SJohn Marino 		}
2419*e4b17023SJohn Marino 	    }
2420*e4b17023SJohn Marino 	}
2421*e4b17023SJohn Marino     }
2422*e4b17023SJohn Marino }
2423*e4b17023SJohn Marino 
2424*e4b17023SJohn Marino /* Determines the overlapping elements due to accesses CHREC_A and
2425*e4b17023SJohn Marino    CHREC_B, that are affine functions.  This function cannot handle
2426*e4b17023SJohn Marino    symbolic evolution functions, ie. when initial conditions are
2427*e4b17023SJohn Marino    parameters, because it uses lambda matrices of integers.  */
2428*e4b17023SJohn Marino 
2429*e4b17023SJohn Marino static void
analyze_subscript_affine_affine(tree chrec_a,tree chrec_b,conflict_function ** overlaps_a,conflict_function ** overlaps_b,tree * last_conflicts)2430*e4b17023SJohn Marino analyze_subscript_affine_affine (tree chrec_a,
2431*e4b17023SJohn Marino 				 tree chrec_b,
2432*e4b17023SJohn Marino 				 conflict_function **overlaps_a,
2433*e4b17023SJohn Marino 				 conflict_function **overlaps_b,
2434*e4b17023SJohn Marino 				 tree *last_conflicts)
2435*e4b17023SJohn Marino {
2436*e4b17023SJohn Marino   unsigned nb_vars_a, nb_vars_b, dim;
2437*e4b17023SJohn Marino   HOST_WIDE_INT init_a, init_b, gamma, gcd_alpha_beta;
2438*e4b17023SJohn Marino   lambda_matrix A, U, S;
2439*e4b17023SJohn Marino   struct obstack scratch_obstack;
2440*e4b17023SJohn Marino 
2441*e4b17023SJohn Marino   if (eq_evolutions_p (chrec_a, chrec_b))
2442*e4b17023SJohn Marino     {
2443*e4b17023SJohn Marino       /* The accessed index overlaps for each iteration in the
2444*e4b17023SJohn Marino 	 loop.  */
2445*e4b17023SJohn Marino       *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
2446*e4b17023SJohn Marino       *overlaps_b = conflict_fn (1, affine_fn_cst (integer_zero_node));
2447*e4b17023SJohn Marino       *last_conflicts = chrec_dont_know;
2448*e4b17023SJohn Marino       return;
2449*e4b17023SJohn Marino     }
2450*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2451*e4b17023SJohn Marino     fprintf (dump_file, "(analyze_subscript_affine_affine \n");
2452*e4b17023SJohn Marino 
2453*e4b17023SJohn Marino   /* For determining the initial intersection, we have to solve a
2454*e4b17023SJohn Marino      Diophantine equation.  This is the most time consuming part.
2455*e4b17023SJohn Marino 
2456*e4b17023SJohn Marino      For answering to the question: "Is there a dependence?" we have
2457*e4b17023SJohn Marino      to prove that there exists a solution to the Diophantine
2458*e4b17023SJohn Marino      equation, and that the solution is in the iteration domain,
2459*e4b17023SJohn Marino      i.e. the solution is positive or zero, and that the solution
2460*e4b17023SJohn Marino      happens before the upper bound loop.nb_iterations.  Otherwise
2461*e4b17023SJohn Marino      there is no dependence.  This function outputs a description of
2462*e4b17023SJohn Marino      the iterations that hold the intersections.  */
2463*e4b17023SJohn Marino 
2464*e4b17023SJohn Marino   nb_vars_a = nb_vars_in_chrec (chrec_a);
2465*e4b17023SJohn Marino   nb_vars_b = nb_vars_in_chrec (chrec_b);
2466*e4b17023SJohn Marino 
2467*e4b17023SJohn Marino   gcc_obstack_init (&scratch_obstack);
2468*e4b17023SJohn Marino 
2469*e4b17023SJohn Marino   dim = nb_vars_a + nb_vars_b;
2470*e4b17023SJohn Marino   U = lambda_matrix_new (dim, dim, &scratch_obstack);
2471*e4b17023SJohn Marino   A = lambda_matrix_new (dim, 1, &scratch_obstack);
2472*e4b17023SJohn Marino   S = lambda_matrix_new (dim, 1, &scratch_obstack);
2473*e4b17023SJohn Marino 
2474*e4b17023SJohn Marino   init_a = int_cst_value (initialize_matrix_A (A, chrec_a, 0, 1));
2475*e4b17023SJohn Marino   init_b = int_cst_value (initialize_matrix_A (A, chrec_b, nb_vars_a, -1));
2476*e4b17023SJohn Marino   gamma = init_b - init_a;
2477*e4b17023SJohn Marino 
2478*e4b17023SJohn Marino   /* Don't do all the hard work of solving the Diophantine equation
2479*e4b17023SJohn Marino      when we already know the solution: for example,
2480*e4b17023SJohn Marino      | {3, +, 1}_1
2481*e4b17023SJohn Marino      | {3, +, 4}_2
2482*e4b17023SJohn Marino      | gamma = 3 - 3 = 0.
2483*e4b17023SJohn Marino      Then the first overlap occurs during the first iterations:
2484*e4b17023SJohn Marino      | {3, +, 1}_1 ({0, +, 4}_x) = {3, +, 4}_2 ({0, +, 1}_x)
2485*e4b17023SJohn Marino   */
2486*e4b17023SJohn Marino   if (gamma == 0)
2487*e4b17023SJohn Marino     {
2488*e4b17023SJohn Marino       if (nb_vars_a == 1 && nb_vars_b == 1)
2489*e4b17023SJohn Marino 	{
2490*e4b17023SJohn Marino 	  HOST_WIDE_INT step_a, step_b;
2491*e4b17023SJohn Marino 	  HOST_WIDE_INT niter, niter_a, niter_b;
2492*e4b17023SJohn Marino 	  affine_fn ova, ovb;
2493*e4b17023SJohn Marino 
2494*e4b17023SJohn Marino 	  niter_a = max_stmt_executions_int (get_chrec_loop (chrec_a), true);
2495*e4b17023SJohn Marino 	  niter_b = max_stmt_executions_int (get_chrec_loop (chrec_b), true);
2496*e4b17023SJohn Marino 	  niter = MIN (niter_a, niter_b);
2497*e4b17023SJohn Marino 	  step_a = int_cst_value (CHREC_RIGHT (chrec_a));
2498*e4b17023SJohn Marino 	  step_b = int_cst_value (CHREC_RIGHT (chrec_b));
2499*e4b17023SJohn Marino 
2500*e4b17023SJohn Marino 	  compute_overlap_steps_for_affine_univar (niter, step_a, step_b,
2501*e4b17023SJohn Marino 						   &ova, &ovb,
2502*e4b17023SJohn Marino 						   last_conflicts, 1);
2503*e4b17023SJohn Marino 	  *overlaps_a = conflict_fn (1, ova);
2504*e4b17023SJohn Marino 	  *overlaps_b = conflict_fn (1, ovb);
2505*e4b17023SJohn Marino 	}
2506*e4b17023SJohn Marino 
2507*e4b17023SJohn Marino       else if (nb_vars_a == 2 && nb_vars_b == 1)
2508*e4b17023SJohn Marino 	compute_overlap_steps_for_affine_1_2
2509*e4b17023SJohn Marino 	  (chrec_a, chrec_b, overlaps_a, overlaps_b, last_conflicts);
2510*e4b17023SJohn Marino 
2511*e4b17023SJohn Marino       else if (nb_vars_a == 1 && nb_vars_b == 2)
2512*e4b17023SJohn Marino 	compute_overlap_steps_for_affine_1_2
2513*e4b17023SJohn Marino 	  (chrec_b, chrec_a, overlaps_b, overlaps_a, last_conflicts);
2514*e4b17023SJohn Marino 
2515*e4b17023SJohn Marino       else
2516*e4b17023SJohn Marino 	{
2517*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
2518*e4b17023SJohn Marino 	    fprintf (dump_file, "affine-affine test failed: too many variables.\n");
2519*e4b17023SJohn Marino 	  *overlaps_a = conflict_fn_not_known ();
2520*e4b17023SJohn Marino 	  *overlaps_b = conflict_fn_not_known ();
2521*e4b17023SJohn Marino 	  *last_conflicts = chrec_dont_know;
2522*e4b17023SJohn Marino 	}
2523*e4b17023SJohn Marino       goto end_analyze_subs_aa;
2524*e4b17023SJohn Marino     }
2525*e4b17023SJohn Marino 
2526*e4b17023SJohn Marino   /* U.A = S */
2527*e4b17023SJohn Marino   lambda_matrix_right_hermite (A, dim, 1, S, U);
2528*e4b17023SJohn Marino 
2529*e4b17023SJohn Marino   if (S[0][0] < 0)
2530*e4b17023SJohn Marino     {
2531*e4b17023SJohn Marino       S[0][0] *= -1;
2532*e4b17023SJohn Marino       lambda_matrix_row_negate (U, dim, 0);
2533*e4b17023SJohn Marino     }
2534*e4b17023SJohn Marino   gcd_alpha_beta = S[0][0];
2535*e4b17023SJohn Marino 
2536*e4b17023SJohn Marino   /* Something went wrong: for example in {1, +, 0}_5 vs. {0, +, 0}_5,
2537*e4b17023SJohn Marino      but that is a quite strange case.  Instead of ICEing, answer
2538*e4b17023SJohn Marino      don't know.  */
2539*e4b17023SJohn Marino   if (gcd_alpha_beta == 0)
2540*e4b17023SJohn Marino     {
2541*e4b17023SJohn Marino       *overlaps_a = conflict_fn_not_known ();
2542*e4b17023SJohn Marino       *overlaps_b = conflict_fn_not_known ();
2543*e4b17023SJohn Marino       *last_conflicts = chrec_dont_know;
2544*e4b17023SJohn Marino       goto end_analyze_subs_aa;
2545*e4b17023SJohn Marino     }
2546*e4b17023SJohn Marino 
2547*e4b17023SJohn Marino   /* The classic "gcd-test".  */
2548*e4b17023SJohn Marino   if (!int_divides_p (gcd_alpha_beta, gamma))
2549*e4b17023SJohn Marino     {
2550*e4b17023SJohn Marino       /* The "gcd-test" has determined that there is no integer
2551*e4b17023SJohn Marino 	 solution, i.e. there is no dependence.  */
2552*e4b17023SJohn Marino       *overlaps_a = conflict_fn_no_dependence ();
2553*e4b17023SJohn Marino       *overlaps_b = conflict_fn_no_dependence ();
2554*e4b17023SJohn Marino       *last_conflicts = integer_zero_node;
2555*e4b17023SJohn Marino     }
2556*e4b17023SJohn Marino 
2557*e4b17023SJohn Marino   /* Both access functions are univariate.  This includes SIV and MIV cases.  */
2558*e4b17023SJohn Marino   else if (nb_vars_a == 1 && nb_vars_b == 1)
2559*e4b17023SJohn Marino     {
2560*e4b17023SJohn Marino       /* Both functions should have the same evolution sign.  */
2561*e4b17023SJohn Marino       if (((A[0][0] > 0 && -A[1][0] > 0)
2562*e4b17023SJohn Marino 	   || (A[0][0] < 0 && -A[1][0] < 0)))
2563*e4b17023SJohn Marino 	{
2564*e4b17023SJohn Marino 	  /* The solutions are given by:
2565*e4b17023SJohn Marino 	     |
2566*e4b17023SJohn Marino 	     | [GAMMA/GCD_ALPHA_BETA  t].[u11 u12]  = [x0]
2567*e4b17023SJohn Marino 	     |                           [u21 u22]    [y0]
2568*e4b17023SJohn Marino 
2569*e4b17023SJohn Marino 	     For a given integer t.  Using the following variables,
2570*e4b17023SJohn Marino 
2571*e4b17023SJohn Marino 	     | i0 = u11 * gamma / gcd_alpha_beta
2572*e4b17023SJohn Marino 	     | j0 = u12 * gamma / gcd_alpha_beta
2573*e4b17023SJohn Marino 	     | i1 = u21
2574*e4b17023SJohn Marino 	     | j1 = u22
2575*e4b17023SJohn Marino 
2576*e4b17023SJohn Marino 	     the solutions are:
2577*e4b17023SJohn Marino 
2578*e4b17023SJohn Marino 	     | x0 = i0 + i1 * t,
2579*e4b17023SJohn Marino 	     | y0 = j0 + j1 * t.  */
2580*e4b17023SJohn Marino       	  HOST_WIDE_INT i0, j0, i1, j1;
2581*e4b17023SJohn Marino 
2582*e4b17023SJohn Marino 	  i0 = U[0][0] * gamma / gcd_alpha_beta;
2583*e4b17023SJohn Marino 	  j0 = U[0][1] * gamma / gcd_alpha_beta;
2584*e4b17023SJohn Marino 	  i1 = U[1][0];
2585*e4b17023SJohn Marino 	  j1 = U[1][1];
2586*e4b17023SJohn Marino 
2587*e4b17023SJohn Marino 	  if ((i1 == 0 && i0 < 0)
2588*e4b17023SJohn Marino 	      || (j1 == 0 && j0 < 0))
2589*e4b17023SJohn Marino 	    {
2590*e4b17023SJohn Marino 	      /* There is no solution.
2591*e4b17023SJohn Marino 		 FIXME: The case "i0 > nb_iterations, j0 > nb_iterations"
2592*e4b17023SJohn Marino 		 falls in here, but for the moment we don't look at the
2593*e4b17023SJohn Marino 		 upper bound of the iteration domain.  */
2594*e4b17023SJohn Marino 	      *overlaps_a = conflict_fn_no_dependence ();
2595*e4b17023SJohn Marino 	      *overlaps_b = conflict_fn_no_dependence ();
2596*e4b17023SJohn Marino 	      *last_conflicts = integer_zero_node;
2597*e4b17023SJohn Marino 	      goto end_analyze_subs_aa;
2598*e4b17023SJohn Marino 	    }
2599*e4b17023SJohn Marino 
2600*e4b17023SJohn Marino 	  if (i1 > 0 && j1 > 0)
2601*e4b17023SJohn Marino 	    {
2602*e4b17023SJohn Marino 	      HOST_WIDE_INT niter_a = max_stmt_executions_int
2603*e4b17023SJohn Marino 		(get_chrec_loop (chrec_a), true);
2604*e4b17023SJohn Marino 	      HOST_WIDE_INT niter_b = max_stmt_executions_int
2605*e4b17023SJohn Marino 		(get_chrec_loop (chrec_b), true);
2606*e4b17023SJohn Marino 	      HOST_WIDE_INT niter = MIN (niter_a, niter_b);
2607*e4b17023SJohn Marino 
2608*e4b17023SJohn Marino 	      /* (X0, Y0) is a solution of the Diophantine equation:
2609*e4b17023SJohn Marino 		 "chrec_a (X0) = chrec_b (Y0)".  */
2610*e4b17023SJohn Marino 	      HOST_WIDE_INT tau1 = MAX (CEIL (-i0, i1),
2611*e4b17023SJohn Marino 					CEIL (-j0, j1));
2612*e4b17023SJohn Marino 	      HOST_WIDE_INT x0 = i1 * tau1 + i0;
2613*e4b17023SJohn Marino 	      HOST_WIDE_INT y0 = j1 * tau1 + j0;
2614*e4b17023SJohn Marino 
2615*e4b17023SJohn Marino 	      /* (X1, Y1) is the smallest positive solution of the eq
2616*e4b17023SJohn Marino 		 "chrec_a (X1) = chrec_b (Y1)", i.e. this is where the
2617*e4b17023SJohn Marino 		 first conflict occurs.  */
2618*e4b17023SJohn Marino 	      HOST_WIDE_INT min_multiple = MIN (x0 / i1, y0 / j1);
2619*e4b17023SJohn Marino 	      HOST_WIDE_INT x1 = x0 - i1 * min_multiple;
2620*e4b17023SJohn Marino 	      HOST_WIDE_INT y1 = y0 - j1 * min_multiple;
2621*e4b17023SJohn Marino 
2622*e4b17023SJohn Marino 	      if (niter > 0)
2623*e4b17023SJohn Marino 		{
2624*e4b17023SJohn Marino 		  HOST_WIDE_INT tau2 = MIN (FLOOR_DIV (niter - i0, i1),
2625*e4b17023SJohn Marino 					    FLOOR_DIV (niter - j0, j1));
2626*e4b17023SJohn Marino 		  HOST_WIDE_INT last_conflict = tau2 - (x1 - i0)/i1;
2627*e4b17023SJohn Marino 
2628*e4b17023SJohn Marino 		  /* If the overlap occurs outside of the bounds of the
2629*e4b17023SJohn Marino 		     loop, there is no dependence.  */
2630*e4b17023SJohn Marino 		  if (x1 >= niter || y1 >= niter)
2631*e4b17023SJohn Marino 		    {
2632*e4b17023SJohn Marino 		      *overlaps_a = conflict_fn_no_dependence ();
2633*e4b17023SJohn Marino 		      *overlaps_b = conflict_fn_no_dependence ();
2634*e4b17023SJohn Marino 		      *last_conflicts = integer_zero_node;
2635*e4b17023SJohn Marino 		      goto end_analyze_subs_aa;
2636*e4b17023SJohn Marino 		    }
2637*e4b17023SJohn Marino 		  else
2638*e4b17023SJohn Marino 		    *last_conflicts = build_int_cst (NULL_TREE, last_conflict);
2639*e4b17023SJohn Marino 		}
2640*e4b17023SJohn Marino 	      else
2641*e4b17023SJohn Marino 		*last_conflicts = chrec_dont_know;
2642*e4b17023SJohn Marino 
2643*e4b17023SJohn Marino 	      *overlaps_a
2644*e4b17023SJohn Marino 		= conflict_fn (1,
2645*e4b17023SJohn Marino 			       affine_fn_univar (build_int_cst (NULL_TREE, x1),
2646*e4b17023SJohn Marino 						 1,
2647*e4b17023SJohn Marino 						 build_int_cst (NULL_TREE, i1)));
2648*e4b17023SJohn Marino 	      *overlaps_b
2649*e4b17023SJohn Marino 		= conflict_fn (1,
2650*e4b17023SJohn Marino 			       affine_fn_univar (build_int_cst (NULL_TREE, y1),
2651*e4b17023SJohn Marino 						 1,
2652*e4b17023SJohn Marino 						 build_int_cst (NULL_TREE, j1)));
2653*e4b17023SJohn Marino 	    }
2654*e4b17023SJohn Marino 	  else
2655*e4b17023SJohn Marino 	    {
2656*e4b17023SJohn Marino 	      /* FIXME: For the moment, the upper bound of the
2657*e4b17023SJohn Marino 		 iteration domain for i and j is not checked.  */
2658*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
2659*e4b17023SJohn Marino 		fprintf (dump_file, "affine-affine test failed: unimplemented.\n");
2660*e4b17023SJohn Marino 	      *overlaps_a = conflict_fn_not_known ();
2661*e4b17023SJohn Marino 	      *overlaps_b = conflict_fn_not_known ();
2662*e4b17023SJohn Marino 	      *last_conflicts = chrec_dont_know;
2663*e4b17023SJohn Marino 	    }
2664*e4b17023SJohn Marino 	}
2665*e4b17023SJohn Marino       else
2666*e4b17023SJohn Marino 	{
2667*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
2668*e4b17023SJohn Marino 	    fprintf (dump_file, "affine-affine test failed: unimplemented.\n");
2669*e4b17023SJohn Marino 	  *overlaps_a = conflict_fn_not_known ();
2670*e4b17023SJohn Marino 	  *overlaps_b = conflict_fn_not_known ();
2671*e4b17023SJohn Marino 	  *last_conflicts = chrec_dont_know;
2672*e4b17023SJohn Marino 	}
2673*e4b17023SJohn Marino     }
2674*e4b17023SJohn Marino   else
2675*e4b17023SJohn Marino     {
2676*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2677*e4b17023SJohn Marino 	fprintf (dump_file, "affine-affine test failed: unimplemented.\n");
2678*e4b17023SJohn Marino       *overlaps_a = conflict_fn_not_known ();
2679*e4b17023SJohn Marino       *overlaps_b = conflict_fn_not_known ();
2680*e4b17023SJohn Marino       *last_conflicts = chrec_dont_know;
2681*e4b17023SJohn Marino     }
2682*e4b17023SJohn Marino 
2683*e4b17023SJohn Marino end_analyze_subs_aa:
2684*e4b17023SJohn Marino   obstack_free (&scratch_obstack, NULL);
2685*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2686*e4b17023SJohn Marino     {
2687*e4b17023SJohn Marino       fprintf (dump_file, "  (overlaps_a = ");
2688*e4b17023SJohn Marino       dump_conflict_function (dump_file, *overlaps_a);
2689*e4b17023SJohn Marino       fprintf (dump_file, ")\n  (overlaps_b = ");
2690*e4b17023SJohn Marino       dump_conflict_function (dump_file, *overlaps_b);
2691*e4b17023SJohn Marino       fprintf (dump_file, ")\n");
2692*e4b17023SJohn Marino       fprintf (dump_file, ")\n");
2693*e4b17023SJohn Marino     }
2694*e4b17023SJohn Marino }
2695*e4b17023SJohn Marino 
2696*e4b17023SJohn Marino /* Returns true when analyze_subscript_affine_affine can be used for
2697*e4b17023SJohn Marino    determining the dependence relation between chrec_a and chrec_b,
2698*e4b17023SJohn Marino    that contain symbols.  This function modifies chrec_a and chrec_b
2699*e4b17023SJohn Marino    such that the analysis result is the same, and such that they don't
2700*e4b17023SJohn Marino    contain symbols, and then can safely be passed to the analyzer.
2701*e4b17023SJohn Marino 
2702*e4b17023SJohn Marino    Example: The analysis of the following tuples of evolutions produce
2703*e4b17023SJohn Marino    the same results: {x+1, +, 1}_1 vs. {x+3, +, 1}_1, and {-2, +, 1}_1
2704*e4b17023SJohn Marino    vs. {0, +, 1}_1
2705*e4b17023SJohn Marino 
2706*e4b17023SJohn Marino    {x+1, +, 1}_1 ({2, +, 1}_1) = {x+3, +, 1}_1 ({0, +, 1}_1)
2707*e4b17023SJohn Marino    {-2, +, 1}_1 ({2, +, 1}_1) = {0, +, 1}_1 ({0, +, 1}_1)
2708*e4b17023SJohn Marino */
2709*e4b17023SJohn Marino 
2710*e4b17023SJohn Marino static bool
can_use_analyze_subscript_affine_affine(tree * chrec_a,tree * chrec_b)2711*e4b17023SJohn Marino can_use_analyze_subscript_affine_affine (tree *chrec_a, tree *chrec_b)
2712*e4b17023SJohn Marino {
2713*e4b17023SJohn Marino   tree diff, type, left_a, left_b, right_b;
2714*e4b17023SJohn Marino 
2715*e4b17023SJohn Marino   if (chrec_contains_symbols (CHREC_RIGHT (*chrec_a))
2716*e4b17023SJohn Marino       || chrec_contains_symbols (CHREC_RIGHT (*chrec_b)))
2717*e4b17023SJohn Marino     /* FIXME: For the moment not handled.  Might be refined later.  */
2718*e4b17023SJohn Marino     return false;
2719*e4b17023SJohn Marino 
2720*e4b17023SJohn Marino   type = chrec_type (*chrec_a);
2721*e4b17023SJohn Marino   left_a = CHREC_LEFT (*chrec_a);
2722*e4b17023SJohn Marino   left_b = chrec_convert (type, CHREC_LEFT (*chrec_b), NULL);
2723*e4b17023SJohn Marino   diff = chrec_fold_minus (type, left_a, left_b);
2724*e4b17023SJohn Marino 
2725*e4b17023SJohn Marino   if (!evolution_function_is_constant_p (diff))
2726*e4b17023SJohn Marino     return false;
2727*e4b17023SJohn Marino 
2728*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2729*e4b17023SJohn Marino     fprintf (dump_file, "can_use_subscript_aff_aff_for_symbolic \n");
2730*e4b17023SJohn Marino 
2731*e4b17023SJohn Marino   *chrec_a = build_polynomial_chrec (CHREC_VARIABLE (*chrec_a),
2732*e4b17023SJohn Marino 				     diff, CHREC_RIGHT (*chrec_a));
2733*e4b17023SJohn Marino   right_b = chrec_convert (type, CHREC_RIGHT (*chrec_b), NULL);
2734*e4b17023SJohn Marino   *chrec_b = build_polynomial_chrec (CHREC_VARIABLE (*chrec_b),
2735*e4b17023SJohn Marino 				     build_int_cst (type, 0),
2736*e4b17023SJohn Marino 				     right_b);
2737*e4b17023SJohn Marino   return true;
2738*e4b17023SJohn Marino }
2739*e4b17023SJohn Marino 
2740*e4b17023SJohn Marino /* Analyze a SIV (Single Index Variable) subscript.  *OVERLAPS_A and
2741*e4b17023SJohn Marino    *OVERLAPS_B are initialized to the functions that describe the
2742*e4b17023SJohn Marino    relation between the elements accessed twice by CHREC_A and
2743*e4b17023SJohn Marino    CHREC_B.  For k >= 0, the following property is verified:
2744*e4b17023SJohn Marino 
2745*e4b17023SJohn Marino    CHREC_A (*OVERLAPS_A (k)) = CHREC_B (*OVERLAPS_B (k)).  */
2746*e4b17023SJohn Marino 
2747*e4b17023SJohn Marino static void
analyze_siv_subscript(tree chrec_a,tree chrec_b,conflict_function ** overlaps_a,conflict_function ** overlaps_b,tree * last_conflicts,int loop_nest_num)2748*e4b17023SJohn Marino analyze_siv_subscript (tree chrec_a,
2749*e4b17023SJohn Marino 		       tree chrec_b,
2750*e4b17023SJohn Marino 		       conflict_function **overlaps_a,
2751*e4b17023SJohn Marino 		       conflict_function **overlaps_b,
2752*e4b17023SJohn Marino 		       tree *last_conflicts,
2753*e4b17023SJohn Marino 		       int loop_nest_num)
2754*e4b17023SJohn Marino {
2755*e4b17023SJohn Marino   dependence_stats.num_siv++;
2756*e4b17023SJohn Marino 
2757*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2758*e4b17023SJohn Marino     fprintf (dump_file, "(analyze_siv_subscript \n");
2759*e4b17023SJohn Marino 
2760*e4b17023SJohn Marino   if (evolution_function_is_constant_p (chrec_a)
2761*e4b17023SJohn Marino       && evolution_function_is_affine_in_loop (chrec_b, loop_nest_num))
2762*e4b17023SJohn Marino     analyze_siv_subscript_cst_affine (chrec_a, chrec_b,
2763*e4b17023SJohn Marino 				      overlaps_a, overlaps_b, last_conflicts);
2764*e4b17023SJohn Marino 
2765*e4b17023SJohn Marino   else if (evolution_function_is_affine_in_loop (chrec_a, loop_nest_num)
2766*e4b17023SJohn Marino 	   && evolution_function_is_constant_p (chrec_b))
2767*e4b17023SJohn Marino     analyze_siv_subscript_cst_affine (chrec_b, chrec_a,
2768*e4b17023SJohn Marino 				      overlaps_b, overlaps_a, last_conflicts);
2769*e4b17023SJohn Marino 
2770*e4b17023SJohn Marino   else if (evolution_function_is_affine_in_loop (chrec_a, loop_nest_num)
2771*e4b17023SJohn Marino 	   && evolution_function_is_affine_in_loop (chrec_b, loop_nest_num))
2772*e4b17023SJohn Marino     {
2773*e4b17023SJohn Marino       if (!chrec_contains_symbols (chrec_a)
2774*e4b17023SJohn Marino 	  && !chrec_contains_symbols (chrec_b))
2775*e4b17023SJohn Marino 	{
2776*e4b17023SJohn Marino 	  analyze_subscript_affine_affine (chrec_a, chrec_b,
2777*e4b17023SJohn Marino 					   overlaps_a, overlaps_b,
2778*e4b17023SJohn Marino 					   last_conflicts);
2779*e4b17023SJohn Marino 
2780*e4b17023SJohn Marino 	  if (CF_NOT_KNOWN_P (*overlaps_a)
2781*e4b17023SJohn Marino 	      || CF_NOT_KNOWN_P (*overlaps_b))
2782*e4b17023SJohn Marino 	    dependence_stats.num_siv_unimplemented++;
2783*e4b17023SJohn Marino 	  else if (CF_NO_DEPENDENCE_P (*overlaps_a)
2784*e4b17023SJohn Marino 		   || CF_NO_DEPENDENCE_P (*overlaps_b))
2785*e4b17023SJohn Marino 	    dependence_stats.num_siv_independent++;
2786*e4b17023SJohn Marino 	  else
2787*e4b17023SJohn Marino 	    dependence_stats.num_siv_dependent++;
2788*e4b17023SJohn Marino 	}
2789*e4b17023SJohn Marino       else if (can_use_analyze_subscript_affine_affine (&chrec_a,
2790*e4b17023SJohn Marino 							&chrec_b))
2791*e4b17023SJohn Marino 	{
2792*e4b17023SJohn Marino 	  analyze_subscript_affine_affine (chrec_a, chrec_b,
2793*e4b17023SJohn Marino 					   overlaps_a, overlaps_b,
2794*e4b17023SJohn Marino 					   last_conflicts);
2795*e4b17023SJohn Marino 
2796*e4b17023SJohn Marino 	  if (CF_NOT_KNOWN_P (*overlaps_a)
2797*e4b17023SJohn Marino 	      || CF_NOT_KNOWN_P (*overlaps_b))
2798*e4b17023SJohn Marino 	    dependence_stats.num_siv_unimplemented++;
2799*e4b17023SJohn Marino 	  else if (CF_NO_DEPENDENCE_P (*overlaps_a)
2800*e4b17023SJohn Marino 		   || CF_NO_DEPENDENCE_P (*overlaps_b))
2801*e4b17023SJohn Marino 	    dependence_stats.num_siv_independent++;
2802*e4b17023SJohn Marino 	  else
2803*e4b17023SJohn Marino 	    dependence_stats.num_siv_dependent++;
2804*e4b17023SJohn Marino 	}
2805*e4b17023SJohn Marino       else
2806*e4b17023SJohn Marino 	goto siv_subscript_dontknow;
2807*e4b17023SJohn Marino     }
2808*e4b17023SJohn Marino 
2809*e4b17023SJohn Marino   else
2810*e4b17023SJohn Marino     {
2811*e4b17023SJohn Marino     siv_subscript_dontknow:;
2812*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2813*e4b17023SJohn Marino 	fprintf (dump_file, "siv test failed: unimplemented.\n");
2814*e4b17023SJohn Marino       *overlaps_a = conflict_fn_not_known ();
2815*e4b17023SJohn Marino       *overlaps_b = conflict_fn_not_known ();
2816*e4b17023SJohn Marino       *last_conflicts = chrec_dont_know;
2817*e4b17023SJohn Marino       dependence_stats.num_siv_unimplemented++;
2818*e4b17023SJohn Marino     }
2819*e4b17023SJohn Marino 
2820*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2821*e4b17023SJohn Marino     fprintf (dump_file, ")\n");
2822*e4b17023SJohn Marino }
2823*e4b17023SJohn Marino 
2824*e4b17023SJohn Marino /* Returns false if we can prove that the greatest common divisor of the steps
2825*e4b17023SJohn Marino    of CHREC does not divide CST, false otherwise.  */
2826*e4b17023SJohn Marino 
2827*e4b17023SJohn Marino static bool
gcd_of_steps_may_divide_p(const_tree chrec,const_tree cst)2828*e4b17023SJohn Marino gcd_of_steps_may_divide_p (const_tree chrec, const_tree cst)
2829*e4b17023SJohn Marino {
2830*e4b17023SJohn Marino   HOST_WIDE_INT cd = 0, val;
2831*e4b17023SJohn Marino   tree step;
2832*e4b17023SJohn Marino 
2833*e4b17023SJohn Marino   if (!host_integerp (cst, 0))
2834*e4b17023SJohn Marino     return true;
2835*e4b17023SJohn Marino   val = tree_low_cst (cst, 0);
2836*e4b17023SJohn Marino 
2837*e4b17023SJohn Marino   while (TREE_CODE (chrec) == POLYNOMIAL_CHREC)
2838*e4b17023SJohn Marino     {
2839*e4b17023SJohn Marino       step = CHREC_RIGHT (chrec);
2840*e4b17023SJohn Marino       if (!host_integerp (step, 0))
2841*e4b17023SJohn Marino 	return true;
2842*e4b17023SJohn Marino       cd = gcd (cd, tree_low_cst (step, 0));
2843*e4b17023SJohn Marino       chrec = CHREC_LEFT (chrec);
2844*e4b17023SJohn Marino     }
2845*e4b17023SJohn Marino 
2846*e4b17023SJohn Marino   return val % cd == 0;
2847*e4b17023SJohn Marino }
2848*e4b17023SJohn Marino 
2849*e4b17023SJohn Marino /* Analyze a MIV (Multiple Index Variable) subscript with respect to
2850*e4b17023SJohn Marino    LOOP_NEST.  *OVERLAPS_A and *OVERLAPS_B are initialized to the
2851*e4b17023SJohn Marino    functions that describe the relation between the elements accessed
2852*e4b17023SJohn Marino    twice by CHREC_A and CHREC_B.  For k >= 0, the following property
2853*e4b17023SJohn Marino    is verified:
2854*e4b17023SJohn Marino 
2855*e4b17023SJohn Marino    CHREC_A (*OVERLAPS_A (k)) = CHREC_B (*OVERLAPS_B (k)).  */
2856*e4b17023SJohn Marino 
2857*e4b17023SJohn Marino static void
analyze_miv_subscript(tree chrec_a,tree chrec_b,conflict_function ** overlaps_a,conflict_function ** overlaps_b,tree * last_conflicts,struct loop * loop_nest)2858*e4b17023SJohn Marino analyze_miv_subscript (tree chrec_a,
2859*e4b17023SJohn Marino 		       tree chrec_b,
2860*e4b17023SJohn Marino 		       conflict_function **overlaps_a,
2861*e4b17023SJohn Marino 		       conflict_function **overlaps_b,
2862*e4b17023SJohn Marino 		       tree *last_conflicts,
2863*e4b17023SJohn Marino 		       struct loop *loop_nest)
2864*e4b17023SJohn Marino {
2865*e4b17023SJohn Marino   tree type, difference;
2866*e4b17023SJohn Marino 
2867*e4b17023SJohn Marino   dependence_stats.num_miv++;
2868*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2869*e4b17023SJohn Marino     fprintf (dump_file, "(analyze_miv_subscript \n");
2870*e4b17023SJohn Marino 
2871*e4b17023SJohn Marino   type = signed_type_for_types (TREE_TYPE (chrec_a), TREE_TYPE (chrec_b));
2872*e4b17023SJohn Marino   chrec_a = chrec_convert (type, chrec_a, NULL);
2873*e4b17023SJohn Marino   chrec_b = chrec_convert (type, chrec_b, NULL);
2874*e4b17023SJohn Marino   difference = chrec_fold_minus (type, chrec_a, chrec_b);
2875*e4b17023SJohn Marino 
2876*e4b17023SJohn Marino   if (eq_evolutions_p (chrec_a, chrec_b))
2877*e4b17023SJohn Marino     {
2878*e4b17023SJohn Marino       /* Access functions are the same: all the elements are accessed
2879*e4b17023SJohn Marino 	 in the same order.  */
2880*e4b17023SJohn Marino       *overlaps_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
2881*e4b17023SJohn Marino       *overlaps_b = conflict_fn (1, affine_fn_cst (integer_zero_node));
2882*e4b17023SJohn Marino       *last_conflicts = max_stmt_executions_tree (get_chrec_loop (chrec_a));
2883*e4b17023SJohn Marino       dependence_stats.num_miv_dependent++;
2884*e4b17023SJohn Marino     }
2885*e4b17023SJohn Marino 
2886*e4b17023SJohn Marino   else if (evolution_function_is_constant_p (difference)
2887*e4b17023SJohn Marino 	   /* For the moment, the following is verified:
2888*e4b17023SJohn Marino 	      evolution_function_is_affine_multivariate_p (chrec_a,
2889*e4b17023SJohn Marino 	      loop_nest->num) */
2890*e4b17023SJohn Marino 	   && !gcd_of_steps_may_divide_p (chrec_a, difference))
2891*e4b17023SJohn Marino     {
2892*e4b17023SJohn Marino       /* testsuite/.../ssa-chrec-33.c
2893*e4b17023SJohn Marino 	 {{21, +, 2}_1, +, -2}_2  vs.  {{20, +, 2}_1, +, -2}_2
2894*e4b17023SJohn Marino 
2895*e4b17023SJohn Marino 	 The difference is 1, and all the evolution steps are multiples
2896*e4b17023SJohn Marino 	 of 2, consequently there are no overlapping elements.  */
2897*e4b17023SJohn Marino       *overlaps_a = conflict_fn_no_dependence ();
2898*e4b17023SJohn Marino       *overlaps_b = conflict_fn_no_dependence ();
2899*e4b17023SJohn Marino       *last_conflicts = integer_zero_node;
2900*e4b17023SJohn Marino       dependence_stats.num_miv_independent++;
2901*e4b17023SJohn Marino     }
2902*e4b17023SJohn Marino 
2903*e4b17023SJohn Marino   else if (evolution_function_is_affine_multivariate_p (chrec_a, loop_nest->num)
2904*e4b17023SJohn Marino 	   && !chrec_contains_symbols (chrec_a)
2905*e4b17023SJohn Marino 	   && evolution_function_is_affine_multivariate_p (chrec_b, loop_nest->num)
2906*e4b17023SJohn Marino 	   && !chrec_contains_symbols (chrec_b))
2907*e4b17023SJohn Marino     {
2908*e4b17023SJohn Marino       /* testsuite/.../ssa-chrec-35.c
2909*e4b17023SJohn Marino 	 {0, +, 1}_2  vs.  {0, +, 1}_3
2910*e4b17023SJohn Marino 	 the overlapping elements are respectively located at iterations:
2911*e4b17023SJohn Marino 	 {0, +, 1}_x and {0, +, 1}_x,
2912*e4b17023SJohn Marino 	 in other words, we have the equality:
2913*e4b17023SJohn Marino 	 {0, +, 1}_2 ({0, +, 1}_x) = {0, +, 1}_3 ({0, +, 1}_x)
2914*e4b17023SJohn Marino 
2915*e4b17023SJohn Marino 	 Other examples:
2916*e4b17023SJohn Marino 	 {{0, +, 1}_1, +, 2}_2 ({0, +, 1}_x, {0, +, 1}_y) =
2917*e4b17023SJohn Marino 	 {0, +, 1}_1 ({{0, +, 1}_x, +, 2}_y)
2918*e4b17023SJohn Marino 
2919*e4b17023SJohn Marino 	 {{0, +, 2}_1, +, 3}_2 ({0, +, 1}_y, {0, +, 1}_x) =
2920*e4b17023SJohn Marino 	 {{0, +, 3}_1, +, 2}_2 ({0, +, 1}_x, {0, +, 1}_y)
2921*e4b17023SJohn Marino       */
2922*e4b17023SJohn Marino       analyze_subscript_affine_affine (chrec_a, chrec_b,
2923*e4b17023SJohn Marino 				       overlaps_a, overlaps_b, last_conflicts);
2924*e4b17023SJohn Marino 
2925*e4b17023SJohn Marino       if (CF_NOT_KNOWN_P (*overlaps_a)
2926*e4b17023SJohn Marino  	  || CF_NOT_KNOWN_P (*overlaps_b))
2927*e4b17023SJohn Marino 	dependence_stats.num_miv_unimplemented++;
2928*e4b17023SJohn Marino       else if (CF_NO_DEPENDENCE_P (*overlaps_a)
2929*e4b17023SJohn Marino 	       || CF_NO_DEPENDENCE_P (*overlaps_b))
2930*e4b17023SJohn Marino 	dependence_stats.num_miv_independent++;
2931*e4b17023SJohn Marino       else
2932*e4b17023SJohn Marino 	dependence_stats.num_miv_dependent++;
2933*e4b17023SJohn Marino     }
2934*e4b17023SJohn Marino 
2935*e4b17023SJohn Marino   else
2936*e4b17023SJohn Marino     {
2937*e4b17023SJohn Marino       /* When the analysis is too difficult, answer "don't know".  */
2938*e4b17023SJohn Marino       if (dump_file && (dump_flags & TDF_DETAILS))
2939*e4b17023SJohn Marino 	fprintf (dump_file, "analyze_miv_subscript test failed: unimplemented.\n");
2940*e4b17023SJohn Marino 
2941*e4b17023SJohn Marino       *overlaps_a = conflict_fn_not_known ();
2942*e4b17023SJohn Marino       *overlaps_b = conflict_fn_not_known ();
2943*e4b17023SJohn Marino       *last_conflicts = chrec_dont_know;
2944*e4b17023SJohn Marino       dependence_stats.num_miv_unimplemented++;
2945*e4b17023SJohn Marino     }
2946*e4b17023SJohn Marino 
2947*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2948*e4b17023SJohn Marino     fprintf (dump_file, ")\n");
2949*e4b17023SJohn Marino }
2950*e4b17023SJohn Marino 
2951*e4b17023SJohn Marino /* Determines the iterations for which CHREC_A is equal to CHREC_B in
2952*e4b17023SJohn Marino    with respect to LOOP_NEST.  OVERLAP_ITERATIONS_A and
2953*e4b17023SJohn Marino    OVERLAP_ITERATIONS_B are initialized with two functions that
2954*e4b17023SJohn Marino    describe the iterations that contain conflicting elements.
2955*e4b17023SJohn Marino 
2956*e4b17023SJohn Marino    Remark: For an integer k >= 0, the following equality is true:
2957*e4b17023SJohn Marino 
2958*e4b17023SJohn Marino    CHREC_A (OVERLAP_ITERATIONS_A (k)) == CHREC_B (OVERLAP_ITERATIONS_B (k)).
2959*e4b17023SJohn Marino */
2960*e4b17023SJohn Marino 
2961*e4b17023SJohn Marino static void
analyze_overlapping_iterations(tree chrec_a,tree chrec_b,conflict_function ** overlap_iterations_a,conflict_function ** overlap_iterations_b,tree * last_conflicts,struct loop * loop_nest)2962*e4b17023SJohn Marino analyze_overlapping_iterations (tree chrec_a,
2963*e4b17023SJohn Marino 				tree chrec_b,
2964*e4b17023SJohn Marino 				conflict_function **overlap_iterations_a,
2965*e4b17023SJohn Marino 				conflict_function **overlap_iterations_b,
2966*e4b17023SJohn Marino 				tree *last_conflicts, struct loop *loop_nest)
2967*e4b17023SJohn Marino {
2968*e4b17023SJohn Marino   unsigned int lnn = loop_nest->num;
2969*e4b17023SJohn Marino 
2970*e4b17023SJohn Marino   dependence_stats.num_subscript_tests++;
2971*e4b17023SJohn Marino 
2972*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
2973*e4b17023SJohn Marino     {
2974*e4b17023SJohn Marino       fprintf (dump_file, "(analyze_overlapping_iterations \n");
2975*e4b17023SJohn Marino       fprintf (dump_file, "  (chrec_a = ");
2976*e4b17023SJohn Marino       print_generic_expr (dump_file, chrec_a, 0);
2977*e4b17023SJohn Marino       fprintf (dump_file, ")\n  (chrec_b = ");
2978*e4b17023SJohn Marino       print_generic_expr (dump_file, chrec_b, 0);
2979*e4b17023SJohn Marino       fprintf (dump_file, ")\n");
2980*e4b17023SJohn Marino     }
2981*e4b17023SJohn Marino 
2982*e4b17023SJohn Marino   if (chrec_a == NULL_TREE
2983*e4b17023SJohn Marino       || chrec_b == NULL_TREE
2984*e4b17023SJohn Marino       || chrec_contains_undetermined (chrec_a)
2985*e4b17023SJohn Marino       || chrec_contains_undetermined (chrec_b))
2986*e4b17023SJohn Marino     {
2987*e4b17023SJohn Marino       dependence_stats.num_subscript_undetermined++;
2988*e4b17023SJohn Marino 
2989*e4b17023SJohn Marino       *overlap_iterations_a = conflict_fn_not_known ();
2990*e4b17023SJohn Marino       *overlap_iterations_b = conflict_fn_not_known ();
2991*e4b17023SJohn Marino     }
2992*e4b17023SJohn Marino 
2993*e4b17023SJohn Marino   /* If they are the same chrec, and are affine, they overlap
2994*e4b17023SJohn Marino      on every iteration.  */
2995*e4b17023SJohn Marino   else if (eq_evolutions_p (chrec_a, chrec_b)
2996*e4b17023SJohn Marino 	   && (evolution_function_is_affine_multivariate_p (chrec_a, lnn)
2997*e4b17023SJohn Marino 	       || operand_equal_p (chrec_a, chrec_b, 0)))
2998*e4b17023SJohn Marino     {
2999*e4b17023SJohn Marino       dependence_stats.num_same_subscript_function++;
3000*e4b17023SJohn Marino       *overlap_iterations_a = conflict_fn (1, affine_fn_cst (integer_zero_node));
3001*e4b17023SJohn Marino       *overlap_iterations_b = conflict_fn (1, affine_fn_cst (integer_zero_node));
3002*e4b17023SJohn Marino       *last_conflicts = chrec_dont_know;
3003*e4b17023SJohn Marino     }
3004*e4b17023SJohn Marino 
3005*e4b17023SJohn Marino   /* If they aren't the same, and aren't affine, we can't do anything
3006*e4b17023SJohn Marino      yet.  */
3007*e4b17023SJohn Marino   else if ((chrec_contains_symbols (chrec_a)
3008*e4b17023SJohn Marino 	    || chrec_contains_symbols (chrec_b))
3009*e4b17023SJohn Marino 	   && (!evolution_function_is_affine_multivariate_p (chrec_a, lnn)
3010*e4b17023SJohn Marino 	       || !evolution_function_is_affine_multivariate_p (chrec_b, lnn)))
3011*e4b17023SJohn Marino     {
3012*e4b17023SJohn Marino       dependence_stats.num_subscript_undetermined++;
3013*e4b17023SJohn Marino       *overlap_iterations_a = conflict_fn_not_known ();
3014*e4b17023SJohn Marino       *overlap_iterations_b = conflict_fn_not_known ();
3015*e4b17023SJohn Marino     }
3016*e4b17023SJohn Marino 
3017*e4b17023SJohn Marino   else if (ziv_subscript_p (chrec_a, chrec_b))
3018*e4b17023SJohn Marino     analyze_ziv_subscript (chrec_a, chrec_b,
3019*e4b17023SJohn Marino 			   overlap_iterations_a, overlap_iterations_b,
3020*e4b17023SJohn Marino 			   last_conflicts);
3021*e4b17023SJohn Marino 
3022*e4b17023SJohn Marino   else if (siv_subscript_p (chrec_a, chrec_b))
3023*e4b17023SJohn Marino     analyze_siv_subscript (chrec_a, chrec_b,
3024*e4b17023SJohn Marino 			   overlap_iterations_a, overlap_iterations_b,
3025*e4b17023SJohn Marino 			   last_conflicts, lnn);
3026*e4b17023SJohn Marino 
3027*e4b17023SJohn Marino   else
3028*e4b17023SJohn Marino     analyze_miv_subscript (chrec_a, chrec_b,
3029*e4b17023SJohn Marino 			   overlap_iterations_a, overlap_iterations_b,
3030*e4b17023SJohn Marino 			   last_conflicts, loop_nest);
3031*e4b17023SJohn Marino 
3032*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
3033*e4b17023SJohn Marino     {
3034*e4b17023SJohn Marino       fprintf (dump_file, "  (overlap_iterations_a = ");
3035*e4b17023SJohn Marino       dump_conflict_function (dump_file, *overlap_iterations_a);
3036*e4b17023SJohn Marino       fprintf (dump_file, ")\n  (overlap_iterations_b = ");
3037*e4b17023SJohn Marino       dump_conflict_function (dump_file, *overlap_iterations_b);
3038*e4b17023SJohn Marino       fprintf (dump_file, ")\n");
3039*e4b17023SJohn Marino       fprintf (dump_file, ")\n");
3040*e4b17023SJohn Marino     }
3041*e4b17023SJohn Marino }
3042*e4b17023SJohn Marino 
3043*e4b17023SJohn Marino /* Helper function for uniquely inserting distance vectors.  */
3044*e4b17023SJohn Marino 
3045*e4b17023SJohn Marino static void
save_dist_v(struct data_dependence_relation * ddr,lambda_vector dist_v)3046*e4b17023SJohn Marino save_dist_v (struct data_dependence_relation *ddr, lambda_vector dist_v)
3047*e4b17023SJohn Marino {
3048*e4b17023SJohn Marino   unsigned i;
3049*e4b17023SJohn Marino   lambda_vector v;
3050*e4b17023SJohn Marino 
3051*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (lambda_vector, DDR_DIST_VECTS (ddr), i, v)
3052*e4b17023SJohn Marino     if (lambda_vector_equal (v, dist_v, DDR_NB_LOOPS (ddr)))
3053*e4b17023SJohn Marino       return;
3054*e4b17023SJohn Marino 
3055*e4b17023SJohn Marino   VEC_safe_push (lambda_vector, heap, DDR_DIST_VECTS (ddr), dist_v);
3056*e4b17023SJohn Marino }
3057*e4b17023SJohn Marino 
3058*e4b17023SJohn Marino /* Helper function for uniquely inserting direction vectors.  */
3059*e4b17023SJohn Marino 
3060*e4b17023SJohn Marino static void
save_dir_v(struct data_dependence_relation * ddr,lambda_vector dir_v)3061*e4b17023SJohn Marino save_dir_v (struct data_dependence_relation *ddr, lambda_vector dir_v)
3062*e4b17023SJohn Marino {
3063*e4b17023SJohn Marino   unsigned i;
3064*e4b17023SJohn Marino   lambda_vector v;
3065*e4b17023SJohn Marino 
3066*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (lambda_vector, DDR_DIR_VECTS (ddr), i, v)
3067*e4b17023SJohn Marino     if (lambda_vector_equal (v, dir_v, DDR_NB_LOOPS (ddr)))
3068*e4b17023SJohn Marino       return;
3069*e4b17023SJohn Marino 
3070*e4b17023SJohn Marino   VEC_safe_push (lambda_vector, heap, DDR_DIR_VECTS (ddr), dir_v);
3071*e4b17023SJohn Marino }
3072*e4b17023SJohn Marino 
3073*e4b17023SJohn Marino /* Add a distance of 1 on all the loops outer than INDEX.  If we
3074*e4b17023SJohn Marino    haven't yet determined a distance for this outer loop, push a new
3075*e4b17023SJohn Marino    distance vector composed of the previous distance, and a distance
3076*e4b17023SJohn Marino    of 1 for this outer loop.  Example:
3077*e4b17023SJohn Marino 
3078*e4b17023SJohn Marino    | loop_1
3079*e4b17023SJohn Marino    |   loop_2
3080*e4b17023SJohn Marino    |     A[10]
3081*e4b17023SJohn Marino    |   endloop_2
3082*e4b17023SJohn Marino    | endloop_1
3083*e4b17023SJohn Marino 
3084*e4b17023SJohn Marino    Saved vectors are of the form (dist_in_1, dist_in_2).  First, we
3085*e4b17023SJohn Marino    save (0, 1), then we have to save (1, 0).  */
3086*e4b17023SJohn Marino 
3087*e4b17023SJohn Marino static void
add_outer_distances(struct data_dependence_relation * ddr,lambda_vector dist_v,int index)3088*e4b17023SJohn Marino add_outer_distances (struct data_dependence_relation *ddr,
3089*e4b17023SJohn Marino 		     lambda_vector dist_v, int index)
3090*e4b17023SJohn Marino {
3091*e4b17023SJohn Marino   /* For each outer loop where init_v is not set, the accesses are
3092*e4b17023SJohn Marino      in dependence of distance 1 in the loop.  */
3093*e4b17023SJohn Marino   while (--index >= 0)
3094*e4b17023SJohn Marino     {
3095*e4b17023SJohn Marino       lambda_vector save_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3096*e4b17023SJohn Marino       lambda_vector_copy (dist_v, save_v, DDR_NB_LOOPS (ddr));
3097*e4b17023SJohn Marino       save_v[index] = 1;
3098*e4b17023SJohn Marino       save_dist_v (ddr, save_v);
3099*e4b17023SJohn Marino     }
3100*e4b17023SJohn Marino }
3101*e4b17023SJohn Marino 
3102*e4b17023SJohn Marino /* Return false when fail to represent the data dependence as a
3103*e4b17023SJohn Marino    distance vector.  INIT_B is set to true when a component has been
3104*e4b17023SJohn Marino    added to the distance vector DIST_V.  INDEX_CARRY is then set to
3105*e4b17023SJohn Marino    the index in DIST_V that carries the dependence.  */
3106*e4b17023SJohn Marino 
3107*e4b17023SJohn Marino static bool
build_classic_dist_vector_1(struct data_dependence_relation * ddr,struct data_reference * ddr_a,struct data_reference * ddr_b,lambda_vector dist_v,bool * init_b,int * index_carry)3108*e4b17023SJohn Marino build_classic_dist_vector_1 (struct data_dependence_relation *ddr,
3109*e4b17023SJohn Marino 			     struct data_reference *ddr_a,
3110*e4b17023SJohn Marino 			     struct data_reference *ddr_b,
3111*e4b17023SJohn Marino 			     lambda_vector dist_v, bool *init_b,
3112*e4b17023SJohn Marino 			     int *index_carry)
3113*e4b17023SJohn Marino {
3114*e4b17023SJohn Marino   unsigned i;
3115*e4b17023SJohn Marino   lambda_vector init_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3116*e4b17023SJohn Marino 
3117*e4b17023SJohn Marino   for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
3118*e4b17023SJohn Marino     {
3119*e4b17023SJohn Marino       tree access_fn_a, access_fn_b;
3120*e4b17023SJohn Marino       struct subscript *subscript = DDR_SUBSCRIPT (ddr, i);
3121*e4b17023SJohn Marino 
3122*e4b17023SJohn Marino       if (chrec_contains_undetermined (SUB_DISTANCE (subscript)))
3123*e4b17023SJohn Marino 	{
3124*e4b17023SJohn Marino 	  non_affine_dependence_relation (ddr);
3125*e4b17023SJohn Marino 	  return false;
3126*e4b17023SJohn Marino 	}
3127*e4b17023SJohn Marino 
3128*e4b17023SJohn Marino       access_fn_a = DR_ACCESS_FN (ddr_a, i);
3129*e4b17023SJohn Marino       access_fn_b = DR_ACCESS_FN (ddr_b, i);
3130*e4b17023SJohn Marino 
3131*e4b17023SJohn Marino       if (TREE_CODE (access_fn_a) == POLYNOMIAL_CHREC
3132*e4b17023SJohn Marino 	  && TREE_CODE (access_fn_b) == POLYNOMIAL_CHREC)
3133*e4b17023SJohn Marino 	{
3134*e4b17023SJohn Marino 	  int dist, index;
3135*e4b17023SJohn Marino 	  int var_a = CHREC_VARIABLE (access_fn_a);
3136*e4b17023SJohn Marino 	  int var_b = CHREC_VARIABLE (access_fn_b);
3137*e4b17023SJohn Marino 
3138*e4b17023SJohn Marino 	  if (var_a != var_b
3139*e4b17023SJohn Marino 	      || chrec_contains_undetermined (SUB_DISTANCE (subscript)))
3140*e4b17023SJohn Marino 	    {
3141*e4b17023SJohn Marino 	      non_affine_dependence_relation (ddr);
3142*e4b17023SJohn Marino 	      return false;
3143*e4b17023SJohn Marino 	    }
3144*e4b17023SJohn Marino 
3145*e4b17023SJohn Marino 	  dist = int_cst_value (SUB_DISTANCE (subscript));
3146*e4b17023SJohn Marino 	  index = index_in_loop_nest (var_a, DDR_LOOP_NEST (ddr));
3147*e4b17023SJohn Marino 	  *index_carry = MIN (index, *index_carry);
3148*e4b17023SJohn Marino 
3149*e4b17023SJohn Marino 	  /* This is the subscript coupling test.  If we have already
3150*e4b17023SJohn Marino 	     recorded a distance for this loop (a distance coming from
3151*e4b17023SJohn Marino 	     another subscript), it should be the same.  For example,
3152*e4b17023SJohn Marino 	     in the following code, there is no dependence:
3153*e4b17023SJohn Marino 
3154*e4b17023SJohn Marino 	     | loop i = 0, N, 1
3155*e4b17023SJohn Marino 	     |   T[i+1][i] = ...
3156*e4b17023SJohn Marino 	     |   ... = T[i][i]
3157*e4b17023SJohn Marino 	     | endloop
3158*e4b17023SJohn Marino 	  */
3159*e4b17023SJohn Marino 	  if (init_v[index] != 0 && dist_v[index] != dist)
3160*e4b17023SJohn Marino 	    {
3161*e4b17023SJohn Marino 	      finalize_ddr_dependent (ddr, chrec_known);
3162*e4b17023SJohn Marino 	      return false;
3163*e4b17023SJohn Marino 	    }
3164*e4b17023SJohn Marino 
3165*e4b17023SJohn Marino 	  dist_v[index] = dist;
3166*e4b17023SJohn Marino 	  init_v[index] = 1;
3167*e4b17023SJohn Marino 	  *init_b = true;
3168*e4b17023SJohn Marino 	}
3169*e4b17023SJohn Marino       else if (!operand_equal_p (access_fn_a, access_fn_b, 0))
3170*e4b17023SJohn Marino 	{
3171*e4b17023SJohn Marino 	  /* This can be for example an affine vs. constant dependence
3172*e4b17023SJohn Marino 	     (T[i] vs. T[3]) that is not an affine dependence and is
3173*e4b17023SJohn Marino 	     not representable as a distance vector.  */
3174*e4b17023SJohn Marino 	  non_affine_dependence_relation (ddr);
3175*e4b17023SJohn Marino 	  return false;
3176*e4b17023SJohn Marino 	}
3177*e4b17023SJohn Marino     }
3178*e4b17023SJohn Marino 
3179*e4b17023SJohn Marino   return true;
3180*e4b17023SJohn Marino }
3181*e4b17023SJohn Marino 
3182*e4b17023SJohn Marino /* Return true when the DDR contains only constant access functions.  */
3183*e4b17023SJohn Marino 
3184*e4b17023SJohn Marino static bool
constant_access_functions(const struct data_dependence_relation * ddr)3185*e4b17023SJohn Marino constant_access_functions (const struct data_dependence_relation *ddr)
3186*e4b17023SJohn Marino {
3187*e4b17023SJohn Marino   unsigned i;
3188*e4b17023SJohn Marino 
3189*e4b17023SJohn Marino   for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
3190*e4b17023SJohn Marino     if (!evolution_function_is_constant_p (DR_ACCESS_FN (DDR_A (ddr), i))
3191*e4b17023SJohn Marino 	|| !evolution_function_is_constant_p (DR_ACCESS_FN (DDR_B (ddr), i)))
3192*e4b17023SJohn Marino       return false;
3193*e4b17023SJohn Marino 
3194*e4b17023SJohn Marino   return true;
3195*e4b17023SJohn Marino }
3196*e4b17023SJohn Marino 
3197*e4b17023SJohn Marino /* Helper function for the case where DDR_A and DDR_B are the same
3198*e4b17023SJohn Marino    multivariate access function with a constant step.  For an example
3199*e4b17023SJohn Marino    see pr34635-1.c.  */
3200*e4b17023SJohn Marino 
3201*e4b17023SJohn Marino static void
add_multivariate_self_dist(struct data_dependence_relation * ddr,tree c_2)3202*e4b17023SJohn Marino add_multivariate_self_dist (struct data_dependence_relation *ddr, tree c_2)
3203*e4b17023SJohn Marino {
3204*e4b17023SJohn Marino   int x_1, x_2;
3205*e4b17023SJohn Marino   tree c_1 = CHREC_LEFT (c_2);
3206*e4b17023SJohn Marino   tree c_0 = CHREC_LEFT (c_1);
3207*e4b17023SJohn Marino   lambda_vector dist_v;
3208*e4b17023SJohn Marino   int v1, v2, cd;
3209*e4b17023SJohn Marino 
3210*e4b17023SJohn Marino   /* Polynomials with more than 2 variables are not handled yet.  When
3211*e4b17023SJohn Marino      the evolution steps are parameters, it is not possible to
3212*e4b17023SJohn Marino      represent the dependence using classical distance vectors.  */
3213*e4b17023SJohn Marino   if (TREE_CODE (c_0) != INTEGER_CST
3214*e4b17023SJohn Marino       || TREE_CODE (CHREC_RIGHT (c_1)) != INTEGER_CST
3215*e4b17023SJohn Marino       || TREE_CODE (CHREC_RIGHT (c_2)) != INTEGER_CST)
3216*e4b17023SJohn Marino     {
3217*e4b17023SJohn Marino       DDR_AFFINE_P (ddr) = false;
3218*e4b17023SJohn Marino       return;
3219*e4b17023SJohn Marino     }
3220*e4b17023SJohn Marino 
3221*e4b17023SJohn Marino   x_2 = index_in_loop_nest (CHREC_VARIABLE (c_2), DDR_LOOP_NEST (ddr));
3222*e4b17023SJohn Marino   x_1 = index_in_loop_nest (CHREC_VARIABLE (c_1), DDR_LOOP_NEST (ddr));
3223*e4b17023SJohn Marino 
3224*e4b17023SJohn Marino   /* For "{{0, +, 2}_1, +, 3}_2" the distance vector is (3, -2).  */
3225*e4b17023SJohn Marino   dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3226*e4b17023SJohn Marino   v1 = int_cst_value (CHREC_RIGHT (c_1));
3227*e4b17023SJohn Marino   v2 = int_cst_value (CHREC_RIGHT (c_2));
3228*e4b17023SJohn Marino   cd = gcd (v1, v2);
3229*e4b17023SJohn Marino   v1 /= cd;
3230*e4b17023SJohn Marino   v2 /= cd;
3231*e4b17023SJohn Marino 
3232*e4b17023SJohn Marino   if (v2 < 0)
3233*e4b17023SJohn Marino     {
3234*e4b17023SJohn Marino       v2 = -v2;
3235*e4b17023SJohn Marino       v1 = -v1;
3236*e4b17023SJohn Marino     }
3237*e4b17023SJohn Marino 
3238*e4b17023SJohn Marino   dist_v[x_1] = v2;
3239*e4b17023SJohn Marino   dist_v[x_2] = -v1;
3240*e4b17023SJohn Marino   save_dist_v (ddr, dist_v);
3241*e4b17023SJohn Marino 
3242*e4b17023SJohn Marino   add_outer_distances (ddr, dist_v, x_1);
3243*e4b17023SJohn Marino }
3244*e4b17023SJohn Marino 
3245*e4b17023SJohn Marino /* Helper function for the case where DDR_A and DDR_B are the same
3246*e4b17023SJohn Marino    access functions.  */
3247*e4b17023SJohn Marino 
3248*e4b17023SJohn Marino static void
add_other_self_distances(struct data_dependence_relation * ddr)3249*e4b17023SJohn Marino add_other_self_distances (struct data_dependence_relation *ddr)
3250*e4b17023SJohn Marino {
3251*e4b17023SJohn Marino   lambda_vector dist_v;
3252*e4b17023SJohn Marino   unsigned i;
3253*e4b17023SJohn Marino   int index_carry = DDR_NB_LOOPS (ddr);
3254*e4b17023SJohn Marino 
3255*e4b17023SJohn Marino   for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
3256*e4b17023SJohn Marino     {
3257*e4b17023SJohn Marino       tree access_fun = DR_ACCESS_FN (DDR_A (ddr), i);
3258*e4b17023SJohn Marino 
3259*e4b17023SJohn Marino       if (TREE_CODE (access_fun) == POLYNOMIAL_CHREC)
3260*e4b17023SJohn Marino 	{
3261*e4b17023SJohn Marino 	  if (!evolution_function_is_univariate_p (access_fun))
3262*e4b17023SJohn Marino 	    {
3263*e4b17023SJohn Marino 	      if (DDR_NUM_SUBSCRIPTS (ddr) != 1)
3264*e4b17023SJohn Marino 		{
3265*e4b17023SJohn Marino 		  DDR_ARE_DEPENDENT (ddr) = chrec_dont_know;
3266*e4b17023SJohn Marino 		  return;
3267*e4b17023SJohn Marino 		}
3268*e4b17023SJohn Marino 
3269*e4b17023SJohn Marino 	      access_fun = DR_ACCESS_FN (DDR_A (ddr), 0);
3270*e4b17023SJohn Marino 
3271*e4b17023SJohn Marino 	      if (TREE_CODE (CHREC_LEFT (access_fun)) == POLYNOMIAL_CHREC)
3272*e4b17023SJohn Marino 		add_multivariate_self_dist (ddr, access_fun);
3273*e4b17023SJohn Marino 	      else
3274*e4b17023SJohn Marino 		/* The evolution step is not constant: it varies in
3275*e4b17023SJohn Marino 		   the outer loop, so this cannot be represented by a
3276*e4b17023SJohn Marino 		   distance vector.  For example in pr34635.c the
3277*e4b17023SJohn Marino 		   evolution is {0, +, {0, +, 4}_1}_2.  */
3278*e4b17023SJohn Marino 		DDR_AFFINE_P (ddr) = false;
3279*e4b17023SJohn Marino 
3280*e4b17023SJohn Marino 	      return;
3281*e4b17023SJohn Marino 	    }
3282*e4b17023SJohn Marino 
3283*e4b17023SJohn Marino 	  index_carry = MIN (index_carry,
3284*e4b17023SJohn Marino 			     index_in_loop_nest (CHREC_VARIABLE (access_fun),
3285*e4b17023SJohn Marino 						 DDR_LOOP_NEST (ddr)));
3286*e4b17023SJohn Marino 	}
3287*e4b17023SJohn Marino     }
3288*e4b17023SJohn Marino 
3289*e4b17023SJohn Marino   dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3290*e4b17023SJohn Marino   add_outer_distances (ddr, dist_v, index_carry);
3291*e4b17023SJohn Marino }
3292*e4b17023SJohn Marino 
3293*e4b17023SJohn Marino static void
insert_innermost_unit_dist_vector(struct data_dependence_relation * ddr)3294*e4b17023SJohn Marino insert_innermost_unit_dist_vector (struct data_dependence_relation *ddr)
3295*e4b17023SJohn Marino {
3296*e4b17023SJohn Marino   lambda_vector dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3297*e4b17023SJohn Marino 
3298*e4b17023SJohn Marino   dist_v[DDR_INNER_LOOP (ddr)] = 1;
3299*e4b17023SJohn Marino   save_dist_v (ddr, dist_v);
3300*e4b17023SJohn Marino }
3301*e4b17023SJohn Marino 
3302*e4b17023SJohn Marino /* Adds a unit distance vector to DDR when there is a 0 overlap.  This
3303*e4b17023SJohn Marino    is the case for example when access functions are the same and
3304*e4b17023SJohn Marino    equal to a constant, as in:
3305*e4b17023SJohn Marino 
3306*e4b17023SJohn Marino    | loop_1
3307*e4b17023SJohn Marino    |   A[3] = ...
3308*e4b17023SJohn Marino    |   ... = A[3]
3309*e4b17023SJohn Marino    | endloop_1
3310*e4b17023SJohn Marino 
3311*e4b17023SJohn Marino    in which case the distance vectors are (0) and (1).  */
3312*e4b17023SJohn Marino 
3313*e4b17023SJohn Marino static void
add_distance_for_zero_overlaps(struct data_dependence_relation * ddr)3314*e4b17023SJohn Marino add_distance_for_zero_overlaps (struct data_dependence_relation *ddr)
3315*e4b17023SJohn Marino {
3316*e4b17023SJohn Marino   unsigned i, j;
3317*e4b17023SJohn Marino 
3318*e4b17023SJohn Marino   for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
3319*e4b17023SJohn Marino     {
3320*e4b17023SJohn Marino       subscript_p sub = DDR_SUBSCRIPT (ddr, i);
3321*e4b17023SJohn Marino       conflict_function *ca = SUB_CONFLICTS_IN_A (sub);
3322*e4b17023SJohn Marino       conflict_function *cb = SUB_CONFLICTS_IN_B (sub);
3323*e4b17023SJohn Marino 
3324*e4b17023SJohn Marino       for (j = 0; j < ca->n; j++)
3325*e4b17023SJohn Marino 	if (affine_function_zero_p (ca->fns[j]))
3326*e4b17023SJohn Marino 	  {
3327*e4b17023SJohn Marino 	    insert_innermost_unit_dist_vector (ddr);
3328*e4b17023SJohn Marino 	    return;
3329*e4b17023SJohn Marino 	  }
3330*e4b17023SJohn Marino 
3331*e4b17023SJohn Marino       for (j = 0; j < cb->n; j++)
3332*e4b17023SJohn Marino 	if (affine_function_zero_p (cb->fns[j]))
3333*e4b17023SJohn Marino 	  {
3334*e4b17023SJohn Marino 	    insert_innermost_unit_dist_vector (ddr);
3335*e4b17023SJohn Marino 	    return;
3336*e4b17023SJohn Marino 	  }
3337*e4b17023SJohn Marino     }
3338*e4b17023SJohn Marino }
3339*e4b17023SJohn Marino 
3340*e4b17023SJohn Marino /* Compute the classic per loop distance vector.  DDR is the data
3341*e4b17023SJohn Marino    dependence relation to build a vector from.  Return false when fail
3342*e4b17023SJohn Marino    to represent the data dependence as a distance vector.  */
3343*e4b17023SJohn Marino 
3344*e4b17023SJohn Marino static bool
build_classic_dist_vector(struct data_dependence_relation * ddr,struct loop * loop_nest)3345*e4b17023SJohn Marino build_classic_dist_vector (struct data_dependence_relation *ddr,
3346*e4b17023SJohn Marino 			   struct loop *loop_nest)
3347*e4b17023SJohn Marino {
3348*e4b17023SJohn Marino   bool init_b = false;
3349*e4b17023SJohn Marino   int index_carry = DDR_NB_LOOPS (ddr);
3350*e4b17023SJohn Marino   lambda_vector dist_v;
3351*e4b17023SJohn Marino 
3352*e4b17023SJohn Marino   if (DDR_ARE_DEPENDENT (ddr) != NULL_TREE)
3353*e4b17023SJohn Marino     return false;
3354*e4b17023SJohn Marino 
3355*e4b17023SJohn Marino   if (same_access_functions (ddr))
3356*e4b17023SJohn Marino     {
3357*e4b17023SJohn Marino       /* Save the 0 vector.  */
3358*e4b17023SJohn Marino       dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3359*e4b17023SJohn Marino       save_dist_v (ddr, dist_v);
3360*e4b17023SJohn Marino 
3361*e4b17023SJohn Marino       if (constant_access_functions (ddr))
3362*e4b17023SJohn Marino 	add_distance_for_zero_overlaps (ddr);
3363*e4b17023SJohn Marino 
3364*e4b17023SJohn Marino       if (DDR_NB_LOOPS (ddr) > 1)
3365*e4b17023SJohn Marino 	add_other_self_distances (ddr);
3366*e4b17023SJohn Marino 
3367*e4b17023SJohn Marino       return true;
3368*e4b17023SJohn Marino     }
3369*e4b17023SJohn Marino 
3370*e4b17023SJohn Marino   dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3371*e4b17023SJohn Marino   if (!build_classic_dist_vector_1 (ddr, DDR_A (ddr), DDR_B (ddr),
3372*e4b17023SJohn Marino 				    dist_v, &init_b, &index_carry))
3373*e4b17023SJohn Marino     return false;
3374*e4b17023SJohn Marino 
3375*e4b17023SJohn Marino   /* Save the distance vector if we initialized one.  */
3376*e4b17023SJohn Marino   if (init_b)
3377*e4b17023SJohn Marino     {
3378*e4b17023SJohn Marino       /* Verify a basic constraint: classic distance vectors should
3379*e4b17023SJohn Marino 	 always be lexicographically positive.
3380*e4b17023SJohn Marino 
3381*e4b17023SJohn Marino 	 Data references are collected in the order of execution of
3382*e4b17023SJohn Marino 	 the program, thus for the following loop
3383*e4b17023SJohn Marino 
3384*e4b17023SJohn Marino 	 | for (i = 1; i < 100; i++)
3385*e4b17023SJohn Marino 	 |   for (j = 1; j < 100; j++)
3386*e4b17023SJohn Marino 	 |     {
3387*e4b17023SJohn Marino 	 |       t = T[j+1][i-1];  // A
3388*e4b17023SJohn Marino 	 |       T[j][i] = t + 2;  // B
3389*e4b17023SJohn Marino 	 |     }
3390*e4b17023SJohn Marino 
3391*e4b17023SJohn Marino 	 references are collected following the direction of the wind:
3392*e4b17023SJohn Marino 	 A then B.  The data dependence tests are performed also
3393*e4b17023SJohn Marino 	 following this order, such that we're looking at the distance
3394*e4b17023SJohn Marino 	 separating the elements accessed by A from the elements later
3395*e4b17023SJohn Marino 	 accessed by B.  But in this example, the distance returned by
3396*e4b17023SJohn Marino 	 test_dep (A, B) is lexicographically negative (-1, 1), that
3397*e4b17023SJohn Marino 	 means that the access A occurs later than B with respect to
3398*e4b17023SJohn Marino 	 the outer loop, ie. we're actually looking upwind.  In this
3399*e4b17023SJohn Marino 	 case we solve test_dep (B, A) looking downwind to the
3400*e4b17023SJohn Marino 	 lexicographically positive solution, that returns the
3401*e4b17023SJohn Marino 	 distance vector (1, -1).  */
3402*e4b17023SJohn Marino       if (!lambda_vector_lexico_pos (dist_v, DDR_NB_LOOPS (ddr)))
3403*e4b17023SJohn Marino 	{
3404*e4b17023SJohn Marino 	  lambda_vector save_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3405*e4b17023SJohn Marino 	  if (!subscript_dependence_tester_1 (ddr, DDR_B (ddr), DDR_A (ddr),
3406*e4b17023SJohn Marino 					      loop_nest))
3407*e4b17023SJohn Marino 	    return false;
3408*e4b17023SJohn Marino 	  compute_subscript_distance (ddr);
3409*e4b17023SJohn Marino 	  if (!build_classic_dist_vector_1 (ddr, DDR_B (ddr), DDR_A (ddr),
3410*e4b17023SJohn Marino 					    save_v, &init_b, &index_carry))
3411*e4b17023SJohn Marino 	    return false;
3412*e4b17023SJohn Marino 	  save_dist_v (ddr, save_v);
3413*e4b17023SJohn Marino 	  DDR_REVERSED_P (ddr) = true;
3414*e4b17023SJohn Marino 
3415*e4b17023SJohn Marino 	  /* In this case there is a dependence forward for all the
3416*e4b17023SJohn Marino 	     outer loops:
3417*e4b17023SJohn Marino 
3418*e4b17023SJohn Marino 	     | for (k = 1; k < 100; k++)
3419*e4b17023SJohn Marino 	     |  for (i = 1; i < 100; i++)
3420*e4b17023SJohn Marino 	     |   for (j = 1; j < 100; j++)
3421*e4b17023SJohn Marino 	     |     {
3422*e4b17023SJohn Marino 	     |       t = T[j+1][i-1];  // A
3423*e4b17023SJohn Marino 	     |       T[j][i] = t + 2;  // B
3424*e4b17023SJohn Marino 	     |     }
3425*e4b17023SJohn Marino 
3426*e4b17023SJohn Marino 	     the vectors are:
3427*e4b17023SJohn Marino 	     (0,  1, -1)
3428*e4b17023SJohn Marino 	     (1,  1, -1)
3429*e4b17023SJohn Marino 	     (1, -1,  1)
3430*e4b17023SJohn Marino 	  */
3431*e4b17023SJohn Marino 	  if (DDR_NB_LOOPS (ddr) > 1)
3432*e4b17023SJohn Marino 	    {
3433*e4b17023SJohn Marino  	      add_outer_distances (ddr, save_v, index_carry);
3434*e4b17023SJohn Marino 	      add_outer_distances (ddr, dist_v, index_carry);
3435*e4b17023SJohn Marino 	    }
3436*e4b17023SJohn Marino 	}
3437*e4b17023SJohn Marino       else
3438*e4b17023SJohn Marino 	{
3439*e4b17023SJohn Marino 	  lambda_vector save_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3440*e4b17023SJohn Marino 	  lambda_vector_copy (dist_v, save_v, DDR_NB_LOOPS (ddr));
3441*e4b17023SJohn Marino 
3442*e4b17023SJohn Marino 	  if (DDR_NB_LOOPS (ddr) > 1)
3443*e4b17023SJohn Marino 	    {
3444*e4b17023SJohn Marino 	      lambda_vector opposite_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3445*e4b17023SJohn Marino 
3446*e4b17023SJohn Marino 	      if (!subscript_dependence_tester_1 (ddr, DDR_B (ddr),
3447*e4b17023SJohn Marino 						  DDR_A (ddr), loop_nest))
3448*e4b17023SJohn Marino 		return false;
3449*e4b17023SJohn Marino 	      compute_subscript_distance (ddr);
3450*e4b17023SJohn Marino 	      if (!build_classic_dist_vector_1 (ddr, DDR_B (ddr), DDR_A (ddr),
3451*e4b17023SJohn Marino 						opposite_v, &init_b,
3452*e4b17023SJohn Marino 						&index_carry))
3453*e4b17023SJohn Marino 		return false;
3454*e4b17023SJohn Marino 
3455*e4b17023SJohn Marino 	      save_dist_v (ddr, save_v);
3456*e4b17023SJohn Marino 	      add_outer_distances (ddr, dist_v, index_carry);
3457*e4b17023SJohn Marino 	      add_outer_distances (ddr, opposite_v, index_carry);
3458*e4b17023SJohn Marino 	    }
3459*e4b17023SJohn Marino 	  else
3460*e4b17023SJohn Marino 	    save_dist_v (ddr, save_v);
3461*e4b17023SJohn Marino 	}
3462*e4b17023SJohn Marino     }
3463*e4b17023SJohn Marino   else
3464*e4b17023SJohn Marino     {
3465*e4b17023SJohn Marino       /* There is a distance of 1 on all the outer loops: Example:
3466*e4b17023SJohn Marino 	 there is a dependence of distance 1 on loop_1 for the array A.
3467*e4b17023SJohn Marino 
3468*e4b17023SJohn Marino 	 | loop_1
3469*e4b17023SJohn Marino 	 |   A[5] = ...
3470*e4b17023SJohn Marino 	 | endloop
3471*e4b17023SJohn Marino       */
3472*e4b17023SJohn Marino       add_outer_distances (ddr, dist_v,
3473*e4b17023SJohn Marino 			   lambda_vector_first_nz (dist_v,
3474*e4b17023SJohn Marino 						   DDR_NB_LOOPS (ddr), 0));
3475*e4b17023SJohn Marino     }
3476*e4b17023SJohn Marino 
3477*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
3478*e4b17023SJohn Marino     {
3479*e4b17023SJohn Marino       unsigned i;
3480*e4b17023SJohn Marino 
3481*e4b17023SJohn Marino       fprintf (dump_file, "(build_classic_dist_vector\n");
3482*e4b17023SJohn Marino       for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
3483*e4b17023SJohn Marino 	{
3484*e4b17023SJohn Marino 	  fprintf (dump_file, "  dist_vector = (");
3485*e4b17023SJohn Marino 	  print_lambda_vector (dump_file, DDR_DIST_VECT (ddr, i),
3486*e4b17023SJohn Marino 			       DDR_NB_LOOPS (ddr));
3487*e4b17023SJohn Marino 	  fprintf (dump_file, "  )\n");
3488*e4b17023SJohn Marino 	}
3489*e4b17023SJohn Marino       fprintf (dump_file, ")\n");
3490*e4b17023SJohn Marino     }
3491*e4b17023SJohn Marino 
3492*e4b17023SJohn Marino   return true;
3493*e4b17023SJohn Marino }
3494*e4b17023SJohn Marino 
3495*e4b17023SJohn Marino /* Return the direction for a given distance.
3496*e4b17023SJohn Marino    FIXME: Computing dir this way is suboptimal, since dir can catch
3497*e4b17023SJohn Marino    cases that dist is unable to represent.  */
3498*e4b17023SJohn Marino 
3499*e4b17023SJohn Marino static inline enum data_dependence_direction
dir_from_dist(int dist)3500*e4b17023SJohn Marino dir_from_dist (int dist)
3501*e4b17023SJohn Marino {
3502*e4b17023SJohn Marino   if (dist > 0)
3503*e4b17023SJohn Marino     return dir_positive;
3504*e4b17023SJohn Marino   else if (dist < 0)
3505*e4b17023SJohn Marino     return dir_negative;
3506*e4b17023SJohn Marino   else
3507*e4b17023SJohn Marino     return dir_equal;
3508*e4b17023SJohn Marino }
3509*e4b17023SJohn Marino 
3510*e4b17023SJohn Marino /* Compute the classic per loop direction vector.  DDR is the data
3511*e4b17023SJohn Marino    dependence relation to build a vector from.  */
3512*e4b17023SJohn Marino 
3513*e4b17023SJohn Marino static void
build_classic_dir_vector(struct data_dependence_relation * ddr)3514*e4b17023SJohn Marino build_classic_dir_vector (struct data_dependence_relation *ddr)
3515*e4b17023SJohn Marino {
3516*e4b17023SJohn Marino   unsigned i, j;
3517*e4b17023SJohn Marino   lambda_vector dist_v;
3518*e4b17023SJohn Marino 
3519*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (lambda_vector, DDR_DIST_VECTS (ddr), i, dist_v)
3520*e4b17023SJohn Marino     {
3521*e4b17023SJohn Marino       lambda_vector dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3522*e4b17023SJohn Marino 
3523*e4b17023SJohn Marino       for (j = 0; j < DDR_NB_LOOPS (ddr); j++)
3524*e4b17023SJohn Marino 	dir_v[j] = dir_from_dist (dist_v[j]);
3525*e4b17023SJohn Marino 
3526*e4b17023SJohn Marino       save_dir_v (ddr, dir_v);
3527*e4b17023SJohn Marino     }
3528*e4b17023SJohn Marino }
3529*e4b17023SJohn Marino 
3530*e4b17023SJohn Marino /* Helper function.  Returns true when there is a dependence between
3531*e4b17023SJohn Marino    data references DRA and DRB.  */
3532*e4b17023SJohn Marino 
3533*e4b17023SJohn Marino static bool
subscript_dependence_tester_1(struct data_dependence_relation * ddr,struct data_reference * dra,struct data_reference * drb,struct loop * loop_nest)3534*e4b17023SJohn Marino subscript_dependence_tester_1 (struct data_dependence_relation *ddr,
3535*e4b17023SJohn Marino 			       struct data_reference *dra,
3536*e4b17023SJohn Marino 			       struct data_reference *drb,
3537*e4b17023SJohn Marino 			       struct loop *loop_nest)
3538*e4b17023SJohn Marino {
3539*e4b17023SJohn Marino   unsigned int i;
3540*e4b17023SJohn Marino   tree last_conflicts;
3541*e4b17023SJohn Marino   struct subscript *subscript;
3542*e4b17023SJohn Marino   tree res = NULL_TREE;
3543*e4b17023SJohn Marino 
3544*e4b17023SJohn Marino   for (i = 0; VEC_iterate (subscript_p, DDR_SUBSCRIPTS (ddr), i, subscript);
3545*e4b17023SJohn Marino        i++)
3546*e4b17023SJohn Marino     {
3547*e4b17023SJohn Marino       conflict_function *overlaps_a, *overlaps_b;
3548*e4b17023SJohn Marino 
3549*e4b17023SJohn Marino       analyze_overlapping_iterations (DR_ACCESS_FN (dra, i),
3550*e4b17023SJohn Marino 				      DR_ACCESS_FN (drb, i),
3551*e4b17023SJohn Marino 				      &overlaps_a, &overlaps_b,
3552*e4b17023SJohn Marino 				      &last_conflicts, loop_nest);
3553*e4b17023SJohn Marino 
3554*e4b17023SJohn Marino       if (SUB_CONFLICTS_IN_A (subscript))
3555*e4b17023SJohn Marino 	free_conflict_function (SUB_CONFLICTS_IN_A (subscript));
3556*e4b17023SJohn Marino       if (SUB_CONFLICTS_IN_B (subscript))
3557*e4b17023SJohn Marino 	free_conflict_function (SUB_CONFLICTS_IN_B (subscript));
3558*e4b17023SJohn Marino 
3559*e4b17023SJohn Marino       SUB_CONFLICTS_IN_A (subscript) = overlaps_a;
3560*e4b17023SJohn Marino       SUB_CONFLICTS_IN_B (subscript) = overlaps_b;
3561*e4b17023SJohn Marino       SUB_LAST_CONFLICT (subscript) = last_conflicts;
3562*e4b17023SJohn Marino 
3563*e4b17023SJohn Marino       /* If there is any undetermined conflict function we have to
3564*e4b17023SJohn Marino          give a conservative answer in case we cannot prove that
3565*e4b17023SJohn Marino 	 no dependence exists when analyzing another subscript.  */
3566*e4b17023SJohn Marino       if (CF_NOT_KNOWN_P (overlaps_a)
3567*e4b17023SJohn Marino  	  || CF_NOT_KNOWN_P (overlaps_b))
3568*e4b17023SJohn Marino  	{
3569*e4b17023SJohn Marino 	  res = chrec_dont_know;
3570*e4b17023SJohn Marino 	  continue;
3571*e4b17023SJohn Marino  	}
3572*e4b17023SJohn Marino 
3573*e4b17023SJohn Marino       /* When there is a subscript with no dependence we can stop.  */
3574*e4b17023SJohn Marino       else if (CF_NO_DEPENDENCE_P (overlaps_a)
3575*e4b17023SJohn Marino  	       || CF_NO_DEPENDENCE_P (overlaps_b))
3576*e4b17023SJohn Marino  	{
3577*e4b17023SJohn Marino 	  res = chrec_known;
3578*e4b17023SJohn Marino 	  break;
3579*e4b17023SJohn Marino  	}
3580*e4b17023SJohn Marino     }
3581*e4b17023SJohn Marino 
3582*e4b17023SJohn Marino   if (res == NULL_TREE)
3583*e4b17023SJohn Marino     return true;
3584*e4b17023SJohn Marino 
3585*e4b17023SJohn Marino   if (res == chrec_known)
3586*e4b17023SJohn Marino     dependence_stats.num_dependence_independent++;
3587*e4b17023SJohn Marino   else
3588*e4b17023SJohn Marino     dependence_stats.num_dependence_undetermined++;
3589*e4b17023SJohn Marino   finalize_ddr_dependent (ddr, res);
3590*e4b17023SJohn Marino   return false;
3591*e4b17023SJohn Marino }
3592*e4b17023SJohn Marino 
3593*e4b17023SJohn Marino /* Computes the conflicting iterations in LOOP_NEST, and initialize DDR.  */
3594*e4b17023SJohn Marino 
3595*e4b17023SJohn Marino static void
subscript_dependence_tester(struct data_dependence_relation * ddr,struct loop * loop_nest)3596*e4b17023SJohn Marino subscript_dependence_tester (struct data_dependence_relation *ddr,
3597*e4b17023SJohn Marino 			     struct loop *loop_nest)
3598*e4b17023SJohn Marino {
3599*e4b17023SJohn Marino 
3600*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
3601*e4b17023SJohn Marino     fprintf (dump_file, "(subscript_dependence_tester \n");
3602*e4b17023SJohn Marino 
3603*e4b17023SJohn Marino   if (subscript_dependence_tester_1 (ddr, DDR_A (ddr), DDR_B (ddr), loop_nest))
3604*e4b17023SJohn Marino     dependence_stats.num_dependence_dependent++;
3605*e4b17023SJohn Marino 
3606*e4b17023SJohn Marino   compute_subscript_distance (ddr);
3607*e4b17023SJohn Marino   if (build_classic_dist_vector (ddr, loop_nest))
3608*e4b17023SJohn Marino     build_classic_dir_vector (ddr);
3609*e4b17023SJohn Marino 
3610*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
3611*e4b17023SJohn Marino     fprintf (dump_file, ")\n");
3612*e4b17023SJohn Marino }
3613*e4b17023SJohn Marino 
3614*e4b17023SJohn Marino /* Returns true when all the access functions of A are affine or
3615*e4b17023SJohn Marino    constant with respect to LOOP_NEST.  */
3616*e4b17023SJohn Marino 
3617*e4b17023SJohn Marino static bool
access_functions_are_affine_or_constant_p(const struct data_reference * a,const struct loop * loop_nest)3618*e4b17023SJohn Marino access_functions_are_affine_or_constant_p (const struct data_reference *a,
3619*e4b17023SJohn Marino 					   const struct loop *loop_nest)
3620*e4b17023SJohn Marino {
3621*e4b17023SJohn Marino   unsigned int i;
3622*e4b17023SJohn Marino   VEC(tree,heap) *fns = DR_ACCESS_FNS (a);
3623*e4b17023SJohn Marino   tree t;
3624*e4b17023SJohn Marino 
3625*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (tree, fns, i, t)
3626*e4b17023SJohn Marino     if (!evolution_function_is_invariant_p (t, loop_nest->num)
3627*e4b17023SJohn Marino 	&& !evolution_function_is_affine_multivariate_p (t, loop_nest->num))
3628*e4b17023SJohn Marino       return false;
3629*e4b17023SJohn Marino 
3630*e4b17023SJohn Marino   return true;
3631*e4b17023SJohn Marino }
3632*e4b17023SJohn Marino 
3633*e4b17023SJohn Marino /* Initializes an equation for an OMEGA problem using the information
3634*e4b17023SJohn Marino    contained in the ACCESS_FUN.  Returns true when the operation
3635*e4b17023SJohn Marino    succeeded.
3636*e4b17023SJohn Marino 
3637*e4b17023SJohn Marino    PB is the omega constraint system.
3638*e4b17023SJohn Marino    EQ is the number of the equation to be initialized.
3639*e4b17023SJohn Marino    OFFSET is used for shifting the variables names in the constraints:
3640*e4b17023SJohn Marino    a constrain is composed of 2 * the number of variables surrounding
3641*e4b17023SJohn Marino    dependence accesses.  OFFSET is set either to 0 for the first n variables,
3642*e4b17023SJohn Marino    then it is set to n.
3643*e4b17023SJohn Marino    ACCESS_FUN is expected to be an affine chrec.  */
3644*e4b17023SJohn Marino 
3645*e4b17023SJohn Marino static bool
init_omega_eq_with_af(omega_pb pb,unsigned eq,unsigned int offset,tree access_fun,struct data_dependence_relation * ddr)3646*e4b17023SJohn Marino init_omega_eq_with_af (omega_pb pb, unsigned eq,
3647*e4b17023SJohn Marino 		       unsigned int offset, tree access_fun,
3648*e4b17023SJohn Marino 		       struct data_dependence_relation *ddr)
3649*e4b17023SJohn Marino {
3650*e4b17023SJohn Marino   switch (TREE_CODE (access_fun))
3651*e4b17023SJohn Marino     {
3652*e4b17023SJohn Marino     case POLYNOMIAL_CHREC:
3653*e4b17023SJohn Marino       {
3654*e4b17023SJohn Marino 	tree left = CHREC_LEFT (access_fun);
3655*e4b17023SJohn Marino 	tree right = CHREC_RIGHT (access_fun);
3656*e4b17023SJohn Marino 	int var = CHREC_VARIABLE (access_fun);
3657*e4b17023SJohn Marino 	unsigned var_idx;
3658*e4b17023SJohn Marino 
3659*e4b17023SJohn Marino 	if (TREE_CODE (right) != INTEGER_CST)
3660*e4b17023SJohn Marino 	  return false;
3661*e4b17023SJohn Marino 
3662*e4b17023SJohn Marino 	var_idx = index_in_loop_nest (var, DDR_LOOP_NEST (ddr));
3663*e4b17023SJohn Marino 	pb->eqs[eq].coef[offset + var_idx + 1] = int_cst_value (right);
3664*e4b17023SJohn Marino 
3665*e4b17023SJohn Marino 	/* Compute the innermost loop index.  */
3666*e4b17023SJohn Marino 	DDR_INNER_LOOP (ddr) = MAX (DDR_INNER_LOOP (ddr), var_idx);
3667*e4b17023SJohn Marino 
3668*e4b17023SJohn Marino 	if (offset == 0)
3669*e4b17023SJohn Marino 	  pb->eqs[eq].coef[var_idx + DDR_NB_LOOPS (ddr) + 1]
3670*e4b17023SJohn Marino 	    += int_cst_value (right);
3671*e4b17023SJohn Marino 
3672*e4b17023SJohn Marino 	switch (TREE_CODE (left))
3673*e4b17023SJohn Marino 	  {
3674*e4b17023SJohn Marino 	  case POLYNOMIAL_CHREC:
3675*e4b17023SJohn Marino 	    return init_omega_eq_with_af (pb, eq, offset, left, ddr);
3676*e4b17023SJohn Marino 
3677*e4b17023SJohn Marino 	  case INTEGER_CST:
3678*e4b17023SJohn Marino 	    pb->eqs[eq].coef[0] += int_cst_value (left);
3679*e4b17023SJohn Marino 	    return true;
3680*e4b17023SJohn Marino 
3681*e4b17023SJohn Marino 	  default:
3682*e4b17023SJohn Marino 	    return false;
3683*e4b17023SJohn Marino 	  }
3684*e4b17023SJohn Marino       }
3685*e4b17023SJohn Marino 
3686*e4b17023SJohn Marino     case INTEGER_CST:
3687*e4b17023SJohn Marino       pb->eqs[eq].coef[0] += int_cst_value (access_fun);
3688*e4b17023SJohn Marino       return true;
3689*e4b17023SJohn Marino 
3690*e4b17023SJohn Marino     default:
3691*e4b17023SJohn Marino       return false;
3692*e4b17023SJohn Marino     }
3693*e4b17023SJohn Marino }
3694*e4b17023SJohn Marino 
3695*e4b17023SJohn Marino /* As explained in the comments preceding init_omega_for_ddr, we have
3696*e4b17023SJohn Marino    to set up a system for each loop level, setting outer loops
3697*e4b17023SJohn Marino    variation to zero, and current loop variation to positive or zero.
3698*e4b17023SJohn Marino    Save each lexico positive distance vector.  */
3699*e4b17023SJohn Marino 
3700*e4b17023SJohn Marino static void
omega_extract_distance_vectors(omega_pb pb,struct data_dependence_relation * ddr)3701*e4b17023SJohn Marino omega_extract_distance_vectors (omega_pb pb,
3702*e4b17023SJohn Marino 				struct data_dependence_relation *ddr)
3703*e4b17023SJohn Marino {
3704*e4b17023SJohn Marino   int eq, geq;
3705*e4b17023SJohn Marino   unsigned i, j;
3706*e4b17023SJohn Marino   struct loop *loopi, *loopj;
3707*e4b17023SJohn Marino   enum omega_result res;
3708*e4b17023SJohn Marino 
3709*e4b17023SJohn Marino   /* Set a new problem for each loop in the nest.  The basis is the
3710*e4b17023SJohn Marino      problem that we have initialized until now.  On top of this we
3711*e4b17023SJohn Marino      add new constraints.  */
3712*e4b17023SJohn Marino   for (i = 0; i <= DDR_INNER_LOOP (ddr)
3713*e4b17023SJohn Marino 	 && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
3714*e4b17023SJohn Marino     {
3715*e4b17023SJohn Marino       int dist = 0;
3716*e4b17023SJohn Marino       omega_pb copy = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr),
3717*e4b17023SJohn Marino 					   DDR_NB_LOOPS (ddr));
3718*e4b17023SJohn Marino 
3719*e4b17023SJohn Marino       omega_copy_problem (copy, pb);
3720*e4b17023SJohn Marino 
3721*e4b17023SJohn Marino       /* For all the outer loops "loop_j", add "dj = 0".  */
3722*e4b17023SJohn Marino       for (j = 0;
3723*e4b17023SJohn Marino 	   j < i && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), j, loopj); j++)
3724*e4b17023SJohn Marino 	{
3725*e4b17023SJohn Marino 	  eq = omega_add_zero_eq (copy, omega_black);
3726*e4b17023SJohn Marino 	  copy->eqs[eq].coef[j + 1] = 1;
3727*e4b17023SJohn Marino 	}
3728*e4b17023SJohn Marino 
3729*e4b17023SJohn Marino       /* For "loop_i", add "0 <= di".  */
3730*e4b17023SJohn Marino       geq = omega_add_zero_geq (copy, omega_black);
3731*e4b17023SJohn Marino       copy->geqs[geq].coef[i + 1] = 1;
3732*e4b17023SJohn Marino 
3733*e4b17023SJohn Marino       /* Reduce the constraint system, and test that the current
3734*e4b17023SJohn Marino 	 problem is feasible.  */
3735*e4b17023SJohn Marino       res = omega_simplify_problem (copy);
3736*e4b17023SJohn Marino       if (res == omega_false
3737*e4b17023SJohn Marino 	  || res == omega_unknown
3738*e4b17023SJohn Marino 	  || copy->num_geqs > (int) DDR_NB_LOOPS (ddr))
3739*e4b17023SJohn Marino 	goto next_problem;
3740*e4b17023SJohn Marino 
3741*e4b17023SJohn Marino       for (eq = 0; eq < copy->num_subs; eq++)
3742*e4b17023SJohn Marino 	if (copy->subs[eq].key == (int) i + 1)
3743*e4b17023SJohn Marino 	  {
3744*e4b17023SJohn Marino 	    dist = copy->subs[eq].coef[0];
3745*e4b17023SJohn Marino 	    goto found_dist;
3746*e4b17023SJohn Marino 	  }
3747*e4b17023SJohn Marino 
3748*e4b17023SJohn Marino       if (dist == 0)
3749*e4b17023SJohn Marino 	{
3750*e4b17023SJohn Marino 	  /* Reinitialize problem...  */
3751*e4b17023SJohn Marino 	  omega_copy_problem (copy, pb);
3752*e4b17023SJohn Marino 	  for (j = 0;
3753*e4b17023SJohn Marino 	       j < i && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), j, loopj); j++)
3754*e4b17023SJohn Marino 	    {
3755*e4b17023SJohn Marino 	      eq = omega_add_zero_eq (copy, omega_black);
3756*e4b17023SJohn Marino 	      copy->eqs[eq].coef[j + 1] = 1;
3757*e4b17023SJohn Marino 	    }
3758*e4b17023SJohn Marino 
3759*e4b17023SJohn Marino 	  /* ..., but this time "di = 1".  */
3760*e4b17023SJohn Marino 	  eq = omega_add_zero_eq (copy, omega_black);
3761*e4b17023SJohn Marino 	  copy->eqs[eq].coef[i + 1] = 1;
3762*e4b17023SJohn Marino 	  copy->eqs[eq].coef[0] = -1;
3763*e4b17023SJohn Marino 
3764*e4b17023SJohn Marino 	  res = omega_simplify_problem (copy);
3765*e4b17023SJohn Marino 	  if (res == omega_false
3766*e4b17023SJohn Marino 	      || res == omega_unknown
3767*e4b17023SJohn Marino 	      || copy->num_geqs > (int) DDR_NB_LOOPS (ddr))
3768*e4b17023SJohn Marino 	    goto next_problem;
3769*e4b17023SJohn Marino 
3770*e4b17023SJohn Marino 	  for (eq = 0; eq < copy->num_subs; eq++)
3771*e4b17023SJohn Marino 	    if (copy->subs[eq].key == (int) i + 1)
3772*e4b17023SJohn Marino 	      {
3773*e4b17023SJohn Marino 		dist = copy->subs[eq].coef[0];
3774*e4b17023SJohn Marino 		goto found_dist;
3775*e4b17023SJohn Marino 	      }
3776*e4b17023SJohn Marino 	}
3777*e4b17023SJohn Marino 
3778*e4b17023SJohn Marino     found_dist:;
3779*e4b17023SJohn Marino       /* Save the lexicographically positive distance vector.  */
3780*e4b17023SJohn Marino       if (dist >= 0)
3781*e4b17023SJohn Marino 	{
3782*e4b17023SJohn Marino 	  lambda_vector dist_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3783*e4b17023SJohn Marino 	  lambda_vector dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
3784*e4b17023SJohn Marino 
3785*e4b17023SJohn Marino 	  dist_v[i] = dist;
3786*e4b17023SJohn Marino 
3787*e4b17023SJohn Marino 	  for (eq = 0; eq < copy->num_subs; eq++)
3788*e4b17023SJohn Marino 	    if (copy->subs[eq].key > 0)
3789*e4b17023SJohn Marino 	      {
3790*e4b17023SJohn Marino 		dist = copy->subs[eq].coef[0];
3791*e4b17023SJohn Marino 		dist_v[copy->subs[eq].key - 1] = dist;
3792*e4b17023SJohn Marino 	      }
3793*e4b17023SJohn Marino 
3794*e4b17023SJohn Marino 	  for (j = 0; j < DDR_NB_LOOPS (ddr); j++)
3795*e4b17023SJohn Marino 	    dir_v[j] = dir_from_dist (dist_v[j]);
3796*e4b17023SJohn Marino 
3797*e4b17023SJohn Marino 	  save_dist_v (ddr, dist_v);
3798*e4b17023SJohn Marino 	  save_dir_v (ddr, dir_v);
3799*e4b17023SJohn Marino 	}
3800*e4b17023SJohn Marino 
3801*e4b17023SJohn Marino     next_problem:;
3802*e4b17023SJohn Marino       omega_free_problem (copy);
3803*e4b17023SJohn Marino     }
3804*e4b17023SJohn Marino }
3805*e4b17023SJohn Marino 
3806*e4b17023SJohn Marino /* This is called for each subscript of a tuple of data references:
3807*e4b17023SJohn Marino    insert an equality for representing the conflicts.  */
3808*e4b17023SJohn Marino 
3809*e4b17023SJohn Marino static bool
omega_setup_subscript(tree access_fun_a,tree access_fun_b,struct data_dependence_relation * ddr,omega_pb pb,bool * maybe_dependent)3810*e4b17023SJohn Marino omega_setup_subscript (tree access_fun_a, tree access_fun_b,
3811*e4b17023SJohn Marino 		       struct data_dependence_relation *ddr,
3812*e4b17023SJohn Marino 		       omega_pb pb, bool *maybe_dependent)
3813*e4b17023SJohn Marino {
3814*e4b17023SJohn Marino   int eq;
3815*e4b17023SJohn Marino   tree type = signed_type_for_types (TREE_TYPE (access_fun_a),
3816*e4b17023SJohn Marino 				     TREE_TYPE (access_fun_b));
3817*e4b17023SJohn Marino   tree fun_a = chrec_convert (type, access_fun_a, NULL);
3818*e4b17023SJohn Marino   tree fun_b = chrec_convert (type, access_fun_b, NULL);
3819*e4b17023SJohn Marino   tree difference = chrec_fold_minus (type, fun_a, fun_b);
3820*e4b17023SJohn Marino   tree minus_one;
3821*e4b17023SJohn Marino 
3822*e4b17023SJohn Marino   /* When the fun_a - fun_b is not constant, the dependence is not
3823*e4b17023SJohn Marino      captured by the classic distance vector representation.  */
3824*e4b17023SJohn Marino   if (TREE_CODE (difference) != INTEGER_CST)
3825*e4b17023SJohn Marino     return false;
3826*e4b17023SJohn Marino 
3827*e4b17023SJohn Marino   /* ZIV test.  */
3828*e4b17023SJohn Marino   if (ziv_subscript_p (fun_a, fun_b) && !integer_zerop (difference))
3829*e4b17023SJohn Marino     {
3830*e4b17023SJohn Marino       /* There is no dependence.  */
3831*e4b17023SJohn Marino       *maybe_dependent = false;
3832*e4b17023SJohn Marino       return true;
3833*e4b17023SJohn Marino     }
3834*e4b17023SJohn Marino 
3835*e4b17023SJohn Marino   minus_one = build_int_cst (type, -1);
3836*e4b17023SJohn Marino   fun_b = chrec_fold_multiply (type, fun_b, minus_one);
3837*e4b17023SJohn Marino 
3838*e4b17023SJohn Marino   eq = omega_add_zero_eq (pb, omega_black);
3839*e4b17023SJohn Marino   if (!init_omega_eq_with_af (pb, eq, DDR_NB_LOOPS (ddr), fun_a, ddr)
3840*e4b17023SJohn Marino       || !init_omega_eq_with_af (pb, eq, 0, fun_b, ddr))
3841*e4b17023SJohn Marino     /* There is probably a dependence, but the system of
3842*e4b17023SJohn Marino        constraints cannot be built: answer "don't know".  */
3843*e4b17023SJohn Marino     return false;
3844*e4b17023SJohn Marino 
3845*e4b17023SJohn Marino   /* GCD test.  */
3846*e4b17023SJohn Marino   if (DDR_NB_LOOPS (ddr) != 0 && pb->eqs[eq].coef[0]
3847*e4b17023SJohn Marino       && !int_divides_p (lambda_vector_gcd
3848*e4b17023SJohn Marino 			 ((lambda_vector) &(pb->eqs[eq].coef[1]),
3849*e4b17023SJohn Marino 			  2 * DDR_NB_LOOPS (ddr)),
3850*e4b17023SJohn Marino 			 pb->eqs[eq].coef[0]))
3851*e4b17023SJohn Marino     {
3852*e4b17023SJohn Marino       /* There is no dependence.  */
3853*e4b17023SJohn Marino       *maybe_dependent = false;
3854*e4b17023SJohn Marino       return true;
3855*e4b17023SJohn Marino     }
3856*e4b17023SJohn Marino 
3857*e4b17023SJohn Marino   return true;
3858*e4b17023SJohn Marino }
3859*e4b17023SJohn Marino 
3860*e4b17023SJohn Marino /* Helper function, same as init_omega_for_ddr but specialized for
3861*e4b17023SJohn Marino    data references A and B.  */
3862*e4b17023SJohn Marino 
3863*e4b17023SJohn Marino static bool
init_omega_for_ddr_1(struct data_reference * dra,struct data_reference * drb,struct data_dependence_relation * ddr,omega_pb pb,bool * maybe_dependent)3864*e4b17023SJohn Marino init_omega_for_ddr_1 (struct data_reference *dra, struct data_reference *drb,
3865*e4b17023SJohn Marino 		      struct data_dependence_relation *ddr,
3866*e4b17023SJohn Marino 		      omega_pb pb, bool *maybe_dependent)
3867*e4b17023SJohn Marino {
3868*e4b17023SJohn Marino   unsigned i;
3869*e4b17023SJohn Marino   int ineq;
3870*e4b17023SJohn Marino   struct loop *loopi;
3871*e4b17023SJohn Marino   unsigned nb_loops = DDR_NB_LOOPS (ddr);
3872*e4b17023SJohn Marino 
3873*e4b17023SJohn Marino   /* Insert an equality per subscript.  */
3874*e4b17023SJohn Marino   for (i = 0; i < DDR_NUM_SUBSCRIPTS (ddr); i++)
3875*e4b17023SJohn Marino     {
3876*e4b17023SJohn Marino       if (!omega_setup_subscript (DR_ACCESS_FN (dra, i), DR_ACCESS_FN (drb, i),
3877*e4b17023SJohn Marino 				  ddr, pb, maybe_dependent))
3878*e4b17023SJohn Marino 	return false;
3879*e4b17023SJohn Marino       else if (*maybe_dependent == false)
3880*e4b17023SJohn Marino 	{
3881*e4b17023SJohn Marino 	  /* There is no dependence.  */
3882*e4b17023SJohn Marino 	  DDR_ARE_DEPENDENT (ddr) = chrec_known;
3883*e4b17023SJohn Marino 	  return true;
3884*e4b17023SJohn Marino 	}
3885*e4b17023SJohn Marino     }
3886*e4b17023SJohn Marino 
3887*e4b17023SJohn Marino   /* Insert inequalities: constraints corresponding to the iteration
3888*e4b17023SJohn Marino      domain, i.e. the loops surrounding the references "loop_x" and
3889*e4b17023SJohn Marino      the distance variables "dx".  The layout of the OMEGA
3890*e4b17023SJohn Marino      representation is as follows:
3891*e4b17023SJohn Marino      - coef[0] is the constant
3892*e4b17023SJohn Marino      - coef[1..nb_loops] are the protected variables that will not be
3893*e4b17023SJohn Marino      removed by the solver: the "dx"
3894*e4b17023SJohn Marino      - coef[nb_loops + 1, 2*nb_loops] are the loop variables: "loop_x".
3895*e4b17023SJohn Marino   */
3896*e4b17023SJohn Marino   for (i = 0; i <= DDR_INNER_LOOP (ddr)
3897*e4b17023SJohn Marino 	 && VEC_iterate (loop_p, DDR_LOOP_NEST (ddr), i, loopi); i++)
3898*e4b17023SJohn Marino     {
3899*e4b17023SJohn Marino       HOST_WIDE_INT nbi = max_stmt_executions_int (loopi, true);
3900*e4b17023SJohn Marino 
3901*e4b17023SJohn Marino       /* 0 <= loop_x */
3902*e4b17023SJohn Marino       ineq = omega_add_zero_geq (pb, omega_black);
3903*e4b17023SJohn Marino       pb->geqs[ineq].coef[i + nb_loops + 1] = 1;
3904*e4b17023SJohn Marino 
3905*e4b17023SJohn Marino       /* 0 <= loop_x + dx */
3906*e4b17023SJohn Marino       ineq = omega_add_zero_geq (pb, omega_black);
3907*e4b17023SJohn Marino       pb->geqs[ineq].coef[i + nb_loops + 1] = 1;
3908*e4b17023SJohn Marino       pb->geqs[ineq].coef[i + 1] = 1;
3909*e4b17023SJohn Marino 
3910*e4b17023SJohn Marino       if (nbi != -1)
3911*e4b17023SJohn Marino 	{
3912*e4b17023SJohn Marino 	  /* loop_x <= nb_iters */
3913*e4b17023SJohn Marino 	  ineq = omega_add_zero_geq (pb, omega_black);
3914*e4b17023SJohn Marino 	  pb->geqs[ineq].coef[i + nb_loops + 1] = -1;
3915*e4b17023SJohn Marino 	  pb->geqs[ineq].coef[0] = nbi;
3916*e4b17023SJohn Marino 
3917*e4b17023SJohn Marino 	  /* loop_x + dx <= nb_iters */
3918*e4b17023SJohn Marino 	  ineq = omega_add_zero_geq (pb, omega_black);
3919*e4b17023SJohn Marino 	  pb->geqs[ineq].coef[i + nb_loops + 1] = -1;
3920*e4b17023SJohn Marino 	  pb->geqs[ineq].coef[i + 1] = -1;
3921*e4b17023SJohn Marino 	  pb->geqs[ineq].coef[0] = nbi;
3922*e4b17023SJohn Marino 
3923*e4b17023SJohn Marino 	  /* A step "dx" bigger than nb_iters is not feasible, so
3924*e4b17023SJohn Marino 	     add "0 <= nb_iters + dx",  */
3925*e4b17023SJohn Marino 	  ineq = omega_add_zero_geq (pb, omega_black);
3926*e4b17023SJohn Marino 	  pb->geqs[ineq].coef[i + 1] = 1;
3927*e4b17023SJohn Marino 	  pb->geqs[ineq].coef[0] = nbi;
3928*e4b17023SJohn Marino 	  /* and "dx <= nb_iters".  */
3929*e4b17023SJohn Marino 	  ineq = omega_add_zero_geq (pb, omega_black);
3930*e4b17023SJohn Marino 	  pb->geqs[ineq].coef[i + 1] = -1;
3931*e4b17023SJohn Marino 	  pb->geqs[ineq].coef[0] = nbi;
3932*e4b17023SJohn Marino 	}
3933*e4b17023SJohn Marino     }
3934*e4b17023SJohn Marino 
3935*e4b17023SJohn Marino   omega_extract_distance_vectors (pb, ddr);
3936*e4b17023SJohn Marino 
3937*e4b17023SJohn Marino   return true;
3938*e4b17023SJohn Marino }
3939*e4b17023SJohn Marino 
3940*e4b17023SJohn Marino /* Sets up the Omega dependence problem for the data dependence
3941*e4b17023SJohn Marino    relation DDR.  Returns false when the constraint system cannot be
3942*e4b17023SJohn Marino    built, ie. when the test answers "don't know".  Returns true
3943*e4b17023SJohn Marino    otherwise, and when independence has been proved (using one of the
3944*e4b17023SJohn Marino    trivial dependence test), set MAYBE_DEPENDENT to false, otherwise
3945*e4b17023SJohn Marino    set MAYBE_DEPENDENT to true.
3946*e4b17023SJohn Marino 
3947*e4b17023SJohn Marino    Example: for setting up the dependence system corresponding to the
3948*e4b17023SJohn Marino    conflicting accesses
3949*e4b17023SJohn Marino 
3950*e4b17023SJohn Marino    | loop_i
3951*e4b17023SJohn Marino    |   loop_j
3952*e4b17023SJohn Marino    |     A[i, i+1] = ...
3953*e4b17023SJohn Marino    |     ... A[2*j, 2*(i + j)]
3954*e4b17023SJohn Marino    |   endloop_j
3955*e4b17023SJohn Marino    | endloop_i
3956*e4b17023SJohn Marino 
3957*e4b17023SJohn Marino    the following constraints come from the iteration domain:
3958*e4b17023SJohn Marino 
3959*e4b17023SJohn Marino    0 <= i <= Ni
3960*e4b17023SJohn Marino    0 <= i + di <= Ni
3961*e4b17023SJohn Marino    0 <= j <= Nj
3962*e4b17023SJohn Marino    0 <= j + dj <= Nj
3963*e4b17023SJohn Marino 
3964*e4b17023SJohn Marino    where di, dj are the distance variables.  The constraints
3965*e4b17023SJohn Marino    representing the conflicting elements are:
3966*e4b17023SJohn Marino 
3967*e4b17023SJohn Marino    i = 2 * (j + dj)
3968*e4b17023SJohn Marino    i + 1 = 2 * (i + di + j + dj)
3969*e4b17023SJohn Marino 
3970*e4b17023SJohn Marino    For asking that the resulting distance vector (di, dj) be
3971*e4b17023SJohn Marino    lexicographically positive, we insert the constraint "di >= 0".  If
3972*e4b17023SJohn Marino    "di = 0" in the solution, we fix that component to zero, and we
3973*e4b17023SJohn Marino    look at the inner loops: we set a new problem where all the outer
3974*e4b17023SJohn Marino    loop distances are zero, and fix this inner component to be
3975*e4b17023SJohn Marino    positive.  When one of the components is positive, we save that
3976*e4b17023SJohn Marino    distance, and set a new problem where the distance on this loop is
3977*e4b17023SJohn Marino    zero, searching for other distances in the inner loops.  Here is
3978*e4b17023SJohn Marino    the classic example that illustrates that we have to set for each
3979*e4b17023SJohn Marino    inner loop a new problem:
3980*e4b17023SJohn Marino 
3981*e4b17023SJohn Marino    | loop_1
3982*e4b17023SJohn Marino    |   loop_2
3983*e4b17023SJohn Marino    |     A[10]
3984*e4b17023SJohn Marino    |   endloop_2
3985*e4b17023SJohn Marino    | endloop_1
3986*e4b17023SJohn Marino 
3987*e4b17023SJohn Marino    we have to save two distances (1, 0) and (0, 1).
3988*e4b17023SJohn Marino 
3989*e4b17023SJohn Marino    Given two array references, refA and refB, we have to set the
3990*e4b17023SJohn Marino    dependence problem twice, refA vs. refB and refB vs. refA, and we
3991*e4b17023SJohn Marino    cannot do a single test, as refB might occur before refA in the
3992*e4b17023SJohn Marino    inner loops, and the contrary when considering outer loops: ex.
3993*e4b17023SJohn Marino 
3994*e4b17023SJohn Marino    | loop_0
3995*e4b17023SJohn Marino    |   loop_1
3996*e4b17023SJohn Marino    |     loop_2
3997*e4b17023SJohn Marino    |       T[{1,+,1}_2][{1,+,1}_1]  // refA
3998*e4b17023SJohn Marino    |       T[{2,+,1}_2][{0,+,1}_1]  // refB
3999*e4b17023SJohn Marino    |     endloop_2
4000*e4b17023SJohn Marino    |   endloop_1
4001*e4b17023SJohn Marino    | endloop_0
4002*e4b17023SJohn Marino 
4003*e4b17023SJohn Marino    refB touches the elements in T before refA, and thus for the same
4004*e4b17023SJohn Marino    loop_0 refB precedes refA: ie. the distance vector (0, 1, -1)
4005*e4b17023SJohn Marino    but for successive loop_0 iterations, we have (1, -1, 1)
4006*e4b17023SJohn Marino 
4007*e4b17023SJohn Marino    The Omega solver expects the distance variables ("di" in the
4008*e4b17023SJohn Marino    previous example) to come first in the constraint system (as
4009*e4b17023SJohn Marino    variables to be protected, or "safe" variables), the constraint
4010*e4b17023SJohn Marino    system is built using the following layout:
4011*e4b17023SJohn Marino 
4012*e4b17023SJohn Marino    "cst | distance vars | index vars".
4013*e4b17023SJohn Marino */
4014*e4b17023SJohn Marino 
4015*e4b17023SJohn Marino static bool
init_omega_for_ddr(struct data_dependence_relation * ddr,bool * maybe_dependent)4016*e4b17023SJohn Marino init_omega_for_ddr (struct data_dependence_relation *ddr,
4017*e4b17023SJohn Marino 		    bool *maybe_dependent)
4018*e4b17023SJohn Marino {
4019*e4b17023SJohn Marino   omega_pb pb;
4020*e4b17023SJohn Marino   bool res = false;
4021*e4b17023SJohn Marino 
4022*e4b17023SJohn Marino   *maybe_dependent = true;
4023*e4b17023SJohn Marino 
4024*e4b17023SJohn Marino   if (same_access_functions (ddr))
4025*e4b17023SJohn Marino     {
4026*e4b17023SJohn Marino       unsigned j;
4027*e4b17023SJohn Marino       lambda_vector dir_v;
4028*e4b17023SJohn Marino 
4029*e4b17023SJohn Marino       /* Save the 0 vector.  */
4030*e4b17023SJohn Marino       save_dist_v (ddr, lambda_vector_new (DDR_NB_LOOPS (ddr)));
4031*e4b17023SJohn Marino       dir_v = lambda_vector_new (DDR_NB_LOOPS (ddr));
4032*e4b17023SJohn Marino       for (j = 0; j < DDR_NB_LOOPS (ddr); j++)
4033*e4b17023SJohn Marino 	dir_v[j] = dir_equal;
4034*e4b17023SJohn Marino       save_dir_v (ddr, dir_v);
4035*e4b17023SJohn Marino 
4036*e4b17023SJohn Marino       /* Save the dependences carried by outer loops.  */
4037*e4b17023SJohn Marino       pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
4038*e4b17023SJohn Marino       res = init_omega_for_ddr_1 (DDR_A (ddr), DDR_B (ddr), ddr, pb,
4039*e4b17023SJohn Marino 				  maybe_dependent);
4040*e4b17023SJohn Marino       omega_free_problem (pb);
4041*e4b17023SJohn Marino       return res;
4042*e4b17023SJohn Marino     }
4043*e4b17023SJohn Marino 
4044*e4b17023SJohn Marino   /* Omega expects the protected variables (those that have to be kept
4045*e4b17023SJohn Marino      after elimination) to appear first in the constraint system.
4046*e4b17023SJohn Marino      These variables are the distance variables.  In the following
4047*e4b17023SJohn Marino      initialization we declare NB_LOOPS safe variables, and the total
4048*e4b17023SJohn Marino      number of variables for the constraint system is 2*NB_LOOPS.  */
4049*e4b17023SJohn Marino   pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
4050*e4b17023SJohn Marino   res = init_omega_for_ddr_1 (DDR_A (ddr), DDR_B (ddr), ddr, pb,
4051*e4b17023SJohn Marino 			      maybe_dependent);
4052*e4b17023SJohn Marino   omega_free_problem (pb);
4053*e4b17023SJohn Marino 
4054*e4b17023SJohn Marino   /* Stop computation if not decidable, or no dependence.  */
4055*e4b17023SJohn Marino   if (res == false || *maybe_dependent == false)
4056*e4b17023SJohn Marino     return res;
4057*e4b17023SJohn Marino 
4058*e4b17023SJohn Marino   pb = omega_alloc_problem (2 * DDR_NB_LOOPS (ddr), DDR_NB_LOOPS (ddr));
4059*e4b17023SJohn Marino   res = init_omega_for_ddr_1 (DDR_B (ddr), DDR_A (ddr), ddr, pb,
4060*e4b17023SJohn Marino 			      maybe_dependent);
4061*e4b17023SJohn Marino   omega_free_problem (pb);
4062*e4b17023SJohn Marino 
4063*e4b17023SJohn Marino   return res;
4064*e4b17023SJohn Marino }
4065*e4b17023SJohn Marino 
4066*e4b17023SJohn Marino /* Return true when DDR contains the same information as that stored
4067*e4b17023SJohn Marino    in DIR_VECTS and in DIST_VECTS, return false otherwise.   */
4068*e4b17023SJohn Marino 
4069*e4b17023SJohn Marino static bool
ddr_consistent_p(FILE * file,struct data_dependence_relation * ddr,VEC (lambda_vector,heap)* dist_vects,VEC (lambda_vector,heap)* dir_vects)4070*e4b17023SJohn Marino ddr_consistent_p (FILE *file,
4071*e4b17023SJohn Marino 		  struct data_dependence_relation *ddr,
4072*e4b17023SJohn Marino 		  VEC (lambda_vector, heap) *dist_vects,
4073*e4b17023SJohn Marino 		  VEC (lambda_vector, heap) *dir_vects)
4074*e4b17023SJohn Marino {
4075*e4b17023SJohn Marino   unsigned int i, j;
4076*e4b17023SJohn Marino 
4077*e4b17023SJohn Marino   /* If dump_file is set, output there.  */
4078*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
4079*e4b17023SJohn Marino     file = dump_file;
4080*e4b17023SJohn Marino 
4081*e4b17023SJohn Marino   if (VEC_length (lambda_vector, dist_vects) != DDR_NUM_DIST_VECTS (ddr))
4082*e4b17023SJohn Marino     {
4083*e4b17023SJohn Marino       lambda_vector b_dist_v;
4084*e4b17023SJohn Marino       fprintf (file, "\n(Number of distance vectors differ: Banerjee has %d, Omega has %d.\n",
4085*e4b17023SJohn Marino 	       VEC_length (lambda_vector, dist_vects),
4086*e4b17023SJohn Marino 	       DDR_NUM_DIST_VECTS (ddr));
4087*e4b17023SJohn Marino 
4088*e4b17023SJohn Marino       fprintf (file, "Banerjee dist vectors:\n");
4089*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (lambda_vector, dist_vects, i, b_dist_v)
4090*e4b17023SJohn Marino 	print_lambda_vector (file, b_dist_v, DDR_NB_LOOPS (ddr));
4091*e4b17023SJohn Marino 
4092*e4b17023SJohn Marino       fprintf (file, "Omega dist vectors:\n");
4093*e4b17023SJohn Marino       for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
4094*e4b17023SJohn Marino 	print_lambda_vector (file, DDR_DIST_VECT (ddr, i), DDR_NB_LOOPS (ddr));
4095*e4b17023SJohn Marino 
4096*e4b17023SJohn Marino       fprintf (file, "data dependence relation:\n");
4097*e4b17023SJohn Marino       dump_data_dependence_relation (file, ddr);
4098*e4b17023SJohn Marino 
4099*e4b17023SJohn Marino       fprintf (file, ")\n");
4100*e4b17023SJohn Marino       return false;
4101*e4b17023SJohn Marino     }
4102*e4b17023SJohn Marino 
4103*e4b17023SJohn Marino   if (VEC_length (lambda_vector, dir_vects) != DDR_NUM_DIR_VECTS (ddr))
4104*e4b17023SJohn Marino     {
4105*e4b17023SJohn Marino       fprintf (file, "\n(Number of direction vectors differ: Banerjee has %d, Omega has %d.)\n",
4106*e4b17023SJohn Marino 	       VEC_length (lambda_vector, dir_vects),
4107*e4b17023SJohn Marino 	       DDR_NUM_DIR_VECTS (ddr));
4108*e4b17023SJohn Marino       return false;
4109*e4b17023SJohn Marino     }
4110*e4b17023SJohn Marino 
4111*e4b17023SJohn Marino   for (i = 0; i < DDR_NUM_DIST_VECTS (ddr); i++)
4112*e4b17023SJohn Marino     {
4113*e4b17023SJohn Marino       lambda_vector a_dist_v;
4114*e4b17023SJohn Marino       lambda_vector b_dist_v = DDR_DIST_VECT (ddr, i);
4115*e4b17023SJohn Marino 
4116*e4b17023SJohn Marino       /* Distance vectors are not ordered in the same way in the DDR
4117*e4b17023SJohn Marino 	 and in the DIST_VECTS: search for a matching vector.  */
4118*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (lambda_vector, dist_vects, j, a_dist_v)
4119*e4b17023SJohn Marino 	if (lambda_vector_equal (a_dist_v, b_dist_v, DDR_NB_LOOPS (ddr)))
4120*e4b17023SJohn Marino 	  break;
4121*e4b17023SJohn Marino 
4122*e4b17023SJohn Marino       if (j == VEC_length (lambda_vector, dist_vects))
4123*e4b17023SJohn Marino 	{
4124*e4b17023SJohn Marino 	  fprintf (file, "\n(Dist vectors from the first dependence analyzer:\n");
4125*e4b17023SJohn Marino 	  print_dist_vectors (file, dist_vects, DDR_NB_LOOPS (ddr));
4126*e4b17023SJohn Marino 	  fprintf (file, "not found in Omega dist vectors:\n");
4127*e4b17023SJohn Marino 	  print_dist_vectors (file, DDR_DIST_VECTS (ddr), DDR_NB_LOOPS (ddr));
4128*e4b17023SJohn Marino 	  fprintf (file, "data dependence relation:\n");
4129*e4b17023SJohn Marino 	  dump_data_dependence_relation (file, ddr);
4130*e4b17023SJohn Marino 	  fprintf (file, ")\n");
4131*e4b17023SJohn Marino 	}
4132*e4b17023SJohn Marino     }
4133*e4b17023SJohn Marino 
4134*e4b17023SJohn Marino   for (i = 0; i < DDR_NUM_DIR_VECTS (ddr); i++)
4135*e4b17023SJohn Marino     {
4136*e4b17023SJohn Marino       lambda_vector a_dir_v;
4137*e4b17023SJohn Marino       lambda_vector b_dir_v = DDR_DIR_VECT (ddr, i);
4138*e4b17023SJohn Marino 
4139*e4b17023SJohn Marino       /* Direction vectors are not ordered in the same way in the DDR
4140*e4b17023SJohn Marino 	 and in the DIR_VECTS: search for a matching vector.  */
4141*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (lambda_vector, dir_vects, j, a_dir_v)
4142*e4b17023SJohn Marino 	if (lambda_vector_equal (a_dir_v, b_dir_v, DDR_NB_LOOPS (ddr)))
4143*e4b17023SJohn Marino 	  break;
4144*e4b17023SJohn Marino 
4145*e4b17023SJohn Marino       if (j == VEC_length (lambda_vector, dist_vects))
4146*e4b17023SJohn Marino 	{
4147*e4b17023SJohn Marino 	  fprintf (file, "\n(Dir vectors from the first dependence analyzer:\n");
4148*e4b17023SJohn Marino 	  print_dir_vectors (file, dir_vects, DDR_NB_LOOPS (ddr));
4149*e4b17023SJohn Marino 	  fprintf (file, "not found in Omega dir vectors:\n");
4150*e4b17023SJohn Marino 	  print_dir_vectors (file, DDR_DIR_VECTS (ddr), DDR_NB_LOOPS (ddr));
4151*e4b17023SJohn Marino 	  fprintf (file, "data dependence relation:\n");
4152*e4b17023SJohn Marino 	  dump_data_dependence_relation (file, ddr);
4153*e4b17023SJohn Marino 	  fprintf (file, ")\n");
4154*e4b17023SJohn Marino 	}
4155*e4b17023SJohn Marino     }
4156*e4b17023SJohn Marino 
4157*e4b17023SJohn Marino   return true;
4158*e4b17023SJohn Marino }
4159*e4b17023SJohn Marino 
4160*e4b17023SJohn Marino /* This computes the affine dependence relation between A and B with
4161*e4b17023SJohn Marino    respect to LOOP_NEST.  CHREC_KNOWN is used for representing the
4162*e4b17023SJohn Marino    independence between two accesses, while CHREC_DONT_KNOW is used
4163*e4b17023SJohn Marino    for representing the unknown relation.
4164*e4b17023SJohn Marino 
4165*e4b17023SJohn Marino    Note that it is possible to stop the computation of the dependence
4166*e4b17023SJohn Marino    relation the first time we detect a CHREC_KNOWN element for a given
4167*e4b17023SJohn Marino    subscript.  */
4168*e4b17023SJohn Marino 
4169*e4b17023SJohn Marino static void
compute_affine_dependence(struct data_dependence_relation * ddr,struct loop * loop_nest)4170*e4b17023SJohn Marino compute_affine_dependence (struct data_dependence_relation *ddr,
4171*e4b17023SJohn Marino 			   struct loop *loop_nest)
4172*e4b17023SJohn Marino {
4173*e4b17023SJohn Marino   struct data_reference *dra = DDR_A (ddr);
4174*e4b17023SJohn Marino   struct data_reference *drb = DDR_B (ddr);
4175*e4b17023SJohn Marino 
4176*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
4177*e4b17023SJohn Marino     {
4178*e4b17023SJohn Marino       fprintf (dump_file, "(compute_affine_dependence\n");
4179*e4b17023SJohn Marino       fprintf (dump_file, "  stmt_a: ");
4180*e4b17023SJohn Marino       print_gimple_stmt (dump_file, DR_STMT (dra), 0, TDF_SLIM);
4181*e4b17023SJohn Marino       fprintf (dump_file, "  stmt_b: ");
4182*e4b17023SJohn Marino       print_gimple_stmt (dump_file, DR_STMT (drb), 0, TDF_SLIM);
4183*e4b17023SJohn Marino     }
4184*e4b17023SJohn Marino 
4185*e4b17023SJohn Marino   /* Analyze only when the dependence relation is not yet known.  */
4186*e4b17023SJohn Marino   if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
4187*e4b17023SJohn Marino     {
4188*e4b17023SJohn Marino       dependence_stats.num_dependence_tests++;
4189*e4b17023SJohn Marino 
4190*e4b17023SJohn Marino       if (access_functions_are_affine_or_constant_p (dra, loop_nest)
4191*e4b17023SJohn Marino 	  && access_functions_are_affine_or_constant_p (drb, loop_nest))
4192*e4b17023SJohn Marino 	{
4193*e4b17023SJohn Marino 	  if (flag_check_data_deps)
4194*e4b17023SJohn Marino 	    {
4195*e4b17023SJohn Marino 	      /* Compute the dependences using the first algorithm.  */
4196*e4b17023SJohn Marino 	      subscript_dependence_tester (ddr, loop_nest);
4197*e4b17023SJohn Marino 
4198*e4b17023SJohn Marino 	      if (dump_file && (dump_flags & TDF_DETAILS))
4199*e4b17023SJohn Marino 		{
4200*e4b17023SJohn Marino 		  fprintf (dump_file, "\n\nBanerjee Analyzer\n");
4201*e4b17023SJohn Marino 		  dump_data_dependence_relation (dump_file, ddr);
4202*e4b17023SJohn Marino 		}
4203*e4b17023SJohn Marino 
4204*e4b17023SJohn Marino 	      if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
4205*e4b17023SJohn Marino 		{
4206*e4b17023SJohn Marino 		  bool maybe_dependent;
4207*e4b17023SJohn Marino 		  VEC (lambda_vector, heap) *dir_vects, *dist_vects;
4208*e4b17023SJohn Marino 
4209*e4b17023SJohn Marino 		  /* Save the result of the first DD analyzer.  */
4210*e4b17023SJohn Marino 		  dist_vects = DDR_DIST_VECTS (ddr);
4211*e4b17023SJohn Marino 		  dir_vects = DDR_DIR_VECTS (ddr);
4212*e4b17023SJohn Marino 
4213*e4b17023SJohn Marino 		  /* Reset the information.  */
4214*e4b17023SJohn Marino 		  DDR_DIST_VECTS (ddr) = NULL;
4215*e4b17023SJohn Marino 		  DDR_DIR_VECTS (ddr) = NULL;
4216*e4b17023SJohn Marino 
4217*e4b17023SJohn Marino 		  /* Compute the same information using Omega.  */
4218*e4b17023SJohn Marino 		  if (!init_omega_for_ddr (ddr, &maybe_dependent))
4219*e4b17023SJohn Marino 		    goto csys_dont_know;
4220*e4b17023SJohn Marino 
4221*e4b17023SJohn Marino 		  if (dump_file && (dump_flags & TDF_DETAILS))
4222*e4b17023SJohn Marino 		    {
4223*e4b17023SJohn Marino 		      fprintf (dump_file, "Omega Analyzer\n");
4224*e4b17023SJohn Marino 		      dump_data_dependence_relation (dump_file, ddr);
4225*e4b17023SJohn Marino 		    }
4226*e4b17023SJohn Marino 
4227*e4b17023SJohn Marino 		  /* Check that we get the same information.  */
4228*e4b17023SJohn Marino 		  if (maybe_dependent)
4229*e4b17023SJohn Marino 		    gcc_assert (ddr_consistent_p (stderr, ddr, dist_vects,
4230*e4b17023SJohn Marino 						  dir_vects));
4231*e4b17023SJohn Marino 		}
4232*e4b17023SJohn Marino 	    }
4233*e4b17023SJohn Marino 	  else
4234*e4b17023SJohn Marino 	    subscript_dependence_tester (ddr, loop_nest);
4235*e4b17023SJohn Marino 	}
4236*e4b17023SJohn Marino 
4237*e4b17023SJohn Marino       /* As a last case, if the dependence cannot be determined, or if
4238*e4b17023SJohn Marino 	 the dependence is considered too difficult to determine, answer
4239*e4b17023SJohn Marino 	 "don't know".  */
4240*e4b17023SJohn Marino       else
4241*e4b17023SJohn Marino 	{
4242*e4b17023SJohn Marino 	csys_dont_know:;
4243*e4b17023SJohn Marino 	  dependence_stats.num_dependence_undetermined++;
4244*e4b17023SJohn Marino 
4245*e4b17023SJohn Marino 	  if (dump_file && (dump_flags & TDF_DETAILS))
4246*e4b17023SJohn Marino 	    {
4247*e4b17023SJohn Marino 	      fprintf (dump_file, "Data ref a:\n");
4248*e4b17023SJohn Marino 	      dump_data_reference (dump_file, dra);
4249*e4b17023SJohn Marino 	      fprintf (dump_file, "Data ref b:\n");
4250*e4b17023SJohn Marino 	      dump_data_reference (dump_file, drb);
4251*e4b17023SJohn Marino 	      fprintf (dump_file, "affine dependence test not usable: access function not affine or constant.\n");
4252*e4b17023SJohn Marino 	    }
4253*e4b17023SJohn Marino 	  finalize_ddr_dependent (ddr, chrec_dont_know);
4254*e4b17023SJohn Marino 	}
4255*e4b17023SJohn Marino     }
4256*e4b17023SJohn Marino 
4257*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_DETAILS))
4258*e4b17023SJohn Marino     {
4259*e4b17023SJohn Marino       if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
4260*e4b17023SJohn Marino 	fprintf (dump_file, ") -> no dependence\n");
4261*e4b17023SJohn Marino       else if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
4262*e4b17023SJohn Marino 	fprintf (dump_file, ") -> dependence analysis failed\n");
4263*e4b17023SJohn Marino       else
4264*e4b17023SJohn Marino 	fprintf (dump_file, ")\n");
4265*e4b17023SJohn Marino     }
4266*e4b17023SJohn Marino }
4267*e4b17023SJohn Marino 
4268*e4b17023SJohn Marino /* Compute in DEPENDENCE_RELATIONS the data dependence graph for all
4269*e4b17023SJohn Marino    the data references in DATAREFS, in the LOOP_NEST.  When
4270*e4b17023SJohn Marino    COMPUTE_SELF_AND_RR is FALSE, don't compute read-read and self
4271*e4b17023SJohn Marino    relations.  Return true when successful, i.e. data references number
4272*e4b17023SJohn Marino    is small enough to be handled.  */
4273*e4b17023SJohn Marino 
4274*e4b17023SJohn Marino bool
compute_all_dependences(VEC (data_reference_p,heap)* datarefs,VEC (ddr_p,heap)** dependence_relations,VEC (loop_p,heap)* loop_nest,bool compute_self_and_rr)4275*e4b17023SJohn Marino compute_all_dependences (VEC (data_reference_p, heap) *datarefs,
4276*e4b17023SJohn Marino 			 VEC (ddr_p, heap) **dependence_relations,
4277*e4b17023SJohn Marino 			 VEC (loop_p, heap) *loop_nest,
4278*e4b17023SJohn Marino 			 bool compute_self_and_rr)
4279*e4b17023SJohn Marino {
4280*e4b17023SJohn Marino   struct data_dependence_relation *ddr;
4281*e4b17023SJohn Marino   struct data_reference *a, *b;
4282*e4b17023SJohn Marino   unsigned int i, j;
4283*e4b17023SJohn Marino 
4284*e4b17023SJohn Marino   if ((int) VEC_length (data_reference_p, datarefs)
4285*e4b17023SJohn Marino       > PARAM_VALUE (PARAM_LOOP_MAX_DATAREFS_FOR_DATADEPS))
4286*e4b17023SJohn Marino     {
4287*e4b17023SJohn Marino       struct data_dependence_relation *ddr;
4288*e4b17023SJohn Marino 
4289*e4b17023SJohn Marino       /* Insert a single relation into dependence_relations:
4290*e4b17023SJohn Marino 	 chrec_dont_know.  */
4291*e4b17023SJohn Marino       ddr = initialize_data_dependence_relation (NULL, NULL, loop_nest);
4292*e4b17023SJohn Marino       VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
4293*e4b17023SJohn Marino       return false;
4294*e4b17023SJohn Marino     }
4295*e4b17023SJohn Marino 
4296*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (data_reference_p, datarefs, i, a)
4297*e4b17023SJohn Marino     for (j = i + 1; VEC_iterate (data_reference_p, datarefs, j, b); j++)
4298*e4b17023SJohn Marino       if (DR_IS_WRITE (a) || DR_IS_WRITE (b) || compute_self_and_rr)
4299*e4b17023SJohn Marino 	{
4300*e4b17023SJohn Marino 	  ddr = initialize_data_dependence_relation (a, b, loop_nest);
4301*e4b17023SJohn Marino 	  VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
4302*e4b17023SJohn Marino           if (loop_nest)
4303*e4b17023SJohn Marino    	    compute_affine_dependence (ddr, VEC_index (loop_p, loop_nest, 0));
4304*e4b17023SJohn Marino 	}
4305*e4b17023SJohn Marino 
4306*e4b17023SJohn Marino   if (compute_self_and_rr)
4307*e4b17023SJohn Marino     FOR_EACH_VEC_ELT (data_reference_p, datarefs, i, a)
4308*e4b17023SJohn Marino       {
4309*e4b17023SJohn Marino 	ddr = initialize_data_dependence_relation (a, a, loop_nest);
4310*e4b17023SJohn Marino 	VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
4311*e4b17023SJohn Marino         if (loop_nest)
4312*e4b17023SJohn Marino    	  compute_affine_dependence (ddr, VEC_index (loop_p, loop_nest, 0));
4313*e4b17023SJohn Marino       }
4314*e4b17023SJohn Marino 
4315*e4b17023SJohn Marino   return true;
4316*e4b17023SJohn Marino }
4317*e4b17023SJohn Marino 
4318*e4b17023SJohn Marino /* Stores the locations of memory references in STMT to REFERENCES.  Returns
4319*e4b17023SJohn Marino    true if STMT clobbers memory, false otherwise.  */
4320*e4b17023SJohn Marino 
4321*e4b17023SJohn Marino bool
get_references_in_stmt(gimple stmt,VEC (data_ref_loc,heap)** references)4322*e4b17023SJohn Marino get_references_in_stmt (gimple stmt, VEC (data_ref_loc, heap) **references)
4323*e4b17023SJohn Marino {
4324*e4b17023SJohn Marino   bool clobbers_memory = false;
4325*e4b17023SJohn Marino   data_ref_loc *ref;
4326*e4b17023SJohn Marino   tree *op0, *op1;
4327*e4b17023SJohn Marino   enum gimple_code stmt_code = gimple_code (stmt);
4328*e4b17023SJohn Marino 
4329*e4b17023SJohn Marino   *references = NULL;
4330*e4b17023SJohn Marino 
4331*e4b17023SJohn Marino   /* ASM_EXPR and CALL_EXPR may embed arbitrary side effects.
4332*e4b17023SJohn Marino      Calls have side-effects, except those to const or pure
4333*e4b17023SJohn Marino      functions.  */
4334*e4b17023SJohn Marino   if ((stmt_code == GIMPLE_CALL
4335*e4b17023SJohn Marino        && !(gimple_call_flags (stmt) & (ECF_CONST | ECF_PURE)))
4336*e4b17023SJohn Marino       || (stmt_code == GIMPLE_ASM
4337*e4b17023SJohn Marino 	  && (gimple_asm_volatile_p (stmt) || gimple_vuse (stmt))))
4338*e4b17023SJohn Marino     clobbers_memory = true;
4339*e4b17023SJohn Marino 
4340*e4b17023SJohn Marino   if (!gimple_vuse (stmt))
4341*e4b17023SJohn Marino     return clobbers_memory;
4342*e4b17023SJohn Marino 
4343*e4b17023SJohn Marino   if (stmt_code == GIMPLE_ASSIGN)
4344*e4b17023SJohn Marino     {
4345*e4b17023SJohn Marino       tree base;
4346*e4b17023SJohn Marino       op0 = gimple_assign_lhs_ptr (stmt);
4347*e4b17023SJohn Marino       op1 = gimple_assign_rhs1_ptr (stmt);
4348*e4b17023SJohn Marino 
4349*e4b17023SJohn Marino       if (DECL_P (*op1)
4350*e4b17023SJohn Marino 	  || (REFERENCE_CLASS_P (*op1)
4351*e4b17023SJohn Marino 	      && (base = get_base_address (*op1))
4352*e4b17023SJohn Marino 	      && TREE_CODE (base) != SSA_NAME))
4353*e4b17023SJohn Marino 	{
4354*e4b17023SJohn Marino 	  ref = VEC_safe_push (data_ref_loc, heap, *references, NULL);
4355*e4b17023SJohn Marino 	  ref->pos = op1;
4356*e4b17023SJohn Marino 	  ref->is_read = true;
4357*e4b17023SJohn Marino 	}
4358*e4b17023SJohn Marino     }
4359*e4b17023SJohn Marino   else if (stmt_code == GIMPLE_CALL)
4360*e4b17023SJohn Marino     {
4361*e4b17023SJohn Marino       unsigned i, n;
4362*e4b17023SJohn Marino 
4363*e4b17023SJohn Marino       op0 = gimple_call_lhs_ptr (stmt);
4364*e4b17023SJohn Marino       n = gimple_call_num_args (stmt);
4365*e4b17023SJohn Marino       for (i = 0; i < n; i++)
4366*e4b17023SJohn Marino 	{
4367*e4b17023SJohn Marino 	  op1 = gimple_call_arg_ptr (stmt, i);
4368*e4b17023SJohn Marino 
4369*e4b17023SJohn Marino 	  if (DECL_P (*op1)
4370*e4b17023SJohn Marino 	      || (REFERENCE_CLASS_P (*op1) && get_base_address (*op1)))
4371*e4b17023SJohn Marino 	    {
4372*e4b17023SJohn Marino 	      ref = VEC_safe_push (data_ref_loc, heap, *references, NULL);
4373*e4b17023SJohn Marino 	      ref->pos = op1;
4374*e4b17023SJohn Marino 	      ref->is_read = true;
4375*e4b17023SJohn Marino 	    }
4376*e4b17023SJohn Marino 	}
4377*e4b17023SJohn Marino     }
4378*e4b17023SJohn Marino   else
4379*e4b17023SJohn Marino     return clobbers_memory;
4380*e4b17023SJohn Marino 
4381*e4b17023SJohn Marino   if (*op0
4382*e4b17023SJohn Marino       && (DECL_P (*op0)
4383*e4b17023SJohn Marino 	  || (REFERENCE_CLASS_P (*op0) && get_base_address (*op0))))
4384*e4b17023SJohn Marino     {
4385*e4b17023SJohn Marino       ref = VEC_safe_push (data_ref_loc, heap, *references, NULL);
4386*e4b17023SJohn Marino       ref->pos = op0;
4387*e4b17023SJohn Marino       ref->is_read = false;
4388*e4b17023SJohn Marino     }
4389*e4b17023SJohn Marino   return clobbers_memory;
4390*e4b17023SJohn Marino }
4391*e4b17023SJohn Marino 
4392*e4b17023SJohn Marino /* Stores the data references in STMT to DATAREFS.  If there is an unanalyzable
4393*e4b17023SJohn Marino    reference, returns false, otherwise returns true.  NEST is the outermost
4394*e4b17023SJohn Marino    loop of the loop nest in which the references should be analyzed.  */
4395*e4b17023SJohn Marino 
4396*e4b17023SJohn Marino bool
find_data_references_in_stmt(struct loop * nest,gimple stmt,VEC (data_reference_p,heap)** datarefs)4397*e4b17023SJohn Marino find_data_references_in_stmt (struct loop *nest, gimple stmt,
4398*e4b17023SJohn Marino 			      VEC (data_reference_p, heap) **datarefs)
4399*e4b17023SJohn Marino {
4400*e4b17023SJohn Marino   unsigned i;
4401*e4b17023SJohn Marino   VEC (data_ref_loc, heap) *references;
4402*e4b17023SJohn Marino   data_ref_loc *ref;
4403*e4b17023SJohn Marino   bool ret = true;
4404*e4b17023SJohn Marino   data_reference_p dr;
4405*e4b17023SJohn Marino 
4406*e4b17023SJohn Marino   if (get_references_in_stmt (stmt, &references))
4407*e4b17023SJohn Marino     {
4408*e4b17023SJohn Marino       VEC_free (data_ref_loc, heap, references);
4409*e4b17023SJohn Marino       return false;
4410*e4b17023SJohn Marino     }
4411*e4b17023SJohn Marino 
4412*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (data_ref_loc, references, i, ref)
4413*e4b17023SJohn Marino     {
4414*e4b17023SJohn Marino       dr = create_data_ref (nest, loop_containing_stmt (stmt),
4415*e4b17023SJohn Marino 			    *ref->pos, stmt, ref->is_read);
4416*e4b17023SJohn Marino       gcc_assert (dr != NULL);
4417*e4b17023SJohn Marino       VEC_safe_push (data_reference_p, heap, *datarefs, dr);
4418*e4b17023SJohn Marino     }
4419*e4b17023SJohn Marino   VEC_free (data_ref_loc, heap, references);
4420*e4b17023SJohn Marino   return ret;
4421*e4b17023SJohn Marino }
4422*e4b17023SJohn Marino 
4423*e4b17023SJohn Marino /* Stores the data references in STMT to DATAREFS.  If there is an
4424*e4b17023SJohn Marino    unanalyzable reference, returns false, otherwise returns true.
4425*e4b17023SJohn Marino    NEST is the outermost loop of the loop nest in which the references
4426*e4b17023SJohn Marino    should be instantiated, LOOP is the loop in which the references
4427*e4b17023SJohn Marino    should be analyzed.  */
4428*e4b17023SJohn Marino 
4429*e4b17023SJohn Marino bool
graphite_find_data_references_in_stmt(loop_p nest,loop_p loop,gimple stmt,VEC (data_reference_p,heap)** datarefs)4430*e4b17023SJohn Marino graphite_find_data_references_in_stmt (loop_p nest, loop_p loop, gimple stmt,
4431*e4b17023SJohn Marino 				       VEC (data_reference_p, heap) **datarefs)
4432*e4b17023SJohn Marino {
4433*e4b17023SJohn Marino   unsigned i;
4434*e4b17023SJohn Marino   VEC (data_ref_loc, heap) *references;
4435*e4b17023SJohn Marino   data_ref_loc *ref;
4436*e4b17023SJohn Marino   bool ret = true;
4437*e4b17023SJohn Marino   data_reference_p dr;
4438*e4b17023SJohn Marino 
4439*e4b17023SJohn Marino   if (get_references_in_stmt (stmt, &references))
4440*e4b17023SJohn Marino     {
4441*e4b17023SJohn Marino       VEC_free (data_ref_loc, heap, references);
4442*e4b17023SJohn Marino       return false;
4443*e4b17023SJohn Marino     }
4444*e4b17023SJohn Marino 
4445*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (data_ref_loc, references, i, ref)
4446*e4b17023SJohn Marino     {
4447*e4b17023SJohn Marino       dr = create_data_ref (nest, loop, *ref->pos, stmt, ref->is_read);
4448*e4b17023SJohn Marino       gcc_assert (dr != NULL);
4449*e4b17023SJohn Marino       VEC_safe_push (data_reference_p, heap, *datarefs, dr);
4450*e4b17023SJohn Marino     }
4451*e4b17023SJohn Marino 
4452*e4b17023SJohn Marino   VEC_free (data_ref_loc, heap, references);
4453*e4b17023SJohn Marino   return ret;
4454*e4b17023SJohn Marino }
4455*e4b17023SJohn Marino 
4456*e4b17023SJohn Marino /* Search the data references in LOOP, and record the information into
4457*e4b17023SJohn Marino    DATAREFS.  Returns chrec_dont_know when failing to analyze a
4458*e4b17023SJohn Marino    difficult case, returns NULL_TREE otherwise.  */
4459*e4b17023SJohn Marino 
4460*e4b17023SJohn Marino tree
find_data_references_in_bb(struct loop * loop,basic_block bb,VEC (data_reference_p,heap)** datarefs)4461*e4b17023SJohn Marino find_data_references_in_bb (struct loop *loop, basic_block bb,
4462*e4b17023SJohn Marino                             VEC (data_reference_p, heap) **datarefs)
4463*e4b17023SJohn Marino {
4464*e4b17023SJohn Marino   gimple_stmt_iterator bsi;
4465*e4b17023SJohn Marino 
4466*e4b17023SJohn Marino   for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
4467*e4b17023SJohn Marino     {
4468*e4b17023SJohn Marino       gimple stmt = gsi_stmt (bsi);
4469*e4b17023SJohn Marino 
4470*e4b17023SJohn Marino       if (!find_data_references_in_stmt (loop, stmt, datarefs))
4471*e4b17023SJohn Marino         {
4472*e4b17023SJohn Marino           struct data_reference *res;
4473*e4b17023SJohn Marino           res = XCNEW (struct data_reference);
4474*e4b17023SJohn Marino           VEC_safe_push (data_reference_p, heap, *datarefs, res);
4475*e4b17023SJohn Marino 
4476*e4b17023SJohn Marino           return chrec_dont_know;
4477*e4b17023SJohn Marino         }
4478*e4b17023SJohn Marino     }
4479*e4b17023SJohn Marino 
4480*e4b17023SJohn Marino   return NULL_TREE;
4481*e4b17023SJohn Marino }
4482*e4b17023SJohn Marino 
4483*e4b17023SJohn Marino /* Search the data references in LOOP, and record the information into
4484*e4b17023SJohn Marino    DATAREFS.  Returns chrec_dont_know when failing to analyze a
4485*e4b17023SJohn Marino    difficult case, returns NULL_TREE otherwise.
4486*e4b17023SJohn Marino 
4487*e4b17023SJohn Marino    TODO: This function should be made smarter so that it can handle address
4488*e4b17023SJohn Marino    arithmetic as if they were array accesses, etc.  */
4489*e4b17023SJohn Marino 
4490*e4b17023SJohn Marino static tree
find_data_references_in_loop(struct loop * loop,VEC (data_reference_p,heap)** datarefs)4491*e4b17023SJohn Marino find_data_references_in_loop (struct loop *loop,
4492*e4b17023SJohn Marino 			      VEC (data_reference_p, heap) **datarefs)
4493*e4b17023SJohn Marino {
4494*e4b17023SJohn Marino   basic_block bb, *bbs;
4495*e4b17023SJohn Marino   unsigned int i;
4496*e4b17023SJohn Marino 
4497*e4b17023SJohn Marino   bbs = get_loop_body_in_dom_order (loop);
4498*e4b17023SJohn Marino 
4499*e4b17023SJohn Marino   for (i = 0; i < loop->num_nodes; i++)
4500*e4b17023SJohn Marino     {
4501*e4b17023SJohn Marino       bb = bbs[i];
4502*e4b17023SJohn Marino 
4503*e4b17023SJohn Marino       if (find_data_references_in_bb (loop, bb, datarefs) == chrec_dont_know)
4504*e4b17023SJohn Marino         {
4505*e4b17023SJohn Marino           free (bbs);
4506*e4b17023SJohn Marino           return chrec_dont_know;
4507*e4b17023SJohn Marino         }
4508*e4b17023SJohn Marino     }
4509*e4b17023SJohn Marino   free (bbs);
4510*e4b17023SJohn Marino 
4511*e4b17023SJohn Marino   return NULL_TREE;
4512*e4b17023SJohn Marino }
4513*e4b17023SJohn Marino 
4514*e4b17023SJohn Marino /* Recursive helper function.  */
4515*e4b17023SJohn Marino 
4516*e4b17023SJohn Marino static bool
find_loop_nest_1(struct loop * loop,VEC (loop_p,heap)** loop_nest)4517*e4b17023SJohn Marino find_loop_nest_1 (struct loop *loop, VEC (loop_p, heap) **loop_nest)
4518*e4b17023SJohn Marino {
4519*e4b17023SJohn Marino   /* Inner loops of the nest should not contain siblings.  Example:
4520*e4b17023SJohn Marino      when there are two consecutive loops,
4521*e4b17023SJohn Marino 
4522*e4b17023SJohn Marino      | loop_0
4523*e4b17023SJohn Marino      |   loop_1
4524*e4b17023SJohn Marino      |     A[{0, +, 1}_1]
4525*e4b17023SJohn Marino      |   endloop_1
4526*e4b17023SJohn Marino      |   loop_2
4527*e4b17023SJohn Marino      |     A[{0, +, 1}_2]
4528*e4b17023SJohn Marino      |   endloop_2
4529*e4b17023SJohn Marino      | endloop_0
4530*e4b17023SJohn Marino 
4531*e4b17023SJohn Marino      the dependence relation cannot be captured by the distance
4532*e4b17023SJohn Marino      abstraction.  */
4533*e4b17023SJohn Marino   if (loop->next)
4534*e4b17023SJohn Marino     return false;
4535*e4b17023SJohn Marino 
4536*e4b17023SJohn Marino   VEC_safe_push (loop_p, heap, *loop_nest, loop);
4537*e4b17023SJohn Marino   if (loop->inner)
4538*e4b17023SJohn Marino     return find_loop_nest_1 (loop->inner, loop_nest);
4539*e4b17023SJohn Marino   return true;
4540*e4b17023SJohn Marino }
4541*e4b17023SJohn Marino 
4542*e4b17023SJohn Marino /* Return false when the LOOP is not well nested.  Otherwise return
4543*e4b17023SJohn Marino    true and insert in LOOP_NEST the loops of the nest.  LOOP_NEST will
4544*e4b17023SJohn Marino    contain the loops from the outermost to the innermost, as they will
4545*e4b17023SJohn Marino    appear in the classic distance vector.  */
4546*e4b17023SJohn Marino 
4547*e4b17023SJohn Marino bool
find_loop_nest(struct loop * loop,VEC (loop_p,heap)** loop_nest)4548*e4b17023SJohn Marino find_loop_nest (struct loop *loop, VEC (loop_p, heap) **loop_nest)
4549*e4b17023SJohn Marino {
4550*e4b17023SJohn Marino   VEC_safe_push (loop_p, heap, *loop_nest, loop);
4551*e4b17023SJohn Marino   if (loop->inner)
4552*e4b17023SJohn Marino     return find_loop_nest_1 (loop->inner, loop_nest);
4553*e4b17023SJohn Marino   return true;
4554*e4b17023SJohn Marino }
4555*e4b17023SJohn Marino 
4556*e4b17023SJohn Marino /* Returns true when the data dependences have been computed, false otherwise.
4557*e4b17023SJohn Marino    Given a loop nest LOOP, the following vectors are returned:
4558*e4b17023SJohn Marino    DATAREFS is initialized to all the array elements contained in this loop,
4559*e4b17023SJohn Marino    DEPENDENCE_RELATIONS contains the relations between the data references.
4560*e4b17023SJohn Marino    Compute read-read and self relations if
4561*e4b17023SJohn Marino    COMPUTE_SELF_AND_READ_READ_DEPENDENCES is TRUE.  */
4562*e4b17023SJohn Marino 
4563*e4b17023SJohn Marino bool
compute_data_dependences_for_loop(struct loop * loop,bool compute_self_and_read_read_dependences,VEC (loop_p,heap)** loop_nest,VEC (data_reference_p,heap)** datarefs,VEC (ddr_p,heap)** dependence_relations)4564*e4b17023SJohn Marino compute_data_dependences_for_loop (struct loop *loop,
4565*e4b17023SJohn Marino 				   bool compute_self_and_read_read_dependences,
4566*e4b17023SJohn Marino 				   VEC (loop_p, heap) **loop_nest,
4567*e4b17023SJohn Marino 				   VEC (data_reference_p, heap) **datarefs,
4568*e4b17023SJohn Marino 				   VEC (ddr_p, heap) **dependence_relations)
4569*e4b17023SJohn Marino {
4570*e4b17023SJohn Marino   bool res = true;
4571*e4b17023SJohn Marino 
4572*e4b17023SJohn Marino   memset (&dependence_stats, 0, sizeof (dependence_stats));
4573*e4b17023SJohn Marino 
4574*e4b17023SJohn Marino   /* If the loop nest is not well formed, or one of the data references
4575*e4b17023SJohn Marino      is not computable, give up without spending time to compute other
4576*e4b17023SJohn Marino      dependences.  */
4577*e4b17023SJohn Marino   if (!loop
4578*e4b17023SJohn Marino       || !find_loop_nest (loop, loop_nest)
4579*e4b17023SJohn Marino       || find_data_references_in_loop (loop, datarefs) == chrec_dont_know
4580*e4b17023SJohn Marino       || !compute_all_dependences (*datarefs, dependence_relations, *loop_nest,
4581*e4b17023SJohn Marino 				   compute_self_and_read_read_dependences))
4582*e4b17023SJohn Marino     res = false;
4583*e4b17023SJohn Marino 
4584*e4b17023SJohn Marino   if (dump_file && (dump_flags & TDF_STATS))
4585*e4b17023SJohn Marino     {
4586*e4b17023SJohn Marino       fprintf (dump_file, "Dependence tester statistics:\n");
4587*e4b17023SJohn Marino 
4588*e4b17023SJohn Marino       fprintf (dump_file, "Number of dependence tests: %d\n",
4589*e4b17023SJohn Marino 	       dependence_stats.num_dependence_tests);
4590*e4b17023SJohn Marino       fprintf (dump_file, "Number of dependence tests classified dependent: %d\n",
4591*e4b17023SJohn Marino 	       dependence_stats.num_dependence_dependent);
4592*e4b17023SJohn Marino       fprintf (dump_file, "Number of dependence tests classified independent: %d\n",
4593*e4b17023SJohn Marino 	       dependence_stats.num_dependence_independent);
4594*e4b17023SJohn Marino       fprintf (dump_file, "Number of undetermined dependence tests: %d\n",
4595*e4b17023SJohn Marino 	       dependence_stats.num_dependence_undetermined);
4596*e4b17023SJohn Marino 
4597*e4b17023SJohn Marino       fprintf (dump_file, "Number of subscript tests: %d\n",
4598*e4b17023SJohn Marino 	       dependence_stats.num_subscript_tests);
4599*e4b17023SJohn Marino       fprintf (dump_file, "Number of undetermined subscript tests: %d\n",
4600*e4b17023SJohn Marino 	       dependence_stats.num_subscript_undetermined);
4601*e4b17023SJohn Marino       fprintf (dump_file, "Number of same subscript function: %d\n",
4602*e4b17023SJohn Marino 	       dependence_stats.num_same_subscript_function);
4603*e4b17023SJohn Marino 
4604*e4b17023SJohn Marino       fprintf (dump_file, "Number of ziv tests: %d\n",
4605*e4b17023SJohn Marino 	       dependence_stats.num_ziv);
4606*e4b17023SJohn Marino       fprintf (dump_file, "Number of ziv tests returning dependent: %d\n",
4607*e4b17023SJohn Marino 	       dependence_stats.num_ziv_dependent);
4608*e4b17023SJohn Marino       fprintf (dump_file, "Number of ziv tests returning independent: %d\n",
4609*e4b17023SJohn Marino 	       dependence_stats.num_ziv_independent);
4610*e4b17023SJohn Marino       fprintf (dump_file, "Number of ziv tests unimplemented: %d\n",
4611*e4b17023SJohn Marino 	       dependence_stats.num_ziv_unimplemented);
4612*e4b17023SJohn Marino 
4613*e4b17023SJohn Marino       fprintf (dump_file, "Number of siv tests: %d\n",
4614*e4b17023SJohn Marino 	       dependence_stats.num_siv);
4615*e4b17023SJohn Marino       fprintf (dump_file, "Number of siv tests returning dependent: %d\n",
4616*e4b17023SJohn Marino 	       dependence_stats.num_siv_dependent);
4617*e4b17023SJohn Marino       fprintf (dump_file, "Number of siv tests returning independent: %d\n",
4618*e4b17023SJohn Marino 	       dependence_stats.num_siv_independent);
4619*e4b17023SJohn Marino       fprintf (dump_file, "Number of siv tests unimplemented: %d\n",
4620*e4b17023SJohn Marino 	       dependence_stats.num_siv_unimplemented);
4621*e4b17023SJohn Marino 
4622*e4b17023SJohn Marino       fprintf (dump_file, "Number of miv tests: %d\n",
4623*e4b17023SJohn Marino 	       dependence_stats.num_miv);
4624*e4b17023SJohn Marino       fprintf (dump_file, "Number of miv tests returning dependent: %d\n",
4625*e4b17023SJohn Marino 	       dependence_stats.num_miv_dependent);
4626*e4b17023SJohn Marino       fprintf (dump_file, "Number of miv tests returning independent: %d\n",
4627*e4b17023SJohn Marino 	       dependence_stats.num_miv_independent);
4628*e4b17023SJohn Marino       fprintf (dump_file, "Number of miv tests unimplemented: %d\n",
4629*e4b17023SJohn Marino 	       dependence_stats.num_miv_unimplemented);
4630*e4b17023SJohn Marino     }
4631*e4b17023SJohn Marino 
4632*e4b17023SJohn Marino   return res;
4633*e4b17023SJohn Marino }
4634*e4b17023SJohn Marino 
4635*e4b17023SJohn Marino /* Returns true when the data dependences for the basic block BB have been
4636*e4b17023SJohn Marino    computed, false otherwise.
4637*e4b17023SJohn Marino    DATAREFS is initialized to all the array elements contained in this basic
4638*e4b17023SJohn Marino    block, DEPENDENCE_RELATIONS contains the relations between the data
4639*e4b17023SJohn Marino    references. Compute read-read and self relations if
4640*e4b17023SJohn Marino    COMPUTE_SELF_AND_READ_READ_DEPENDENCES is TRUE.  */
4641*e4b17023SJohn Marino bool
compute_data_dependences_for_bb(basic_block bb,bool compute_self_and_read_read_dependences,VEC (data_reference_p,heap)** datarefs,VEC (ddr_p,heap)** dependence_relations)4642*e4b17023SJohn Marino compute_data_dependences_for_bb (basic_block bb,
4643*e4b17023SJohn Marino                                  bool compute_self_and_read_read_dependences,
4644*e4b17023SJohn Marino                                  VEC (data_reference_p, heap) **datarefs,
4645*e4b17023SJohn Marino                                  VEC (ddr_p, heap) **dependence_relations)
4646*e4b17023SJohn Marino {
4647*e4b17023SJohn Marino   if (find_data_references_in_bb (NULL, bb, datarefs) == chrec_dont_know)
4648*e4b17023SJohn Marino     return false;
4649*e4b17023SJohn Marino 
4650*e4b17023SJohn Marino   return compute_all_dependences (*datarefs, dependence_relations, NULL,
4651*e4b17023SJohn Marino 				  compute_self_and_read_read_dependences);
4652*e4b17023SJohn Marino }
4653*e4b17023SJohn Marino 
4654*e4b17023SJohn Marino /* Entry point (for testing only).  Analyze all the data references
4655*e4b17023SJohn Marino    and the dependence relations in LOOP.
4656*e4b17023SJohn Marino 
4657*e4b17023SJohn Marino    The data references are computed first.
4658*e4b17023SJohn Marino 
4659*e4b17023SJohn Marino    A relation on these nodes is represented by a complete graph.  Some
4660*e4b17023SJohn Marino    of the relations could be of no interest, thus the relations can be
4661*e4b17023SJohn Marino    computed on demand.
4662*e4b17023SJohn Marino 
4663*e4b17023SJohn Marino    In the following function we compute all the relations.  This is
4664*e4b17023SJohn Marino    just a first implementation that is here for:
4665*e4b17023SJohn Marino    - for showing how to ask for the dependence relations,
4666*e4b17023SJohn Marino    - for the debugging the whole dependence graph,
4667*e4b17023SJohn Marino    - for the dejagnu testcases and maintenance.
4668*e4b17023SJohn Marino 
4669*e4b17023SJohn Marino    It is possible to ask only for a part of the graph, avoiding to
4670*e4b17023SJohn Marino    compute the whole dependence graph.  The computed dependences are
4671*e4b17023SJohn Marino    stored in a knowledge base (KB) such that later queries don't
4672*e4b17023SJohn Marino    recompute the same information.  The implementation of this KB is
4673*e4b17023SJohn Marino    transparent to the optimizer, and thus the KB can be changed with a
4674*e4b17023SJohn Marino    more efficient implementation, or the KB could be disabled.  */
4675*e4b17023SJohn Marino static void
analyze_all_data_dependences(struct loop * loop)4676*e4b17023SJohn Marino analyze_all_data_dependences (struct loop *loop)
4677*e4b17023SJohn Marino {
4678*e4b17023SJohn Marino   unsigned int i;
4679*e4b17023SJohn Marino   int nb_data_refs = 10;
4680*e4b17023SJohn Marino   VEC (data_reference_p, heap) *datarefs =
4681*e4b17023SJohn Marino     VEC_alloc (data_reference_p, heap, nb_data_refs);
4682*e4b17023SJohn Marino   VEC (ddr_p, heap) *dependence_relations =
4683*e4b17023SJohn Marino     VEC_alloc (ddr_p, heap, nb_data_refs * nb_data_refs);
4684*e4b17023SJohn Marino   VEC (loop_p, heap) *loop_nest = VEC_alloc (loop_p, heap, 3);
4685*e4b17023SJohn Marino 
4686*e4b17023SJohn Marino   /* Compute DDs on the whole function.  */
4687*e4b17023SJohn Marino   compute_data_dependences_for_loop (loop, false, &loop_nest, &datarefs,
4688*e4b17023SJohn Marino 				     &dependence_relations);
4689*e4b17023SJohn Marino 
4690*e4b17023SJohn Marino   if (dump_file)
4691*e4b17023SJohn Marino     {
4692*e4b17023SJohn Marino       dump_data_dependence_relations (dump_file, dependence_relations);
4693*e4b17023SJohn Marino       fprintf (dump_file, "\n\n");
4694*e4b17023SJohn Marino 
4695*e4b17023SJohn Marino       if (dump_flags & TDF_DETAILS)
4696*e4b17023SJohn Marino 	dump_dist_dir_vectors (dump_file, dependence_relations);
4697*e4b17023SJohn Marino 
4698*e4b17023SJohn Marino       if (dump_flags & TDF_STATS)
4699*e4b17023SJohn Marino 	{
4700*e4b17023SJohn Marino 	  unsigned nb_top_relations = 0;
4701*e4b17023SJohn Marino 	  unsigned nb_bot_relations = 0;
4702*e4b17023SJohn Marino 	  unsigned nb_chrec_relations = 0;
4703*e4b17023SJohn Marino 	  struct data_dependence_relation *ddr;
4704*e4b17023SJohn Marino 
4705*e4b17023SJohn Marino 	  FOR_EACH_VEC_ELT (ddr_p, dependence_relations, i, ddr)
4706*e4b17023SJohn Marino 	    {
4707*e4b17023SJohn Marino 	      if (chrec_contains_undetermined (DDR_ARE_DEPENDENT (ddr)))
4708*e4b17023SJohn Marino 		nb_top_relations++;
4709*e4b17023SJohn Marino 
4710*e4b17023SJohn Marino 	      else if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
4711*e4b17023SJohn Marino 		nb_bot_relations++;
4712*e4b17023SJohn Marino 
4713*e4b17023SJohn Marino 	      else
4714*e4b17023SJohn Marino 		nb_chrec_relations++;
4715*e4b17023SJohn Marino 	    }
4716*e4b17023SJohn Marino 
4717*e4b17023SJohn Marino 	  gather_stats_on_scev_database ();
4718*e4b17023SJohn Marino 	}
4719*e4b17023SJohn Marino     }
4720*e4b17023SJohn Marino 
4721*e4b17023SJohn Marino   VEC_free (loop_p, heap, loop_nest);
4722*e4b17023SJohn Marino   free_dependence_relations (dependence_relations);
4723*e4b17023SJohn Marino   free_data_refs (datarefs);
4724*e4b17023SJohn Marino }
4725*e4b17023SJohn Marino 
4726*e4b17023SJohn Marino /* Computes all the data dependences and check that the results of
4727*e4b17023SJohn Marino    several analyzers are the same.  */
4728*e4b17023SJohn Marino 
4729*e4b17023SJohn Marino void
tree_check_data_deps(void)4730*e4b17023SJohn Marino tree_check_data_deps (void)
4731*e4b17023SJohn Marino {
4732*e4b17023SJohn Marino   loop_iterator li;
4733*e4b17023SJohn Marino   struct loop *loop_nest;
4734*e4b17023SJohn Marino 
4735*e4b17023SJohn Marino   FOR_EACH_LOOP (li, loop_nest, 0)
4736*e4b17023SJohn Marino     analyze_all_data_dependences (loop_nest);
4737*e4b17023SJohn Marino }
4738*e4b17023SJohn Marino 
4739*e4b17023SJohn Marino /* Free the memory used by a data dependence relation DDR.  */
4740*e4b17023SJohn Marino 
4741*e4b17023SJohn Marino void
free_dependence_relation(struct data_dependence_relation * ddr)4742*e4b17023SJohn Marino free_dependence_relation (struct data_dependence_relation *ddr)
4743*e4b17023SJohn Marino {
4744*e4b17023SJohn Marino   if (ddr == NULL)
4745*e4b17023SJohn Marino     return;
4746*e4b17023SJohn Marino 
4747*e4b17023SJohn Marino   if (DDR_SUBSCRIPTS (ddr))
4748*e4b17023SJohn Marino     free_subscripts (DDR_SUBSCRIPTS (ddr));
4749*e4b17023SJohn Marino   if (DDR_DIST_VECTS (ddr))
4750*e4b17023SJohn Marino     VEC_free (lambda_vector, heap, DDR_DIST_VECTS (ddr));
4751*e4b17023SJohn Marino   if (DDR_DIR_VECTS (ddr))
4752*e4b17023SJohn Marino     VEC_free (lambda_vector, heap, DDR_DIR_VECTS (ddr));
4753*e4b17023SJohn Marino 
4754*e4b17023SJohn Marino   free (ddr);
4755*e4b17023SJohn Marino }
4756*e4b17023SJohn Marino 
4757*e4b17023SJohn Marino /* Free the memory used by the data dependence relations from
4758*e4b17023SJohn Marino    DEPENDENCE_RELATIONS.  */
4759*e4b17023SJohn Marino 
4760*e4b17023SJohn Marino void
free_dependence_relations(VEC (ddr_p,heap)* dependence_relations)4761*e4b17023SJohn Marino free_dependence_relations (VEC (ddr_p, heap) *dependence_relations)
4762*e4b17023SJohn Marino {
4763*e4b17023SJohn Marino   unsigned int i;
4764*e4b17023SJohn Marino   struct data_dependence_relation *ddr;
4765*e4b17023SJohn Marino 
4766*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (ddr_p, dependence_relations, i, ddr)
4767*e4b17023SJohn Marino     if (ddr)
4768*e4b17023SJohn Marino       free_dependence_relation (ddr);
4769*e4b17023SJohn Marino 
4770*e4b17023SJohn Marino   VEC_free (ddr_p, heap, dependence_relations);
4771*e4b17023SJohn Marino }
4772*e4b17023SJohn Marino 
4773*e4b17023SJohn Marino /* Free the memory used by the data references from DATAREFS.  */
4774*e4b17023SJohn Marino 
4775*e4b17023SJohn Marino void
free_data_refs(VEC (data_reference_p,heap)* datarefs)4776*e4b17023SJohn Marino free_data_refs (VEC (data_reference_p, heap) *datarefs)
4777*e4b17023SJohn Marino {
4778*e4b17023SJohn Marino   unsigned int i;
4779*e4b17023SJohn Marino   struct data_reference *dr;
4780*e4b17023SJohn Marino 
4781*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (data_reference_p, datarefs, i, dr)
4782*e4b17023SJohn Marino     free_data_ref (dr);
4783*e4b17023SJohn Marino   VEC_free (data_reference_p, heap, datarefs);
4784*e4b17023SJohn Marino }
4785*e4b17023SJohn Marino 
4786*e4b17023SJohn Marino 
4787*e4b17023SJohn Marino 
4788*e4b17023SJohn Marino /* Dump vertex I in RDG to FILE.  */
4789*e4b17023SJohn Marino 
4790*e4b17023SJohn Marino void
dump_rdg_vertex(FILE * file,struct graph * rdg,int i)4791*e4b17023SJohn Marino dump_rdg_vertex (FILE *file, struct graph *rdg, int i)
4792*e4b17023SJohn Marino {
4793*e4b17023SJohn Marino   struct vertex *v = &(rdg->vertices[i]);
4794*e4b17023SJohn Marino   struct graph_edge *e;
4795*e4b17023SJohn Marino 
4796*e4b17023SJohn Marino   fprintf (file, "(vertex %d: (%s%s) (in:", i,
4797*e4b17023SJohn Marino 	   RDG_MEM_WRITE_STMT (rdg, i) ? "w" : "",
4798*e4b17023SJohn Marino 	   RDG_MEM_READS_STMT (rdg, i) ? "r" : "");
4799*e4b17023SJohn Marino 
4800*e4b17023SJohn Marino   if (v->pred)
4801*e4b17023SJohn Marino     for (e = v->pred; e; e = e->pred_next)
4802*e4b17023SJohn Marino       fprintf (file, " %d", e->src);
4803*e4b17023SJohn Marino 
4804*e4b17023SJohn Marino   fprintf (file, ") (out:");
4805*e4b17023SJohn Marino 
4806*e4b17023SJohn Marino   if (v->succ)
4807*e4b17023SJohn Marino     for (e = v->succ; e; e = e->succ_next)
4808*e4b17023SJohn Marino       fprintf (file, " %d", e->dest);
4809*e4b17023SJohn Marino 
4810*e4b17023SJohn Marino   fprintf (file, ")\n");
4811*e4b17023SJohn Marino   print_gimple_stmt (file, RDGV_STMT (v), 0, TDF_VOPS|TDF_MEMSYMS);
4812*e4b17023SJohn Marino   fprintf (file, ")\n");
4813*e4b17023SJohn Marino }
4814*e4b17023SJohn Marino 
4815*e4b17023SJohn Marino /* Call dump_rdg_vertex on stderr.  */
4816*e4b17023SJohn Marino 
4817*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_rdg_vertex(struct graph * rdg,int i)4818*e4b17023SJohn Marino debug_rdg_vertex (struct graph *rdg, int i)
4819*e4b17023SJohn Marino {
4820*e4b17023SJohn Marino   dump_rdg_vertex (stderr, rdg, i);
4821*e4b17023SJohn Marino }
4822*e4b17023SJohn Marino 
4823*e4b17023SJohn Marino /* Dump component C of RDG to FILE.  If DUMPED is non-null, set the
4824*e4b17023SJohn Marino    dumped vertices to that bitmap.  */
4825*e4b17023SJohn Marino 
dump_rdg_component(FILE * file,struct graph * rdg,int c,bitmap dumped)4826*e4b17023SJohn Marino void dump_rdg_component (FILE *file, struct graph *rdg, int c, bitmap dumped)
4827*e4b17023SJohn Marino {
4828*e4b17023SJohn Marino   int i;
4829*e4b17023SJohn Marino 
4830*e4b17023SJohn Marino   fprintf (file, "(%d\n", c);
4831*e4b17023SJohn Marino 
4832*e4b17023SJohn Marino   for (i = 0; i < rdg->n_vertices; i++)
4833*e4b17023SJohn Marino     if (rdg->vertices[i].component == c)
4834*e4b17023SJohn Marino       {
4835*e4b17023SJohn Marino 	if (dumped)
4836*e4b17023SJohn Marino 	  bitmap_set_bit (dumped, i);
4837*e4b17023SJohn Marino 
4838*e4b17023SJohn Marino 	dump_rdg_vertex (file, rdg, i);
4839*e4b17023SJohn Marino       }
4840*e4b17023SJohn Marino 
4841*e4b17023SJohn Marino   fprintf (file, ")\n");
4842*e4b17023SJohn Marino }
4843*e4b17023SJohn Marino 
4844*e4b17023SJohn Marino /* Call dump_rdg_vertex on stderr.  */
4845*e4b17023SJohn Marino 
4846*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_rdg_component(struct graph * rdg,int c)4847*e4b17023SJohn Marino debug_rdg_component (struct graph *rdg, int c)
4848*e4b17023SJohn Marino {
4849*e4b17023SJohn Marino   dump_rdg_component (stderr, rdg, c, NULL);
4850*e4b17023SJohn Marino }
4851*e4b17023SJohn Marino 
4852*e4b17023SJohn Marino /* Dump the reduced dependence graph RDG to FILE.  */
4853*e4b17023SJohn Marino 
4854*e4b17023SJohn Marino void
dump_rdg(FILE * file,struct graph * rdg)4855*e4b17023SJohn Marino dump_rdg (FILE *file, struct graph *rdg)
4856*e4b17023SJohn Marino {
4857*e4b17023SJohn Marino   int i;
4858*e4b17023SJohn Marino   bitmap dumped = BITMAP_ALLOC (NULL);
4859*e4b17023SJohn Marino 
4860*e4b17023SJohn Marino   fprintf (file, "(rdg\n");
4861*e4b17023SJohn Marino 
4862*e4b17023SJohn Marino   for (i = 0; i < rdg->n_vertices; i++)
4863*e4b17023SJohn Marino     if (!bitmap_bit_p (dumped, i))
4864*e4b17023SJohn Marino       dump_rdg_component (file, rdg, rdg->vertices[i].component, dumped);
4865*e4b17023SJohn Marino 
4866*e4b17023SJohn Marino   fprintf (file, ")\n");
4867*e4b17023SJohn Marino   BITMAP_FREE (dumped);
4868*e4b17023SJohn Marino }
4869*e4b17023SJohn Marino 
4870*e4b17023SJohn Marino /* Call dump_rdg on stderr.  */
4871*e4b17023SJohn Marino 
4872*e4b17023SJohn Marino DEBUG_FUNCTION void
debug_rdg(struct graph * rdg)4873*e4b17023SJohn Marino debug_rdg (struct graph *rdg)
4874*e4b17023SJohn Marino {
4875*e4b17023SJohn Marino   dump_rdg (stderr, rdg);
4876*e4b17023SJohn Marino }
4877*e4b17023SJohn Marino 
4878*e4b17023SJohn Marino static void
dot_rdg_1(FILE * file,struct graph * rdg)4879*e4b17023SJohn Marino dot_rdg_1 (FILE *file, struct graph *rdg)
4880*e4b17023SJohn Marino {
4881*e4b17023SJohn Marino   int i;
4882*e4b17023SJohn Marino 
4883*e4b17023SJohn Marino   fprintf (file, "digraph RDG {\n");
4884*e4b17023SJohn Marino 
4885*e4b17023SJohn Marino   for (i = 0; i < rdg->n_vertices; i++)
4886*e4b17023SJohn Marino     {
4887*e4b17023SJohn Marino       struct vertex *v = &(rdg->vertices[i]);
4888*e4b17023SJohn Marino       struct graph_edge *e;
4889*e4b17023SJohn Marino 
4890*e4b17023SJohn Marino       /* Highlight reads from memory.  */
4891*e4b17023SJohn Marino       if (RDG_MEM_READS_STMT (rdg, i))
4892*e4b17023SJohn Marino        fprintf (file, "%d [style=filled, fillcolor=green]\n", i);
4893*e4b17023SJohn Marino 
4894*e4b17023SJohn Marino       /* Highlight stores to memory.  */
4895*e4b17023SJohn Marino       if (RDG_MEM_WRITE_STMT (rdg, i))
4896*e4b17023SJohn Marino        fprintf (file, "%d [style=filled, fillcolor=red]\n", i);
4897*e4b17023SJohn Marino 
4898*e4b17023SJohn Marino       if (v->succ)
4899*e4b17023SJohn Marino        for (e = v->succ; e; e = e->succ_next)
4900*e4b17023SJohn Marino          switch (RDGE_TYPE (e))
4901*e4b17023SJohn Marino            {
4902*e4b17023SJohn Marino            case input_dd:
4903*e4b17023SJohn Marino              fprintf (file, "%d -> %d [label=input] \n", i, e->dest);
4904*e4b17023SJohn Marino              break;
4905*e4b17023SJohn Marino 
4906*e4b17023SJohn Marino            case output_dd:
4907*e4b17023SJohn Marino              fprintf (file, "%d -> %d [label=output] \n", i, e->dest);
4908*e4b17023SJohn Marino              break;
4909*e4b17023SJohn Marino 
4910*e4b17023SJohn Marino            case flow_dd:
4911*e4b17023SJohn Marino              /* These are the most common dependences: don't print these. */
4912*e4b17023SJohn Marino              fprintf (file, "%d -> %d \n", i, e->dest);
4913*e4b17023SJohn Marino              break;
4914*e4b17023SJohn Marino 
4915*e4b17023SJohn Marino            case anti_dd:
4916*e4b17023SJohn Marino              fprintf (file, "%d -> %d [label=anti] \n", i, e->dest);
4917*e4b17023SJohn Marino              break;
4918*e4b17023SJohn Marino 
4919*e4b17023SJohn Marino            default:
4920*e4b17023SJohn Marino              gcc_unreachable ();
4921*e4b17023SJohn Marino            }
4922*e4b17023SJohn Marino     }
4923*e4b17023SJohn Marino 
4924*e4b17023SJohn Marino   fprintf (file, "}\n\n");
4925*e4b17023SJohn Marino }
4926*e4b17023SJohn Marino 
4927*e4b17023SJohn Marino /* Display the Reduced Dependence Graph using dotty.  */
4928*e4b17023SJohn Marino extern void dot_rdg (struct graph *);
4929*e4b17023SJohn Marino 
4930*e4b17023SJohn Marino DEBUG_FUNCTION void
dot_rdg(struct graph * rdg)4931*e4b17023SJohn Marino dot_rdg (struct graph *rdg)
4932*e4b17023SJohn Marino {
4933*e4b17023SJohn Marino   /* When debugging, enable the following code.  This cannot be used
4934*e4b17023SJohn Marino      in production compilers because it calls "system".  */
4935*e4b17023SJohn Marino #if 0
4936*e4b17023SJohn Marino   FILE *file = fopen ("/tmp/rdg.dot", "w");
4937*e4b17023SJohn Marino   gcc_assert (file != NULL);
4938*e4b17023SJohn Marino 
4939*e4b17023SJohn Marino   dot_rdg_1 (file, rdg);
4940*e4b17023SJohn Marino   fclose (file);
4941*e4b17023SJohn Marino 
4942*e4b17023SJohn Marino   system ("dotty /tmp/rdg.dot &");
4943*e4b17023SJohn Marino #else
4944*e4b17023SJohn Marino   dot_rdg_1 (stderr, rdg);
4945*e4b17023SJohn Marino #endif
4946*e4b17023SJohn Marino }
4947*e4b17023SJohn Marino 
4948*e4b17023SJohn Marino /* This structure is used for recording the mapping statement index in
4949*e4b17023SJohn Marino    the RDG.  */
4950*e4b17023SJohn Marino 
4951*e4b17023SJohn Marino struct GTY(()) rdg_vertex_info
4952*e4b17023SJohn Marino {
4953*e4b17023SJohn Marino   gimple stmt;
4954*e4b17023SJohn Marino   int index;
4955*e4b17023SJohn Marino };
4956*e4b17023SJohn Marino 
4957*e4b17023SJohn Marino /* Returns the index of STMT in RDG.  */
4958*e4b17023SJohn Marino 
4959*e4b17023SJohn Marino int
rdg_vertex_for_stmt(struct graph * rdg,gimple stmt)4960*e4b17023SJohn Marino rdg_vertex_for_stmt (struct graph *rdg, gimple stmt)
4961*e4b17023SJohn Marino {
4962*e4b17023SJohn Marino   struct rdg_vertex_info rvi, *slot;
4963*e4b17023SJohn Marino 
4964*e4b17023SJohn Marino   rvi.stmt = stmt;
4965*e4b17023SJohn Marino   slot = (struct rdg_vertex_info *) htab_find (rdg->indices, &rvi);
4966*e4b17023SJohn Marino 
4967*e4b17023SJohn Marino   if (!slot)
4968*e4b17023SJohn Marino     return -1;
4969*e4b17023SJohn Marino 
4970*e4b17023SJohn Marino   return slot->index;
4971*e4b17023SJohn Marino }
4972*e4b17023SJohn Marino 
4973*e4b17023SJohn Marino /* Creates an edge in RDG for each distance vector from DDR.  The
4974*e4b17023SJohn Marino    order that we keep track of in the RDG is the order in which
4975*e4b17023SJohn Marino    statements have to be executed.  */
4976*e4b17023SJohn Marino 
4977*e4b17023SJohn Marino static void
create_rdg_edge_for_ddr(struct graph * rdg,ddr_p ddr)4978*e4b17023SJohn Marino create_rdg_edge_for_ddr (struct graph *rdg, ddr_p ddr)
4979*e4b17023SJohn Marino {
4980*e4b17023SJohn Marino   struct graph_edge *e;
4981*e4b17023SJohn Marino   int va, vb;
4982*e4b17023SJohn Marino   data_reference_p dra = DDR_A (ddr);
4983*e4b17023SJohn Marino   data_reference_p drb = DDR_B (ddr);
4984*e4b17023SJohn Marino   unsigned level = ddr_dependence_level (ddr);
4985*e4b17023SJohn Marino 
4986*e4b17023SJohn Marino   /* For non scalar dependences, when the dependence is REVERSED,
4987*e4b17023SJohn Marino      statement B has to be executed before statement A.  */
4988*e4b17023SJohn Marino   if (level > 0
4989*e4b17023SJohn Marino       && !DDR_REVERSED_P (ddr))
4990*e4b17023SJohn Marino     {
4991*e4b17023SJohn Marino       data_reference_p tmp = dra;
4992*e4b17023SJohn Marino       dra = drb;
4993*e4b17023SJohn Marino       drb = tmp;
4994*e4b17023SJohn Marino     }
4995*e4b17023SJohn Marino 
4996*e4b17023SJohn Marino   va = rdg_vertex_for_stmt (rdg, DR_STMT (dra));
4997*e4b17023SJohn Marino   vb = rdg_vertex_for_stmt (rdg, DR_STMT (drb));
4998*e4b17023SJohn Marino 
4999*e4b17023SJohn Marino   if (va < 0 || vb < 0)
5000*e4b17023SJohn Marino     return;
5001*e4b17023SJohn Marino 
5002*e4b17023SJohn Marino   e = add_edge (rdg, va, vb);
5003*e4b17023SJohn Marino   e->data = XNEW (struct rdg_edge);
5004*e4b17023SJohn Marino 
5005*e4b17023SJohn Marino   RDGE_LEVEL (e) = level;
5006*e4b17023SJohn Marino   RDGE_RELATION (e) = ddr;
5007*e4b17023SJohn Marino 
5008*e4b17023SJohn Marino   /* Determines the type of the data dependence.  */
5009*e4b17023SJohn Marino   if (DR_IS_READ (dra) && DR_IS_READ (drb))
5010*e4b17023SJohn Marino     RDGE_TYPE (e) = input_dd;
5011*e4b17023SJohn Marino   else if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb))
5012*e4b17023SJohn Marino     RDGE_TYPE (e) = output_dd;
5013*e4b17023SJohn Marino   else if (DR_IS_WRITE (dra) && DR_IS_READ (drb))
5014*e4b17023SJohn Marino     RDGE_TYPE (e) = flow_dd;
5015*e4b17023SJohn Marino   else if (DR_IS_READ (dra) && DR_IS_WRITE (drb))
5016*e4b17023SJohn Marino     RDGE_TYPE (e) = anti_dd;
5017*e4b17023SJohn Marino }
5018*e4b17023SJohn Marino 
5019*e4b17023SJohn Marino /* Creates dependence edges in RDG for all the uses of DEF.  IDEF is
5020*e4b17023SJohn Marino    the index of DEF in RDG.  */
5021*e4b17023SJohn Marino 
5022*e4b17023SJohn Marino static void
create_rdg_edges_for_scalar(struct graph * rdg,tree def,int idef)5023*e4b17023SJohn Marino create_rdg_edges_for_scalar (struct graph *rdg, tree def, int idef)
5024*e4b17023SJohn Marino {
5025*e4b17023SJohn Marino   use_operand_p imm_use_p;
5026*e4b17023SJohn Marino   imm_use_iterator iterator;
5027*e4b17023SJohn Marino 
5028*e4b17023SJohn Marino   FOR_EACH_IMM_USE_FAST (imm_use_p, iterator, def)
5029*e4b17023SJohn Marino     {
5030*e4b17023SJohn Marino       struct graph_edge *e;
5031*e4b17023SJohn Marino       int use = rdg_vertex_for_stmt (rdg, USE_STMT (imm_use_p));
5032*e4b17023SJohn Marino 
5033*e4b17023SJohn Marino       if (use < 0)
5034*e4b17023SJohn Marino 	continue;
5035*e4b17023SJohn Marino 
5036*e4b17023SJohn Marino       e = add_edge (rdg, idef, use);
5037*e4b17023SJohn Marino       e->data = XNEW (struct rdg_edge);
5038*e4b17023SJohn Marino       RDGE_TYPE (e) = flow_dd;
5039*e4b17023SJohn Marino       RDGE_RELATION (e) = NULL;
5040*e4b17023SJohn Marino     }
5041*e4b17023SJohn Marino }
5042*e4b17023SJohn Marino 
5043*e4b17023SJohn Marino /* Creates the edges of the reduced dependence graph RDG.  */
5044*e4b17023SJohn Marino 
5045*e4b17023SJohn Marino static void
create_rdg_edges(struct graph * rdg,VEC (ddr_p,heap)* ddrs)5046*e4b17023SJohn Marino create_rdg_edges (struct graph *rdg, VEC (ddr_p, heap) *ddrs)
5047*e4b17023SJohn Marino {
5048*e4b17023SJohn Marino   int i;
5049*e4b17023SJohn Marino   struct data_dependence_relation *ddr;
5050*e4b17023SJohn Marino   def_operand_p def_p;
5051*e4b17023SJohn Marino   ssa_op_iter iter;
5052*e4b17023SJohn Marino 
5053*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (ddr_p, ddrs, i, ddr)
5054*e4b17023SJohn Marino     if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE)
5055*e4b17023SJohn Marino       create_rdg_edge_for_ddr (rdg, ddr);
5056*e4b17023SJohn Marino 
5057*e4b17023SJohn Marino   for (i = 0; i < rdg->n_vertices; i++)
5058*e4b17023SJohn Marino     FOR_EACH_PHI_OR_STMT_DEF (def_p, RDG_STMT (rdg, i),
5059*e4b17023SJohn Marino 			      iter, SSA_OP_DEF)
5060*e4b17023SJohn Marino       create_rdg_edges_for_scalar (rdg, DEF_FROM_PTR (def_p), i);
5061*e4b17023SJohn Marino }
5062*e4b17023SJohn Marino 
5063*e4b17023SJohn Marino /* Build the vertices of the reduced dependence graph RDG.  */
5064*e4b17023SJohn Marino 
5065*e4b17023SJohn Marino void
create_rdg_vertices(struct graph * rdg,VEC (gimple,heap)* stmts)5066*e4b17023SJohn Marino create_rdg_vertices (struct graph *rdg, VEC (gimple, heap) *stmts)
5067*e4b17023SJohn Marino {
5068*e4b17023SJohn Marino   int i, j;
5069*e4b17023SJohn Marino   gimple stmt;
5070*e4b17023SJohn Marino 
5071*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (gimple, stmts, i, stmt)
5072*e4b17023SJohn Marino     {
5073*e4b17023SJohn Marino       VEC (data_ref_loc, heap) *references;
5074*e4b17023SJohn Marino       data_ref_loc *ref;
5075*e4b17023SJohn Marino       struct vertex *v = &(rdg->vertices[i]);
5076*e4b17023SJohn Marino       struct rdg_vertex_info *rvi = XNEW (struct rdg_vertex_info);
5077*e4b17023SJohn Marino       struct rdg_vertex_info **slot;
5078*e4b17023SJohn Marino 
5079*e4b17023SJohn Marino       rvi->stmt = stmt;
5080*e4b17023SJohn Marino       rvi->index = i;
5081*e4b17023SJohn Marino       slot = (struct rdg_vertex_info **) htab_find_slot (rdg->indices, rvi, INSERT);
5082*e4b17023SJohn Marino 
5083*e4b17023SJohn Marino       if (!*slot)
5084*e4b17023SJohn Marino 	*slot = rvi;
5085*e4b17023SJohn Marino       else
5086*e4b17023SJohn Marino 	free (rvi);
5087*e4b17023SJohn Marino 
5088*e4b17023SJohn Marino       v->data = XNEW (struct rdg_vertex);
5089*e4b17023SJohn Marino       RDG_STMT (rdg, i) = stmt;
5090*e4b17023SJohn Marino 
5091*e4b17023SJohn Marino       RDG_MEM_WRITE_STMT (rdg, i) = false;
5092*e4b17023SJohn Marino       RDG_MEM_READS_STMT (rdg, i) = false;
5093*e4b17023SJohn Marino       if (gimple_code (stmt) == GIMPLE_PHI)
5094*e4b17023SJohn Marino 	continue;
5095*e4b17023SJohn Marino 
5096*e4b17023SJohn Marino       get_references_in_stmt (stmt, &references);
5097*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (data_ref_loc, references, j, ref)
5098*e4b17023SJohn Marino 	if (!ref->is_read)
5099*e4b17023SJohn Marino 	  RDG_MEM_WRITE_STMT (rdg, i) = true;
5100*e4b17023SJohn Marino 	else
5101*e4b17023SJohn Marino 	  RDG_MEM_READS_STMT (rdg, i) = true;
5102*e4b17023SJohn Marino 
5103*e4b17023SJohn Marino       VEC_free (data_ref_loc, heap, references);
5104*e4b17023SJohn Marino     }
5105*e4b17023SJohn Marino }
5106*e4b17023SJohn Marino 
5107*e4b17023SJohn Marino /* Initialize STMTS with all the statements of LOOP.  When
5108*e4b17023SJohn Marino    INCLUDE_PHIS is true, include also the PHI nodes.  The order in
5109*e4b17023SJohn Marino    which we discover statements is important as
5110*e4b17023SJohn Marino    generate_loops_for_partition is using the same traversal for
5111*e4b17023SJohn Marino    identifying statements. */
5112*e4b17023SJohn Marino 
5113*e4b17023SJohn Marino static void
stmts_from_loop(struct loop * loop,VEC (gimple,heap)** stmts)5114*e4b17023SJohn Marino stmts_from_loop (struct loop *loop, VEC (gimple, heap) **stmts)
5115*e4b17023SJohn Marino {
5116*e4b17023SJohn Marino   unsigned int i;
5117*e4b17023SJohn Marino   basic_block *bbs = get_loop_body_in_dom_order (loop);
5118*e4b17023SJohn Marino 
5119*e4b17023SJohn Marino   for (i = 0; i < loop->num_nodes; i++)
5120*e4b17023SJohn Marino     {
5121*e4b17023SJohn Marino       basic_block bb = bbs[i];
5122*e4b17023SJohn Marino       gimple_stmt_iterator bsi;
5123*e4b17023SJohn Marino       gimple stmt;
5124*e4b17023SJohn Marino 
5125*e4b17023SJohn Marino       for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi))
5126*e4b17023SJohn Marino 	VEC_safe_push (gimple, heap, *stmts, gsi_stmt (bsi));
5127*e4b17023SJohn Marino 
5128*e4b17023SJohn Marino       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
5129*e4b17023SJohn Marino 	{
5130*e4b17023SJohn Marino 	  stmt = gsi_stmt (bsi);
5131*e4b17023SJohn Marino 	  if (gimple_code (stmt) != GIMPLE_LABEL && !is_gimple_debug (stmt))
5132*e4b17023SJohn Marino 	    VEC_safe_push (gimple, heap, *stmts, stmt);
5133*e4b17023SJohn Marino 	}
5134*e4b17023SJohn Marino     }
5135*e4b17023SJohn Marino 
5136*e4b17023SJohn Marino   free (bbs);
5137*e4b17023SJohn Marino }
5138*e4b17023SJohn Marino 
5139*e4b17023SJohn Marino /* Returns true when all the dependences are computable.  */
5140*e4b17023SJohn Marino 
5141*e4b17023SJohn Marino static bool
known_dependences_p(VEC (ddr_p,heap)* dependence_relations)5142*e4b17023SJohn Marino known_dependences_p (VEC (ddr_p, heap) *dependence_relations)
5143*e4b17023SJohn Marino {
5144*e4b17023SJohn Marino   ddr_p ddr;
5145*e4b17023SJohn Marino   unsigned int i;
5146*e4b17023SJohn Marino 
5147*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (ddr_p, dependence_relations, i, ddr)
5148*e4b17023SJohn Marino     if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
5149*e4b17023SJohn Marino       return false;
5150*e4b17023SJohn Marino 
5151*e4b17023SJohn Marino   return true;
5152*e4b17023SJohn Marino }
5153*e4b17023SJohn Marino 
5154*e4b17023SJohn Marino /* Computes a hash function for element ELT.  */
5155*e4b17023SJohn Marino 
5156*e4b17023SJohn Marino static hashval_t
hash_stmt_vertex_info(const void * elt)5157*e4b17023SJohn Marino hash_stmt_vertex_info (const void *elt)
5158*e4b17023SJohn Marino {
5159*e4b17023SJohn Marino   const struct rdg_vertex_info *const rvi =
5160*e4b17023SJohn Marino     (const struct rdg_vertex_info *) elt;
5161*e4b17023SJohn Marino   gimple stmt = rvi->stmt;
5162*e4b17023SJohn Marino 
5163*e4b17023SJohn Marino   return htab_hash_pointer (stmt);
5164*e4b17023SJohn Marino }
5165*e4b17023SJohn Marino 
5166*e4b17023SJohn Marino /* Compares database elements E1 and E2.  */
5167*e4b17023SJohn Marino 
5168*e4b17023SJohn Marino static int
eq_stmt_vertex_info(const void * e1,const void * e2)5169*e4b17023SJohn Marino eq_stmt_vertex_info (const void *e1, const void *e2)
5170*e4b17023SJohn Marino {
5171*e4b17023SJohn Marino   const struct rdg_vertex_info *elt1 = (const struct rdg_vertex_info *) e1;
5172*e4b17023SJohn Marino   const struct rdg_vertex_info *elt2 = (const struct rdg_vertex_info *) e2;
5173*e4b17023SJohn Marino 
5174*e4b17023SJohn Marino   return elt1->stmt == elt2->stmt;
5175*e4b17023SJohn Marino }
5176*e4b17023SJohn Marino 
5177*e4b17023SJohn Marino /* Free the element E.  */
5178*e4b17023SJohn Marino 
5179*e4b17023SJohn Marino static void
hash_stmt_vertex_del(void * e)5180*e4b17023SJohn Marino hash_stmt_vertex_del (void *e)
5181*e4b17023SJohn Marino {
5182*e4b17023SJohn Marino   free (e);
5183*e4b17023SJohn Marino }
5184*e4b17023SJohn Marino 
5185*e4b17023SJohn Marino /* Build the Reduced Dependence Graph (RDG) with one vertex per
5186*e4b17023SJohn Marino    statement of the loop nest, and one edge per data dependence or
5187*e4b17023SJohn Marino    scalar dependence.  */
5188*e4b17023SJohn Marino 
5189*e4b17023SJohn Marino struct graph *
build_empty_rdg(int n_stmts)5190*e4b17023SJohn Marino build_empty_rdg (int n_stmts)
5191*e4b17023SJohn Marino {
5192*e4b17023SJohn Marino   int nb_data_refs = 10;
5193*e4b17023SJohn Marino   struct graph *rdg = new_graph (n_stmts);
5194*e4b17023SJohn Marino 
5195*e4b17023SJohn Marino   rdg->indices = htab_create (nb_data_refs, hash_stmt_vertex_info,
5196*e4b17023SJohn Marino 			      eq_stmt_vertex_info, hash_stmt_vertex_del);
5197*e4b17023SJohn Marino   return rdg;
5198*e4b17023SJohn Marino }
5199*e4b17023SJohn Marino 
5200*e4b17023SJohn Marino /* Build the Reduced Dependence Graph (RDG) with one vertex per
5201*e4b17023SJohn Marino    statement of the loop nest, and one edge per data dependence or
5202*e4b17023SJohn Marino    scalar dependence.  */
5203*e4b17023SJohn Marino 
5204*e4b17023SJohn Marino struct graph *
build_rdg(struct loop * loop,VEC (loop_p,heap)** loop_nest,VEC (ddr_p,heap)** dependence_relations,VEC (data_reference_p,heap)** datarefs)5205*e4b17023SJohn Marino build_rdg (struct loop *loop,
5206*e4b17023SJohn Marino 	   VEC (loop_p, heap) **loop_nest,
5207*e4b17023SJohn Marino 	   VEC (ddr_p, heap) **dependence_relations,
5208*e4b17023SJohn Marino 	   VEC (data_reference_p, heap) **datarefs)
5209*e4b17023SJohn Marino {
5210*e4b17023SJohn Marino   struct graph *rdg = NULL;
5211*e4b17023SJohn Marino 
5212*e4b17023SJohn Marino   if (compute_data_dependences_for_loop (loop, false, loop_nest, datarefs,
5213*e4b17023SJohn Marino 					 dependence_relations)
5214*e4b17023SJohn Marino       && known_dependences_p (*dependence_relations))
5215*e4b17023SJohn Marino     {
5216*e4b17023SJohn Marino       VEC (gimple, heap) *stmts = VEC_alloc (gimple, heap, 10);
5217*e4b17023SJohn Marino       stmts_from_loop (loop, &stmts);
5218*e4b17023SJohn Marino       rdg = build_empty_rdg (VEC_length (gimple, stmts));
5219*e4b17023SJohn Marino       create_rdg_vertices (rdg, stmts);
5220*e4b17023SJohn Marino       create_rdg_edges (rdg, *dependence_relations);
5221*e4b17023SJohn Marino       VEC_free (gimple, heap, stmts);
5222*e4b17023SJohn Marino     }
5223*e4b17023SJohn Marino 
5224*e4b17023SJohn Marino   return rdg;
5225*e4b17023SJohn Marino }
5226*e4b17023SJohn Marino 
5227*e4b17023SJohn Marino /* Free the reduced dependence graph RDG.  */
5228*e4b17023SJohn Marino 
5229*e4b17023SJohn Marino void
free_rdg(struct graph * rdg)5230*e4b17023SJohn Marino free_rdg (struct graph *rdg)
5231*e4b17023SJohn Marino {
5232*e4b17023SJohn Marino   int i;
5233*e4b17023SJohn Marino 
5234*e4b17023SJohn Marino   for (i = 0; i < rdg->n_vertices; i++)
5235*e4b17023SJohn Marino     {
5236*e4b17023SJohn Marino       struct vertex *v = &(rdg->vertices[i]);
5237*e4b17023SJohn Marino       struct graph_edge *e;
5238*e4b17023SJohn Marino 
5239*e4b17023SJohn Marino       for (e = v->succ; e; e = e->succ_next)
5240*e4b17023SJohn Marino 	free (e->data);
5241*e4b17023SJohn Marino 
5242*e4b17023SJohn Marino       free (v->data);
5243*e4b17023SJohn Marino     }
5244*e4b17023SJohn Marino 
5245*e4b17023SJohn Marino   htab_delete (rdg->indices);
5246*e4b17023SJohn Marino   free_graph (rdg);
5247*e4b17023SJohn Marino }
5248*e4b17023SJohn Marino 
5249*e4b17023SJohn Marino /* Initialize STMTS with all the statements of LOOP that contain a
5250*e4b17023SJohn Marino    store to memory.  */
5251*e4b17023SJohn Marino 
5252*e4b17023SJohn Marino void
stores_from_loop(struct loop * loop,VEC (gimple,heap)** stmts)5253*e4b17023SJohn Marino stores_from_loop (struct loop *loop, VEC (gimple, heap) **stmts)
5254*e4b17023SJohn Marino {
5255*e4b17023SJohn Marino   unsigned int i;
5256*e4b17023SJohn Marino   basic_block *bbs = get_loop_body_in_dom_order (loop);
5257*e4b17023SJohn Marino 
5258*e4b17023SJohn Marino   for (i = 0; i < loop->num_nodes; i++)
5259*e4b17023SJohn Marino     {
5260*e4b17023SJohn Marino       basic_block bb = bbs[i];
5261*e4b17023SJohn Marino       gimple_stmt_iterator bsi;
5262*e4b17023SJohn Marino 
5263*e4b17023SJohn Marino       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
5264*e4b17023SJohn Marino 	if (gimple_vdef (gsi_stmt (bsi)))
5265*e4b17023SJohn Marino 	  VEC_safe_push (gimple, heap, *stmts, gsi_stmt (bsi));
5266*e4b17023SJohn Marino     }
5267*e4b17023SJohn Marino 
5268*e4b17023SJohn Marino   free (bbs);
5269*e4b17023SJohn Marino }
5270*e4b17023SJohn Marino 
5271*e4b17023SJohn Marino /* Returns true when the statement at STMT is of the form "A[i] = 0"
5272*e4b17023SJohn Marino    that contains a data reference on its LHS with a stride of the same
5273*e4b17023SJohn Marino    size as its unit type.  */
5274*e4b17023SJohn Marino 
5275*e4b17023SJohn Marino bool
stmt_with_adjacent_zero_store_dr_p(gimple stmt)5276*e4b17023SJohn Marino stmt_with_adjacent_zero_store_dr_p (gimple stmt)
5277*e4b17023SJohn Marino {
5278*e4b17023SJohn Marino   tree lhs, rhs;
5279*e4b17023SJohn Marino   bool res;
5280*e4b17023SJohn Marino   struct data_reference *dr;
5281*e4b17023SJohn Marino 
5282*e4b17023SJohn Marino   if (!stmt
5283*e4b17023SJohn Marino       || !gimple_vdef (stmt)
5284*e4b17023SJohn Marino       || !gimple_assign_single_p (stmt))
5285*e4b17023SJohn Marino     return false;
5286*e4b17023SJohn Marino 
5287*e4b17023SJohn Marino   lhs = gimple_assign_lhs (stmt);
5288*e4b17023SJohn Marino   rhs = gimple_assign_rhs1 (stmt);
5289*e4b17023SJohn Marino 
5290*e4b17023SJohn Marino   /* If this is a bitfield store bail out.  */
5291*e4b17023SJohn Marino   if (TREE_CODE (lhs) == COMPONENT_REF
5292*e4b17023SJohn Marino       && DECL_BIT_FIELD (TREE_OPERAND (lhs, 1)))
5293*e4b17023SJohn Marino     return false;
5294*e4b17023SJohn Marino 
5295*e4b17023SJohn Marino   if (!(integer_zerop (rhs) || real_zerop (rhs)))
5296*e4b17023SJohn Marino     return false;
5297*e4b17023SJohn Marino 
5298*e4b17023SJohn Marino   dr = XCNEW (struct data_reference);
5299*e4b17023SJohn Marino 
5300*e4b17023SJohn Marino   DR_STMT (dr) = stmt;
5301*e4b17023SJohn Marino   DR_REF (dr) = lhs;
5302*e4b17023SJohn Marino 
5303*e4b17023SJohn Marino   res = dr_analyze_innermost (dr, loop_containing_stmt (stmt))
5304*e4b17023SJohn Marino     && stride_of_unit_type_p (DR_STEP (dr), TREE_TYPE (lhs));
5305*e4b17023SJohn Marino 
5306*e4b17023SJohn Marino   free_data_ref (dr);
5307*e4b17023SJohn Marino   return res;
5308*e4b17023SJohn Marino }
5309*e4b17023SJohn Marino 
5310*e4b17023SJohn Marino /* Initialize STMTS with all the statements of LOOP that contain a
5311*e4b17023SJohn Marino    store to memory of the form "A[i] = 0".  */
5312*e4b17023SJohn Marino 
5313*e4b17023SJohn Marino void
stores_zero_from_loop(struct loop * loop,VEC (gimple,heap)** stmts)5314*e4b17023SJohn Marino stores_zero_from_loop (struct loop *loop, VEC (gimple, heap) **stmts)
5315*e4b17023SJohn Marino {
5316*e4b17023SJohn Marino   unsigned int i;
5317*e4b17023SJohn Marino   basic_block bb;
5318*e4b17023SJohn Marino   gimple_stmt_iterator si;
5319*e4b17023SJohn Marino   gimple stmt;
5320*e4b17023SJohn Marino   basic_block *bbs = get_loop_body_in_dom_order (loop);
5321*e4b17023SJohn Marino 
5322*e4b17023SJohn Marino   for (i = 0; i < loop->num_nodes; i++)
5323*e4b17023SJohn Marino     for (bb = bbs[i], si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
5324*e4b17023SJohn Marino       if ((stmt = gsi_stmt (si))
5325*e4b17023SJohn Marino 	  && stmt_with_adjacent_zero_store_dr_p (stmt))
5326*e4b17023SJohn Marino 	VEC_safe_push (gimple, heap, *stmts, gsi_stmt (si));
5327*e4b17023SJohn Marino 
5328*e4b17023SJohn Marino   free (bbs);
5329*e4b17023SJohn Marino }
5330*e4b17023SJohn Marino 
5331*e4b17023SJohn Marino /* For a data reference REF, return the declaration of its base
5332*e4b17023SJohn Marino    address or NULL_TREE if the base is not determined.  */
5333*e4b17023SJohn Marino 
5334*e4b17023SJohn Marino static inline tree
ref_base_address(gimple stmt,data_ref_loc * ref)5335*e4b17023SJohn Marino ref_base_address (gimple stmt, data_ref_loc *ref)
5336*e4b17023SJohn Marino {
5337*e4b17023SJohn Marino   tree base = NULL_TREE;
5338*e4b17023SJohn Marino   tree base_address;
5339*e4b17023SJohn Marino   struct data_reference *dr = XCNEW (struct data_reference);
5340*e4b17023SJohn Marino 
5341*e4b17023SJohn Marino   DR_STMT (dr) = stmt;
5342*e4b17023SJohn Marino   DR_REF (dr) = *ref->pos;
5343*e4b17023SJohn Marino   dr_analyze_innermost (dr, loop_containing_stmt (stmt));
5344*e4b17023SJohn Marino   base_address = DR_BASE_ADDRESS (dr);
5345*e4b17023SJohn Marino 
5346*e4b17023SJohn Marino   if (!base_address)
5347*e4b17023SJohn Marino     goto end;
5348*e4b17023SJohn Marino 
5349*e4b17023SJohn Marino   switch (TREE_CODE (base_address))
5350*e4b17023SJohn Marino     {
5351*e4b17023SJohn Marino     case ADDR_EXPR:
5352*e4b17023SJohn Marino       base = TREE_OPERAND (base_address, 0);
5353*e4b17023SJohn Marino       break;
5354*e4b17023SJohn Marino 
5355*e4b17023SJohn Marino     default:
5356*e4b17023SJohn Marino       base = base_address;
5357*e4b17023SJohn Marino       break;
5358*e4b17023SJohn Marino     }
5359*e4b17023SJohn Marino 
5360*e4b17023SJohn Marino  end:
5361*e4b17023SJohn Marino   free_data_ref (dr);
5362*e4b17023SJohn Marino   return base;
5363*e4b17023SJohn Marino }
5364*e4b17023SJohn Marino 
5365*e4b17023SJohn Marino /* Determines whether the statement from vertex V of the RDG has a
5366*e4b17023SJohn Marino    definition used outside the loop that contains this statement.  */
5367*e4b17023SJohn Marino 
5368*e4b17023SJohn Marino bool
rdg_defs_used_in_other_loops_p(struct graph * rdg,int v)5369*e4b17023SJohn Marino rdg_defs_used_in_other_loops_p (struct graph *rdg, int v)
5370*e4b17023SJohn Marino {
5371*e4b17023SJohn Marino   gimple stmt = RDG_STMT (rdg, v);
5372*e4b17023SJohn Marino   struct loop *loop = loop_containing_stmt (stmt);
5373*e4b17023SJohn Marino   use_operand_p imm_use_p;
5374*e4b17023SJohn Marino   imm_use_iterator iterator;
5375*e4b17023SJohn Marino   ssa_op_iter it;
5376*e4b17023SJohn Marino   def_operand_p def_p;
5377*e4b17023SJohn Marino 
5378*e4b17023SJohn Marino   if (!loop)
5379*e4b17023SJohn Marino     return true;
5380*e4b17023SJohn Marino 
5381*e4b17023SJohn Marino   FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, it, SSA_OP_DEF)
5382*e4b17023SJohn Marino     {
5383*e4b17023SJohn Marino       FOR_EACH_IMM_USE_FAST (imm_use_p, iterator, DEF_FROM_PTR (def_p))
5384*e4b17023SJohn Marino 	{
5385*e4b17023SJohn Marino 	  if (loop_containing_stmt (USE_STMT (imm_use_p)) != loop)
5386*e4b17023SJohn Marino 	    return true;
5387*e4b17023SJohn Marino 	}
5388*e4b17023SJohn Marino     }
5389*e4b17023SJohn Marino 
5390*e4b17023SJohn Marino   return false;
5391*e4b17023SJohn Marino }
5392*e4b17023SJohn Marino 
5393*e4b17023SJohn Marino /* Determines whether statements S1 and S2 access to similar memory
5394*e4b17023SJohn Marino    locations.  Two memory accesses are considered similar when they
5395*e4b17023SJohn Marino    have the same base address declaration, i.e. when their
5396*e4b17023SJohn Marino    ref_base_address is the same.  */
5397*e4b17023SJohn Marino 
5398*e4b17023SJohn Marino bool
have_similar_memory_accesses(gimple s1,gimple s2)5399*e4b17023SJohn Marino have_similar_memory_accesses (gimple s1, gimple s2)
5400*e4b17023SJohn Marino {
5401*e4b17023SJohn Marino   bool res = false;
5402*e4b17023SJohn Marino   unsigned i, j;
5403*e4b17023SJohn Marino   VEC (data_ref_loc, heap) *refs1, *refs2;
5404*e4b17023SJohn Marino   data_ref_loc *ref1, *ref2;
5405*e4b17023SJohn Marino 
5406*e4b17023SJohn Marino   get_references_in_stmt (s1, &refs1);
5407*e4b17023SJohn Marino   get_references_in_stmt (s2, &refs2);
5408*e4b17023SJohn Marino 
5409*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (data_ref_loc, refs1, i, ref1)
5410*e4b17023SJohn Marino     {
5411*e4b17023SJohn Marino       tree base1 = ref_base_address (s1, ref1);
5412*e4b17023SJohn Marino 
5413*e4b17023SJohn Marino       if (base1)
5414*e4b17023SJohn Marino 	FOR_EACH_VEC_ELT (data_ref_loc, refs2, j, ref2)
5415*e4b17023SJohn Marino 	  if (base1 == ref_base_address (s2, ref2))
5416*e4b17023SJohn Marino 	    {
5417*e4b17023SJohn Marino 	      res = true;
5418*e4b17023SJohn Marino 	      goto end;
5419*e4b17023SJohn Marino 	    }
5420*e4b17023SJohn Marino     }
5421*e4b17023SJohn Marino 
5422*e4b17023SJohn Marino  end:
5423*e4b17023SJohn Marino   VEC_free (data_ref_loc, heap, refs1);
5424*e4b17023SJohn Marino   VEC_free (data_ref_loc, heap, refs2);
5425*e4b17023SJohn Marino   return res;
5426*e4b17023SJohn Marino }
5427*e4b17023SJohn Marino 
5428*e4b17023SJohn Marino /* Helper function for the hashtab.  */
5429*e4b17023SJohn Marino 
5430*e4b17023SJohn Marino static int
have_similar_memory_accesses_1(const void * s1,const void * s2)5431*e4b17023SJohn Marino have_similar_memory_accesses_1 (const void *s1, const void *s2)
5432*e4b17023SJohn Marino {
5433*e4b17023SJohn Marino   return have_similar_memory_accesses (CONST_CAST_GIMPLE ((const_gimple) s1),
5434*e4b17023SJohn Marino 				       CONST_CAST_GIMPLE ((const_gimple) s2));
5435*e4b17023SJohn Marino }
5436*e4b17023SJohn Marino 
5437*e4b17023SJohn Marino /* Helper function for the hashtab.  */
5438*e4b17023SJohn Marino 
5439*e4b17023SJohn Marino static hashval_t
ref_base_address_1(const void * s)5440*e4b17023SJohn Marino ref_base_address_1 (const void *s)
5441*e4b17023SJohn Marino {
5442*e4b17023SJohn Marino   gimple stmt = CONST_CAST_GIMPLE ((const_gimple) s);
5443*e4b17023SJohn Marino   unsigned i;
5444*e4b17023SJohn Marino   VEC (data_ref_loc, heap) *refs;
5445*e4b17023SJohn Marino   data_ref_loc *ref;
5446*e4b17023SJohn Marino   hashval_t res = 0;
5447*e4b17023SJohn Marino 
5448*e4b17023SJohn Marino   get_references_in_stmt (stmt, &refs);
5449*e4b17023SJohn Marino 
5450*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (data_ref_loc, refs, i, ref)
5451*e4b17023SJohn Marino     if (!ref->is_read)
5452*e4b17023SJohn Marino       {
5453*e4b17023SJohn Marino 	res = htab_hash_pointer (ref_base_address (stmt, ref));
5454*e4b17023SJohn Marino 	break;
5455*e4b17023SJohn Marino       }
5456*e4b17023SJohn Marino 
5457*e4b17023SJohn Marino   VEC_free (data_ref_loc, heap, refs);
5458*e4b17023SJohn Marino   return res;
5459*e4b17023SJohn Marino }
5460*e4b17023SJohn Marino 
5461*e4b17023SJohn Marino /* Try to remove duplicated write data references from STMTS.  */
5462*e4b17023SJohn Marino 
5463*e4b17023SJohn Marino void
remove_similar_memory_refs(VEC (gimple,heap)** stmts)5464*e4b17023SJohn Marino remove_similar_memory_refs (VEC (gimple, heap) **stmts)
5465*e4b17023SJohn Marino {
5466*e4b17023SJohn Marino   unsigned i;
5467*e4b17023SJohn Marino   gimple stmt;
5468*e4b17023SJohn Marino   htab_t seen = htab_create (VEC_length (gimple, *stmts), ref_base_address_1,
5469*e4b17023SJohn Marino 			     have_similar_memory_accesses_1, NULL);
5470*e4b17023SJohn Marino 
5471*e4b17023SJohn Marino   for (i = 0; VEC_iterate (gimple, *stmts, i, stmt); )
5472*e4b17023SJohn Marino     {
5473*e4b17023SJohn Marino       void **slot;
5474*e4b17023SJohn Marino 
5475*e4b17023SJohn Marino       slot = htab_find_slot (seen, stmt, INSERT);
5476*e4b17023SJohn Marino 
5477*e4b17023SJohn Marino       if (*slot)
5478*e4b17023SJohn Marino 	VEC_ordered_remove (gimple, *stmts, i);
5479*e4b17023SJohn Marino       else
5480*e4b17023SJohn Marino 	{
5481*e4b17023SJohn Marino 	  *slot = (void *) stmt;
5482*e4b17023SJohn Marino 	  i++;
5483*e4b17023SJohn Marino 	}
5484*e4b17023SJohn Marino     }
5485*e4b17023SJohn Marino 
5486*e4b17023SJohn Marino   htab_delete (seen);
5487*e4b17023SJohn Marino }
5488*e4b17023SJohn Marino 
5489*e4b17023SJohn Marino /* Returns the index of PARAMETER in the parameters vector of the
5490*e4b17023SJohn Marino    ACCESS_MATRIX.  If PARAMETER does not exist return -1.  */
5491*e4b17023SJohn Marino 
5492*e4b17023SJohn Marino int
access_matrix_get_index_for_parameter(tree parameter,struct access_matrix * access_matrix)5493*e4b17023SJohn Marino access_matrix_get_index_for_parameter (tree parameter,
5494*e4b17023SJohn Marino 				       struct access_matrix *access_matrix)
5495*e4b17023SJohn Marino {
5496*e4b17023SJohn Marino   int i;
5497*e4b17023SJohn Marino   VEC (tree,heap) *lambda_parameters = AM_PARAMETERS (access_matrix);
5498*e4b17023SJohn Marino   tree lambda_parameter;
5499*e4b17023SJohn Marino 
5500*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (tree, lambda_parameters, i, lambda_parameter)
5501*e4b17023SJohn Marino     if (lambda_parameter == parameter)
5502*e4b17023SJohn Marino       return i + AM_NB_INDUCTION_VARS (access_matrix);
5503*e4b17023SJohn Marino 
5504*e4b17023SJohn Marino   return -1;
5505*e4b17023SJohn Marino }
5506