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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 * 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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