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

          Line data    Source code
       1             : /*
       2             :  * Copyright 2010-2011 INRIA Saclay
       3             :  * Copyright 2012-2013 Ecole Normale Superieure
       4             :  *
       5             :  * Use of this software is governed by the MIT license
       6             :  *
       7             :  * Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
       8             :  * Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
       9             :  * 91893 Orsay, France
      10             :  * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
      11             :  */
      12             : 
      13             : #include <isl/val.h>
      14             : #include <isl/space.h>
      15             : #include <isl_map_private.h>
      16             : #include <isl_aff_private.h>
      17             : #include <isl/constraint.h>
      18             : #include <isl/ilp.h>
      19             : #include <isl/fixed_box.h>
      20             : 
      21             : /* Representation of a box of fixed size containing the elements
      22             :  * [offset, offset + size).
      23             :  * "size" lives in the target space of "offset".
      24             :  *
      25             :  * If any of the "offsets" is NaN, then the object represents
      26             :  * the failure of finding a fixed-size box.
      27             :  */
      28             : struct isl_fixed_box {
      29             :         isl_multi_aff *offset;
      30             :         isl_multi_val *size;
      31             : };
      32             : 
      33             : /* Free "box" and return NULL.
      34             :  */
      35           0 : __isl_null isl_fixed_box *isl_fixed_box_free(__isl_take isl_fixed_box *box)
      36             : {
      37           0 :         if (!box)
      38           0 :                 return NULL;
      39           0 :         isl_multi_aff_free(box->offset);
      40           0 :         isl_multi_val_free(box->size);
      41           0 :         free(box);
      42           0 :         return NULL;
      43             : }
      44             : 
      45             : /* Construct an isl_fixed_box with the given offset and size.
      46             :  */
      47           0 : static __isl_give isl_fixed_box *isl_fixed_box_alloc(
      48             :         __isl_take isl_multi_aff *offset, __isl_take isl_multi_val *size)
      49             : {
      50             :         isl_ctx *ctx;
      51             :         isl_fixed_box *box;
      52             : 
      53           0 :         if (!offset || !size)
      54             :                 goto error;
      55           0 :         ctx = isl_multi_aff_get_ctx(offset);
      56           0 :         box = isl_alloc_type(ctx, struct isl_fixed_box);
      57           0 :         if (!box)
      58           0 :                 goto error;
      59           0 :         box->offset = offset;
      60           0 :         box->size = size;
      61             : 
      62           0 :         return box;
      63             : error:
      64           0 :         isl_multi_aff_free(offset);
      65           0 :         isl_multi_val_free(size);
      66           0 :         return NULL;
      67             : }
      68             : 
      69             : /* Construct an initial isl_fixed_box with zero offsets
      70             :  * in the given space and zero corresponding sizes.
      71             :  */
      72           0 : static __isl_give isl_fixed_box *isl_fixed_box_init(
      73             :         __isl_take isl_space *space)
      74             : {
      75             :         isl_multi_aff *offset;
      76             :         isl_multi_val *size;
      77             : 
      78           0 :         offset = isl_multi_aff_zero(isl_space_copy(space));
      79           0 :         size = isl_multi_val_zero(isl_space_range(space));
      80           0 :         return isl_fixed_box_alloc(offset, size);
      81             : }
      82             : 
      83             : /* Return a copy of "box".
      84             :  */
      85           0 : __isl_give isl_fixed_box *isl_fixed_box_copy(__isl_keep isl_fixed_box *box)
      86             : {
      87             :         isl_multi_aff *offset;
      88             :         isl_multi_val *size;
      89             : 
      90           0 :         offset = isl_fixed_box_get_offset(box);
      91           0 :         size = isl_fixed_box_get_size(box);
      92           0 :         return isl_fixed_box_alloc(offset, size);
      93             : }
      94             : 
      95             : /* Replace the offset and size in direction "pos" by "offset" and "size"
      96             :  * (without checking whether "box" is a valid box).
      97             :  */
      98           0 : static __isl_give isl_fixed_box *isl_fixed_box_set_extent(
      99             :         __isl_take isl_fixed_box *box, int pos, __isl_keep isl_aff *offset,
     100             :         __isl_keep isl_val *size)
     101             : {
     102           0 :         if (!box)
     103           0 :                 return NULL;
     104           0 :         box->offset = isl_multi_aff_set_aff(box->offset, pos,
     105             :                                                         isl_aff_copy(offset));
     106           0 :         box->size = isl_multi_val_set_val(box->size, pos, isl_val_copy(size));
     107           0 :         if (!box->offset || !box->size)
     108           0 :                 return isl_fixed_box_free(box);
     109           0 :         return box;
     110             : }
     111             : 
     112             : /* Replace the offset and size in direction "pos" by "offset" and "size",
     113             :  * if "box" is a valid box.
     114             :  */
     115           0 : static __isl_give isl_fixed_box *isl_fixed_box_set_valid_extent(
     116             :         __isl_take isl_fixed_box *box, int pos, __isl_keep isl_aff *offset,
     117             :         __isl_keep isl_val *size)
     118             : {
     119             :         isl_bool valid;
     120             : 
     121           0 :         valid = isl_fixed_box_is_valid(box);
     122           0 :         if (valid < 0 || !valid)
     123           0 :                 return box;
     124           0 :         return isl_fixed_box_set_extent(box, pos, offset, size);
     125             : }
     126             : 
     127             : /* Replace "box" by an invalid box, by setting all offsets to NaN
     128             :  * (and all sizes to infinity).
     129             :  */
     130           0 : static __isl_give isl_fixed_box *isl_fixed_box_invalidate(
     131             :         __isl_take isl_fixed_box *box)
     132             : {
     133             :         int i, n;
     134             :         isl_space *space;
     135             :         isl_val *infty;
     136             :         isl_aff *nan;
     137             : 
     138           0 :         if (!box)
     139           0 :                 return NULL;
     140           0 :         n = isl_multi_val_dim(box->size, isl_dim_set);
     141             : 
     142           0 :         infty = isl_val_infty(isl_fixed_box_get_ctx(box));
     143           0 :         space = isl_space_domain(isl_fixed_box_get_space(box));
     144           0 :         nan = isl_aff_nan_on_domain(isl_local_space_from_space(space));
     145           0 :         for (i = 0; i < n; ++i)
     146           0 :                 box = isl_fixed_box_set_extent(box, i, nan, infty);
     147           0 :         isl_aff_free(nan);
     148           0 :         isl_val_free(infty);
     149             : 
     150           0 :         if (!box->offset || !box->size)
     151           0 :                 return isl_fixed_box_free(box);
     152           0 :         return box;
     153             : }
     154             : 
     155             : /* Return the isl_ctx to which "box" belongs.
     156             :  */
     157           0 : isl_ctx *isl_fixed_box_get_ctx(__isl_keep isl_fixed_box *box)
     158             : {
     159           0 :         if (!box)
     160           0 :                 return NULL;
     161           0 :         return isl_multi_aff_get_ctx(box->offset);
     162             : }
     163             : 
     164             : /* Return the space in which "box" lives.
     165             :  */
     166           0 : __isl_give isl_space *isl_fixed_box_get_space(__isl_keep isl_fixed_box *box)
     167             : {
     168           0 :         if (!box)
     169           0 :                 return NULL;
     170           0 :         return isl_multi_aff_get_space(box->offset);
     171             : }
     172             : 
     173             : /* Does "box" contain valid information?
     174             :  */
     175           0 : isl_bool isl_fixed_box_is_valid(__isl_keep isl_fixed_box *box)
     176             : {
     177           0 :         if (!box)
     178           0 :                 return isl_bool_error;
     179           0 :         return isl_bool_not(isl_multi_aff_involves_nan(box->offset));
     180             : }
     181             : 
     182             : /* Return the offsets of the box "box".
     183             :  */
     184           0 : __isl_give isl_multi_aff *isl_fixed_box_get_offset(
     185             :         __isl_keep isl_fixed_box *box)
     186             : {
     187           0 :         if (!box)
     188           0 :                 return NULL;
     189           0 :         return isl_multi_aff_copy(box->offset);
     190             : }
     191             : 
     192             : /* Return the sizes of the box "box".
     193             :  */
     194           0 : __isl_give isl_multi_val *isl_fixed_box_get_size(__isl_keep isl_fixed_box *box)
     195             : {
     196           0 :         if (!box)
     197           0 :                 return NULL;
     198           0 :         return isl_multi_val_copy(box->size);
     199             : }
     200             : 
     201             : /* Data used in set_dim_extent and compute_size_in_direction.
     202             :  *
     203             :  * "bset" is a wrapped copy of the basic map that has the selected
     204             :  * output dimension as range.
     205             :  * "pos" is the position of the variable representing the output dimension,
     206             :  * i.e., the variable for which the size should be computed.  This variable
     207             :  * is also the last variable in "bset".
     208             :  * "size" is the best size found so far
     209             :  * (infinity if no offset was found so far).
     210             :  * "offset" is the offset corresponding to the best size
     211             :  * (NULL if no offset was found so far).
     212             :  */
     213             : struct isl_size_info {
     214             :         isl_basic_set *bset;
     215             :         int pos;
     216             :         isl_val *size;
     217             :         isl_aff *offset;
     218             : };
     219             : 
     220             : /* Is "c" a suitable bound on dimension "pos" for use as a lower bound
     221             :  * of a fixed-size range.
     222             :  * In particular, it needs to be a lower bound on "pos".
     223             :  * In order for the final offset not to be too complicated,
     224             :  * the constraint itself should also not involve any integer divisions.
     225             :  */
     226           0 : static isl_bool is_suitable_bound(__isl_keep isl_constraint *c, unsigned pos)
     227             : {
     228             :         unsigned n_div;
     229             :         isl_bool is_bound, any_divs;
     230             : 
     231           0 :         is_bound = isl_constraint_is_lower_bound(c, isl_dim_set, pos);
     232           0 :         if (is_bound < 0 || !is_bound)
     233           0 :                 return is_bound;
     234             : 
     235           0 :         n_div = isl_constraint_dim(c, isl_dim_div);
     236           0 :         any_divs = isl_constraint_involves_dims(c, isl_dim_div, 0, n_div);
     237           0 :         return isl_bool_not(any_divs);
     238             : }
     239             : 
     240             : /* Given a constraint from the basic set describing the bounds on
     241             :  * an array index, check if it is a lower bound, say m i >= b(x), and,
     242             :  * if so, check whether the expression "i - ceil(b(x)/m) + 1" has a constant
     243             :  * upper bound.  If so, and if this bound is smaller than any bound
     244             :  * derived from earlier constraints, set the size to this bound on
     245             :  * the expression and the lower bound to ceil(b(x)/m).
     246             :  */
     247           0 : static isl_stat compute_size_in_direction(__isl_take isl_constraint *c,
     248             :         void *user)
     249             : {
     250           0 :         struct isl_size_info *info = user;
     251             :         isl_val *v;
     252             :         isl_aff *aff;
     253             :         isl_aff *lb;
     254             :         isl_bool is_bound, better;
     255             : 
     256           0 :         is_bound = is_suitable_bound(c, info->pos);
     257           0 :         if (is_bound < 0 || !is_bound) {
     258           0 :                 isl_constraint_free(c);
     259           0 :                 return is_bound < 0 ? isl_stat_error : isl_stat_ok;
     260             :         }
     261             : 
     262           0 :         aff = isl_constraint_get_bound(c, isl_dim_set, info->pos);
     263           0 :         aff = isl_aff_ceil(aff);
     264             : 
     265           0 :         lb = isl_aff_copy(aff);
     266             : 
     267           0 :         aff = isl_aff_neg(aff);
     268           0 :         aff = isl_aff_add_coefficient_si(aff, isl_dim_in, info->pos, 1);
     269             : 
     270           0 :         v = isl_basic_set_max_val(info->bset, aff);
     271           0 :         isl_aff_free(aff);
     272             : 
     273           0 :         v = isl_val_add_ui(v, 1);
     274           0 :         better = isl_val_lt(v, info->size);
     275           0 :         if (better >= 0 && better) {
     276           0 :                 isl_val_free(info->size);
     277           0 :                 info->size = isl_val_copy(v);
     278           0 :                 lb = isl_aff_domain_factor_domain(lb);
     279           0 :                 isl_aff_free(info->offset);
     280           0 :                 info->offset = isl_aff_copy(lb);
     281             :         }
     282           0 :         isl_val_free(v);
     283           0 :         isl_aff_free(lb);
     284             : 
     285           0 :         isl_constraint_free(c);
     286             : 
     287           0 :         return better < 0 ? isl_stat_error : isl_stat_ok;
     288             : }
     289             : 
     290             : /* Look for a fixed-size range of values for the output dimension "pos"
     291             :  * of "map", by looking for a lower-bound expression in the parameters
     292             :  * and input dimensions such that the range of the output dimension
     293             :  * is a constant shifted by this expression.
     294             :  *
     295             :  * In particular, look through the explicit lower bounds on the output dimension
     296             :  * for candidate expressions and pick the one that results in the smallest size.
     297             :  * Initialize the size with infinity and if no better size is found
     298             :  * then invalidate the box.  Otherwise, set the offset and size
     299             :  * in the given direction by those that correspond to the smallest size.
     300             :  */
     301           0 : static __isl_give isl_fixed_box *set_dim_extent(__isl_take isl_fixed_box *box,
     302             :         __isl_keep isl_map *map, int pos)
     303             : {
     304             :         struct isl_size_info info;
     305             :         isl_bool valid;
     306             :         isl_ctx *ctx;
     307             : 
     308           0 :         if (!box || !map)
     309           0 :                 return isl_fixed_box_free(box);
     310             : 
     311           0 :         ctx = isl_map_get_ctx(map);
     312           0 :         map = isl_map_copy(map);
     313           0 :         map = isl_map_project_onto(map, isl_dim_out, pos, 1);
     314           0 :         map = isl_map_compute_divs(map);
     315           0 :         info.size = isl_val_infty(ctx);
     316           0 :         info.offset = NULL;
     317           0 :         info.pos = isl_map_dim(map, isl_dim_in);
     318           0 :         info.bset = isl_basic_map_wrap(isl_map_simple_hull(map));
     319           0 :         if (isl_basic_set_foreach_constraint(info.bset,
     320             :                                         &compute_size_in_direction, &info) < 0)
     321           0 :                 box = isl_fixed_box_free(box);
     322           0 :         valid = isl_val_is_int(info.size);
     323           0 :         if (valid < 0)
     324           0 :                 box = isl_fixed_box_free(box);
     325           0 :         else if (valid)
     326           0 :                 box = isl_fixed_box_set_valid_extent(box, pos,
     327             :                                                      info.offset, info.size);
     328             :         else
     329           0 :                 box = isl_fixed_box_invalidate(box);
     330           0 :         isl_val_free(info.size);
     331           0 :         isl_aff_free(info.offset);
     332           0 :         isl_basic_set_free(info.bset);
     333             : 
     334           0 :         return box;
     335             : }
     336             : 
     337             : /* Try and construct a fixed-size rectangular box with an offset
     338             :  * in terms of the domain of "map" that contains the range of "map".
     339             :  * If no such box can be constructed, then return an invalidated box,
     340             :  * i.e., one where isl_fixed_box_is_valid returns false.
     341             :  *
     342             :  * Iterate over the dimensions in the range
     343             :  * setting the corresponding offset and extent.
     344             :  */
     345           0 : __isl_give isl_fixed_box *isl_map_get_range_simple_fixed_box_hull(
     346             :         __isl_keep isl_map *map)
     347             : {
     348             :         int i, n;
     349             :         isl_space *space;
     350             :         isl_fixed_box *box;
     351             : 
     352           0 :         n = isl_map_dim(map, isl_dim_out);
     353           0 :         space = isl_map_get_space(map);
     354           0 :         box = isl_fixed_box_init(space);
     355             : 
     356           0 :         map = isl_map_detect_equalities(isl_map_copy(map));
     357           0 :         for (i = 0; i < n; ++i) {
     358             :                 isl_bool valid;
     359             : 
     360           0 :                 box = set_dim_extent(box, map, i);
     361           0 :                 valid = isl_fixed_box_is_valid(box);
     362           0 :                 if (valid < 0 || !valid)
     363             :                         break;
     364             :         }
     365           0 :         isl_map_free(map);
     366             : 
     367           0 :         return box;
     368             : }

Generated by: LCOV version 1.12