Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===------ ISLTools.h ------------------------------------------*- C++ -*-===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Tools, utilities, helpers and extensions useful in conjunction with the
10
// Integer Set Library (isl).
11
//
12
//===----------------------------------------------------------------------===//
13
 
14
#ifndef POLLY_ISLTOOLS_H
15
#define POLLY_ISLTOOLS_H
16
 
17
#include "llvm/ADT/Sequence.h"
18
#include "llvm/ADT/iterator.h"
19
#include "isl/isl-noexceptions.h"
20
#include <algorithm>
21
#include <cassert>
22
 
23
/// In debug builds assert that the @p Size is valid, in non-debug builds
24
/// disable the mandatory state checking but do not enforce the error checking.
25
inline void islAssert(const isl::size &Size) {
26
#ifdef NDEBUG
27
  // Calling is_error() marks that the error status has been checked which
28
  // disables the error-status-not-checked errors that would otherwise occur
29
  // when using the value.
30
  (void)Size.is_error();
31
#else
32
  // Assert on error in debug builds.
33
  assert(!Size.is_error());
34
#endif
35
}
36
 
37
/// Check that @p Size is valid (only on debug builds) and cast it to unsigned.
38
/// Cast the @p Size to unsigned. If the @p Size is not valid (Size.is_error()
39
/// == true) then an assert and an abort are triggered.
40
inline unsigned unsignedFromIslSize(const isl::size &Size) {
41
  islAssert(Size);
42
  return static_cast<unsigned>(Size);
43
}
44
 
45
namespace isl {
46
inline namespace noexceptions {
47
 
48
template <typename ListT>
49
using list_element_type = decltype(std::declval<ListT>().get_at(0));
50
 
51
template <typename ListT>
52
class isl_iterator
53
    : public llvm::iterator_facade_base<isl_iterator<ListT>,
54
                                        std::forward_iterator_tag,
55
                                        list_element_type<ListT>> {
56
public:
57
  using ElementT = list_element_type<ListT>;
58
 
59
  explicit isl_iterator(const ListT &List)
60
      : List(&List), Position(std::max(List.size().release(), 0)) {}
61
  isl_iterator(const ListT &List, int Position)
62
      : List(&List), Position(Position) {}
63
 
64
  bool operator==(const isl_iterator &O) const {
65
    return List == O.List && Position == O.Position;
66
  }
67
 
68
  isl_iterator &operator++() {
69
    ++Position;
70
    return *this;
71
  }
72
 
73
  isl_iterator operator++(int) {
74
    isl_iterator Copy{*this};
75
    ++Position;
76
    return Copy;
77
  }
78
 
79
  ElementT operator*() const { return List->get_at(this->Position); }
80
 
81
protected:
82
  const ListT *List;
83
  int Position = 0;
84
};
85
 
86
template <typename T> isl_iterator<T> begin(const T &t) {
87
  return isl_iterator<T>(t, 0);
88
}
89
template <typename T> isl_iterator<T> end(const T &t) {
90
  return isl_iterator<T>(t);
91
}
92
 
93
} // namespace noexceptions
94
} // namespace isl
95
 
