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
//===- Support/GICHelper.h -- Helper functions for ISL --------------------===//
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
// Helper functions for isl objects.
10
//
11
//===----------------------------------------------------------------------===//
12
//
13
#ifndef POLLY_SUPPORT_GIC_HELPER_H
14
#define POLLY_SUPPORT_GIC_HELPER_H
15
 
16
#include "llvm/ADT/APInt.h"
17
#include "llvm/IR/DiagnosticInfo.h"
18
#include "llvm/Support/raw_ostream.h"
19
#include "isl/ctx.h"
20
#include "isl/isl-noexceptions.h"
21
#include "isl/options.h"
22
 
23
namespace polly {
24
 
25
/// Translate an llvm::APInt to an isl_val.
26
///
27
/// Translate the bitsequence without sign information as provided by APInt into
28
/// a signed isl_val type. Depending on the value of @p IsSigned @p Int is
29
/// interpreted as unsigned value or as signed value in two's complement
30
/// representation.
31
///
32
/// Input IsSigned                 Output
33
///
34
///     0        0           ->    0
35
///     1        0           ->    1
36
///    00        0           ->    0
37
///    01        0           ->    1
38
///    10        0           ->    2
39
///    11        0           ->    3
40
///
41
///     0        1           ->    0
42
///     1        1           ->   -1
43
///    00        1           ->    0
44
///    01        1           ->    1
45
///    10        1           ->   -2
46
///    11        1           ->   -1
47
///
48
/// @param Ctx      The isl_ctx to create the isl_val in.
49
/// @param Int      The integer value to translate.
50
/// @param IsSigned If the APInt should be interpreted as signed or unsigned
51
///                 value.
52
///
53
/// @return The isl_val corresponding to @p Int.
54
__isl_give isl_val *isl_valFromAPInt(isl_ctx *Ctx, const llvm::APInt Int,
55
                                     bool IsSigned);
56
 
57
/// Translate an llvm::APInt to an isl::val.
58
///
59
/// Translate the bitsequence without sign information as provided by APInt into
60
/// a signed isl::val type. Depending on the value of @p IsSigned @p Int is
61
/// interpreted as unsigned value or as signed value in two's complement
62
/// representation.
63
///
64
/// Input IsSigned                 Output
65
///
66
///     0        0           ->    0
67
///     1        0           ->    1
68
///    00        0           ->    0
69
///    01        0           ->    1
70
///    10        0           ->    2
71
///    11        0           ->    3
72
///
73
///     0        1           ->    0
74
///     1        1           ->   -1
75
///    00        1           ->    0
76
///    01        1           ->    1
77
///    10        1           ->   -2
78
///    11        1           ->   -1
79
///
80
/// @param Ctx      The isl_ctx to create the isl::val in.
81
/// @param Int      The integer value to translate.
82
/// @param IsSigned If the APInt should be interpreted as signed or unsigned
83
///                 value.
84
///
85
/// @return The isl::val corresponding to @p Int.
86
inline isl::val valFromAPInt(isl_ctx *Ctx, const llvm::APInt Int,
87
                             bool IsSigned) {
88
  return isl::manage(isl_valFromAPInt(Ctx, Int, IsSigned));
89
}
90
 
91
/// Translate isl_val to llvm::APInt.
92
///
93
/// This function can only be called on isl_val values which are integers.
94
/// Calling this function with a non-integral rational, NaN or infinity value
95
/// is not allowed.
96
///
97
/// As the input isl_val may be negative, the APInt that this function returns
98
/// must always be interpreted as signed two's complement value. The bitwidth of
99
/// the generated APInt is always the minimal bitwidth necessary to model the
100
/// provided integer when interpreting the bit pattern as signed value.
101
///
102
/// Some example conversions are:
103
///
104
///   Input      Bits    Signed  Bitwidth
105
///       0 ->      0         0         1
106
///      -1 ->      1        -1         1
107
///       1 ->     01         1         2
108
///      -2 ->     10        -2         2
109
///       2 ->    010         2         3
110
///      -3 ->    101        -3         3
111
///       3 ->    011         3         3
112
///      -4 ->    100        -4         3
113
///       4 ->   0100         4         4
114
///
115
/// @param Val The isl val to translate.
116
///
117
/// @return The APInt value corresponding to @p Val.
118
llvm::APInt APIntFromVal(__isl_take isl_val *Val);
119
 
120
/// Translate isl::val to llvm::APInt.
121
///
122
/// This function can only be called on isl::val values which are integers.
123
/// Calling this function with a non-integral rational, NaN or infinity value
124
/// is not allowed.
125
///
126
/// As the input isl::val may be negative, the APInt that this function returns
127
/// must always be interpreted as signed two's complement value. The bitwidth of
128
/// the generated APInt is always the minimal bitwidth necessary to model the
129
/// provided integer when interpreting the bit pattern as signed value.
130
///
131
/// Some example conversions are:
132
///
133
///   Input      Bits    Signed  Bitwidth
134
///       0 ->      0         0         1
135
///      -1 ->      1        -1         1
136
///       1 ->     01         1         2
137
///      -2 ->     10        -2         2
138
///       2 ->    010         2         3
139
///      -3 ->    101        -3         3
140
///       3 ->    011         3         3
141
///      -4 ->    100        -4         3
142
///       4 ->   0100         4         4
143
///
144
/// @param Val The isl val to translate.
145
///
146
/// @return The APInt value corresponding to @p Val.
147
inline llvm::APInt APIntFromVal(isl::val V) {
148
  return APIntFromVal(V.release());
149
}
150
 
151
/// Get c++ string from Isl objects.
152
//@{
153
#define ISL_CPP_OBJECT_TO_STRING(name)                                         \
154
  inline std::string stringFromIslObj(const name &Obj,                         \
155
                                      std::string DefaultValue = "") {         \
156
    return stringFromIslObj(Obj.get(), DefaultValue);                          \
157
  }
158
 
159
#define ISL_OBJECT_TO_STRING(name)                                             \
160
  std::string stringFromIslObj(__isl_keep isl_##name *Obj,                     \
161
                               std::string DefaultValue = "");                 \
162
  ISL_CPP_OBJECT_TO_STRING(isl::name)
163
 
164
ISL_OBJECT_TO_STRING(aff)
165
ISL_OBJECT_TO_STRING(ast_expr)
166
ISL_OBJECT_TO_STRING(ast_node)
167
ISL_OBJECT_TO_STRING(basic_map)
168
ISL_OBJECT_TO_STRING(basic_set)
169
ISL_OBJECT_TO_STRING(map)
170
ISL_OBJECT_TO_STRING(set)
171
ISL_OBJECT_TO_STRING(id)
172
ISL_OBJECT_TO_STRING(multi_aff)
173
ISL_OBJECT_TO_STRING(multi_pw_aff)
174
ISL_OBJECT_TO_STRING(multi_union_pw_aff)
175
ISL_OBJECT_TO_STRING(point)
176
ISL_OBJECT_TO_STRING(pw_aff)
177
ISL_OBJECT_TO_STRING(pw_multi_aff)
178
ISL_OBJECT_TO_STRING(schedule)
179
ISL_OBJECT_TO_STRING(schedule_node)
180
ISL_OBJECT_TO_STRING(space)
181
ISL_OBJECT_TO_STRING(union_access_info)
182
ISL_OBJECT_TO_STRING(union_flow)
183
ISL_OBJECT_TO_STRING(union_set)
184
ISL_OBJECT_TO_STRING(union_map)
185
ISL_OBJECT_TO_STRING(union_pw_aff)
186
ISL_OBJECT_TO_STRING(union_pw_multi_aff)
187
//@}
188
 
189
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
190
/// C++ wrapper for isl_*_dump() functions.
191
//@{
192
 
193
#define ISL_DUMP_OBJECT(name)                                                  \
194
  void dumpIslObj(const isl::name &Obj);                                       \
195
  void dumpIslObj(isl_##name *Obj);
196
 
197
ISL_DUMP_OBJECT(aff)
198
ISL_DUMP_OBJECT(aff_list)
199
ISL_DUMP_OBJECT(ast_expr)
200
ISL_DUMP_OBJECT(ast_node)
201
ISL_DUMP_OBJECT(ast_node_list)
202
ISL_DUMP_OBJECT(basic_map)
203
ISL_DUMP_OBJECT(basic_map_list)
204
ISL_DUMP_OBJECT(basic_set)
205
ISL_DUMP_OBJECT(basic_set_list)
206
ISL_DUMP_OBJECT(constraint)
207
ISL_DUMP_OBJECT(id)
208
ISL_DUMP_OBJECT(id_list)
209
ISL_DUMP_OBJECT(id_to_ast_expr)
210
ISL_DUMP_OBJECT(local_space)
211
ISL_DUMP_OBJECT(map)
212
ISL_DUMP_OBJECT(map_list)
213
ISL_DUMP_OBJECT(multi_aff)
214
ISL_DUMP_OBJECT(multi_pw_aff)
215
ISL_DUMP_OBJECT(multi_union_pw_aff)
216
ISL_DUMP_OBJECT(multi_val)
217
ISL_DUMP_OBJECT(point)
218
ISL_DUMP_OBJECT(pw_aff)
219
ISL_DUMP_OBJECT(pw_aff_list)
220
ISL_DUMP_OBJECT(pw_multi_aff)
221
ISL_DUMP_OBJECT(schedule)
222
ISL_DUMP_OBJECT(schedule_constraints)
223
ISL_DUMP_OBJECT(schedule_node)
224
ISL_DUMP_OBJECT(set)
225
ISL_DUMP_OBJECT(set_list)
226
ISL_DUMP_OBJECT(space)
227
ISL_DUMP_OBJECT(union_map)
228
ISL_DUMP_OBJECT(union_pw_aff)
229
ISL_DUMP_OBJECT(union_pw_aff_list)
230
ISL_DUMP_OBJECT(union_pw_multi_aff)
231
ISL_DUMP_OBJECT(union_set)
232
ISL_DUMP_OBJECT(union_set_list)
233
ISL_DUMP_OBJECT(val)
234
ISL_DUMP_OBJECT(val_list)
235
//@}
236
 
237
/// Emit the equivaltent of the isl_*_dump output into a raw_ostream.
238
/// @{
239
void dumpIslObj(const isl::schedule_node &Node, llvm::raw_ostream &OS);
240
void dumpIslObj(__isl_keep isl_schedule_node *node, llvm::raw_ostream &OS);
241
/// @}
242
#endif
243
 
244
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
245
                                     __isl_keep isl_union_map *Map) {
246
  OS << polly::stringFromIslObj(Map, "null");
247
  return OS;
248
}
249
 
250
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
251
                                     __isl_keep isl_map *Map) {
252
  OS << polly::stringFromIslObj(Map, "null");
253
  return OS;
254
}
255
 
