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
43using 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
50static 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
85namespace polly {
86
87/// Small string conversion via raw_string_stream.
88template <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
97namespace llvm {
98
99// Lexicographic order on (line, col) of our debug locations.
100static 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
106namespace polly {
107
108BBPair getBBPairForRegion(const Region *R) {
109 return std::make_pair(x: R->getEntry(), y: R->getExit());
110}
111
112void 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
134void 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
169RejectReason::RejectReason(RejectReasonKind K) : Kind(K) {
170 RejectStatistics[static_cast<int>(K)]++;
171}
172
173const DebugLoc RejectReason::Unknown = DebugLoc();
174
175const DebugLoc &RejectReason::getDebugLoc() const {
176 // Allocate an empty DebugLoc and return it a reference to it.
177 return Unknown;
178}
179
180// RejectLog.
181void 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
190ReportCFG::ReportCFG(const RejectReasonKind K) : RejectReason(K) {}
191
192bool ReportCFG::classof(const RejectReason *RR) {
193 return RR->getKind() >= RejectReasonKind::CFG &&
194 RR->getKind() <= RejectReasonKind::LastCFG;
195}
196
197//===----------------------------------------------------------------------===//
198// ReportInvalidTerminator.
199
200std::string ReportInvalidTerminator::getRemarkName() const {
201 return "InvalidTerminator";
202}
203
204const BasicBlock *ReportInvalidTerminator::getRemarkBB() const { return BB; }
205
206std::string ReportInvalidTerminator::getMessage() const {
207 return ("Invalid instruction terminates BB: " + BB->getName()).str();
208}
209
210const DebugLoc &ReportInvalidTerminator::getDebugLoc() const {
211 return BB->getTerminator()->getDebugLoc();
212}
213
214bool ReportInvalidTerminator::classof(const RejectReason *RR) {
215 return RR->getKind() == RejectReasonKind::InvalidTerminator;
216}
217
218//===----------------------------------------------------------------------===//
219// UnreachableInExit.
220
221std::string ReportUnreachableInExit::getRemarkName() const {
222 return "UnreachableInExit";
223}
224
225const BasicBlock *ReportUnreachableInExit::getRemarkBB() const { return BB; }
226
227std::string ReportUnreachableInExit::getMessage() const {
228 std::string BBName = BB->getName().str();
229 return "Unreachable in exit block" + BBName;
230}
231
232const DebugLoc &ReportUnreachableInExit::getDebugLoc() const { return DbgLoc; }
233
234std::string ReportUnreachableInExit::getEndUserMessage() const {
235 return "Unreachable in exit block.";
236}
237
238bool ReportUnreachableInExit::classof(const RejectReason *RR) {
239 return RR->getKind() == RejectReasonKind::UnreachableInExit;
240}
241
242//===----------------------------------------------------------------------===//
243// IndirectPredecessor.
244
245std::string ReportIndirectPredecessor::getRemarkName() const {
246 return "IndirectPredecessor";
247}
248
249const BasicBlock *ReportIndirectPredecessor::getRemarkBB() const {
250 if (Inst)
251 return Inst->getParent();
252 return nullptr;
253}
254
255std::string ReportIndirectPredecessor::getMessage() const {
256 if (Inst)
257 return "Branch from indirect terminator: " + *Inst;
258 return getEndUserMessage();
259}
260
261const DebugLoc &ReportIndirectPredecessor::getDebugLoc() const {
262 return DbgLoc;
263}
264
265std::string ReportIndirectPredecessor::getEndUserMessage() const {
266 return "Branch from indirect terminator.";
267}
268
269bool ReportIndirectPredecessor::classof(const RejectReason *RR) {
270 return RR->getKind() == RejectReasonKind::IndirectPredecessor;
271}
272
273//===----------------------------------------------------------------------===//
274// ReportIrreducibleRegion.
275
276std::string ReportIrreducibleRegion::getRemarkName() const {
277 return "IrreducibleRegion";
278}
279
280const BasicBlock *ReportIrreducibleRegion::getRemarkBB() const {
281 return R->getEntry();
282}
283
284std::string ReportIrreducibleRegion::getMessage() const {
285 return "Irreducible region encountered: " + R->getNameStr();
286}
287
288const DebugLoc &ReportIrreducibleRegion::getDebugLoc() const { return DbgLoc; }
289
290std::string ReportIrreducibleRegion::getEndUserMessage() const {
291 return "Irreducible region encountered in control flow.";
292}
293
294bool ReportIrreducibleRegion::classof(const RejectReason *RR) {
295 return RR->getKind() == RejectReasonKind::IrreducibleRegion;
296}
297
298//===----------------------------------------------------------------------===//
299// ReportAffFunc.
300
301ReportAffFunc::ReportAffFunc(const RejectReasonKind K, const Instruction *Inst)
302 : RejectReason(K), Inst(Inst) {}
303
304bool ReportAffFunc::classof(const RejectReason *RR) {
305 return RR->getKind() >= RejectReasonKind::AffFunc &&
306 RR->getKind() <= RejectReasonKind::LastAffFunc;
307}
308
309//===----------------------------------------------------------------------===//
310// ReportUndefCond.
311
312std::string ReportUndefCond::getRemarkName() const { return "UndefCond"; }
313
314const BasicBlock *ReportUndefCond::getRemarkBB() const { return BB; }
315
316std::string ReportUndefCond::getMessage() const {
317 return ("Condition based on 'undef' value in BB: " + BB->getName()).str();
318}
319
320bool ReportUndefCond::classof(const RejectReason *RR) {
321 return RR->getKind() == RejectReasonKind::UndefCond;
322}
323
324//===----------------------------------------------------------------------===//
325// ReportInvalidCond.
326
327std::string ReportInvalidCond::getRemarkName() const { return "InvalidCond"; }
328
329const BasicBlock *ReportInvalidCond::getRemarkBB() const { return BB; }
330
331std::string ReportInvalidCond::getMessage() const {
332 return ("Condition in BB '" + BB->getName()).str() +
333 "' neither constant nor an icmp instruction";
334}
335
336bool ReportInvalidCond::classof(const RejectReason *RR) {
337 return RR->getKind() == RejectReasonKind::InvalidCond;
338}
339
340//===----------------------------------------------------------------------===//
341// ReportUndefOperand.
342
343std::string ReportUndefOperand::getRemarkName() const { return "UndefOperand"; }
344
345const BasicBlock *ReportUndefOperand::getRemarkBB() const { return BB; }
346
347std::string ReportUndefOperand::getMessage() const {
348 return ("undef operand in branch at BB: " + BB->getName()).str();
349}
350
351bool ReportUndefOperand::classof(const RejectReason *RR) {
352 return RR->getKind() == RejectReasonKind::UndefOperand;
353}
354
355//===----------------------------------------------------------------------===//
356// ReportNonAffBranch.
357
358std::string ReportNonAffBranch::getRemarkName() const { return "NonAffBranch"; }
359
360const BasicBlock *ReportNonAffBranch::getRemarkBB() const { return BB; }
361
362std::string ReportNonAffBranch::getMessage() const {
363 return ("Non affine branch in BB '" + BB->getName()).str() +
364 "' with LHS: " + *LHS + " and RHS: " + *RHS;
365}
366
367bool ReportNonAffBranch::classof(const RejectReason *RR) {
368 return RR->getKind() == RejectReasonKind::NonAffBranch;
369}
370
371//===----------------------------------------------------------------------===//
372// ReportNoBasePtr.
373
374std::string ReportNoBasePtr::getRemarkName() const { return "NoBasePtr"; }
375
376const BasicBlock *ReportNoBasePtr::getRemarkBB() const {
377 return Inst->getParent();
378}
379
380std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; }
381
382bool ReportNoBasePtr::classof(const RejectReason *RR) {
383 return RR->getKind() == RejectReasonKind::NoBasePtr;
384}
385
386//===----------------------------------------------------------------------===//
387// ReportUndefBasePtr.
388
389std::string ReportUndefBasePtr::getRemarkName() const { return "UndefBasePtr"; }
390
391const BasicBlock *ReportUndefBasePtr::getRemarkBB() const {
392 return Inst->getParent();
393}
394
395std::string ReportUndefBasePtr::getMessage() const {
396 return "Undefined base pointer";
397}
398
399bool ReportUndefBasePtr::classof(const RejectReason *RR) {
400 return RR->getKind() == RejectReasonKind::UndefBasePtr;
401}
402
403//===----------------------------------------------------------------------===//
404// ReportVariantBasePtr.
405
406std::string ReportVariantBasePtr::getRemarkName() const {
407 return "VariantBasePtr";
408}
409
410const BasicBlock *ReportVariantBasePtr::getRemarkBB() const {
411 return Inst->getParent();
412}
413
414std::string ReportVariantBasePtr::getMessage() const {
415 return "Base address not invariant in current region:" + *BaseValue;
416}
417
418std::string ReportVariantBasePtr::getEndUserMessage() const {
419 return "The base address of this array is not invariant inside the loop";
420}
421
422bool ReportVariantBasePtr::classof(const RejectReason *RR) {
423 return RR->getKind() == RejectReasonKind::VariantBasePtr;
424}
425
426//===----------------------------------------------------------------------===//
427// ReportDifferentArrayElementSize
428
429std::string ReportDifferentArrayElementSize::getRemarkName() const {
430 return "DifferentArrayElementSize";
431}
432
433const BasicBlock *ReportDifferentArrayElementSize::getRemarkBB() const {
434 return Inst->getParent();
435}
436
437std::string ReportDifferentArrayElementSize::getMessage() const {
438 return "Access to one array through data types of different size";
439}
440
441bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) {
442 return RR->getKind() == RejectReasonKind::DifferentElementSize;
443}
444
445std::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
456std::string ReportNonAffineAccess::getRemarkName() const {
457 return "NonAffineAccess";
458}
459
460const BasicBlock *ReportNonAffineAccess::getRemarkBB() const {
461 return Inst->getParent();
462}
463
464std::string ReportNonAffineAccess::getMessage() const {
465 return "Non affine access function: " + *AccessFunction;
466}
467
468bool ReportNonAffineAccess::classof(const RejectReason *RR) {
469 return RR->getKind() == RejectReasonKind::NonAffineAccess;
470}
471
472std::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
481ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount)
482 : RejectReason(RejectReasonKind::LoopBound), L(L), LoopCount(LoopCount),
483 Loc(L->getStartLoc()) {}
484
485std::string ReportLoopBound::getRemarkName() const { return "LoopBound"; }
486
487const BasicBlock *ReportLoopBound::getRemarkBB() const {
488 return L->getHeader();
489}
490
491std::string ReportLoopBound::getMessage() const {
492 return "Non affine loop bound '" + *LoopCount +
493 "' in loop: " + L->getHeader()->getName();
494}
495
496const DebugLoc &ReportLoopBound::getDebugLoc() const { return Loc; }
497
498bool ReportLoopBound::classof(const RejectReason *RR) {
499 return RR->getKind() == RejectReasonKind::LoopBound;
500}
501
502std::string ReportLoopBound::getEndUserMessage() const {
503 return "Failed to derive an affine function from the loop bounds.";
504}
505
506//===----------------------------------------------------------------------===//
507// ReportLoopHasNoExit.
508
509std::string ReportLoopHasNoExit::getRemarkName() const {
510 return "LoopHasNoExit";
511}
512
513const BasicBlock *ReportLoopHasNoExit::getRemarkBB() const {
514 return L->getHeader();
515}
516
517std::string ReportLoopHasNoExit::getMessage() const {
518 return "Loop " + L->getHeader()->getName() + " has no exit.";
519}
520
521bool ReportLoopHasNoExit::classof(const RejectReason *RR) {
522 return RR->getKind() == RejectReasonKind::LoopHasNoExit;
523}
524
525const DebugLoc &ReportLoopHasNoExit::getDebugLoc() const { return Loc; }
526
527std::string ReportLoopHasNoExit::getEndUserMessage() const {
528 return "Loop cannot be handled because it has no exit.";
529}
530
531//===----------------------------------------------------------------------===//
532// ReportLoopHasMultipleExits.
533
534std::string ReportLoopHasMultipleExits::getRemarkName() const {
535 return "ReportLoopHasMultipleExits";
536}
537
538const BasicBlock *ReportLoopHasMultipleExits::getRemarkBB() const {
539 return L->getHeader();
540}
541
542std::string ReportLoopHasMultipleExits::getMessage() const {
543 return "Loop " + L->getHeader()->getName() + " has multiple exits.";
544}
545
546bool ReportLoopHasMultipleExits::classof(const RejectReason *RR) {
547 return RR->getKind() == RejectReasonKind::LoopHasMultipleExits;
548}
549
550const DebugLoc &ReportLoopHasMultipleExits::getDebugLoc() const { return Loc; }
551
552std::string ReportLoopHasMultipleExits::getEndUserMessage() const {
553 return "Loop cannot be handled because it has multiple exits.";
554}
555
556//===----------------------------------------------------------------------===//
557// ReportLoopOnlySomeLatches
558
559std::string ReportLoopOnlySomeLatches::getRemarkName() const {
560 return "LoopHasNoExit";
561}
562
563const BasicBlock *ReportLoopOnlySomeLatches::getRemarkBB() const {
564 return L->getHeader();
565}
566
567std::string ReportLoopOnlySomeLatches::getMessage() const {
568 return "Not all latches of loop " + L->getHeader()->getName() +
569 " part of scop.";
570}
571
572bool ReportLoopOnlySomeLatches::classof(const RejectReason *RR) {
573 return RR->getKind() == RejectReasonKind::LoopHasNoExit;
574}
575
576const DebugLoc &ReportLoopOnlySomeLatches::getDebugLoc() const { return Loc; }
577
578std::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
586ReportFuncCall::ReportFuncCall(Instruction *Inst)
587 : RejectReason(RejectReasonKind::FuncCall), Inst(Inst) {}
588
589std::string ReportFuncCall::getRemarkName() const { return "FuncCall"; }
590
591const BasicBlock *ReportFuncCall::getRemarkBB() const {
592 return Inst->getParent();
593}
594
595std::string ReportFuncCall::getMessage() const {
596 return "Call instruction: " + *Inst;
597}
598
599const DebugLoc &ReportFuncCall::getDebugLoc() const {
600 return Inst->getDebugLoc();
601}
602
603std::string ReportFuncCall::getEndUserMessage() const {
604 return "This function call cannot be handled. "
605 "Try to inline it.";
606}
607
608bool ReportFuncCall::classof(const RejectReason *RR) {
609 return RR->getKind() == RejectReasonKind::FuncCall;
610}
611
612//===----------------------------------------------------------------------===//
613// ReportNonSimpleMemoryAccess
614
615ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst)
616 : ReportOther(RejectReasonKind::NonSimpleMemoryAccess), Inst(Inst) {}
617
618std::string ReportNonSimpleMemoryAccess::getRemarkName() const {
619 return "NonSimpleMemoryAccess";
620}
621
622const BasicBlock *ReportNonSimpleMemoryAccess::getRemarkBB() const {
623 return Inst->getParent();
624}
625
626std::string ReportNonSimpleMemoryAccess::getMessage() const {
627 return "Non-simple memory access: " + *Inst;
628}
629
630const DebugLoc &ReportNonSimpleMemoryAccess::getDebugLoc() const {
631 return Inst->getDebugLoc();
632}
633
634std::string ReportNonSimpleMemoryAccess::getEndUserMessage() const {
635 return "Volatile memory accesses or memory accesses for atomic types "
636 "are not supported.";
637}
638
639bool ReportNonSimpleMemoryAccess::classof(const RejectReason *RR) {
640 return RR->getKind() == RejectReasonKind::NonSimpleMemoryAccess;
641}
642
643//===----------------------------------------------------------------------===//
644// ReportAlias.
645
646ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS)
647 : RejectReason(RejectReasonKind::Alias), Inst(Inst) {
648 append_range(C&: Pointers, R: AS.getPointers());
649}
650
651std::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
682std::string ReportAlias::getRemarkName() const { return "Alias"; }
683
684const BasicBlock *ReportAlias::getRemarkBB() const { return Inst->getParent(); }
685
686std::string ReportAlias::getMessage() const {
687 return formatInvalidAlias(Prefix: "Possible aliasing: ");
688}
689
690std::string ReportAlias::getEndUserMessage() const {
691 return formatInvalidAlias(Prefix: "Accesses to the arrays ",
692 Suffix: " may access the same memory.");
693}
694
695const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); }
696
697bool ReportAlias::classof(const RejectReason *RR) {
698 return RR->getKind() == RejectReasonKind::Alias;
699}
700
701//===----------------------------------------------------------------------===//
702// ReportOther.
703
704std::string ReportOther::getRemarkName() const { return "UnknownRejectReason"; }
705
706std::string ReportOther::getMessage() const { return "Unknown reject reason"; }
707
708ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {}
709
710bool ReportOther::classof(const RejectReason *RR) {
711 return RR->getKind() >= RejectReasonKind::Other &&
712 RR->getKind() <= RejectReasonKind::LastOther;
713}
714
715//===----------------------------------------------------------------------===//
716// ReportIntToPtr.
717ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue)
718 : ReportOther(RejectReasonKind::IntToPtr), BaseValue(BaseValue) {}
719
720std::string ReportIntToPtr::getRemarkName() const { return "IntToPtr"; }
721
722const BasicBlock *ReportIntToPtr::getRemarkBB() const {
723 return BaseValue->getParent();
724}
725
726std::string ReportIntToPtr::getMessage() const {
727 return "Find bad intToptr prt: " + *BaseValue;
728}
729
730const DebugLoc &ReportIntToPtr::getDebugLoc() const {
731 return BaseValue->getDebugLoc();
732}
733
734bool ReportIntToPtr::classof(const RejectReason *RR) {
735 return RR->getKind() == RejectReasonKind::IntToPtr;
736}
737
738//===----------------------------------------------------------------------===//
739// ReportAlloca.
740
741ReportAlloca::ReportAlloca(Instruction *Inst)
742 : ReportOther(RejectReasonKind::Alloca), Inst(Inst) {}
743
744std::string ReportAlloca::getRemarkName() const { return "Alloca"; }
745
746const BasicBlock *ReportAlloca::getRemarkBB() const {
747 return Inst->getParent();
748}
749
750std::string ReportAlloca::getMessage() const {
751 return "Alloca instruction: " + *Inst;
752}
753
754const DebugLoc &ReportAlloca::getDebugLoc() const {
755 return Inst->getDebugLoc();
756}
757
758bool ReportAlloca::classof(const RejectReason *RR) {
759 return RR->getKind() == RejectReasonKind::Alloca;
760}
761
762//===----------------------------------------------------------------------===//
763// ReportUnknownInst.
764
765ReportUnknownInst::ReportUnknownInst(Instruction *Inst)
766 : ReportOther(RejectReasonKind::UnknownInst), Inst(Inst) {}
767
768std::string ReportUnknownInst::getRemarkName() const { return "UnknownInst"; }
769
770const BasicBlock *ReportUnknownInst::getRemarkBB() const {
771 return Inst->getParent();
772}
773
774std::string ReportUnknownInst::getMessage() const {
775 return "Unknown instruction: " + *Inst;
776}
777
778const DebugLoc &ReportUnknownInst::getDebugLoc() const {
779 return Inst->getDebugLoc();
780}
781
782bool ReportUnknownInst::classof(const RejectReason *RR) {
783 return RR->getKind() == RejectReasonKind::UnknownInst;
784}
785
786//===----------------------------------------------------------------------===//
787// ReportEntry.
788
789ReportEntry::ReportEntry(BasicBlock *BB)
790 : ReportOther(RejectReasonKind::Entry), BB(BB) {}
791
792std::string ReportEntry::getRemarkName() const { return "Entry"; }
793
794const BasicBlock *ReportEntry::getRemarkBB() const { return BB; }
795
796std::string ReportEntry::getMessage() const {
797 return "Region containing entry block of function is invalid!";
798}
799
800std::string ReportEntry::getEndUserMessage() const {
801 return "Scop contains function entry (not yet supported).";
802}
803
804const DebugLoc &ReportEntry::getDebugLoc() const {
805 return BB->getTerminator()->getDebugLoc();
806}
807
808bool ReportEntry::classof(const RejectReason *RR) {
809 return RR->getKind() == RejectReasonKind::Entry;
810}
811
812//===----------------------------------------------------------------------===//
813// ReportUnprofitable.
814
815ReportUnprofitable::ReportUnprofitable(Region *R)
816 : ReportOther(RejectReasonKind::Unprofitable), R(R) {}
817
818std::string ReportUnprofitable::getRemarkName() const { return "Unprofitable"; }
819
820const BasicBlock *ReportUnprofitable::getRemarkBB() const {
821 return R->getEntry();
822}
823
824std::string ReportUnprofitable::getMessage() const {
825 return "Region can not profitably be optimized!";
826}
827
828std::string ReportUnprofitable::getEndUserMessage() const {
829 return "No profitable polyhedral optimization found";
830}
831
832const 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
841bool ReportUnprofitable::classof(const RejectReason *RR) {
842 return RR->getKind() == RejectReasonKind::Unprofitable;
843}
844} // namespace polly
845

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of polly/lib/Analysis/ScopDetectionDiagnostic.cpp