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"
45#define DEBUG_TYPE "polly-detect"
47#define SCOP_STAT(NAME, DESC) \
48 {"polly-detect", "NAME", "Number of rejected regions: " DESC}
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"),
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"),
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"),
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"),
74 "Complicated access semantics (volatile or atomic)"),
75 SCOP_STAT(IncompatibleType,
"Non-fixed size type (e.g. Scalable vector)"),
76 SCOP_STAT(Alias,
"Base address aliasing"),
78 SCOP_STAT(IntToPtr,
"Integer to pointer conversions"),
80 SCOP_STAT(UnknownInst,
"Unknown Instructions"),
82 SCOP_STAT(Unprofitable,
"Assumed to be unprofitable"),
89template <
typename T> std::string
operator+(Twine LHS,
const T &RHS) {
91 raw_string_ostream fmt(Buf);
94 return LHS.concat(Buf).str();
101static bool operator<(
const DebugLoc &LHS,
const DebugLoc &RHS) {
102 return LHS.getLine() < RHS.getLine() ||
103 (LHS.getLine() == RHS.getLine() && LHS.getCol() < RHS.getCol());
110 return std::make_pair(R->getEntry(), R->getExit());
114 SmallPtrSet<BasicBlock *, 32> Seen;
115 SmallVector<BasicBlock *, 32> Todo;
116 Todo.push_back(P.first);
117 while (!Todo.empty()) {
118 auto *BB = Todo.pop_back_val();
121 if (!Seen.insert(BB).second)
123 Todo.append(succ_begin(BB), succ_end(BB));
124 for (
const Instruction &Inst : *BB) {
125 DebugLoc DL = Inst.getStableDebugLoc();
129 Begin = Begin ? std::min(Begin, DL) : DL;
130 End = End ? std::max(End, DL) : DL;
136 OptimizationRemarkEmitter &ORE) {
141 OptimizationRemarkMissed(
DEBUG_TYPE,
"RejectionErrors", Begin, P.first)
142 <<
"The following errors keep this region from being a Scop.");
146 if (
const DebugLoc &Loc = RR->getDebugLoc())
147 ORE.emit(OptimizationRemarkMissed(
DEBUG_TYPE, RR->getRemarkName(), Loc,
149 << RR->getEndUserMessage());
151 ORE.emit(OptimizationRemarkMissed(
DEBUG_TYPE, RR->getRemarkName(), Begin,
153 << RR->getEndUserMessage());
159 OptimizationRemarkMissed(
DEBUG_TYPE,
"InvalidScopEnd", End, P.second)
160 <<
"Invalid Scop candidate ends here.");
163 OptimizationRemarkMissed(
DEBUG_TYPE,
"InvalidScopEnd", End, P.first)
164 <<
"Invalid Scop candidate ends here.");
185 OS.indent(level) <<
"[" << j++ <<
"] " << Reason->getMessage() <<
"\n";
202 return "InvalidTerminator";
208 return (
"Invalid instruction terminates BB: " +
BB->getName()).str();
212 return BB->getTerminator()->getDebugLoc();
223 return "UnreachableInExit";
229 std::string BBName =
BB->getName().str();
230 return "Unreachable in exit block" + BBName;
236 return "Unreachable in exit block.";
247 return "IndirectPredecessor";
252 return Inst->getParent();
258 return "Branch from indirect terminator: " + *
Inst;
267 return "Branch from indirect terminator.";
278 return "IrreducibleRegion";
282 return R->getEntry();
286 return "Irreducible region encountered: " +
R->getNameStr();
292 return "Irreducible region encountered in control flow.";
318 return (
"Condition based on 'undef' value in BB: " +
BB->getName()).str();
333 return (
"Condition in BB '" +
BB->getName()).str() +
334 "' neither constant nor an icmp instruction";
349 return (
"undef operand in branch at BB: " +
BB->getName()).str();
364 return (
"Non affine branch in BB '" +
BB->getName()).str() +
365 "' with LHS: " + *
LHS +
" and RHS: " + *
RHS;
378 return Inst->getParent();
393 return Inst->getParent();
397 return "Undefined base pointer";
408 return "VariantBasePtr";
412 return Inst->getParent();
416 return "Base address not invariant in current region:" + *
BaseValue;
420 return "The base address of this array is not invariant inside the loop";
431 return "DifferentArrayElementSize";
435 return Inst->getParent();
439 return "Access to one array through data types of different size";
447 StringRef BaseName =
BaseValue->getName();
448 std::string Name = BaseName.empty() ?
"UNKNOWN" : BaseName.str();
449 return "The array \"" + Name +
450 "\" is accessed through elements that differ "
458 return "NonAffineAccess";
462 return Inst->getParent();
474 StringRef BaseName =
BaseValue->getName();
475 std::string Name = BaseName.empty() ?
"UNKNOWN" : BaseName.str();
476 return "The array subscript of \"" + Name +
"\" is not affine";
484 Loc(
L->getStartLoc()) {}
489 return L->getHeader();
493 return "Non affine loop bound '" + *
LoopCount +
494 "' in loop: " +
L->getHeader()->getName();
504 return "Failed to derive an affine function from the loop bounds.";
511 return "LoopHasNoExit";
515 return L->getHeader();
519 return "Loop " +
L->getHeader()->getName() +
" has no exit.";
529 return "Loop cannot be handled because it has no exit.";
536 return "ReportLoopHasMultipleExits";
540 return L->getHeader();
544 return "Loop " +
L->getHeader()->getName() +
" has multiple exits.";
554 return "Loop cannot be handled because it has multiple exits.";
561 return "LoopHasNoExit";
565 return L->getHeader();
569 return "Not all latches of loop " +
L->getHeader()->getName() +
580 return "Loop cannot be handled because not all latches are part of loop "
593 return Inst->getParent();
597 return "Call instruction: " + *
Inst;
601 return Inst->getDebugLoc();
605 return "This function call cannot be handled. "
620 return "NonSimpleMemoryAccess";
624 return Inst->getParent();
628 return "Non-simple memory access: " + *
Inst;
632 return Inst->getDebugLoc();
636 return "Volatile memory accesses or memory accesses for atomic types "
637 "are not supported.";
653 std::string Suffix)
const {
655 raw_string_ostream OS(Message);
659 for (PointerSnapshotTy::const_iterator PI =
Pointers.begin(),
662 const Value *V = *PI;
663 assert(V &&
"Diagnostic info does not match found LLVM-IR anymore.");
665 if (V->getName().empty())
666 OS <<
"\" <unknown> \"";
668 OS <<
"\"" << V->getName() <<
"\"";
693 " may access the same memory.");
728 return "Find bad intToptr prt: " + *
BaseValue;
748 return Inst->getParent();
752 return "Alloca instruction: " + *
Inst;
756 return Inst->getDebugLoc();
772 return Inst->getParent();
776 return "Unknown instruction: " + *
Inst;
780 return Inst->getDebugLoc();
798 return "Region containing entry block of function is invalid!";
802 return "Scop contains function entry (not yet supported).";
806 return BB->getTerminator()->getDebugLoc();
822 return R->getEntry();
826 return "Region can not profitably be optimized!";
830 return "No profitable polyhedral optimization found";
834 for (
const BasicBlock *BB :
R->blocks())
835 for (
const Instruction &Inst : *BB)
836 if (
const DebugLoc &DL = Inst.getStableDebugLoc())
839 return R->getEntry()->getTerminator()->getDebugLoc();
853 return "IncompatibleType";
857 return Inst->getParent();
861 return "Incompatible type: " + *
Inst;
865 return Inst->getDebugLoc();
869 return "Incompatible (non-fixed size) type: " + *
Ty;
#define SCOP_STAT(NAME, DESC)
static Statistic RejectStatistics[]
Stores all errors that occurred during the detection.
void print(raw_ostream &OS, int level=0) const
SmallVector< RejectReasonPtr, 1 > ErrorReports
Base class of all reject reasons found during Scop detection.
const RejectReasonKind Kind
static const DebugLoc Unknown
RejectReason(RejectReasonKind K)
RejectReasonKind getKind() const
virtual const DebugLoc & getDebugLoc() const
Get the source location of this error.
static bool classof(const RejectReason *RR)
ReportAffFunc(const RejectReasonKind K, const Instruction *Inst)
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
static bool classof(const RejectReason *RR)
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
std::string formatInvalidAlias(std::string Prefix="", std::string Suffix="") const
Format an invalid alias set.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
ReportAlias(Instruction *Inst, AliasSet &AS)
PointerSnapshotTy Pointers
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
ReportAlloca(Instruction *Inst)
std::string getRemarkName() const override
Generate the remark name to identify this remark.
static bool classof(const RejectReason *RR)
static bool classof(const RejectReason *RR)
ReportCFG(const RejectReasonKind K)
static bool classof(const RejectReason *RR)
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
ReportEntry(BasicBlock *BB)
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
static bool classof(const RejectReason *RR)
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
ReportFuncCall(Instruction *Inst)
static bool classof(const RejectReason *RR)
static bool classof(const RejectReason *RR)
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
ReportIncompatibleType(Instruction *Inst, llvm::Type *Ty)
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
static bool classof(const RejectReason *RR)
static bool classof(const RejectReason *RR)
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
ReportIntToPtr(Instruction *BaseValue)
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
static bool classof(const RejectReason *RR)
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
static bool classof(const RejectReason *RR)
static bool classof(const RejectReason *RR)
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
ReportLoopBound(Loop *L, const SCEV *LoopCount)
static bool classof(const RejectReason *RR)
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
static bool classof(const RejectReason *RR)
std::string getRemarkName() const override
Generate the remark name to identify this remark.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
Loop * L
The loop that has multiple exits.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
Loop * L
The loop that has no exit.
static bool classof(const RejectReason *RR)
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
Loop * L
The loop for which not all loop latches are part of the scop.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
static bool classof(const RejectReason *RR)
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
static bool classof(const RejectReason *RR)
const SCEV * LHS
LHS & RHS of the failed condition.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
static bool classof(const RejectReason *RR)
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const SCEV * AccessFunction
static bool classof(const RejectReason *RR)
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
ReportNonSimpleMemoryAccess(Instruction *Inst)
static bool classof(const RejectReason *RR)
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
static bool classof(const RejectReason *RR)
ReportOther(const RejectReasonKind K)
static bool classof(const RejectReason *RR)
std::string getRemarkName() const override
Generate the remark name to identify this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
static bool classof(const RejectReason *RR)
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
static bool classof(const RejectReason *RR)
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
ReportUnknownInst(Instruction *Inst)
static bool classof(const RejectReason *RR)
static bool classof(const RejectReason *RR)
ReportUnprofitable(Region *R)
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
std::string getRemarkName() const override
Generate the remark name to identify this remark.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
static bool classof(const RejectReason *RR)
const DebugLoc & getDebugLoc() const override
Get the source location of this error.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
std::string getEndUserMessage() const override
Generate a message for the end-user describing this error.
const BasicBlock * getRemarkBB() const override
Get the Basic Block containing this remark.
static bool classof(const RejectReason *RR)
std::string getRemarkName() const override
Generate the remark name to identify this remark.
std::string getMessage() const override
Generate a reasonable diagnostic message describing this error.
static __isl_give isl_union_map * append_range(__isl_take isl_union_map *umap, int extra)
static bool operator<(const DebugLoc &LHS, const DebugLoc &RHS)
std::shared_ptr< RejectReason > RejectReasonPtr
void getDebugLocations(const BBPair &P, DebugLoc &Begin, DebugLoc &End)
Set the begin and end source location for the region limited by P.
isl::pw_aff operator+(isl::pw_aff Left, isl::pw_aff Right)
Addition.
@ Value
MemoryKind::Value: Models an llvm::Value.
void emitRejectionRemarks(const BBPair &P, const RejectLog &Log, OptimizationRemarkEmitter &ORE)
Emit optimization remarks about the rejected regions to the user.
BBPair getBBPairForRegion(const Region *R)
Return the region delimiters (entry & exit block) of R.
std::pair< llvm::BasicBlock *, llvm::BasicBlock * > BBPair
Type to hold region delimiters (entry & exit block).