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 Statistic RejectStatistics[] = {
51     SCOP_STAT(CFG, ""),
52     SCOP_STAT(InvalidTerminator, "Unsupported terminator instruction"),
53     SCOP_STAT(UnreachableInExit, "Unreachable in exit block"),
54     SCOP_STAT(IrreducibleRegion, "Irreducible loops"),
55     SCOP_STAT(LastCFG, ""),
56     SCOP_STAT(AffFunc, ""),
57     SCOP_STAT(UndefCond, "Undefined branch condition"),
58     SCOP_STAT(InvalidCond, "Non-integer branch condition"),
59     SCOP_STAT(UndefOperand, "Undefined operands in comparison"),
60     SCOP_STAT(NonAffBranch, "Non-affine branch condition"),
61     SCOP_STAT(NoBasePtr, "No base pointer"),
62     SCOP_STAT(UndefBasePtr, "Undefined base pointer"),
63     SCOP_STAT(VariantBasePtr, "Variant base pointer"),
64     SCOP_STAT(NonAffineAccess, "Non-affine memory accesses"),
65     SCOP_STAT(DifferentElementSize, "Accesses with differing sizes"),
66     SCOP_STAT(LastAffFunc, ""),
67     SCOP_STAT(LoopBound, "Uncomputable loop bounds"),
68     SCOP_STAT(LoopHasNoExit, "Loop without exit"),
69     SCOP_STAT(LoopHasMultipleExits, "Loop with multiple exits"),
70     SCOP_STAT(LoopOnlySomeLatches, "Not all loop latches in scop"),
71     SCOP_STAT(FuncCall, "Function call with side effects"),
72     SCOP_STAT(NonSimpleMemoryAccess,
73               "Compilated access semantics (volatile or atomic)"),
74     SCOP_STAT(Alias, "Base address aliasing"),
75     SCOP_STAT(Other, ""),
76     SCOP_STAT(IntToPtr, "Integer to pointer conversions"),
77     SCOP_STAT(Alloca, "Stack allocations"),
78     SCOP_STAT(UnknownInst, "Unknown Instructions"),
79     SCOP_STAT(Entry, "Contains entry block"),
80     SCOP_STAT(Unprofitable, "Assumed to be unprofitable"),
81     SCOP_STAT(LastOther, ""),
82 };
83 
84 namespace polly {
85 
86 /// Small string conversion via raw_string_stream.
operator +(Twine LHS,const T & RHS)87 template <typename T> std::string operator+(Twine LHS, const T &RHS) {
88   std::string Buf;
89   raw_string_ostream fmt(Buf);
90   fmt << RHS;
91   fmt.flush();
92 
93   return LHS.concat(Buf).str();
94 }
95 } // namespace polly
96 
97 namespace llvm {
98 
99 // Lexicographic order on (line, col) of our debug locations.
operator <(const DebugLoc & LHS,const DebugLoc & RHS)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 
getBBPairForRegion(const Region * R)108 BBPair getBBPairForRegion(const Region *R) {
109   return std::make_pair(R->getEntry(), R->getExit());
110 }
111 
getDebugLocations(const BBPair & P,DebugLoc & Begin,DebugLoc & End)112 void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End) {
113   SmallPtrSet<BasicBlock *, 32> Seen;
114   SmallVector<BasicBlock *, 32> Todo;
115   Todo.push_back(P.first);
116   while (!Todo.empty()) {
117     auto *BB = Todo.pop_back_val();
118     if (BB == P.second)
119       continue;
120     if (!Seen.insert(BB).second)
121       continue;
122     Todo.append(succ_begin(BB), succ_end(BB));
123     for (const Instruction &Inst : *BB) {
124       DebugLoc DL = Inst.getDebugLoc();
125       if (!DL)
126         continue;
127 
128       Begin = Begin ? std::min(Begin, DL) : DL;
129       End = End ? std::max(End, DL) : DL;
130     }
131   }
132 }
133 
emitRejectionRemarks(const BBPair & P,const RejectLog & Log,OptimizationRemarkEmitter & ORE)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       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(OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Loc,
147                                         RR->getRemarkBB())
148                << RR->getEndUserMessage());
149     else
150       ORE.emit(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         OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.second)
159         << "Invalid Scop candidate ends here.");
160   else
161     ORE.emit(
162         OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.first)
163         << "Invalid Scop candidate ends here.");
164 }
165 
166 //===----------------------------------------------------------------------===//
167 // RejectReason.
168 
RejectReason(RejectReasonKind K)169 RejectReason::RejectReason(RejectReasonKind K) : Kind(K) {
170   RejectStatistics[static_cast<int>(K)]++;
171 }
172 
173 const DebugLoc RejectReason::Unknown = DebugLoc();
174 
getDebugLoc() const175 const DebugLoc &RejectReason::getDebugLoc() const {
176   // Allocate an empty DebugLoc and return it a reference to it.
177   return Unknown;
178 }
179 
180 // RejectLog.
print(raw_ostream & OS,int level) const181 void RejectLog::print(raw_ostream &OS, int level) const {
182   int j = 0;
183   for (auto Reason : ErrorReports)
184     OS.indent(level) << "[" << j++ << "] " << Reason->getMessage() << "\n";
185 }
186 
187 //===----------------------------------------------------------------------===//
188 // ReportCFG.
189 
ReportCFG(const RejectReasonKind K)190 ReportCFG::ReportCFG(const RejectReasonKind K) : RejectReason(K) {}
191 
classof(const RejectReason * RR)192 bool ReportCFG::classof(const RejectReason *RR) {
193   return RR->getKind() >= RejectReasonKind::CFG &&
194          RR->getKind() <= RejectReasonKind::LastCFG;
195 }
196 
197 //===----------------------------------------------------------------------===//
198 // ReportInvalidTerminator.
199 
getRemarkName() const200 std::string ReportInvalidTerminator::getRemarkName() const {
201   return "InvalidTerminator";
202 }
203 
getRemarkBB() const204 const Value *ReportInvalidTerminator::getRemarkBB() const { return BB; }
205 
getMessage() const206 std::string ReportInvalidTerminator::getMessage() const {
207   return ("Invalid instruction terminates BB: " + BB->getName()).str();
208 }
209 
getDebugLoc() const210 const DebugLoc &ReportInvalidTerminator::getDebugLoc() const {
211   return BB->getTerminator()->getDebugLoc();
212 }
213 
classof(const RejectReason * RR)214 bool ReportInvalidTerminator::classof(const RejectReason *RR) {
215   return RR->getKind() == RejectReasonKind::InvalidTerminator;
216 }
217 
218 //===----------------------------------------------------------------------===//
219 // UnreachableInExit.
220 
getRemarkName() const221 std::string ReportUnreachableInExit::getRemarkName() const {
222   return "UnreachableInExit";
223 }
224 
getRemarkBB() const225 const Value *ReportUnreachableInExit::getRemarkBB() const { return BB; }
226 
getMessage() const227 std::string ReportUnreachableInExit::getMessage() const {
228   std::string BBName = BB->getName().str();
229   return "Unreachable in exit block" + BBName;
230 }
231 
getDebugLoc() const232 const DebugLoc &ReportUnreachableInExit::getDebugLoc() const { return DbgLoc; }
233 
getEndUserMessage() const234 std::string ReportUnreachableInExit::getEndUserMessage() const {
235   return "Unreachable in exit block.";
236 }
237 
classof(const RejectReason * RR)238 bool ReportUnreachableInExit::classof(const RejectReason *RR) {
239   return RR->getKind() == RejectReasonKind::UnreachableInExit;
240 }
241 
242 //===----------------------------------------------------------------------===//
243 // ReportIrreducibleRegion.
244 
getRemarkName() const245 std::string ReportIrreducibleRegion::getRemarkName() const {
246   return "IrreducibleRegion";
247 }
248 
getRemarkBB() const249 const Value *ReportIrreducibleRegion::getRemarkBB() const {
250   return R->getEntry();
251 }
252 
getMessage() const253 std::string ReportIrreducibleRegion::getMessage() const {
254   return "Irreducible region encountered: " + R->getNameStr();
255 }
256 
getDebugLoc() const257 const DebugLoc &ReportIrreducibleRegion::getDebugLoc() const { return DbgLoc; }
258 
getEndUserMessage() const259 std::string ReportIrreducibleRegion::getEndUserMessage() const {
260   return "Irreducible region encountered in control flow.";
261 }
262 
classof(const RejectReason * RR)263 bool ReportIrreducibleRegion::classof(const RejectReason *RR) {
264   return RR->getKind() == RejectReasonKind::IrreducibleRegion;
265 }
266 
267 //===----------------------------------------------------------------------===//
268 // ReportAffFunc.
269 
ReportAffFunc(const RejectReasonKind K,const Instruction * Inst)270 ReportAffFunc::ReportAffFunc(const RejectReasonKind K, const Instruction *Inst)
271     : RejectReason(K), Inst(Inst) {}
272 
classof(const RejectReason * RR)273 bool ReportAffFunc::classof(const RejectReason *RR) {
274   return RR->getKind() >= RejectReasonKind::AffFunc &&
275          RR->getKind() <= RejectReasonKind::LastAffFunc;
276 }
277 
278 //===----------------------------------------------------------------------===//
279 // ReportUndefCond.
280 
getRemarkName() const281 std::string ReportUndefCond::getRemarkName() const { return "UndefCond"; }
282 
getRemarkBB() const283 const Value *ReportUndefCond::getRemarkBB() const { return BB; }
284 
getMessage() const285 std::string ReportUndefCond::getMessage() const {
286   return ("Condition based on 'undef' value in BB: " + BB->getName()).str();
287 }
288 
classof(const RejectReason * RR)289 bool ReportUndefCond::classof(const RejectReason *RR) {
290   return RR->getKind() == RejectReasonKind::UndefCond;
291 }
292 
293 //===----------------------------------------------------------------------===//
294 // ReportInvalidCond.
295 
getRemarkName() const296 std::string ReportInvalidCond::getRemarkName() const { return "InvalidCond"; }
297 
getRemarkBB() const298 const Value *ReportInvalidCond::getRemarkBB() const { return BB; }
299 
getMessage() const300 std::string ReportInvalidCond::getMessage() const {
301   return ("Condition in BB '" + BB->getName()).str() +
302          "' neither constant nor an icmp instruction";
303 }
304 
classof(const RejectReason * RR)305 bool ReportInvalidCond::classof(const RejectReason *RR) {
306   return RR->getKind() == RejectReasonKind::InvalidCond;
307 }
308 
309 //===----------------------------------------------------------------------===//
310 // ReportUndefOperand.
311 
getRemarkName() const312 std::string ReportUndefOperand::getRemarkName() const { return "UndefOperand"; }
313 
getRemarkBB() const314 const Value *ReportUndefOperand::getRemarkBB() const { return BB; }
315 
getMessage() const316 std::string ReportUndefOperand::getMessage() const {
317   return ("undef operand in branch at BB: " + BB->getName()).str();
318 }
319 
classof(const RejectReason * RR)320 bool ReportUndefOperand::classof(const RejectReason *RR) {
321   return RR->getKind() == RejectReasonKind::UndefOperand;
322 }
323 
324 //===----------------------------------------------------------------------===//
325 // ReportNonAffBranch.
326 
getRemarkName() const327 std::string ReportNonAffBranch::getRemarkName() const { return "NonAffBranch"; }
328 
getRemarkBB() const329 const Value *ReportNonAffBranch::getRemarkBB() const { return BB; }
330 
getMessage() const331 std::string ReportNonAffBranch::getMessage() const {
332   return ("Non affine branch in BB '" + BB->getName()).str() +
333          "' with LHS: " + *LHS + " and RHS: " + *RHS;
334 }
335 
classof(const RejectReason * RR)336 bool ReportNonAffBranch::classof(const RejectReason *RR) {
337   return RR->getKind() == RejectReasonKind::NonAffBranch;
338 }
339 
340 //===----------------------------------------------------------------------===//
341 // ReportNoBasePtr.
342 
getRemarkName() const343 std::string ReportNoBasePtr::getRemarkName() const { return "NoBasePtr"; }
344 
getRemarkBB() const345 const Value *ReportNoBasePtr::getRemarkBB() const { return Inst->getParent(); }
346 
getMessage() const347 std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; }
348 
classof(const RejectReason * RR)349 bool ReportNoBasePtr::classof(const RejectReason *RR) {
350   return RR->getKind() == RejectReasonKind::NoBasePtr;
351 }
352 
353 //===----------------------------------------------------------------------===//
354 // ReportUndefBasePtr.
355 
getRemarkName() const356 std::string ReportUndefBasePtr::getRemarkName() const { return "UndefBasePtr"; }
357 
getRemarkBB() const358 const Value *ReportUndefBasePtr::getRemarkBB() const {
359   return Inst->getParent();
360 }
361 
getMessage() const362 std::string ReportUndefBasePtr::getMessage() const {
363   return "Undefined base pointer";
364 }
365 
classof(const RejectReason * RR)366 bool ReportUndefBasePtr::classof(const RejectReason *RR) {
367   return RR->getKind() == RejectReasonKind::UndefBasePtr;
368 }
369 
370 //===----------------------------------------------------------------------===//
371 // ReportVariantBasePtr.
372 
getRemarkName() const373 std::string ReportVariantBasePtr::getRemarkName() const {
374   return "VariantBasePtr";
375 }
376 
getRemarkBB() const377 const Value *ReportVariantBasePtr::getRemarkBB() const {
378   return Inst->getParent();
379 }
380 
getMessage() const381 std::string ReportVariantBasePtr::getMessage() const {
382   return "Base address not invariant in current region:" + *BaseValue;
383 }
384 
getEndUserMessage() const385 std::string ReportVariantBasePtr::getEndUserMessage() const {
386   return "The base address of this array is not invariant inside the loop";
387 }
388 
classof(const RejectReason * RR)389 bool ReportVariantBasePtr::classof(const RejectReason *RR) {
390   return RR->getKind() == RejectReasonKind::VariantBasePtr;
391 }
392 
393 //===----------------------------------------------------------------------===//
394 // ReportDifferentArrayElementSize
395 
getRemarkName() const396 std::string ReportDifferentArrayElementSize::getRemarkName() const {
397   return "DifferentArrayElementSize";
398 }
399 
getRemarkBB() const400 const Value *ReportDifferentArrayElementSize::getRemarkBB() const {
401   return Inst->getParent();
402 }
403 
getMessage() const404 std::string ReportDifferentArrayElementSize::getMessage() const {
405   return "Access to one array through data types of different size";
406 }
407 
classof(const RejectReason * RR)408 bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) {
409   return RR->getKind() == RejectReasonKind::DifferentElementSize;
410 }
411 
getEndUserMessage() const412 std::string ReportDifferentArrayElementSize::getEndUserMessage() const {
413   StringRef BaseName = BaseValue->getName();
414   std::string Name = BaseName.empty() ? "UNKNOWN" : BaseName.str();
415   return "The array \"" + Name +
416          "\" is accessed through elements that differ "
417          "in size";
418 }
419 
420 //===----------------------------------------------------------------------===//
421 // ReportNonAffineAccess.
422 
getRemarkName() const423 std::string ReportNonAffineAccess::getRemarkName() const {
424   return "NonAffineAccess";
425 }
426 
getRemarkBB() const427 const Value *ReportNonAffineAccess::getRemarkBB() const {
428   return Inst->getParent();
429 }
430 
getMessage() const431 std::string ReportNonAffineAccess::getMessage() const {
432   return "Non affine access function: " + *AccessFunction;
433 }
434 
classof(const RejectReason * RR)435 bool ReportNonAffineAccess::classof(const RejectReason *RR) {
436   return RR->getKind() == RejectReasonKind::NonAffineAccess;
437 }
438 
getEndUserMessage() const439 std::string ReportNonAffineAccess::getEndUserMessage() const {
440   StringRef BaseName = BaseValue->getName();
441   std::string Name = BaseName.empty() ? "UNKNOWN" : BaseName.str();
442   return "The array subscript of \"" + Name + "\" is not affine";
443 }
444 
445 //===----------------------------------------------------------------------===//
446 // ReportLoopBound.
447 
ReportLoopBound(Loop * L,const SCEV * LoopCount)448 ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount)
449     : RejectReason(RejectReasonKind::LoopBound), L(L), LoopCount(LoopCount),
450       Loc(L->getStartLoc()) {}
451 
getRemarkName() const452 std::string ReportLoopBound::getRemarkName() const { return "LoopBound"; }
453 
getRemarkBB() const454 const Value *ReportLoopBound::getRemarkBB() const { return L->getHeader(); }
455 
getMessage() const456 std::string ReportLoopBound::getMessage() const {
457   return "Non affine loop bound '" + *LoopCount +
458          "' in loop: " + L->getHeader()->getName();
459 }
460 
getDebugLoc() const461 const DebugLoc &ReportLoopBound::getDebugLoc() const { return Loc; }
462 
classof(const RejectReason * RR)463 bool ReportLoopBound::classof(const RejectReason *RR) {
464   return RR->getKind() == RejectReasonKind::LoopBound;
465 }
466 
getEndUserMessage() const467 std::string ReportLoopBound::getEndUserMessage() const {
468   return "Failed to derive an affine function from the loop bounds.";
469 }
470 
471 //===----------------------------------------------------------------------===//
472 // ReportLoopHasNoExit.
473 
getRemarkName() const474 std::string ReportLoopHasNoExit::getRemarkName() const {
475   return "LoopHasNoExit";
476 }
477 
getRemarkBB() const478 const Value *ReportLoopHasNoExit::getRemarkBB() const { return L->getHeader(); }
479 
getMessage() const480 std::string ReportLoopHasNoExit::getMessage() const {
481   return "Loop " + L->getHeader()->getName() + " has no exit.";
482 }
483 
classof(const RejectReason * RR)484 bool ReportLoopHasNoExit::classof(const RejectReason *RR) {
485   return RR->getKind() == RejectReasonKind::LoopHasNoExit;
486 }
487 
getDebugLoc() const488 const DebugLoc &ReportLoopHasNoExit::getDebugLoc() const { return Loc; }
489 
getEndUserMessage() const490 std::string ReportLoopHasNoExit::getEndUserMessage() const {
491   return "Loop cannot be handled because it has no exit.";
492 }
493 
494 //===----------------------------------------------------------------------===//
495 // ReportLoopHasMultipleExits.
496 
getRemarkName() const497 std::string ReportLoopHasMultipleExits::getRemarkName() const {
498   return "ReportLoopHasMultipleExits";
499 }
500 
getRemarkBB() const501 const Value *ReportLoopHasMultipleExits::getRemarkBB() const {
502   return L->getHeader();
503 }
504 
getMessage() const505 std::string ReportLoopHasMultipleExits::getMessage() const {
506   return "Loop " + L->getHeader()->getName() + " has multiple exits.";
507 }
508 
classof(const RejectReason * RR)509 bool ReportLoopHasMultipleExits::classof(const RejectReason *RR) {
510   return RR->getKind() == RejectReasonKind::LoopHasMultipleExits;
511 }
512 
getDebugLoc() const513 const DebugLoc &ReportLoopHasMultipleExits::getDebugLoc() const { return Loc; }
514 
getEndUserMessage() const515 std::string ReportLoopHasMultipleExits::getEndUserMessage() const {
516   return "Loop cannot be handled because it has multiple exits.";
517 }
518 
519 //===----------------------------------------------------------------------===//
520 // ReportLoopOnlySomeLatches
521 
getRemarkName() const522 std::string ReportLoopOnlySomeLatches::getRemarkName() const {
523   return "LoopHasNoExit";
524 }
525 
getRemarkBB() const526 const Value *ReportLoopOnlySomeLatches::getRemarkBB() const {
527   return L->getHeader();
528 }
529 
getMessage() const530 std::string ReportLoopOnlySomeLatches::getMessage() const {
531   return "Not all latches of loop " + L->getHeader()->getName() +
532          " part of scop.";
533 }
534 
classof(const RejectReason * RR)535 bool ReportLoopOnlySomeLatches::classof(const RejectReason *RR) {
536   return RR->getKind() == RejectReasonKind::LoopHasNoExit;
537 }
538 
getDebugLoc() const539 const DebugLoc &ReportLoopOnlySomeLatches::getDebugLoc() const { return Loc; }
540 
getEndUserMessage() const541 std::string ReportLoopOnlySomeLatches::getEndUserMessage() const {
542   return "Loop cannot be handled because not all latches are part of loop "
543          "region.";
544 }
545 
546 //===----------------------------------------------------------------------===//
547 // ReportFuncCall.
548 
ReportFuncCall(Instruction * Inst)549 ReportFuncCall::ReportFuncCall(Instruction *Inst)
550     : RejectReason(RejectReasonKind::FuncCall), Inst(Inst) {}
551 
getRemarkName() const552 std::string ReportFuncCall::getRemarkName() const { return "FuncCall"; }
553 
getRemarkBB() const554 const Value *ReportFuncCall::getRemarkBB() const { return Inst->getParent(); }
555 
getMessage() const556 std::string ReportFuncCall::getMessage() const {
557   return "Call instruction: " + *Inst;
558 }
559 
getDebugLoc() const560 const DebugLoc &ReportFuncCall::getDebugLoc() const {
561   return Inst->getDebugLoc();
562 }
563 
getEndUserMessage() const564 std::string ReportFuncCall::getEndUserMessage() const {
565   return "This function call cannot be handled. "
566          "Try to inline it.";
567 }
568 
classof(const RejectReason * RR)569 bool ReportFuncCall::classof(const RejectReason *RR) {
570   return RR->getKind() == RejectReasonKind::FuncCall;
571 }
572 
573 //===----------------------------------------------------------------------===//
574 // ReportNonSimpleMemoryAccess
575 
ReportNonSimpleMemoryAccess(Instruction * Inst)576 ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst)
577     : ReportOther(RejectReasonKind::NonSimpleMemoryAccess), Inst(Inst) {}
578 
getRemarkName() const579 std::string ReportNonSimpleMemoryAccess::getRemarkName() const {
580   return "NonSimpleMemoryAccess";
581 }
582 
getRemarkBB() const583 const Value *ReportNonSimpleMemoryAccess::getRemarkBB() const {
584   return Inst->getParent();
585 }
586 
getMessage() const587 std::string ReportNonSimpleMemoryAccess::getMessage() const {
588   return "Non-simple memory access: " + *Inst;
589 }
590 
getDebugLoc() const591 const DebugLoc &ReportNonSimpleMemoryAccess::getDebugLoc() const {
592   return Inst->getDebugLoc();
593 }
594 
getEndUserMessage() const595 std::string ReportNonSimpleMemoryAccess::getEndUserMessage() const {
596   return "Volatile memory accesses or memory accesses for atomic types "
597          "are not supported.";
598 }
599 
classof(const RejectReason * RR)600 bool ReportNonSimpleMemoryAccess::classof(const RejectReason *RR) {
601   return RR->getKind() == RejectReasonKind::NonSimpleMemoryAccess;
602 }
603 
604 //===----------------------------------------------------------------------===//
605 // ReportAlias.
606 
ReportAlias(Instruction * Inst,AliasSet & AS)607 ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS)
608     : RejectReason(RejectReasonKind::Alias), Inst(Inst) {
609   for (const auto &I : AS)
610     Pointers.push_back(I.getValue());
611 }
612 
formatInvalidAlias(std::string Prefix,std::string Suffix) const613 std::string ReportAlias::formatInvalidAlias(std::string Prefix,
614                                             std::string Suffix) const {
615   std::string Message;
616   raw_string_ostream OS(Message);
617 
618   OS << Prefix;
619 
620   for (PointerSnapshotTy::const_iterator PI = Pointers.begin(),
621                                          PE = Pointers.end();
622        ;) {
623     const Value *V = *PI;
624     assert(V && "Diagnostic info does not match found LLVM-IR anymore.");
625 
626     if (V->getName().empty())
627       OS << "\" <unknown> \"";
628     else
629       OS << "\"" << V->getName() << "\"";
630 
631     ++PI;
632 
633     if (PI != PE)
634       OS << ", ";
635     else
636       break;
637   }
638 
639   OS << Suffix;
640 
641   return OS.str();
642 }
643 
getRemarkName() const644 std::string ReportAlias::getRemarkName() const { return "Alias"; }
645 
getRemarkBB() const646 const Value *ReportAlias::getRemarkBB() const { return Inst->getParent(); }
647 
getMessage() const648 std::string ReportAlias::getMessage() const {
649   return formatInvalidAlias("Possible aliasing: ");
650 }
651 
getEndUserMessage() const652 std::string ReportAlias::getEndUserMessage() const {
653   return formatInvalidAlias("Accesses to the arrays ",
654                             " may access the same memory.");
655 }
656 
getDebugLoc() const657 const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); }
658 
classof(const RejectReason * RR)659 bool ReportAlias::classof(const RejectReason *RR) {
660   return RR->getKind() == RejectReasonKind::Alias;
661 }
662 
663 //===----------------------------------------------------------------------===//
664 // ReportOther.
665 
getRemarkName() const666 std::string ReportOther::getRemarkName() const { return "UnknownRejectReason"; }
667 
getMessage() const668 std::string ReportOther::getMessage() const { return "Unknown reject reason"; }
669 
ReportOther(const RejectReasonKind K)670 ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {}
671 
classof(const RejectReason * RR)672 bool ReportOther::classof(const RejectReason *RR) {
673   return RR->getKind() >= RejectReasonKind::Other &&
674          RR->getKind() <= RejectReasonKind::LastOther;
675 }
676 
677 //===----------------------------------------------------------------------===//
678 // ReportIntToPtr.
ReportIntToPtr(Instruction * BaseValue)679 ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue)
680     : ReportOther(RejectReasonKind::IntToPtr), BaseValue(BaseValue) {}
681 
getRemarkName() const682 std::string ReportIntToPtr::getRemarkName() const { return "IntToPtr"; }
683 
getRemarkBB() const684 const Value *ReportIntToPtr::getRemarkBB() const {
685   return BaseValue->getParent();
686 }
687 
getMessage() const688 std::string ReportIntToPtr::getMessage() const {
689   return "Find bad intToptr prt: " + *BaseValue;
690 }
691 
getDebugLoc() const692 const DebugLoc &ReportIntToPtr::getDebugLoc() const {
693   return BaseValue->getDebugLoc();
694 }
695 
classof(const RejectReason * RR)696 bool ReportIntToPtr::classof(const RejectReason *RR) {
697   return RR->getKind() == RejectReasonKind::IntToPtr;
698 }
699 
700 //===----------------------------------------------------------------------===//
701 // ReportAlloca.
702 
ReportAlloca(Instruction * Inst)703 ReportAlloca::ReportAlloca(Instruction *Inst)
704     : ReportOther(RejectReasonKind::Alloca), Inst(Inst) {}
705 
getRemarkName() const706 std::string ReportAlloca::getRemarkName() const { return "Alloca"; }
707 
getRemarkBB() const708 const Value *ReportAlloca::getRemarkBB() const { return Inst->getParent(); }
709 
getMessage() const710 std::string ReportAlloca::getMessage() const {
711   return "Alloca instruction: " + *Inst;
712 }
713 
getDebugLoc() const714 const DebugLoc &ReportAlloca::getDebugLoc() const {
715   return Inst->getDebugLoc();
716 }
717 
classof(const RejectReason * RR)718 bool ReportAlloca::classof(const RejectReason *RR) {
719   return RR->getKind() == RejectReasonKind::Alloca;
720 }
721 
722 //===----------------------------------------------------------------------===//
723 // ReportUnknownInst.
724 
ReportUnknownInst(Instruction * Inst)725 ReportUnknownInst::ReportUnknownInst(Instruction *Inst)
726     : ReportOther(RejectReasonKind::UnknownInst), Inst(Inst) {}
727 
getRemarkName() const728 std::string ReportUnknownInst::getRemarkName() const { return "UnknownInst"; }
729 
getRemarkBB() const730 const Value *ReportUnknownInst::getRemarkBB() const {
731   return Inst->getParent();
732 }
733 
getMessage() const734 std::string ReportUnknownInst::getMessage() const {
735   return "Unknown instruction: " + *Inst;
736 }
737 
getDebugLoc() const738 const DebugLoc &ReportUnknownInst::getDebugLoc() const {
739   return Inst->getDebugLoc();
740 }
741 
classof(const RejectReason * RR)742 bool ReportUnknownInst::classof(const RejectReason *RR) {
743   return RR->getKind() == RejectReasonKind::UnknownInst;
744 }
745 
746 //===----------------------------------------------------------------------===//
747 // ReportEntry.
748 
ReportEntry(BasicBlock * BB)749 ReportEntry::ReportEntry(BasicBlock *BB)
750     : ReportOther(RejectReasonKind::Entry), BB(BB) {}
751 
getRemarkName() const752 std::string ReportEntry::getRemarkName() const { return "Entry"; }
753 
getRemarkBB() const754 const Value *ReportEntry::getRemarkBB() const { return BB; }
755 
getMessage() const756 std::string ReportEntry::getMessage() const {
757   return "Region containing entry block of function is invalid!";
758 }
759 
getEndUserMessage() const760 std::string ReportEntry::getEndUserMessage() const {
761   return "Scop contains function entry (not yet supported).";
762 }
763 
getDebugLoc() const764 const DebugLoc &ReportEntry::getDebugLoc() const {
765   return BB->getTerminator()->getDebugLoc();
766 }
767 
classof(const RejectReason * RR)768 bool ReportEntry::classof(const RejectReason *RR) {
769   return RR->getKind() == RejectReasonKind::Entry;
770 }
771 
772 //===----------------------------------------------------------------------===//
773 // ReportUnprofitable.
774 
ReportUnprofitable(Region * R)775 ReportUnprofitable::ReportUnprofitable(Region *R)
776     : ReportOther(RejectReasonKind::Unprofitable), R(R) {}
777 
getRemarkName() const778 std::string ReportUnprofitable::getRemarkName() const { return "Unprofitable"; }
779 
getRemarkBB() const780 const Value *ReportUnprofitable::getRemarkBB() const { return R->getEntry(); }
781 
getMessage() const782 std::string ReportUnprofitable::getMessage() const {
783   return "Region can not profitably be optimized!";
784 }
785 
getEndUserMessage() const786 std::string ReportUnprofitable::getEndUserMessage() const {
787   return "No profitable polyhedral optimization found";
788 }
789 
getDebugLoc() const790 const DebugLoc &ReportUnprofitable::getDebugLoc() const {
791   for (const BasicBlock *BB : R->blocks())
792     for (const Instruction &Inst : *BB)
793       if (const DebugLoc &DL = Inst.getDebugLoc())
794         return DL;
795 
796   return R->getEntry()->getTerminator()->getDebugLoc();
797 }
798 
classof(const RejectReason * RR)799 bool ReportUnprofitable::classof(const RejectReason *RR) {
800   return RR->getKind() == RejectReasonKind::Unprofitable;
801 }
802 } // namespace polly
803