1 | //===- ScopDetectionDiagnostic.h - Diagnostic for ScopDetection -*- C++ -*-===// |
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 | // Small set of diagnostic helper classes to encapsulate any errors occurred |
10 | // during the detection of Scops. |
11 | // |
12 | // The ScopDetection defines a set of error classes (via Statistic variables) |
13 | // that groups a number of individual errors into a group, e.g. non-affinity |
14 | // related errors. |
15 | // On error we generate an object that carries enough additional information |
16 | // to diagnose the error and generate a helpful error message. |
17 | // |
18 | //===----------------------------------------------------------------------===// |
19 | |
20 | #ifndef POLLY_SCOPDETECTIONDIAGNOSTIC_H |
21 | #define POLLY_SCOPDETECTIONDIAGNOSTIC_H |
22 | |
23 | #include "llvm/Analysis/LoopInfo.h" |
24 | #include "llvm/IR/DebugLoc.h" |
25 | #include "llvm/IR/Instruction.h" |
26 | #include <cstddef> |
27 | |
28 | namespace llvm { |
29 | class AliasSet; |
30 | class BasicBlock; |
31 | class ; |
32 | class Region; |
33 | class SCEV; |
34 | } // namespace llvm |
35 | |
36 | namespace polly { |
37 | using llvm::AliasSet; |
38 | using llvm::BasicBlock; |
39 | using llvm::DebugLoc; |
40 | using llvm::Instruction; |
41 | using llvm::Loop; |
42 | using llvm::OptimizationRemarkEmitter; |
43 | using llvm::raw_ostream; |
44 | using llvm::Region; |
45 | using llvm::SCEV; |
46 | using llvm::SmallVector; |
47 | using llvm::Value; |
48 | |
49 | /// Type to hold region delimiters (entry & exit block). |
50 | using BBPair = std::pair<BasicBlock *, BasicBlock *>; |
51 | |
52 | /// Return the region delimiters (entry & exit block) of @p R. |
53 | BBPair getBBPairForRegion(const Region *R); |
54 | |
55 | /// Set the begin and end source location for the region limited by @p P. |
56 | void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End); |
57 | |
58 | class RejectLog; |
59 | |
60 | /// Emit optimization remarks about the rejected regions to the user. |
61 | /// |
62 | /// This emits the content of the reject log as optimization remarks. |
63 | /// Remember to at least track failures (-polly-detect-track-failures). |
64 | /// @param P The region delimiters (entry & exit) we emit remarks for. |
65 | /// @param Log The error log containing all messages being emitted as remark. |
66 | void (const BBPair &P, const RejectLog &Log, |
67 | OptimizationRemarkEmitter &ORE); |
68 | |
69 | // Discriminator for LLVM-style RTTI (dyn_cast<> et al.) |
70 | enum class RejectReasonKind { |
71 | // CFG Category |
72 | CFG, |
73 | InvalidTerminator, |
74 | IrreducibleRegion, |
75 | UnreachableInExit, |
76 | IndirectPredecessor, |
77 | LastCFG, |
78 | |
79 | // Non-Affinity |
80 | AffFunc, |
81 | UndefCond, |
82 | InvalidCond, |
83 | UndefOperand, |
84 | NonAffBranch, |
85 | NoBasePtr, |
86 | UndefBasePtr, |
87 | VariantBasePtr, |
88 | NonAffineAccess, |
89 | DifferentElementSize, |
90 | LastAffFunc, |
91 | |
92 | LoopBound, |
93 | LoopHasNoExit, |
94 | LoopHasMultipleExits, |
95 | LoopOnlySomeLatches, |
96 | |
97 | FuncCall, |
98 | NonSimpleMemoryAccess, |
99 | |
100 | Alias, |
101 | |
102 | // Other |
103 | Other, |
104 | IntToPtr, |
105 | Alloca, |
106 | UnknownInst, |
107 | Entry, |
108 | Unprofitable, |
109 | LastOther |
110 | }; |
111 | |
112 | //===----------------------------------------------------------------------===// |
113 | /// Base class of all reject reasons found during Scop detection. |
114 | /// |
115 | /// Subclasses of RejectReason should provide means to capture enough |
116 | /// diagnostic information to help clients figure out what and where something |
117 | /// went wrong in the Scop detection. |
118 | class RejectReason { |
119 | private: |
120 | const RejectReasonKind Kind; |
121 | |
122 | protected: |
123 | static const DebugLoc Unknown; |
124 | |
125 | public: |
126 | RejectReason(RejectReasonKind K); |
127 | |
128 | virtual ~RejectReason() = default; |
129 | |
130 | RejectReasonKind getKind() const { return Kind; } |
131 | |
132 | /// Generate the remark name to identify this remark. |
133 | /// |
134 | /// @return A short string that identifies the error. |
135 | virtual std::string () const = 0; |
136 | |
137 | /// Get the Basic Block containing this remark. |
138 | /// |
139 | /// @return The Basic Block containing this remark. |
140 | virtual const Value *() const = 0; |
141 | |
142 | /// Generate a reasonable diagnostic message describing this error. |
143 | /// |
144 | /// @return A debug message representing this error. |
145 | virtual std::string getMessage() const = 0; |
146 | |
147 | /// Generate a message for the end-user describing this error. |
148 | /// |
149 | /// The message provided has to be suitable for the end-user. So it should |
150 | /// not reference any LLVM internal data structures or terminology. |
151 | /// Ideally, the message helps the end-user to increase the size of the |
152 | /// regions amenable to Polly. |
153 | /// |
154 | /// @return A short message representing this error. |
155 | virtual std::string getEndUserMessage() const { return "Unspecified error." ; } |
156 | |
157 | /// Get the source location of this error. |
158 | /// |
159 | /// @return The debug location for this error. |
160 | virtual const DebugLoc &getDebugLoc() const; |
161 | }; |
162 | |
163 | using RejectReasonPtr = std::shared_ptr<RejectReason>; |
164 | |
165 | /// Stores all errors that occurred during the detection. |
166 | class RejectLog final { |
167 | Region *R; |
168 | SmallVector<RejectReasonPtr, 1> ErrorReports; |
169 | |
170 | public: |
171 | explicit RejectLog(Region *R) : R(R) {} |
172 | |
173 | using iterator = SmallVector<RejectReasonPtr, 1>::const_iterator; |
174 | |
175 | iterator begin() const { return ErrorReports.begin(); } |
176 | iterator end() const { return ErrorReports.end(); } |
177 | size_t size() const { return ErrorReports.size(); } |
178 | |
179 | /// Returns true, if we store at least one error. |
180 | /// |
181 | /// @return true, if we store at least one error. |
182 | bool hasErrors() const { return size() > 0; } |
183 | |
184 | void print(raw_ostream &OS, int level = 0) const; |
185 | |
186 | const Region *region() const { return R; } |
187 | void report(RejectReasonPtr Reject) { ErrorReports.push_back(Elt: Reject); } |
188 | }; |
189 | |
190 | //===----------------------------------------------------------------------===// |
191 | /// Base class for CFG related reject reasons. |
192 | /// |
193 | /// Scop candidates that violate structural restrictions can be grouped under |
194 | /// this reject reason class. |
195 | class ReportCFG : public RejectReason { |
196 | public: |
197 | ReportCFG(const RejectReasonKind K); |
198 | |
199 | /// @name LLVM-RTTI interface |
200 | //@{ |
201 | static bool classof(const RejectReason *RR); |
202 | //@} |
203 | }; |
204 | |
205 | //===----------------------------------------------------------------------===// |
206 | /// Captures bad terminator within a Scop candidate. |
207 | class ReportInvalidTerminator final : public ReportCFG { |
208 | BasicBlock *BB; |
209 | |
210 | public: |
211 | ReportInvalidTerminator(BasicBlock *BB) |
212 | : ReportCFG(RejectReasonKind::InvalidTerminator), BB(BB) {} |
213 | |
214 | /// @name LLVM-RTTI interface |
215 | //@{ |
216 | static bool classof(const RejectReason *RR); |
217 | //@} |
218 | |
219 | /// @name RejectReason interface |
220 | //@{ |
221 | std::string () const override; |
222 | const Value *() const override; |
223 | std::string getMessage() const override; |
224 | const DebugLoc &getDebugLoc() const override; |
225 | //@} |
226 | }; |
227 | |
228 | //===----------------------------------------------------------------------===// |
229 | /// Captures irreducible regions in CFG. |
230 | class ReportIrreducibleRegion final : public ReportCFG { |
231 | Region *R; |
232 | DebugLoc DbgLoc; |
233 | |
234 | public: |
235 | ReportIrreducibleRegion(Region *R, DebugLoc DbgLoc) |
236 | : ReportCFG(RejectReasonKind::IrreducibleRegion), R(R), DbgLoc(DbgLoc) {} |
237 | |
238 | /// @name LLVM-RTTI interface |
239 | //@{ |
240 | static bool classof(const RejectReason *RR); |
241 | //@} |
242 | |
243 | /// @name RejectReason interface |
244 | //@{ |
245 | std::string () const override; |
246 | const Value *() const override; |
247 | std::string getMessage() const override; |
248 | std::string getEndUserMessage() const override; |
249 | const DebugLoc &getDebugLoc() const override; |
250 | //@} |
251 | }; |
252 | |
253 | //===----------------------------------------------------------------------===// |
254 | /// Captures regions with an unreachable in the exit block. |
255 | class ReportUnreachableInExit final : public ReportCFG { |
256 | BasicBlock *BB; |
257 | DebugLoc DbgLoc; |
258 | |
259 | public: |
260 | ReportUnreachableInExit(BasicBlock *BB, DebugLoc DbgLoc) |
261 | : ReportCFG(RejectReasonKind::UnreachableInExit), BB(BB), DbgLoc(DbgLoc) { |
262 | } |
263 | |
264 | /// @name LLVM-RTTI interface |
265 | //@{ |
266 | static bool classof(const RejectReason *RR); |
267 | //@} |
268 | |
269 | /// @name RejectReason interface |
270 | //@{ |
271 | std::string () const override; |
272 | const Value *() const override; |
273 | std::string getMessage() const override; |
274 | std::string getEndUserMessage() const override; |
275 | const DebugLoc &getDebugLoc() const override; |
276 | //@} |
277 | }; |
278 | |
279 | //===----------------------------------------------------------------------===// |
280 | /// Captures regions with an IndirectBr predecessor. |
281 | class ReportIndirectPredecessor final : public ReportCFG { |
282 | Instruction *Inst; |
283 | DebugLoc DbgLoc; |
284 | |
285 | public: |
286 | ReportIndirectPredecessor(Instruction *Inst, DebugLoc DbgLoc) |
287 | : ReportCFG(RejectReasonKind::IndirectPredecessor), Inst(Inst), |
288 | DbgLoc(DbgLoc) {} |
289 | |
290 | /// @name LLVM-RTTI interface |
291 | //@{ |
292 | static bool classof(const RejectReason *RR); |
293 | //@} |
294 | |
295 | /// @name RejectReason interface |
296 | //@{ |
297 | std::string () const override; |
298 | const Value *() const override; |
299 | std::string getMessage() const override; |
300 | std::string getEndUserMessage() const override; |
301 | const DebugLoc &getDebugLoc() const override; |
302 | //@} |
303 | }; |
304 | |
305 | //===----------------------------------------------------------------------===// |
306 | /// Base class for non-affine reject reasons. |
307 | /// |
308 | /// Scop candidates that violate restrictions to affinity are reported under |
309 | /// this class. |
310 | class ReportAffFunc : public RejectReason { |
311 | protected: |
312 | // The instruction that caused non-affinity to occur. |
313 | const Instruction *Inst; |
314 | |
315 | public: |
316 | ReportAffFunc(const RejectReasonKind K, const Instruction *Inst); |
317 | |
318 | /// @name LLVM-RTTI interface |
319 | //@{ |
320 | static bool classof(const RejectReason *RR); |
321 | //@} |
322 | |
323 | /// @name RejectReason interface |
324 | //@{ |
325 | const DebugLoc &getDebugLoc() const override { return Inst->getDebugLoc(); } |
326 | //@} |
327 | }; |
328 | |
329 | //===----------------------------------------------------------------------===// |
330 | /// Captures a condition that is based on an 'undef' value. |
331 | class ReportUndefCond final : public ReportAffFunc { |
332 | // The BasicBlock we found the broken condition in. |
333 | BasicBlock *BB; |
334 | |
335 | public: |
336 | ReportUndefCond(const Instruction *Inst, BasicBlock *BB) |
337 | : ReportAffFunc(RejectReasonKind::UndefCond, Inst), BB(BB) {} |
338 | |
339 | /// @name LLVM-RTTI interface |
340 | //@{ |
341 | static bool classof(const RejectReason *RR); |
342 | //@} |
343 | |
344 | /// @name RejectReason interface |
345 | //@{ |
346 | std::string () const override; |
347 | const Value *() const override; |
348 | std::string getMessage() const override; |
349 | //@} |
350 | }; |
351 | |
352 | //===----------------------------------------------------------------------===// |
353 | /// Captures an invalid condition |
354 | /// |
355 | /// Conditions have to be either constants or icmp instructions. |
356 | class ReportInvalidCond final : public ReportAffFunc { |
357 | // The BasicBlock we found the broken condition in. |
358 | BasicBlock *BB; |
359 | |
360 | public: |
361 | ReportInvalidCond(const Instruction *Inst, BasicBlock *BB) |
362 | : ReportAffFunc(RejectReasonKind::InvalidCond, Inst), BB(BB) {} |
363 | |
364 | /// @name LLVM-RTTI interface |
365 | //@{ |
366 | static bool classof(const RejectReason *RR); |
367 | //@} |
368 | |
369 | /// @name RejectReason interface |
370 | //@{ |
371 | std::string () const override; |
372 | const Value *() const override; |
373 | std::string getMessage() const override; |
374 | //@} |
375 | }; |
376 | |
377 | //===----------------------------------------------------------------------===// |
378 | /// Captures an undefined operand. |
379 | class ReportUndefOperand final : public ReportAffFunc { |
380 | // The BasicBlock we found the undefined operand in. |
381 | BasicBlock *BB; |
382 | |
383 | public: |
384 | ReportUndefOperand(BasicBlock *BB, const Instruction *Inst) |
385 | : ReportAffFunc(RejectReasonKind::UndefOperand, Inst), BB(BB) {} |
386 | |
387 | /// @name LLVM-RTTI interface |
388 | //@{ |
389 | static bool classof(const RejectReason *RR); |
390 | //@} |
391 | |
392 | /// @name RejectReason interface |
393 | //@{ |
394 | std::string getRemarkName() const override; |
395 | const Value *getRemarkBB() const override; |
396 | std::string getMessage() const override; |
397 | //@} |
398 | }; |
399 | |
400 | //===----------------------------------------------------------------------===// |
401 | /// Captures a non-affine branch. |
402 | class ReportNonAffBranch final : public ReportAffFunc { |
403 | // The BasicBlock we found the non-affine branch in. |
404 | BasicBlock *BB; |
405 | |
406 | /// LHS & RHS of the failed condition. |
407 | //@{ |
408 | const SCEV *LHS; |
409 | const SCEV *RHS; |
410 | //@} |
411 | |
412 | public: |
413 | ReportNonAffBranch(BasicBlock *BB, const SCEV *LHS, const SCEV *RHS, |
414 | const Instruction *Inst) |
415 | : ReportAffFunc(RejectReasonKind::NonAffBranch, Inst), BB(BB), LHS(LHS), |
416 | RHS(RHS) {} |
417 | |
418 | const SCEV *lhs() { return LHS; } |
419 | const SCEV *rhs() { return RHS; } |
420 | |
421 | /// @name LLVM-RTTI interface |
422 | //@{ |
423 | static bool classof(const RejectReason *RR); |
424 | //@} |
425 | |
426 | /// @name RejectReason interface |
427 | //@{ |
428 | std::string () const override; |
429 | const Value *() const override; |
430 | std::string getMessage() const override; |
431 | //@} |
432 | }; |
433 | |
434 | //===----------------------------------------------------------------------===// |
435 | /// Captures a missing base pointer. |
436 | class ReportNoBasePtr final : public ReportAffFunc { |
437 | public: |
438 | ReportNoBasePtr(const Instruction *Inst) |
439 | : ReportAffFunc(RejectReasonKind::NoBasePtr, Inst) {} |
440 | |
441 | /// @name LLVM-RTTI interface |
442 | //@{ |
443 | static bool classof(const RejectReason *RR); |
444 | //@} |
445 | |
446 | /// @name RejectReason interface |
447 | //@{ |
448 | std::string () const override; |
449 | const Value *() const override; |
450 | std::string getMessage() const override; |
451 | //@} |
452 | }; |
453 | |
454 | //===----------------------------------------------------------------------===// |
455 | /// Captures an undefined base pointer. |
456 | class ReportUndefBasePtr final : public ReportAffFunc { |
457 | public: |
458 | ReportUndefBasePtr(const Instruction *Inst) |
459 | : ReportAffFunc(RejectReasonKind::UndefBasePtr, Inst) {} |
460 | |
461 | /// @name LLVM-RTTI interface |
462 | //@{ |
463 | static bool classof(const RejectReason *RR); |
464 | //@} |
465 | |
466 | /// @name RejectReason interface |
467 | //@{ |
468 | std::string () const override; |
469 | const Value *() const override; |
470 | std::string getMessage() const override; |
471 | //@} |
472 | }; |
473 | |
474 | //===----------------------------------------------------------------------===// |
475 | /// Captures a base pointer that is not invariant in the region. |
476 | class ReportVariantBasePtr final : public ReportAffFunc { |
477 | // The variant base pointer. |
478 | Value *BaseValue; |
479 | |
480 | public: |
481 | ReportVariantBasePtr(Value *BaseValue, const Instruction *Inst) |
482 | : ReportAffFunc(RejectReasonKind::VariantBasePtr, Inst), |
483 | BaseValue(BaseValue) {} |
484 | |
485 | /// @name LLVM-RTTI interface |
486 | //@{ |
487 | static bool classof(const RejectReason *RR); |
488 | //@} |
489 | |
490 | /// @name RejectReason interface |
491 | //@{ |
492 | std::string () const override; |
493 | const Value *() const override; |
494 | std::string getMessage() const override; |
495 | std::string getEndUserMessage() const override; |
496 | //@} |
497 | }; |
498 | |
499 | //===----------------------------------------------------------------------===// |
500 | /// Captures a non-affine access function. |
501 | class ReportNonAffineAccess final : public ReportAffFunc { |
502 | // The non-affine access function. |
503 | const SCEV *AccessFunction; |
504 | |
505 | // The base pointer of the memory access. |
506 | const Value *BaseValue; |
507 | |
508 | public: |
509 | ReportNonAffineAccess(const SCEV *AccessFunction, const Instruction *Inst, |
510 | const Value *V) |
511 | : ReportAffFunc(RejectReasonKind::NonAffineAccess, Inst), |
512 | AccessFunction(AccessFunction), BaseValue(V) {} |
513 | |
514 | const SCEV *get() { return AccessFunction; } |
515 | |
516 | /// @name LLVM-RTTI interface |
517 | //@{ |
518 | static bool classof(const RejectReason *RR); |
519 | //@} |
520 | |
521 | /// @name RejectReason interface |
522 | //@{ |
523 | std::string () const override; |
524 | const Value *() const override; |
525 | std::string getMessage() const override; |
526 | std::string getEndUserMessage() const override; |
527 | //@} |
528 | }; |
529 | |
530 | //===----------------------------------------------------------------------===// |
531 | /// Report array accesses with differing element size. |
532 | class ReportDifferentArrayElementSize final : public ReportAffFunc { |
533 | // The base pointer of the memory access. |
534 | const Value *BaseValue; |
535 | |
536 | public: |
537 | ReportDifferentArrayElementSize(const Instruction *Inst, const Value *V) |
538 | : ReportAffFunc(RejectReasonKind::DifferentElementSize, Inst), |
539 | BaseValue(V) {} |
540 | |
541 | /// @name LLVM-RTTI interface |
542 | //@{ |
543 | static bool classof(const RejectReason *RR); |
544 | //@} |
545 | |
546 | /// @name RejectReason interface |
547 | //@{ |
548 | std::string () const override; |
549 | const Value *() const override; |
550 | std::string getMessage() const override; |
551 | std::string getEndUserMessage() const override; |
552 | //@} |
553 | }; |
554 | |
555 | //===----------------------------------------------------------------------===// |
556 | /// Captures errors with non affine loop bounds. |
557 | class ReportLoopBound final : public RejectReason { |
558 | // The offending loop. |
559 | Loop *L; |
560 | |
561 | // The non-affine loop bound. |
562 | const SCEV *LoopCount; |
563 | |
564 | // A copy of the offending loop's debug location. |
565 | const DebugLoc Loc; |
566 | |
567 | public: |
568 | ReportLoopBound(Loop *L, const SCEV *LoopCount); |
569 | |
570 | const SCEV *loopCount() { return LoopCount; } |
571 | |
572 | /// @name LLVM-RTTI interface |
573 | //@{ |
574 | static bool classof(const RejectReason *RR); |
575 | //@} |
576 | |
577 | /// @name RejectReason interface |
578 | //@{ |
579 | std::string () const override; |
580 | const Value *() const override; |
581 | std::string getMessage() const override; |
582 | const DebugLoc &getDebugLoc() const override; |
583 | std::string getEndUserMessage() const override; |
584 | //@} |
585 | }; |
586 | |
587 | //===----------------------------------------------------------------------===// |
588 | /// Captures errors when loop has no exit. |
589 | class ReportLoopHasNoExit final : public RejectReason { |
590 | /// The loop that has no exit. |
591 | Loop *L; |
592 | |
593 | const DebugLoc Loc; |
594 | |
595 | public: |
596 | ReportLoopHasNoExit(Loop *L) |
597 | : RejectReason(RejectReasonKind::LoopHasNoExit), L(L), |
598 | Loc(L->getStartLoc()) {} |
599 | |
600 | /// @name LLVM-RTTI interface |
601 | //@{ |
602 | static bool classof(const RejectReason *RR); |
603 | //@} |
604 | |
605 | /// @name RejectReason interface |
606 | //@{ |
607 | std::string () const override; |
608 | const Value *() const override; |
609 | std::string getMessage() const override; |
610 | const DebugLoc &getDebugLoc() const override; |
611 | std::string getEndUserMessage() const override; |
612 | //@} |
613 | }; |
614 | |
615 | //===----------------------------------------------------------------------===// |
616 | /// Captures errors when a loop has multiple exists. |
617 | class ReportLoopHasMultipleExits final : public RejectReason { |
618 | /// The loop that has multiple exits. |
619 | Loop *L; |
620 | |
621 | const DebugLoc Loc; |
622 | |
623 | public: |
624 | ReportLoopHasMultipleExits(Loop *L) |
625 | : RejectReason(RejectReasonKind::LoopHasMultipleExits), L(L), |
626 | Loc(L->getStartLoc()) {} |
627 | |
628 | /// @name LLVM-RTTI interface |
629 | //@{ |
630 | static bool classof(const RejectReason *RR); |
631 | //@} |
632 | |
633 | /// @name RejectReason interface |
634 | //@{ |
635 | std::string () const override; |
636 | const Value *() const override; |
637 | std::string getMessage() const override; |
638 | const DebugLoc &getDebugLoc() const override; |
639 | std::string getEndUserMessage() const override; |
640 | //@} |
641 | }; |
642 | |
643 | //===----------------------------------------------------------------------===// |
644 | /// Captures errors when not all loop latches are part of the scop. |
645 | class ReportLoopOnlySomeLatches final : public RejectReason { |
646 | /// The loop for which not all loop latches are part of the scop. |
647 | Loop *L; |
648 | |
649 | const DebugLoc Loc; |
650 | |
651 | public: |
652 | ReportLoopOnlySomeLatches(Loop *L) |
653 | : RejectReason(RejectReasonKind::LoopOnlySomeLatches), L(L), |
654 | Loc(L->getStartLoc()) {} |
655 | |
656 | /// @name LLVM-RTTI interface |
657 | //@{ |
658 | static bool classof(const RejectReason *RR); |
659 | //@} |
660 | |
661 | /// @name RejectReason interface |
662 | //@{ |
663 | std::string () const override; |
664 | const Value *() const override; |
665 | std::string getMessage() const override; |
666 | const DebugLoc &getDebugLoc() const override; |
667 | std::string getEndUserMessage() const override; |
668 | //@} |
669 | }; |
670 | |
671 | //===----------------------------------------------------------------------===// |
672 | /// Captures errors with non-side-effect-known function calls. |
673 | class ReportFuncCall final : public RejectReason { |
674 | // The offending call instruction. |
675 | Instruction *Inst; |
676 | |
677 | public: |
678 | ReportFuncCall(Instruction *Inst); |
679 | |
680 | /// @name LLVM-RTTI interface |
681 | //@{ |
682 | static bool classof(const RejectReason *RR); |
683 | //@} |
684 | |
685 | /// @name RejectReason interface |
686 | //@{ |
687 | std::string () const override; |
688 | const Value *() const override; |
689 | std::string getMessage() const override; |
690 | const DebugLoc &getDebugLoc() const override; |
691 | std::string getEndUserMessage() const override; |
692 | //@} |
693 | }; |
694 | |
695 | //===----------------------------------------------------------------------===// |
696 | /// Captures errors with aliasing. |
697 | class ReportAlias final : public RejectReason { |
698 | public: |
699 | using PointerSnapshotTy = std::vector<const Value *>; |
700 | |
701 | private: |
702 | /// Format an invalid alias set. |
703 | /// |
704 | // @param Prefix A prefix string to put before the list of aliasing pointers. |
705 | // @param Suffix A suffix string to put after the list of aliasing pointers. |
706 | std::string formatInvalidAlias(std::string Prefix = "" , |
707 | std::string Suffix = "" ) const; |
708 | |
709 | Instruction *Inst; |
710 | |
711 | // A snapshot of the llvm values that took part in the aliasing error. |
712 | mutable PointerSnapshotTy Pointers; |
713 | |
714 | public: |
715 | ReportAlias(Instruction *Inst, AliasSet &AS); |
716 | |
717 | const PointerSnapshotTy &getPointers() const { return Pointers; } |
718 | |
719 | /// @name LLVM-RTTI interface |
720 | //@{ |
721 | static bool classof(const RejectReason *RR); |
722 | //@} |
723 | |
724 | /// @name RejectReason interface |
725 | //@{ |
726 | std::string () const override; |
727 | const Value *() const override; |
728 | std::string getMessage() const override; |
729 | const DebugLoc &getDebugLoc() const override; |
730 | std::string getEndUserMessage() const override; |
731 | //@} |
732 | }; |
733 | |
734 | //===----------------------------------------------------------------------===// |
735 | /// Base class for otherwise ungrouped reject reasons. |
736 | class ReportOther : public RejectReason { |
737 | public: |
738 | ReportOther(const RejectReasonKind K); |
739 | |
740 | /// @name LLVM-RTTI interface |
741 | //@{ |
742 | static bool classof(const RejectReason *RR); |
743 | //@} |
744 | |
745 | /// @name RejectReason interface |
746 | //@{ |
747 | std::string () const override; |
748 | std::string getMessage() const override; |
749 | //@} |
750 | }; |
751 | |
752 | //===----------------------------------------------------------------------===// |
753 | /// Captures errors with bad IntToPtr instructions. |
754 | class ReportIntToPtr final : public ReportOther { |
755 | // The offending base value. |
756 | Instruction *BaseValue; |
757 | |
758 | public: |
759 | ReportIntToPtr(Instruction *BaseValue); |
760 | |
761 | /// @name LLVM-RTTI interface |
762 | //@{ |
763 | static bool classof(const RejectReason *RR); |
764 | //@} |
765 | |
766 | /// @name RejectReason interface |
767 | //@{ |
768 | std::string () const override; |
769 | const Value *() const override; |
770 | std::string getMessage() const override; |
771 | const DebugLoc &getDebugLoc() const override; |
772 | //@} |
773 | }; |
774 | |
775 | //===----------------------------------------------------------------------===// |
776 | /// Captures errors with alloca instructions. |
777 | class ReportAlloca final : public ReportOther { |
778 | Instruction *Inst; |
779 | |
780 | public: |
781 | ReportAlloca(Instruction *Inst); |
782 | |
783 | /// @name LLVM-RTTI interface |
784 | //@{ |
785 | static bool classof(const RejectReason *RR); |
786 | //@} |
787 | |
788 | /// @name RejectReason interface |
789 | //@{ |
790 | std::string () const override; |
791 | const Value *() const override; |
792 | std::string getMessage() const override; |
793 | const DebugLoc &getDebugLoc() const override; |
794 | //@} |
795 | }; |
796 | |
797 | //===----------------------------------------------------------------------===// |
798 | /// Captures errors with unknown instructions. |
799 | class ReportUnknownInst final : public ReportOther { |
800 | Instruction *Inst; |
801 | |
802 | public: |
803 | ReportUnknownInst(Instruction *Inst); |
804 | |
805 | /// @name LLVM-RTTI interface |
806 | //@{ |
807 | static bool classof(const RejectReason *RR); |
808 | //@} |
809 | |
810 | /// @name RejectReason interface |
811 | //@{ |
812 | std::string () const override; |
813 | const Value *() const override; |
814 | std::string getMessage() const override; |
815 | const DebugLoc &getDebugLoc() const override; |
816 | //@} |
817 | }; |
818 | |
819 | //===----------------------------------------------------------------------===// |
820 | /// Captures errors with regions containing the function entry block. |
821 | class ReportEntry final : public ReportOther { |
822 | BasicBlock *BB; |
823 | |
824 | public: |
825 | ReportEntry(BasicBlock *BB); |
826 | |
827 | /// @name LLVM-RTTI interface |
828 | //@{ |
829 | static bool classof(const RejectReason *RR); |
830 | //@} |
831 | |
832 | /// @name RejectReason interface |
833 | //@{ |
834 | std::string () const override; |
835 | const Value *() const override; |
836 | std::string getMessage() const override; |
837 | std::string getEndUserMessage() const override; |
838 | const DebugLoc &getDebugLoc() const override; |
839 | //@} |
840 | }; |
841 | |
842 | //===----------------------------------------------------------------------===// |
843 | /// Report regions that seem not profitable to be optimized. |
844 | class ReportUnprofitable final : public ReportOther { |
845 | Region *R; |
846 | |
847 | public: |
848 | ReportUnprofitable(Region *R); |
849 | |
850 | /// @name LLVM-RTTI interface |
851 | //@{ |
852 | static bool classof(const RejectReason *RR); |
853 | //@} |
854 | |
855 | /// @name RejectReason interface |
856 | //@{ |
857 | std::string () const override; |
858 | const Value *() const override; |
859 | std::string getMessage() const override; |
860 | std::string getEndUserMessage() const override; |
861 | const DebugLoc &getDebugLoc() const override; |
862 | //@} |
863 | }; |
864 | |
865 | //===----------------------------------------------------------------------===// |
866 | /// Captures errors with non-simple memory accesses. |
867 | class ReportNonSimpleMemoryAccess final : public ReportOther { |
868 | // The offending call instruction. |
869 | Instruction *Inst; |
870 | |
871 | public: |
872 | ReportNonSimpleMemoryAccess(Instruction *Inst); |
873 | |
874 | /// @name LLVM-RTTI interface |
875 | //@{ |
876 | static bool classof(const RejectReason *RR); |
877 | //@} |
878 | |
879 | /// @name RejectReason interface |
880 | //@{ |
881 | std::string () const override; |
882 | const Value *() const override; |
883 | std::string getMessage() const override; |
884 | const DebugLoc &getDebugLoc() const override; |
885 | std::string getEndUserMessage() const override; |
886 | //@} |
887 | }; |
888 | } // namespace polly |
889 | |
890 | #endif // POLLY_SCOPDETECTIONDIAGNOSTIC_H |
891 | |