256
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
257
                                     __isl_keep isl_set *Set) {
258
  OS << polly::stringFromIslObj(Set, "null");
259
  return OS;
260
}
261
 
262
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
263
                                     __isl_keep isl_pw_aff *Map) {
264
  OS << polly::stringFromIslObj(Map, "null");
265
  return OS;
266
}
267
 
268
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
269
                                     __isl_keep isl_pw_multi_aff *PMA) {
270
  OS << polly::stringFromIslObj(PMA, "null");
271
  return OS;
272
}
273
 
274
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
275
                                     __isl_keep isl_multi_aff *MA) {
276
  OS << polly::stringFromIslObj(MA, "null");
277
  return OS;
278
}
279
 
280
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
281
                                     __isl_keep isl_union_pw_multi_aff *UPMA) {
282
  OS << polly::stringFromIslObj(UPMA, "null");
283
  return OS;
284
}
285
 
286
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
287
                                     __isl_keep isl_schedule *Schedule) {
288
  OS << polly::stringFromIslObj(Schedule, "null");
289
  return OS;
290
}
291
 
292
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
293
                                     __isl_keep isl_space *Space) {
294
  OS << polly::stringFromIslObj(Space, "null");
295
  return OS;
296
}
297
 
298
/// Combine Prefix, Val (or Number) and Suffix to an isl-compatible name.
299
///
300
/// In case @p UseInstructionNames is set, this function returns:
301
///
302
/// @p Prefix + "_" + @p Val->getName() + @p Suffix
303
///
304
/// otherwise
305
///
306
/// @p Prefix + to_string(Number) + @p Suffix
307
///
308
/// We ignore the value names by default, as they may change between release
309
/// and debug mode and can consequently not be used when aiming for reproducible
310
/// builds. However, for debugging named statements are often helpful, hence
311
/// we allow their optional use.
312
std::string getIslCompatibleName(const std::string &Prefix,
313
                                 const llvm::Value *Val, long Number,
314
                                 const std::string &Suffix,
315
                                 bool UseInstructionNames);
