Coverage Report

Created: 2019-02-23 12:57

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