ScopDetectionDiagnostic.cpp 26 KB

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