316
 
317
/// Combine Prefix, Name (or Number) and Suffix to an isl-compatible name.
318
///
319
/// In case @p UseInstructionNames is set, this function returns:
320
///
321
/// @p Prefix + "_" + Name + @p Suffix
322
///
323
/// otherwise
324
///
325
/// @p Prefix + to_string(Number) + @p Suffix
326
///
327
/// We ignore @p Name by default, as they may change between release
328
/// and debug mode and can consequently not be used when aiming for reproducible
329
/// builds. However, for debugging named statements are often helpful, hence
330
/// we allow their optional use.
331
std::string getIslCompatibleName(const std::string &Prefix,
332
                                 const std::string &Middle, long Number,
333
                                 const std::string &Suffix,
334
                                 bool UseInstructionNames);
335
 
336
std::string getIslCompatibleName(const std::string &Prefix,
337
                                 const std::string &Middle,
338
                                 const std::string &Suffix);
339
 
340
inline llvm::DiagnosticInfoOptimizationBase &
341
operator<<(llvm::DiagnosticInfoOptimizationBase &OS,
342
           const isl::union_map &Obj) {
343
  OS << stringFromIslObj(Obj);
344
  return OS;
345
}
346
 
347
/// Scope guard for code that allows arbitrary isl function to return an error
348
/// if the max-operations quota exceeds.
349
///
350
/// This allows to opt-in code sections that have known long executions times.
351
/// code not in a hot path can continue to assume that no unexpected error
352
/// occurs.
353
///
354
/// This is typically used inside a nested IslMaxOperationsGuard scope. The
355
/// IslMaxOperationsGuard defines the number of allowed base operations for some
356
/// code, IslQuotaScope defines where it is allowed to return an error result.
357
class IslQuotaScope final {
358
  isl_ctx *IslCtx;
359
  int OldOnError;
360
 
361
public:
362
  IslQuotaScope() : IslCtx(nullptr) {}
363
  IslQuotaScope(const IslQuotaScope &) = delete;
364
  IslQuotaScope(IslQuotaScope &&Other)
365
      : IslCtx(Other.IslCtx), OldOnError(Other.OldOnError) {
366
    Other.IslCtx = nullptr;
367
  }
368
  const IslQuotaScope &operator=(IslQuotaScope &&Other) {
369
    std::swap(this->IslCtx, Other.IslCtx);
370
    std::swap(this->OldOnError, Other.OldOnError);
371
    return *this;
372
  }
373
 
374
  /// Enter a quota-aware scope.
375
  ///
376
  /// Should not be used directly. Use IslMaxOperationsGuard::enter() instead.
377
  explicit IslQuotaScope(isl_ctx *IslCtx, unsigned long LocalMaxOps)
378
      : IslCtx(IslCtx) {
379
    assert(IslCtx);
380
    assert(isl_ctx_get_max_operations(IslCtx) == 0 && "Incorrect nesting");
381
    if (LocalMaxOps == 0) {
382
      this->IslCtx = nullptr;
383
      return;
384
    }
385
 
386
    OldOnError = isl_options_get_on_error(IslCtx);
387
    isl_options_set_on_error(IslCtx, ISL_ON_ERROR_CONTINUE);
388
    isl_ctx_reset_error(IslCtx);
389
    isl_ctx_set_max_operations(IslCtx, LocalMaxOps);
390
  }
391
 
392
  ~IslQuotaScope() {
393
    if (!IslCtx)
394
      return;
395
 
396
    assert(isl_ctx_get_max_operations(IslCtx) > 0 && "Incorrect nesting");
397
    assert(isl_options_get_on_error(IslCtx) == ISL_ON_ERROR_CONTINUE &&
398
           "Incorrect nesting");
399
    isl_ctx_set_max_operations(IslCtx, 0);
400
    isl_options_set_on_error(IslCtx, OldOnError);
401
  }
402
 
403
  /// Return whether the current quota has exceeded.
404
  bool hasQuotaExceeded() const {
405
    if (!IslCtx)
406
      return false;
407
 
408
    return isl_ctx_last_error(IslCtx) == isl_error_quota;
409
  }
410
};
411
 
