|  | //===- ScopDetectionDiagnostic.cpp - Error diagnostics --------------------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // Small set of diagnostic helper classes to encapsulate any errors occurred | 
|  | // during the detection of Scops. | 
|  | // | 
|  | // The ScopDetection defines a set of error classes (via Statistic variables) | 
|  | // that groups a number of individual errors into a group, e.g. non-affinity | 
|  | // related errors. | 
|  | // On error we generate an object that carries enough additional information | 
|  | // to diagnose the error and generate a helpful error message. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "polly/ScopDetectionDiagnostic.h" | 
|  | #include "llvm/ADT/SmallPtrSet.h" | 
|  | #include "llvm/ADT/SmallVector.h" | 
|  | #include "llvm/ADT/Statistic.h" | 
|  | #include "llvm/ADT/StringRef.h" | 
|  | #include "llvm/ADT/Twine.h" | 
|  | #include "llvm/Analysis/AliasSetTracker.h" | 
|  | #include "llvm/Analysis/LoopInfo.h" | 
|  | #include "llvm/Analysis/OptimizationRemarkEmitter.h" | 
|  | #include "llvm/Analysis/RegionInfo.h" | 
|  | #include "llvm/Analysis/ScalarEvolution.h" | 
|  | #include "llvm/IR/BasicBlock.h" | 
|  | #include "llvm/IR/CFG.h" | 
|  | #include "llvm/IR/DebugLoc.h" | 
|  | #include "llvm/IR/DiagnosticInfo.h" | 
|  | #include "llvm/IR/Instruction.h" | 
|  | #include "llvm/IR/Value.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  | #include <algorithm> | 
|  | #include <cassert> | 
|  | #include <string> | 
|  | #include <utility> | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | #define DEBUG_TYPE "polly-detect" | 
|  |  | 
|  | #define SCOP_STAT(NAME, DESC)                                                  \ | 
|  | {                                                                            \ | 
|  | "polly-detect", "NAME", "Number of rejected regions: " DESC, {0}, {        \ | 
|  | false                                                                    \ | 
|  | }                                                                          \ | 
|  | } | 
|  |  | 
|  | Statistic RejectStatistics[] = { | 
|  | SCOP_STAT(CFG, ""), | 
|  | SCOP_STAT(InvalidTerminator, "Unsupported terminator instruction"), | 
|  | SCOP_STAT(UnreachableInExit, "Unreachable in exit block"), | 
|  | SCOP_STAT(IrreducibleRegion, "Irreducible loops"), | 
|  | SCOP_STAT(LastCFG, ""), | 
|  | SCOP_STAT(AffFunc, ""), | 
|  | SCOP_STAT(UndefCond, "Undefined branch condition"), | 
|  | SCOP_STAT(InvalidCond, "Non-integer branch condition"), | 
|  | SCOP_STAT(UndefOperand, "Undefined operands in comparison"), | 
|  | SCOP_STAT(NonAffBranch, "Non-affine branch condition"), | 
|  | SCOP_STAT(NoBasePtr, "No base pointer"), | 
|  | SCOP_STAT(UndefBasePtr, "Undefined base pointer"), | 
|  | SCOP_STAT(VariantBasePtr, "Variant base pointer"), | 
|  | SCOP_STAT(NonAffineAccess, "Non-affine memory accesses"), | 
|  | SCOP_STAT(DifferentElementSize, "Accesses with differing sizes"), | 
|  | SCOP_STAT(LastAffFunc, ""), | 
|  | SCOP_STAT(LoopBound, "Uncomputable loop bounds"), | 
|  | SCOP_STAT(LoopHasNoExit, "Loop without exit"), | 
|  | SCOP_STAT(LoopHasMultipleExits, "Loop with multiple exits"), | 
|  | SCOP_STAT(LoopOnlySomeLatches, "Not all loop latches in scop"), | 
|  | SCOP_STAT(FuncCall, "Function call with side effects"), | 
|  | SCOP_STAT(NonSimpleMemoryAccess, | 
|  | "Compilated access semantics (volatile or atomic)"), | 
|  | SCOP_STAT(Alias, "Base address aliasing"), | 
|  | SCOP_STAT(Other, ""), | 
|  | SCOP_STAT(IntToPtr, "Integer to pointer conversions"), | 
|  | SCOP_STAT(Alloca, "Stack allocations"), | 
|  | SCOP_STAT(UnknownInst, "Unknown Instructions"), | 
|  | SCOP_STAT(Entry, "Contains entry block"), | 
|  | SCOP_STAT(Unprofitable, "Assumed to be unprofitable"), | 
|  | SCOP_STAT(LastOther, ""), | 
|  | }; | 
|  |  | 
|  | namespace polly { | 
|  |  | 
|  | /// Small string conversion via raw_string_stream. | 
|  | template <typename T> std::string operator+(Twine LHS, const T &RHS) { | 
|  | std::string Buf; | 
|  | raw_string_ostream fmt(Buf); | 
|  | fmt << RHS; | 
|  | fmt.flush(); | 
|  |  | 
|  | return LHS.concat(Buf).str(); | 
|  | } | 
|  | } // namespace polly | 
|  |  | 
|  | namespace llvm { | 
|  |  | 
|  | // Lexicographic order on (line, col) of our debug locations. | 
|  | static bool operator<(const DebugLoc &LHS, const DebugLoc &RHS) { | 
|  | return LHS.getLine() < RHS.getLine() || | 
|  | (LHS.getLine() == RHS.getLine() && LHS.getCol() < RHS.getCol()); | 
|  | } | 
|  | } // namespace llvm | 
|  |  | 
|  | namespace polly { | 
|  |  | 
|  | BBPair getBBPairForRegion(const Region *R) { | 
|  | return std::make_pair(R->getEntry(), R->getExit()); | 
|  | } | 
|  |  | 
|  | void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End) { | 
|  | SmallPtrSet<BasicBlock *, 32> Seen; | 
|  | SmallVector<BasicBlock *, 32> Todo; | 
|  | Todo.push_back(P.first); | 
|  | while (!Todo.empty()) { | 
|  | auto *BB = Todo.pop_back_val(); | 
|  | if (BB == P.second) | 
|  | continue; | 
|  | if (!Seen.insert(BB).second) | 
|  | continue; | 
|  | Todo.append(succ_begin(BB), succ_end(BB)); | 
|  | for (const Instruction &Inst : *BB) { | 
|  | DebugLoc DL = Inst.getDebugLoc(); | 
|  | if (!DL) | 
|  | continue; | 
|  |  | 
|  | Begin = Begin ? std::min(Begin, DL) : DL; | 
|  | End = End ? std::max(End, DL) : DL; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void emitRejectionRemarks(const BBPair &P, const RejectLog &Log, | 
|  | OptimizationRemarkEmitter &ORE) { | 
|  | DebugLoc Begin, End; | 
|  | getDebugLocations(P, Begin, End); | 
|  |  | 
|  | ORE.emit( | 
|  | OptimizationRemarkMissed(DEBUG_TYPE, "RejectionErrors", Begin, P.first) | 
|  | << "The following errors keep this region from being a Scop."); | 
|  |  | 
|  | for (RejectReasonPtr RR : Log) { | 
|  |  | 
|  | if (const DebugLoc &Loc = RR->getDebugLoc()) | 
|  | ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Loc, | 
|  | RR->getRemarkBB()) | 
|  | << RR->getEndUserMessage()); | 
|  | else | 
|  | ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Begin, | 
|  | RR->getRemarkBB()) | 
|  | << RR->getEndUserMessage()); | 
|  | } | 
|  |  | 
|  | /* Check to see if Region is a top level region, getExit = NULL*/ | 
|  | if (P.second) | 
|  | ORE.emit( | 
|  | OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.second) | 
|  | << "Invalid Scop candidate ends here."); | 
|  | else | 
|  | ORE.emit( | 
|  | OptimizationRemarkMissed(DEBUG_TYPE, "InvalidScopEnd", End, P.first) | 
|  | << "Invalid Scop candidate ends here."); | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // RejectReason. | 
|  |  | 
|  | RejectReason::RejectReason(RejectReasonKind K) : Kind(K) { | 
|  | RejectStatistics[static_cast<int>(K)]++; | 
|  | } | 
|  |  | 
|  | const DebugLoc RejectReason::Unknown = DebugLoc(); | 
|  |  | 
|  | const DebugLoc &RejectReason::getDebugLoc() const { | 
|  | // Allocate an empty DebugLoc and return it a reference to it. | 
|  | return Unknown; | 
|  | } | 
|  |  | 
|  | // RejectLog. | 
|  | void RejectLog::print(raw_ostream &OS, int level) const { | 
|  | int j = 0; | 
|  | for (auto Reason : ErrorReports) | 
|  | OS.indent(level) << "[" << j++ << "] " << Reason->getMessage() << "\n"; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportCFG. | 
|  |  | 
|  | ReportCFG::ReportCFG(const RejectReasonKind K) : RejectReason(K) {} | 
|  |  | 
|  | bool ReportCFG::classof(const RejectReason *RR) { | 
|  | return RR->getKind() >= RejectReasonKind::CFG && | 
|  | RR->getKind() <= RejectReasonKind::LastCFG; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportInvalidTerminator. | 
|  |  | 
|  | std::string ReportInvalidTerminator::getRemarkName() const { | 
|  | return "InvalidTerminator"; | 
|  | } | 
|  |  | 
|  | const Value *ReportInvalidTerminator::getRemarkBB() const { return BB; } | 
|  |  | 
|  | std::string ReportInvalidTerminator::getMessage() const { | 
|  | return ("Invalid instruction terminates BB: " + BB->getName()).str(); | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportInvalidTerminator::getDebugLoc() const { | 
|  | return BB->getTerminator()->getDebugLoc(); | 
|  | } | 
|  |  | 
|  | bool ReportInvalidTerminator::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::InvalidTerminator; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // UnreachableInExit. | 
|  |  | 
|  | std::string ReportUnreachableInExit::getRemarkName() const { | 
|  | return "UnreachableInExit"; | 
|  | } | 
|  |  | 
|  | const Value *ReportUnreachableInExit::getRemarkBB() const { return BB; } | 
|  |  | 
|  | std::string ReportUnreachableInExit::getMessage() const { | 
|  | std::string BBName = BB->getName(); | 
|  | return "Unreachable in exit block" + BBName; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportUnreachableInExit::getDebugLoc() const { return DbgLoc; } | 
|  |  | 
|  | std::string ReportUnreachableInExit::getEndUserMessage() const { | 
|  | return "Unreachable in exit block."; | 
|  | } | 
|  |  | 
|  | bool ReportUnreachableInExit::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::UnreachableInExit; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportIrreducibleRegion. | 
|  |  | 
|  | std::string ReportIrreducibleRegion::getRemarkName() const { | 
|  | return "IrreducibleRegion"; | 
|  | } | 
|  |  | 
|  | const Value *ReportIrreducibleRegion::getRemarkBB() const { | 
|  | return R->getEntry(); | 
|  | } | 
|  |  | 
|  | std::string ReportIrreducibleRegion::getMessage() const { | 
|  | return "Irreducible region encountered: " + R->getNameStr(); | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportIrreducibleRegion::getDebugLoc() const { return DbgLoc; } | 
|  |  | 
|  | std::string ReportIrreducibleRegion::getEndUserMessage() const { | 
|  | return "Irreducible region encountered in control flow."; | 
|  | } | 
|  |  | 
|  | bool ReportIrreducibleRegion::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::IrreducibleRegion; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportAffFunc. | 
|  |  | 
|  | ReportAffFunc::ReportAffFunc(const RejectReasonKind K, const Instruction *Inst) | 
|  | : RejectReason(K), Inst(Inst) {} | 
|  |  | 
|  | bool ReportAffFunc::classof(const RejectReason *RR) { | 
|  | return RR->getKind() >= RejectReasonKind::AffFunc && | 
|  | RR->getKind() <= RejectReasonKind::LastAffFunc; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportUndefCond. | 
|  |  | 
|  | std::string ReportUndefCond::getRemarkName() const { return "UndefCond"; } | 
|  |  | 
|  | const Value *ReportUndefCond::getRemarkBB() const { return BB; } | 
|  |  | 
|  | std::string ReportUndefCond::getMessage() const { | 
|  | return ("Condition based on 'undef' value in BB: " + BB->getName()).str(); | 
|  | } | 
|  |  | 
|  | bool ReportUndefCond::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::UndefCond; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportInvalidCond. | 
|  |  | 
|  | std::string ReportInvalidCond::getRemarkName() const { return "InvalidCond"; } | 
|  |  | 
|  | const Value *ReportInvalidCond::getRemarkBB() const { return BB; } | 
|  |  | 
|  | std::string ReportInvalidCond::getMessage() const { | 
|  | return ("Condition in BB '" + BB->getName()).str() + | 
|  | "' neither constant nor an icmp instruction"; | 
|  | } | 
|  |  | 
|  | bool ReportInvalidCond::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::InvalidCond; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportUndefOperand. | 
|  |  | 
|  | std::string ReportUndefOperand::getRemarkName() const { return "UndefOperand"; } | 
|  |  | 
|  | const Value *ReportUndefOperand::getRemarkBB() const { return BB; } | 
|  |  | 
|  | std::string ReportUndefOperand::getMessage() const { | 
|  | return ("undef operand in branch at BB: " + BB->getName()).str(); | 
|  | } | 
|  |  | 
|  | bool ReportUndefOperand::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::UndefOperand; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportNonAffBranch. | 
|  |  | 
|  | std::string ReportNonAffBranch::getRemarkName() const { return "NonAffBranch"; } | 
|  |  | 
|  | const Value *ReportNonAffBranch::getRemarkBB() const { return BB; } | 
|  |  | 
|  | std::string ReportNonAffBranch::getMessage() const { | 
|  | return ("Non affine branch in BB '" + BB->getName()).str() + | 
|  | "' with LHS: " + *LHS + " and RHS: " + *RHS; | 
|  | } | 
|  |  | 
|  | bool ReportNonAffBranch::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::NonAffBranch; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportNoBasePtr. | 
|  |  | 
|  | std::string ReportNoBasePtr::getRemarkName() const { return "NoBasePtr"; } | 
|  |  | 
|  | const Value *ReportNoBasePtr::getRemarkBB() const { return Inst->getParent(); } | 
|  |  | 
|  | std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; } | 
|  |  | 
|  | bool ReportNoBasePtr::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::NoBasePtr; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportUndefBasePtr. | 
|  |  | 
|  | std::string ReportUndefBasePtr::getRemarkName() const { return "UndefBasePtr"; } | 
|  |  | 
|  | const Value *ReportUndefBasePtr::getRemarkBB() const { | 
|  | return Inst->getParent(); | 
|  | } | 
|  |  | 
|  | std::string ReportUndefBasePtr::getMessage() const { | 
|  | return "Undefined base pointer"; | 
|  | } | 
|  |  | 
|  | bool ReportUndefBasePtr::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::UndefBasePtr; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportVariantBasePtr. | 
|  |  | 
|  | std::string ReportVariantBasePtr::getRemarkName() const { | 
|  | return "VariantBasePtr"; | 
|  | } | 
|  |  | 
|  | const Value *ReportVariantBasePtr::getRemarkBB() const { | 
|  | return Inst->getParent(); | 
|  | } | 
|  |  | 
|  | std::string ReportVariantBasePtr::getMessage() const { | 
|  | return "Base address not invariant in current region:" + *BaseValue; | 
|  | } | 
|  |  | 
|  | std::string ReportVariantBasePtr::getEndUserMessage() const { | 
|  | return "The base address of this array is not invariant inside the loop"; | 
|  | } | 
|  |  | 
|  | bool ReportVariantBasePtr::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::VariantBasePtr; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportDifferentArrayElementSize | 
|  |  | 
|  | std::string ReportDifferentArrayElementSize::getRemarkName() const { | 
|  | return "DifferentArrayElementSize"; | 
|  | } | 
|  |  | 
|  | const Value *ReportDifferentArrayElementSize::getRemarkBB() const { | 
|  | return Inst->getParent(); | 
|  | } | 
|  |  | 
|  | std::string ReportDifferentArrayElementSize::getMessage() const { | 
|  | return "Access to one array through data types of different size"; | 
|  | } | 
|  |  | 
|  | bool ReportDifferentArrayElementSize::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::DifferentElementSize; | 
|  | } | 
|  |  | 
|  | std::string ReportDifferentArrayElementSize::getEndUserMessage() const { | 
|  | StringRef BaseName = BaseValue->getName(); | 
|  | std::string Name = BaseName.empty() ? "UNKNOWN" : BaseName; | 
|  | return "The array \"" + Name + | 
|  | "\" is accessed through elements that differ " | 
|  | "in size"; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportNonAffineAccess. | 
|  |  | 
|  | std::string ReportNonAffineAccess::getRemarkName() const { | 
|  | return "NonAffineAccess"; | 
|  | } | 
|  |  | 
|  | const Value *ReportNonAffineAccess::getRemarkBB() const { | 
|  | return Inst->getParent(); | 
|  | } | 
|  |  | 
|  | std::string ReportNonAffineAccess::getMessage() const { | 
|  | return "Non affine access function: " + *AccessFunction; | 
|  | } | 
|  |  | 
|  | bool ReportNonAffineAccess::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::NonAffineAccess; | 
|  | } | 
|  |  | 
|  | std::string ReportNonAffineAccess::getEndUserMessage() const { | 
|  | StringRef BaseName = BaseValue->getName(); | 
|  | std::string Name = BaseName.empty() ? "UNKNOWN" : BaseName; | 
|  | return "The array subscript of \"" + Name + "\" is not affine"; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportLoopBound. | 
|  |  | 
|  | ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount) | 
|  | : RejectReason(RejectReasonKind::LoopBound), L(L), LoopCount(LoopCount), | 
|  | Loc(L->getStartLoc()) {} | 
|  |  | 
|  | std::string ReportLoopBound::getRemarkName() const { return "LoopBound"; } | 
|  |  | 
|  | const Value *ReportLoopBound::getRemarkBB() const { return L->getHeader(); } | 
|  |  | 
|  | std::string ReportLoopBound::getMessage() const { | 
|  | return "Non affine loop bound '" + *LoopCount + | 
|  | "' in loop: " + L->getHeader()->getName(); | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportLoopBound::getDebugLoc() const { return Loc; } | 
|  |  | 
|  | bool ReportLoopBound::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::LoopBound; | 
|  | } | 
|  |  | 
|  | std::string ReportLoopBound::getEndUserMessage() const { | 
|  | return "Failed to derive an affine function from the loop bounds."; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportLoopHasNoExit. | 
|  |  | 
|  | std::string ReportLoopHasNoExit::getRemarkName() const { | 
|  | return "LoopHasNoExit"; | 
|  | } | 
|  |  | 
|  | const Value *ReportLoopHasNoExit::getRemarkBB() const { return L->getHeader(); } | 
|  |  | 
|  | std::string ReportLoopHasNoExit::getMessage() const { | 
|  | return "Loop " + L->getHeader()->getName() + " has no exit."; | 
|  | } | 
|  |  | 
|  | bool ReportLoopHasNoExit::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::LoopHasNoExit; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportLoopHasNoExit::getDebugLoc() const { return Loc; } | 
|  |  | 
|  | std::string ReportLoopHasNoExit::getEndUserMessage() const { | 
|  | return "Loop cannot be handled because it has no exit."; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportLoopHasMultipleExits. | 
|  |  | 
|  | std::string ReportLoopHasMultipleExits::getRemarkName() const { | 
|  | return "ReportLoopHasMultipleExits"; | 
|  | } | 
|  |  | 
|  | const Value *ReportLoopHasMultipleExits::getRemarkBB() const { | 
|  | return L->getHeader(); | 
|  | } | 
|  |  | 
|  | std::string ReportLoopHasMultipleExits::getMessage() const { | 
|  | return "Loop " + L->getHeader()->getName() + " has multiple exits."; | 
|  | } | 
|  |  | 
|  | bool ReportLoopHasMultipleExits::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::LoopHasMultipleExits; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportLoopHasMultipleExits::getDebugLoc() const { return Loc; } | 
|  |  | 
|  | std::string ReportLoopHasMultipleExits::getEndUserMessage() const { | 
|  | return "Loop cannot be handled because it has multiple exits."; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportLoopOnlySomeLatches | 
|  |  | 
|  | std::string ReportLoopOnlySomeLatches::getRemarkName() const { | 
|  | return "LoopHasNoExit"; | 
|  | } | 
|  |  | 
|  | const Value *ReportLoopOnlySomeLatches::getRemarkBB() const { | 
|  | return L->getHeader(); | 
|  | } | 
|  |  | 
|  | std::string ReportLoopOnlySomeLatches::getMessage() const { | 
|  | return "Not all latches of loop " + L->getHeader()->getName() + | 
|  | " part of scop."; | 
|  | } | 
|  |  | 
|  | bool ReportLoopOnlySomeLatches::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::LoopHasNoExit; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportLoopOnlySomeLatches::getDebugLoc() const { return Loc; } | 
|  |  | 
|  | std::string ReportLoopOnlySomeLatches::getEndUserMessage() const { | 
|  | return "Loop cannot be handled because not all latches are part of loop " | 
|  | "region."; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportFuncCall. | 
|  |  | 
|  | ReportFuncCall::ReportFuncCall(Instruction *Inst) | 
|  | : RejectReason(RejectReasonKind::FuncCall), Inst(Inst) {} | 
|  |  | 
|  | std::string ReportFuncCall::getRemarkName() const { return "FuncCall"; } | 
|  |  | 
|  | const Value *ReportFuncCall::getRemarkBB() const { return Inst->getParent(); } | 
|  |  | 
|  | std::string ReportFuncCall::getMessage() const { | 
|  | return "Call instruction: " + *Inst; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportFuncCall::getDebugLoc() const { | 
|  | return Inst->getDebugLoc(); | 
|  | } | 
|  |  | 
|  | std::string ReportFuncCall::getEndUserMessage() const { | 
|  | return "This function call cannot be handled. " | 
|  | "Try to inline it."; | 
|  | } | 
|  |  | 
|  | bool ReportFuncCall::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::FuncCall; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportNonSimpleMemoryAccess | 
|  |  | 
|  | ReportNonSimpleMemoryAccess::ReportNonSimpleMemoryAccess(Instruction *Inst) | 
|  | : ReportOther(RejectReasonKind::NonSimpleMemoryAccess), Inst(Inst) {} | 
|  |  | 
|  | std::string ReportNonSimpleMemoryAccess::getRemarkName() const { | 
|  | return "NonSimpleMemoryAccess"; | 
|  | } | 
|  |  | 
|  | const Value *ReportNonSimpleMemoryAccess::getRemarkBB() const { | 
|  | return Inst->getParent(); | 
|  | } | 
|  |  | 
|  | std::string ReportNonSimpleMemoryAccess::getMessage() const { | 
|  | return "Non-simple memory access: " + *Inst; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportNonSimpleMemoryAccess::getDebugLoc() const { | 
|  | return Inst->getDebugLoc(); | 
|  | } | 
|  |  | 
|  | std::string ReportNonSimpleMemoryAccess::getEndUserMessage() const { | 
|  | return "Volatile memory accesses or memory accesses for atomic types " | 
|  | "are not supported."; | 
|  | } | 
|  |  | 
|  | bool ReportNonSimpleMemoryAccess::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::NonSimpleMemoryAccess; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportAlias. | 
|  |  | 
|  | ReportAlias::ReportAlias(Instruction *Inst, AliasSet &AS) | 
|  | : RejectReason(RejectReasonKind::Alias), Inst(Inst) { | 
|  | for (const auto &I : AS) | 
|  | Pointers.push_back(I.getValue()); | 
|  | } | 
|  |  | 
|  | std::string ReportAlias::formatInvalidAlias(std::string Prefix, | 
|  | std::string Suffix) const { | 
|  | std::string Message; | 
|  | raw_string_ostream OS(Message); | 
|  |  | 
|  | OS << Prefix; | 
|  |  | 
|  | for (PointerSnapshotTy::const_iterator PI = Pointers.begin(), | 
|  | PE = Pointers.end(); | 
|  | ;) { | 
|  | const Value *V = *PI; | 
|  | assert(V && "Diagnostic info does not match found LLVM-IR anymore."); | 
|  |  | 
|  | if (V->getName().empty()) | 
|  | OS << "\" <unknown> \""; | 
|  | else | 
|  | OS << "\"" << V->getName() << "\""; | 
|  |  | 
|  | ++PI; | 
|  |  | 
|  | if (PI != PE) | 
|  | OS << ", "; | 
|  | else | 
|  | break; | 
|  | } | 
|  |  | 
|  | OS << Suffix; | 
|  |  | 
|  | return OS.str(); | 
|  | } | 
|  |  | 
|  | std::string ReportAlias::getRemarkName() const { return "Alias"; } | 
|  |  | 
|  | const Value *ReportAlias::getRemarkBB() const { return Inst->getParent(); } | 
|  |  | 
|  | std::string ReportAlias::getMessage() const { | 
|  | return formatInvalidAlias("Possible aliasing: "); | 
|  | } | 
|  |  | 
|  | std::string ReportAlias::getEndUserMessage() const { | 
|  | return formatInvalidAlias("Accesses to the arrays ", | 
|  | " may access the same memory."); | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); } | 
|  |  | 
|  | bool ReportAlias::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::Alias; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportOther. | 
|  |  | 
|  | std::string ReportOther::getRemarkName() const { return "UnknownRejectReason"; } | 
|  |  | 
|  | std::string ReportOther::getMessage() const { return "Unknown reject reason"; } | 
|  |  | 
|  | ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {} | 
|  |  | 
|  | bool ReportOther::classof(const RejectReason *RR) { | 
|  | return RR->getKind() >= RejectReasonKind::Other && | 
|  | RR->getKind() <= RejectReasonKind::LastOther; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportIntToPtr. | 
|  | ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue) | 
|  | : ReportOther(RejectReasonKind::IntToPtr), BaseValue(BaseValue) {} | 
|  |  | 
|  | std::string ReportIntToPtr::getRemarkName() const { return "IntToPtr"; } | 
|  |  | 
|  | const Value *ReportIntToPtr::getRemarkBB() const { | 
|  | return BaseValue->getParent(); | 
|  | } | 
|  |  | 
|  | std::string ReportIntToPtr::getMessage() const { | 
|  | return "Find bad intToptr prt: " + *BaseValue; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportIntToPtr::getDebugLoc() const { | 
|  | return BaseValue->getDebugLoc(); | 
|  | } | 
|  |  | 
|  | bool ReportIntToPtr::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::IntToPtr; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportAlloca. | 
|  |  | 
|  | ReportAlloca::ReportAlloca(Instruction *Inst) | 
|  | : ReportOther(RejectReasonKind::Alloca), Inst(Inst) {} | 
|  |  | 
|  | std::string ReportAlloca::getRemarkName() const { return "Alloca"; } | 
|  |  | 
|  | const Value *ReportAlloca::getRemarkBB() const { return Inst->getParent(); } | 
|  |  | 
|  | std::string ReportAlloca::getMessage() const { | 
|  | return "Alloca instruction: " + *Inst; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportAlloca::getDebugLoc() const { | 
|  | return Inst->getDebugLoc(); | 
|  | } | 
|  |  | 
|  | bool ReportAlloca::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::Alloca; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportUnknownInst. | 
|  |  | 
|  | ReportUnknownInst::ReportUnknownInst(Instruction *Inst) | 
|  | : ReportOther(RejectReasonKind::UnknownInst), Inst(Inst) {} | 
|  |  | 
|  | std::string ReportUnknownInst::getRemarkName() const { return "UnknownInst"; } | 
|  |  | 
|  | const Value *ReportUnknownInst::getRemarkBB() const { | 
|  | return Inst->getParent(); | 
|  | } | 
|  |  | 
|  | std::string ReportUnknownInst::getMessage() const { | 
|  | return "Unknown instruction: " + *Inst; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportUnknownInst::getDebugLoc() const { | 
|  | return Inst->getDebugLoc(); | 
|  | } | 
|  |  | 
|  | bool ReportUnknownInst::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::UnknownInst; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportEntry. | 
|  |  | 
|  | ReportEntry::ReportEntry(BasicBlock *BB) | 
|  | : ReportOther(RejectReasonKind::Entry), BB(BB) {} | 
|  |  | 
|  | std::string ReportEntry::getRemarkName() const { return "Entry"; } | 
|  |  | 
|  | const Value *ReportEntry::getRemarkBB() const { return BB; } | 
|  |  | 
|  | std::string ReportEntry::getMessage() const { | 
|  | return "Region containing entry block of function is invalid!"; | 
|  | } | 
|  |  | 
|  | std::string ReportEntry::getEndUserMessage() const { | 
|  | return "Scop contains function entry (not yet supported)."; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportEntry::getDebugLoc() const { | 
|  | return BB->getTerminator()->getDebugLoc(); | 
|  | } | 
|  |  | 
|  | bool ReportEntry::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::Entry; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ReportUnprofitable. | 
|  |  | 
|  | ReportUnprofitable::ReportUnprofitable(Region *R) | 
|  | : ReportOther(RejectReasonKind::Unprofitable), R(R) {} | 
|  |  | 
|  | std::string ReportUnprofitable::getRemarkName() const { return "Unprofitable"; } | 
|  |  | 
|  | const Value *ReportUnprofitable::getRemarkBB() const { return R->getEntry(); } | 
|  |  | 
|  | std::string ReportUnprofitable::getMessage() const { | 
|  | return "Region can not profitably be optimized!"; | 
|  | } | 
|  |  | 
|  | std::string ReportUnprofitable::getEndUserMessage() const { | 
|  | return "No profitable polyhedral optimization found"; | 
|  | } | 
|  |  | 
|  | const DebugLoc &ReportUnprofitable::getDebugLoc() const { | 
|  | for (const BasicBlock *BB : R->blocks()) | 
|  | for (const Instruction &Inst : *BB) | 
|  | if (const DebugLoc &DL = Inst.getDebugLoc()) | 
|  | return DL; | 
|  |  | 
|  | return R->getEntry()->getTerminator()->getDebugLoc(); | 
|  | } | 
|  |  | 
|  | bool ReportUnprofitable::classof(const RejectReason *RR) { | 
|  | return RR->getKind() == RejectReasonKind::Unprofitable; | 
|  | } | 
|  | } // namespace polly |