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

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