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 |