96
namespace polly {
97
 
98
/// Return the range elements that are lexicographically smaller.
99
///
100
/// @param Map    { Space[] -> Scatter[] }
101
/// @param Strict True for strictly lexicographically smaller elements (exclude
102
///               same timepoints from the result).
103
///
104
/// @return { Space[] -> Scatter[] }
105
///         A map to all timepoints that happen before the timepoints the input
106
///         mapped to.
107
isl::map beforeScatter(isl::map Map, bool Strict);
108
 
109
/// Piecewise beforeScatter(isl::map,bool).
110
isl::union_map beforeScatter(isl::union_map UMap, bool Strict);
111
 
112
/// Return the range elements that are lexicographically larger.
113
///
114
/// @param Map    { Space[] -> Scatter[] }
115
/// @param Strict True for strictly lexicographically larger elements (exclude
116
///               same timepoints from the result).
117
///
118
/// @return { Space[] -> Scatter[] }
119
///         A map to all timepoints that happen after the timepoints the input
120
///         map originally mapped to.
121
isl::map afterScatter(isl::map Map, bool Strict);
122
 
123
/// Piecewise afterScatter(isl::map,bool).
124
isl::union_map afterScatter(const isl::union_map &UMap, bool Strict);
125
 
126
/// Construct a range of timepoints between two timepoints.
127
///
128
/// Example:
129
/// From := { A[] -> [0]; B[] -> [0] }
130
/// To   := {             B[] -> [10]; C[] -> [20] }
131
///
132
/// Result:
133
/// { B[] -> [i] : 0 < i < 10 }
134
///
135
/// Note that A[] and C[] are not in the result because they do not have a start
136
/// or end timepoint. If a start (or end) timepoint is not unique, the first
137
/// (respectively last) is chosen.
138
///
139
/// @param From     { Space[] -> Scatter[] }
140
///                 Map to start timepoints.
141
/// @param To       { Space[] -> Scatter[] }
142
///                 Map to end timepoints.
143
/// @param InclFrom Whether to include the start timepoints in the result. In
144
///                 the example, this would add { B[] -> [0] }
145
/// @param InclTo   Whether to include the end timepoints in the result. In this
146
///                 example, this would add { B[] -> [10] }
147
///
148
/// @return { Space[] -> Scatter[] }
149
///         A map for each domain element of timepoints between two extreme
150
///         points, or nullptr if @p From or @p To is nullptr, or the isl max
151
///         operations is exceeded.
152
isl::map betweenScatter(isl::map From, isl::map To, bool InclFrom, bool InclTo);
153
 
154
/// Piecewise betweenScatter(isl::map,isl::map,bool,bool).
155
isl::union_map betweenScatter(isl::union_map From, isl::union_map To,
156
                              bool InclFrom, bool InclTo);
157
 
158
/// If by construction a union map is known to contain only a single map, return
159
/// it.
160
///
161
/// This function combines isl_map_from_union_map() and
162
/// isl_union_map_extract_map(). isl_map_from_union_map() fails if the map is
163
/// empty because it does not know which space it would be in.
164
/// isl_union_map_extract_map() on the other hand does not check whether there
165
/// is (at most) one isl_map in the union, i.e. how it has been constructed is
166
/// probably wrong.
167
isl::map singleton(isl::union_map UMap, isl::space ExpectedSpace);
168
 
169
/// If by construction an isl_union_set is known to contain only a single
170
/// isl_set, return it.
171
///
172
/// This function combines isl_set_from_union_set() and
173
/// isl_union_set_extract_set(). isl_map_from_union_set() fails if the set is
174
/// empty because it does not know which space it would be in.
175
/// isl_union_set_extract_set() on the other hand does not check whether there
176
/// is (at most) one isl_set in the union, i.e. how it has been constructed is
177
/// probably wrong.
178
isl::set singleton(isl::union_set USet, isl::space ExpectedSpace);
179
 
180
/// Determine how many dimensions the scatter space of @p Schedule has.
181
///
182
/// The schedule must not be empty and have equal number of dimensions of any
183
/// subspace it contains.
184
///
185
/// The implementation currently returns the maximum number of dimensions it
186
/// encounters, if different, and 0 if none is encountered. However, most other
187
/// code will most likely fail if one of these happen.
188
unsigned getNumScatterDims(const isl::union_map &Schedule);
189
 
190
/// Return the scatter space of a @p Schedule.
191
///
192
/// This is basically the range space of the schedule map, but harder to
193
/// determine because it is an isl_union_map.
194
isl::space getScatterSpace(const isl::union_map &Schedule);
195
 
196
/// Construct an identity map for the given domain values.
197
///
198
/// @param USet           { Space[] }
199
///                       The returned map's domain and range.
200
/// @param RestrictDomain If true, the returned map only maps elements contained
201
///                       in @p Set and no other. If false, it returns an
202
///                       overapproximation with the identity maps of any space
203
///                       in @p Set, not just the elements in it.
204
///
205
/// @return { Space[] -> Space[] }
206
///         A map that maps each value of @p Set to itself.
207
isl::map makeIdentityMap(const isl::set &Set, bool RestrictDomain);
208
 
209
/// Construct an identity map for the given domain values.
210
///
211
/// There is no type resembling isl_union_space, hence we have to pass an
212
/// isl_union_set as the map's domain and range space.
213
///
214
/// @param USet           { Space[] }
215
///                       The returned map's domain and range.
216
/// @param RestrictDomain If true, the returned map only maps elements contained
217
///                       in @p USet and no other. If false, it returns an
218
///                       overapproximation with the identity maps of any space
219
///                       in @p USet, not just the elements in it.
220
///
221
/// @return { Space[] -> Space[] }
222
///         A map that maps each value of @p USet to itself.
223
isl::union_map makeIdentityMap(const isl::union_set &USet, bool RestrictDomain);
224
 
225
/// Reverse the nested map tuple in @p Map's domain.
226
///
227
/// @param Map { [Space1[] -> Space2[]] -> Space3[] }
228
///
229
/// @return { [Space2[] -> Space1[]] -> Space3[] }
230
isl::map reverseDomain(isl::map Map);
231
 
232
/// Piecewise reverseDomain(isl::map).
233
isl::union_map reverseDomain(const isl::union_map &UMap);
234
 
235
/// Add a constant to one dimension of a set.
236
///
237
/// @param Map    The set to shift a dimension in.
238
/// @param Pos    The dimension to shift. If negative, the dimensions are
239
///               counted from the end instead from the beginning. E.g. -1 is
240
///               the last dimension in the tuple.
241
/// @param Amount The offset to add to the specified dimension.
242
///
243
/// @return The modified set.
244
isl::set shiftDim(isl::set Set, int Pos, int Amount);
245
 
246
/// Piecewise shiftDim(isl::set,int,int).
247
isl::union_set shiftDim(isl::union_set USet, int Pos, int Amount);
248
 
249
/// Add a constant to one dimension of a map.
250
///
251
/// @param Map    The map to shift a dimension in.
252
/// @param Type   A tuple of @p Map which contains the dimension to shift.
253
/// @param Pos    The dimension to shift. If negative, the dimensions are
254
/// counted from the end instead from the beginning. Eg. -1 is the last
255
/// dimension in the tuple.
256
/// @param Amount The offset to add to the specified dimension.
257
///
258
/// @return The modified map.
259
isl::map shiftDim(isl::map Map, isl::dim Dim, int Pos, int Amount);
260
 
261
/// Add a constant to one dimension of a each map in a union map.
262
///
263
/// @param UMap   The maps to shift a dimension in.
264
/// @param Type   The tuple which contains the dimension to shift.
265
/// @param Pos    The dimension to shift. If negative, the dimensions are
266
///               counted from the ends of each map of union instead from their
267
///               beginning. E.g. -1 is the last dimension of any map.
268
/// @param Amount The offset to add to the specified dimension.
269
///
270
/// @return The union of all modified maps.
271
isl::union_map shiftDim(isl::union_map UMap, isl::dim Dim, int Pos, int Amount);
272
 
273
/// Simplify a set inplace.
274
void simplify(isl::set &Set);
275
 
276
/// Simplify a union set inplace.
277
void simplify(isl::union_set &USet);
278
 
279
/// Simplify a map inplace.
280
void simplify(isl::map &Map);
281
 
282
/// Simplify a union map inplace.
283
void simplify(isl::union_map &UMap);
284
 
285
/// Compute the reaching definition statement or the next overwrite for each
286
/// definition of an array element.
287
///
288
/// The reaching definition of an array element at a specific timepoint is the
289
/// statement instance that has written the current element's content.
290
/// Alternatively, this function determines for each timepoint and element which
291
/// write is going to overwrite an element at a future timepoint. This can be
292
/// seen as "reaching definition in reverse" where definitions are found in the
293
/// past.
294
///
295
/// For example:
296
///
297
/// Schedule := { Write[] -> [0]; Overwrite[] -> [10] }
298
/// Defs := { Write[] -> A[5]; Overwrite[] -> A[5] }
299
///
300
/// If index 5 of array A is written at timepoint 0 and 10, the resulting
301
/// reaching definitions are:
302
///
303
/// { [A[5] -> [i]] -> Write[] : 0 < i < 10;
304
///   [A[5] -> [i]] -> Overwrite[] : 10 < i }
305
///
306
/// Between timepoint 0 (Write[]) and timepoint 10 (Overwrite[]), the
307
/// content of A[5] is written by statement instance Write[] and after
308
/// timepoint 10 by Overwrite[]. Values not defined in the map have no known
309
/// definition. This includes the statement instance timepoints themselves,
310
/// because reads at those timepoints could either read the old or the new
311
/// value, defined only by the statement itself. But this can be changed by @p
312
/// InclPrevDef and @p InclNextDef. InclPrevDef=false and InclNextDef=true
313
/// returns a zone. Unless @p InclPrevDef and @p InclNextDef are both true,
314
/// there is only one unique definition per element and timepoint.
315
///
316
/// @param Schedule    { DomainWrite[] -> Scatter[] }
317
///                    Schedule of (at least) all array writes. Instances not in
318
///                    @p Writes are ignored.
319
/// @param Writes      { DomainWrite[] -> Element[] }
320
///                    Elements written to by the statement instances.
321
/// @param Reverse     If true, look for definitions in the future. That is,
322
///                    find the write that is overwrites the current value.
323
/// @param InclPrevDef Include the definition's timepoint to the set of
324
///                    well-defined elements (any load at that timepoint happen
325
///                    at the writes). In the example, enabling this option adds
326
///                    {[A[5] -> [0]] -> Write[]; [A[5] -> [10]] -> Overwrite[]}
327
///                    to the result.
328
/// @param InclNextDef Whether to assume that at the timepoint where an element
329
///                    is overwritten, it still contains the old value (any load
330
///                    at that timepoint would happen before the overwrite). In
331
///                    this example, enabling this adds
332
///                    { [A[] -> [10]] -> Write[] } to the result.
333
///
334
/// @return { [Element[] -> Scatter[]] -> DomainWrite[] }
335
///         The reaching definitions or future overwrite as described above, or
336
///         nullptr if either @p Schedule or @p Writes is nullptr, or the isl
337
///         max operations count has exceeded.
338
isl::union_map computeReachingWrite(isl::union_map Schedule,
339
                                    isl::union_map Writes, bool Reverse,
340
                                    bool InclPrevDef, bool InclNextDef);
341
 
342
/// Compute the timepoints where the contents of an array element are not used.
343
///
344
/// An element is unused at a timepoint when the element is overwritten in
345
/// the future, but it is not read in between. Another way to express this: the
346
/// time from when the element is written, to the most recent read before it, or
347
/// infinitely into the past if there is no read before. Such unused elements
348
/// can be overwritten by any value without changing the scop's semantics. An
349
/// example:
350
///
351
/// Schedule := { Read[] -> [0]; Write[] -> [10]; Def[] -> [20] }
352
/// Writes := { Write[] -> A[5]; Def[] -> A[6] }
353
/// Reads := { Read[] -> A[5] }
354
///
355
/// The result is:
356
///
357
/// { A[5] -> [i] : 0 < i < 10;
358
///   A[6] -> [i] : i < 20 }
359
///
360
/// That is, A[5] is unused between timepoint 0 (the read) and timepoint 10 (the
361
/// write). A[6] is unused before timepoint 20, but might be used after the
362
/// scop's execution (A[5] and any other A[i] as well). Use InclLastRead=false
363
/// and InclWrite=true to interpret the result as zone.
364
///
365
/// @param Schedule          { Domain[] -> Scatter[] }
366
///                          The schedule of (at least) all statement instances
367
///                          occurring in @p Writes or @p Reads. All other
368
///                          instances are ignored.
369
/// @param Writes            { DomainWrite[] -> Element[] }
370
///                          Elements written to by the statement instances.
371
/// @param Reads             { DomainRead[] -> Element[] }
372
///                          Elements read from by the statement instances.
373
/// @param ReadEltInSameInst Whether a load reads the value from a write
374
///                          that is scheduled at the same timepoint (Writes
375
///                          happen before reads). Otherwise, loads use the
376
///                          value of an element that it had before the
377
///                          timepoint (Reads before writes). For example:
378
///                          { Read[] -> [0]; Write[] -> [0] }
379
///                          With ReadEltInSameInst=false it is assumed that the
380
///                          read happens before the write, such that the
381
///                          element is never unused, or just at timepoint 0,
382
///                          depending on InclLastRead/InclWrite.
383
///                          With ReadEltInSameInst=false it assumes that the
384
///                          value just written is used. Anything before
385
///                          timepoint 0 is considered unused.
386
/// @param InclLastRead      Whether a timepoint where an element is last read
387
///                          counts as unused (the read happens at the beginning
388
///                          of its timepoint, and nothing (else) can use it
389
///                          during the timepoint). In the example, this option
390
///                          adds { A[5] -> [0] } to the result.
391
/// @param InclWrite         Whether the timepoint where an element is written
392
///                          itself counts as unused (the write happens at the
393
///                          end of its timepoint; no (other) operations uses
394
///                          the element during the timepoint). In this example,
395
///                          this adds
396
///                          { A[5] -> [10]; A[6] -> [20] } to the result.
397
///
398
/// @return { Element[] -> Scatter[] }
399
///         The unused timepoints as defined above, or nullptr if either @p
400
///         Schedule, @p Writes are @p Reads is nullptr, or the ISL max
401
///         operations count is exceeded.
402
isl::union_map computeArrayUnused(isl::union_map Schedule,
403
                                  isl::union_map Writes, isl::union_map Reads,
404
                                  bool ReadEltInSameInst, bool InclLastRead,
405
                                  bool InclWrite);
406
 
407
/// Convert a zone (range between timepoints) to timepoints.
408
///
409
/// A zone represents the time between (integer) timepoints, but not the
410
/// timepoints themselves. This function can be used to determine whether a
411
/// timepoint lies within a zone.
412
///
413
/// For instance, the range (1,3), representing the time between 1 and 3, is
414
/// represented by the zone
415
///
416
/// { [i] : 1 < i <= 3 }
417
///
418
/// The set of timepoints that lie completely within this range is
419
///
420
/// { [i] : 1 < i < 3 }
421
///
422
/// A typical use-case is the range in which a value written by a store is
423
/// available until it is overwritten by another value. If the write is at
424
/// timepoint 1 and its value is overwritten by another value at timepoint 3,
425
/// the value is available between those timepoints: timepoint 2 in this
426
/// example.
427
///
428
///
429
/// When InclStart is true, the range is interpreted left-inclusive, i.e. adds
430
/// the timepoint 1 to the result:
431
///
432
/// { [i] : 1 <= i < 3 }
433
///
434
/// In the use-case mentioned above that means that the value written at
435
/// timepoint 1 is already available in timepoint 1 (write takes place before
436
/// any read of it even if executed at the same timepoint)
437
///
438
/// When InclEnd is true, the range is interpreted right-inclusive, i.e. adds
439
/// the timepoint 3 to the result:
440
///
441
/// { [i] : 1 < i <= 3 }
442
///
443
/// In the use-case mentioned above that means that although the value is
444
/// overwritten in timepoint 3, the old value is still available at timepoint 3
445
/// (write takes place after any read even if executed at the same timepoint)
446
///
447
/// @param Zone      { Zone[] }
448
/// @param InclStart Include timepoints adjacent to the beginning of a zone.
449
/// @param InclEnd   Include timepoints adjacent to the ending of a zone.
450
///
451
/// @return { Scatter[] }
452
isl::union_set convertZoneToTimepoints(isl::union_set Zone, bool InclStart,
453
                                       bool InclEnd);
454
 
455
/// Like convertZoneToTimepoints(isl::union_set,InclStart,InclEnd), but convert
456
/// either the domain or the range of a map.
457
isl::union_map convertZoneToTimepoints(isl::union_map Zone, isl::dim Dim,
458
                                       bool InclStart, bool InclEnd);
459
 
460
/// Overload of convertZoneToTimepoints(isl::map,InclStart,InclEnd) to process
461
/// only a single map.
462
isl::map convertZoneToTimepoints(isl::map Zone, isl::dim Dim, bool InclStart,
463
                                 bool InclEnd);
464
 
465
/// Distribute the domain to the tuples of a wrapped range map.
466
///
467
/// @param Map { Domain[] -> [Range1[] -> Range2[]] }
468
///
469
/// @return { [Domain[] -> Range1[]] -> [Domain[] -> Range2[]] }
470
isl::map distributeDomain(isl::map Map);
471
 
472
/// Apply distributeDomain(isl::map) to each map in the union.
473
isl::union_map distributeDomain(isl::union_map UMap);
474
 
475
/// Prepend a space to the tuples of a map.
476
///
477
/// @param UMap   { Domain[] -> Range[] }
478
/// @param Factor { Factor[] }
479
///
480
/// @return { [Factor[] -> Domain[]] -> [Factor[] -> Range[]] }
481
isl::union_map liftDomains(isl::union_map UMap, isl::union_set Factor);
482
 
483
/// Apply a map to the 'middle' of another relation.
484
///
485
/// @param UMap { [DomainDomain[] -> DomainRange[]] -> Range[] }
486
/// @param Func { DomainRange[] -> NewDomainRange[] }
487
///
488
/// @return { [DomainDomain[] -> NewDomainRange[]] -> Range[] }
489
isl::union_map applyDomainRange(isl::union_map UMap, isl::union_map Func);
490
 
491
/// Intersect the range of @p Map with @p Range.
492
///
493
/// Since @p Map is an isl::map, the result will be a single space, even though
494
/// @p Range is an isl::union_set. This is the only difference to
495
/// isl::map::intersect_range and isl::union_map::interset_range.
496
///
497
/// @param Map   { Domain[] -> Range[] }
498
/// @param Range { Range[] }
499
///
500
/// @return { Domain[] -> Range[] }
501
isl::map intersectRange(isl::map Map, isl::union_set Range);
502
 
503
/// Subtract the parameter space @p Params from @p Map.
504
/// This is akin to isl::map::intersect_params.
505
///
506
/// Example:
507
///   subtractParams(
508
///     { [i] -> [i] },
509
///     [x] -> { : x < 0 }
510
///   ) = [x] -> { [i] -> [i] : x >= 0 }
511
///
512
/// @param Map    Remove the conditions of @p Params from this map.
513
/// @param Params Parameter set to subtract.
514
///
515
/// @param The map with the parameter conditions removed.
516
isl::map subtractParams(isl::map Map, isl::set Params);
517
 
518
/// Subtract the parameter space @p Params from @p Set.
519
isl::set subtractParams(isl::set Set, isl::set Params);
520
 
521
/// If @p PwAff maps to a constant, return said constant. If @p Max/@p Min, it
522
/// can also be a piecewise constant and it would return the minimum/maximum
523
/// value. Otherwise, return NaN.
524
isl::val getConstant(isl::pw_aff PwAff, bool Max, bool Min);
525
 
526
/// If the relation @p PwAff lies on a hyperplane where the given
527
/// dimension @p Pos with the type @p Dim has a fixed value, then
528
/// return that value. Otherwise return NaN.
529
isl::val getConstant(isl::map Map, isl::dim Dim, int Pos);
530
 
531
/// Check that @p End is valid and return an iterator from @p Begin to @p End
532
///
533
/// Use case example:
534
///   for (unsigned i : rangeIslSize(0, Map.domain_tuple_dim()))
535
///     // do stuff
536
llvm::iota_range<unsigned> rangeIslSize(unsigned Begin, isl::size End);
537
 
538
/// Dump a description of the argument to llvm::errs().
539
///
540
/// In contrast to isl's dump function, there are a few differences:
541
/// - Each polyhedron (pieces) is written on its own line.
542
/// - Spaces are sorted by structure. E.g. maps with same domain space are
543
///   grouped. Isl sorts them according to the space's hash function.
544
/// - Pieces of the same space are sorted using their lower bound.
545
/// - A more compact to_str representation is used instead of Isl's dump
546
///   functions that try to show the internal representation.
547
///
548
/// The goal is to get a better understandable representation that is also
549
/// useful to compare two sets. As all dump() functions, its intended use is to
550
/// be called in a debugger only.
551
///
552
/// isl_map_dump example:
553
/// [p_0, p_1, p_2] -> { Stmt0[i0] -> [o0, o1] : (o0 = i0 and o1 = 0 and i0 > 0
554
/// and i0 <= 5 - p_2) or (i0 = 0 and o0 = 0 and o1 = 0); Stmt3[i0] -> [o0, o1]
555
/// : (o0 = i0 and o1 = 3 and i0 > 0 and i0 <= 5 - p_2) or (i0 = 0 and o0 = 0
556
/// and o1 = 3); Stmt2[i0] -> [o0, o1] : (o0 = i0 and o1 = 1 and i0 >= 3 + p_0 -
557
/// p_1 and i0 > 0 and i0 <= 5 - p_2) or (o0 = i0 and o1 = 1 and i0 > 0 and i0
558
/// <= 5 - p_2 and i0 < p_0 - p_1) or (i0 = 0 and o0 = 0 and o1 = 1 and p_1 >= 3
559
/// + p_0) or (i0 = 0 and o0 = 0 and o1 = 1 and p_1 < p_0) or (p_0 = 0 and i0 =
560
/// 2 - p_1 and o0 = 2 - p_1 and o1 = 1 and p_2 <= 3 + p_1 and p_1 <= 1) or (p_1
561
/// = 1 + p_0 and i0 = 0 and o0 = 0 and o1 = 1) or (p_0 = 0 and p_1 = 2 and i0 =
562
/// 0 and o0 = 0 and o1 = 1) or (p_0 = -1 and p_1 = -1 and i0 = 0 and o0 = 0 and
563
/// o1 = 1); Stmt1[i0] -> [o0, o1] : (p_0 = -1 and i0 = 1 - p_1 and o0 = 1 - p_1
564
/// and o1 = 2 and p_2 <= 4 + p_1 and p_1 <= 0) or (p_0 = 0 and i0 = -p_1 and o0
565
/// = -p_1 and o1 = 2 and p_2 <= 5 + p_1 and p_1 < 0) or (p_0 = -1 and p_1 = 1
566
/// and i0 = 0 and o0 = 0 and o1 = 2) or (p_0 = 0 and p_1 = 0 and i0 = 0 and o0
567
/// = 0 and o1 = 2) }
568
///
569
/// dumpPw example (same set):
570
/// [p_0, p_1, p_2] -> {
571
///   Stmt0[0] -> [0, 0];
572
///   Stmt0[i0] -> [i0, 0] : 0 < i0 <= 5 - p_2;
573
///   Stmt1[0] -> [0, 2] : p_1 = 1 and p_0 = -1;
574
///   Stmt1[0] -> [0, 2] : p_1 = 0 and p_0 = 0;
575
///   Stmt1[1 - p_1] -> [1 - p_1, 2] : p_0 = -1 and p_1 <= 0 and p_2 <= 4 + p_1;
576
///   Stmt1[-p_1] -> [-p_1, 2] : p_0 = 0 and p_1 < 0 and p_2 <= 5 + p_1;
577
///   Stmt2[0] -> [0, 1] : p_1 >= 3 + p_0;
578
///   Stmt2[0] -> [0, 1] : p_1 < p_0;
579
///   Stmt2[0] -> [0, 1] : p_1 = 1 + p_0;
580
///   Stmt2[0] -> [0, 1] : p_1 = 2 and p_0 = 0;
581
///   Stmt2[0] -> [0, 1] : p_1 = -1 and p_0 = -1;
582
///   Stmt2[i0] -> [i0, 1] : i0 >= 3 + p_0 - p_1 and 0 < i0 <= 5 - p_2;
583
///   Stmt2[i0] -> [i0, 1] : 0 < i0 <= 5 - p_2 and i0 < p_0 - p_1;
584
///   Stmt2[2 - p_1] -> [2 - p_1, 1] : p_0 = 0 and p_1 <= 1 and p_2 <= 3 + p_1;
585
///   Stmt3[0] -> [0, 3];
586
///   Stmt3[i0] -> [i0, 3] : 0 < i0 <= 5 - p_2
587
/// }
588
/// @{
589
void dumpPw(const isl::set &Set);
590
void dumpPw(const isl::map &Map);
591
void dumpPw(const isl::union_set &USet);
592
void dumpPw(const isl::union_map &UMap);
593
void dumpPw(__isl_keep isl_set *Set);
594
void dumpPw(__isl_keep isl_map *Map);
595
void dumpPw(__isl_keep isl_union_set *USet);
596
void dumpPw(__isl_keep isl_union_map *UMap);
597
/// @}
598
 
599
/// Dump all points of the argument to llvm::errs().
600
///
601
/// Before being printed by dumpPw(), the argument's pieces are expanded to
602
/// contain only single points. If a dimension is unbounded, it keeps its
603
/// representation.
604
///
605
/// This is useful for debugging reduced cases where parameters are set to
606
/// constants to keep the example simple. Such sets can still contain
607
/// existential dimensions which makes the polyhedral hard to compare.
608
///
609
/// Example:
610
///   { [MemRef_A[i0] -> [i1]] : (exists (e0 = floor((1 + i1)/3): i0 = 1 and 3e0
611
///   <= i1 and 3e0 >= -1 + i1 and i1 >= 15 and i1 <= 25)) or (exists (e0 =
612
///   floor((i1)/3): i0 = 0 and 3e0 < i1 and 3e0 >= -2 + i1 and i1 > 0 and i1 <=
613
///   11)) }
614
///
615
/// dumpExpanded:
616
/// {
617
///   [MemRef_A[0] ->[1]];
618
///   [MemRef_A[0] ->[2]];
619
///   [MemRef_A[0] ->[4]];
620
///   [MemRef_A[0] ->[5]];
621
///   [MemRef_A[0] ->[7]];
622
///   [MemRef_A[0] ->[8]];
623
///   [MemRef_A[0] ->[10]];
624
///   [MemRef_A[0] ->[11]];
625
///   [MemRef_A[1] ->[15]];
626
///   [MemRef_A[1] ->[16]];
627
///   [MemRef_A[1] ->[18]];
628
///   [MemRef_A[1] ->[19]];
629
///   [MemRef_A[1] ->[21]];
630
///   [MemRef_A[1] ->[22]];
631
///   [MemRef_A[1] ->[24]];
632
///   [MemRef_A[1] ->[25]]
633
/// }
634
/// @{
635
void dumpExpanded(const isl::set &Set);
636
void dumpExpanded(const isl::map &Map);
637
void dumpExpanded(const isl::union_set &USet);
638
void dumpExpanded(const isl::union_map &UMap);
639
void dumpExpanded(__isl_keep isl_set *Set);
640
void dumpExpanded(__isl_keep isl_map *Map);
641
void dumpExpanded(__isl_keep isl_union_set *USet);
642
void dumpExpanded(__isl_keep isl_union_map *UMap);
643
/// @}
644
} // namespace polly
645
 
646
#endif /* POLLY_ISLTOOLS_H */