Index: polly/trunk/include/polly/ScopDetection.h =================================================================== --- polly/trunk/include/polly/ScopDetection.h +++ polly/trunk/include/polly/ScopDetection.h @@ -326,6 +326,23 @@ 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. /// Index: polly/trunk/include/polly/ScopDetectionDiagnostic.h =================================================================== --- polly/trunk/include/polly/ScopDetectionDiagnostic.h +++ polly/trunk/include/polly/ScopDetectionDiagnostic.h @@ -52,6 +52,20 @@ 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. /// @@ -67,6 +81,23 @@ /// /// @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 RejectReasonPtr; @@ -79,10 +110,10 @@ public: explicit RejectLog(Region *R) : R(R) {} - typedef llvm::SmallVector::iterator iterator; + typedef llvm::SmallVector::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; } @@ -104,11 +135,12 @@ 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; //@} }; @@ -121,11 +153,12 @@ 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; //@} }; @@ -136,8 +169,16 @@ /// 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(); + } }; //===----------------------------------------------------------------------===// @@ -149,11 +190,12 @@ 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; //@} }; @@ -168,11 +210,12 @@ 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; //@} }; @@ -185,11 +228,12 @@ 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; //@} }; @@ -208,15 +252,16 @@ //@} 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; //@} }; @@ -225,9 +270,11 @@ 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; //@} }; @@ -236,9 +283,11 @@ 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; //@} }; @@ -251,11 +300,12 @@ 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; //@} }; @@ -268,14 +318,14 @@ 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; //@} }; @@ -299,11 +349,12 @@ 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; //@} }; @@ -316,11 +367,12 @@ 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; //@} }; @@ -333,11 +385,12 @@ 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; //@} }; @@ -345,12 +398,16 @@ /// @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; //@} }; @@ -372,7 +429,8 @@ /// @name RejectReason interface //@{ - virtual std::string getMessage() const; + virtual std::string getMessage() const override; + virtual const DebugLoc &getDebugLoc() const override; //@} }; @@ -389,7 +447,9 @@ /// @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; //@} }; @@ -398,20 +458,21 @@ 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; //@} }; @@ -424,7 +485,7 @@ /// @name RejectReason interface //@{ - std::string getMessage() const; + virtual std::string getMessage() const override; //@} }; @@ -437,7 +498,7 @@ /// @name RejectReason interface //@{ - std::string getMessage() const { return "Unknown reject reason"; } + virtual std::string getMessage() const override; //@} }; @@ -447,14 +508,15 @@ //===--------------------------------------------------------------------===// // 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; //@} }; @@ -465,11 +527,12 @@ 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; //@} }; @@ -480,11 +543,12 @@ 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; //@} }; @@ -492,10 +556,15 @@ /// @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; //@} }; @@ -503,10 +572,15 @@ /// @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; //@} }; Index: polly/trunk/lib/Analysis/ScopDetection.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopDetection.cpp +++ polly/trunk/lib/Analysis/ScopDetection.cpp @@ -250,11 +250,11 @@ // UndefValue is not allowed as condition. if (isa(Condition)) - return invalid(Context, /*Assert=*/true, &BB); + return invalid(Context, /*Assert=*/true, Br, &BB); // Only Constant and ICmpInst are allowed as condition. if (!(isa(Condition) || isa(Condition))) - return invalid(Context, /*Assert=*/true, &BB); + return invalid(Context, /*Assert=*/true, Br, &BB); // Allow perfectly nested conditions. assert(Br->getNumSuccessors() == 2 && "Unexpected number of successors"); @@ -271,7 +271,7 @@ // Are both operands of the ICmp affine? if (isa(ICmp->getOperand(0)) || isa(ICmp->getOperand(1))) - return invalid(Context, /*Assert=*/true, &BB); + return invalid(Context, /*Assert=*/true, &BB, ICmp); Loop *L = LI->getLoopFor(ICmp->getParent()); const SCEV *LHS = SE->getSCEVAtScope(ICmp->getOperand(0), L); @@ -280,7 +280,7 @@ if (!isAffineExpr(&Context.CurRegion, LHS, *SE) || !isAffineExpr(&Context.CurRegion, RHS, *SE)) return invalid(Context, /*Assert=*/true, &BB, LHS, - RHS); + RHS, ICmp); } // Allow loop exit conditions. @@ -380,8 +380,8 @@ const SCEVAddRecExpr *AF = PIAF.second; const Instruction *Insn = PIAF.first; if (Shape->DelinearizedSizes.empty()) - return invalid(Context, /*Assert=*/true, - PIAF.second); + return invalid(Context, /*Assert=*/true, AF, + Insn); MemAcc *Acc = new MemAcc(Insn, Shape); InsnToMemAcc.insert({Insn, Acc}); @@ -389,12 +389,14 @@ Shape->DelinearizedSizes); if (Shape->DelinearizedSizes.empty() || Acc->DelinearizedSubscripts.empty()) - return invalid(Context, /*Assert=*/true, AF); + return invalid(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(Context, /*Assert=*/true, AF); + return invalid(Context, /*Assert=*/true, AF, + Insn); } } return true; @@ -411,12 +413,12 @@ BasePointer = dyn_cast(SE->getPointerBase(AccessFunction)); if (!BasePointer) - return invalid(Context, /*Assert=*/true); + return invalid(Context, /*Assert=*/true, &Inst); BaseValue = BasePointer->getValue(); if (isa(BaseValue)) - return invalid(Context, /*Assert=*/true); + return invalid(Context, /*Assert=*/true, &Inst); // Check that the base address of the access is invariant in the current // region. @@ -424,7 +426,8 @@ // 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(Context, /*Assert=*/false, BaseValue); + return invalid(Context, /*Assert=*/false, BaseValue, + &Inst); AccessFunction = SE->getMinusSCEV(AccessFunction, BasePointer); @@ -436,7 +439,7 @@ if (!PollyDelinearize || !AF) return invalid(Context, /*Assert=*/true, - AccessFunction); + AccessFunction, &Inst); const SCEV *ElementSize = SE->getElementSize(&Inst); Context.ElementSize[BasePointer] = ElementSize; @@ -456,8 +459,8 @@ // FIXME: Alias Analysis thinks IntToPtrInst aliases with alloca instructions // created by IndependentBlocks Pass. - if (isa(BaseValue)) - return invalid(Context, /*Assert=*/true, BaseValue); + if (IntToPtrInst *Inst = dyn_cast(BaseValue)) + return invalid(Context, /*Assert=*/true, Inst); if (IgnoreAliasing) return true; @@ -476,7 +479,7 @@ // not proof this without -basicaa we would fail. We disable this check to // not cause irrelevant verification failures. if (!AS.isMustAlias()) - return invalid(Context, /*Assert=*/true, &AS); + return invalid(Context, /*Assert=*/true, &Inst, &AS); return true; } @@ -692,7 +695,7 @@ if (BasicBlock *Exit = R.getExit()) { BasicBlock::iterator I = Exit->begin(); if (I != Exit->end() && isa(*I)) - return invalid(Context, /*Assert=*/true); + return invalid(Context, /*Assert=*/true, I); } return true; @@ -745,7 +748,7 @@ // Region entering edges come from the same loop but outside the region // are not allowed. if (L->contains(*PI) && !R.contains(*PI)) - return invalid(Context, /*Assert=*/true); + return invalid(Context, /*Assert=*/true, *PI); } } } @@ -753,7 +756,7 @@ // 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(Context, /*Assert=*/true); + return invalid(Context, /*Assert=*/true, R.getEntry()); if (!isValidExit(Context)) return false; @@ -780,6 +783,34 @@ } } +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 &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(); RI = &getAnalysis(); @@ -800,6 +831,15 @@ 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); Index: polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp +++ polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp @@ -22,12 +22,15 @@ #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" @@ -81,75 +84,204 @@ } } +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().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; } @@ -158,7 +290,15 @@ 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; } @@ -166,7 +306,22 @@ 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; @@ -204,31 +359,89 @@ 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 Index: polly/trunk/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll =================================================================== --- polly/trunk/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll +++ polly/trunk/test/ScopDetectionDiagnostics/ReportFuncCall-01.ll @@ -0,0 +1,67 @@ +; 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