|
|
|||
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 */
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|