forked from OSchip/llvm-project
808 lines
25 KiB
C++
808 lines
25 KiB
C++
//===- 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
|