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               "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 
85 namespace polly {
86 
87 /// Small string conversion via raw_string_stream.
operator +(Twine LHS,const T & RHS)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   fmt.flush();
93 
94   return LHS.concat(Buf).str();
95 }
96 } // namespace polly
97 
98 namespace llvm {
99 
100 // Lexicographic order on (line, col) of our debug locations.
operator <(const DebugLoc & LHS,const DebugLoc & RHS)101 static 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 
107 namespace polly {
108 
getBBPairForRegion(const Region * R)109 BBPair getBBPairForRegion(const Region *R) {
110   return std::make_pair(R->getEntry(), R->getExit());
111 }
112 
getDebugLocations(const BBPair & P,DebugLoc & Begin,DebugLoc & End)113 void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End) {
114   SmallPtrSet<BasicBlock *, 32> Seen;
115   SmallVector<BasicBlock *, 32> Todo;
116   Todo.push_back(P.first);
117   while (!Todo.empty()) {
118     auto *BB = Todo.pop_back_val();
119     if (BB == P.second)
120       continue;
121     if (!Seen.insert(BB).second)
122       continue;
123     Todo.append(succ_begin(BB), succ_end(BB));
124     for (const Instruction &Inst : *BB) {
125       DebugLoc DL = Inst.getDebugLoc();
126       if (!DL)
127         continue;
128 
129       Begin = Begin ? std::min(Begin, DL) : DL;
130       End = End ? std::max(End, DL) : DL;
131     }
132   }
133 }
134 
emitRejectionRemarks(const BBPair & P,const RejectLog & Log,OptimizationRemarkEmitter & ORE)135 void emitRejectionRemarks(const BBPair &P, const RejectLog &Log,
136                           OptimizationRemarkEmitter &ORE) {
137   DebugLoc Begin, End;
138   getDebugLocations(P, Begin, End);
139 
140   ORE.emit(
141       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(OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Loc,
148                                         RR->getRemarkBB())
149                << RR->getEndUserMessage());
150     else
151       ORE.emit(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         OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.second)
160         << "Invalid Scop candidate ends here.");
161   else
162     ORE.emit(
163         OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.first)
164         << "Invalid Scop candidate ends here.");
165 }
166 
167 //===----------------------------------------------------------------------===//
168 // RejectReason.
169 
RejectReason(RejectReasonKind K)170 RejectReason::RejectReason(RejectReasonKind K) : Kind(K) {
171   RejectStatistics[static_cast<int>(K)]++;
172 }
173 
174 const DebugLoc RejectReason::Unknown = DebugLoc();
175 
getDebugLoc() const176 const DebugLoc &RejectReason::getDebugLoc() const {
177   // Allocate an empty DebugLoc and return it a reference to it.
178   return Unknown;
179 }
180 
181 // RejectLog.
print(raw_ostream & OS,int level) const182 void RejectLog::print(raw_ostream &OS, int level) const {
183   int j = 0;
184   for (auto Reason : ErrorReports)
185     OS.indent(level) << "[" << j++ << "] " << Reason->getMessage() << "\n";
186 }
187 
188 //===----------------------------------------------------------------------===//
189 // ReportCFG.
190 
ReportCFG(const RejectReasonKind K)191 ReportCFG::ReportCFG(const RejectReasonKind K) : RejectReason(K) {}
192 
classof(const RejectReason * RR)193 bool ReportCFG::classof(const RejectReason *RR) {
194   return RR->getKind() >= RejectReasonKind::CFG &&
195          RR->getKind() <= RejectReasonKind::LastCFG;
196 }
197 
198 //===----------------------------------------------------------------------===//
199 // ReportInvalidTerminator.
200 
getRemarkName() const201 std::string ReportInvalidTerminator::getRemarkName() const {
202   return "InvalidTerminator";
203 }
204 
getRemarkBB() const205 const Value *ReportInvalidTerminator::getRemarkBB() const { return BB; }
206 
getMessage() const207 std::string ReportInvalidTerminator::getMessage() const {
208   return ("Invalid instruction terminates BB: " + BB->getName()).str();
209 }
210 
getDebugLoc() const211 const DebugLoc &ReportInvalidTerminator::getDebugLoc() const {
212   return BB->getTerminator()->getDebugLoc();
213 }
214 
classof(const RejectReason * RR)215 bool ReportInvalidTerminator::classof(const RejectReason *RR) {
216   return RR->getKind() == RejectReasonKind::InvalidTerminator;
217 }
218 
219 //===----------------------------------------------------------------------===//
220 // UnreachableInExit.
221 
getRemarkName() const222 std::string ReportUnreachableInExit::getRemarkName() const {
223   return "UnreachableInExit";
224 }
225 
getRemarkBB() const226 const Value *ReportUnreachableInExit::getRemarkBB() const { return BB; }
227 
getMessage() const228 std::string ReportUnreachableInExit::getMessage() const {
229   std::string BBName = BB->getName().str();
230   return "Unreachable in exit block" + BBName;
231 }
232 
getDebugLoc() const233 const DebugLoc &ReportUnreachableInExit::getDebugLoc() const { return DbgLoc; }
234 
getEndUserMessage() const235 std::string ReportUnreachableInExit::getEndUserMessage() const {
236   return "Unreachable in exit block.";
237 }
238 
classof(const RejectReason * RR)239 bool ReportUnreachableInExit::classof(const RejectReason *RR) {
240   return RR->getKind() == RejectReasonKind::UnreachableInExit;
241 }
242 
243 //===----------------------------------------------------------------------===//
244 // IndirectPredecessor.
245 
getRemarkName() const246 std::string ReportIndirectPredecessor::getRemarkName() const {
247   return "IndirectPredecessor";
248 }
249 
getRemarkBB() const250 const Value *ReportIndirectPredecessor::getRemarkBB() const {
251   if (Inst)
252     return Inst->getParent();
253   return nullptr;
254 }
255 
getMessage() const256 std::string ReportIndirectPredecessor::getMessage() const {
257   if (Inst)
258     return "Branch from indirect terminator: " + *Inst;
259   return getEndUserMessage();
260 }
261 
getDebugLoc() const262 const DebugLoc &ReportIndirectPredecessor::getDebugLoc() const {
263   return DbgLoc;
264 }
265 
getEndUserMessage() const266 std::string ReportIndirectPredecessor::getEndUserMessage() const {
267   return "Branch from indirect terminator.";
268 }
269 
classof(const RejectReason * RR)270 bool ReportIndirectPredecessor::classof(const RejectReason *RR) {
271   return RR->getKind() == RejectReasonKind::IndirectPredecessor;
272 }
273 
274 //===----------------------------------------------------------------------===//
275 // ReportIrreducibleRegion.
276 
getRemarkName() const277 std::string ReportIrreducibleRegion::getRemarkName() const {
278   return "IrreducibleRegion";
279 }
280 
getRemarkBB() const281 const Value *ReportIrreducibleRegion::getRemarkBB() const {
282   return R->getEntry();
283 }
284 
getMessage() const285 std::string ReportIrreducibleRegion::getMessage() const {
286   return "Irreducible region encountered: " + R->getNameStr();
287 }
288 
getDebugLoc() const289 const DebugLoc &ReportIrreducibleRegion::getDebugLoc() const { return DbgLoc; }
290 
getEndUserMessage() const291 std::string ReportIrreducibleRegion::getEndUserMessage() const {
292   return "Irreducible region encountered in control flow.";
293 }
294 
classof(const RejectReason * RR)295 bool ReportIrreducibleRegion::classof(const RejectReason *RR) {
296   return RR->getKind() == RejectReasonKind::IrreducibleRegion;
297 }
298 
299 //===----------------------------------------------------------------------===//
300 // ReportAffFunc.
301 
ReportAffFunc(const RejectReasonKind K,const Instruction * Inst)302 ReportAffFunc::ReportAffFunc(const RejectReasonKind K, const Instruction *Inst)
303     : RejectReason(K), Inst(Inst) {}
304 
classof(const RejectReason * RR)305 bool ReportAffFunc::classof(const RejectReason *RR) {
306   return RR->getKind() >= RejectReasonKind::AffFunc &&
307          RR->getKind() <= RejectReasonKind::LastAffFunc;
308 }
309 
310 //===----------------------------------------------------------------------===//
311 // ReportUndefCond.
312 
getRemarkName() const313 std::string ReportUndefCond::getRemarkName() const { return "UndefCond"; }
314 
getRemarkBB() const315 const Value *ReportUndefCond::getRemarkBB() const { return BB; }
316 
getMessage() const317 std::string ReportUndefCond::getMessage() const {
318   return ("Condition based on 'undef' value in BB: " + BB->getName()).str();
319 }
320 
classof(const RejectReason * RR)321 bool ReportUndefCond::classof(const RejectReason *RR) {
322   return RR->getKind() == RejectReasonKind::UndefCond;
323 }
324 
325 //===----------------------------------------------------------------------===//
326 // ReportInvalidCond.
327 
getRemarkName() const328 std::string ReportInvalidCond::getRemarkName() const { return "InvalidCond"; }
329 
getRemarkBB() const330 const Value *ReportInvalidCond::getRemarkBB() const { return BB; }
331 
getMessage() const332 std::string ReportInvalidCond::getMessage() const {
333   return ("Condition in BB '" + BB->getName()).str() +
334          "' neither constant nor an icmp instruction";
335 }
336 
classof(const RejectReason * RR)337 bool ReportInvalidCond::classof(const RejectReason *RR) {
338   return RR->getKind() == RejectReasonKind::InvalidCond;
339 }
340 
341 //===----------------------------------------------------------------------===//
342 // ReportUndefOperand.
343 
getRemarkName() const344 std::string ReportUndefOperand::getRemarkName() const { return "UndefOperand"; }
345 
getRemarkBB() const346 const Value *ReportUndefOperand::getRemarkBB() const { return BB; }
347 
getMessage() const348 std::string ReportUndefOperand::getMessage() const {
349   return ("undef operand in branch at BB: " + BB->getName()).str();
350 }
351 
classof(const RejectReason * RR)352 bool ReportUndefOperand::classof(const RejectReason *RR) {
353   return RR->getKind() == RejectReasonKind::UndefOperand;
354 }
355 
356 //===----------------------------------------------------------------------===//
357 // ReportNonAffBranch.
358 
getRemarkName() const359 std::string ReportNonAffBranch::getRemarkName() const { return "NonAffBranch"; }
360 
getRemarkBB() const361 const Value *ReportNonAffBranch::getRemarkBB() const { return BB; }
362 
getMessage() const363 std::string ReportNonAffBranch::getMessage() const {
364   return ("Non affine branch in BB '" + BB->getName()).str() +
365          "' with LHS: " + *LHS + " and RHS: " + *RHS;
366 }
367 
classof(const RejectReason * RR)368 bool ReportNonAffBranch::classof(const RejectReason *RR) {
369   return RR->getKind() == RejectReasonKind::NonAffBranch;
370 }
371 
372 //===----------------------------------------------------------------------===//
373 // ReportNoBasePtr.
374 
getRemarkName() const375 std::string ReportNoBasePtr::getRemarkName() const { return "NoBasePtr"; }
376 
getRemarkBB() const377 const Value *ReportNoBasePtr::getRemarkBB() const { return Inst->getParent(); }
378 
getMessage() const379 std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; }
380 
classof(const RejectReason * RR)381 bool ReportNoBasePtr::classof(const RejectReason *RR) {
382   return RR->getKind() == RejectReasonKind::NoBasePtr;
383 }
384 
385 //===----------------------------------------------------------------------===//
386 // ReportUndefBasePtr.
387 
getRemarkName() const388 std::string ReportUndefBasePtr::getRemarkName() const { return "UndefBasePtr"; }
389 
getRemarkBB() const390 const Value *ReportUndefBasePtr::getRemarkBB() const {
391   return Inst->getParent();
392 }
393 
getMessage() const394 std::string ReportUndefBasePtr::getMessage() const {
395   return "Undefined base pointer";
396 }
397 
classof(const RejectReason * RR)398 bool ReportUndefBasePtr::classof(const RejectReason *RR) {
399   return RR->getKind() == RejectReasonKind::UndefBasePtr;
400 }
401 
402 //===----------------------------------------------------------------------===//
403 // ReportVariantBasePtr.
404 
getRemarkName() const405 std::string ReportVariantBasePtr::getRemarkName() const {
406   return "VariantBasePtr";
407 }
408 
getRemarkBB() const409 const Value *ReportVariantBasePtr::getRemarkBB() const {
410   return Inst->getParent();
411 }
412 
getMessage() const413 std::string ReportVariantBasePtr::getMessage() const {
414   return "Base address not invariant in current region:" + *BaseValue;
415 }
416 
getEndUserMessage() const417 std::string ReportVariantBasePtr::getEndUserMessage() const {
418   return "The base address of this array is not invariant inside the loop";
419 }
420 
classof(const RejectReason * RR)421 bool ReportVariantBasePtr::classof(const RejectReason *RR) {
422   return RR->getKind() == RejectReasonKind::VariantBasePtr;
423 }
424 
425 //===----------------------------------------------------------------------===//
426 // ReportDifferentArrayElementSize
427 
getRemarkName() const428 std::string ReportDifferentArrayElementSize::getRemarkName() const {
429   return "DifferentArrayElementSize";
430 }
431 
getRemarkBB() const432 const Value *ReportDifferentArrayElementSize::getRemarkBB() const {
433   return Inst->getParent();
434 }
435 
getMessage() const436 std::string ReportDifferentArrayElementSize::getMessage() const {
437   return "Access to one array through data types of different size";
438 }
439 
classof(const RejectReason * RR)440 bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) {
441   return RR->getKind() == RejectReasonKind::DifferentElementSize;
442 }
443 
getEndUserMessage() const444 std::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 
getRemarkName() const455 std::string ReportNonAffineAccess::getRemarkName() const {
456   return "NonAffineAccess";
457 }
458 
getRemarkBB() const459 const Value *ReportNonAffineAccess::getRemarkBB() const {
460   return Inst->getParent();
461 }
462 
getMessage() const463 std::string ReportNonAffineAccess::getMessage() const {
464   return "Non affine access function: " + *AccessFunction;
465 }
466 
classof(const RejectReason * RR)467 bool ReportNonAffineAccess::classof(const RejectReason *RR) {
468   return RR->getKind() == RejectReasonKind::NonAffineAccess;
469 }
470 
getEndUserMessage() const471 std::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 
ReportLoopBound(Loop * L,const SCEV * LoopCount)480 ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount)
481     : RejectReason(RejectReasonKind::LoopBound), L(L), LoopCount(LoopCount),
482       Loc(L->getStartLoc()) {}
483 
getRemarkName() const484 std::string ReportLoopBound::getRemarkName() const { return "LoopBound"; }
485 
getRemarkBB() const486 const Value *ReportLoopBound::getRemarkBB() const { return L->getHeader(); }
487 
getMessage() const488 std::string ReportLoopBound::getMessage() const {
489   return "Non affine loop bound '" + *LoopCount +
490          "' in loop: " + L->getHeader()->getName();
491 }
492 
getDebugLoc() const493 const DebugLoc &ReportLoopBound::getDebugLoc() const { return Loc; }
494 
classof(const RejectReason * RR)495 bool ReportLoopBound::classof(const RejectReason *RR) {
496   return RR->getKind() == RejectReasonKind::LoopBound;
497 }
498 
getEndUserMessage() const499 std::string ReportLoopBound::getEndUserMessage() const {
500   return "Failed to derive an affine function from the loop bounds.";
501 }
502 
503 //===----------------------------------------------------------------------===//
504 // ReportLoopHasNoExit.
505 
getRemarkName() const506 std::string ReportLoopHasNoExit::getRemarkName() const {
507   return "LoopHasNoExit";
508 }
509 
getRemarkBB() const510 const Value *ReportLoopHasNoExit::getRemarkBB() const { return L->getHeader(); }
511 
getMessage() const512 std::string ReportLoopHasNoExit::getMessage() const {
513   return "Loop " + L->getHeader()->getName() + " has no exit.";
514 }
515 
classof(const RejectReason * RR)516 bool ReportLoopHasNoExit::classof(const RejectReason *RR) {
517   return RR->getKind() == RejectReasonKind::LoopHasNoExit;
518 }
519 
getDebugLoc() const520 const DebugLoc &ReportLoopHasNoExit::getDebugLoc() const { return Loc; }
521 
getEndUserMessage() const522 std::string ReportLoopHasNoExit::getEndUserMessage() const {
523   return "Loop cannot be handled because it has no exit.";
524 }
525 
526 //===----------------------------------------------------------------------===//
527 // ReportLoopHasMultipleExits.
528 
getRemarkName() const529 std::string ReportLoopHasMultipleExits::getRemarkName() const {
530   return "ReportLoopHasMultipleExits";
531 }
532 
getRemarkBB() const533 const Value *ReportLoopHasMultipleExits::getRemarkBB() const {
534   return L->getHeader();
535 }
536 
getMessage() const537 std::string ReportLoopHasMultipleExits::getMessage() const {
538   return "Loop " + L->getHeader()->getName() + " has multiple exits.";
539 }
540 
classof(const RejectReason * RR)541 bool ReportLoopHasMultipleExits::classof(const RejectReason *RR) {
542   return RR->getKind() == RejectReasonKind::LoopHasMultipleExits;
543 }
544 
getDebugLoc() const545 const DebugLoc &ReportLoopHasMultipleExits::getDebugLoc() const { return Loc; }
546 
getEndUserMessage() const547 std::string ReportLoopHasMultipleExits::getEndUserMessage() const {
548   return "Loop cannot be handled because it has multiple exits.";
549 }
550 
551 //===----------------------------------------------------------------------===//
552 // ReportLoopOnlySomeLatches
553 
getRemarkName() const554 std::string ReportLoopOnlySomeLatches::getRemarkName() const {
555   return "LoopHasNoExit";
556 }
557 
getRemarkBB() const558 const Value *ReportLoopOnlySomeLatches::getRemarkBB() const {
559   return L->getHeader();
560 }
561 
getMessage() const562 std::string ReportLoopOnlySomeLatches::getMessage() const {
563   return "Not all latches of loop " + L->getHeader()->getName() +
564          " part of scop.";
565 }
566 
classof(const RejectReason * RR)567 bool ReportLoopOnlySomeLatches::classof(const RejectReason *RR) {
568   return RR->getKind() == RejectReasonKind::LoopHasNoExit;
569 }
570 
getDebugLoc() const571 const DebugLoc &ReportLoopOnlySomeLatches::getDebugLoc() const { return Loc; }
572 
getEndUserMessage() const573 std::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 
ReportFuncCall(Instruction * Inst)581 ReportFuncCall::ReportFuncCall(Instruction *Inst)
582     : RejectReason(RejectReasonKind::FuncCall), Inst(Inst) {}
583 
getRemarkName() const584 std::string ReportFuncCall::getRemarkName() const { return "FuncCall"; }
585 
getRemarkBB() const586 const Value *ReportFuncCall::getRemarkBB() const { return Inst->getParent(); }
587 
getMessage() const588 std::string ReportFuncCall::getMessage() const {
589   return "Call instruction: " + *Inst;
590 }
591 
getDebugLoc() const592 const DebugLoc &ReportFuncCall::getDebugLoc() const {
593   return Inst->getDebugLoc();
594 }
595 
getEndUserMessage() const596 std::string ReportFuncCall::getEndUserMessage() const {
597   return "This function call cannot be handled. "
598          "Try to inline it.";
599 }
600 
classof(const RejectReason * RR)601 bool ReportFuncCall::classof(const RejectReason *RR) {
602   return RR->getKind() == RejectReasonKind::FuncCall;
603 }
604 
605 //===----------------------------------------------------------------------===//
606 // ReportNonSimpleMemoryAccess
607 
ReportNonSimpleMemoryAccess(Instruction * Inst)608 ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst)
609     : ReportOther(RejectReasonKind::NonSimpleMemoryAccess), Inst(Inst) {}
610 
getRemarkName() const611 std::string ReportNonSimpleMemoryAccess::getRemarkName() const {
612   return "NonSimpleMemoryAccess";
613 }
614 
getRemarkBB() const615 const Value *ReportNonSimpleMemoryAccess::getRemarkBB() const {
616   return Inst->getParent();
617 }
618 
getMessage() const619 std::string ReportNonSimpleMemoryAccess::getMessage() const {
620   return "Non-simple memory access: " + *Inst;
621 }
622 
getDebugLoc() const623 const DebugLoc &ReportNonSimpleMemoryAccess::getDebugLoc() const {
624   return Inst->getDebugLoc();
625 }
626 
getEndUserMessage() const627 std::string ReportNonSimpleMemoryAccess::getEndUserMessage() const {
628   return "Volatile memory accesses or memory accesses for atomic types "
629          "are not supported.";
630 }
631 
classof(const RejectReason * RR)632 bool ReportNonSimpleMemoryAccess::classof(const RejectReason *RR) {
633   return RR->getKind() == RejectReasonKind::NonSimpleMemoryAccess;
634 }
635 
636 //===----------------------------------------------------------------------===//
637 // ReportAlias.
638 
ReportAlias(Instruction * Inst,AliasSet & AS)639 ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS)
640     : RejectReason(RejectReasonKind::Alias), Inst(Inst) {
641   for (const auto &I : AS)
642     Pointers.push_back(I.getValue());
643 }
644 
formatInvalidAlias(std::string Prefix,std::string Suffix) const645 std::string ReportAlias::formatInvalidAlias(std::string Prefix,
646                                             std::string Suffix) const {
647   std::string Message;
648   raw_string_ostream OS(Message);
649 
650   OS << Prefix;
651 
652   for (PointerSnapshotTy::const_iterator PI = Pointers.begin(),
653                                          PE = Pointers.end();
654        ;) {
655     const Value *V = *PI;
656     assert(V && "Diagnostic info does not match found LLVM-IR anymore.");
657 
658     if (V->getName().empty())
659       OS << "\" <unknown> \"";
660     else
661       OS << "\"" << V->getName() << "\"";
662 
663     ++PI;
664 
665     if (PI != PE)
666       OS << ", ";
667     else
668       break;
669   }
670 
671   OS << Suffix;
672 
673   return OS.str();
674 }
675 
getRemarkName() const676 std::string ReportAlias::getRemarkName() const { return "Alias"; }
677 
getRemarkBB() const678 const Value *ReportAlias::getRemarkBB() const { return Inst->getParent(); }
679 
getMessage() const680 std::string ReportAlias::getMessage() const {
681   return formatInvalidAlias("Possible aliasing: ");
682 }
683 
getEndUserMessage() const684 std::string ReportAlias::getEndUserMessage() const {
685   return formatInvalidAlias("Accesses to the arrays ",
686                             " may access the same memory.");
687 }
688 
getDebugLoc() const689 const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); }
690 
classof(const RejectReason * RR)691 bool ReportAlias::classof(const RejectReason *RR) {
692   return RR->getKind() == RejectReasonKind::Alias;
693 }
694 
695 //===----------------------------------------------------------------------===//
696 // ReportOther.
697 
getRemarkName() const698 std::string ReportOther::getRemarkName() const { return "UnknownRejectReason"; }
699 
getMessage() const700 std::string ReportOther::getMessage() const { return "Unknown reject reason"; }
701 
ReportOther(const RejectReasonKind K)702 ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {}
703 
classof(const RejectReason * RR)704 bool ReportOther::classof(const RejectReason *RR) {
705   return RR->getKind() >= RejectReasonKind::Other &&
706          RR->getKind() <= RejectReasonKind::LastOther;
707 }
708 
709 //===----------------------------------------------------------------------===//
710 // ReportIntToPtr.
ReportIntToPtr(Instruction * BaseValue)711 ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue)
712     : ReportOther(RejectReasonKind::IntToPtr), BaseValue(BaseValue) {}
713 
getRemarkName() const714 std::string ReportIntToPtr::getRemarkName() const { return "IntToPtr"; }
715 
getRemarkBB() const716 const Value *ReportIntToPtr::getRemarkBB() const {
717   return BaseValue->getParent();
718 }
719 
getMessage() const720 std::string ReportIntToPtr::getMessage() const {
721   return "Find bad intToptr prt: " + *BaseValue;
722 }
723 
getDebugLoc() const724 const DebugLoc &ReportIntToPtr::getDebugLoc() const {
725   return BaseValue->getDebugLoc();
726 }
727 
classof(const RejectReason * RR)728 bool ReportIntToPtr::classof(const RejectReason *RR) {
729   return RR->getKind() == RejectReasonKind::IntToPtr;
730 }
731 
732 //===----------------------------------------------------------------------===//
733 // ReportAlloca.
734 
ReportAlloca(Instruction * Inst)735 ReportAlloca::ReportAlloca(Instruction *Inst)
736     : ReportOther(RejectReasonKind::Alloca), Inst(Inst) {}
737 
getRemarkName() const738 std::string ReportAlloca::getRemarkName() const { return "Alloca"; }
739 
getRemarkBB() const740 const Value *ReportAlloca::getRemarkBB() const { return Inst->getParent(); }
741 
getMessage() const742 std::string ReportAlloca::getMessage() const {
743   return "Alloca instruction: " + *Inst;
744 }
745 
getDebugLoc() const746 const DebugLoc &ReportAlloca::getDebugLoc() const {
747   return Inst->getDebugLoc();
748 }
749 
classof(const RejectReason * RR)750 bool ReportAlloca::classof(const RejectReason *RR) {
751   return RR->getKind() == RejectReasonKind::Alloca;
752 }
753 
754 //===----------------------------------------------------------------------===//
755 // ReportUnknownInst.
756 
ReportUnknownInst(Instruction * Inst)757 ReportUnknownInst::ReportUnknownInst(Instruction *Inst)
758     : ReportOther(RejectReasonKind::UnknownInst), Inst(Inst) {}
759 
getRemarkName() const760 std::string ReportUnknownInst::getRemarkName() const { return "UnknownInst"; }
761 
getRemarkBB() const762 const Value *ReportUnknownInst::getRemarkBB() const {
763   return Inst->getParent();
764 }
765 
getMessage() const766 std::string ReportUnknownInst::getMessage() const {
767   return "Unknown instruction: " + *Inst;
768 }
769 
getDebugLoc() const770 const DebugLoc &ReportUnknownInst::getDebugLoc() const {
771   return Inst->getDebugLoc();
772 }
773 
classof(const RejectReason * RR)774 bool ReportUnknownInst::classof(const RejectReason *RR) {
775   return RR->getKind() == RejectReasonKind::UnknownInst;
776 }
777 
778 //===----------------------------------------------------------------------===//
779 // ReportEntry.
780 
ReportEntry(BasicBlock * BB)781 ReportEntry::ReportEntry(BasicBlock *BB)
782     : ReportOther(RejectReasonKind::Entry), BB(BB) {}
783 
getRemarkName() const784 std::string ReportEntry::getRemarkName() const { return "Entry"; }
785 
getRemarkBB() const786 const Value *ReportEntry::getRemarkBB() const { return BB; }
787 
getMessage() const788 std::string ReportEntry::getMessage() const {
789   return "Region containing entry block of function is invalid!";
790 }
791 
getEndUserMessage() const792 std::string ReportEntry::getEndUserMessage() const {
793   return "Scop contains function entry (not yet supported).";
794 }
795 
getDebugLoc() const796 const DebugLoc &ReportEntry::getDebugLoc() const {
797   return BB->getTerminator()->getDebugLoc();
798 }
799 
classof(const RejectReason * RR)800 bool ReportEntry::classof(const RejectReason *RR) {
801   return RR->getKind() == RejectReasonKind::Entry;
802 }
803 
804 //===----------------------------------------------------------------------===//
805 // ReportUnprofitable.
806 
ReportUnprofitable(Region * R)807 ReportUnprofitable::ReportUnprofitable(Region *R)
808     : ReportOther(RejectReasonKind::Unprofitable), R(R) {}
809 
getRemarkName() const810 std::string ReportUnprofitable::getRemarkName() const { return "Unprofitable"; }
811 
getRemarkBB() const812 const Value *ReportUnprofitable::getRemarkBB() const { return R->getEntry(); }
813 
getMessage() const814 std::string ReportUnprofitable::getMessage() const {
815   return "Region can not profitably be optimized!";
816 }
817 
getEndUserMessage() const818 std::string ReportUnprofitable::getEndUserMessage() const {
819   return "No profitable polyhedral optimization found";
820 }
821 
getDebugLoc() const822 const DebugLoc &ReportUnprofitable::getDebugLoc() const {
823   for (const BasicBlock *BB : R->blocks())
824     for (const Instruction &Inst : *BB)
825       if (const DebugLoc &DL = Inst.getDebugLoc())
826         return DL;
827 
828   return R->getEntry()->getTerminator()->getDebugLoc();
829 }
830 
classof(const RejectReason * RR)831 bool ReportUnprofitable::classof(const RejectReason *RR) {
832   return RR->getKind() == RejectReasonKind::Unprofitable;
833 }
834 } // namespace polly
835