Coverage Report

Created: 2018-12-13 20:48

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