LCOV - code coverage report
Current view: top level - gcc - graphite-dependences.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.2 % 161 150
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 10 10
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.