brintos

brintos / llvm-project-archived public Read only

0
0
Text · 26.0 KiB · 44b8b10 Raw
845 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// Small set of diagnostic helper classes to encapsulate any errors occurred10// 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-affinity14// related errors.15// On error we generate an object that carries enough additional information16// to diagnose the error and generate a helpful error message.17//18//===----------------------------------------------------------------------===//19 20#include "polly/ScopDetectionDiagnostic.h"21#include "llvm/ADT/SmallPtrSet.h"22#include "llvm/ADT/SmallVector.h"23#include "llvm/ADT/Statistic.h"24#include "llvm/ADT/StringRef.h"25#include "llvm/ADT/Twine.h"26#include "llvm/Analysis/AliasSetTracker.h"27#include "llvm/Analysis/LoopInfo.h"28#include "llvm/Analysis/OptimizationRemarkEmitter.h"29#include "llvm/Analysis/RegionInfo.h"30#include "llvm/Analysis/ScalarEvolution.h"31#include "llvm/IR/BasicBlock.h"32#include "llvm/IR/CFG.h"33#include "llvm/IR/DebugLoc.h"34#include "llvm/IR/DiagnosticInfo.h"35#include "llvm/IR/Instruction.h"36#include "llvm/IR/Value.h"37#include "llvm/Support/raw_ostream.h"38#include <algorithm>39#include <cassert>40#include <string>41#include <utility>42 43using namespace llvm;44 45#define DEBUG_TYPE "polly-detect"46 47#define SCOP_STAT(NAME, DESC)                                                  \48  {"polly-detect", "NAME", "Number of rejected regions: " DESC}49 50static Statistic RejectStatistics[] = {51    SCOP_STAT(CFG, ""),52    SCOP_STAT(InvalidTerminator, "Unsupported terminator instruction"),53    SCOP_STAT(IrreducibleRegion, "Irreducible loops"),54    SCOP_STAT(UnreachableInExit, "Unreachable in exit block"),55    SCOP_STAT(IndirectPredecessor, "Branch from indirect terminator"),56    SCOP_STAT(LastCFG, ""),57    SCOP_STAT(AffFunc, ""),58    SCOP_STAT(UndefCond, "Undefined branch condition"),59    SCOP_STAT(InvalidCond, "Non-integer branch condition"),60    SCOP_STAT(UndefOperand, "Undefined operands in comparison"),61    SCOP_STAT(NonAffBranch, "Non-affine branch condition"),62    SCOP_STAT(NoBasePtr, "No base pointer"),63    SCOP_STAT(UndefBasePtr, "Undefined base pointer"),64    SCOP_STAT(VariantBasePtr, "Variant base pointer"),65    SCOP_STAT(NonAffineAccess, "Non-affine memory accesses"),66    SCOP_STAT(DifferentElementSize, "Accesses with differing sizes"),67    SCOP_STAT(LastAffFunc, ""),68    SCOP_STAT(LoopBound, "Uncomputable loop bounds"),69    SCOP_STAT(LoopHasNoExit, "Loop without exit"),70    SCOP_STAT(LoopHasMultipleExits, "Loop with multiple exits"),71    SCOP_STAT(LoopOnlySomeLatches, "Not all loop latches in scop"),72    SCOP_STAT(FuncCall, "Function call with side effects"),73    SCOP_STAT(NonSimpleMemoryAccess,74              "Complicated access semantics (volatile or atomic)"),75    SCOP_STAT(Alias, "Base address aliasing"),76    SCOP_STAT(Other, ""),77    SCOP_STAT(IntToPtr, "Integer to pointer conversions"),78    SCOP_STAT(Alloca, "Stack allocations"),79    SCOP_STAT(UnknownInst, "Unknown Instructions"),80    SCOP_STAT(Entry, "Contains entry block"),81    SCOP_STAT(Unprofitable, "Assumed to be unprofitable"),82    SCOP_STAT(LastOther, ""),83};84 85namespace polly {86 87/// Small string conversion via raw_string_stream.88template <typename T> std::string operator+(Twine LHS, const T &RHS) {89  std::string Buf;90  raw_string_ostream fmt(Buf);91  fmt << RHS;92 93  return LHS.concat(Buf).str();94}95} // namespace polly96 97namespace llvm {98 99// Lexicographic order on (line, col) of our debug locations.100static bool operator<(const DebugLoc &LHS, const DebugLoc &RHS) {101  return LHS.getLine() < RHS.getLine() ||102         (LHS.getLine() == RHS.getLine() && LHS.getCol() < RHS.getCol());103}104} // namespace llvm105 106namespace polly {107 108BBPair getBBPairForRegion(const Region *R) {109  return std::make_pair(R->getEntry(), R->getExit());110}111 112void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End) {113  SmallPtrSet<BasicBlock *, 32> Seen;114  SmallVector<BasicBlock *, 32> Todo;115  Todo.push_back(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.getStableDebugLoc();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 134void emitRejectionRemarks(const BBPair &P, const RejectLog &Log,135                          OptimizationRemarkEmitter &ORE) {136  DebugLoc Begin, End;137  getDebugLocations(P, Begin, End);138 139  ORE.emit(140      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    else150      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  else161    ORE.emit(162        OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.first)163        << "Invalid Scop candidate ends here.");164}165 166//===----------------------------------------------------------------------===//167// RejectReason.168 169RejectReason::RejectReason(RejectReasonKind K) : Kind(K) {170  RejectStatistics[static_cast<int>(K)]++;171}172 173const DebugLoc RejectReason::Unknown = DebugLoc();174 175const DebugLoc &RejectReason::getDebugLoc() const {176  // Allocate an empty DebugLoc and return it a reference to it.177  return Unknown;178}179 180// RejectLog.181void RejectLog::print(raw_ostream &OS, int level) const {182  int j = 0;183  for (auto Reason : ErrorReports)184    OS.indent(level) << "[" << j++ << "] " << Reason->getMessage() << "\n";185}186 187//===----------------------------------------------------------------------===//188// ReportCFG.189 190ReportCFG::ReportCFG(const RejectReasonKind K) : RejectReason(K) {}191 192bool ReportCFG::classof(const RejectReason *RR) {193  return RR->getKind() >= RejectReasonKind::CFG &&194         RR->getKind() <= RejectReasonKind::LastCFG;195}196 197//===----------------------------------------------------------------------===//198// ReportInvalidTerminator.199 200std::string ReportInvalidTerminator::getRemarkName() const {201  return "InvalidTerminator";202}203 204const BasicBlock *ReportInvalidTerminator::getRemarkBB() const { return BB; }205 206std::string ReportInvalidTerminator::getMessage() const {207  return ("Invalid instruction terminates BB: " + BB->getName()).str();208}209 210const DebugLoc &ReportInvalidTerminator::getDebugLoc() const {211  return BB->getTerminator()->getDebugLoc();212}213 214bool ReportInvalidTerminator::classof(const RejectReason *RR) {215  return RR->getKind() == RejectReasonKind::InvalidTerminator;216}217 218//===----------------------------------------------------------------------===//219// UnreachableInExit.220 221std::string ReportUnreachableInExit::getRemarkName() const {222  return "UnreachableInExit";223}224 225const BasicBlock *ReportUnreachableInExit::getRemarkBB() const { return BB; }226 227std::string ReportUnreachableInExit::getMessage() const {228  std::string BBName = BB->getName().str();229  return "Unreachable in exit block" + BBName;230}231 232const DebugLoc &ReportUnreachableInExit::getDebugLoc() const { return DbgLoc; }233 234std::string ReportUnreachableInExit::getEndUserMessage() const {235  return "Unreachable in exit block.";236}237 238bool ReportUnreachableInExit::classof(const RejectReason *RR) {239  return RR->getKind() == RejectReasonKind::UnreachableInExit;240}241 242//===----------------------------------------------------------------------===//243// IndirectPredecessor.244 245std::string ReportIndirectPredecessor::getRemarkName() const {246  return "IndirectPredecessor";247}248 249const BasicBlock *ReportIndirectPredecessor::getRemarkBB() const {250  if (Inst)251    return Inst->getParent();252  return nullptr;253}254 255std::string ReportIndirectPredecessor::getMessage() const {256  if (Inst)257    return "Branch from indirect terminator: " + *Inst;258  return getEndUserMessage();259}260 261const DebugLoc &ReportIndirectPredecessor::getDebugLoc() const {262  return DbgLoc;263}264 265std::string ReportIndirectPredecessor::getEndUserMessage() const {266  return "Branch from indirect terminator.";267}268 269bool ReportIndirectPredecessor::classof(const RejectReason *RR) {270  return RR->getKind() == RejectReasonKind::IndirectPredecessor;271}272 273//===----------------------------------------------------------------------===//274// ReportIrreducibleRegion.275 276std::string ReportIrreducibleRegion::getRemarkName() const {277  return "IrreducibleRegion";278}279 280const BasicBlock *ReportIrreducibleRegion::getRemarkBB() const {281  return R->getEntry();282}283 284std::string ReportIrreducibleRegion::getMessage() const {285  return "Irreducible region encountered: " + R->getNameStr();286}287 288const DebugLoc &ReportIrreducibleRegion::getDebugLoc() const { return DbgLoc; }289 290std::string ReportIrreducibleRegion::getEndUserMessage() const {291  return "Irreducible region encountered in control flow.";292}293 294bool ReportIrreducibleRegion::classof(const RejectReason *RR) {295  return RR->getKind() == RejectReasonKind::IrreducibleRegion;296}297 298//===----------------------------------------------------------------------===//299// ReportAffFunc.300 301ReportAffFunc::ReportAffFunc(const RejectReasonKind K, const Instruction *Inst)302    : RejectReason(K), Inst(Inst) {}303 304bool ReportAffFunc::classof(const RejectReason *RR) {305  return RR->getKind() >= RejectReasonKind::AffFunc &&306         RR->getKind() <= RejectReasonKind::LastAffFunc;307}308 309//===----------------------------------------------------------------------===//310// ReportUndefCond.311 312std::string ReportUndefCond::getRemarkName() const { return "UndefCond"; }313 314const BasicBlock *ReportUndefCond::getRemarkBB() const { return BB; }315 316std::string ReportUndefCond::getMessage() const {317  return ("Condition based on 'undef' value in BB: " + BB->getName()).str();318}319 320bool ReportUndefCond::classof(const RejectReason *RR) {321  return RR->getKind() == RejectReasonKind::UndefCond;322}323 324//===----------------------------------------------------------------------===//325// ReportInvalidCond.326 327std::string ReportInvalidCond::getRemarkName() const { return "InvalidCond"; }328 329const BasicBlock *ReportInvalidCond::getRemarkBB() const { return BB; }330 331std::string ReportInvalidCond::getMessage() const {332  return ("Condition in BB '" + BB->getName()).str() +333         "' neither constant nor an icmp instruction";334}335 336bool ReportInvalidCond::classof(const RejectReason *RR) {337  return RR->getKind() == RejectReasonKind::InvalidCond;338}339 340//===----------------------------------------------------------------------===//341// ReportUndefOperand.342 343std::string ReportUndefOperand::getRemarkName() const { return "UndefOperand"; }344 345const BasicBlock *ReportUndefOperand::getRemarkBB() const { return BB; }346 347std::string ReportUndefOperand::getMessage() const {348  return ("undef operand in branch at BB: " + BB->getName()).str();349}350 351bool ReportUndefOperand::classof(const RejectReason *RR) {352  return RR->getKind() == RejectReasonKind::UndefOperand;353}354 355//===----------------------------------------------------------------------===//356// ReportNonAffBranch.357 358std::string ReportNonAffBranch::getRemarkName() const { return "NonAffBranch"; }359 360const BasicBlock *ReportNonAffBranch::getRemarkBB() const { return BB; }361 362std::string ReportNonAffBranch::getMessage() const {363  return ("Non affine branch in BB '" + BB->getName()).str() +364         "' with LHS: " + *LHS + " and RHS: " + *RHS;365}366 367bool ReportNonAffBranch::classof(const RejectReason *RR) {368  return RR->getKind() == RejectReasonKind::NonAffBranch;369}370 371//===----------------------------------------------------------------------===//372// ReportNoBasePtr.373 374std::string ReportNoBasePtr::getRemarkName() const { return "NoBasePtr"; }375 376const BasicBlock *ReportNoBasePtr::getRemarkBB() const {377  return Inst->getParent();378}379 380std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; }381 382bool ReportNoBasePtr::classof(const RejectReason *RR) {383  return RR->getKind() == RejectReasonKind::NoBasePtr;384}385 386//===----------------------------------------------------------------------===//387// ReportUndefBasePtr.388 389std::string ReportUndefBasePtr::getRemarkName() const { return "UndefBasePtr"; }390 391const BasicBlock *ReportUndefBasePtr::getRemarkBB() const {392  return Inst->getParent();393}394 395std::string ReportUndefBasePtr::getMessage() const {396  return "Undefined base pointer";397}398 399bool ReportUndefBasePtr::classof(const RejectReason *RR) {400  return RR->getKind() == RejectReasonKind::UndefBasePtr;401}402 403//===----------------------------------------------------------------------===//404// ReportVariantBasePtr.405 406std::string ReportVariantBasePtr::getRemarkName() const {407  return "VariantBasePtr";408}409 410const BasicBlock *ReportVariantBasePtr::getRemarkBB() const {411  return Inst->getParent();412}413 414std::string ReportVariantBasePtr::getMessage() const {415  return "Base address not invariant in current region:" + *BaseValue;416}417 418std::string ReportVariantBasePtr::getEndUserMessage() const {419  return "The base address of this array is not invariant inside the loop";420}421 422bool ReportVariantBasePtr::classof(const RejectReason *RR) {423  return RR->getKind() == RejectReasonKind::VariantBasePtr;424}425 426//===----------------------------------------------------------------------===//427// ReportDifferentArrayElementSize428 429std::string ReportDifferentArrayElementSize::getRemarkName() const {430  return "DifferentArrayElementSize";431}432 433const BasicBlock *ReportDifferentArrayElementSize::getRemarkBB() const {434  return Inst->getParent();435}436 437std::string ReportDifferentArrayElementSize::getMessage() const {438  return "Access to one array through data types of different size";439}440 441bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) {442  return RR->getKind() == RejectReasonKind::DifferentElementSize;443}444 445std::string ReportDifferentArrayElementSize::getEndUserMessage() const {446  StringRef BaseName = BaseValue->getName();447  std::string Name = BaseName.empty() ? "UNKNOWN" : BaseName.str();448  return "The array \"" + Name +449         "\" is accessed through elements that differ "450         "in size";451}452 453//===----------------------------------------------------------------------===//454// ReportNonAffineAccess.455 456std::string ReportNonAffineAccess::getRemarkName() const {457  return "NonAffineAccess";458}459 460const BasicBlock *ReportNonAffineAccess::getRemarkBB() const {461  return Inst->getParent();462}463 464std::string ReportNonAffineAccess::getMessage() const {465  return "Non affine access function: " + *AccessFunction;466}467 468bool ReportNonAffineAccess::classof(const RejectReason *RR) {469  return RR->getKind() == RejectReasonKind::NonAffineAccess;470}471 472std::string ReportNonAffineAccess::getEndUserMessage() const {473  StringRef BaseName = BaseValue->getName();474  std::string Name = BaseName.empty() ? "UNKNOWN" : BaseName.str();475  return "The array subscript of \"" + Name + "\" is not affine";476}477 478//===----------------------------------------------------------------------===//479// ReportLoopBound.480 481ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount)482    : RejectReason(RejectReasonKind::LoopBound), L(L), LoopCount(LoopCount),483      Loc(L->getStartLoc()) {}484 485std::string ReportLoopBound::getRemarkName() const { return "LoopBound"; }486 487const BasicBlock *ReportLoopBound::getRemarkBB() const {488  return L->getHeader();489}490 491std::string ReportLoopBound::getMessage() const {492  return "Non affine loop bound '" + *LoopCount +493         "' in loop: " + L->getHeader()->getName();494}495 496const DebugLoc &ReportLoopBound::getDebugLoc() const { return Loc; }497 498bool ReportLoopBound::classof(const RejectReason *RR) {499  return RR->getKind() == RejectReasonKind::LoopBound;500}501 502std::string ReportLoopBound::getEndUserMessage() const {503  return "Failed to derive an affine function from the loop bounds.";504}505 506//===----------------------------------------------------------------------===//507// ReportLoopHasNoExit.508 509std::string ReportLoopHasNoExit::getRemarkName() const {510  return "LoopHasNoExit";511}512 513const BasicBlock *ReportLoopHasNoExit::getRemarkBB() const {514  return L->getHeader();515}516 517std::string ReportLoopHasNoExit::getMessage() const {518  return "Loop " + L->getHeader()->getName() + " has no exit.";519}520 521bool ReportLoopHasNoExit::classof(const RejectReason *RR) {522  return RR->getKind() == RejectReasonKind::LoopHasNoExit;523}524 525const DebugLoc &ReportLoopHasNoExit::getDebugLoc() const { return Loc; }526 527std::string ReportLoopHasNoExit::getEndUserMessage() const {528  return "Loop cannot be handled because it has no exit.";529}530 531//===----------------------------------------------------------------------===//532// ReportLoopHasMultipleExits.533 534std::string ReportLoopHasMultipleExits::getRemarkName() const {535  return "ReportLoopHasMultipleExits";536}537 538const BasicBlock *ReportLoopHasMultipleExits::getRemarkBB() const {539  return L->getHeader();540}541 542std::string ReportLoopHasMultipleExits::getMessage() const {543  return "Loop " + L->getHeader()->getName() + " has multiple exits.";544}545 546bool ReportLoopHasMultipleExits::classof(const RejectReason *RR) {547  return RR->getKind() == RejectReasonKind::LoopHasMultipleExits;548}549 550const DebugLoc &ReportLoopHasMultipleExits::getDebugLoc() const { return Loc; }551 552std::string ReportLoopHasMultipleExits::getEndUserMessage() const {553  return "Loop cannot be handled because it has multiple exits.";554}555 556//===----------------------------------------------------------------------===//557// ReportLoopOnlySomeLatches558 559std::string ReportLoopOnlySomeLatches::getRemarkName() const {560  return "LoopHasNoExit";561}562 563const BasicBlock *ReportLoopOnlySomeLatches::getRemarkBB() const {564  return L->getHeader();565}566 567std::string ReportLoopOnlySomeLatches::getMessage() const {568  return "Not all latches of loop " + L->getHeader()->getName() +569         " part of scop.";570}571 572bool ReportLoopOnlySomeLatches::classof(const RejectReason *RR) {573  return RR->getKind() == RejectReasonKind::LoopHasNoExit;574}575 576const DebugLoc &ReportLoopOnlySomeLatches::getDebugLoc() const { return Loc; }577 578std::string ReportLoopOnlySomeLatches::getEndUserMessage() const {579  return "Loop cannot be handled because not all latches are part of loop "580         "region.";581}582 583//===----------------------------------------------------------------------===//584// ReportFuncCall.585 586ReportFuncCall::ReportFuncCall(Instruction *Inst)587    : RejectReason(RejectReasonKind::FuncCall), Inst(Inst) {}588 589std::string ReportFuncCall::getRemarkName() const { return "FuncCall"; }590 591const BasicBlock *ReportFuncCall::getRemarkBB() const {592  return Inst->getParent();593}594 595std::string ReportFuncCall::getMessage() const {596  return "Call instruction: " + *Inst;597}598 599const DebugLoc &ReportFuncCall::getDebugLoc() const {600  return Inst->getDebugLoc();601}602 603std::string ReportFuncCall::getEndUserMessage() const {604  return "This function call cannot be handled. "605         "Try to inline it.";606}607 608bool ReportFuncCall::classof(const RejectReason *RR) {609  return RR->getKind() == RejectReasonKind::FuncCall;610}611 612//===----------------------------------------------------------------------===//613// ReportNonSimpleMemoryAccess614 615ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst)616    : ReportOther(RejectReasonKind::NonSimpleMemoryAccess), Inst(Inst) {}617 618std::string ReportNonSimpleMemoryAccess::getRemarkName() const {619  return "NonSimpleMemoryAccess";620}621 622const BasicBlock *ReportNonSimpleMemoryAccess::getRemarkBB() const {623  return Inst->getParent();624}625 626std::string ReportNonSimpleMemoryAccess::getMessage() const {627  return "Non-simple memory access: " + *Inst;628}629 630const DebugLoc &ReportNonSimpleMemoryAccess::getDebugLoc() const {631  return Inst->getDebugLoc();632}633 634std::string ReportNonSimpleMemoryAccess::getEndUserMessage() const {635  return "Volatile memory accesses or memory accesses for atomic types "636         "are not supported.";637}638 639bool ReportNonSimpleMemoryAccess::classof(const RejectReason *RR) {640  return RR->getKind() == RejectReasonKind::NonSimpleMemoryAccess;641}642 643//===----------------------------------------------------------------------===//644// ReportAlias.645 646ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS)647    : RejectReason(RejectReasonKind::Alias), Inst(Inst) {648  append_range(Pointers, AS.getPointers());649}650 651std::string ReportAlias::formatInvalidAlias(std::string Prefix,652                                            std::string Suffix) const {653  std::string Message;654  raw_string_ostream OS(Message);655 656  OS << Prefix;657 658  for (PointerSnapshotTy::const_iterator PI = Pointers.begin(),659                                         PE = Pointers.end();660       ;) {661    const Value *V = *PI;662    assert(V && "Diagnostic info does not match found LLVM-IR anymore.");663 664    if (V->getName().empty())665      OS << "\" <unknown> \"";666    else667      OS << "\"" << V->getName() << "\"";668 669    ++PI;670 671    if (PI != PE)672      OS << ", ";673    else674      break;675  }676 677  OS << Suffix;678 679  return Message;680}681 682std::string ReportAlias::getRemarkName() const { return "Alias"; }683 684const BasicBlock *ReportAlias::getRemarkBB() const { return Inst->getParent(); }685 686std::string ReportAlias::getMessage() const {687  return formatInvalidAlias("Possible aliasing: ");688}689 690std::string ReportAlias::getEndUserMessage() const {691  return formatInvalidAlias("Accesses to the arrays ",692                            " may access the same memory.");693}694 695const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); }696 697bool ReportAlias::classof(const RejectReason *RR) {698  return RR->getKind() == RejectReasonKind::Alias;699}700 701//===----------------------------------------------------------------------===//702// ReportOther.703 704std::string ReportOther::getRemarkName() const { return "UnknownRejectReason"; }705 706std::string ReportOther::getMessage() const { return "Unknown reject reason"; }707 708ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {}709 710bool ReportOther::classof(const RejectReason *RR) {711  return RR->getKind() >= RejectReasonKind::Other &&712         RR->getKind() <= RejectReasonKind::LastOther;713}714 715//===----------------------------------------------------------------------===//716// ReportIntToPtr.717ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue)718    : ReportOther(RejectReasonKind::IntToPtr), BaseValue(BaseValue) {}719 720std::string ReportIntToPtr::getRemarkName() const { return "IntToPtr"; }721 722const BasicBlock *ReportIntToPtr::getRemarkBB() const {723  return BaseValue->getParent();724}725 726std::string ReportIntToPtr::getMessage() const {727  return "Find bad intToptr prt: " + *BaseValue;728}729 730const DebugLoc &ReportIntToPtr::getDebugLoc() const {731  return BaseValue->getDebugLoc();732}733 734bool ReportIntToPtr::classof(const RejectReason *RR) {735  return RR->getKind() == RejectReasonKind::IntToPtr;736}737 738//===----------------------------------------------------------------------===//739// ReportAlloca.740 741ReportAlloca::ReportAlloca(Instruction *Inst)742    : ReportOther(RejectReasonKind::Alloca), Inst(Inst) {}743 744std::string ReportAlloca::getRemarkName() const { return "Alloca"; }745 746const BasicBlock *ReportAlloca::getRemarkBB() const {747  return Inst->getParent();748}749 750std::string ReportAlloca::getMessage() const {751  return "Alloca instruction: " + *Inst;752}753 754const DebugLoc &ReportAlloca::getDebugLoc() const {755  return Inst->getDebugLoc();756}757 758bool ReportAlloca::classof(const RejectReason *RR) {759  return RR->getKind() == RejectReasonKind::Alloca;760}761 762//===----------------------------------------------------------------------===//763// ReportUnknownInst.764 765ReportUnknownInst::ReportUnknownInst(Instruction *Inst)766    : ReportOther(RejectReasonKind::UnknownInst), Inst(Inst) {}767 768std::string ReportUnknownInst::getRemarkName() const { return "UnknownInst"; }769 770const BasicBlock *ReportUnknownInst::getRemarkBB() const {771  return Inst->getParent();772}773 774std::string ReportUnknownInst::getMessage() const {775  return "Unknown instruction: " + *Inst;776}777 778const DebugLoc &ReportUnknownInst::getDebugLoc() const {779  return Inst->getDebugLoc();780}781 782bool ReportUnknownInst::classof(const RejectReason *RR) {783  return RR->getKind() == RejectReasonKind::UnknownInst;784}785 786//===----------------------------------------------------------------------===//787// ReportEntry.788 789ReportEntry::ReportEntry(BasicBlock *BB)790    : ReportOther(RejectReasonKind::Entry), BB(BB) {}791 792std::string ReportEntry::getRemarkName() const { return "Entry"; }793 794const BasicBlock *ReportEntry::getRemarkBB() const { return BB; }795 796std::string ReportEntry::getMessage() const {797  return "Region containing entry block of function is invalid!";798}799 800std::string ReportEntry::getEndUserMessage() const {801  return "Scop contains function entry (not yet supported).";802}803 804const DebugLoc &ReportEntry::getDebugLoc() const {805  return BB->getTerminator()->getDebugLoc();806}807 808bool ReportEntry::classof(const RejectReason *RR) {809  return RR->getKind() == RejectReasonKind::Entry;810}811 812//===----------------------------------------------------------------------===//813// ReportUnprofitable.814 815ReportUnprofitable::ReportUnprofitable(Region *R)816    : ReportOther(RejectReasonKind::Unprofitable), R(R) {}817 818std::string ReportUnprofitable::getRemarkName() const { return "Unprofitable"; }819 820const BasicBlock *ReportUnprofitable::getRemarkBB() const {821  return R->getEntry();822}823 824std::string ReportUnprofitable::getMessage() const {825  return "Region can not profitably be optimized!";826}827 828std::string ReportUnprofitable::getEndUserMessage() const {829  return "No profitable polyhedral optimization found";830}831 832const DebugLoc &ReportUnprofitable::getDebugLoc() const {833  for (const BasicBlock *BB : R->blocks())834    for (const Instruction &Inst : *BB)835      if (const DebugLoc &DL = Inst.getStableDebugLoc())836        return DL;837 838  return R->getEntry()->getTerminator()->getDebugLoc();839}840 841bool ReportUnprofitable::classof(const RejectReason *RR) {842  return RR->getKind() == RejectReasonKind::Unprofitable;843}844} // namespace polly845