Home | History | Annotate | Line # | Download | only in gcc
      1  1.1  mrg /* Data dependence analysis for Graphite.
      2  1.1  mrg    Copyright (C) 2009-2022 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Sebastian Pop <sebastian.pop (at) amd.com> and
      4  1.1  mrg    Konrad Trifunovic <konrad.trifunovic (at) inria.fr>.
      5  1.1  mrg 
      6  1.1  mrg This file is part of GCC.
      7  1.1  mrg 
      8  1.1  mrg GCC is free software; you can redistribute it and/or modify
      9  1.1  mrg it under the terms of the GNU General Public License as published by
     10  1.1  mrg the Free Software Foundation; either version 3, or (at your option)
     11  1.1  mrg any later version.
     12  1.1  mrg 
     13  1.1  mrg GCC is distributed in the hope that it will be useful,
     14  1.1  mrg but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  1.1  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  1.1  mrg GNU General Public License for more details.
     17  1.1  mrg 
     18  1.1  mrg You should have received a copy of the GNU General Public License
     19  1.1  mrg along with GCC; see the file COPYING3.  If not see
     20  1.1  mrg <http://www.gnu.org/licenses/>.  */
     21  1.1  mrg 
     22  1.1  mrg #define INCLUDE_ISL
     23  1.1  mrg 
     24  1.1  mrg #include "config.h"
     25  1.1  mrg 
     26  1.1  mrg #ifdef HAVE_isl
     27  1.1  mrg 
     28  1.1  mrg #include "system.h"
     29  1.1  mrg #include "coretypes.h"
     30  1.1  mrg #include "backend.h"
     31  1.1  mrg #include "cfghooks.h"
     32  1.1  mrg #include "tree.h"
     33  1.1  mrg #include "gimple.h"
     34  1.1  mrg #include "fold-const.h"
     35  1.1  mrg #include "gimple-iterator.h"
     36  1.1  mrg #include "tree-ssa-loop.h"
     37  1.1  mrg #include "tree-pass.h"
     38  1.1  mrg #include "cfgloop.h"
     39  1.1  mrg #include "tree-data-ref.h"
     40  1.1  mrg #include "graphite.h"
     41  1.1  mrg 
     42  1.1  mrg /* Add the constraints from the set S to the domain of MAP.  */
     43  1.1  mrg 
     44  1.1  mrg static isl_map *
     45  1.1  mrg constrain_domain (isl_map *map, isl_set *s)
     46  1.1  mrg {
     47  1.1  mrg   isl_space *d = isl_map_get_space (map);
     48  1.1  mrg   isl_id *id = isl_space_get_tuple_id (d, isl_dim_in);
     49  1.1  mrg 
     50  1.1  mrg   s = isl_set_set_tuple_id (s, id);
     51  1.1  mrg   isl_space_free (d);
     52  1.1  mrg   return isl_map_coalesce (isl_map_intersect_domain (map, s));
     53  1.1  mrg }
     54  1.1  mrg 
     55  1.1  mrg /* Constrain pdr->accesses with pdr->subscript_sizes and pbb->domain.  */
     56  1.1  mrg 
     57  1.1  mrg static isl_map *
     58  1.1  mrg add_pdr_constraints (poly_dr_p pdr, poly_bb_p pbb)
     59  1.1  mrg {
     60  1.1  mrg   isl_map *x = isl_map_intersect_range (isl_map_copy (pdr->accesses),
     61  1.1  mrg 					isl_set_copy (pdr->subscript_sizes));
     62  1.1  mrg   x = isl_map_coalesce (x);
     63  1.1  mrg   return constrain_domain (x, isl_set_copy (pbb->domain));
     64  1.1  mrg }
     65  1.1  mrg 
     66  1.1  mrg /* Returns an isl description of all memory operations in SCOP.  The memory
     67  1.1  mrg    reads are returned in READS and writes in MUST_WRITES and MAY_WRITES.  */
     68  1.1  mrg 
     69  1.1  mrg static void
     70  1.1  mrg scop_get_reads_and_writes (scop_p scop, isl_union_map *&reads,
     71  1.1  mrg 			   isl_union_map *&must_writes,
     72  1.1  mrg 			   isl_union_map *&may_writes)
     73  1.1  mrg {
     74  1.1  mrg   int i, j;
     75  1.1  mrg   poly_bb_p pbb;
     76  1.1  mrg   poly_dr_p pdr;
     77  1.1  mrg 
     78  1.1  mrg   FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
     79  1.1  mrg     {
     80  1.1  mrg       FOR_EACH_VEC_ELT (PBB_DRS (pbb), j, pdr) {
     81  1.1  mrg 	if (pdr_read_p (pdr))
     82  1.1  mrg 	  {
     83  1.1  mrg 	    if (dump_file)
     84  1.1  mrg 	      {
     85  1.1  mrg 		fprintf (dump_file, "Adding read to depedence graph: ");
     86  1.1  mrg 		print_pdr (dump_file, pdr);
     87  1.1  mrg 	      }
     88  1.1  mrg 	    isl_union_map *um
     89  1.1  mrg 	      = isl_union_map_from_map (add_pdr_constraints (pdr, pbb));
     90  1.1  mrg 	    reads = isl_union_map_union (reads, um);
     91  1.1  mrg 	    if (dump_file)
     92  1.1  mrg 	      {
     93  1.1  mrg 		fprintf (dump_file, "Reads depedence graph: ");
     94  1.1  mrg 		print_isl_union_map (dump_file, reads);
     95  1.1  mrg 	      }
     96  1.1  mrg 	  }
     97  1.1  mrg 	else if (pdr_write_p (pdr))
     98  1.1  mrg 	  {
     99  1.1  mrg 	    if (dump_file)
    100  1.1  mrg 	      {
    101  1.1  mrg 		fprintf (dump_file, "Adding must write to depedence graph: ");
    102  1.1  mrg 		print_pdr (dump_file, pdr);
    103  1.1  mrg 	      }
    104  1.1  mrg 	    isl_union_map *um
    105  1.1  mrg 	      = isl_union_map_from_map (add_pdr_constraints (pdr, pbb));
    106  1.1  mrg 	    must_writes = isl_union_map_union (must_writes, um);
    107  1.1  mrg 	    if (dump_file)
    108  1.1  mrg 	      {
    109  1.1  mrg 		fprintf (dump_file, "Must writes depedence graph: ");
    110  1.1  mrg 		print_isl_union_map (dump_file, must_writes);
    111  1.1  mrg 	      }
    112  1.1  mrg 	  }
    113  1.1  mrg 	else if (pdr_may_write_p (pdr))
    114  1.1  mrg 	  {
    115  1.1  mrg 	    if (dump_file)
    116  1.1  mrg 	      {
    117  1.1  mrg 		fprintf (dump_file, "Adding may write to depedence graph: ");
    118  1.1  mrg 		print_pdr (dump_file, pdr);
    119  1.1  mrg 	      }
    120  1.1  mrg 	    isl_union_map *um
    121  1.1  mrg 	      = isl_union_map_from_map (add_pdr_constraints (pdr, pbb));
    122  1.1  mrg 	    may_writes = isl_union_map_union (may_writes, um);
    123  1.1  mrg 	    if (dump_file)
    124  1.1  mrg 	      {
    125  1.1  mrg 		fprintf (dump_file, "May writes depedence graph: ");
    126  1.1  mrg 		print_isl_union_map (dump_file, may_writes);
    127  1.1  mrg 	      }
    128  1.1  mrg 	  }
    129  1.1  mrg       }
    130  1.1  mrg     }
    131  1.1  mrg }
    132  1.1  mrg 
    133  1.1  mrg /* Helper function used on each MAP of a isl_union_map.  Computes the
    134  1.1  mrg    maximal output dimension.  */
    135  1.1  mrg 
    136  1.1  mrg static isl_stat
    137  1.1  mrg max_number_of_out_dimensions (__isl_take isl_map *map, void *user)
    138  1.1  mrg {
    139  1.1  mrg   int global_max = *((int *) user);
    140  1.1  mrg   isl_space *space = isl_map_get_space (map);
    141  1.1  mrg   int nb_out = isl_space_dim (space, isl_dim_out);
    142  1.1  mrg 
    143  1.1  mrg   if (global_max < nb_out)
    144  1.1  mrg     *((int *) user) = nb_out;
    145  1.1  mrg 
    146  1.1  mrg   isl_map_free (map);
    147  1.1  mrg   isl_space_free (space);
    148  1.1  mrg   return isl_stat_ok;
    149  1.1  mrg }
    150  1.1  mrg 
    151  1.1  mrg /* Extends the output dimension of MAP to MAX dimensions.  */
    152  1.1  mrg 
    153  1.1  mrg static __isl_give isl_map *
    154  1.1  mrg extend_map (__isl_take isl_map *map, int max)
    155  1.1  mrg {
    156  1.1  mrg   isl_space *space = isl_map_get_space (map);
    157  1.1  mrg   int n = isl_space_dim (space, isl_dim_out);
    158  1.1  mrg 
    159  1.1  mrg   isl_space_free (space);
    160  1.1  mrg   return isl_map_add_dims (map, isl_dim_out, max - n);
    161  1.1  mrg }
    162  1.1  mrg 
    163  1.1  mrg /* Structure used to pass parameters to extend_schedule_1.  */
    164  1.1  mrg 
    165  1.1  mrg struct extend_schedule_str {
    166  1.1  mrg   int max;
    167  1.1  mrg   isl_union_map *umap;
    168  1.1  mrg };
    169  1.1  mrg 
    170  1.1  mrg /* Helper function for extend_schedule.  */
    171  1.1  mrg 
    172  1.1  mrg static isl_stat
    173  1.1  mrg extend_schedule_1 (__isl_take isl_map *map, void *user)
    174  1.1  mrg {
    175  1.1  mrg   struct extend_schedule_str *str = (struct extend_schedule_str *) user;
    176  1.1  mrg   str->umap = isl_union_map_add_map (str->umap, extend_map (map, str->max));
    177  1.1  mrg   return isl_stat_ok;
    178  1.1  mrg }
    179  1.1  mrg 
    180  1.1  mrg /* Return a relation that has uniform output dimensions.  */
    181  1.1  mrg 
    182  1.1  mrg static __isl_give isl_union_map *
    183  1.1  mrg extend_schedule (__isl_take isl_union_map *x)
    184  1.1  mrg {
    185  1.1  mrg   int max = 0;
    186  1.1  mrg   struct extend_schedule_str str;
    187  1.1  mrg 
    188  1.1  mrg   isl_union_map_foreach_map (x, max_number_of_out_dimensions, (void *) &max);
    189  1.1  mrg   str.max = max;
    190  1.1  mrg   str.umap = isl_union_map_empty (isl_union_map_get_space (x));
    191  1.1  mrg   isl_union_map_foreach_map (x, extend_schedule_1, (void *) &str);
    192  1.1  mrg   isl_union_map_free (x);
    193  1.1  mrg   return isl_union_map_coalesce (str.umap);
    194  1.1  mrg }
    195  1.1  mrg 
    196  1.1  mrg /* Applies SCHEDULE to the in and out dimensions of the dependences
    197  1.1  mrg    DEPS and return the resulting relation.  */
    198  1.1  mrg 
    199  1.1  mrg static isl_map *
    200  1.1  mrg apply_schedule_on_deps (__isl_keep isl_union_map *schedule,
    201  1.1  mrg 			__isl_keep isl_union_map *deps)
    202  1.1  mrg {
    203  1.1  mrg   isl_union_map *trans = extend_schedule (isl_union_map_copy (schedule));
    204  1.1  mrg   isl_union_map *ux = isl_union_map_copy (deps);
    205  1.1  mrg   ux = isl_union_map_apply_domain (ux, isl_union_map_copy (trans));
    206  1.1  mrg   ux = isl_union_map_apply_range (ux, trans);
    207  1.1  mrg   ux = isl_union_map_coalesce (ux);
    208  1.1  mrg 
    209  1.1  mrg   if (!isl_union_map_is_empty (ux))
    210  1.1  mrg     return isl_map_from_union_map (ux);
    211  1.1  mrg 
    212  1.1  mrg   isl_union_map_free (ux);
    213  1.1  mrg   return NULL;
    214  1.1  mrg }
    215  1.1  mrg 
    216  1.1  mrg /* Return true when DEPS is non empty and the intersection of LEX with
    217  1.1  mrg    the DEPS transformed by SCHEDULE is non empty.  LEX is the relation
    218  1.1  mrg    in which all the inputs before DEPTH occur at the same time as the
    219  1.1  mrg    output, and the input at DEPTH occurs before output.  */
    220  1.1  mrg 
    221  1.1  mrg bool
    222  1.1  mrg carries_deps (__isl_keep isl_union_map *schedule,
    223  1.1  mrg 	      __isl_keep isl_union_map *deps,
    224  1.1  mrg 	      int depth)
    225  1.1  mrg {
    226  1.1  mrg   if (isl_union_map_is_empty (deps))
    227  1.1  mrg     return false;
    228  1.1  mrg 
    229  1.1  mrg   isl_map *x = apply_schedule_on_deps (schedule, deps);
    230  1.1  mrg   if (x == NULL)
    231  1.1  mrg     return false;
    232  1.1  mrg 
    233  1.1  mrg   isl_space *space = isl_map_get_space (x);
    234  1.1  mrg   isl_map *lex = isl_map_lex_le (isl_space_range (space));
    235  1.1  mrg   isl_constraint *ineq = isl_inequality_alloc
    236  1.1  mrg     (isl_local_space_from_space (isl_map_get_space (x)));
    237  1.1  mrg 
    238  1.1  mrg   for (int i = 0; i < depth - 1; i++)
    239  1.1  mrg     lex = isl_map_equate (lex, isl_dim_in, i, isl_dim_out, i);
    240  1.1  mrg 
    241  1.1  mrg   /* in + 1 <= out  */
    242  1.1  mrg   ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_out, depth - 1, 1);
    243  1.1  mrg   ineq = isl_constraint_set_coefficient_si (ineq, isl_dim_in, depth - 1, -1);
    244  1.1  mrg   ineq = isl_constraint_set_constant_si (ineq, -1);
    245  1.1  mrg   lex = isl_map_add_constraint (lex, ineq);
    246  1.1  mrg   lex = isl_map_coalesce (lex);
    247  1.1  mrg   x = isl_map_intersect (x, lex);
    248  1.1  mrg   bool res = !isl_map_is_empty (x);
    249  1.1  mrg 
    250  1.1  mrg   isl_map_free (x);
    251  1.1  mrg   return res;
    252  1.1  mrg }
    253  1.1  mrg 
    254  1.1  mrg /* Compute the dependence relations for the SCOP:
    255  1.1  mrg    RAW are read after write dependences,
    256  1.1  mrg    WAR are write after read dependences,
    257  1.1  mrg    WAW are write after write dependences.  */
    258  1.1  mrg 
    259  1.1  mrg void
    260  1.1  mrg scop_get_dependences (scop_p scop)
    261  1.1  mrg {
    262  1.1  mrg   if (scop->dependence)
    263  1.1  mrg     return;
    264  1.1  mrg 
    265  1.1  mrg   isl_space *space = isl_set_get_space (scop->param_context);
    266  1.1  mrg   isl_union_map *reads = isl_union_map_empty (isl_space_copy (space));
    267  1.1  mrg   isl_union_map *must_writes = isl_union_map_empty (isl_space_copy (space));
    268  1.1  mrg   isl_union_map *may_writes = isl_union_map_empty (space);
    269  1.1  mrg   scop_get_reads_and_writes (scop, reads, must_writes, may_writes);
    270  1.1  mrg 
    271  1.1  mrg   if (dump_file)
    272  1.1  mrg     {
    273  1.1  mrg       fprintf (dump_file, "\n--- Documentation for datarefs dump: ---\n");
    274  1.1  mrg       fprintf (dump_file, "Statements on the iteration domain are mapped to"
    275  1.1  mrg 	       " array references.\n");
    276  1.1  mrg       fprintf (dump_file, "  To read the following data references:\n\n");
    277  1.1  mrg       fprintf (dump_file, "  S_5[i0] -> [106] : i0 >= 0 and i0 <= 3\n");
    278  1.1  mrg       fprintf (dump_file, "  S_8[i0] -> [1, i0] : i0 >= 0 and i0 <= 3\n\n");
    279  1.1  mrg 
    280  1.1  mrg       fprintf (dump_file, "  S_5[i0] is the dynamic instance of statement"
    281  1.1  mrg 	       " bb_5 in a loop that accesses all iterations 0 <= i0 <= 3.\n");
    282  1.1  mrg       fprintf (dump_file, "  [1, i0] is a 'memref' with alias set 1"
    283  1.1  mrg 	       " and first subscript access i0.\n");
    284  1.1  mrg       fprintf (dump_file, "  [106] is a 'scalar reference' which is the sum of"
    285  1.1  mrg 	       " SSA_NAME_VERSION 6"
    286  1.1  mrg 	       " and --param graphite-max-arrays-per-scop=100\n");
    287  1.1  mrg       fprintf (dump_file, "-----------------------\n\n");
    288  1.1  mrg 
    289  1.1  mrg       fprintf (dump_file, "data references (\n");
    290  1.1  mrg       fprintf (dump_file, "  reads: ");
    291  1.1  mrg       print_isl_union_map (dump_file, reads);
    292  1.1  mrg       fprintf (dump_file, "  must_writes: ");
    293  1.1  mrg       print_isl_union_map (dump_file, must_writes);
    294  1.1  mrg       fprintf (dump_file, "  may_writes: ");
    295  1.1  mrg       print_isl_union_map (dump_file, may_writes);
    296  1.1  mrg       fprintf (dump_file, ")\n");
    297  1.1  mrg     }
    298  1.1  mrg 
    299  1.1  mrg   gcc_assert (scop->original_schedule);
    300  1.1  mrg 
    301  1.1  mrg   isl_union_access_info *ai;
    302  1.1  mrg   ai = isl_union_access_info_from_sink (isl_union_map_copy (reads));
    303  1.1  mrg   ai = isl_union_access_info_set_must_source (ai, isl_union_map_copy (must_writes));
    304  1.1  mrg   ai = isl_union_access_info_set_may_source (ai, may_writes);
    305  1.1  mrg   ai = isl_union_access_info_set_schedule
    306  1.1  mrg     (ai, isl_schedule_copy (scop->original_schedule));
    307  1.1  mrg   isl_union_flow *flow = isl_union_access_info_compute_flow (ai);
    308  1.1  mrg   isl_union_map *raw = isl_union_flow_get_must_dependence (flow);
    309  1.1  mrg   isl_union_flow_free (flow);
    310  1.1  mrg 
    311  1.1  mrg   ai = isl_union_access_info_from_sink (isl_union_map_copy (must_writes));
    312  1.1  mrg   ai = isl_union_access_info_set_must_source (ai, must_writes);
    313  1.1  mrg   ai = isl_union_access_info_set_may_source (ai, reads);
    314  1.1  mrg   ai = isl_union_access_info_set_schedule
    315  1.1  mrg     (ai, isl_schedule_copy (scop->original_schedule));
    316  1.1  mrg   flow = isl_union_access_info_compute_flow (ai);
    317  1.1  mrg 
    318  1.1  mrg   isl_union_map *waw = isl_union_flow_get_must_dependence (flow);
    319  1.1  mrg   isl_union_map *war = isl_union_flow_get_may_dependence (flow);
    320  1.1  mrg   war = isl_union_map_subtract (war, isl_union_map_copy (waw));
    321  1.1  mrg   isl_union_flow_free (flow);
    322  1.1  mrg 
    323  1.1  mrg   raw = isl_union_map_coalesce (raw);
    324  1.1  mrg   waw = isl_union_map_coalesce (waw);
    325  1.1  mrg   war = isl_union_map_coalesce (war);
    326  1.1  mrg 
    327  1.1  mrg   isl_union_map *dependences = raw;
    328  1.1  mrg   dependences = isl_union_map_union (dependences, war);
    329  1.1  mrg   dependences = isl_union_map_union (dependences, waw);
    330  1.1  mrg   dependences = isl_union_map_coalesce (dependences);
    331  1.1  mrg 
    332  1.1  mrg   if (dump_file)
    333  1.1  mrg     {
    334  1.1  mrg       fprintf (dump_file, "data dependences (\n");
    335  1.1  mrg       print_isl_union_map (dump_file, dependences);
    336  1.1  mrg       fprintf (dump_file, ")\n");
    337  1.1  mrg     }
    338  1.1  mrg 
    339  1.1  mrg   scop->dependence = dependences;
    340  1.1  mrg }
    341  1.1  mrg 
    342  1.1  mrg #endif /* HAVE_isl */
    343