Coverage Report

Created: 2019-07-24 05:18

/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
// 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
2.48k
                             bool IsSigned) {
88
2.48k
  return isl::manage(isl_valFromAPInt(Ctx, Int, IsSigned));
89
2.48k
}
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
946
inline llvm::APInt APIntFromVal(isl::val V) {
148
946
  return APIntFromVal(V.release());
149
946
}
150
151
/// Get c++ string from Isl objects.
152
//@{
153
std::string stringFromIslObj(__isl_keep isl_map *map);
154
std::string stringFromIslObj(__isl_keep isl_union_map *umap);
155
std::string stringFromIslObj(__isl_keep isl_set *set);
156
std::string stringFromIslObj(__isl_keep isl_union_set *uset);
157
std::string stringFromIslObj(__isl_keep isl_schedule *schedule);
158
std::string stringFromIslObj(__isl_keep isl_multi_aff *maff);
159
std::string stringFromIslObj(__isl_keep isl_pw_multi_aff *pma);
160
std::string stringFromIslObj(__isl_keep isl_multi_pw_aff *mpa);
161
std::string stringFromIslObj(__isl_keep isl_union_pw_multi_aff *upma);
162
std::string stringFromIslObj(__isl_keep isl_aff *aff);
163
std::string stringFromIslObj(__isl_keep isl_pw_aff *pwaff);
164
std::string stringFromIslObj(__isl_keep isl_space *space);
165
//@}
166
167
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
168
261
                                     __isl_keep isl_union_map *Map) {
169
261
  OS << polly::stringFromIslObj(Map);
170
261
  return OS;
171
261
}
172
173
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
174
0
                                     __isl_keep isl_map *Map) {
175
0
  OS << polly::stringFromIslObj(Map);
176
0
  return OS;
177
0
}
178
179
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
180
0
                                     __isl_keep isl_set *Set) {
181
0
  OS << polly::stringFromIslObj(Set);
182
0
  return OS;
183
0
}
184
185
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
186
0
                                     __isl_keep isl_pw_aff *Map) {
187
0
  OS << polly::stringFromIslObj(Map);
188
0
  return OS;
189
0
}
190
191
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
192
0
                                     __isl_keep isl_pw_multi_aff *PMA) {
193
0
  OS << polly::stringFromIslObj(PMA);
194
0
  return OS;
195
0
}
196
197
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
198
0
                                     __isl_keep isl_multi_aff *MA) {
199
0
  OS << polly::stringFromIslObj(MA);
200
0
  return OS;
201
0
}
202
203
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
204
0
                                     __isl_keep isl_union_pw_multi_aff *UPMA) {
205
0
  OS << polly::stringFromIslObj(UPMA);
206
0
  return OS;
207
0
}
208
209
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
210
0
                                     __isl_keep isl_schedule *Schedule) {
211
0
  OS << polly::stringFromIslObj(Schedule);
212
0
  return OS;
213
0
}
214
215
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
216
0
                                     __isl_keep isl_space *Space) {
217
0
  OS << polly::stringFromIslObj(Space);
218
0
  return OS;
219
0
}
220
221
/// Combine Prefix, Val (or Number) and Suffix to an isl-compatible name.
222
///
223
/// In case @p UseInstructionNames is set, this function returns:
224
///
225
/// @p Prefix + "_" + @p Val->getName() + @p Suffix
226
///
227
/// otherwise
228
///
229
/// @p Prefix + to_string(Number) + @p Suffix
230
///
231
/// We ignore the value names by default, as they may change between release
232
/// and debug mode and can consequently not be used when aiming for reproducible
233
/// builds. However, for debugging named statements are often helpful, hence
234
/// we allow their optional use.
235
std::string getIslCompatibleName(const std::string &Prefix,
236
                                 const llvm::Value *Val, long Number,
237
                                 const std::string &Suffix,
238
                                 bool UseInstructionNames);
