Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:48:20

0001 //===------ ISLTools.h ------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // Tools, utilities, helpers and extensions useful in conjunction with the
0010 // Integer Set Library (isl).
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef POLLY_ISLTOOLS_H
0015 #define POLLY_ISLTOOLS_H
0016 
0017 #include "llvm/ADT/Sequence.h"
0018 #include "llvm/ADT/iterator.h"
0019 #include "isl/isl-noexceptions.h"
0020 #include <algorithm>
0021 #include <cassert>
0022 
0023 /// In debug builds assert that the @p Size is valid, in non-debug builds
0024 /// disable the mandatory state checking but do not enforce the error checking.
0025 inline void islAssert(const isl::size &Size) {
0026 #ifdef NDEBUG
0027   // Calling is_error() marks that the error status has been checked which
0028   // disables the error-status-not-checked errors that would otherwise occur
0029   // when using the value.
0030   (void)Size.is_error();
0031 #else
0032   // Assert on error in debug builds.
0033   assert(!Size.is_error());
0034 #endif
0035 }
0036 
0037 /// Check that @p Size is valid (only on debug builds) and cast it to unsigned.
0038 /// Cast the @p Size to unsigned. If the @p Size is not valid (Size.is_error()
0039 /// == true) then an assert and an abort are triggered.
0040 inline unsigned unsignedFromIslSize(const isl::size &Size) {
0041   islAssert(Size);
0042   return static_cast<unsigned>(Size);
0043 }
0044 
0045 namespace isl {
0046 inline namespace noexceptions {
0047 
0048 template <typename ListT>
0049 using list_element_type = decltype(std::declval<ListT>().get_at(0));
0050 
0051 template <typename ListT>
0052 class isl_iterator
0053     : public llvm::iterator_facade_base<isl_iterator<ListT>,
0054                                         std::forward_iterator_tag,
0055                                         list_element_type<ListT>> {
0056 public:
0057   using ElementT = list_element_type<ListT>;
0058 
0059   explicit isl_iterator(const ListT &List)
0060       : List(&List), Position(std::max(List.size().release(), 0)) {}
0061   isl_iterator(const ListT &List, int Position)
0062       : List(&List), Position(Position) {}
0063 
0064   bool operator==(const isl_iterator &O) const {
0065     return List == O.List && Position == O.Position;
0066   }
0067 
0068   isl_iterator &operator++() {
0069     ++Position;
0070     return *this;
0071   }
0072 
0073   isl_iterator operator++(int) {
0074     isl_iterator Copy{*this};
0075     ++Position;
0076     return Copy;
0077   }
0078 
0079   ElementT operator*() const { return List->get_at(this->Position); }
0080 
0081 protected:
0082   const ListT *List;
0083   int Position = 0;
0084 };
0085 
0086 template <typename T> isl_iterator<T> begin(const T &t) {
0087   return isl_iterator<T>(t, 0);
0088 }
0089 template <typename T> isl_iterator<T> end(const T &t) {
0090   return isl_iterator<T>(t);
0091 }
0092 
0093 } // namespace noexceptions
0094 } // namespace isl
0095 
0096 namespace polly {
0097 
0098 /// Return the range elements that are lexicographically smaller.
0099 ///
0100 /// @param Map    { Space[] -> Scatter[] }
0101 /// @param Strict True for strictly lexicographically smaller elements (exclude
0102 ///               same timepoints from the result).
0103 ///
0104 /// @return { Space[] -> Scatter[] }
0105 ///         A map to all timepoints that happen before the timepoints the input
0106 ///         mapped to.
0107 isl::map beforeScatter(isl::map Map, bool Strict);
0108 
0109 /// Piecewise beforeScatter(isl::map,bool).
0110 isl::union_map beforeScatter(isl::union_map UMap, bool Strict);
0111 
0112 /// Return the range elements that are lexicographically larger.
0113 ///
0114 /// @param Map    { Space[] -> Scatter[] }
0115 /// @param Strict True for strictly lexicographically larger elements (exclude
0116 ///               same timepoints from the result).
0117 ///
0118 /// @return { Space[] -> Scatter[] }
0119 ///         A map to all timepoints that happen after the timepoints the input
0120 ///         map originally mapped to.
0121 isl::map afterScatter(isl::map Map, bool Strict);
0122 
0123 /// Piecewise afterScatter(isl::map,bool).
0124 isl::union_map afterScatter(const isl::union_map &UMap, bool Strict);
0125 
0126 /// Construct a range of timepoints between two timepoints.
0127 ///
0128 /// Example:
0129 /// From := { A[] -> [0]; B[] -> [0] }
0130 /// To   := {             B[] -> [10]; C[] -> [20] }
0131 ///
0132 /// Result:
0133 /// { B[] -> [i] : 0 < i < 10 }
0134 ///
0135 /// Note that A[] and C[] are not in the result because they do not have a start
0136 /// or end timepoint. If a start (or end) timepoint is not unique, the first
0137 /// (respectively last) is chosen.
0138 ///
0139 /// @param From     { Space[] -> Scatter[] }
0140 ///                 Map to start timepoints.
0141 /// @param To       { Space[] -> Scatter[] }
0142 ///                 Map to end timepoints.
0143 /// @param InclFrom Whether to include the start timepoints in the result. In
0144 ///                 the example, this would add { B[] -> [0] }
0145 /// @param InclTo   Whether to include the end timepoints in the result. In this
0146 ///                 example, this would add { B[] -> [10] }
0147 ///
0148 /// @return { Space[] -> Scatter[] }
0149 ///         A map for each domain element of timepoints between two extreme
0150 ///         points, or nullptr if @p From or @p To is nullptr, or the isl max
0151 ///         operations is exceeded.
0152 isl::map betweenScatter(isl::map From, isl::map To, bool InclFrom, bool InclTo);
0153 
0154 /// Piecewise betweenScatter(isl::map,isl::map,bool,bool).
0155 isl::union_map betweenScatter(isl::union_map From, isl::union_map To,
0156                               bool InclFrom, bool InclTo);
0157 
0158 /// If by construction a union map is known to contain only a single map, return
0159 /// it.
0160 ///
0161 /// This function combines isl_map_from_union_map() and
0162 /// isl_union_map_extract_map(). isl_map_from_union_map() fails if the map is
0163 /// empty because it does not know which space it would be in.
0164 /// isl_union_map_extract_map() on the other hand does not check whether there
0165 /// is (at most) one isl_map in the union, i.e. how it has been constructed is
0166 /// probably wrong.
0167 isl::map singleton(isl::union_map UMap, isl::space ExpectedSpace);
0168 
0169 /// If by construction an isl_union_set is known to contain only a single
0170 /// isl_set, return it.
0171 ///
0172 /// This function combines isl_set_from_union_set() and
0173 /// isl_union_set_extract_set(). isl_map_from_union_set() fails if the set is
0174 /// empty because it does not know which space it would be in.
0175 /// isl_union_set_extract_set() on the other hand does not check whether there
0176 /// is (at most) one isl_set in the union, i.e. how it has been constructed is
0177 /// probably wrong.
0178 isl::set singleton(isl::union_set USet, isl::space ExpectedSpace);
0179 
0180 /// Determine how many dimensions the scatter space of @p Schedule has.
0181 ///
0182 /// The schedule must not be empty and have equal number of dimensions of any
0183 /// subspace it contains.
0184 ///
0185 /// The implementation currently returns the maximum number of dimensions it
0186 /// encounters, if different, and 0 if none is encountered. However, most other
0187 /// code will most likely fail if one of these happen.
0188 unsigned getNumScatterDims(const isl::union_map &Schedule);
0189 
0190 /// Return the scatter space of a @p Schedule.
0191 ///
0192 /// This is basically the range space of the schedule map, but harder to
0193 /// determine because it is an isl_union_map.
0194 isl::space getScatterSpace(const isl::union_map &Schedule);
0195 
0196 /// Construct an identity map for the given domain values.
0197 ///
0198 /// @param USet           { Space[] }
0199 ///                       The returned map's domain and range.
0200 /// @param RestrictDomain If true, the returned map only maps elements contained
0201 ///                       in @p Set and no other. If false, it returns an
0202 ///                       overapproximation with the identity maps of any space
0203 ///                       in @p Set, not just the elements in it.
0204 ///
0205 /// @return { Space[] -> Space[] }
0206 ///         A map that maps each value of @p Set to itself.
0207 isl::map makeIdentityMap(const isl::set &Set, bool RestrictDomain);
0208 
0209 /// Construct an identity map for the given domain values.
0210 ///
0211 /// There is no type resembling isl_union_space, hence we have to pass an
0212 /// isl_union_set as the map's domain and range space.
0213 ///
0214 /// @param USet           { Space[] }
0215 ///                       The returned map's domain and range.
0216 /// @param RestrictDomain If true, the returned map only maps elements contained
0217 ///                       in @p USet and no other. If false, it returns an
0218 ///                       overapproximation with the identity maps of any space
0219 ///                       in @p USet, not just the elements in it.
0220 ///
0221 /// @return { Space[] -> Space[] }
0222 ///         A map that maps each value of @p USet to itself.
0223 isl::union_map makeIdentityMap(const isl::union_set &USet, bool RestrictDomain);
0224 
0225 /// Reverse the nested map tuple in @p Map's domain.
0226 ///
0227 /// @param Map { [Space1[] -> Space2[]] -> Space3[] }
0228 ///
0229 /// @return { [Space2[] -> Space1[]] -> Space3[] }
0230 isl::map reverseDomain(isl::map Map);
0231 
0232 /// Piecewise reverseDomain(isl::map).
0233 isl::union_map reverseDomain(const isl::union_map &UMap);
0234 
0235 /// Add a constant to one dimension of a set.
0236 ///
0237 /// @param Map    The set to shift a dimension in.
0238 /// @param Pos    The dimension to shift. If negative, the dimensions are
0239 ///               counted from the end instead from the beginning. E.g. -1 is
0240 ///               the last dimension in the tuple.
0241 /// @param Amount The offset to add to the specified dimension.
0242 ///
0243 /// @return The modified set.
0244 isl::set shiftDim(isl::set Set, int Pos, int Amount);
0245 
0246 /// Piecewise shiftDim(isl::set,int,int).
0247 isl::union_set shiftDim(isl::union_set USet, int Pos, int Amount);
0248 
0249 /// Add a constant to one dimension of a map.
0250 ///
0251 /// @param Map    The map to shift a dimension in.
0252 /// @param Type   A tuple of @p Map which contains the dimension to shift.
0253 /// @param Pos    The dimension to shift. If negative, the dimensions are
0254 /// counted from the end instead from the beginning. Eg. -1 is the last
0255 /// dimension in the tuple.
0256 /// @param Amount The offset to add to the specified dimension.
0257 ///
0258 /// @return The modified map.
0259 isl::map shiftDim(isl::map Map, isl::dim Dim, int Pos, int Amount);
0260 
0261 /// Add a constant to one dimension of a each map in a union map.
0262 ///
0263 /// @param UMap   The maps to shift a dimension in.
0264 /// @param Type   The tuple which contains the dimension to shift.
0265 /// @param Pos    The dimension to shift. If negative, the dimensions are
0266 ///               counted from the ends of each map of union instead from their
0267 ///               beginning. E.g. -1 is the last dimension of any map.
0268 /// @param Amount The offset to add to the specified dimension.
0269 ///
0270 /// @return The union of all modified maps.
0271 isl::union_map shiftDim(isl::union_map UMap, isl::dim Dim, int Pos, int Amount);
0272 
0273 /// Simplify a set inplace.
0274 void simplify(isl::set &Set);
0275 
0276 /// Simplify a union set inplace.
0277 void simplify(isl::union_set &USet);
0278 
0279 /// Simplify a map inplace.
0280 void simplify(isl::map &Map);
0281 
0282 /// Simplify a union map inplace.
0283 void simplify(isl::union_map &UMap);
0284 
0285 /// Compute the reaching definition statement or the next overwrite for each
0286 /// definition of an array element.
0287 ///
0288 /// The reaching definition of an array element at a specific timepoint is the
0289 /// statement instance that has written the current element's content.
0290 /// Alternatively, this function determines for each timepoint and element which
0291 /// write is going to overwrite an element at a future timepoint. This can be
0292 /// seen as "reaching definition in reverse" where definitions are found in the
0293 /// past.
0294 ///
0295 /// For example:
0296 ///
0297 /// Schedule := { Write[] -> [0]; Overwrite[] -> [10] }
0298 /// Defs := { Write[] -> A[5]; Overwrite[] -> A[5] }
0299 ///
0300 /// If index 5 of array A is written at timepoint 0 and 10, the resulting
0301 /// reaching definitions are:
0302 ///
0303 /// { [A[5] -> [i]] -> Write[] : 0 < i < 10;
0304 ///   [A[5] -> [i]] -> Overwrite[] : 10 < i }
0305 ///
0306 /// Between timepoint 0 (Write[]) and timepoint 10 (Overwrite[]), the
0307 /// content of A[5] is written by statement instance Write[] and after
0308 /// timepoint 10 by Overwrite[]. Values not defined in the map have no known
0309 /// definition. This includes the statement instance timepoints themselves,
0310 /// because reads at those timepoints could either read the old or the new
0311 /// value, defined only by the statement itself. But this can be changed by @p
0312 /// InclPrevDef and @p InclNextDef. InclPrevDef=false and InclNextDef=true
0313 /// returns a zone. Unless @p InclPrevDef and @p InclNextDef are both true,
0314 /// there is only one unique definition per element and timepoint.
0315 ///
0316 /// @param Schedule    { DomainWrite[] -> Scatter[] }
0317 ///                    Schedule of (at least) all array writes. Instances not in
0318 ///                    @p Writes are ignored.
0319 /// @param Writes      { DomainWrite[] -> Element[] }
0320 ///                    Elements written to by the statement instances.
0321 /// @param Reverse     If true, look for definitions in the future. That is,
0322 ///                    find the write that is overwrites the current value.
0323 /// @param InclPrevDef Include the definition's timepoint to the set of
0324 ///                    well-defined elements (any load at that timepoint happen
0325 ///                    at the writes). In the example, enabling this option adds
0326 ///                    {[A[5] -> [0]] -> Write[]; [A[5] -> [10]] -> Overwrite[]}
0327 ///                    to the result.
0328 /// @param InclNextDef Whether to assume that at the timepoint where an element
0329 ///                    is overwritten, it still contains the old value (any load
0330 ///                    at that timepoint would happen before the overwrite). In
0331 ///                    this example, enabling this adds
0332 ///                    { [A[] -> [10]] -> Write[] } to the result.
0333 ///
0334 /// @return { [Element[] -> Scatter[]] -> DomainWrite[] }
0335 ///         The reaching definitions or future overwrite as described above, or
0336 ///         nullptr if either @p Schedule or @p Writes is nullptr, or the isl
0337 ///         max operations count has exceeded.
0338 isl::union_map computeReachingWrite(isl::union_map Schedule,
0339                                     isl::union_map Writes, bool Reverse,
0340                                     bool InclPrevDef, bool InclNextDef);
0341 
0342 /// Compute the timepoints where the contents of an array element are not used.
0343 ///
0344 /// An element is unused at a timepoint when the element is overwritten in
0345 /// the future, but it is not read in between. Another way to express this: the
0346 /// time from when the element is written, to the most recent read before it, or
0347 /// infinitely into the past if there is no read before. Such unused elements
0348 /// can be overwritten by any value without changing the scop's semantics. An
0349 /// example:
0350 ///
0351 /// Schedule := { Read[] -> [0]; Write[] -> [10]; Def[] -> [20] }
0352 /// Writes := { Write[] -> A[5]; Def[] -> A[6] }
0353 /// Reads := { Read[] -> A[5] }
0354 ///
0355 /// The result is:
0356 ///
0357 /// { A[5] -> [i] : 0 < i < 10;
0358 ///   A[6] -> [i] : i < 20 }
0359 ///
0360 /// That is, A[5] is unused between timepoint 0 (the read) and timepoint 10 (the
0361 /// write). A[6] is unused before timepoint 20, but might be used after the
0362 /// scop's execution (A[5] and any other A[i] as well). Use InclLastRead=false
0363 /// and InclWrite=true to interpret the result as zone.
0364 ///
0365 /// @param Schedule          { Domain[] -> Scatter[] }
0366 ///                          The schedule of (at least) all statement instances
0367 ///                          occurring in @p Writes or @p Reads. All other
0368 ///                          instances are ignored.
0369 /// @param Writes            { DomainWrite[] -> Element[] }
0370 ///                          Elements written to by the statement instances.
0371 /// @param Reads             { DomainRead[] -> Element[] }
0372 ///                          Elements read from by the statement instances.
0373 /// @param ReadEltInSameInst Whether a load reads the value from a write
0374 ///                          that is scheduled at the same timepoint (Writes
0375 ///                          happen before reads). Otherwise, loads use the
0376 ///                          value of an element that it had before the
0377 ///                          timepoint (Reads before writes). For example:
0378 ///                          { Read[] -> [0]; Write[] -> [0] }
0379 ///                          With ReadEltInSameInst=false it is assumed that the
0380 ///                          read happens before the write, such that the
0381 ///                          element is never unused, or just at timepoint 0,
0382 ///                          depending on InclLastRead/InclWrite.
0383 ///                          With ReadEltInSameInst=false it assumes that the
0384 ///                          value just written is used. Anything before
0385 ///                          timepoint 0 is considered unused.
0386 /// @param InclLastRead      Whether a timepoint where an element is last read
0387 ///                          counts as unused (the read happens at the beginning
0388 ///                          of its timepoint, and nothing (else) can use it
0389 ///                          during the timepoint). In the example, this option
0390 ///                          adds { A[5] -> [0] } to the result.
0391 /// @param InclWrite         Whether the timepoint where an element is written
0392 ///                          itself counts as unused (the write happens at the
0393 ///                          end of its timepoint; no (other) operations uses
0394 ///                          the element during the timepoint). In this example,
0395 ///                          this adds
0396 ///                          { A[5] -> [10]; A[6] -> [20] } to the result.
0397 ///
0398 /// @return { Element[] -> Scatter[] }
0399 ///         The unused timepoints as defined above, or nullptr if either @p
0400 ///         Schedule, @p Writes are @p Reads is nullptr, or the ISL max
0401 ///         operations count is exceeded.
0402 isl::union_map computeArrayUnused(isl::union_map Schedule,
0403                                   isl::union_map Writes, isl::union_map Reads,
0404                                   bool ReadEltInSameInst, bool InclLastRead,
0405                                   bool InclWrite);
0406 
0407 /// Convert a zone (range between timepoints) to timepoints.
0408 ///
0409 /// A zone represents the time between (integer) timepoints, but not the
0410 /// timepoints themselves. This function can be used to determine whether a
0411 /// timepoint lies within a zone.
0412 ///
0413 /// For instance, the range (1,3), representing the time between 1 and 3, is
0414 /// represented by the zone
0415 ///
0416 /// { [i] : 1 < i <= 3 }
0417 ///
0418 /// The set of timepoints that lie completely within this range is
0419 ///
0420 /// { [i] : 1 < i < 3 }
0421 ///
0422 /// A typical use-case is the range in which a value written by a store is
0423 /// available until it is overwritten by another value. If the write is at
0424 /// timepoint 1 and its value is overwritten by another value at timepoint 3,
0425 /// the value is available between those timepoints: timepoint 2 in this
0426 /// example.
0427 ///
0428 ///
0429 /// When InclStart is true, the range is interpreted left-inclusive, i.e. adds
0430 /// the timepoint 1 to the result:
0431 ///
0432 /// { [i] : 1 <= i < 3 }
0433 ///
0434 /// In the use-case mentioned above that means that the value written at
0435 /// timepoint 1 is already available in timepoint 1 (write takes place before
0436 /// any read of it even if executed at the same timepoint)
0437 ///
0438 /// When InclEnd is true, the range is interpreted right-inclusive, i.e. adds
0439 /// the timepoint 3 to the result:
0440 ///
0441 /// { [i] : 1 < i <= 3 }
0442 ///
0443 /// In the use-case mentioned above that means that although the value is
0444 /// overwritten in timepoint 3, the old value is still available at timepoint 3
0445 /// (write takes place after any read even if executed at the same timepoint)
0446 ///
0447 /// @param Zone      { Zone[] }
0448 /// @param InclStart Include timepoints adjacent to the beginning of a zone.
0449 /// @param InclEnd   Include timepoints adjacent to the ending of a zone.
0450 ///
0451 /// @return { Scatter[] }
0452 isl::union_set convertZoneToTimepoints(isl::union_set Zone, bool InclStart,
0453                                        bool InclEnd);
0454 
0455 /// Like convertZoneToTimepoints(isl::union_set,InclStart,InclEnd), but convert
0456 /// either the domain or the range of a map.
0457 isl::union_map convertZoneToTimepoints(isl::union_map Zone, isl::dim Dim,
0458                                        bool InclStart, bool InclEnd);
0459 
0460 /// Overload of convertZoneToTimepoints(isl::map,InclStart,InclEnd) to process
0461 /// only a single map.
0462 isl::map convertZoneToTimepoints(isl::map Zone, isl::dim Dim, bool InclStart,
0463                                  bool InclEnd);
0464 
0465 /// Distribute the domain to the tuples of a wrapped range map.
0466 ///
0467 /// @param Map { Domain[] -> [Range1[] -> Range2[]] }
0468 ///
0469 /// @return { [Domain[] -> Range1[]] -> [Domain[] -> Range2[]] }
0470 isl::map distributeDomain(isl::map Map);
0471 
0472 /// Apply distributeDomain(isl::map) to each map in the union.
0473 isl::union_map distributeDomain(isl::union_map UMap);
0474 
0475 /// Prepend a space to the tuples of a map.
0476 ///
0477 /// @param UMap   { Domain[] -> Range[] }
0478 /// @param Factor { Factor[] }
0479 ///
0480 /// @return { [Factor[] -> Domain[]] -> [Factor[] -> Range[]] }
0481 isl::union_map liftDomains(isl::union_map UMap, isl::union_set Factor);
0482 
0483 /// Apply a map to the 'middle' of another relation.
0484 ///
0485 /// @param UMap { [DomainDomain[] -> DomainRange[]] -> Range[] }
0486 /// @param Func { DomainRange[] -> NewDomainRange[] }
0487 ///
0488 /// @return { [DomainDomain[] -> NewDomainRange[]] -> Range[] }
0489 isl::union_map applyDomainRange(isl::union_map UMap, isl::union_map Func);
0490 
0491 /// Intersect the range of @p Map with @p Range.
0492 ///
0493 /// Since @p Map is an isl::map, the result will be a single space, even though
0494 /// @p Range is an isl::union_set. This is the only difference to
0495 /// isl::map::intersect_range and isl::union_map::interset_range.
0496 ///
0497 /// @param Map   { Domain[] -> Range[] }
0498 /// @param Range { Range[] }
0499 ///
0500 /// @return { Domain[] -> Range[] }
0501 isl::map intersectRange(isl::map Map, isl::union_set Range);
0502 
0503 /// Subtract the parameter space @p Params from @p Map.
0504 /// This is akin to isl::map::intersect_params.
0505 ///
0506 /// Example:
0507 ///   subtractParams(
0508 ///     { [i] -> [i] },
0509 ///     [x] -> { : x < 0 }
0510 ///   ) = [x] -> { [i] -> [i] : x >= 0 }
0511 ///
0512 /// @param Map    Remove the conditions of @p Params from this map.
0513 /// @param Params Parameter set to subtract.
0514 ///
0515 /// @param The map with the parameter conditions removed.
0516 isl::map subtractParams(isl::map Map, isl::set Params);
0517 
0518 /// Subtract the parameter space @p Params from @p Set.
0519 isl::set subtractParams(isl::set Set, isl::set Params);
0520 
0521 /// If @p PwAff maps to a constant, return said constant. If @p Max/@p Min, it
0522 /// can also be a piecewise constant and it would return the minimum/maximum
0523 /// value. Otherwise, return NaN.
0524 isl::val getConstant(isl::pw_aff PwAff, bool Max, bool Min);
0525 
0526 /// If the relation @p PwAff lies on a hyperplane where the given
0527 /// dimension @p Pos with the type @p Dim has a fixed value, then
0528 /// return that value. Otherwise return NaN.
0529 isl::val getConstant(isl::map Map, isl::dim Dim, int Pos);
0530 
0531 /// Check that @p End is valid and return an iterator from @p Begin to @p End
0532 ///
0533 /// Use case example:
0534 ///   for (unsigned i : rangeIslSize(0, Map.domain_tuple_dim()))
0535 ///     // do stuff
0536 llvm::iota_range<unsigned> rangeIslSize(unsigned Begin, isl::size End);
0537 
0538 /// Dump a description of the argument to llvm::errs().
0539 ///
0540 /// In contrast to isl's dump function, there are a few differences:
0541 /// - Each polyhedron (pieces) is written on its own line.
0542 /// - Spaces are sorted by structure. E.g. maps with same domain space are
0543 ///   grouped. Isl sorts them according to the space's hash function.
0544 /// - Pieces of the same space are sorted using their lower bound.
0545 /// - A more compact to_str representation is used instead of Isl's dump
0546 ///   functions that try to show the internal representation.
0547 ///
0548 /// The goal is to get a better understandable representation that is also
0549 /// useful to compare two sets. As all dump() functions, its intended use is to
0550 /// be called in a debugger only.
0551 ///
0552 /// isl_map_dump example:
0553 /// [p_0, p_1, p_2] -> { Stmt0[i0] -> [o0, o1] : (o0 = i0 and o1 = 0 and i0 > 0
0554 /// and i0 <= 5 - p_2) or (i0 = 0 and o0 = 0 and o1 = 0); Stmt3[i0] -> [o0, o1]
0555 /// : (o0 = i0 and o1 = 3 and i0 > 0 and i0 <= 5 - p_2) or (i0 = 0 and o0 = 0
0556 /// and o1 = 3); Stmt2[i0] -> [o0, o1] : (o0 = i0 and o1 = 1 and i0 >= 3 + p_0 -
0557 /// p_1 and i0 > 0 and i0 <= 5 - p_2) or (o0 = i0 and o1 = 1 and i0 > 0 and i0
0558 /// <= 5 - p_2 and i0 < p_0 - p_1) or (i0 = 0 and o0 = 0 and o1 = 1 and p_1 >= 3
0559 /// + p_0) or (i0 = 0 and o0 = 0 and o1 = 1 and p_1 < p_0) or (p_0 = 0 and i0 =
0560 /// 2 - p_1 and o0 = 2 - p_1 and o1 = 1 and p_2 <= 3 + p_1 and p_1 <= 1) or (p_1
0561 /// = 1 + p_0 and i0 = 0 and o0 = 0 and o1 = 1) or (p_0 = 0 and p_1 = 2 and i0 =
0562 /// 0 and o0 = 0 and o1 = 1) or (p_0 = -1 and p_1 = -1 and i0 = 0 and o0 = 0 and
0563 /// o1 = 1); Stmt1[i0] -> [o0, o1] : (p_0 = -1 and i0 = 1 - p_1 and o0 = 1 - p_1
0564 /// and o1 = 2 and p_2 <= 4 + p_1 and p_1 <= 0) or (p_0 = 0 and i0 = -p_1 and o0
0565 /// = -p_1 and o1 = 2 and p_2 <= 5 + p_1 and p_1 < 0) or (p_0 = -1 and p_1 = 1
0566 /// and i0 = 0 and o0 = 0 and o1 = 2) or (p_0 = 0 and p_1 = 0 and i0 = 0 and o0
0567 /// = 0 and o1 = 2) }
0568 ///
0569 /// dumpPw example (same set):
0570 /// [p_0, p_1, p_2] -> {
0571 ///   Stmt0[0] -> [0, 0];
0572 ///   Stmt0[i0] -> [i0, 0] : 0 < i0 <= 5 - p_2;
0573 ///   Stmt1[0] -> [0, 2] : p_1 = 1 and p_0 = -1;
0574 ///   Stmt1[0] -> [0, 2] : p_1 = 0 and p_0 = 0;
0575 ///   Stmt1[1 - p_1] -> [1 - p_1, 2] : p_0 = -1 and p_1 <= 0 and p_2 <= 4 + p_1;
0576 ///   Stmt1[-p_1] -> [-p_1, 2] : p_0 = 0 and p_1 < 0 and p_2 <= 5 + p_1;
0577 ///   Stmt2[0] -> [0, 1] : p_1 >= 3 + p_0;
0578 ///   Stmt2[0] -> [0, 1] : p_1 < p_0;
0579 ///   Stmt2[0] -> [0, 1] : p_1 = 1 + p_0;
0580 ///   Stmt2[0] -> [0, 1] : p_1 = 2 and p_0 = 0;
0581 ///   Stmt2[0] -> [0, 1] : p_1 = -1 and p_0 = -1;
0582 ///   Stmt2[i0] -> [i0, 1] : i0 >= 3 + p_0 - p_1 and 0 < i0 <= 5 - p_2;
0583 ///   Stmt2[i0] -> [i0, 1] : 0 < i0 <= 5 - p_2 and i0 < p_0 - p_1;
0584 ///   Stmt2[2 - p_1] -> [2 - p_1, 1] : p_0 = 0 and p_1 <= 1 and p_2 <= 3 + p_1;
0585 ///   Stmt3[0] -> [0, 3];
0586 ///   Stmt3[i0] -> [i0, 3] : 0 < i0 <= 5 - p_2
0587 /// }
0588 /// @{
0589 void dumpPw(const isl::set &Set);
0590 void dumpPw(const isl::map &Map);
0591 void dumpPw(const isl::union_set &USet);
0592 void dumpPw(const isl::union_map &UMap);
0593 void dumpPw(__isl_keep isl_set *Set);
0594 void dumpPw(__isl_keep isl_map *Map);
0595 void dumpPw(__isl_keep isl_union_set *USet);
0596 void dumpPw(__isl_keep isl_union_map *UMap);
0597 /// @}
0598 
0599 /// Dump all points of the argument to llvm::errs().
0600 ///
0601 /// Before being printed by dumpPw(), the argument's pieces are expanded to
0602 /// contain only single points. If a dimension is unbounded, it keeps its
0603 /// representation.
0604 ///
0605 /// This is useful for debugging reduced cases where parameters are set to
0606 /// constants to keep the example simple. Such sets can still contain
0607 /// existential dimensions which makes the polyhedral hard to compare.
0608 ///
0609 /// Example:
0610 ///   { [MemRef_A[i0] -> [i1]] : (exists (e0 = floor((1 + i1)/3): i0 = 1 and 3e0
0611 ///   <= i1 and 3e0 >= -1 + i1 and i1 >= 15 and i1 <= 25)) or (exists (e0 =
0612 ///   floor((i1)/3): i0 = 0 and 3e0 < i1 and 3e0 >= -2 + i1 and i1 > 0 and i1 <=
0613 ///   11)) }
0614 ///
0615 /// dumpExpanded:
0616 /// {
0617 ///   [MemRef_A[0] ->[1]];
0618 ///   [MemRef_A[0] ->[2]];
0619 ///   [MemRef_A[0] ->[4]];
0620 ///   [MemRef_A[0] ->[5]];
0621 ///   [MemRef_A[0] ->[7]];
0622 ///   [MemRef_A[0] ->[8]];
0623 ///   [MemRef_A[0] ->[10]];
0624 ///   [MemRef_A[0] ->[11]];
0625 ///   [MemRef_A[1] ->[15]];
0626 ///   [MemRef_A[1] ->[16]];
0627 ///   [MemRef_A[1] ->[18]];
0628 ///   [MemRef_A[1] ->[19]];
0629 ///   [MemRef_A[1] ->[21]];
0630 ///   [MemRef_A[1] ->[22]];
0631 ///   [MemRef_A[1] ->[24]];
0632 ///   [MemRef_A[1] ->[25]]
0633 /// }
0634 /// @{
0635 void dumpExpanded(const isl::set &Set);
0636 void dumpExpanded(const isl::map &Map);
0637 void dumpExpanded(const isl::union_set &USet);
0638 void dumpExpanded(const isl::union_map &UMap);
0639 void dumpExpanded(__isl_keep isl_set *Set);
0640 void dumpExpanded(__isl_keep isl_map *Map);
0641 void dumpExpanded(__isl_keep isl_union_set *USet);
0642 void dumpExpanded(__isl_keep isl_union_map *UMap);
0643 /// @}
0644 } // namespace polly
0645 
0646 #endif /* POLLY_ISLTOOLS_H */