LCOV - code coverage report
Current view: top level - gcc - graphite-sese-to-poly.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.5 % 619 579
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 44 44
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Conversion of SESE regions to Polyhedra.
       2              :    Copyright (C) 2009-2026 Free Software Foundation, Inc.
       3              :    Contributed by Sebastian Pop <sebastian.pop@amd.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify
       8              : it under the terms of the GNU General Public License as published by
       9              : the Free Software Foundation; either version 3, or (at your option)
      10              : any later version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful,
      13              : but WITHOUT ANY WARRANTY; without even the implied warranty of
      14              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15              : GNU General Public License for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #define INCLUDE_ISL
      22              : 
      23              : #include "config.h"
      24              : 
      25              : #ifdef HAVE_isl
      26              : 
      27              : #include "system.h"
      28              : #include "coretypes.h"
      29              : #include "backend.h"
      30              : #include "cfghooks.h"
      31              : #include "tree.h"
      32              : #include "gimple.h"
      33              : #include "ssa.h"
      34              : #include "fold-const.h"
      35              : #include "gimple-iterator.h"
      36              : #include "gimplify.h"
      37              : #include "gimplify-me.h"
      38              : #include "tree-cfg.h"
      39              : #include "tree-ssa-loop-manip.h"
      40              : #include "tree-ssa-loop-niter.h"
      41              : #include "tree-ssa-loop.h"
      42              : #include "tree-into-ssa.h"
      43              : #include "tree-pass.h"
      44              : #include "cfgloop.h"
      45              : #include "tree-data-ref.h"
      46              : #include "tree-scalar-evolution.h"
      47              : #include "domwalk.h"
      48              : #include "tree-ssa-propagate.h"
      49              : #include "graphite.h"
      50              : 
      51              : /* Return an isl identifier for the polyhedral basic block PBB.  */
      52              : 
      53              : static isl_id *
      54          668 : isl_id_for_pbb (scop_p s, poly_bb_p pbb)
      55              : {
      56          668 :   char name[14];
      57          668 :   snprintf (name, sizeof (name), "S_%d", pbb_index (pbb));
      58          668 :   return isl_id_alloc (s->isl_context, name, pbb);
      59              : }
      60              : 
      61              : static isl_pw_aff *extract_affine (scop_p, tree, __isl_take isl_space *space);
      62              : 
      63              : /* Extract an affine expression from the chain of recurrence E.  */
      64              : 
      65              : static isl_pw_aff *
      66         1202 : extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space)
      67              : {
      68         1202 :   isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space));
      69         1202 :   isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space));
      70         1202 :   isl_local_space *ls = isl_local_space_from_space (space);
      71         1202 :   unsigned pos = sese_loop_depth (s->scop_info->region, get_chrec_loop (e)) - 1;
      72         1202 :   isl_aff *loop = isl_aff_set_coefficient_si
      73         1202 :     (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1);
      74         1202 :   isl_pw_aff *l = isl_pw_aff_from_aff (loop);
      75              : 
      76              :   /* Before multiplying, make sure that the result is affine.  */
      77         1202 :   gcc_assert (isl_pw_aff_is_cst (rhs)
      78              :               || isl_pw_aff_is_cst (l));
      79              : 
      80         1202 :   return isl_pw_aff_add (lhs, isl_pw_aff_mul (rhs, l));
      81              : }
      82              : 
      83              : /* Extract an affine expression from the mult_expr E.  */
      84              : 
      85              : static isl_pw_aff *
      86            1 : extract_affine_mul (scop_p s, tree e, __isl_take isl_space *space)
      87              : {
      88            1 :   isl_pw_aff *lhs = extract_affine (s, TREE_OPERAND (e, 0),
      89              :                                     isl_space_copy (space));
      90            1 :   isl_pw_aff *rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
      91              : 
      92            1 :   if (!isl_pw_aff_is_cst (lhs)
      93            1 :       && !isl_pw_aff_is_cst (rhs))
      94              :     {
      95            0 :       isl_pw_aff_free (lhs);
      96            0 :       isl_pw_aff_free (rhs);
      97            0 :       return NULL;
      98              :     }
      99              : 
     100            1 :   return isl_pw_aff_mul (lhs, rhs);
     101              : }
     102              : 
     103              : /* Return an isl identifier for the parameter P.  */
     104              : 
     105              : static isl_id *
     106          133 : isl_id_for_parameter (scop_p s, tree p)
     107              : {
     108          133 :   gcc_checking_assert (TREE_CODE (p) == SSA_NAME);
     109          133 :   char name[14];
     110          133 :   snprintf (name, sizeof (name), "P_%d", SSA_NAME_VERSION (p));
     111          133 :   return isl_id_alloc (s->isl_context, name, p);
     112              : }
     113              : 
     114              : /* Return an isl identifier for the data reference DR.  Data references and
     115              :    scalar references get the same isl_id.  They need to be comparable and are
     116              :    distinguished through the first dimension, which contains the alias set or
     117              :    SSA_NAME_VERSION number.  */
     118              : 
     119              : static isl_id *
     120         1400 : isl_id_for_dr (scop_p s)
     121              : {
     122            0 :   return isl_id_alloc (s->isl_context, "", 0);
     123              : }
     124              : 
     125              : /* Extract an affine expression from the ssa_name E.  */
     126              : 
     127              : static isl_pw_aff *
     128          321 : extract_affine_name (int dimension, __isl_take isl_space *space)
     129              : {
     130          321 :   isl_set *dom = isl_set_universe (isl_space_copy (space));
     131          321 :   isl_aff *aff = isl_aff_zero_on_domain (isl_local_space_from_space (space));
     132          321 :   aff = isl_aff_add_coefficient_si (aff, isl_dim_param, dimension, 1);
     133          321 :   return isl_pw_aff_alloc (dom, aff);
     134              : }
     135              : 
     136              : /* Convert WI to a isl_val with CTX.  */
     137              : 
     138              : static __isl_give isl_val *
     139         5014 : isl_val_int_from_wi (isl_ctx *ctx, const widest_int &wi)
     140              : {
     141         5014 :   if (wi::neg_p (wi, SIGNED))
     142              :     {
     143          166 :       widest_int mwi = -wi;
     144          332 :       return isl_val_neg (isl_val_int_from_chunks (ctx, mwi.get_len (),
     145              :                                                    sizeof (HOST_WIDE_INT),
     146          166 :                                                    mwi.get_val ()));
     147          166 :     }
     148         9696 :   return isl_val_int_from_chunks (ctx, wi.get_len (), sizeof (HOST_WIDE_INT),
     149         9696 :                                   wi.get_val ());
     150              : }
     151              : 
     152              : /* Extract an affine expression from the gmp constant G.  */
     153              : 
     154              : static isl_pw_aff *
     155         4172 : extract_affine_wi (const widest_int &g, __isl_take isl_space *space)
     156              : {
     157         4172 :   isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
     158         4172 :   isl_aff *aff = isl_aff_zero_on_domain (ls);
     159         4172 :   isl_set *dom = isl_set_universe (space);
     160         4172 :   isl_ctx *ct = isl_aff_get_ctx (aff);
     161         4172 :   isl_val *v = isl_val_int_from_wi (ct, g);
     162         4172 :   aff = isl_aff_add_constant_val (aff, v);
     163              : 
     164         4172 :   return isl_pw_aff_alloc (dom, aff);
     165              : }
     166              : 
     167              : /* Extract an affine expression from the integer_cst E.  */
     168              : 
     169              : static isl_pw_aff *
     170         4026 : extract_affine_int (tree e, __isl_take isl_space *space)
     171              : {
     172         4026 :   isl_pw_aff *res = extract_affine_wi (wi::to_widest (e), space);
     173         4026 :   return res;
     174              : }
     175              : 
     176              : /* Compute pwaff mod 2^width.  */
     177              : 
     178              : static isl_pw_aff *
     179          316 : wrap (isl_pw_aff *pwaff, unsigned width)
     180              : {
     181          316 :   isl_val *mod;
     182              : 
     183          316 :   mod = isl_val_int_from_ui (isl_pw_aff_get_ctx (pwaff), width);
     184          316 :   mod = isl_val_2exp (mod);
     185          316 :   pwaff = isl_pw_aff_mod_val (pwaff, mod);
     186              : 
     187          316 :   return pwaff;
     188              : }
     189              : 
     190              : /* When parameter NAME is in REGION, returns its index in SESE_PARAMS.
     191              :    Otherwise returns -1.  */
     192              : 
     193              : static inline int
     194          321 : parameter_index_in_region (tree name, sese_info_p region)
     195              : {
     196          321 :   int i;
     197          321 :   tree p;
     198          514 :   FOR_EACH_VEC_ELT (region->params, i, p)
     199          514 :     if (p == name)
     200              :       return i;
     201              :   return -1;
     202              : }
     203              : 
     204              : /* Extract an affine expression from the tree E in the scop S.  */
     205              : 
     206              : static isl_pw_aff *
     207         4251 : extract_affine (scop_p s, tree e, __isl_take isl_space *space)
     208              : {
     209         4251 :   isl_pw_aff *lhs, *rhs, *res;
     210              : 
     211         4251 :   if (e == chrec_dont_know) {
     212            0 :     isl_space_free (space);
     213            0 :     return NULL;
     214              :   }
     215              : 
     216         4251 :   tree type = TREE_TYPE (e);
     217         4251 :   switch (TREE_CODE (e))
     218              :     {
     219         1202 :     case POLYNOMIAL_CHREC:
     220         1202 :       res = extract_affine_chrec (s, e, space);
     221         1202 :       break;
     222              : 
     223            1 :     case MULT_EXPR:
     224            1 :       res = extract_affine_mul (s, e, space);
     225            1 :       break;
     226              : 
     227            0 :     case POINTER_PLUS_EXPR:
     228            0 :       {
     229            0 :         lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
     230              :         /* The RHS of a pointer-plus expression is to be interpreted
     231              :            as signed value.  Try to look through a sign-changing conversion
     232              :            first.  */
     233            0 :         tree tem = TREE_OPERAND (e, 1);
     234            0 :         STRIP_NOPS (tem);
     235            0 :         rhs = extract_affine (s, tem, space);
     236            0 :         if (TYPE_UNSIGNED (TREE_TYPE (tem)))
     237            0 :           rhs = wrap (rhs, TYPE_PRECISION (type) - 1);
     238            0 :         res = isl_pw_aff_add (lhs, rhs);
     239            0 :         break;
     240              :       }
     241              : 
     242          156 :     case PLUS_EXPR:
     243          156 :       lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
     244          156 :       rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
     245          156 :       res = isl_pw_aff_add (lhs, rhs);
     246          156 :       break;
     247              : 
     248           14 :     case MINUS_EXPR:
     249           14 :       lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
     250           14 :       rhs = extract_affine (s, TREE_OPERAND (e, 1), space);
     251           14 :       res = isl_pw_aff_sub (lhs, rhs);
     252           14 :       break;
     253              : 
     254            0 :     case BIT_NOT_EXPR:
     255            0 :       lhs = extract_affine (s, integer_minus_one_node, isl_space_copy (space));
     256            0 :       rhs = extract_affine (s, TREE_OPERAND (e, 0), space);
     257            0 :       res = isl_pw_aff_sub (lhs, rhs);
     258              :       /* We need to always wrap the result of a bitwise operation.  */
     259            0 :       return wrap (res, TYPE_PRECISION (type) - (TYPE_UNSIGNED (type) ? 0 : 1));
     260              : 
     261            7 :     case NEGATE_EXPR:
     262            7 :       lhs = extract_affine (s, TREE_OPERAND (e, 0), isl_space_copy (space));
     263            7 :       rhs = extract_affine (s, integer_minus_one_node, space);
     264            7 :       res = isl_pw_aff_mul (lhs, rhs);
     265            7 :       break;
     266              : 
     267          321 :     case SSA_NAME:
     268          321 :       {
     269          321 :         gcc_assert (! defined_in_sese_p (e, s->scop_info->region));
     270          321 :         int dim = parameter_index_in_region (e, s->scop_info);
     271          321 :         gcc_assert (dim != -1);
     272              :         /* No need to wrap a parameter.  */
     273          321 :         return extract_affine_name (dim, space);
     274              :       }
     275              : 
     276         2394 :     case INTEGER_CST:
     277         2394 :       res = extract_affine_int (e, space);
     278              :       /* No need to wrap a single integer.  */
     279         2394 :       return res;
     280              : 
     281          156 :     CASE_CONVERT:
     282          156 :       {
     283          156 :         tree itype = TREE_TYPE (TREE_OPERAND (e, 0));
     284          156 :         res = extract_affine (s, TREE_OPERAND (e, 0), space);
     285              :         /* Signed values, even if overflow is undefined, get modulo-reduced.
     286              :            But only if not all values of the old type fit in the new.  */
     287          156 :         if (! TYPE_UNSIGNED (type)
     288          156 :             && ((TYPE_UNSIGNED (itype)
     289            9 :                  && TYPE_PRECISION (type) <= TYPE_PRECISION (itype))
     290            5 :                 || TYPE_PRECISION (type) < TYPE_PRECISION (itype)))
     291            9 :           res = wrap (res, TYPE_PRECISION (type) - 1);
     292          147 :         else if (TYPE_UNSIGNED (type)
     293          147 :                  && (!TYPE_UNSIGNED (itype)
     294            0 :                      || TYPE_PRECISION (type) < TYPE_PRECISION (itype)))
     295          142 :           res = wrap (res, TYPE_PRECISION (type));
     296              :         return res;
     297              :       }
     298              : 
     299            0 :     case NON_LVALUE_EXPR:
     300            0 :       res = extract_affine (s, TREE_OPERAND (e, 0), space);
     301            0 :       break;
     302              : 
     303            0 :     default:
     304            0 :       gcc_unreachable ();
     305         1380 :       break;
     306              :     }
     307              : 
     308              :   /* For all wrapping arithmetic wrap the result.  */
     309         1380 :   if (TYPE_OVERFLOW_WRAPS (type))
     310          165 :     res = wrap (res, TYPE_PRECISION (type));
     311              : 
     312              :   return res;
     313              : }
     314              : 
     315              : /* Returns a linear expression for tree T evaluated in PBB.  */
     316              : 
     317              : static isl_pw_aff *
     318          190 : create_pw_aff_from_tree (poly_bb_p pbb, loop_p loop, tree t)
     319              : {
     320          190 :   scop_p scop = PBB_SCOP (pbb);
     321              : 
     322          190 :   t = cached_scalar_evolution_in_region (scop->scop_info->region, loop, t);
     323              : 
     324          190 :   gcc_assert (!chrec_contains_undetermined (t));
     325          190 :   gcc_assert (!automatically_generated_chrec_p (t));
     326              : 
     327          190 :   return extract_affine (scop, t, isl_set_get_space (pbb->domain));
     328              : }
     329              : 
     330              : /* Add conditional statement STMT to pbb.  CODE is used as the comparison
     331              :    operator.  This allows us to invert the condition or to handle
     332              :    inequalities.  */
     333              : 
     334              : static void
     335           95 : add_condition_to_pbb (poly_bb_p pbb, gcond *stmt, enum tree_code code)
     336              : {
     337           95 :   loop_p loop = gimple_bb (stmt)->loop_father;
     338           95 :   isl_pw_aff *lhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_lhs (stmt));
     339           95 :   isl_pw_aff *rhs = create_pw_aff_from_tree (pbb, loop, gimple_cond_rhs (stmt));
     340              : 
     341           95 :   isl_set *cond;
     342           95 :   switch (code)
     343              :     {
     344            0 :       case LT_EXPR:
     345            0 :         cond = isl_pw_aff_lt_set (lhs, rhs);
     346            0 :         break;
     347              : 
     348           26 :       case GT_EXPR:
     349           26 :         cond = isl_pw_aff_gt_set (lhs, rhs);
     350           26 :         break;
     351              : 
     352           28 :       case LE_EXPR:
     353           28 :         cond = isl_pw_aff_le_set (lhs, rhs);
     354           28 :         break;
     355              : 
     356            1 :       case GE_EXPR:
     357            1 :         cond = isl_pw_aff_ge_set (lhs, rhs);
     358            1 :         break;
     359              : 
     360           20 :       case EQ_EXPR:
     361           20 :         cond = isl_pw_aff_eq_set (lhs, rhs);
     362           20 :         break;
     363              : 
     364           20 :       case NE_EXPR:
     365           20 :         cond = isl_pw_aff_ne_set (lhs, rhs);
     366           20 :         break;
     367              : 
     368            0 :       default:
     369            0 :         gcc_unreachable ();
     370              :     }
     371              : 
     372           95 :   cond = isl_set_coalesce (cond);
     373           95 :   cond = isl_set_set_tuple_id (cond, isl_set_get_tuple_id (pbb->domain));
     374           95 :   pbb->domain = isl_set_coalesce (isl_set_intersect (pbb->domain, cond));
     375           95 : }
     376              : 
     377              : /* Add conditions to the domain of PBB.  */
     378              : 
     379              : static void
     380          668 : add_conditions_to_domain (poly_bb_p pbb)
     381              : {
     382          668 :   unsigned int i;
     383          668 :   gimple *stmt;
     384          668 :   gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
     385              : 
     386          668 :   if (GBB_CONDITIONS (gbb).is_empty ())
     387          668 :     return;
     388              : 
     389          185 :   FOR_EACH_VEC_ELT (GBB_CONDITIONS (gbb), i, stmt)
     390           95 :     switch (gimple_code (stmt))
     391              :       {
     392           95 :       case GIMPLE_COND:
     393           95 :           {
     394              :             /* Don't constrain on anything else than INTEGRAL_TYPE_P.  */
     395           95 :             tree cmp_type = TREE_TYPE (gimple_cond_lhs (stmt));
     396           95 :             if (!INTEGRAL_TYPE_P (cmp_type))
     397              :               break;
     398              : 
     399           95 :             gcond *cond_stmt = as_a <gcond *> (stmt);
     400           95 :             enum tree_code code = gimple_cond_code (cond_stmt);
     401              : 
     402              :             /* The conditions for ELSE-branches are inverted.  */
     403           95 :             if (!GBB_CONDITION_CASES (gbb)[i])
     404           46 :               code = invert_tree_comparison (code, false);
     405              : 
     406           95 :             add_condition_to_pbb (pbb, cond_stmt, code);
     407           95 :             break;
     408              :           }
     409              : 
     410            0 :       default:
     411            0 :         gcc_unreachable ();
     412           95 :         break;
     413              :       }
     414              : }
     415              : 
     416              : /* Add constraints on the possible values of parameter P from the type
     417              :    of P.  */
     418              : 
     419              : static void
     420          133 : add_param_constraints (scop_p scop, graphite_dim_t p, tree parameter)
     421              : {
     422          133 :   tree type = TREE_TYPE (parameter);
     423          133 :   int_range_max r;
     424          133 :   wide_int min, max;
     425              : 
     426          133 :   gcc_assert (INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type));
     427              : 
     428          133 :   if (INTEGRAL_TYPE_P (type)
     429          264 :       && get_range_query (cfun)->range_of_expr (r, parameter)
     430          265 :       && !r.undefined_p ())
     431              :     {
     432          124 :       min = r.lower_bound ();
     433          124 :       max = r.upper_bound ();
     434              :     }
     435              :   else
     436              :     {
     437            9 :       min = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type));
     438            9 :       max = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type));
     439              :     }
     440              : 
     441          133 :   isl_space *space = isl_set_get_space (scop->param_context);
     442          133 :   isl_constraint *c = isl_inequality_alloc (isl_local_space_from_space (space));
     443          133 :   isl_val *v = isl_val_int_from_wi (scop->isl_context,
     444          133 :                                     widest_int::from (min, TYPE_SIGN (type)));
     445          133 :   v = isl_val_neg (v);
     446          133 :   c = isl_constraint_set_constant_val (c, v);
     447          133 :   c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, 1);
     448          266 :   scop->param_context = isl_set_coalesce
     449          133 :       (isl_set_add_constraint (scop->param_context, c));
     450              : 
     451          133 :   space = isl_set_get_space (scop->param_context);
     452          133 :   c = isl_inequality_alloc (isl_local_space_from_space (space));
     453          133 :   v = isl_val_int_from_wi (scop->isl_context,
     454          133 :                            widest_int::from (max, TYPE_SIGN (type)));
     455          133 :   c = isl_constraint_set_constant_val (c, v);
     456          133 :   c = isl_constraint_set_coefficient_si (c, isl_dim_param, p, -1);
     457          133 :   scop->param_context = isl_set_coalesce
     458          133 :       (isl_set_add_constraint (scop->param_context, c));
     459          133 : }
     460              : 
     461              : /* Add a constrain to the ACCESSES polyhedron for the alias set of
     462              :    data reference DR.  ACCESSP_NB_DIMS is the dimension of the
     463              :    ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
     464              :    domain.  */
     465              : 
     466              : static isl_map *
     467          732 : pdr_add_alias_set (isl_map *acc, dr_info &dri)
     468              : {
     469          732 :   isl_constraint *c = isl_equality_alloc
     470          732 :       (isl_local_space_from_space (isl_map_get_space (acc)));
     471              :   /* Positive numbers for all alias sets.  */
     472          732 :   c = isl_constraint_set_constant_si (c, -dri.alias_set);
     473          732 :   c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
     474              : 
     475          732 :   return isl_map_add_constraint (acc, c);
     476              : }
     477              : 
     478              : /* Assign the affine expression INDEX to the output dimension POS of
     479              :    MAP and return the result.  */
     480              : 
     481              : static isl_map *
     482          999 : set_index (isl_map *map, int pos, isl_pw_aff *index)
     483              : {
     484          999 :   isl_map *index_map;
     485          999 :   int len = isl_map_dim (map, isl_dim_out);
     486          999 :   isl_id *id;
     487              : 
     488          999 :   index_map = isl_map_from_pw_aff (index);
     489          999 :   index_map = isl_map_insert_dims (index_map, isl_dim_out, 0, pos);
     490          999 :   index_map = isl_map_add_dims (index_map, isl_dim_out, len - pos - 1);
     491              : 
     492          999 :   id = isl_map_get_tuple_id (map, isl_dim_out);
     493          999 :   index_map = isl_map_set_tuple_id (index_map, isl_dim_out, id);
     494          999 :   id = isl_map_get_tuple_id (map, isl_dim_in);
     495          999 :   index_map = isl_map_set_tuple_id (index_map, isl_dim_in, id);
     496              : 
     497          999 :   return isl_map_intersect (map, index_map);
     498              : }
     499              : 
     500              : /* Add to ACCESSES polyhedron equalities defining the access functions
     501              :    to the memory.  ACCESSP_NB_DIMS is the dimension of the ACCESSES
     502              :    polyhedron, DOM_NB_DIMS is the dimension of the iteration domain.
     503              :    PBB is the poly_bb_p that contains the data reference DR.  */
     504              : 
     505              : static isl_map *
     506          732 : pdr_add_memory_accesses (isl_map *acc, dr_info &dri)
     507              : {
     508          732 :   data_reference_p dr = dri.dr;
     509          732 :   poly_bb_p pbb = dri.pbb;
     510          732 :   int i, nb_subscripts = DR_NUM_DIMENSIONS (dr);
     511          732 :   scop_p scop = PBB_SCOP (pbb);
     512              : 
     513         1731 :   for (i = 0; i < nb_subscripts; i++)
     514              :     {
     515          999 :       isl_pw_aff *aff;
     516          999 :       tree afn = DR_ACCESS_FN (dr, i);
     517              : 
     518          999 :       aff = extract_affine (scop, afn,
     519              :                             isl_space_domain (isl_map_get_space (acc)));
     520          999 :       acc = set_index (acc, nb_subscripts - i , aff);
     521              :     }
     522              : 
     523          732 :   return isl_map_coalesce (acc);
     524              : }
     525              : 
     526              : /* Return true when the LOW and HIGH bounds of an array reference REF are valid
     527              :    to extract constraints on accessed elements of the array.  Returning false is
     528              :    the conservative answer.  */
     529              : 
     530              : static bool
     531          902 : bounds_are_valid (tree ref, tree low, tree high)
     532              : {
     533          902 :   if (!high)
     534              :     return false;
     535              : 
     536          856 :   if (!tree_fits_shwi_p (low)
     537          856 :       || !tree_fits_shwi_p (high))
     538              :     return false;
     539              : 
     540              :   /* An array that has flexible size may extend over
     541              :      their declared size.  */
     542          816 :   if (array_ref_flexible_size_p (ref)
     543          816 :       && operand_equal_p (low, high, 0))
     544              :     return false;
     545              : 
     546              :   /* Fortran has some arrays where high bound is -1 and low is 0.  */
     547          816 :   if (integer_onep (fold_build2 (LT_EXPR, boolean_type_node, high, low)))
     548              :     return false;
     549              : 
     550              :   return true;
     551              : }
     552              : 
     553              : /* Add constrains representing the size of the accessed data to the
     554              :    ACCESSES polyhedron.  ACCESSP_NB_DIMS is the dimension of the
     555              :    ACCESSES polyhedron, DOM_NB_DIMS is the dimension of the iteration
     556              :    domain.  */
     557              : 
     558              : static isl_set *
     559          732 : pdr_add_data_dimensions (isl_set *subscript_sizes, scop_p scop,
     560              :                          data_reference_p dr)
     561              : {
     562          732 :   tree ref = DR_REF (dr);
     563              : 
     564          732 :   int nb_subscripts = DR_NUM_DIMENSIONS (dr);
     565         1634 :   for (int i = nb_subscripts - 1; i >= 0; i--, ref = TREE_OPERAND (ref, 0))
     566              :     {
     567          990 :       if (TREE_CODE (ref) != ARRAY_REF)
     568              :         return subscript_sizes;
     569              : 
     570          902 :       tree low = array_ref_low_bound (ref);
     571          902 :       tree high = array_ref_up_bound (ref);
     572              : 
     573          902 :       if (!bounds_are_valid (ref, low, high))
     574           86 :         continue;
     575              : 
     576          816 :       isl_space *space = isl_set_get_space (subscript_sizes);
     577          816 :       isl_pw_aff *lb = extract_affine_int (low, isl_space_copy (space));
     578          816 :       isl_pw_aff *ub = extract_affine_int (high, isl_space_copy (space));
     579              : 
     580              :       /* high >= 0 */
     581          816 :       isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (ub));
     582          816 :       valid = isl_set_project_out (valid, isl_dim_set, 0,
     583          816 :                                    isl_set_dim (valid, isl_dim_set));
     584         1632 :       scop->param_context = isl_set_coalesce
     585          816 :         (isl_set_intersect (scop->param_context, valid));
     586              : 
     587          816 :       isl_aff *aff
     588          816 :         = isl_aff_zero_on_domain (isl_local_space_from_space (space));
     589          816 :       aff = isl_aff_add_coefficient_si (aff, isl_dim_in, i + 1, 1);
     590          816 :       isl_set *univ
     591          816 :         = isl_set_universe (isl_space_domain (isl_aff_get_space (aff)));
     592          816 :       isl_pw_aff *index = isl_pw_aff_alloc (univ, aff);
     593              : 
     594          816 :       isl_id *id = isl_set_get_tuple_id (subscript_sizes);
     595          816 :       lb = isl_pw_aff_set_tuple_id (lb, isl_dim_in, isl_id_copy (id));
     596          816 :       ub = isl_pw_aff_set_tuple_id (ub, isl_dim_in, id);
     597              : 
     598              :       /* low <= sub_i <= high */
     599          816 :       isl_set *lbs = isl_pw_aff_ge_set (isl_pw_aff_copy (index), lb);
     600          816 :       isl_set *ubs = isl_pw_aff_le_set (index, ub);
     601          816 :       subscript_sizes = isl_set_intersect (subscript_sizes, lbs);
     602          816 :       subscript_sizes = isl_set_intersect (subscript_sizes, ubs);
     603              :     }
     604              : 
     605          644 :   return isl_set_coalesce (subscript_sizes);
     606              : }
     607              : 
     608              : /* Build data accesses for DRI.  */
     609              : 
     610              : static void
     611          732 : build_poly_dr (dr_info &dri)
     612              : {
     613          732 :   isl_map *acc;
     614          732 :   isl_set *subscript_sizes;
     615          732 :   poly_bb_p pbb = dri.pbb;
     616          732 :   data_reference_p dr = dri.dr;
     617          732 :   scop_p scop = PBB_SCOP (pbb);
     618          732 :   isl_id *id = isl_id_for_dr (scop);
     619              : 
     620          732 :   {
     621          732 :     isl_space *dc = isl_set_get_space (pbb->domain);
     622          732 :     int nb_out = 1 + DR_NUM_DIMENSIONS (dr);
     623          732 :     isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
     624              :                                            isl_dim_out, nb_out);
     625              : 
     626          732 :     acc = isl_map_universe (space);
     627          732 :     acc = isl_map_set_tuple_id (acc, isl_dim_out, isl_id_copy (id));
     628              :   }
     629              : 
     630          732 :   acc = pdr_add_alias_set (acc, dri);
     631          732 :   acc = pdr_add_memory_accesses (acc, dri);
     632              : 
     633          732 :   {
     634          732 :     int nb = 1 + DR_NUM_DIMENSIONS (dr);
     635          732 :     isl_space *space = isl_space_set_alloc (scop->isl_context, 0, nb);
     636              : 
     637          732 :     space = isl_space_set_tuple_id (space, isl_dim_set, id);
     638          732 :     subscript_sizes = isl_set_nat_universe (space);
     639          732 :     subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
     640              :                                       dri.alias_set);
     641          732 :     subscript_sizes = pdr_add_data_dimensions (subscript_sizes, scop, dr);
     642              :   }
     643              : 
     644         1105 :   new_poly_dr (pbb, DR_STMT (dr), DR_IS_READ (dr) ? PDR_READ : PDR_WRITE,
     645              :                acc, subscript_sizes);
     646          732 : }
     647              : 
     648              : static void
     649         1453 : build_poly_sr_1 (poly_bb_p pbb, gimple *stmt, tree var, enum poly_dr_type kind,
     650              :                  isl_map *acc, isl_set *subscript_sizes)
     651              : {
     652         1453 :   scop_p scop = PBB_SCOP (pbb);
     653              :   /* Each scalar variable has a unique alias set number starting from
     654              :      the maximum alias set assigned to a dr.  */
     655         1453 :   int alias_set = scop->max_alias_set + SSA_NAME_VERSION (var);
     656         1453 :   subscript_sizes = isl_set_fix_si (subscript_sizes, isl_dim_set, 0,
     657              :                                     alias_set);
     658              : 
     659              :   /* Add a constrain to the ACCESSES polyhedron for the alias set of
     660              :      the reference.  */
     661         1453 :   isl_constraint *c
     662         1453 :     = isl_equality_alloc (isl_local_space_from_space (isl_map_get_space (acc)));
     663         1453 :   c = isl_constraint_set_constant_si (c, -alias_set);
     664         1453 :   c = isl_constraint_set_coefficient_si (c, isl_dim_out, 0, 1);
     665              : 
     666         1453 :   new_poly_dr (pbb, stmt, kind, isl_map_add_constraint (acc, c),
     667              :                subscript_sizes);
     668         1453 : }
     669              : 
     670              : /* Record all cross basic block scalar variables in PBB.  */
     671              : 
     672              : static void
     673          668 : build_poly_sr (poly_bb_p pbb)
     674              : {
     675          668 :   scop_p scop = PBB_SCOP (pbb);
     676          668 :   gimple_poly_bb_p gbb = PBB_BLACK_BOX (pbb);
     677          668 :   vec<scalar_use> &reads = gbb->read_scalar_refs;
     678          668 :   vec<tree> &writes = gbb->write_scalar_refs;
     679              : 
     680          668 :   isl_space *dc = isl_set_get_space (pbb->domain);
     681          668 :   int nb_out = 1;
     682          668 :   isl_space *space = isl_space_add_dims (isl_space_from_domain (dc),
     683              :                                          isl_dim_out, nb_out);
     684          668 :   isl_id *id = isl_id_for_dr (scop);
     685          668 :   space = isl_space_set_tuple_id (space, isl_dim_set, isl_id_copy (id));
     686          668 :   isl_map *acc = isl_map_universe (isl_space_copy (space));
     687          668 :   acc = isl_map_set_tuple_id (acc, isl_dim_out, id);
     688          668 :   isl_set *subscript_sizes = isl_set_nat_universe (space);
     689              : 
     690          668 :   int i;
     691          668 :   tree var;
     692         2147 :   FOR_EACH_VEC_ELT (writes, i, var)
     693          811 :     build_poly_sr_1 (pbb, SSA_NAME_DEF_STMT (var), var, PDR_WRITE,
     694              :                      isl_map_copy (acc), isl_set_copy (subscript_sizes));
     695              : 
     696              :   scalar_use *use;
     697         1310 :   FOR_EACH_VEC_ELT (reads, i, use)
     698          642 :     build_poly_sr_1 (pbb, use->first, use->second, PDR_READ, isl_map_copy (acc),
     699              :                      isl_set_copy (subscript_sizes));
     700              : 
     701          668 :   isl_map_free (acc);
     702          668 :   isl_set_free (subscript_sizes);
     703          668 : }
     704              : 
     705              : /* Build data references in SCOP.  */
     706              : 
     707              : static void
     708          201 : build_scop_drs (scop_p scop)
     709              : {
     710          201 :   int i;
     711          201 :   dr_info *dri;
     712          933 :   FOR_EACH_VEC_ELT (scop->drs, i, dri)
     713          732 :     build_poly_dr (*dri);
     714              : 
     715              :   poly_bb_p pbb;
     716          869 :   FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
     717          668 :     build_poly_sr (pbb);
     718          201 : }
     719              : 
     720              : /* Add to the iteration DOMAIN one extra dimension for LOOP->num.  */
     721              : 
     722              : static isl_set *
     723          576 : add_iter_domain_dimension (__isl_take isl_set *domain, loop_p loop, scop_p scop)
     724              : {
     725          576 :   int loop_index = isl_set_dim (domain, isl_dim_set);
     726          576 :   domain = isl_set_add_dims (domain, isl_dim_set, 1);
     727          576 :   char name[50];
     728          576 :   snprintf (name, sizeof(name), "i%d", loop->num);
     729          576 :   isl_id *label = isl_id_alloc (scop->isl_context, name, NULL);
     730          576 :   return isl_set_set_dim_id (domain, isl_dim_set, loop_index, label);
     731              : }
     732              : 
     733              : /* Add constraints to DOMAIN for each loop from LOOP up to CONTEXT.  */
     734              : 
     735              : static isl_set *
     736         1050 : add_loop_constraints (scop_p scop, __isl_take isl_set *domain, loop_p loop,
     737              :                       loop_p context)
     738              : {
     739         1050 :   if (loop == context)
     740              :     return domain;
     741          917 :   const sese_l &region = scop->scop_info->region;
     742          917 :   if (!loop_in_sese_p (loop, region))
     743              :     return domain;
     744              : 
     745              :   /* Recursion all the way up to the context loop.  */
     746          576 :   domain = add_loop_constraints (scop, domain, loop_outer (loop), context);
     747              : 
     748              :   /* Then, build constraints over the loop in post-order: outer to inner.  */
     749              : 
     750          576 :   int loop_index = isl_set_dim (domain, isl_dim_set);
     751          576 :   if (dump_file)
     752          298 :     fprintf (dump_file, "[sese-to-poly] adding one extra dimension to the "
     753              :              "domain for loop_%d.\n", loop->num);
     754          576 :   domain = add_iter_domain_dimension (domain, loop, scop);
     755          576 :   isl_space *space = isl_set_get_space (domain);
     756              : 
     757              :   /* 0 <= loop_i */
     758          576 :   isl_local_space *ls = isl_local_space_from_space (isl_space_copy (space));
     759          576 :   isl_constraint *c = isl_inequality_alloc (ls);
     760          576 :   c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, 1);
     761          576 :   if (dump_file)
     762              :     {
     763          298 :       fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
     764          298 :       print_isl_constraint (dump_file, c);
     765              :     }
     766          576 :   domain = isl_set_add_constraint (domain, c);
     767              : 
     768          576 :   tree nb_iters = number_of_latch_executions (loop);
     769          576 :   if (TREE_CODE (nb_iters) == INTEGER_CST)
     770              :     {
     771              :       /* loop_i <= cst_nb_iters */
     772          430 :       isl_local_space *ls = isl_local_space_from_space (space);
     773          430 :       isl_constraint *c = isl_inequality_alloc (ls);
     774          430 :       c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
     775          430 :       isl_val *v
     776          430 :         = isl_val_int_from_wi (scop->isl_context, wi::to_widest (nb_iters));
     777          430 :       c = isl_constraint_set_constant_val (c, v);
     778          430 :       return isl_set_add_constraint (domain, c);
     779              :     }
     780              :   /* loop_i <= expr_nb_iters */
     781          146 :   gcc_assert (!chrec_contains_undetermined (nb_iters));
     782          146 :   nb_iters = cached_scalar_evolution_in_region (region, loop, nb_iters);
     783          146 :   gcc_assert (!chrec_contains_undetermined (nb_iters));
     784              : 
     785          146 :   isl_pw_aff *aff_nb_iters = extract_affine (scop, nb_iters,
     786              :                                              isl_space_copy (space));
     787          146 :   isl_set *valid = isl_pw_aff_nonneg_set (isl_pw_aff_copy (aff_nb_iters));
     788          146 :   valid = isl_set_project_out (valid, isl_dim_set, 0,
     789          146 :                                isl_set_dim (valid, isl_dim_set));
     790              : 
     791          146 :   if (valid)
     792          146 :     scop->param_context = isl_set_intersect (scop->param_context, valid);
     793              : 
     794          146 :   ls = isl_local_space_from_space (isl_space_copy (space));
     795          146 :   isl_aff *loop_i = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls),
     796              :                                                 isl_dim_in, loop_index, 1);
     797          146 :   isl_set *le = isl_pw_aff_le_set (isl_pw_aff_from_aff (loop_i),
     798              :                                    isl_pw_aff_copy (aff_nb_iters));
     799          146 :   if (dump_file)
     800              :     {
     801           49 :       fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
     802           49 :       print_isl_set (dump_file, le);
     803              :     }
     804          146 :   domain = isl_set_intersect (domain, le);
     805              : 
     806          146 :   widest_int nit;
     807          146 :   if (!max_stmt_executions (loop, &nit))
     808              :     {
     809            0 :       isl_pw_aff_free (aff_nb_iters);
     810            0 :       isl_space_free (space);
     811            0 :       return domain;
     812              :     }
     813              : 
     814              :   /* NIT is an upper bound to NB_ITERS: "NIT >= NB_ITERS", although we
     815              :      do not know whether the loop executes at least once.  */
     816          146 :   --nit;
     817              : 
     818          146 :   isl_pw_aff *approx = extract_affine_wi (nit, isl_space_copy (space));
     819          146 :   isl_set *x = isl_pw_aff_ge_set (approx, aff_nb_iters);
     820          146 :   x = isl_set_project_out (x, isl_dim_set, 0,
     821          146 :                            isl_set_dim (x, isl_dim_set));
     822          146 :   scop->param_context = isl_set_intersect (scop->param_context, x);
     823              : 
     824          146 :   ls = isl_local_space_from_space (space);
     825          146 :   c = isl_inequality_alloc (ls);
     826          146 :   c = isl_constraint_set_coefficient_si (c, isl_dim_set, loop_index, -1);
     827          146 :   isl_val *v = isl_val_int_from_wi (scop->isl_context, nit);
     828          146 :   c = isl_constraint_set_constant_val (c, v);
     829              : 
     830          146 :   if (dump_file)
     831              :     {
     832           49 :       fprintf (dump_file, "[sese-to-poly] adding constraint to the domain: ");
     833           49 :       print_isl_constraint (dump_file, c);
     834              :     }
     835              : 
     836          146 :   return isl_set_add_constraint (domain, c);
     837          146 : }
     838              : 
     839              : /* Builds the original iteration domains for each pbb in the SCOP.  */
     840              : 
     841              : static int
     842          474 : build_iteration_domains (scop_p scop, __isl_keep isl_set *context,
     843              :                          int index, loop_p context_loop)
     844              : {
     845          474 :   loop_p current = pbb_loop (scop->pbbs[index]);
     846          474 :   isl_set *domain = isl_set_copy (context);
     847          474 :   domain = add_loop_constraints (scop, domain, current, context_loop);
     848          474 :   const sese_l &region = scop->scop_info->region;
     849              : 
     850          474 :   int i;
     851          474 :   poly_bb_p pbb;
     852         1275 :   FOR_EACH_VEC_ELT_FROM (scop->pbbs, i, pbb, index)
     853              :     {
     854         1041 :       loop_p loop = pbb_loop (pbb);
     855         1041 :       if (current == loop)
     856              :         {
     857          668 :           pbb->iterators = isl_set_copy (domain);
     858          668 :           pbb->domain = isl_set_copy (domain);
     859          668 :           pbb->domain = isl_set_set_tuple_id (pbb->domain,
     860              :                                               isl_id_for_pbb (scop, pbb));
     861          668 :           add_conditions_to_domain (pbb);
     862              : 
     863          668 :           if (dump_file)
     864              :             {
     865          343 :               fprintf (dump_file, "[sese-to-poly] set pbb_%d->domain: ",
     866              :                        pbb_index (pbb));
     867          343 :               print_isl_set (dump_file, domain);
     868              :             }
     869          668 :           continue;
     870              :         }
     871              : 
     872          734 :       while (loop_in_sese_p (loop, region)
     873          734 :              && current != loop)
     874          361 :         loop = loop_outer (loop);
     875              : 
     876          373 :       if (current != loop)
     877              :         {
     878              :           /* A statement in a different loop nest than CURRENT loop.  */
     879          240 :           isl_set_free (domain);
     880          240 :           return i;
     881              :         }
     882              : 
     883              :       /* A statement nested in the CURRENT loop.  */
     884          133 :       i = build_iteration_domains (scop, domain, i, current);
     885          133 :       i--;
     886              :     }
     887              : 
     888          234 :   isl_set_free (domain);
     889          234 :   return i;
     890              : }
     891              : 
     892              : /* Assign dimension for each parameter in SCOP and add constraints for the
     893              :    parameters.  */
     894              : 
     895              : static void
     896          201 : build_scop_context (scop_p scop)
     897              : {
     898          201 :   sese_info_p region = scop->scop_info;
     899          201 :   unsigned nbp = sese_nb_params (region);
     900          201 :   isl_space *space = isl_space_set_alloc (scop->isl_context, nbp, 0);
     901              : 
     902          201 :   unsigned i;
     903          201 :   tree p;
     904          535 :   FOR_EACH_VEC_ELT (region->params, i, p)
     905          133 :     space = isl_space_set_dim_id (space, isl_dim_param, i,
     906              :                                   isl_id_for_parameter (scop, p));
     907              : 
     908          201 :   scop->param_context = isl_set_universe (space);
     909              : 
     910          334 :   FOR_EACH_VEC_ELT (region->params, i, p)
     911          133 :     add_param_constraints (scop, i, p);
     912          201 : }
     913              : 
     914              : /* Return true when loop A is nested in loop B.  */
     915              : 
     916              : static bool
     917         1142 : nested_in (loop_p a, loop_p b)
     918              : {
     919          252 :   return b == find_common_loop (a, b);
     920              : }
     921              : 
     922              : /* Return the loop at a specific SCOP->pbbs[*INDEX].  */
     923              : static loop_p
     924         2363 : loop_at (scop_p scop, int *index)
     925              : {
     926         2363 :   return pbb_loop (scop->pbbs[*index]);
     927              : }
     928              : 
     929              : /* Return the index of any pbb belonging to loop or a subloop of A.  */
     930              : 
     931              : static int
     932          119 : index_outermost_in_loop (loop_p a, scop_p scop)
     933              : {
     934          119 :   int i, outermost = -1;
     935          119 :   int last_depth = -1;
     936          119 :   poly_bb_p pbb;
     937          371 :   FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
     938          252 :     if (nested_in (pbb_loop (pbb), a)
     939          252 :         && (last_depth == -1
     940           88 :             || last_depth > (int) loop_depth (pbb_loop (pbb))))
     941              :       {
     942          120 :         outermost = i;
     943          240 :         last_depth = loop_depth (pbb_loop (pbb));
     944              :       }
     945          119 :   return outermost;
     946              : }
     947              : 
     948              : /* Return the index of any pbb belonging to loop or a subloop of A.  */
     949              : 
     950              : static int
     951          533 : index_pbb_in_loop (loop_p a, scop_p scop)
     952              : {
     953          533 :   int i;
     954          533 :   poly_bb_p pbb;
     955         1212 :   FOR_EACH_VEC_ELT (scop->pbbs, i, pbb)
     956         1093 :     if (pbb_loop (pbb) == a)
     957              :       return i;
     958              :   return -1;
     959              : }
     960              : 
     961              : static poly_bb_p
     962          533 : outermost_pbb_in (loop_p loop, scop_p scop)
     963              : {
     964          533 :   int x = index_pbb_in_loop (loop, scop);
     965          533 :   if (x == -1)
     966          119 :     x = index_outermost_in_loop (loop, scop);
     967          533 :   return scop->pbbs[x];
     968              : }
     969              : 
     970              : static isl_schedule *
     971         1056 : add_in_sequence (__isl_take isl_schedule *a, __isl_take isl_schedule *b)
     972              : {
     973         1056 :   gcc_assert (a || b);
     974              : 
     975         1056 :   if (!a)
     976              :     return b;
     977              : 
     978          467 :   if (!b)
     979              :     return a;
     980              : 
     981          467 :   return isl_schedule_sequence (a, b);
     982              : }
     983              : 
     984              : struct map_to_dimension_data {
     985              :   int n;
     986              :   isl_union_pw_multi_aff *res;
     987              : };
     988              : 
     989              : /* Create a function that maps the elements of SET to its N-th dimension and add
     990              :    it to USER->res.  */
     991              : 
     992              : static isl_stat
     993          919 : add_outer_projection (__isl_take isl_set *set, void *user)
     994              : {
     995          919 :   struct map_to_dimension_data *data = (struct map_to_dimension_data *) user;
     996          919 :   int dim = isl_set_dim (set, isl_dim_set);
     997          919 :   isl_space *space = isl_set_get_space (set);
     998              : 
     999          919 :   gcc_assert (dim >= data->n);
    1000          919 :   isl_pw_multi_aff *pma
    1001         1838 :     = isl_pw_multi_aff_project_out_map (space, isl_dim_set, data->n,
    1002          919 :                                         dim - data->n);
    1003          919 :   data->res = isl_union_pw_multi_aff_add_pw_multi_aff (data->res, pma);
    1004              : 
    1005          919 :   isl_set_free (set);
    1006          919 :   return isl_stat_ok;
    1007              : }
    1008              : 
    1009              : /* Return SET in which all inner dimensions above N are removed.  */
    1010              : 
    1011              : static isl_multi_union_pw_aff *
    1012          532 : outer_projection_mupa (__isl_take isl_union_set *set, int n)
    1013              : {
    1014          532 :   gcc_assert (n >= 0);
    1015          532 :   gcc_assert (set);
    1016          532 :   gcc_assert (!isl_union_set_is_empty (set));
    1017              : 
    1018          532 :   isl_space *space = isl_union_set_get_space (set);
    1019          532 :   isl_union_pw_multi_aff *pwaff = isl_union_pw_multi_aff_empty (space);
    1020              : 
    1021          532 :   struct map_to_dimension_data data = {n, pwaff};
    1022              : 
    1023          532 :   if (isl_union_set_foreach_set (set, &add_outer_projection, &data) < 0)
    1024            0 :     data.res = isl_union_pw_multi_aff_free (data.res);
    1025              : 
    1026          532 :   isl_union_set_free (set);
    1027          532 :   return isl_multi_union_pw_aff_from_union_pw_multi_aff (data.res);
    1028              : }
    1029              : 
    1030              : /* Embed SCHEDULE in the constraints of the LOOP domain.  */
    1031              : 
    1032              : static isl_schedule *
    1033          533 : add_loop_schedule (__isl_take isl_schedule *schedule, loop_p loop,
    1034              :                    scop_p scop)
    1035              : {
    1036          533 :   poly_bb_p pbb = outermost_pbb_in (loop, scop);
    1037          533 :   isl_set *iterators = pbb->iterators;
    1038              : 
    1039          533 :   int empty = isl_set_is_empty (iterators);
    1040          533 :   if (empty < 0 || empty)
    1041            0 :     return empty < 0 ? isl_schedule_free (schedule) : schedule;
    1042              : 
    1043          533 :   isl_union_set *domain = isl_schedule_get_domain (schedule);
    1044              :   /* We cannot apply an empty domain to pbbs in this loop so return early.  */
    1045          533 :   if (isl_union_set_is_empty (domain))
    1046              :     {
    1047            1 :       isl_union_set_free (domain);
    1048            1 :       return schedule;
    1049              :     }
    1050              : 
    1051          532 :   isl_space *space = isl_set_get_space (iterators);
    1052          532 :   int loop_index = isl_space_dim (space, isl_dim_set) - 1;
    1053              : 
    1054          532 :   loop_p ploop = pbb_loop (pbb);
    1055          673 :   while (loop != ploop)
    1056              :     {
    1057          141 :       --loop_index;
    1058          141 :       ploop = loop_outer (ploop);
    1059              :     }
    1060              : 
    1061          532 :   isl_local_space *ls = isl_local_space_from_space (space);
    1062          532 :   isl_aff *aff = isl_aff_var_on_domain (ls, isl_dim_set, loop_index);
    1063          532 :   isl_multi_aff *prefix = isl_multi_aff_from_aff (aff);
    1064          532 :   char name[50];
    1065          532 :   snprintf (name, sizeof(name), "L_%d", loop->num);
    1066          532 :   isl_id *label = isl_id_alloc (isl_schedule_get_ctx (schedule),
    1067              :                                 name, NULL);
    1068          532 :   prefix = isl_multi_aff_set_tuple_id (prefix, isl_dim_out, label);
    1069              : 
    1070          532 :   int n = isl_multi_aff_dim (prefix, isl_dim_in);
    1071          532 :   isl_multi_union_pw_aff *mupa = outer_projection_mupa (domain, n);
    1072          532 :   mupa = isl_multi_union_pw_aff_apply_multi_aff (mupa, prefix);
    1073          532 :   return isl_schedule_insert_partial_schedule (schedule, mupa);
    1074              : }
    1075              : 
    1076              : /* Build schedule for the pbb at INDEX.  */
    1077              : 
    1078              : static isl_schedule *
    1079          668 : build_schedule_pbb (scop_p scop, int *index)
    1080              : {
    1081          668 :   poly_bb_p pbb = scop->pbbs[*index];
    1082          668 :   ++*index;
    1083          668 :   isl_set *domain = isl_set_copy (pbb->domain);
    1084          668 :   isl_union_set *ud = isl_union_set_from_set (domain);
    1085          668 :   return isl_schedule_from_domain (ud);
    1086              : }
    1087              : 
    1088              : static isl_schedule *build_schedule_loop_nest (scop_p, int *, loop_p);
    1089              : 
    1090              : /* Build the schedule of the loop containing the SCOP pbb at INDEX.  */
    1091              : 
    1092              : static isl_schedule *
    1093          388 : build_schedule_loop (scop_p scop, int *index)
    1094              : {
    1095          388 :   int max = scop->pbbs.length ();
    1096          388 :   gcc_assert (*index < max);
    1097          388 :   loop_p loop = loop_at (scop, index);
    1098              : 
    1099          388 :   isl_schedule *s = NULL;
    1100         1245 :   while (nested_in (loop_at (scop, index), loop))
    1101              :     {
    1102          626 :       if (loop == loop_at (scop, index))
    1103          535 :         s = add_in_sequence (s, build_schedule_pbb (scop, index));
    1104              :       else
    1105           91 :         s = add_in_sequence (s, build_schedule_loop_nest (scop, index, loop));
    1106              : 
    1107          626 :       if (*index == max)
    1108              :         break;
    1109              :     }
    1110              : 
    1111          388 :   return add_loop_schedule (s, loop, scop);
    1112              : }
    1113              : 
    1114              : /* S is the schedule of the loop LOOP.  Embed the schedule S in all outer loops.
    1115              :    When CONTEXT_LOOP is null, embed the schedule in all loops contained in the
    1116              :    SCOP surrounding LOOP.  When CONTEXT_LOOP is non null, only embed S in the
    1117              :    maximal loop nest contained within CONTEXT_LOOP.  */
    1118              : 
    1119              : static isl_schedule *
    1120          368 : embed_in_surrounding_loops (__isl_take isl_schedule *s, scop_p scop,
    1121              :                             loop_p loop, int *index, loop_p context_loop)
    1122              : {
    1123          513 :   loop_p outer = loop_outer (loop);
    1124          513 :   sese_l region = scop->scop_info->region;
    1125          513 :   if (context_loop == outer
    1126          513 :       || !loop_in_sese_p (outer, region))
    1127          368 :     return s;
    1128              : 
    1129          145 :   int max = scop->pbbs.length ();
    1130          145 :   if (*index == max
    1131           58 :       || (context_loop && !nested_in (loop_at (scop, index), context_loop))
    1132          145 :       || (!context_loop
    1133           58 :           && !loop_in_sese_p (find_common_loop (outer, loop_at (scop, index)),
    1134              :                               region)))
    1135          108 :     return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop),
    1136          108 :                                        scop, outer, index, context_loop);
    1137              : 
    1138              :   bool a_pbb;
    1139          132 :   while ((a_pbb = (outer == loop_at (scop, index)))
    1140           66 :          || nested_in (loop_at (scop, index), outer))
    1141              :     {
    1142           53 :       if (a_pbb)
    1143           33 :         s = add_in_sequence (s, build_schedule_pbb (scop, index));
    1144              :       else
    1145           20 :         s = add_in_sequence (s, build_schedule_loop (scop, index));
    1146              : 
    1147           53 :       if (*index == max)
    1148              :         break;
    1149              :     }
    1150              : 
    1151              :   /* We reached the end of the OUTER loop: embed S in OUTER.  */
    1152           37 :   return embed_in_surrounding_loops (add_loop_schedule (s, outer, scop), scop,
    1153           37 :                                      outer, index, context_loop);
    1154              : }
    1155              : 
    1156              : /* Build schedule for the full loop nest containing the pbb at INDEX.  When
    1157              :    CONTEXT_LOOP is null, build the schedule of all loops contained in the SCOP
    1158              :    surrounding the pbb.  When CONTEXT_LOOP is non null, only build the maximal loop
    1159              :    nest contained within CONTEXT_LOOP.  */
    1160              : 
    1161              : static isl_schedule *
    1162          368 : build_schedule_loop_nest (scop_p scop, int *index, loop_p context_loop)
    1163              : {
    1164          736 :   gcc_assert (*index != (int) scop->pbbs.length ());
    1165              : 
    1166          368 :   loop_p loop = loop_at (scop, index);
    1167          368 :   isl_schedule *s = build_schedule_loop (scop, index);
    1168          368 :   return embed_in_surrounding_loops (s, scop, loop, index, context_loop);
    1169              : }
    1170              : 
    1171              : /* Build the schedule of the SCOP.  */
    1172              : 
    1173              : static void
    1174          201 : build_original_schedule (scop_p scop)
    1175              : {
    1176          201 :   int i = 0;
    1177          201 :   int n = scop->pbbs.length ();
    1178          578 :   while (i < n)
    1179              :     {
    1180          377 :       poly_bb_p pbb = scop->pbbs[i];
    1181          377 :       isl_schedule *s = NULL;
    1182          377 :       if (!loop_in_sese_p (pbb_loop (pbb), scop->scop_info->region))
    1183          100 :         s = build_schedule_pbb (scop, &i);
    1184              :       else
    1185          277 :         s = build_schedule_loop_nest (scop, &i, NULL);
    1186              : 
    1187          377 :       scop->original_schedule = add_in_sequence (scop->original_schedule, s);
    1188              :     }
    1189              : 
    1190          201 :   if (dump_file)
    1191              :     {
    1192          101 :       fprintf (dump_file, "[sese-to-poly] original schedule:\n");
    1193          101 :       print_isl_schedule (dump_file, scop->original_schedule);
    1194              :     }
    1195          201 : }
    1196              : 
    1197              : /* Builds the polyhedral representation for a SESE region.  */
    1198              : 
    1199              : bool
    1200          201 : build_poly_scop (scop_p scop)
    1201              : {
    1202          201 :   int old_err = isl_options_get_on_error (scop->isl_context);
    1203          201 :   isl_options_set_on_error (scop->isl_context, ISL_ON_ERROR_CONTINUE);
    1204              : 
    1205          201 :   build_scop_context (scop);
    1206              : 
    1207          201 :   unsigned i = 0;
    1208          201 :   unsigned n = scop->pbbs.length ();
    1209          542 :   while (i < n)
    1210          341 :     i = build_iteration_domains (scop, scop->param_context, i, NULL);
    1211              : 
    1212          201 :   build_scop_drs (scop);
    1213          201 :   build_original_schedule (scop);
    1214              : 
    1215          201 :   enum isl_error err = isl_ctx_last_error (scop->isl_context);
    1216          201 :   isl_ctx_reset_error (scop->isl_context);
    1217          201 :   isl_options_set_on_error (scop->isl_context, old_err);
    1218          201 :   if (err != isl_error_none
    1219          201 :       && dump_enabled_p ())
    1220            0 :     dump_printf (MSG_MISSED_OPTIMIZATION,
    1221              :                  "ISL error while building poly scop\n");
    1222              : 
    1223          201 :   return err == isl_error_none;
    1224              : }
    1225              : #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.