412
/// Scoped limit of ISL operations.
413
///
414
/// Limits the number of ISL operations during the lifetime of this object. The
415
/// idea is to use this as an RAII guard for the scope where the code is aware
416
/// that ISL can return errors even when all input is valid. After leaving the
417
/// scope, it will return to the error setting as it was before. That also means
418
/// that the error setting should not be changed while in that scope.
419
///
420
/// Such scopes are not allowed to be nested because the previous operations
421
/// counter cannot be reset to the previous state, or one that adds the
422
/// operations while being in the nested scope. Use therefore is only allowed
423
/// while currently a no operations-limit is active.
424
class IslMaxOperationsGuard final {
425
private:
426
  /// The ISL context to set the operations limit.
427
  ///
428
  /// If set to nullptr, there is no need for any action at the end of the
429
  /// scope.
430
  isl_ctx *IslCtx;
431
 
432
  /// Maximum number of operations for the scope.
433
  unsigned long LocalMaxOps;
434
 
435
  /// When AutoEnter is enabled, holds the IslQuotaScope object.
436
  IslQuotaScope TopLevelScope;
437
 
438
public:
439
  /// Enter a max operations scope.
440
  ///
441
  /// @param IslCtx      The ISL context to set the operations limit for.
442
  /// @param LocalMaxOps Maximum number of operations allowed in the
443
  ///                    scope. If set to zero, no operations limit is enforced.
444
  /// @param AutoEnter   If true, automatically enters an IslQuotaScope such
445
  ///                    that isl operations may return quota errors
446
  ///                    immediately. If false, only starts the operations
447
  ///                    counter, but isl does not return quota errors before
448
  ///                    calling enter().
449
  IslMaxOperationsGuard(isl_ctx *IslCtx, unsigned long LocalMaxOps,
450
                        bool AutoEnter = true)
451
      : IslCtx(IslCtx), LocalMaxOps(LocalMaxOps) {
452
    assert(IslCtx);
453
    assert(isl_ctx_get_max_operations(IslCtx) == 0 &&
454
           "Nested max operations not supported");
455
 
456
    // Users of this guard may check whether the last error was isl_error_quota.
457
    // Reset the last error such that a previous out-of-quota error is not
458
    // mistaken to have occurred in the in this quota, even if the max number of
459
    // operations is set to infinite (LocalMaxOps == 0).
460
    isl_ctx_reset_error(IslCtx);
461
 
462
    if (LocalMaxOps == 0) {
463
      // No limit on operations; also disable restoring on_error/max_operations.
464
      this->IslCtx = nullptr;
465
      return;
466
    }
467
 
468
    isl_ctx_reset_operations(IslCtx);
469
    TopLevelScope = enter(AutoEnter);
470
  }
471
 
472
  /// Enter a scope that can handle out-of-quota errors.
473
  ///
474
  /// @param AllowReturnNull Whether the scoped code can handle out-of-quota
475
  ///                        errors. If false, returns a dummy scope object that
476
  ///                        does nothing.
477
  IslQuotaScope enter(bool AllowReturnNull = true) {
478
    return AllowReturnNull && IslCtx ? IslQuotaScope(IslCtx, LocalMaxOps)
479
                                     : IslQuotaScope();
480
  }
481
 
482
  /// Return whether the current quota has exceeded.
483
  bool hasQuotaExceeded() const {
484
    if (!IslCtx)
485
      return false;
486
 
487
    return isl_ctx_last_error(IslCtx) == isl_error_quota;
488
  }
489
};
490
} // end namespace polly
491
 
492
#endif