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