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