239
240
/// Combine Prefix, Name (or Number) and Suffix to an isl-compatible name.
241
///
242
/// In case @p UseInstructionNames is set, this function returns:
243
///
244
/// @p Prefix + "_" + Name + @p Suffix
245
///
246
/// otherwise
247
///
248
/// @p Prefix + to_string(Number) + @p Suffix
249
///
250
/// We ignore @p Name by default, as they may change between release
251
/// and debug mode and can consequently not be used when aiming for reproducible
252
/// builds. However, for debugging named statements are often helpful, hence
253
/// we allow their optional use.
254
std::string getIslCompatibleName(const std::string &Prefix,
255
                                 const std::string &Middle, long Number,
256
                                 const std::string &Suffix,
257
                                 bool UseInstructionNames);
258
259
std::string getIslCompatibleName(const std::string &Prefix,
260
                                 const std::string &Middle,
261
                                 const std::string &Suffix);
262
263
inline llvm::DiagnosticInfoOptimizationBase &
264
operator<<(llvm::DiagnosticInfoOptimizationBase &OS,
265
6
           const isl::union_map &Obj) {
266
6
  OS << Obj.to_str();
267
6
  return OS;
268
6
}
269
270
/// Scope guard for code that allows arbitrary isl function to return an error
271
/// if the max-operations quota exceeds.
272
///
273
/// This allows to opt-in code sections that have known long executions times.
274
/// code not in a hot path can continue to assume that no unexpected error
275
/// occurs.
276
///
277
/// This is typically used inside a nested IslMaxOperationsGuard scope. The
278
/// IslMaxOperationsGuard defines the number of allowed base operations for some
279
/// code, IslQuotaScope defines where it is allowed to return an error result.
280
class IslQuotaScope {
281
  isl_ctx *IslCtx;
282
  int OldOnError;
283
284
public:
285
1.13k
  IslQuotaScope() : IslCtx(nullptr) {}
286
  IslQuotaScope(const IslQuotaScope &) = delete;
287
  IslQuotaScope(IslQuotaScope &&Other)
288
0
      : IslCtx(Other.IslCtx), OldOnError(Other.OldOnError) {
289
0
    Other.IslCtx = nullptr;
290
0
  }
291
1.07k
  const IslQuotaScope &operator=(IslQuotaScope &&Other) {
292
1.07k
    std::swap(this->IslCtx, Other.IslCtx);
293
1.07k
    std::swap(this->OldOnError, Other.OldOnError);
294
1.07k
    return *this;
295
1.07k
  }
296
297
  /// Enter a quota-aware scope.
298
  ///
299
  /// Should not be used directly. Use IslMaxOperationsGuard::enter() instead.
300
  explicit IslQuotaScope(isl_ctx *IslCtx, unsigned long LocalMaxOps)
301
1.11k
      : IslCtx(IslCtx) {
302
1.11k
    assert(IslCtx);
303
1.11k
    assert(isl_ctx_get_max_operations(IslCtx) == 0 && "Incorrect nesting");
304
1.11k
    if (LocalMaxOps == 0) {
305
0
      this->IslCtx = nullptr;
306
0
      return;
307
0
    }
308
1.11k
309
1.11k
    OldOnError = isl_options_get_on_error(IslCtx);
310
1.11k
    isl_options_set_on_error(IslCtx, ISL_ON_ERROR_CONTINUE);
311
1.11k
    isl_ctx_reset_error(IslCtx);
312
1.11k
    isl_ctx_set_max_operations(IslCtx, LocalMaxOps);
313
1.11k
  }
314
315
2.25k
  ~IslQuotaScope() {
316
2.25k
    if (!IslCtx)
317
1.13k
      return;
318
1.11k
319
1.11k
    assert(isl_ctx_get_max_operations(IslCtx) > 0 && "Incorrect nesting");
320
1.11k
    assert(isl_options_get_on_error(IslCtx) == ISL_ON_ERROR_CONTINUE &&
321
1.11k
           "Incorrect nesting");
322
1.11k
    isl_ctx_set_max_operations(IslCtx, 0);
323
1.11k
    isl_options_set_on_error(IslCtx, OldOnError);
324
1.11k
  }
325
326
  /// Return whether the current quota has exceeded.
327
0
  bool hasQuotaExceeded() const {
328
0
    if (!IslCtx)
329
0
      return false;
330
0
331
0
    return isl_ctx_last_error(IslCtx) == isl_error_quota;
332
0
  }
333
};
334
335
/// Scoped limit of ISL operations.
336
///
337
/// Limits the number of ISL operations during the lifetime of this object. The
338
/// idea is to use this as an RAII guard for the scope where the code is aware
339
/// that ISL can return errors even when all input is valid. After leaving the
340
/// scope, it will return to the error setting as it was before. That also means
341
/// that the error setting should not be changed while in that scope.
342
///
343
/// Such scopes are not allowed to be nested because the previous operations
344
/// counter cannot be reset to the previous state, or one that adds the
345
/// operations while being in the nested scope. Use therefore is only allowed
346
/// while currently a no operations-limit is active.
347
class IslMaxOperationsGuard {
348
private:
349
  /// The ISL context to set the operations limit.
350
  ///
351
  /// If set to nullptr, there is no need for any action at the end of the
352
  /// scope.
353
  isl_ctx *IslCtx;
354
355
  /// Maximum number of operations for the scope.
356
  unsigned long LocalMaxOps;
357
358
  /// When AutoEnter is enabled, holds the IslQuotaScope object.
359
  IslQuotaScope TopLevelScope;
360
361
public:
362
  /// Enter a max operations scope.
363
  ///
364
  /// @param IslCtx      The ISL context to set the operations limit for.
365
  /// @param LocalMaxOps Maximum number of operations allowed in the
366
  ///                    scope. If set to zero, no operations limit is enforced.
367
  /// @param AutoEnter   If true, automatically enters an IslQuotaScope such
368
  ///                    that isl operations may return quota errors
369
  ///                    immediately. If false, only starts the operations
370
  ///                    counter, but isl does not return quota errors before
371
  ///                    calling enter().
372
  IslMaxOperationsGuard(isl_ctx *IslCtx, unsigned long LocalMaxOps,
373
                        bool AutoEnter = true)
374
1.07k
      : IslCtx(IslCtx), LocalMaxOps(LocalMaxOps) {
375
1.07k
    assert(IslCtx);
376
1.07k
    assert(isl_ctx_get_max_operations(IslCtx) == 0 &&
377
1.07k
           "Nested max operations not supported");
378
1.07k
379
1.07k
    // Users of this guard may check whether the last error was isl_error_quota.
380
1.07k
    // Reset the last error such that a previous out-of-quota error is not
381
1.07k
    // mistaken to have occurred in the in this quota, even if the max number of
382
1.07k
    // operations is set to infinite (LocalMaxOps == 0).
383
1.07k
    isl_ctx_reset_error(IslCtx);
384
1.07k
385
1.07k
    if (LocalMaxOps == 0) {
386
1
      // No limit on operations; also disable restoring on_error/max_operations.
387
1
      this->IslCtx = nullptr;
388
1
      return;
389
1
    }
390
1.07k
391
1.07k
    isl_ctx_reset_operations(IslCtx);
392
1.07k
    TopLevelScope = enter(AutoEnter);
393
1.07k
  }
394
395
  /// Enter a scope that can handle out-of-quota errors.
396
  ///
397
  /// @param AllowReturnNull Whether the scoped code can handle out-of-quota
398
  ///                        errors. If false, returns a dummy scope object that
399
  ///                        does nothing.
400
1.17k
  IslQuotaScope enter(bool AllowReturnNull = true) {
401
1.17k
    return AllowReturnNull && 
IslCtx1.11k
?
IslQuotaScope(IslCtx, LocalMaxOps)1.11k
402
1.17k
                                     : 
IslQuotaScope()62
;
403
1.17k
  }
404
405
  /// Return whether the current quota has exceeded.
406
124
  bool hasQuotaExceeded() const {
407
124
    if (!IslCtx)
408
0
      return false;
409
124
410
124
    return isl_ctx_last_error(IslCtx) == isl_error_quota;
411
124
  }
412
};
413
} // end namespace polly
414
415
#endif