const_reject_iterator reject_end() const { return RejectLogs.end(); }
//@}
+ /// @brief Emit rejection remarks for all smallest invalid regions.
+ ///
+ /// @param F The function to emit remarks for.
+ /// @param R The region to start the region tree traversal for.
+ void emitMissedRemarksForLeaves(const Function &F, const Region *R);
+
+ /// @brief Emit rejection remarks for the parent regions of all valid regions.
+ ///
+ /// Emitting rejection remarks for the parent regions of all valid regions
+ /// may give the end-user clues about how to increase the size of the
+ /// detected Scops.
+ ///
+ /// @param F The function to emit remarks for.
+ /// @param ValidRegions The set of valid regions to emit remarks for.
+ void emitMissedRemarksForValidRegions(const Function &F,
+ const RegionSet &ValidRegions);
+
/// @brief Mark the function as invalid so we will not extract any scop from
/// the function.
///
void getDebugLocation(const Region *R, unsigned &LineBegin, unsigned &LineEnd,
std::string &FileName);
+class RejectLog;
+/// @brief Emit optimization remarks about the rejected regions to the user.
+///
+/// This emits the content of the reject log as optimization remarks.
+/// Remember to at least track failures (-polly-detect-track-failures).
+/// @param F The function we emit remarks for.
+/// @param Log The error log containing all messages being emitted as remark.
+void emitRejectionRemarks(const llvm::Function &F, const RejectLog &Log);
+
+/// @brief Emit diagnostic remarks for a valid Scop
+///
+/// @param F The function we emit remarks for
+/// @param R The region that marks a valid Scop
+void emitValidRemarks(const llvm::Function &F, const Region *R);
//===----------------------------------------------------------------------===//
/// @brief Base class of all reject reasons found during Scop detection.
///
///
/// @return A debug message representing this error.
virtual std::string getMessage() const = 0;
+
+ /// @brief Generate a message for the end-user describing this error.
+ ///
+ /// The message provided has to be suitable for the end-user. So it should
+ /// not reference any LLVM internal data structures or terminology.
+ /// Ideally, the message helps the end-user to increase the size of the
+ /// regions amenable to Polly.
+ ///
+ /// @return A short message representing this error.
+ virtual std::string getEndUserMessage() const {
+ return "Unspecified error.";
+ };
+
+ /// @brief Get the source location of this error.
+ ///
+ /// @return The debug location for this error.
+ virtual const llvm::DebugLoc &getDebugLoc() const;
};
typedef std::shared_ptr<RejectReason> RejectReasonPtr;
public:
explicit RejectLog(Region *R) : R(R) {}
- typedef llvm::SmallVector<RejectReasonPtr, 1>::iterator iterator;
+ typedef llvm::SmallVector<RejectReasonPtr, 1>::const_iterator iterator;
- iterator begin() { return ErrorReports.begin(); }
- iterator end() { return ErrorReports.end(); }
+ iterator begin() const { return ErrorReports.begin(); }
+ iterator end() const { return ErrorReports.end(); }
size_t size() { return ErrorReports.size(); }
const Region *region() const { return R; }
BasicBlock *BB;
public:
- ReportNonBranchTerminator(BasicBlock *BB) : BB(BB) {}
+ ReportNonBranchTerminator(BasicBlock *BB) : ReportCFG(), BB(BB) {}
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
BasicBlock *BB;
public:
- ReportCondition(BasicBlock *BB) : BB(BB) {}
+ ReportCondition(BasicBlock *BB) : ReportCFG(), BB(BB) {}
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
/// this class.
class ReportAffFunc : public RejectReason {
//===--------------------------------------------------------------------===//
+
+ // The instruction that caused non-affinity to occur.
+ const Instruction *Inst;
+
public:
- ReportAffFunc();
+ ReportAffFunc(const Instruction *Inst);
+
+ virtual const DebugLoc &getDebugLoc() const override {
+ return Inst->getDebugLoc();
+ }
};
//===----------------------------------------------------------------------===//
BasicBlock *BB;
public:
- ReportUndefCond(BasicBlock *BB) : BB(BB) {}
+ ReportUndefCond(const Instruction *Inst, BasicBlock *BB)
+ : ReportAffFunc(Inst), BB(BB) {}
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
//@}
};
BasicBlock *BB;
public:
- ReportInvalidCond(BasicBlock *BB) : BB(BB) {}
+ ReportInvalidCond(const Instruction *Inst, BasicBlock *BB)
+ : ReportAffFunc(Inst), BB(BB) {}
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
//@}
};
BasicBlock *BB;
public:
- ReportUndefOperand(BasicBlock *BB) : BB(BB) {}
+ ReportUndefOperand(BasicBlock *BB, const Instruction *Inst)
+ : ReportAffFunc(Inst), BB(BB) {}
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
//@}
};
//@}
public:
- ReportNonAffBranch(BasicBlock *BB, const SCEV *LHS, const SCEV *RHS)
- : BB(BB), LHS(LHS), RHS(RHS) {}
+ ReportNonAffBranch(BasicBlock *BB, const SCEV *LHS, const SCEV *RHS,
+ const Instruction *Inst)
+ : ReportAffFunc(Inst), BB(BB), LHS(LHS), RHS(RHS) {}
const SCEV *lhs() { return LHS; }
const SCEV *rhs() { return RHS; }
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
//@}
};
class ReportNoBasePtr : public ReportAffFunc {
//===--------------------------------------------------------------------===//
public:
+ ReportNoBasePtr(const Instruction *Inst) : ReportAffFunc(Inst) {}
+
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
//@}
};
class ReportUndefBasePtr : public ReportAffFunc {
//===--------------------------------------------------------------------===//
public:
+ ReportUndefBasePtr(const Instruction *Inst) : ReportAffFunc(Inst) {}
+
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
//@}
};
Value *BaseValue;
public:
- ReportVariantBasePtr(Value *BaseValue) : BaseValue(BaseValue) {}
+ ReportVariantBasePtr(Value *BaseValue, const Instruction *Inst)
+ : ReportAffFunc(Inst), BaseValue(BaseValue) {}
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
//@}
};
const SCEV *AccessFunction;
public:
- ReportNonAffineAccess(const SCEV *AccessFunction)
- : AccessFunction(AccessFunction) {}
+ ReportNonAffineAccess(const SCEV *AccessFunction, const Instruction *Inst)
+ : ReportAffFunc(Inst), AccessFunction(AccessFunction) {}
const SCEV *get() { return AccessFunction; }
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
//@}
};
Instruction *Inst;
public:
- ReportPhiNodeRefInRegion(Instruction *Inst) : Inst(Inst) {}
+ ReportPhiNodeRefInRegion(Instruction *Inst);
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
Instruction *Inst;
public:
- ReportNonCanonicalPhiNode(Instruction *Inst) : Inst(Inst) {}
+ ReportNonCanonicalPhiNode(Instruction *Inst);
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
Loop *L;
public:
- ReportLoopHeader(Loop *L) : L(L) {}
+ ReportLoopHeader(Loop *L);
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
/// @brief Captures a region with invalid entering edges.
class ReportIndEdge : public RejectReason {
//===--------------------------------------------------------------------===//
+
+ BasicBlock *BB;
+
public:
- ReportIndEdge();
+ ReportIndEdge(BasicBlock *BB);
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
/// @name RejectReason interface
//@{
- virtual std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
/// @name RejectReason interface
//@{
- std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
+ virtual std::string getEndUserMessage() const override;
//@}
};
class ReportAlias : public RejectReason {
//===--------------------------------------------------------------------===//
- // The offending alias set.
- AliasSet *AS;
-
/// @brief Format an invalid alias set.
///
/// @param AS The invalid alias set to format.
std::string formatInvalidAlias(AliasSet &AS) const;
+ AliasSet *AS;
+ Instruction *Inst;
+
public:
- ReportAlias(AliasSet *AS);
+ ReportAlias(Instruction *Inst, AliasSet *AS);
/// @name RejectReason interface
//@{
- std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
/// @name RejectReason interface
//@{
- std::string getMessage() const;
+ virtual std::string getMessage() const override;
//@}
};
/// @name RejectReason interface
//@{
- std::string getMessage() const { return "Unknown reject reason"; }
+ virtual std::string getMessage() const override;
//@}
};
//===--------------------------------------------------------------------===//
// The offending base value.
- Value *BaseValue;
+ Instruction *BaseValue;
public:
- ReportIntToPtr(Value *BaseValue) : BaseValue(BaseValue) {}
+ ReportIntToPtr(Instruction *BaseValue);
/// @name RejectReason interface
//@{
- std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
Instruction *Inst;
public:
- ReportAlloca(Instruction *Inst) : Inst(Inst) {}
+ ReportAlloca(Instruction *Inst);
/// @name RejectReason interface
//@{
- std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
Instruction *Inst;
public:
- ReportUnknownInst(Instruction *Inst) : Inst(Inst) {}
+ ReportUnknownInst(Instruction *Inst);
/// @name RejectReason interface
//@{
- std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
/// @brief Captures errors with phi nodes in exit BBs.
class ReportPHIinExit : public ReportOther {
//===--------------------------------------------------------------------===//
+ Instruction *Inst;
+
public:
+ ReportPHIinExit(Instruction *Inst);
+
/// @name RejectReason interface
//@{
- std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
/// @brief Captures errors with regions containing the function entry block.
class ReportEntry : public ReportOther {
//===--------------------------------------------------------------------===//
+ BasicBlock *BB;
+
public:
+ ReportEntry(BasicBlock *BB);
+
/// @name RejectReason interface
//@{
- std::string getMessage() const;
+ virtual std::string getMessage() const override;
+ virtual const DebugLoc &getDebugLoc() const override;
//@}
};
// UndefValue is not allowed as condition.
if (isa<UndefValue>(Condition))
- return invalid<ReportUndefCond>(Context, /*Assert=*/true, &BB);
+ return invalid<ReportUndefCond>(Context, /*Assert=*/true, Br, &BB);
// Only Constant and ICmpInst are allowed as condition.
if (!(isa<Constant>(Condition) || isa<ICmpInst>(Condition)))
- return invalid<ReportInvalidCond>(Context, /*Assert=*/true, &BB);
+ return invalid<ReportInvalidCond>(Context, /*Assert=*/true, Br, &BB);
// Allow perfectly nested conditions.
assert(Br->getNumSuccessors() == 2 && "Unexpected number of successors");
// Are both operands of the ICmp affine?
if (isa<UndefValue>(ICmp->getOperand(0)) ||
isa<UndefValue>(ICmp->getOperand(1)))
- return invalid<ReportUndefOperand>(Context, /*Assert=*/true, &BB);
+ return invalid<ReportUndefOperand>(Context, /*Assert=*/true, &BB, ICmp);
Loop *L = LI->getLoopFor(ICmp->getParent());
const SCEV *LHS = SE->getSCEVAtScope(ICmp->getOperand(0), L);
if (!isAffineExpr(&Context.CurRegion, LHS, *SE) ||
!isAffineExpr(&Context.CurRegion, RHS, *SE))
return invalid<ReportNonAffBranch>(Context, /*Assert=*/true, &BB, LHS,
- RHS);
+ RHS, ICmp);
}
// Allow loop exit conditions.
const SCEVAddRecExpr *AF = PIAF.second;
const Instruction *Insn = PIAF.first;
if (Shape->DelinearizedSizes.empty())
- return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true,
- PIAF.second);
+ return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF,
+ Insn);
MemAcc *Acc = new MemAcc(Insn, Shape);
InsnToMemAcc.insert({Insn, Acc});
Shape->DelinearizedSizes);
if (Shape->DelinearizedSizes.empty() ||
Acc->DelinearizedSubscripts.empty())
- return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF);
+ return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF,
+ Insn);
// Check that the delinearized subscripts are affine.
for (const SCEV *S : Acc->DelinearizedSubscripts)
if (!isAffineExpr(&Context.CurRegion, S, *SE, BaseValue))
- return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF);
+ return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true, AF,
+ Insn);
}
}
return true;
BasePointer = dyn_cast<SCEVUnknown>(SE->getPointerBase(AccessFunction));
if (!BasePointer)
- return invalid<ReportNoBasePtr>(Context, /*Assert=*/true);
+ return invalid<ReportNoBasePtr>(Context, /*Assert=*/true, &Inst);
BaseValue = BasePointer->getValue();
if (isa<UndefValue>(BaseValue))
- return invalid<ReportUndefBasePtr>(Context, /*Assert=*/true);
+ return invalid<ReportUndefBasePtr>(Context, /*Assert=*/true, &Inst);
// Check that the base address of the access is invariant in the current
// region.
// Verification of this property is difficult as the independent blocks
// pass may introduce aliasing that we did not have when running the
// scop detection.
- return invalid<ReportVariantBasePtr>(Context, /*Assert=*/false, BaseValue);
+ return invalid<ReportVariantBasePtr>(Context, /*Assert=*/false, BaseValue,
+ &Inst);
AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer);
if (!PollyDelinearize || !AF)
return invalid<ReportNonAffineAccess>(Context, /*Assert=*/true,
- AccessFunction);
+ AccessFunction, &Inst);
const SCEV *ElementSize = SE->getElementSize(&Inst);
Context.ElementSize[BasePointer] = ElementSize;
// FIXME: Alias Analysis thinks IntToPtrInst aliases with alloca instructions
// created by IndependentBlocks Pass.
- if (isa<IntToPtrInst>(BaseValue))
- return invalid<ReportIntToPtr>(Context, /*Assert=*/true, BaseValue);
+ if (IntToPtrInst *Inst = dyn_cast<IntToPtrInst>(BaseValue))
+ return invalid<ReportIntToPtr>(Context, /*Assert=*/true, Inst);
if (IgnoreAliasing)
return true;
// not proof this without -basicaa we would fail. We disable this check to
// not cause irrelevant verification failures.
if (!AS.isMustAlias())
- return invalid<ReportAlias>(Context, /*Assert=*/true, &AS);
+ return invalid<ReportAlias>(Context, /*Assert=*/true, &Inst, &AS);
return true;
}
if (BasicBlock *Exit = R.getExit()) {
BasicBlock::iterator I = Exit->begin();
if (I != Exit->end() && isa<PHINode>(*I))
- return invalid<ReportPHIinExit>(Context, /*Assert=*/true);
+ return invalid<ReportPHIinExit>(Context, /*Assert=*/true, I);
}
return true;
// Region entering edges come from the same loop but outside the region
// are not allowed.
if (L->contains(*PI) && !R.contains(*PI))
- return invalid<ReportIndEdge>(Context, /*Assert=*/true);
+ return invalid<ReportIndEdge>(Context, /*Assert=*/true, *PI);
}
}
}
// SCoP cannot contain the entry block of the function, because we need
// to insert alloca instruction there when translate scalar to array.
if (R.getEntry() == &(R.getEntry()->getParent()->getEntryBlock()))
- return invalid<ReportEntry>(Context, /*Assert=*/true);
+ return invalid<ReportEntry>(Context, /*Assert=*/true, R.getEntry());
if (!isValidExit(Context))
return false;
}
}
+void
+ScopDetection::emitMissedRemarksForValidRegions(const Function &F,
+ const RegionSet &ValidRegions) {
+ for (const Region *R : ValidRegions) {
+ const Region *Parent = R->getParent();
+ if (Parent && !Parent->isTopLevelRegion() && RejectLogs.count(Parent))
+ emitRejectionRemarks(F, RejectLogs.at(Parent));
+ }
+}
+
+void ScopDetection::emitMissedRemarksForLeaves(const Function &F,
+ const Region *R) {
+ for (const std::unique_ptr<Region> &Child : *R) {
+ bool IsValid = ValidRegions.count(Child.get());
+ if (IsValid)
+ continue;
+
+ bool IsLeaf = Child->begin() == Child->end();
+ if (!IsLeaf)
+ emitMissedRemarksForLeaves(F, Child.get());
+ else {
+ if (RejectLogs.count(Child.get())) {
+ emitRejectionRemarks(F, RejectLogs.at(Child.get()));
+ }
+ }
+ }
+}
+
bool ScopDetection::runOnFunction(llvm::Function &F) {
LI = &getAnalysis<LoopInfo>();
RI = &getAnalysis<RegionInfo>();
findScops(*TopRegion);
+ // Only makes sense when we tracked errors.
+ if (PollyTrackFailures) {
+ emitMissedRemarksForValidRegions(F, ValidRegions);
+ emitMissedRemarksForLeaves(F, TopRegion);
+ }
+
+ for (const Region *R : ValidRegions)
+ emitValidRemarks(F, R);
+
if (ReportLevel >= 1)
printLocations(F);
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/AliasSetTracker.h"
#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Value.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/RegionInfo.h"
-#include "llvm/IR/DebugInfo.h"
#define DEBUG_TYPE "polly-detect"
#include "llvm/Support/Debug.h"
}
}
+void emitRejectionRemarks(const llvm::Function &F, const RejectLog &Log) {
+ LLVMContext &Ctx = F.getContext();
+
+ const Region *R = Log.region();
+ const BasicBlock *Entry = R->getEntry();
+ DebugLoc DL = Entry->getTerminator()->getDebugLoc();
+
+ emitOptimizationRemarkMissed(
+ Ctx, DEBUG_TYPE, F, DL,
+ "The following errors keep this region from being a Scop.");
+ for (RejectReasonPtr RR : Log) {
+ const DebugLoc &Loc = RR->getDebugLoc();
+ if (!Loc.isUnknown())
+ emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, Loc,
+ RR->getEndUserMessage());
+ }
+}
+
+void emitValidRemarks(const llvm::Function &F, const Region *R) {
+ LLVMContext &Ctx = F.getContext();
+
+ const BasicBlock *Entry = R->getEntry();
+ const BasicBlock *Exit = R->getExit();
+
+ const DebugLoc &Begin = Entry->getFirstNonPHIOrDbg()->getDebugLoc();
+ const DebugLoc &End = Exit->getFirstNonPHIOrDbg()->getDebugLoc();
+
+ emitOptimizationRemark(Ctx, DEBUG_TYPE, F, Begin,
+ "A valid Scop begins here.");
+ emitOptimizationRemark(Ctx, DEBUG_TYPE, F, End, "A valid Scop ends here.");
+}
+
+//===----------------------------------------------------------------------===//
+// RejectReason.
+
+const llvm::DebugLoc &RejectReason::getDebugLoc() const {
+ // Allocate an empty DebugLoc and return it a reference to it.
+ return *(std::make_shared<DebugLoc>().get());
+}
+
//===----------------------------------------------------------------------===//
// ReportCFG.
ReportCFG::ReportCFG() { ++BadCFGForScop; }
+//===----------------------------------------------------------------------===//
+// ReportNonBranchTerminator.
+
std::string ReportNonBranchTerminator::getMessage() const {
return ("Non branch instruction terminates BB: " + BB->getName()).str();
}
+const DebugLoc &ReportNonBranchTerminator::getDebugLoc() const {
+ return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportCondition.
+
std::string ReportCondition::getMessage() const {
return ("Not well structured condition at BB: " + BB->getName()).str();
}
-ReportAffFunc::ReportAffFunc() { ++BadAffFuncForScop; }
+const DebugLoc &ReportCondition::getDebugLoc() const {
+ return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportAffFunc.
+
+ReportAffFunc::ReportAffFunc(const Instruction *Inst)
+ : RejectReason(), Inst(Inst) {
+ ++BadAffFuncForScop;
+}
+
+//===----------------------------------------------------------------------===//
+// ReportUndefCond.
std::string ReportUndefCond::getMessage() const {
return ("Condition based on 'undef' value in BB: " + BB->getName()).str();
}
+//===----------------------------------------------------------------------===//
+// ReportInvalidCond.
+
std::string ReportInvalidCond::getMessage() const {
return ("Condition in BB '" + BB->getName()).str() +
"' neither constant nor an icmp instruction";
}
+//===----------------------------------------------------------------------===//
+// ReportUndefOperand.
+
std::string ReportUndefOperand::getMessage() const {
return ("undef operand in branch at BB: " + BB->getName()).str();
}
+//===----------------------------------------------------------------------===//
+// ReportNonAffBranch.
+
std::string ReportNonAffBranch::getMessage() const {
return ("Non affine branch in BB '" + BB->getName()).str() + "' with LHS: " +
*LHS + " and RHS: " + *RHS;
}
+//===----------------------------------------------------------------------===//
+// ReportNoBasePtr.
+
std::string ReportNoBasePtr::getMessage() const { return "No base pointer"; }
+//===----------------------------------------------------------------------===//
+// ReportUndefBasePtr.
+
std::string ReportUndefBasePtr::getMessage() const {
return "Undefined base pointer";
}
+//===----------------------------------------------------------------------===//
+// ReportVariantBasePtr.
+
std::string ReportVariantBasePtr::getMessage() const {
return "Base address not invariant in current region:" + *BaseValue;
}
+//===----------------------------------------------------------------------===//
+// ReportNonAffineAccess.
+
std::string ReportNonAffineAccess::getMessage() const {
return "Non affine access function: " + *AccessFunction;
}
-ReportIndVar::ReportIndVar() { ++BadIndVarForScop; }
+//===----------------------------------------------------------------------===//
+// ReportIndVar.
+
+ReportIndVar::ReportIndVar() : RejectReason() { ++BadIndVarForScop; }
+
+//===----------------------------------------------------------------------===//
+// ReportPhiNodeRefInRegion.
+
+ReportPhiNodeRefInRegion::ReportPhiNodeRefInRegion(Instruction *Inst)
+ : ReportIndVar(), Inst(Inst) {}
std::string ReportPhiNodeRefInRegion::getMessage() const {
return "SCEV of PHI node refers to SSA names in region: " + *Inst;
}
+const DebugLoc &ReportPhiNodeRefInRegion::getDebugLoc() const {
+ return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportNonCanonicalPhiNode.
+
+ReportNonCanonicalPhiNode::ReportNonCanonicalPhiNode(Instruction *Inst)
+ : ReportIndVar(), Inst(Inst) {}
+
std::string ReportNonCanonicalPhiNode::getMessage() const {
return "Non canonical PHI node: " + *Inst;
}
+const DebugLoc &ReportNonCanonicalPhiNode::getDebugLoc() const {
+ return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportLoopHeader.
+
+ReportLoopHeader::ReportLoopHeader(Loop *L) : ReportIndVar(), L(L) {}
+
std::string ReportLoopHeader::getMessage() const {
return ("No canonical IV at loop header: " + L->getHeader()->getName()).str();
}
-ReportIndEdge::ReportIndEdge() { ++BadIndEdgeForScop; }
+const DebugLoc &ReportLoopHeader::getDebugLoc() const {
+ BasicBlock *BB = L->getHeader();
+ return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportIndEdge.
+
+ReportIndEdge::ReportIndEdge(BasicBlock *BB) : RejectReason(), BB(BB) {
+ ++BadIndEdgeForScop;
+}
std::string ReportIndEdge::getMessage() const {
return "Region has invalid entering edges!";
}
+const DebugLoc &ReportIndEdge::getDebugLoc() const {
+ return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportLoopBound.
+
ReportLoopBound::ReportLoopBound(Loop *L, const SCEV *LoopCount)
- : L(L), LoopCount(LoopCount) {
+ : RejectReason(), L(L), LoopCount(LoopCount) {
++BadLoopBoundForScop;
}
L->getHeader()->getName();
}
-ReportFuncCall::ReportFuncCall(Instruction *Inst) : Inst(Inst) {
+const DebugLoc &ReportLoopBound::getDebugLoc() const {
+ const BasicBlock *BB = L->getHeader();
+ return BB->getTerminator()->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportFuncCall.
+
+ReportFuncCall::ReportFuncCall(Instruction *Inst) : RejectReason(), Inst(Inst) {
++BadFuncCallForScop;
}
return "Call instruction: " + *Inst;
}
-ReportAlias::ReportAlias(AliasSet *AS) : AS(AS) { ++BadAliasForScop; }
+const DebugLoc &ReportFuncCall::getDebugLoc() const {
+ return Inst->getDebugLoc();
+}
+
+std::string ReportFuncCall::getEndUserMessage() const {
+ return "This function call cannot be handeled. "
+ "Try to inline it.";
+}
+
+//===----------------------------------------------------------------------===//
+// ReportAlias.
+
+ReportAlias::ReportAlias(Instruction *Inst, AliasSet *AS)
+ : RejectReason(), AS(AS), Inst(Inst) {
+ ++BadAliasForScop;
+}
std::string ReportAlias::formatInvalidAlias(AliasSet &AS) const {
std::string Message;
std::string ReportAlias::getMessage() const { return formatInvalidAlias(*AS); }
-ReportSimpleLoop::ReportSimpleLoop() { ++BadSimpleLoopForScop; }
+const DebugLoc &ReportAlias::getDebugLoc() const { return Inst->getDebugLoc(); }
+
+//===----------------------------------------------------------------------===//
+// ReportSimpleLoop.
+
+ReportSimpleLoop::ReportSimpleLoop() : RejectReason() {
+ ++BadSimpleLoopForScop;
+}
std::string ReportSimpleLoop::getMessage() const {
return "Loop not in simplify form is invalid!";
}
-ReportOther::ReportOther() { ++BadOtherForScop; }
+//===----------------------------------------------------------------------===//
+// ReportOther.
+
+std::string ReportOther::getMessage() const { return "Unknown reject reason"; }
+
+ReportOther::ReportOther() : RejectReason() { ++BadOtherForScop; }
+
+//===----------------------------------------------------------------------===//
+// ReportIntToPtr.
+ReportIntToPtr::ReportIntToPtr(Instruction *BaseValue)
+ : ReportOther(), BaseValue(BaseValue) {}
std::string ReportIntToPtr::getMessage() const {
return "Find bad intToptr prt: " + *BaseValue;
}
+const DebugLoc &ReportIntToPtr::getDebugLoc() const {
+ return BaseValue->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportAlloca.
+
+ReportAlloca::ReportAlloca(Instruction *Inst) : ReportOther(), Inst(Inst) {}
+
std::string ReportAlloca::getMessage() const {
return "Alloca instruction: " + *Inst;
}
+const DebugLoc &ReportAlloca::getDebugLoc() const {
+ return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportUnknownInst.
+
+ReportUnknownInst::ReportUnknownInst(Instruction *Inst)
+ : ReportOther(), Inst(Inst) {}
+
std::string ReportUnknownInst::getMessage() const {
return "Unknown instruction: " + *Inst;
}
+const DebugLoc &ReportUnknownInst::getDebugLoc() const {
+ return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportPHIinExit.
+
+ReportPHIinExit::ReportPHIinExit(Instruction *Inst)
+ : ReportOther(), Inst(Inst) {}
+
std::string ReportPHIinExit::getMessage() const {
return "PHI node in exit BB";
}
+const DebugLoc &ReportPHIinExit::getDebugLoc() const {
+ return Inst->getDebugLoc();
+}
+
+//===----------------------------------------------------------------------===//
+// ReportEntry.
+ReportEntry::ReportEntry(BasicBlock *BB) : ReportOther(), BB(BB) {}
+
std::string ReportEntry::getMessage() const {
return "Region containing entry block of function is invalid!";
}
+
+const DebugLoc &ReportEntry::getDebugLoc() const {
+ return BB->getTerminator()->getDebugLoc();
+}
} // namespace polly
--- /dev/null
+; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1 | FileCheck %s
+
+; #define N 1024
+; double invalidCall(double A[N]);
+;
+; void a(double A[N], int n) {
+; for (int i=0; i<n; ++i) {
+; A[i] = invalidCall(A);
+; }
+; }
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+define void @a(double* %A, i32 %n) #0 {
+entry:
+ %cmp1 = icmp sgt i32 %n, 0, !dbg !10
+ br i1 %cmp1, label %for.body.lr.ph, label %for.end, !dbg !10
+
+for.body.lr.ph: ; preds = %entry
+ %0 = zext i32 %n to i64
+ br label %for.body, !dbg !10
+
+for.body: ; preds = %for.body, %for.body.lr.ph
+ %indvar = phi i64 [ 0, %for.body.lr.ph ], [ %indvar.next, %for.body ]
+ %arrayidx = getelementptr double* %A, i64 %indvar, !dbg !12
+ %call = tail call double @invalidCall(double* %A) #2, !dbg !12
+ store double %call, double* %arrayidx, align 8, !dbg !12, !tbaa !14
+ %indvar.next = add i64 %indvar, 1, !dbg !10
+ %exitcond = icmp eq i64 %indvar.next, %0, !dbg !10
+ br i1 %exitcond, label %for.end.loopexit, label %for.body, !dbg !10
+
+for.end.loopexit: ; preds = %for.body
+ br label %for.end
+
+for.end: ; preds = %for.end.loopexit, %entry
+ ret void, !dbg !18
+}
+
+declare double @invalidCall(double*) #1
+
+; CHECK: remark: ReportFuncCall.c:4:8: The following errors keep this region from being a Scop.
+; CHECK: remark: ReportFuncCall.c:5:12: This function call cannot be handeled. Try to inline it.
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!7, !8}
+!llvm.ident = !{!9}
+
+!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5.0 ", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 2} ; [ DW_TAG_compile_unit ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c] [DW_LANG_C99]
+!1 = metadata !{metadata !"ReportFuncCall.c", metadata !"/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics"}
+!2 = metadata !{}
+!3 = metadata !{metadata !4}
+!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"a", metadata !"a", metadata !"", i32 3, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 true, void (double*, i32)* @a, null, null, metadata !2, i32 3} ; [ DW_TAG_subprogram ] [line 3] [def] [a]
+!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c]
+!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ]
+!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4}
+!8 = metadata !{i32 2, metadata !"Debug Info Version", i32 1}
+!9 = metadata !{metadata !"clang version 3.5.0 "}
+!10 = metadata !{i32 4, i32 8, metadata !11, null}
+!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 3, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c]
+!12 = metadata !{i32 5, i32 12, metadata !13, null}
+!13 = metadata !{i32 786443, metadata !1, metadata !11, i32 4, i32 27, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [/home/simbuerg/Projekte/llvm/tools/polly/test/ScopDetectionDiagnostics/ReportFuncCall.c]
+!14 = metadata !{metadata !15, metadata !15, i64 0}
+!15 = metadata !{metadata !"double", metadata !16, i64 0}
+!16 = metadata !{metadata !"omnipotent char", metadata !17, i64 0}
+!17 = metadata !{metadata !"Simple C/C++ TBAA"}
+!18 = metadata !{i32 7, i32 1, metadata !4, null}