LCOV - code coverage report
Current view: top level - metalib_isl - isl_schedule_band.c (source / functions) Hit Total Coverage
Test: 2018-10-31_point_maint_greina16.lcov Lines: 0 593 0.0 %
Date: 2018-11-01 11:27:00 Functions: 0 53 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2013-2014 Ecole Normale Superieure
       3             :  * Copyright 2014      INRIA Rocquencourt
       4             :  *
       5             :  * Use of this software is governed by the MIT license
       6             :  *
       7             :  * Written by Sven Verdoolaege,
       8             :  * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
       9             :  * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
      10             :  * B.P. 105 - 78153 Le Chesnay, France
      11             :  */
      12             : 
      13             : #include <string.h>
      14             : #include <isl/val.h>
      15             : #include <isl/space.h>
      16             : #include <isl/map.h>
      17             : #include <isl/schedule_node.h>
      18             : #include <isl_schedule_band.h>
      19             : #include <isl_schedule_private.h>
      20             : 
      21           0 : isl_ctx *isl_schedule_band_get_ctx(__isl_keep isl_schedule_band *band)
      22             : {
      23           0 :         return band ? isl_multi_union_pw_aff_get_ctx(band->mupa) : NULL;
      24             : }
      25             : 
      26             : /* Return a new uninitialized isl_schedule_band.
      27             :  */
      28           0 : static __isl_give isl_schedule_band *isl_schedule_band_alloc(isl_ctx *ctx)
      29             : {
      30             :         isl_schedule_band *band;
      31             : 
      32           0 :         band = isl_calloc_type(ctx, isl_schedule_band);
      33           0 :         if (!band)
      34           0 :                 return NULL;
      35             : 
      36           0 :         band->ref = 1;
      37             : 
      38           0 :         return band;
      39             : }
      40             : 
      41             : /* Return a new isl_schedule_band with partial schedule "mupa".
      42             :  * First replace "mupa" by its greatest integer part to ensure
      43             :  * that the schedule is always integral.
      44             :  * The band is not marked permutable, the dimensions are not
      45             :  * marked coincident and the AST build options are empty.
      46             :  * Since there are no build options, the node is not anchored.
      47             :  */
      48           0 : __isl_give isl_schedule_band *isl_schedule_band_from_multi_union_pw_aff(
      49             :         __isl_take isl_multi_union_pw_aff *mupa)
      50             : {
      51             :         isl_ctx *ctx;
      52             :         isl_schedule_band *band;
      53             :         isl_space *space;
      54             : 
      55           0 :         mupa = isl_multi_union_pw_aff_floor(mupa);
      56           0 :         if (!mupa)
      57           0 :                 return NULL;
      58           0 :         ctx = isl_multi_union_pw_aff_get_ctx(mupa);
      59           0 :         band = isl_schedule_band_alloc(ctx);
      60           0 :         if (!band)
      61           0 :                 goto error;
      62             : 
      63           0 :         band->n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
      64           0 :         band->coincident = isl_calloc_array(ctx, int, band->n);
      65           0 :         band->mupa = mupa;
      66           0 :         space = isl_space_params_alloc(ctx, 0);
      67           0 :         band->ast_build_options = isl_union_set_empty(space);
      68           0 :         band->anchored = 0;
      69             : 
      70           0 :         if ((band->n && !band->coincident) || !band->ast_build_options)
      71           0 :                 return isl_schedule_band_free(band);
      72             : 
      73           0 :         return band;
      74             : error:
      75           0 :         isl_multi_union_pw_aff_free(mupa);
      76           0 :         return NULL;
      77             : }
      78             : 
      79             : /* Create a duplicate of the given isl_schedule_band.
      80             :  */
      81           0 : __isl_give isl_schedule_band *isl_schedule_band_dup(
      82             :         __isl_keep isl_schedule_band *band)
      83             : {
      84             :         int i;
      85             :         isl_ctx *ctx;
      86             :         isl_schedule_band *dup;
      87             : 
      88           0 :         if (!band)
      89           0 :                 return NULL;
      90             : 
      91           0 :         ctx = isl_schedule_band_get_ctx(band);
      92           0 :         dup = isl_schedule_band_alloc(ctx);
      93           0 :         if (!dup)
      94           0 :                 return NULL;
      95             : 
      96           0 :         dup->n = band->n;
      97           0 :         dup->coincident = isl_alloc_array(ctx, int, band->n);
      98           0 :         if (band->n && !dup->coincident)
      99           0 :                 return isl_schedule_band_free(dup);
     100             : 
     101           0 :         for (i = 0; i < band->n; ++i)
     102           0 :                 dup->coincident[i] = band->coincident[i];
     103           0 :         dup->permutable = band->permutable;
     104             : 
     105           0 :         dup->mupa = isl_multi_union_pw_aff_copy(band->mupa);
     106           0 :         dup->ast_build_options = isl_union_set_copy(band->ast_build_options);
     107           0 :         if (!dup->mupa || !dup->ast_build_options)
     108           0 :                 return isl_schedule_band_free(dup);
     109             : 
     110           0 :         if (band->loop_type) {
     111           0 :                 dup->loop_type = isl_alloc_array(ctx,
     112             :                                             enum isl_ast_loop_type, band->n);
     113           0 :                 if (band->n && !dup->loop_type)
     114           0 :                         return isl_schedule_band_free(dup);
     115           0 :                 for (i = 0; i < band->n; ++i)
     116           0 :                         dup->loop_type[i] = band->loop_type[i];
     117             :         }
     118           0 :         if (band->isolate_loop_type) {
     119           0 :                 dup->isolate_loop_type = isl_alloc_array(ctx,
     120             :                                             enum isl_ast_loop_type, band->n);
     121           0 :                 if (band->n && !dup->isolate_loop_type)
     122           0 :                         return isl_schedule_band_free(dup);
     123           0 :                 for (i = 0; i < band->n; ++i)
     124           0 :                         dup->isolate_loop_type[i] = band->isolate_loop_type[i];
     125             :         }
     126             : 
     127           0 :         return dup;
     128             : }
     129             : 
     130             : /* Return an isl_schedule_band that is equal to "band" and that has only
     131             :  * a single reference.
     132             :  */
     133           0 : __isl_give isl_schedule_band *isl_schedule_band_cow(
     134             :         __isl_take isl_schedule_band *band)
     135             : {
     136           0 :         if (!band)
     137           0 :                 return NULL;
     138             : 
     139           0 :         if (band->ref == 1)
     140           0 :                 return band;
     141           0 :         band->ref--;
     142           0 :         return isl_schedule_band_dup(band);
     143             : }
     144             : 
     145             : /* Return a new reference to "band".
     146             :  */
     147           0 : __isl_give isl_schedule_band *isl_schedule_band_copy(
     148             :         __isl_keep isl_schedule_band *band)
     149             : {
     150           0 :         if (!band)
     151           0 :                 return NULL;
     152             : 
     153           0 :         band->ref++;
     154           0 :         return band;
     155             : }
     156             : 
     157             : /* Free a reference to "band" and return NULL.
     158             :  */
     159           0 : __isl_null isl_schedule_band *isl_schedule_band_free(
     160             :         __isl_take isl_schedule_band *band)
     161             : {
     162           0 :         if (!band)
     163           0 :                 return NULL;
     164             : 
     165           0 :         if (--band->ref > 0)
     166           0 :                 return NULL;
     167             : 
     168           0 :         isl_multi_union_pw_aff_free(band->mupa);
     169           0 :         isl_union_set_free(band->ast_build_options);
     170           0 :         free(band->loop_type);
     171           0 :         free(band->isolate_loop_type);
     172           0 :         free(band->coincident);
     173           0 :         free(band);
     174             : 
     175           0 :         return NULL;
     176             : }
     177             : 
     178             : /* Are "band1" and "band2" obviously equal?
     179             :  */
     180           0 : isl_bool isl_schedule_band_plain_is_equal(__isl_keep isl_schedule_band *band1,
     181             :         __isl_keep isl_schedule_band *band2)
     182             : {
     183             :         int i;
     184             :         isl_bool equal;
     185             : 
     186           0 :         if (!band1 || !band2)
     187           0 :                 return isl_bool_error;
     188           0 :         if (band1 == band2)
     189           0 :                 return isl_bool_true;
     190             : 
     191           0 :         if (band1->n != band2->n)
     192           0 :                 return isl_bool_false;
     193           0 :         for (i = 0; i < band1->n; ++i)
     194           0 :                 if (band1->coincident[i] != band2->coincident[i])
     195           0 :                         return isl_bool_false;
     196           0 :         if (band1->permutable != band2->permutable)
     197           0 :                 return isl_bool_false;
     198             : 
     199           0 :         equal = isl_multi_union_pw_aff_plain_is_equal(band1->mupa, band2->mupa);
     200           0 :         if (equal < 0 || !equal)
     201           0 :                 return equal;
     202             : 
     203           0 :         if (!band1->loop_type != !band2->loop_type)
     204           0 :                 return isl_bool_false;
     205           0 :         if (band1->loop_type)
     206           0 :                 for (i = 0; i < band1->n; ++i)
     207           0 :                         if (band1->loop_type[i] != band2->loop_type[i])
     208           0 :                                 return isl_bool_false;
     209             : 
     210           0 :         if (!band1->isolate_loop_type != !band2->isolate_loop_type)
     211           0 :                 return isl_bool_false;
     212           0 :         if (band1->isolate_loop_type)
     213           0 :                 for (i = 0; i < band1->n; ++i)
     214           0 :                         if (band1->isolate_loop_type[i] !=
     215           0 :                                                 band2->isolate_loop_type[i])
     216           0 :                                 return isl_bool_false;
     217             : 
     218           0 :         return isl_union_set_is_equal(band1->ast_build_options,
     219             :                                         band2->ast_build_options);
     220             : }
     221             : 
     222             : /* Return the number of scheduling dimensions in the band.
     223             :  */
     224           0 : int isl_schedule_band_n_member(__isl_keep isl_schedule_band *band)
     225             : {
     226           0 :         return band ? band->n : 0;
     227             : }
     228             : 
     229             : /* Is the given scheduling dimension coincident within the band and
     230             :  * with respect to the coincidence constraints?
     231             :  */
     232           0 : isl_bool isl_schedule_band_member_get_coincident(
     233             :         __isl_keep isl_schedule_band *band, int pos)
     234             : {
     235           0 :         if (!band)
     236           0 :                 return isl_bool_error;
     237             : 
     238           0 :         if (pos < 0 || pos >= band->n)
     239           0 :                 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
     240             :                         "invalid member position", return isl_bool_error);
     241             : 
     242           0 :         return band->coincident[pos];
     243             : }
     244             : 
     245             : /* Mark the given scheduling dimension as being coincident or not
     246             :  * according to "coincident".
     247             :  */
     248           0 : __isl_give isl_schedule_band *isl_schedule_band_member_set_coincident(
     249             :         __isl_take isl_schedule_band *band, int pos, int coincident)
     250             : {
     251           0 :         if (!band)
     252           0 :                 return NULL;
     253           0 :         if (isl_schedule_band_member_get_coincident(band, pos) == coincident)
     254           0 :                 return band;
     255           0 :         band = isl_schedule_band_cow(band);
     256           0 :         if (!band)
     257           0 :                 return NULL;
     258             : 
     259           0 :         if (pos < 0 || pos >= band->n)
     260           0 :                 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
     261             :                         "invalid member position",
     262             :                         return isl_schedule_band_free(band));
     263             : 
     264           0 :         band->coincident[pos] = coincident;
     265             : 
     266           0 :         return band;
     267             : }
     268             : 
     269             : /* Is the schedule band mark permutable?
     270             :  */
     271           0 : isl_bool isl_schedule_band_get_permutable(__isl_keep isl_schedule_band *band)
     272             : {
     273           0 :         if (!band)
     274           0 :                 return isl_bool_error;
     275           0 :         return band->permutable;
     276             : }
     277             : 
     278             : /* Mark the schedule band permutable or not according to "permutable"?
     279             :  */
     280           0 : __isl_give isl_schedule_band *isl_schedule_band_set_permutable(
     281             :         __isl_take isl_schedule_band *band, int permutable)
     282             : {
     283           0 :         if (!band)
     284           0 :                 return NULL;
     285           0 :         if (band->permutable == permutable)
     286           0 :                 return band;
     287           0 :         band = isl_schedule_band_cow(band);
     288           0 :         if (!band)
     289           0 :                 return NULL;
     290             : 
     291           0 :         band->permutable = permutable;
     292             : 
     293           0 :         return band;
     294             : }
     295             : 
     296             : /* Is the band node "node" anchored?  That is, does it reference
     297             :  * the outer band nodes?
     298             :  */
     299           0 : int isl_schedule_band_is_anchored(__isl_keep isl_schedule_band *band)
     300             : {
     301           0 :         return band ? band->anchored : -1;
     302             : }
     303             : 
     304             : /* Return the schedule space of the band.
     305             :  */
     306           0 : __isl_give isl_space *isl_schedule_band_get_space(
     307             :         __isl_keep isl_schedule_band *band)
     308             : {
     309           0 :         if (!band)
     310           0 :                 return NULL;
     311           0 :         return isl_multi_union_pw_aff_get_space(band->mupa);
     312             : }
     313             : 
     314             : /* Intersect the domain of the band schedule of "band" with "domain".
     315             :  */
     316           0 : __isl_give isl_schedule_band *isl_schedule_band_intersect_domain(
     317             :         __isl_take isl_schedule_band *band, __isl_take isl_union_set *domain)
     318             : {
     319           0 :         band = isl_schedule_band_cow(band);
     320           0 :         if (!band || !domain)
     321             :                 goto error;
     322             : 
     323           0 :         band->mupa = isl_multi_union_pw_aff_intersect_domain(band->mupa,
     324             :                                                                 domain);
     325           0 :         if (!band->mupa)
     326           0 :                 return isl_schedule_band_free(band);
     327             : 
     328           0 :         return band;
     329             : error:
     330           0 :         isl_schedule_band_free(band);
     331           0 :         isl_union_set_free(domain);
     332           0 :         return NULL;
     333             : }
     334             : 
     335             : /* Return the schedule of the band in isolation.
     336             :  */
     337           0 : __isl_give isl_multi_union_pw_aff *isl_schedule_band_get_partial_schedule(
     338             :         __isl_keep isl_schedule_band *band)
     339             : {
     340           0 :         return band ? isl_multi_union_pw_aff_copy(band->mupa) : NULL;
     341             : }
     342             : 
     343             : /* Replace the schedule of "band" by "schedule".
     344             :  */
     345           0 : __isl_give isl_schedule_band *isl_schedule_band_set_partial_schedule(
     346             :         __isl_take isl_schedule_band *band,
     347             :         __isl_take isl_multi_union_pw_aff *schedule)
     348             : {
     349           0 :         band = isl_schedule_band_cow(band);
     350           0 :         if (!band || !schedule)
     351             :                 goto error;
     352             : 
     353           0 :         isl_multi_union_pw_aff_free(band->mupa);
     354           0 :         band->mupa = schedule;
     355             : 
     356           0 :         return band;
     357             : error:
     358           0 :         isl_schedule_band_free(band);
     359           0 :         isl_multi_union_pw_aff_free(schedule);
     360           0 :         return NULL;
     361             : }
     362             : 
     363             : /* Return the loop AST generation type for the band member of "band"
     364             :  * at position "pos".
     365             :  */
     366           0 : enum isl_ast_loop_type isl_schedule_band_member_get_ast_loop_type(
     367             :         __isl_keep isl_schedule_band *band, int pos)
     368             : {
     369           0 :         if (!band)
     370           0 :                 return isl_ast_loop_error;
     371             : 
     372           0 :         if (pos < 0 || pos >= band->n)
     373           0 :                 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
     374             :                         "invalid member position", return isl_ast_loop_error);
     375             : 
     376           0 :         if (!band->loop_type)
     377           0 :                 return isl_ast_loop_default;
     378             : 
     379           0 :         return band->loop_type[pos];
     380             : }
     381             : 
     382             : /* Set the loop AST generation type for the band member of "band"
     383             :  * at position "pos" to "type".
     384             :  */
     385           0 : __isl_give isl_schedule_band *isl_schedule_band_member_set_ast_loop_type(
     386             :         __isl_take isl_schedule_band *band, int pos,
     387             :         enum isl_ast_loop_type type)
     388             : {
     389           0 :         if (!band)
     390           0 :                 return NULL;
     391           0 :         if (isl_schedule_band_member_get_ast_loop_type(band, pos) == type)
     392           0 :                 return band;
     393             : 
     394           0 :         if (pos < 0 || pos >= band->n)
     395           0 :                 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
     396             :                         "invalid member position",
     397             :                         return isl_schedule_band_free(band));
     398             : 
     399           0 :         band = isl_schedule_band_cow(band);
     400           0 :         if (!band)
     401           0 :                 return isl_schedule_band_free(band);
     402             : 
     403           0 :         if (!band->loop_type) {
     404             :                 isl_ctx *ctx;
     405             : 
     406           0 :                 ctx = isl_schedule_band_get_ctx(band);
     407           0 :                 band->loop_type = isl_calloc_array(ctx,
     408             :                                             enum isl_ast_loop_type, band->n);
     409           0 :                 if (band->n && !band->loop_type)
     410           0 :                         return isl_schedule_band_free(band);
     411             :         }
     412             : 
     413           0 :         band->loop_type[pos] = type;
     414             : 
     415           0 :         return band;
     416             : }
     417             : 
     418             : /* Return the loop AST generation type for the band member of "band"
     419             :  * at position "pos" for the part that has been isolated by the isolate option.
     420             :  */
     421           0 : enum isl_ast_loop_type isl_schedule_band_member_get_isolate_ast_loop_type(
     422             :         __isl_keep isl_schedule_band *band, int pos)
     423             : {
     424           0 :         if (!band)
     425           0 :                 return isl_ast_loop_error;
     426             : 
     427           0 :         if (pos < 0 || pos >= band->n)
     428           0 :                 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
     429             :                         "invalid member position", return isl_ast_loop_error);
     430             : 
     431           0 :         if (!band->isolate_loop_type)
     432           0 :                 return isl_ast_loop_default;
     433             : 
     434           0 :         return band->isolate_loop_type[pos];
     435             : }
     436             : 
     437             : /* Set the loop AST generation type for the band member of "band"
     438             :  * at position "pos" to "type" for the part that has been isolated
     439             :  * by the isolate option.
     440             :  */
     441             : __isl_give isl_schedule_band *
     442           0 : isl_schedule_band_member_set_isolate_ast_loop_type(
     443             :         __isl_take isl_schedule_band *band, int pos,
     444             :         enum isl_ast_loop_type type)
     445             : {
     446           0 :         if (!band)
     447           0 :                 return NULL;
     448           0 :         if (isl_schedule_band_member_get_isolate_ast_loop_type(band, pos) ==
     449             :                                                                         type)
     450           0 :                 return band;
     451             : 
     452           0 :         if (pos < 0 || pos >= band->n)
     453           0 :                 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
     454             :                         "invalid member position",
     455             :                         return isl_schedule_band_free(band));
     456             : 
     457           0 :         band = isl_schedule_band_cow(band);
     458           0 :         if (!band)
     459           0 :                 return isl_schedule_band_free(band);
     460             : 
     461           0 :         if (!band->isolate_loop_type) {
     462             :                 isl_ctx *ctx;
     463             : 
     464           0 :                 ctx = isl_schedule_band_get_ctx(band);
     465           0 :                 band->isolate_loop_type = isl_calloc_array(ctx,
     466             :                                             enum isl_ast_loop_type, band->n);
     467           0 :                 if (band->n && !band->isolate_loop_type)
     468           0 :                         return isl_schedule_band_free(band);
     469             :         }
     470             : 
     471           0 :         band->isolate_loop_type[pos] = type;
     472             : 
     473           0 :         return band;
     474             : }
     475             : 
     476             : static const char *option_str[] = {
     477             :         [isl_ast_loop_atomic] = "atomic",
     478             :         [isl_ast_loop_unroll] = "unroll",
     479             :         [isl_ast_loop_separate] = "separate"
     480             : };
     481             : 
     482             : /* Given a parameter space "space", extend it to a set space
     483             :  *
     484             :  *      { type[x] }
     485             :  *
     486             :  * or
     487             :  *
     488             :  *      { [isolate[] -> type[x]] }
     489             :  *
     490             :  * depending on whether "isolate" is set.
     491             :  * These can be used to encode loop AST generation options of the given type.
     492             :  */
     493           0 : static __isl_give isl_space *loop_type_space(__isl_take isl_space *space,
     494             :         enum isl_ast_loop_type type, int isolate)
     495             : {
     496             :         const char *name;
     497             : 
     498           0 :         name = option_str[type];
     499           0 :         space = isl_space_set_from_params(space);
     500           0 :         space = isl_space_add_dims(space, isl_dim_set, 1);
     501           0 :         space = isl_space_set_tuple_name(space, isl_dim_set, name);
     502           0 :         if (!isolate)
     503           0 :                 return space;
     504           0 :         space = isl_space_from_range(space);
     505           0 :         space = isl_space_set_tuple_name(space, isl_dim_in, "isolate");
     506           0 :         space = isl_space_wrap(space);
     507             : 
     508           0 :         return space;
     509             : }
     510             : 
     511             : /* Add encodings of the "n" loop AST generation options "type" to "options".
     512             :  * If "isolate" is set, then these options refer to the isolated part.
     513             :  *
     514             :  * In particular, for each sequence of consecutive identical types "t",
     515             :  * different from the default, add an option
     516             :  *
     517             :  *      { t[x] : first <= x <= last }
     518             :  *
     519             :  * or
     520             :  *
     521             :  *      { [isolate[] -> t[x]] : first <= x <= last }
     522             :  */
     523           0 : static __isl_give isl_union_set *add_loop_types(
     524             :         __isl_take isl_union_set *options, int n, enum isl_ast_loop_type *type,
     525             :         int isolate)
     526             : {
     527             :         int i;
     528             : 
     529           0 :         if (!type)
     530           0 :                 return options;
     531           0 :         if (!options)
     532           0 :                 return NULL;
     533             : 
     534           0 :         for (i = 0; i < n; ++i) {
     535             :                 int first;
     536             :                 isl_space *space;
     537             :                 isl_set *option;
     538             : 
     539           0 :                 if (type[i] == isl_ast_loop_default)
     540           0 :                         continue;
     541             : 
     542           0 :                 first = i;
     543           0 :                 while (i + 1 < n && type[i + 1] == type[i])
     544           0 :                         ++i;
     545             : 
     546           0 :                 space = isl_union_set_get_space(options);
     547           0 :                 space = loop_type_space(space, type[i], isolate);
     548           0 :                 option = isl_set_universe(space);
     549           0 :                 option = isl_set_lower_bound_si(option, isl_dim_set, 0, first);
     550           0 :                 option = isl_set_upper_bound_si(option, isl_dim_set, 0, i);
     551           0 :                 options = isl_union_set_add_set(options, option);
     552             :         }
     553             : 
     554           0 :         return options;
     555             : }
     556             : 
     557             : /* Return the AST build options associated to "band".
     558             :  */
     559           0 : __isl_give isl_union_set *isl_schedule_band_get_ast_build_options(
     560             :         __isl_keep isl_schedule_band *band)
     561             : {
     562             :         isl_union_set *options;
     563             : 
     564           0 :         if (!band)
     565           0 :                 return NULL;
     566             : 
     567           0 :         options = isl_union_set_copy(band->ast_build_options);
     568           0 :         options = add_loop_types(options, band->n, band->loop_type, 0);
     569           0 :         options = add_loop_types(options, band->n, band->isolate_loop_type, 1);
     570             : 
     571           0 :         return options;
     572             : }
     573             : 
     574             : /* Does "uset" contain any set that satisfies "is"?
     575             :  * "is" is assumed to set its integer argument to 1 if it is satisfied.
     576             :  */
     577           0 : static int has_any(__isl_keep isl_union_set *uset,
     578             :         isl_stat (*is)(__isl_take isl_set *set, void *user))
     579             : {
     580           0 :         int found = 0;
     581             : 
     582           0 :         if (isl_union_set_foreach_set(uset, is, &found) < 0 && !found)
     583           0 :                 return -1;
     584             : 
     585           0 :         return found;
     586             : }
     587             : 
     588             : /* Does "set" live in a space of the form
     589             :  *
     590             :  *      isolate[[...] -> [...]]
     591             :  *
     592             :  * ?
     593             :  *
     594             :  * If so, set *found and abort the search.
     595             :  */
     596           0 : static isl_stat is_isolate(__isl_take isl_set *set, void *user)
     597             : {
     598           0 :         int *found = user;
     599             : 
     600           0 :         if (isl_set_has_tuple_name(set)) {
     601             :                 const char *name;
     602           0 :                 name = isl_set_get_tuple_name(set);
     603           0 :                 if (isl_set_is_wrapping(set) && !strcmp(name, "isolate"))
     604           0 :                         *found = 1;
     605             :         }
     606           0 :         isl_set_free(set);
     607             : 
     608           0 :         return *found ? isl_stat_error : isl_stat_ok;
     609             : }
     610             : 
     611             : /* Does "options" include an option of the ofrm
     612             :  *
     613             :  *      isolate[[...] -> [...]]
     614             :  *
     615             :  * ?
     616             :  */
     617           0 : static int has_isolate_option(__isl_keep isl_union_set *options)
     618             : {
     619           0 :         return has_any(options, &is_isolate);
     620             : }
     621             : 
     622             : /* Does "set" encode a loop AST generation option?
     623             :  */
     624           0 : static isl_stat is_loop_type_option(__isl_take isl_set *set, void *user)
     625             : {
     626           0 :         int *found = user;
     627             : 
     628           0 :         if (isl_set_dim(set, isl_dim_set) == 1 &&
     629           0 :             isl_set_has_tuple_name(set)) {
     630             :                 const char *name;
     631             :                 enum isl_ast_loop_type type;
     632           0 :                 name = isl_set_get_tuple_name(set);
     633           0 :                 for (type = isl_ast_loop_atomic;
     634           0 :                     type <= isl_ast_loop_separate; ++type) {
     635           0 :                         if (strcmp(name, option_str[type]))
     636           0 :                                 continue;
     637           0 :                         *found = 1;
     638           0 :                         break;
     639             :                 }
     640             :         }
     641           0 :         isl_set_free(set);
     642             : 
     643           0 :         return *found ? isl_stat_error : isl_stat_ok;
     644             : }
     645             : 
     646             : /* Does "set" encode a loop AST generation option for the isolated part?
     647             :  * That is, is of the form
     648             :  *
     649             :  *      { [isolate[] -> t[x]] }
     650             :  *
     651             :  * with t equal to "atomic", "unroll" or "separate"?
     652             :  */
     653           0 : static isl_stat is_isolate_loop_type_option(__isl_take isl_set *set, void *user)
     654             : {
     655           0 :         int *found = user;
     656             :         const char *name;
     657             :         enum isl_ast_loop_type type;
     658             :         isl_map *map;
     659             : 
     660           0 :         if (!isl_set_is_wrapping(set)) {
     661           0 :                 isl_set_free(set);
     662           0 :                 return isl_stat_ok;
     663             :         }
     664           0 :         map = isl_set_unwrap(set);
     665           0 :         if (!isl_map_has_tuple_name(map, isl_dim_in) ||
     666           0 :             !isl_map_has_tuple_name(map, isl_dim_out)) {
     667           0 :                 isl_map_free(map);
     668           0 :                 return isl_stat_ok;
     669             :         }
     670           0 :         name = isl_map_get_tuple_name(map, isl_dim_in);
     671           0 :         if (!strcmp(name, "isolate")) {
     672           0 :                 name = isl_map_get_tuple_name(map, isl_dim_out);
     673           0 :                 for (type = isl_ast_loop_atomic;
     674           0 :                     type <= isl_ast_loop_separate; ++type) {
     675           0 :                         if (strcmp(name, option_str[type]))
     676           0 :                                 continue;
     677           0 :                         *found = 1;
     678           0 :                         break;
     679             :                 }
     680             :         }
     681           0 :         isl_map_free(map);
     682             : 
     683           0 :         return *found ? isl_stat_error : isl_stat_ok;
     684             : }
     685             : 
     686             : /* Does "options" encode any loop AST generation options
     687             :  * for the isolated part?
     688             :  */
     689           0 : static int has_isolate_loop_type_options(__isl_keep isl_union_set *options)
     690             : {
     691           0 :         return has_any(options, &is_isolate_loop_type_option);
     692             : }
     693             : 
     694             : /* Does "options" encode any loop AST generation options?
     695             :  */
     696           0 : static int has_loop_type_options(__isl_keep isl_union_set *options)
     697             : {
     698           0 :         return has_any(options, &is_loop_type_option);
     699             : }
     700             : 
     701             : /* Extract the loop AST generation type for the band member
     702             :  * at position "pos" from "options".
     703             :  * If "isolate" is set, then extract the loop types for the isolated part.
     704             :  */
     705           0 : static enum isl_ast_loop_type extract_loop_type(
     706             :         __isl_keep isl_union_set *options, int pos, int isolate)
     707             : {
     708             :         isl_ctx *ctx;
     709           0 :         enum isl_ast_loop_type type, res = isl_ast_loop_default;
     710             : 
     711           0 :         ctx = isl_union_set_get_ctx(options);
     712           0 :         for (type = isl_ast_loop_atomic;
     713           0 :             type <= isl_ast_loop_separate; ++type) {
     714             :                 isl_space *space;
     715             :                 isl_set *option;
     716             :                 int empty;
     717             : 
     718           0 :                 space = isl_union_set_get_space(options);
     719           0 :                 space = loop_type_space(space, type, isolate);
     720           0 :                 option = isl_union_set_extract_set(options, space);
     721           0 :                 option = isl_set_fix_si(option, isl_dim_set, 0, pos);
     722           0 :                 empty = isl_set_is_empty(option);
     723           0 :                 isl_set_free(option);
     724             : 
     725           0 :                 if (empty < 0)
     726           0 :                         return isl_ast_loop_error;
     727           0 :                 if (empty)
     728           0 :                         continue;
     729           0 :                 if (res != isl_ast_loop_default)
     730           0 :                         isl_die(ctx, isl_error_invalid,
     731             :                                 "conflicting loop type options",
     732             :                                 return isl_ast_loop_error);
     733           0 :                 res = type;
     734             :         }
     735             : 
     736           0 :         return res;
     737             : }
     738             : 
     739             : /* Extract the loop AST generation types for the members of "band"
     740             :  * from "options" and store them in band->loop_type.
     741             :  * Return -1 on error.
     742             :  */
     743           0 : static int extract_loop_types(__isl_keep isl_schedule_band *band,
     744             :         __isl_keep isl_union_set *options)
     745             : {
     746             :         int i;
     747             : 
     748           0 :         if (!band->loop_type) {
     749           0 :                 isl_ctx *ctx = isl_schedule_band_get_ctx(band);
     750           0 :                 band->loop_type = isl_alloc_array(ctx,
     751             :                                             enum isl_ast_loop_type, band->n);
     752           0 :                 if (band->n && !band->loop_type)
     753           0 :                         return -1;
     754             :         }
     755           0 :         for (i = 0; i < band->n; ++i) {
     756           0 :                 band->loop_type[i] = extract_loop_type(options, i, 0);
     757           0 :                 if (band->loop_type[i] == isl_ast_loop_error)
     758           0 :                         return -1;
     759             :         }
     760             : 
     761           0 :         return 0;
     762             : }
     763             : 
     764             : /* Extract the loop AST generation types for the members of "band"
     765             :  * from "options" for the isolated part and
     766             :  * store them in band->isolate_loop_type.
     767             :  * Return -1 on error.
     768             :  */
     769           0 : static int extract_isolate_loop_types(__isl_keep isl_schedule_band *band,
     770             :         __isl_keep isl_union_set *options)
     771             : {
     772             :         int i;
     773             : 
     774           0 :         if (!band->isolate_loop_type) {
     775           0 :                 isl_ctx *ctx = isl_schedule_band_get_ctx(band);
     776           0 :                 band->isolate_loop_type = isl_alloc_array(ctx,
     777             :                                             enum isl_ast_loop_type, band->n);
     778           0 :                 if (band->n && !band->isolate_loop_type)
     779           0 :                         return -1;
     780             :         }
     781           0 :         for (i = 0; i < band->n; ++i) {
     782           0 :                 band->isolate_loop_type[i] = extract_loop_type(options, i, 1);
     783           0 :                 if (band->isolate_loop_type[i] == isl_ast_loop_error)
     784           0 :                         return -1;
     785             :         }
     786             : 
     787           0 :         return 0;
     788             : }
     789             : 
     790             : /* Construct universe sets of the spaces that encode loop AST generation
     791             :  * types (for the isolated part if "isolate" is set).  That is, construct
     792             :  *
     793             :  *      { atomic[x]; separate[x]; unroll[x] }
     794             :  *
     795             :  * or
     796             :  *
     797             :  *      { [isolate[] -> atomic[x]]; [isolate[] -> separate[x]];
     798             :  *        [isolate[] -> unroll[x]] }
     799             :  */
     800           0 : static __isl_give isl_union_set *loop_types(__isl_take isl_space *space,
     801             :         int isolate)
     802             : {
     803             :         enum isl_ast_loop_type type;
     804             :         isl_union_set *types;
     805             : 
     806           0 :         types = isl_union_set_empty(space);
     807           0 :         for (type = isl_ast_loop_atomic;
     808           0 :             type <= isl_ast_loop_separate; ++type) {
     809             :                 isl_set *set;
     810             : 
     811           0 :                 space = isl_union_set_get_space(types);
     812           0 :                 space = loop_type_space(space, type, isolate);
     813           0 :                 set = isl_set_universe(space);
     814           0 :                 types = isl_union_set_add_set(types, set);
     815             :         }
     816             : 
     817           0 :         return types;
     818             : }
     819             : 
     820             : /* Remove all elements from spaces that encode loop AST generation types
     821             :  * from "options".
     822             :  */
     823           0 : static __isl_give isl_union_set *clear_loop_types(
     824             :         __isl_take isl_union_set *options)
     825             : {
     826             :         isl_union_set *types;
     827             : 
     828           0 :         types = loop_types(isl_union_set_get_space(options), 0);
     829           0 :         options = isl_union_set_subtract(options, types);
     830             : 
     831           0 :         return options;
     832             : }
     833             : 
     834             : /* Remove all elements from spaces that encode loop AST generation types
     835             :  * for the isolated part from "options".
     836             :  */
     837           0 : static __isl_give isl_union_set *clear_isolate_loop_types(
     838             :         __isl_take isl_union_set *options)
     839             : {
     840             :         isl_union_set *types;
     841             : 
     842           0 :         types = loop_types(isl_union_set_get_space(options), 1);
     843           0 :         options = isl_union_set_subtract(options, types);
     844             : 
     845           0 :         return options;
     846             : }
     847             : 
     848             : /* Replace the AST build options associated to "band" by "options".
     849             :  * If there are any loop AST generation type options, then they
     850             :  * are extracted and stored in band->loop_type.  Otherwise,
     851             :  * band->loop_type is removed to indicate that the default applies
     852             :  * to all members.  Similarly for the loop AST generation type options
     853             :  * for the isolated part, which are stored in band->isolate_loop_type.
     854             :  * The remaining options are stored in band->ast_build_options.
     855             :  *
     856             :  * Set anchored if the options include an isolate option since the
     857             :  * domain of the wrapped map references the outer band node schedules.
     858             :  */
     859           0 : __isl_give isl_schedule_band *isl_schedule_band_set_ast_build_options(
     860             :         __isl_take isl_schedule_band *band, __isl_take isl_union_set *options)
     861             : {
     862             :         int has_isolate, has_loop_type, has_isolate_loop_type;
     863             : 
     864           0 :         band = isl_schedule_band_cow(band);
     865           0 :         if (!band || !options)
     866             :                 goto error;
     867           0 :         has_isolate = has_isolate_option(options);
     868           0 :         if (has_isolate < 0)
     869           0 :                 goto error;
     870           0 :         has_loop_type = has_loop_type_options(options);
     871           0 :         if (has_loop_type < 0)
     872           0 :                 goto error;
     873           0 :         has_isolate_loop_type = has_isolate_loop_type_options(options);
     874           0 :         if (has_isolate_loop_type < 0)
     875           0 :                 goto error;
     876             : 
     877           0 :         if (!has_loop_type) {
     878           0 :                 free(band->loop_type);
     879           0 :                 band->loop_type = NULL;
     880             :         } else {
     881           0 :                 if (extract_loop_types(band, options) < 0)
     882           0 :                         goto error;
     883           0 :                 options = clear_loop_types(options);
     884           0 :                 if (!options)
     885           0 :                         goto error;
     886             :         }
     887             : 
     888           0 :         if (!has_isolate_loop_type) {
     889           0 :                 free(band->isolate_loop_type);
     890           0 :                 band->isolate_loop_type = NULL;
     891             :         } else {
     892           0 :                 if (extract_isolate_loop_types(band, options) < 0)
     893           0 :                         goto error;
     894           0 :                 options = clear_isolate_loop_types(options);
     895           0 :                 if (!options)
     896           0 :                         goto error;
     897             :         }
     898             : 
     899           0 :         isl_union_set_free(band->ast_build_options);
     900           0 :         band->ast_build_options = options;
     901           0 :         band->anchored = has_isolate;
     902             : 
     903           0 :         return band;
     904             : error:
     905           0 :         isl_schedule_band_free(band);
     906           0 :         isl_union_set_free(options);
     907           0 :         return NULL;
     908             : }
     909             : 
     910             : /* Return the "isolate" option associated to "band", assuming
     911             :  * it at appears at schedule depth "depth".
     912             :  *
     913             :  * The isolate option is of the form
     914             :  *
     915             :  *      isolate[[flattened outer bands] -> band]
     916             :  */
     917           0 : __isl_give isl_set *isl_schedule_band_get_ast_isolate_option(
     918             :         __isl_keep isl_schedule_band *band, int depth)
     919             : {
     920             :         isl_space *space;
     921             :         isl_set *isolate;
     922             : 
     923           0 :         if (!band)
     924           0 :                 return NULL;
     925             : 
     926           0 :         space = isl_schedule_band_get_space(band);
     927           0 :         space = isl_space_from_range(space);
     928           0 :         space = isl_space_add_dims(space, isl_dim_in, depth);
     929           0 :         space = isl_space_wrap(space);
     930           0 :         space = isl_space_set_tuple_name(space, isl_dim_set, "isolate");
     931             : 
     932           0 :         isolate = isl_union_set_extract_set(band->ast_build_options, space);
     933             : 
     934           0 :         return isolate;
     935             : }
     936             : 
     937             : /* Replace the option "drop" in the AST build options by "add".
     938             :  * That is, remove "drop" and add "add".
     939             :  */
     940           0 : __isl_give isl_schedule_band *isl_schedule_band_replace_ast_build_option(
     941             :         __isl_take isl_schedule_band *band, __isl_take isl_set *drop,
     942             :         __isl_take isl_set *add)
     943             : {
     944             :         isl_union_set *options;
     945             : 
     946           0 :         band = isl_schedule_band_cow(band);
     947           0 :         if (!band)
     948           0 :                 goto error;
     949             : 
     950           0 :         options = band->ast_build_options;
     951           0 :         options = isl_union_set_subtract(options, isl_union_set_from_set(drop));
     952           0 :         options = isl_union_set_union(options, isl_union_set_from_set(add));
     953           0 :         band->ast_build_options = options;
     954             : 
     955           0 :         if (!band->ast_build_options)
     956           0 :                 return isl_schedule_band_free(band);
     957             : 
     958           0 :         return band;
     959             : error:
     960           0 :         isl_schedule_band_free(band);
     961           0 :         isl_set_free(drop);
     962           0 :         isl_set_free(add);
     963           0 :         return NULL;
     964             : }
     965             : 
     966             : /* Multiply the partial schedule of "band" with the factors in "mv".
     967             :  * Replace the result by its greatest integer part to ensure
     968             :  * that the schedule is always integral.
     969             :  */
     970           0 : __isl_give isl_schedule_band *isl_schedule_band_scale(
     971             :         __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
     972             : {
     973           0 :         band = isl_schedule_band_cow(band);
     974           0 :         if (!band || !mv)
     975             :                 goto error;
     976           0 :         band->mupa = isl_multi_union_pw_aff_scale_multi_val(band->mupa, mv);
     977           0 :         band->mupa = isl_multi_union_pw_aff_floor(band->mupa);
     978           0 :         if (!band->mupa)
     979           0 :                 return isl_schedule_band_free(band);
     980           0 :         return band;
     981             : error:
     982           0 :         isl_schedule_band_free(band);
     983           0 :         isl_multi_val_free(mv);
     984           0 :         return NULL;
     985             : }
     986             : 
     987             : /* Divide the partial schedule of "band" by the factors in "mv".
     988             :  * Replace the result by its greatest integer part to ensure
     989             :  * that the schedule is always integral.
     990             :  */
     991           0 : __isl_give isl_schedule_band *isl_schedule_band_scale_down(
     992             :         __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
     993             : {
     994           0 :         band = isl_schedule_band_cow(band);
     995           0 :         if (!band || !mv)
     996             :                 goto error;
     997           0 :         band->mupa = isl_multi_union_pw_aff_scale_down_multi_val(band->mupa,
     998             :                                                                 mv);
     999           0 :         band->mupa = isl_multi_union_pw_aff_floor(band->mupa);
    1000           0 :         if (!band->mupa)
    1001           0 :                 return isl_schedule_band_free(band);
    1002           0 :         return band;
    1003             : error:
    1004           0 :         isl_schedule_band_free(band);
    1005           0 :         isl_multi_val_free(mv);
    1006           0 :         return NULL;
    1007             : }
    1008             : 
    1009             : /* Reduce the partial schedule of "band" modulo the factors in "mv".
    1010             :  */
    1011           0 : __isl_give isl_schedule_band *isl_schedule_band_mod(
    1012             :         __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
    1013             : {
    1014           0 :         band = isl_schedule_band_cow(band);
    1015           0 :         if (!band || !mv)
    1016             :                 goto error;
    1017           0 :         band->mupa = isl_multi_union_pw_aff_mod_multi_val(band->mupa, mv);
    1018           0 :         if (!band->mupa)
    1019           0 :                 return isl_schedule_band_free(band);
    1020           0 :         return band;
    1021             : error:
    1022           0 :         isl_schedule_band_free(band);
    1023           0 :         isl_multi_val_free(mv);
    1024           0 :         return NULL;
    1025             : }
    1026             : 
    1027             : /* Shift the partial schedule of "band" by "shift" after checking
    1028             :  * that the domain of the partial schedule would not be affected
    1029             :  * by this shift.
    1030             :  */
    1031           0 : __isl_give isl_schedule_band *isl_schedule_band_shift(
    1032             :         __isl_take isl_schedule_band *band,
    1033             :         __isl_take isl_multi_union_pw_aff *shift)
    1034             : {
    1035             :         isl_union_set *dom1, *dom2;
    1036             :         isl_bool subset;
    1037             : 
    1038           0 :         band = isl_schedule_band_cow(band);
    1039           0 :         if (!band || !shift)
    1040             :                 goto error;
    1041           0 :         dom1 = isl_multi_union_pw_aff_domain(
    1042             :                                 isl_multi_union_pw_aff_copy(band->mupa));
    1043           0 :         dom2 = isl_multi_union_pw_aff_domain(
    1044             :                                 isl_multi_union_pw_aff_copy(shift));
    1045           0 :         subset = isl_union_set_is_subset(dom1, dom2);
    1046           0 :         isl_union_set_free(dom1);
    1047           0 :         isl_union_set_free(dom2);
    1048           0 :         if (subset < 0)
    1049           0 :                 goto error;
    1050           0 :         if (!subset)
    1051           0 :                 isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
    1052             :                         "domain of shift needs to include domain of "
    1053             :                         "partial schedule", goto error);
    1054           0 :         band->mupa = isl_multi_union_pw_aff_add(band->mupa, shift);
    1055           0 :         if (!band->mupa)
    1056           0 :                 return isl_schedule_band_free(band);
    1057           0 :         return band;
    1058             : error:
    1059           0 :         isl_schedule_band_free(band);
    1060           0 :         isl_multi_union_pw_aff_free(shift);
    1061           0 :         return NULL;
    1062             : }
    1063             : 
    1064             : /* Given the schedule of a band, construct the corresponding
    1065             :  * schedule for the tile loops based on the given tile sizes
    1066             :  * and return the result.
    1067             :  *
    1068             :  * If the scale tile loops options is set, then the tile loops
    1069             :  * are scaled by the tile sizes.
    1070             :  *
    1071             :  * That is replace each schedule dimension "i" by either
    1072             :  * "floor(i/s)" or "s * floor(i/s)".
    1073             :  */
    1074           0 : static isl_multi_union_pw_aff *isl_multi_union_pw_aff_tile(
    1075             :         __isl_take isl_multi_union_pw_aff *sched,
    1076             :         __isl_take isl_multi_val *sizes)
    1077             : {
    1078             :         isl_ctx *ctx;
    1079             :         int i, n;
    1080             :         isl_val *v;
    1081             :         int scale;
    1082             : 
    1083           0 :         ctx = isl_multi_val_get_ctx(sizes);
    1084           0 :         scale = isl_options_get_tile_scale_tile_loops(ctx);
    1085             : 
    1086           0 :         n = isl_multi_union_pw_aff_dim(sched, isl_dim_set);
    1087           0 :         for (i = 0; i < n; ++i) {
    1088             :                 isl_union_pw_aff *upa;
    1089             : 
    1090           0 :                 upa = isl_multi_union_pw_aff_get_union_pw_aff(sched, i);
    1091           0 :                 v = isl_multi_val_get_val(sizes, i);
    1092             : 
    1093           0 :                 upa = isl_union_pw_aff_scale_down_val(upa, isl_val_copy(v));
    1094           0 :                 upa = isl_union_pw_aff_floor(upa);
    1095           0 :                 if (scale)
    1096           0 :                         upa = isl_union_pw_aff_scale_val(upa, isl_val_copy(v));
    1097           0 :                 isl_val_free(v);
    1098             : 
    1099           0 :                 sched = isl_multi_union_pw_aff_set_union_pw_aff(sched, i, upa);
    1100             :         }
    1101             : 
    1102           0 :         isl_multi_val_free(sizes);
    1103           0 :         return sched;
    1104             : }
    1105             : 
    1106             : /* Replace "band" by a band corresponding to the tile loops of a tiling
    1107             :  * with the given tile sizes.
    1108             :  */
    1109           0 : __isl_give isl_schedule_band *isl_schedule_band_tile(
    1110             :         __isl_take isl_schedule_band *band, __isl_take isl_multi_val *sizes)
    1111             : {
    1112           0 :         band = isl_schedule_band_cow(band);
    1113           0 :         if (!band || !sizes)
    1114             :                 goto error;
    1115           0 :         band->mupa = isl_multi_union_pw_aff_tile(band->mupa, sizes);
    1116           0 :         if (!band->mupa)
    1117           0 :                 return isl_schedule_band_free(band);
    1118           0 :         return band;
    1119             : error:
    1120           0 :         isl_schedule_band_free(band);
    1121           0 :         isl_multi_val_free(sizes);
    1122           0 :         return NULL;
    1123             : }
    1124             : 
    1125             : /* Replace "band" by a band corresponding to the point loops of a tiling
    1126             :  * with the given tile sizes.
    1127             :  * "tile" is the corresponding tile loop band.
    1128             :  *
    1129             :  * If the shift point loops option is set, then the point loops
    1130             :  * are shifted to start at zero.  That is, each schedule dimension "i"
    1131             :  * is replaced by "i - s * floor(i/s)".
    1132             :  * The expression "floor(i/s)" (or "s * floor(i/s)") is extracted from
    1133             :  * the tile band.
    1134             :  *
    1135             :  * Otherwise, the band is left untouched.
    1136             :  */
    1137           0 : __isl_give isl_schedule_band *isl_schedule_band_point(
    1138             :         __isl_take isl_schedule_band *band, __isl_keep isl_schedule_band *tile,
    1139             :         __isl_take isl_multi_val *sizes)
    1140             : {
    1141             :         isl_ctx *ctx;
    1142             :         isl_multi_union_pw_aff *scaled;
    1143             : 
    1144           0 :         if (!band || !sizes)
    1145             :                 goto error;
    1146             : 
    1147           0 :         ctx = isl_schedule_band_get_ctx(band);
    1148           0 :         if (!isl_options_get_tile_shift_point_loops(ctx)) {
    1149           0 :                 isl_multi_val_free(sizes);
    1150           0 :                 return band;
    1151             :         }
    1152           0 :         band = isl_schedule_band_cow(band);
    1153           0 :         if (!band)
    1154           0 :                 goto error;
    1155             : 
    1156           0 :         scaled = isl_schedule_band_get_partial_schedule(tile);
    1157           0 :         if (!isl_options_get_tile_scale_tile_loops(ctx))
    1158           0 :                 scaled = isl_multi_union_pw_aff_scale_multi_val(scaled, sizes);
    1159             :         else
    1160           0 :                 isl_multi_val_free(sizes);
    1161           0 :         band->mupa = isl_multi_union_pw_aff_sub(band->mupa, scaled);
    1162           0 :         if (!band->mupa)
    1163           0 :                 return isl_schedule_band_free(band);
    1164           0 :         return band;
    1165             : error:
    1166           0 :         isl_schedule_band_free(band);
    1167           0 :         isl_multi_val_free(sizes);
    1168           0 :         return NULL;
    1169             : }
    1170             : 
    1171             : /* Drop the "n" dimensions starting at "pos" from "band".
    1172             :  *
    1173             :  * We apply the transformation even if "n" is zero to ensure consistent
    1174             :  * behavior with respect to changes in the schedule space.
    1175             :  *
    1176             :  * The caller is responsible for updating the isolate option.
    1177             :  */
    1178           0 : __isl_give isl_schedule_band *isl_schedule_band_drop(
    1179             :         __isl_take isl_schedule_band *band, int pos, int n)
    1180             : {
    1181             :         int i;
    1182             : 
    1183           0 :         if (pos < 0 || n < 0 || pos + n > band->n)
    1184           0 :                 isl_die(isl_schedule_band_get_ctx(band), isl_error_internal,
    1185             :                         "range out of bounds",
    1186             :                         return isl_schedule_band_free(band));
    1187             : 
    1188           0 :         band = isl_schedule_band_cow(band);
    1189           0 :         if (!band)
    1190           0 :                 return NULL;
    1191             : 
    1192           0 :         band->mupa = isl_multi_union_pw_aff_drop_dims(band->mupa,
    1193             :                                                         isl_dim_set, pos, n);
    1194           0 :         if (!band->mupa)
    1195           0 :                 return isl_schedule_band_free(band);
    1196             : 
    1197           0 :         for (i = pos + n; i < band->n; ++i)
    1198           0 :                 band->coincident[i - n] = band->coincident[i];
    1199           0 :         if (band->loop_type)
    1200           0 :                 for (i = pos + n; i < band->n; ++i)
    1201           0 :                         band->loop_type[i - n] = band->loop_type[i];
    1202           0 :         if (band->isolate_loop_type)
    1203           0 :                 for (i = pos + n; i < band->n; ++i)
    1204           0 :                         band->isolate_loop_type[i - n] =
    1205           0 :                                                     band->isolate_loop_type[i];
    1206             : 
    1207           0 :         band->n -= n;
    1208             : 
    1209           0 :         return band;
    1210             : }
    1211             : 
    1212             : /* Reset the user pointer on all identifiers of parameters and tuples
    1213             :  * in "band".
    1214             :  */
    1215           0 : __isl_give isl_schedule_band *isl_schedule_band_reset_user(
    1216             :         __isl_take isl_schedule_band *band)
    1217             : {
    1218           0 :         band = isl_schedule_band_cow(band);
    1219           0 :         if (!band)
    1220           0 :                 return NULL;
    1221             : 
    1222           0 :         band->mupa = isl_multi_union_pw_aff_reset_user(band->mupa);
    1223           0 :         band->ast_build_options =
    1224           0 :                 isl_union_set_reset_user(band->ast_build_options);
    1225           0 :         if (!band->mupa || !band->ast_build_options)
    1226           0 :                 return isl_schedule_band_free(band);
    1227             : 
    1228           0 :         return band;
    1229             : }
    1230             : 
    1231             : /* Align the parameters of "band" to those of "space".
    1232             :  */
    1233           0 : __isl_give isl_schedule_band *isl_schedule_band_align_params(
    1234             :         __isl_take isl_schedule_band *band, __isl_take isl_space *space)
    1235             : {
    1236           0 :         band = isl_schedule_band_cow(band);
    1237           0 :         if (!band || !space)
    1238             :                 goto error;
    1239             : 
    1240           0 :         band->mupa = isl_multi_union_pw_aff_align_params(band->mupa,
    1241             :                                                 isl_space_copy(space));
    1242           0 :         band->ast_build_options =
    1243           0 :                 isl_union_set_align_params(band->ast_build_options, space);
    1244           0 :         if (!band->mupa || !band->ast_build_options)
    1245           0 :                 return isl_schedule_band_free(band);
    1246             : 
    1247           0 :         return band;
    1248             : error:
    1249           0 :         isl_space_free(space);
    1250           0 :         isl_schedule_band_free(band);
    1251           0 :         return NULL;
    1252             : }
    1253             : 
    1254             : /* Compute the pullback of "band" by the function represented by "upma".
    1255             :  * In other words, plug in "upma" in the iteration domains of "band".
    1256             :  */
    1257           0 : __isl_give isl_schedule_band *isl_schedule_band_pullback_union_pw_multi_aff(
    1258             :         __isl_take isl_schedule_band *band,
    1259             :         __isl_take isl_union_pw_multi_aff *upma)
    1260             : {
    1261           0 :         band = isl_schedule_band_cow(band);
    1262           0 :         if (!band || !upma)
    1263             :                 goto error;
    1264             : 
    1265           0 :         band->mupa =
    1266           0 :                 isl_multi_union_pw_aff_pullback_union_pw_multi_aff(band->mupa,
    1267             :                                                                         upma);
    1268           0 :         if (!band->mupa)
    1269           0 :                 return isl_schedule_band_free(band);
    1270             : 
    1271           0 :         return band;
    1272             : error:
    1273           0 :         isl_union_pw_multi_aff_free(upma);
    1274           0 :         isl_schedule_band_free(band);
    1275           0 :         return NULL;
    1276             : }
    1277             : 
    1278             : /* Compute the gist of "band" with respect to "context".
    1279             :  * In particular, compute the gist of the associated partial schedule.
    1280             :  */
    1281           0 : __isl_give isl_schedule_band *isl_schedule_band_gist(
    1282             :         __isl_take isl_schedule_band *band, __isl_take isl_union_set *context)
    1283             : {
    1284           0 :         if (!band || !context)
    1285             :                 goto error;
    1286           0 :         if (band->n == 0) {
    1287           0 :                 isl_union_set_free(context);
    1288           0 :                 return band;
    1289             :         }
    1290           0 :         band = isl_schedule_band_cow(band);
    1291           0 :         if (!band)
    1292           0 :                 goto error;
    1293           0 :         band->mupa = isl_multi_union_pw_aff_gist(band->mupa, context);
    1294           0 :         if (!band->mupa)
    1295           0 :                 return isl_schedule_band_free(band);
    1296           0 :         return band;
    1297             : error:
    1298           0 :         isl_union_set_free(context);
    1299           0 :         isl_schedule_band_free(band);
    1300           0 :         return NULL;
    1301             : }

Generated by: LCOV version 1.12