1 | //===- ScopDetectionDiagnostic.cpp - Error diagnostics --------------------===// |
---|---|
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 | #include "polly/ScopDetectionDiagnostic.h" |
21 | #include "llvm/ADT/SmallPtrSet.h" |
22 | #include "llvm/ADT/SmallVector.h" |
23 | #include "llvm/ADT/Statistic.h" |
24 | #include "llvm/ADT/StringRef.h" |
25 | #include "llvm/ADT/Twine.h" |
26 | #include "llvm/Analysis/AliasSetTracker.h" |
27 | #include "llvm/Analysis/LoopInfo.h" |
28 | #include "llvm/Analysis/OptimizationRemarkEmitter.h" |
29 | #include "llvm/Analysis/RegionInfo.h" |
30 | #include "llvm/Analysis/ScalarEvolution.h" |
31 | #include "llvm/IR/BasicBlock.h" |
32 | #include "llvm/IR/CFG.h" |
33 | #include "llvm/IR/DebugLoc.h" |
34 | #include "llvm/IR/DiagnosticInfo.h" |
35 | #include "llvm/IR/Instruction.h" |
36 | #include "llvm/IR/Value.h" |
37 | #include "llvm/Support/raw_ostream.h" |
38 | #include <algorithm> |
39 | #include <cassert> |
40 | #include <string> |
41 | #include <utility> |
42 | |
43 | using namespace llvm; |
44 | |
45 | #define DEBUG_TYPE "polly-detect" |
46 | |
47 | #define SCOP_STAT(NAME, DESC) \ |
48 | {"polly-detect", "NAME", "Number of rejected regions: " DESC} |
49 | |
50 | static Statistic RejectStatistics[] = { |
51 | SCOP_STAT(CFG, ""), |
52 | SCOP_STAT(InvalidTerminator, "Unsupported terminator instruction"), |
53 | SCOP_STAT(IrreducibleRegion, "Irreducible loops"), |
54 | SCOP_STAT(UnreachableInExit, "Unreachable in exit block"), |
55 | SCOP_STAT(IndirectPredecessor, "Branch from indirect terminator"), |
56 | SCOP_STAT(LastCFG, ""), |
57 | SCOP_STAT(AffFunc, ""), |
58 | SCOP_STAT(UndefCond, "Undefined branch condition"), |
59 | SCOP_STAT(InvalidCond, "Non-integer branch condition"), |
60 | SCOP_STAT(UndefOperand, "Undefined operands in comparison"), |
61 | SCOP_STAT(NonAffBranch, "Non-affine branch condition"), |
62 | SCOP_STAT(NoBasePtr, "No base pointer"), |
63 | SCOP_STAT(UndefBasePtr, "Undefined base pointer"), |
64 | SCOP_STAT(VariantBasePtr, "Variant base pointer"), |
65 | SCOP_STAT(NonAffineAccess, "Non-affine memory accesses"), |
66 | SCOP_STAT(DifferentElementSize, "Accesses with differing sizes"), |
67 | SCOP_STAT(LastAffFunc, ""), |
68 | SCOP_STAT(LoopBound, "Uncomputable loop bounds"), |
69 | SCOP_STAT(LoopHasNoExit, "Loop without exit"), |
70 | SCOP_STAT(LoopHasMultipleExits, "Loop with multiple exits"), |
71 | SCOP_STAT(LoopOnlySomeLatches, "Not all loop latches in scop"), |
72 | SCOP_STAT(FuncCall, "Function call with side effects"), |
73 | SCOP_STAT(NonSimpleMemoryAccess, |
74 | "Complicated access semantics (volatile or atomic)"), |
75 | SCOP_STAT(Alias, "Base address aliasing"), |
76 | SCOP_STAT(Other, ""), |
77 | SCOP_STAT(IntToPtr, "Integer to pointer conversions"), |
78 | SCOP_STAT(Alloca, "Stack allocations"), |
79 | SCOP_STAT(UnknownInst, "Unknown Instructions"), |
80 | SCOP_STAT(Entry, "Contains entry block"), |
81 | SCOP_STAT(Unprofitable, "Assumed to be unprofitable"), |
82 | SCOP_STAT(LastOther, ""), |
83 | }; |
84 | |
85 | namespace polly { |
86 | |
87 | /// Small string conversion via raw_string_stream. |
88 | template <typename T> std::string operator+(Twine LHS, const T &RHS) { |
89 | std::string Buf; |
90 | raw_string_ostream fmt(Buf); |
91 | fmt << RHS; |
92 | |
93 | return LHS.concat(Suffix: Buf).str(); |
94 | } |
95 | } // namespace polly |
96 | |
97 | namespace llvm { |
98 | |
99 | // Lexicographic order on (line, col) of our debug locations. |
100 | static bool operator<(const DebugLoc &LHS, const DebugLoc &RHS) { |
101 | return LHS.getLine() < RHS.getLine() || |
102 | (LHS.getLine() == RHS.getLine() && LHS.getCol() < RHS.getCol()); |
103 | } |
104 | } // namespace llvm |
105 | |
106 | namespace polly { |
107 | |
108 | BBPair getBBPairForRegion(const Region *R) { |
109 | return std::make_pair(x: R->getEntry(), y: R->getExit()); |
110 | } |
111 | |
112 | void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End) { |
113 | SmallPtrSet<BasicBlock *, 32> Seen; |
114 | SmallVector<BasicBlock *, 32> Todo; |
115 | Todo.push_back(Elt: P.first); |
116 | while (!Todo.empty()) { |
117 | auto *BB = Todo.pop_back_val(); |
118 | if (BB == P.second) |
119 | continue; |
120 | if (!Seen.insert(Ptr: BB).second) |
121 | continue; |
122 | Todo.append(in_start: succ_begin(BB), in_end: succ_end(BB)); |
123 | for (const Instruction &Inst : *BB) { |
124 | DebugLoc DL = Inst.getStableDebugLoc(); |
125 | if (!DL) |
126 | continue; |
127 | |
128 | Begin = Begin ? std::min(a: Begin, b: DL) : DL; |
129 | End = End ? std::max(a: End, b: DL) : DL; |
130 | } |
131 | } |
132 | } |
133 | |
134 | void emitRejectionRemarks(const BBPair &P, const RejectLog &Log, |
135 | OptimizationRemarkEmitter &ORE) { |
136 | DebugLoc Begin, End; |
137 | getDebugLocations(P, Begin, End); |
138 | |
139 | ORE.emit( |
140 | OptDiag: OptimizationRemarkMissed(DEBUG_TYPE, "RejectionErrors", Begin, P.first) |
141 | << "The following errors keep this region from being a Scop."); |
142 | |
143 | for (RejectReasonPtr RR : Log) { |
144 | |
145 | if (const DebugLoc &Loc = RR->getDebugLoc()) |
146 | ORE.emit(OptDiag: OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Loc, |
147 | RR->getRemarkBB()) |
148 | << RR->getEndUserMessage()); |
149 | else |
150 | ORE.emit(OptDiag: OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Begin, |
151 | RR->getRemarkBB()) |
152 | << RR->getEndUserMessage()); |
153 | } |
154 | |
155 | /* Check to see if Region is a top level region, getExit = NULL*/ |
156 | if (P.second) |
157 | ORE.emit( |
158 | OptDiag: OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.second) |
159 | << "Invalid Scop candidate ends here."); |
160 | else |
161 | ORE.emit( |
162 | OptDiag: OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.first) |
163 | << "Invalid Scop candidate ends here."); |
164 | } |
165 | |
166 | //===----------------------------------------------------------------------===// |
167 | // RejectReason. |
168 | |
169 | RejectReason::RejectReason(RejectReasonKind K) : Kind(K) { |
170 | RejectStatistics[static_cast<int>(K)]++; |
171 | } |
172 | |
173 | const DebugLoc RejectReason::Unknown = DebugLoc(); |
174 | |
175 | const DebugLoc &RejectReason::getDebugLoc() const { |
176 | // Allocate an empty DebugLoc and return it a reference to it. |
177 | return Unknown; |
178 | } |
179 | |
180 | // RejectLog. |
181 | void RejectLog::print(raw_ostream &OS, int level) const { |
182 | int j = 0; |
183 | for (auto Reason : ErrorReports) |
184 | OS.indent(NumSpaces: level) << "["<< j++ << "] "<< Reason->getMessage() << "\n"; |
185 | } |
186 | |
187 | //===----------------------------------------------------------------------===// |
188 | // ReportCFG. |
189 | |
190 | ReportCFG::ReportCFG(const RejectReasonKind K) : RejectReason(K) {} |
191 | |
192 | bool ReportCFG::classof(const RejectReason *RR) { |
193 | return RR->getKind() >= RejectReasonKind::CFG && |
194 | RR->getKind() <= RejectReasonKind::LastCFG; |
195 | } |
196 | |
197 | //===----------------------------------------------------------------------===// |
198 | // ReportInvalidTerminator. |
199 | |
200 | std::string ReportInvalidTerminator::getRemarkName() const { |
201 | return "InvalidTerminator"; |
202 | } |
203 | |
204 | const BasicBlock *ReportInvalidTerminator::getRemarkBB() const { return BB; } |
205 | |
206 | std::string ReportInvalidTerminator::getMessage() const { |
207 | return ("Invalid instruction terminates BB: "+ BB->getName()).str(); |
208 | } |
209 | |
210 | const DebugLoc &ReportInvalidTerminator::getDebugLoc() const { |
211 | return BB->getTerminator()->getDebugLoc(); |
212 | } |
213 | |
214 | bool ReportInvalidTerminator::classof(const RejectReason *RR) { |
215 | return RR->getKind() == RejectReasonKind::InvalidTerminator; |
216 | } |
217 | |
218 | //===----------------------------------------------------------------------===// |
219 | // UnreachableInExit. |
220 | |
221 | std::string ReportUnreachableInExit::getRemarkName() const { |
222 | return "UnreachableInExit"; |
223 | } |
224 | |
225 | const BasicBlock *ReportUnreachableInExit::getRemarkBB() const { return BB; } |
226 | |
227 | std::string ReportUnreachableInExit::getMessage() const { |
228 | std::string BBName = BB->getName().str(); |
229 | return "Unreachable in exit block"+ BBName; |
230 | } |
231 | |
232 | const DebugLoc &ReportUnreachableInExit::getDebugLoc() const { return DbgLoc; } |
233 | |
234 | std::string ReportUnreachableInExit::getEndUserMessage() const { |
235 | return "Unreachable in exit block."; |
236 | } |
237 | |
238 | bool ReportUnreachableInExit::classof(const RejectReason *RR) { |
239 | return RR->getKind() == RejectReasonKind::UnreachableInExit; |
240 | } |
241 | |
242 | //===----------------------------------------------------------------------===// |
243 | // IndirectPredecessor. |
244 | |
245 | std::string ReportIndirectPredecessor::getRemarkName() const { |
246 | return "IndirectPredecessor"; |
247 | } |
248 | |
249 | const BasicBlock *ReportIndirectPredecessor::getRemarkBB() const { |
250 | if (Inst) |
251 | return Inst->getParent(); |
252 | return nullptr; |
253 | } |
254 | |
255 | std::string ReportIndirectPredecessor::getMessage() const { |
256 | if (Inst) |
257 | return "Branch from indirect terminator: "+ *Inst; |
258 | return getEndUserMessage(); |
259 | } |
260 | |
261 | const DebugLoc &ReportIndirectPredecessor::getDebugLoc() const { |
262 | return DbgLoc; |
263 | } |
264 | |
265 | std::string ReportIndirectPredecessor::getEndUserMessage() const { |
266 | return "Branch from indirect terminator."; |
267 | } |
268 | |
269 | bool ReportIndirectPredecessor::classof(const RejectReason *RR) { |
270 | return RR->getKind() == RejectReasonKind::IndirectPredecessor; |
271 | } |
272 | |
273 | //===----------------------------------------------------------------------===// |
274 | // ReportIrreducibleRegion. |
275 | |
276 | std::string ReportIrreducibleRegion::getRemarkName() const { |
277 | return "IrreducibleRegion"; |
278 | } |
279 | |
280 | const BasicBlock *ReportIrreducibleRegion::getRemarkBB() const { |
281 | return R->getEntry(); |
282 | } |
283 | |
284 | std::string ReportIrreducibleRegion::getMessage() const { |
285 | return "Irreducible region encountered: "+ R->getNameStr(); |
286 | } |
287 | |
288 | const DebugLoc &ReportIrreducibleRegion::getDebugLoc() const { return DbgLoc; } |
289 | |
290 | std::string ReportIrreducibleRegion::getEndUserMessage() const { |
291 | return "Irreducible region encountered in control flow."; |
292 | } |
293 | |
294 | bool ReportIrreducibleRegion::classof(const RejectReason *RR) { |
295 | return RR->getKind() == RejectReasonKind::IrreducibleRegion; |
296 | } |
297 | |
298 | //===----------------------------------------------------------------------===// |
299 | // ReportAffFunc. |
300 | |
301 | ReportAffFunc::ReportAffFunc(const RejectReasonKind K, const Instruction *Inst) |
302 | : RejectReason(K), Inst(Inst) {} |
303 | |
304 | bool ReportAffFunc::classof(const RejectReason *RR) { |
305 | return RR->getKind() >= RejectReasonKind::AffFunc && |
306 | RR->getKind() <= RejectReasonKind::LastAffFunc; |
307 | } |
308 | |
309 | //===----------------------------------------------------------------------===// |
310 | // ReportUndefCond. |
311 | |
312 | std::string ReportUndefCond::getRemarkName() const { return "UndefCond"; } |
313 | |
314 | const BasicBlock *ReportUndefCond::getRemarkBB() const { return BB; } |
315 | |
316 | std::string ReportUndefCond::getMessage() const { |
317 | return ("Condition based on 'undef' value in BB: "+ BB->getName()).str(); |
318 | } |
319 | |
320 | bool ReportUndefCond::classof(const RejectReason *RR) { |
321 | return RR->getKind() == RejectReasonKind::UndefCond; |
322 | } |
323 | |
324 | //===----------------------------------------------------------------------===// |
325 | // ReportInvalidCond. |
326 | |
327 | std::string ReportInvalidCond::getRemarkName() const { return "InvalidCond"; } |
328 | |
329 | const BasicBlock *ReportInvalidCond::getRemarkBB() const { return BB; } |
330 | |
331 | std::string ReportInvalidCond::getMessage() const { |
332 | return ("Condition in BB '"+ BB->getName()).str() + |
333 | "' neither constant nor an icmp instruction"; |
334 | } |
335 | |
336 | bool ReportInvalidCond::classof(const RejectReason *RR) { |
337 | return RR->getKind() == RejectReasonKind::InvalidCond; |
338 | } |
339 | |
340 | //===----------------------------------------------------------------------===// |
341 | // ReportUndefOperand. |
342 | |
343 | std::string ReportUndefOperand::getRemarkName() const { return "UndefOperand"; } |
344 | |
345 | const BasicBlock *ReportUndefOperand::getRemarkBB() const { return BB; } |
346 | |
347 | std::string ReportUndefOperand::getMessage() const { |
348 | return ("undef operand in branch at BB: "+ BB->getName()).str(); |
349 | } |
350 | |
351 | bool ReportUndefOperand::classof(const RejectReason *RR) { |
352 | return RR->getKind() == RejectReasonKind::UndefOperand; |
353 | } |
354 | |
355 | //===----------------------------------------------------------------------===// |
356 | // ReportNonAffBranch. |
357 | |
358 | std::string ReportNonAffBranch::getRemarkName() const { return "NonAffBranch"; } |
359 | |
360 | const BasicBlock *ReportNonAffBranch::getRemarkBB() const { return BB; } |
361 | |
362 | std::string ReportNonAffBranch::getMessage() const { |
363 | return ("Non affine branch in BB '"+ BB->getName()).str() + |
364 | "' with LHS: "+ *LHS + " and RHS: "+ *RHS; |
365 | } |
366 | |
367 | bool ReportNonAffBranch::classof(const RejectReason *RR) { |
368 | return RR->getKind() == RejectReasonKind::NonAffBranch; |
369 | } |
370 | |
371 | //===----------------------------------------------------------------------===// |
372 | // ReportNoBasePtr. |
373 | |
374 | std::string ReportNoBasePtr::getRemarkName() const { return "NoBasePtr"; } |
375 | |
376 | const BasicBlock *ReportNoBasePtr::getRemarkBB() const { |
377 | return Inst->getParent(); |
378 | } |
379 | |
380 | std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; } |
381 | |
382 | bool ReportNoBasePtr::classof(const RejectReason *RR) { |
383 | return RR->getKind() == RejectReasonKind::NoBasePtr; |
384 | } |
385 | |
386 | //===----------------------------------------------------------------------===// |
387 | // ReportUndefBasePtr. |
388 | |
389 | std::string ReportUndefBasePtr::getRemarkName() const { return "UndefBasePtr"; } |
390 | |
391 | const BasicBlock *ReportUndefBasePtr::getRemarkBB() const { |
392 | return Inst->getParent(); |
393 | } |
394 | |
395 | std::string ReportUndefBasePtr::getMessage() const { |
396 | return "Undefined base pointer"; |
397 | } |
398 | |
399 | bool ReportUndefBasePtr::classof(const RejectReason *RR) { |
400 | return RR->getKind() == RejectReasonKind::UndefBasePtr; |
401 | } |
402 | |
403 | //===----------------------------------------------------------------------===// |
404 | // ReportVariantBasePtr. |
405 | |
406 | std::string ReportVariantBasePtr::getRemarkName() const { |
407 | return "VariantBasePtr"; |
408 | } |
409 | |
410 | const BasicBlock *ReportVariantBasePtr::getRemarkBB() const { |
411 | return Inst->getParent(); |
412 | } |
413 | |
414 | std::string ReportVariantBasePtr::getMessage() const { |
415 | return "Base address not invariant in current region:"+ *BaseValue; |
416 | } |
417 | |
418 | std::string ReportVariantBasePtr::getEndUserMessage() const { |
419 | return "The base address of this array is not invariant inside the loop"; |
420 | } |
421 | |
422 | bool ReportVariantBasePtr::classof(const RejectReason *RR) { |
423 | return RR->getKind() == RejectReasonKind::VariantBasePtr; |
424 | } |
425 | |
426 | //===----------------------------------------------------------------------===// |
427 | // ReportDifferentArrayElementSize |
428 | |
429 | std::string ReportDifferentArrayElementSize::getRemarkName() const { |
430 | return "DifferentArrayElementSize"; |
431 | } |
432 | |
433 | const BasicBlock *ReportDifferentArrayElementSize::getRemarkBB() const { |
434 | return Inst->getParent(); |
435 | } |
436 | |
437 | std::string ReportDifferentArrayElementSize::getMessage() const { |
438 | return "Access to one array through data types of different size"; |
439 | } |
440 | |
441 | bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) { |
442 | return RR->getKind() == RejectReasonKind::DifferentElementSize; |
443 | } |
444 | |
445 | std::string ReportDifferentArrayElementSize::getEndUserMessage() const { |
446 | StringRef BaseName = BaseValue->getName(); |
447 | std::string Name = BaseName.empty() ? "UNKNOWN": BaseName.str(); |
448 | return "The array \""+ Name + |
449 | "\" is accessed through elements that differ " |
450 | "in size"; |
451 | } |
452 | |
453 | //===----------------------------------------------------------------------===// |
454 | // ReportNonAffineAccess. |
455 | |
456 | std::string ReportNonAffineAccess::getRemarkName() const { |
457 | return "NonAffineAccess"; |
458 | } |
459 | |
460 | const BasicBlock *ReportNonAffineAccess::getRemarkBB() const { |
461 | return Inst->getParent(); |
462 | } |
463 | |
464 | std::string ReportNonAffineAccess::getMessage() const { |
465 | return "Non affine access function: "+ *AccessFunction; |
466 | } |
467 | |
468 | bool ReportNonAffineAccess::classof(const RejectReason *RR) { |
469 | return RR->getKind() == RejectReasonKind::NonAffineAccess; |
470 | } |
471 | |
472 | std::string ReportNonAffineAccess::getEndUserMessage() const { |
473 | StringRef BaseName = BaseValue->getName(); |
474 | std::string Name = BaseName.empty() ? "UNKNOWN": BaseName.str(); |
475 | return "The array subscript of \""+ Name + "\" is not affine"; |
476 | } |
477 | |
478 | //===----------------------------------------------------------------------===// |
479 | // ReportLoopBound. |
480 | |
481 | ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount) |
482 | : RejectReason(RejectReasonKind::LoopBound), L(L), LoopCount(LoopCount), |
483 | Loc(L->getStartLoc()) {} |
484 | |
485 | std::string ReportLoopBound::getRemarkName() const { return "LoopBound"; } |
486 | |
487 | const BasicBlock *ReportLoopBound::getRemarkBB() const { |
488 | return L->getHeader(); |
489 | } |
490 | |
491 | std::string ReportLoopBound::getMessage() const { |
492 | return "Non affine loop bound '"+ *LoopCount + |
493 | "' in loop: "+ L->getHeader()->getName(); |
494 | } |
495 | |
496 | const DebugLoc &ReportLoopBound::getDebugLoc() const { return Loc; } |
497 | |
498 | bool ReportLoopBound::classof(const RejectReason *RR) { |
499 | return RR->getKind() == RejectReasonKind::LoopBound; |
500 | } |
501 | |
502 | std::string ReportLoopBound::getEndUserMessage() const { |
503 | return "Failed to derive an affine function from the loop bounds."; |
504 | } |
505 | |
506 | //===----------------------------------------------------------------------===// |
507 | // ReportLoopHasNoExit. |
508 | |
509 | std::string ReportLoopHasNoExit::getRemarkName() const { |
510 | return "LoopHasNoExit"; |
511 | } |
512 | |
513 | const BasicBlock *ReportLoopHasNoExit::getRemarkBB() const { |
514 | return L->getHeader(); |
515 | } |
516 | |
517 | std::string ReportLoopHasNoExit::getMessage() const { |
518 | return "Loop "+ L->getHeader()->getName() + " has no exit."; |
519 | } |
520 | |
521 | bool ReportLoopHasNoExit::classof(const RejectReason *RR) { |
522 | return RR->getKind() == RejectReasonKind::LoopHasNoExit; |
523 | } |
524 | |
525 | const DebugLoc &ReportLoopHasNoExit::getDebugLoc() const { return Loc; } |
526 | |
527 | std::string ReportLoopHasNoExit::getEndUserMessage() const { |
528 | return "Loop cannot be handled because it has no exit."; |
529 | } |
530 | |
531 | //===----------------------------------------------------------------------===// |
532 | // ReportLoopHasMultipleExits. |
533 | |
534 | std::string ReportLoopHasMultipleExits::getRemarkName() const { |
535 | return "ReportLoopHasMultipleExits"; |
536 | } |
537 | |
538 | const BasicBlock *ReportLoopHasMultipleExits::getRemarkBB() const { |
539 | return L->getHeader(); |
540 | } |
541 | |
542 | std::string ReportLoopHasMultipleExits::getMessage() const { |
543 | return "Loop "+ L->getHeader()->getName() + " has multiple exits."; |
544 | } |
545 | |
546 | bool ReportLoopHasMultipleExits::classof(const RejectReason *RR) { |
547 | return RR->getKind() == RejectReasonKind::LoopHasMultipleExits; |
548 | } |
549 | |
550 | const DebugLoc &ReportLoopHasMultipleExits::getDebugLoc() const { return Loc; } |
551 | |
552 | std::string ReportLoopHasMultipleExits::getEndUserMessage() const { |
553 | return "Loop cannot be handled because it has multiple exits."; |
554 | } |
555 | |
556 | //===----------------------------------------------------------------------===// |
557 | // ReportLoopOnlySomeLatches |
558 | |
559 | std::string ReportLoopOnlySomeLatches::getRemarkName() const { |
560 | return "LoopHasNoExit"; |
561 | } |
562 | |
563 | const BasicBlock *ReportLoopOnlySomeLatches::getRemarkBB() const { |
564 | return L->getHeader(); |
565 | } |
566 | |
567 | std::string ReportLoopOnlySomeLatches::getMessage() const { |
568 | return "Not all latches of loop "+ L->getHeader()->getName() + |
569 | " part of scop."; |
570 | } |
571 | |
572 | bool ReportLoopOnlySomeLatches::classof(const RejectReason *RR) { |
573 | return RR->getKind() == RejectReasonKind::LoopHasNoExit; |
574 | } |
575 | |
576 | const DebugLoc &ReportLoopOnlySomeLatches::getDebugLoc() const { return Loc; } |
577 | |
578 | std::string ReportLoopOnlySomeLatches::getEndUserMessage() const { |
579 | return "Loop cannot be handled because not all latches are part of loop " |
580 | "region."; |
581 | } |
582 | |
583 | //===----------------------------------------------------------------------===// |
584 | // ReportFuncCall. |
585 | |
586 | ReportFuncCall::ReportFuncCall(Instruction *Inst) |
587 | : RejectReason(RejectReasonKind::FuncCall), Inst(Inst) {} |
588 | |
589 | std::string ReportFuncCall::getRemarkName() const { return "FuncCall"; } |
590 | |
591 | const BasicBlock *ReportFuncCall::getRemarkBB() const { |
592 | return Inst->getParent(); |
593 | } |
594 | |
595 | std::string ReportFuncCall::getMessage() const { |
596 | return "Call instruction: "+ *Inst; |
597 | } |
598 | |
599 | const DebugLoc &ReportFuncCall::getDebugLoc() const { |
600 | return Inst->getDebugLoc(); |
601 | } |
602 | |
603 | std::string ReportFuncCall::getEndUserMessage() const { |
604 | return "This function call cannot be handled. " |
605 | "Try to inline it."; |
606 | } |
607 | |
608 | bool ReportFuncCall::classof(const RejectReason *RR) { |
609 | return RR->getKind() == RejectReasonKind::FuncCall; |
610 | } |
611 | |
612 | //===----------------------------------------------------------------------===// |
613 | // ReportNonSimpleMemoryAccess |
614 | |
615 | ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst) |
616 | : ReportOther(RejectReasonKind::NonSimpleMemoryAccess), Inst(Inst) {} |
617 | |
618 | std::string ReportNonSimpleMemoryAccess::getRemarkName() const { |
619 | return "NonSimpleMemoryAccess"; |
620 | } |
621 | |
622 | const BasicBlock *ReportNonSimpleMemoryAccess::getRemarkBB() const { |
623 | return Inst->getParent(); |
624 | } |
625 | |
626 | std::string ReportNonSimpleMemoryAccess::getMessage() const { |
627 | return "Non-simple memory access: "+ *Inst; |
628 | } |
629 | |
630 | const DebugLoc &ReportNonSimpleMemoryAccess::getDebugLoc() const { |
631 | return Inst->getDebugLoc(); |
632 | } |
633 | |
634 | std::string ReportNonSimpleMemoryAccess::getEndUserMessage() const { |
635 | return "Volatile memory accesses or memory accesses for atomic types " |
636 | "are not supported."; |
637 | } |
638 | |
639 | bool ReportNonSimpleMemoryAccess::classof(const RejectReason *RR) { |
640 | return RR->getKind() == RejectReasonKind::NonSimpleMemoryAccess; |
641 | } |
642 | |
643 | //===----------------------------------------------------------------------===// |
644 | // ReportAlias. |
645 | |
646 | ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS) |
647 | : RejectReason(RejectReasonKind::Alias), Inst(Inst) { |
648 | append_range(C&: Pointers, R: AS.getPointers()); |
649 | } |
650 | |
651 | std::string ReportAlias::formatInvalidAlias(std::string Prefix, |
652 | std::string Suffix) const { |
653 | std::string Message; |
654 | raw_string_ostream OS(Message); |
655 | |
656 | OS << Prefix; |
657 | |
658 | for (PointerSnapshotTy::const_iterator PI = Pointers.begin(), |
659 | PE = Pointers.end(); |
660 | ;) { |
661 | const Value *V = *PI; |
662 | assert(V && "Diagnostic info does not match found LLVM-IR anymore."); |
663 | |
664 | if (V->getName().empty()) |
665 | OS << "\" <unknown> \""; |
666 | else |
667 | OS << "\""<< V->getName() << "\""; |
668 | |
669 | ++PI; |
670 | |
671 | if (PI != PE) |
672 | OS << ", "; |
673 | else |
674 | break; |
675 | } |
676 | |
677 | OS << Suffix; |
678 | |
679 | return Message; |
680 | } |
681 | |
682 | std::string ReportAlias::getRemarkName() const { return "Alias"; } |
683 | |
684 | const BasicBlock *ReportAlias::getRemarkBB() const { return Inst->getParent(); } |
685 | |
686 | std::string ReportAlias::getMessage() const { |
687 | return formatInvalidAlias(Prefix: "Possible aliasing: "); |
688 | } |
689 | |
690 | std::string ReportAlias::getEndUserMessage() const { |
691 | return formatInvalidAlias(Prefix: "Accesses to the arrays ", |
692 | Suffix: " may access the same memory."); |
693 | } |
694 | |
695 | const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); } |
696 | |
697 | bool ReportAlias::classof(const RejectReason *RR) { |
698 | return RR->getKind() == RejectReasonKind::Alias; |
699 | } |
700 | |
701 | //===----------------------------------------------------------------------===// |
702 | // ReportOther. |
703 | |
704 | std::string ReportOther::getRemarkName() const { return "UnknownRejectReason"; } |
705 | |
706 | std::string ReportOther::getMessage() const { return "Unknown reject reason"; } |
707 | |
708 | ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {} |
709 | |
710 | bool ReportOther::classof(const RejectReason *RR) { |
711 | return RR->getKind() >= RejectReasonKind::Other && |
712 | RR->getKind() <= RejectReasonKind::LastOther; |
713 | } |
714 | |
715 | //===----------------------------------------------------------------------===// |
716 | // ReportIntToPtr. |
717 | ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue) |
718 | : ReportOther(RejectReasonKind::IntToPtr), BaseValue(BaseValue) {} |
719 | |
720 | std::string ReportIntToPtr::getRemarkName() const { return "IntToPtr"; } |
721 | |
722 | const BasicBlock *ReportIntToPtr::getRemarkBB() const { |
723 | return BaseValue->getParent(); |
724 | } |
725 | |
726 | std::string ReportIntToPtr::getMessage() const { |
727 | return "Find bad intToptr prt: "+ *BaseValue; |
728 | } |
729 | |
730 | const DebugLoc &ReportIntToPtr::getDebugLoc() const { |
731 | return BaseValue->getDebugLoc(); |
732 | } |
733 | |
734 | bool ReportIntToPtr::classof(const RejectReason *RR) { |
735 | return RR->getKind() == RejectReasonKind::IntToPtr; |
736 | } |
737 | |
738 | //===----------------------------------------------------------------------===// |
739 | // ReportAlloca. |
740 | |
741 | ReportAlloca::ReportAlloca(Instruction *Inst) |
742 | : ReportOther(RejectReasonKind::Alloca), Inst(Inst) {} |
743 | |
744 | std::string ReportAlloca::getRemarkName() const { return "Alloca"; } |
745 | |
746 | const BasicBlock *ReportAlloca::getRemarkBB() const { |
747 | return Inst->getParent(); |
748 | } |
749 | |
750 | std::string ReportAlloca::getMessage() const { |
751 | return "Alloca instruction: "+ *Inst; |
752 | } |
753 | |
754 | const DebugLoc &ReportAlloca::getDebugLoc() const { |
755 | return Inst->getDebugLoc(); |
756 | } |
757 | |
758 | bool ReportAlloca::classof(const RejectReason *RR) { |
759 | return RR->getKind() == RejectReasonKind::Alloca; |
760 | } |
761 | |
762 | //===----------------------------------------------------------------------===// |
763 | // ReportUnknownInst. |
764 | |
765 | ReportUnknownInst::ReportUnknownInst(Instruction *Inst) |
766 | : ReportOther(RejectReasonKind::UnknownInst), Inst(Inst) {} |
767 | |
768 | std::string ReportUnknownInst::getRemarkName() const { return "UnknownInst"; } |
769 | |
770 | const BasicBlock *ReportUnknownInst::getRemarkBB() const { |
771 | return Inst->getParent(); |
772 | } |
773 | |
774 | std::string ReportUnknownInst::getMessage() const { |
775 | return "Unknown instruction: "+ *Inst; |
776 | } |
777 | |
778 | const DebugLoc &ReportUnknownInst::getDebugLoc() const { |
779 | return Inst->getDebugLoc(); |
780 | } |
781 | |
782 | bool ReportUnknownInst::classof(const RejectReason *RR) { |
783 | return RR->getKind() == RejectReasonKind::UnknownInst; |
784 | } |
785 | |
786 | //===----------------------------------------------------------------------===// |
787 | // ReportEntry. |
788 | |
789 | ReportEntry::ReportEntry(BasicBlock *BB) |
790 | : ReportOther(RejectReasonKind::Entry), BB(BB) {} |
791 | |
792 | std::string ReportEntry::getRemarkName() const { return "Entry"; } |
793 | |
794 | const BasicBlock *ReportEntry::getRemarkBB() const { return BB; } |
795 | |
796 | std::string ReportEntry::getMessage() const { |
797 | return "Region containing entry block of function is invalid!"; |
798 | } |
799 | |
800 | std::string ReportEntry::getEndUserMessage() const { |
801 | return "Scop contains function entry (not yet supported)."; |
802 | } |
803 | |
804 | const DebugLoc &ReportEntry::getDebugLoc() const { |
805 | return BB->getTerminator()->getDebugLoc(); |
806 | } |
807 | |
808 | bool ReportEntry::classof(const RejectReason *RR) { |
809 | return RR->getKind() == RejectReasonKind::Entry; |
810 | } |
811 | |
812 | //===----------------------------------------------------------------------===// |
813 | // ReportUnprofitable. |
814 | |
815 | ReportUnprofitable::ReportUnprofitable(Region *R) |
816 | : ReportOther(RejectReasonKind::Unprofitable), R(R) {} |
817 | |
818 | std::string ReportUnprofitable::getRemarkName() const { return "Unprofitable"; } |
819 | |
820 | const BasicBlock *ReportUnprofitable::getRemarkBB() const { |
821 | return R->getEntry(); |
822 | } |
823 | |
824 | std::string ReportUnprofitable::getMessage() const { |
825 | return "Region can not profitably be optimized!"; |
826 | } |
827 | |
828 | std::string ReportUnprofitable::getEndUserMessage() const { |
829 | return "No profitable polyhedral optimization found"; |
830 | } |
831 | |
832 | const DebugLoc &ReportUnprofitable::getDebugLoc() const { |
833 | for (const BasicBlock *BB : R->blocks()) |
834 | for (const Instruction &Inst : *BB) |
835 | if (const DebugLoc &DL = Inst.getStableDebugLoc()) |
836 | return DL; |
837 | |
838 | return R->getEntry()->getTerminator()->getDebugLoc(); |
839 | } |
840 | |
841 | bool ReportUnprofitable::classof(const RejectReason *RR) { |
842 | return RR->getKind() == RejectReasonKind::Unprofitable; |
843 | } |
844 | } // namespace polly |
845 |
Definitions
- RejectStatistics
- operator+
- operator<
- getBBPairForRegion
- getDebugLocations
- emitRejectionRemarks
- RejectReason
- Unknown
- getDebugLoc
- ReportCFG
- classof
- getRemarkName
- getRemarkBB
- getMessage
- getDebugLoc
- classof
- getRemarkName
- getRemarkBB
- getMessage
- getDebugLoc
- getEndUserMessage
- classof
- getRemarkName
- getRemarkBB
- getMessage
- getDebugLoc
- getEndUserMessage
- classof
- getRemarkName
- getRemarkBB
- getMessage
- getDebugLoc
- getEndUserMessage
- classof
- ReportAffFunc
- classof
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getRemarkName
- getRemarkBB
- getMessage
- getEndUserMessage
- classof
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getEndUserMessage
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getEndUserMessage
- ReportLoopBound
- getRemarkName
- getRemarkBB
- getMessage
- getDebugLoc
- classof
- getEndUserMessage
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getDebugLoc
- getEndUserMessage
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getDebugLoc
- getEndUserMessage
- getRemarkName
- getRemarkBB
- getMessage
- classof
- getDebugLoc
- getEndUserMessage
- ReportFuncCall
- getRemarkName
- getRemarkBB
- getMessage
- getDebugLoc
- getEndUserMessage
- classof
- ReportNonSimpleMemoryAccess
- getRemarkName
- getRemarkBB
- getMessage
- getDebugLoc
- getEndUserMessage
- classof
- ReportAlias
- formatInvalidAlias
- getRemarkName
- getRemarkBB
- getMessage
- getEndUserMessage
- getDebugLoc
- classof
- getRemarkName
- getMessage
- ReportOther
- classof
- ReportIntToPtr
- getRemarkName
- getRemarkBB
- getMessage
- getDebugLoc
- classof
- ReportAlloca
- getRemarkName
- getRemarkBB
- getMessage
- getDebugLoc
- classof
- ReportUnknownInst
- getRemarkName
- getRemarkBB
- getMessage
- getDebugLoc
- classof
- ReportEntry
- getRemarkName
- getRemarkBB
- getMessage
- getEndUserMessage
- getDebugLoc
- classof
- ReportUnprofitable
- getRemarkName
- getRemarkBB
- getMessage
- getEndUserMessage
- getDebugLoc
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more