Index: polly/trunk/include/polly/ScopDetection.h =================================================================== --- polly/trunk/include/polly/ScopDetection.h +++ polly/trunk/include/polly/ScopDetection.h @@ -52,6 +52,7 @@ #include "llvm/ADT/SetVector.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/OptimizationDiagnosticInfo.h" #include "llvm/Analysis/RegionInfo.h" #include "llvm/Pass.h" #include @@ -526,7 +527,8 @@ public: ScopDetection(Function &F, const DominatorTree &DT, ScalarEvolution &SE, - LoopInfo &LI, RegionInfo &RI, AliasAnalysis &AA); + LoopInfo &LI, RegionInfo &RI, AliasAnalysis &AA, + OptimizationRemarkEmitter &ORE); /// Get the RegionInfo stored in this pass. /// @@ -607,6 +609,9 @@ static ScopDetection::LoopStats countBeneficialLoops(Region *R, ScalarEvolution &SE, LoopInfo &LI, unsigned MinProfitableTrips); + + /// OptimizationRemarkEmitter object used to emit diagnostic remarks + OptimizationRemarkEmitter &ORE; }; struct ScopAnalysis : public AnalysisInfoMixin { Index: polly/trunk/include/polly/ScopDetectionDiagnostic.h =================================================================== --- polly/trunk/include/polly/ScopDetectionDiagnostic.h +++ polly/trunk/include/polly/ScopDetectionDiagnostic.h @@ -25,6 +25,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/OptimizationDiagnosticInfo.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Value.h" @@ -59,7 +60,8 @@ /// Remember to at least track failures (-polly-detect-track-failures). /// @param P The region delimiters (entry & exit) we emit remarks for. /// @param Log The error log containing all messages being emitted as remark. -void emitRejectionRemarks(const BBPair &P, const RejectLog &Log); +void emitRejectionRemarks(const BBPair &P, const RejectLog &Log, + OptimizationRemarkEmitter &ORE); // Discriminator for LLVM-style RTTI (dyn_cast<> et al.) enum class RejectReasonKind { @@ -123,6 +125,16 @@ virtual ~RejectReason() {} + /// Generate the remark name to identify this remark. + /// + /// @return A short string that identifies the error. + virtual std::string getRemarkName() const = 0; + + /// Get the Basic Block containing this remark. + /// + /// @return The Basic Block containing this remark. + virtual const Value *getRemarkBB() const = 0; + /// Generate a reasonable diagnostic message describing this error. /// /// @return A debug message representing this error. @@ -203,6 +215,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual const DebugLoc &getDebugLoc() const override; //@} @@ -225,6 +239,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual std::string getEndUserMessage() const override; virtual const DebugLoc &getDebugLoc() const override; @@ -249,6 +265,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual std::string getEndUserMessage() const override; virtual const DebugLoc &getDebugLoc() const override; @@ -263,6 +281,7 @@ class ReportAffFunc : public RejectReason { //===--------------------------------------------------------------------===// +protected: // The instruction that caused non-affinity to occur. const Instruction *Inst; @@ -301,6 +320,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; //@} }; @@ -326,6 +347,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; //@} }; @@ -349,6 +372,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; //@} }; @@ -383,6 +408,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; //@} }; @@ -402,6 +429,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; //@} }; @@ -421,6 +450,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; //@} }; @@ -445,6 +476,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual std::string getEndUserMessage() const override; //@} @@ -476,6 +509,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual std::string getEndUserMessage() const override; //@} @@ -501,6 +536,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual std::string getEndUserMessage() const override; //@} @@ -532,6 +569,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual const DebugLoc &getDebugLoc() const override; virtual std::string getEndUserMessage() const override; @@ -560,6 +599,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual const DebugLoc &getDebugLoc() const override; virtual std::string getEndUserMessage() const override; @@ -588,6 +629,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual const DebugLoc &getDebugLoc() const override; virtual std::string getEndUserMessage() const override; @@ -612,6 +655,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual const DebugLoc &getDebugLoc() const override; virtual std::string getEndUserMessage() const override; @@ -650,6 +695,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual const DebugLoc &getDebugLoc() const override; virtual std::string getEndUserMessage() const override; @@ -670,6 +717,7 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; virtual std::string getMessage() const override; //@} }; @@ -692,6 +740,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual const DebugLoc &getDebugLoc() const override; //@} @@ -713,6 +763,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual const DebugLoc &getDebugLoc() const override; //@} @@ -734,6 +786,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual const DebugLoc &getDebugLoc() const override; //@} @@ -755,6 +809,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual std::string getEndUserMessage() const override; virtual const DebugLoc &getDebugLoc() const override; @@ -777,6 +833,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual std::string getEndUserMessage() const override; virtual const DebugLoc &getDebugLoc() const override; @@ -801,6 +859,8 @@ /// @name RejectReason interface //@{ + virtual std::string getRemarkName() const override; + virtual const Value *getRemarkBB() const override; virtual std::string getMessage() const override; virtual const DebugLoc &getDebugLoc() const override; virtual std::string getEndUserMessage() const override; Index: polly/trunk/include/polly/ScopInfo.h =================================================================== --- polly/trunk/include/polly/ScopInfo.h +++ polly/trunk/include/polly/ScopInfo.h @@ -1658,6 +1658,9 @@ /// The context of the SCoP created during SCoP detection. ScopDetection::DetectionContext &DC; + /// OptimizationRemarkEmitter object for displaying diagnostic remarks + OptimizationRemarkEmitter &ORE; + /// Isl context. /// /// We need a shared_ptr with reference counter to delete the context when all @@ -1822,7 +1825,7 @@ /// Scop constructor; invoked from ScopBuilder::buildScop. Scop(Region &R, ScalarEvolution &SE, LoopInfo &LI, - ScopDetection::DetectionContext &DC); + ScopDetection::DetectionContext &DC, OptimizationRemarkEmitter &ORE); //@} @@ -2453,10 +2456,12 @@ /// @param Loc The location in the source that caused this assumption. /// @param Sign Enum to indicate if the assumptions in @p Set are positive /// (needed/assumptions) or negative (invalid/restrictions). + /// @param BB The block in which this assumption was taken. Used to + /// calculate hotness when emitting remark. /// /// @returns True if the assumption is not trivial. bool trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set, - DebugLoc Loc, AssumptionSign Sign); + DebugLoc Loc, AssumptionSign Sign, BasicBlock *BB); /// Add assumptions to assumed context. /// @@ -2474,8 +2479,10 @@ /// @param Loc The location in the source that caused this assumption. /// @param Sign Enum to indicate if the assumptions in @p Set are positive /// (needed/assumptions) or negative (invalid/restrictions). + /// @param BB The block in which this assumption was taken. Used to + /// calculate hotness when emitting remark. void addAssumption(AssumptionKind Kind, __isl_take isl_set *Set, DebugLoc Loc, - AssumptionSign Sign); + AssumptionSign Sign, BasicBlock *BB); /// Record an assumption for later addition to the assumed context. /// @@ -2508,7 +2515,8 @@ /// /// @param Kind The assumption kind describing the underlying cause. /// @param Loc The location in the source that triggered . - void invalidate(AssumptionKind Kind, DebugLoc Loc); + /// @param BB The BasicBlock where it was triggered. + void invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB = nullptr); /// Get the invalid context for this Scop. /// Index: polly/trunk/lib/Analysis/ScopBuilder.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopBuilder.cpp +++ polly/trunk/lib/Analysis/ScopBuilder.cpp @@ -427,7 +427,7 @@ cast(Sizes.back())->getAPInt().getSExtValue(); Sizes.pop_back(); if (ElementSize != DelinearizedSize) - scop->invalidate(DELINEARIZATION, Inst->getDebugLoc()); + scop->invalidate(DELINEARIZATION, Inst->getDebugLoc(), Inst->getParent()); addArrayAccess(Stmt, Inst, AccType, BasePointer->getValue(), ElementType, true, AccItr->second.DelinearizedSubscripts, Sizes, Val); @@ -935,7 +935,7 @@ } void ScopBuilder::buildScop(Region &R, AssumptionCache &AC) { - scop.reset(new Scop(R, SE, LI, *SD.getDetectionContext(&R))); + scop.reset(new Scop(R, SE, LI, *SD.getDetectionContext(&R), SD.ORE)); buildStmts(R); buildAccessFunctions(); @@ -1038,12 +1038,13 @@ ScopDetection &SD, ScalarEvolution &SE) : AA(AA), DL(DL), DT(DT), LI(LI), SD(SD), SE(SE) { - Function *F = R->getEntry()->getParent(); - DebugLoc Beg, End; - getDebugLocations(getBBPairForRegion(R), Beg, End); + auto P = getBBPairForRegion(R); + getDebugLocations(P, Beg, End); + std::string Msg = "SCoP begins here."; - emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, Beg, Msg); + SD.ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEntry", Beg, P.first) + << Msg); buildScop(*R, AC); @@ -1060,5 +1061,10 @@ ++RichScopFound; } - emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, End, Msg); + if (R->isTopLevelRegion()) + SD.ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEnd", End, P.first) + << Msg); + else + SD.ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "ScopEnd", End, P.second) + << Msg); } Index: polly/trunk/lib/Analysis/ScopDetection.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopDetection.cpp +++ polly/trunk/lib/Analysis/ScopDetection.cpp @@ -284,8 +284,8 @@ ScopDetection::ScopDetection(Function &F, const DominatorTree &DT, ScalarEvolution &SE, LoopInfo &LI, RegionInfo &RI, - AliasAnalysis &AA) - : DT(DT), SE(SE), LI(LI), RI(RI), AA(AA) { + AliasAnalysis &AA, OptimizationRemarkEmitter &ORE) + : DT(DT), SE(SE), LI(LI), RI(RI), AA(AA), ORE(ORE) { if (!PollyProcessUnprofitable && LI.empty()) return; @@ -1579,7 +1579,7 @@ for (auto &DIt : DetectionContextMap) { auto &DC = DIt.getSecond(); if (DC.Log.hasErrors()) - emitRejectionRemarks(DIt.getFirst(), DC.Log); + emitRejectionRemarks(DIt.getFirst(), DC.Log, ORE); } } @@ -1728,7 +1728,8 @@ auto &AA = getAnalysis().getAAResults(); auto &SE = getAnalysis().getSE(); auto &DT = getAnalysis().getDomTree(); - Result.reset(new ScopDetection(F, DT, SE, LI, RI, AA)); + auto &ORE = getAnalysis().getORE(); + Result.reset(new ScopDetection(F, DT, SE, LI, RI, AA, ORE)); return false; } @@ -1736,6 +1737,7 @@ AU.addRequired(); AU.addRequiredTransitive(); AU.addRequired(); + AU.addRequired(); // We also need AA and RegionInfo when we are verifying analysis. AU.addRequiredTransitive(); AU.addRequiredTransitive(); @@ -1767,7 +1769,8 @@ auto &AA = FAM.getResult(F); auto &SE = FAM.getResult(F); auto &DT = FAM.getResult(F); - return {F, DT, SE, LI, RI, AA}; + auto &ORE = FAM.getResult(F); + return {F, DT, SE, LI, RI, AA, ORE}; } PreservedAnalyses ScopAnalysisPrinterPass::run(Function &F, @@ -1792,5 +1795,6 @@ INITIALIZE_PASS_DEPENDENCY(RegionInfoPass); INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass); INITIALIZE_PASS_DEPENDENCY(ScalarEvolutionWrapperPass); +INITIALIZE_PASS_DEPENDENCY(OptimizationRemarkEmitterWrapperPass); INITIALIZE_PASS_END(ScopDetectionWrapperPass, "polly-detect", "Polly - Detect static control parts (SCoPs)", false, false) Index: polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp +++ polly/trunk/lib/Analysis/ScopDetectionDiagnostic.cpp @@ -23,6 +23,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/LoopInfo.h" +#include "llvm/Analysis/OptimizationDiagnosticInfo.h" #include "llvm/Analysis/RegionInfo.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DebugInfo.h" @@ -121,28 +122,36 @@ } } -void emitRejectionRemarks(const BBPair &P, const RejectLog &Log) { - Function &F = *P.first->getParent(); - LLVMContext &Ctx = F.getContext(); - +void emitRejectionRemarks(const BBPair &P, const RejectLog &Log, + OptimizationRemarkEmitter &ORE) { DebugLoc Begin, End; getDebugLocations(P, Begin, End); - emitOptimizationRemarkMissed( - Ctx, DEBUG_TYPE, F, Begin, - "The following errors keep this region from being a Scop."); + 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()) - emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, Loc, - RR->getEndUserMessage()); + ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Loc, + RR->getRemarkBB()) + << RR->getEndUserMessage()); else - emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, Begin, - RR->getEndUserMessage()); + ORE.emit(OptimizationRemarkMissed(DEBUG_TYPE, RR->getRemarkName(), Begin, + RR->getRemarkBB()) + << RR->getEndUserMessage()); } - emitOptimizationRemarkMissed(Ctx, DEBUG_TYPE, F, End, - "Invalid Scop candidate ends here."); + /* 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."); } //===----------------------------------------------------------------------===// @@ -179,6 +188,12 @@ //===----------------------------------------------------------------------===// // 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(); } @@ -194,6 +209,12 @@ //===----------------------------------------------------------------------===// // 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; @@ -212,6 +233,14 @@ //===----------------------------------------------------------------------===// // 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(); } @@ -240,6 +269,10 @@ //===----------------------------------------------------------------------===// // 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(); } @@ -251,6 +284,10 @@ //===----------------------------------------------------------------------===// // 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"; @@ -263,6 +300,10 @@ //===----------------------------------------------------------------------===// // 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(); } @@ -274,6 +315,10 @@ //===----------------------------------------------------------------------===// // 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; @@ -286,6 +331,10 @@ //===----------------------------------------------------------------------===// // 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) { @@ -295,6 +344,12 @@ //===----------------------------------------------------------------------===// // 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"; } @@ -306,6 +361,14 @@ //===----------------------------------------------------------------------===// // 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; } @@ -321,6 +384,14 @@ //===----------------------------------------------------------------------===// // 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"; } @@ -340,6 +411,14 @@ //===----------------------------------------------------------------------===// // 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; } @@ -361,6 +440,10 @@ : 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(); @@ -379,6 +462,12 @@ //===----------------------------------------------------------------------===// // 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."; } @@ -396,6 +485,14 @@ //===----------------------------------------------------------------------===// // 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."; @@ -418,6 +515,10 @@ 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; } @@ -441,6 +542,14 @@ 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; } @@ -499,6 +608,10 @@ 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: "); } @@ -517,6 +630,8 @@ //===----------------------------------------------------------------------===// // ReportOther. +std::string ReportOther::getRemarkName() const { return "UnknownRejectReason"; } + std::string ReportOther::getMessage() const { return "Unknown reject reason"; } ReportOther::ReportOther(const RejectReasonKind K) : RejectReason(K) {} @@ -531,6 +646,12 @@ 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; } @@ -549,6 +670,10 @@ 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; } @@ -567,6 +692,12 @@ 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; } @@ -584,6 +715,10 @@ 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!"; } @@ -605,6 +740,10 @@ 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!"; } Index: polly/trunk/lib/Analysis/ScopInfo.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopInfo.cpp +++ polly/trunk/lib/Analysis/ScopInfo.cpp @@ -1617,7 +1617,8 @@ } if (TooComplex) { - S.invalidate(COMPLEXITY, TI ? TI->getDebugLoc() : DebugLoc()); + S.invalidate(COMPLEXITY, TI ? TI->getDebugLoc() : DebugLoc(), + TI ? TI->getParent() : nullptr /* BasicBlock */); isl_set_free(AlternativeCondSet); isl_set_free(ConsequenceCondSet); return false; @@ -2163,7 +2164,6 @@ void Scop::addUserAssumptions( AssumptionCache &AC, DominatorTree &DT, LoopInfo &LI, DenseMap &InvalidDomainMap) { - auto &F = getFunction(); for (auto &Assumption : AC.assumptions()) { auto *CI = dyn_cast_or_null(Assumption); if (!CI || CI->getNumArgOperands() != 1) @@ -2177,9 +2177,9 @@ auto *Val = CI->getArgOperand(0); ParameterSetTy DetectedParams; if (!isAffineConstraint(Val, &R, L, *SE, DetectedParams)) { - emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F, - CI->getDebugLoc(), - "Non-affine user assumption ignored."); + ORE.emit( + OptimizationRemarkAnalysis(DEBUG_TYPE, "IgnoreUserAssumption", CI) + << "Non-affine user assumption ignored."); continue; } @@ -2227,10 +2227,8 @@ isl_set_project_out(AssumptionCtx, isl_dim_param, u--, 1); } } - - emitOptimizationRemarkAnalysis( - F.getContext(), DEBUG_TYPE, F, CI->getDebugLoc(), - "Use user assumption: " + stringFromIslObj(AssumptionCtx)); + ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "UserAssumption", CI) + << "Use user assumption: " << stringFromIslObj(AssumptionCtx)); Context = isl_set_intersect(Context, AssumptionCtx); } } @@ -2827,7 +2825,7 @@ continue; InvalidDomainMap.erase(BB); - invalidate(COMPLEXITY, TI->getDebugLoc()); + invalidate(COMPLEXITY, TI->getDebugLoc(), TI->getParent()); return false; } @@ -3383,17 +3381,13 @@ SmallPtrSet ReadWriteArrays; SmallPtrSet ReadOnlyArrays; - auto &F = getFunction(); - if (AliasGroup.size() < 2) return true; for (MemoryAccess *Access : AliasGroup) { - emitOptimizationRemarkAnalysis( - F.getContext(), DEBUG_TYPE, F, - Access->getAccessInstruction()->getDebugLoc(), - "Possibly aliasing pointer, use restrict keyword."); - + ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "PossibleAlias", + Access->getAccessInstruction()) + << "Possibly aliasing pointer, use restrict keyword."); const ScopArrayInfo *Array = Access->getScopArrayInfo(); if (HasWriteAccess.count(Array)) { ReadWriteArrays.insert(Array); @@ -3417,7 +3411,8 @@ // compute a sufficiently tight lower and upper bound: bail out. for (MemoryAccess *MA : AliasGroup) { if (!MA->isAffine()) { - invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc()); + invalidate(ALIASING, MA->getAccessInstruction()->getDebugLoc(), + MA->getAccessInstruction()->getParent()); return false; } } @@ -3492,10 +3487,10 @@ } Scop::Scop(Region &R, ScalarEvolution &ScalarEvolution, LoopInfo &LI, - ScopDetection::DetectionContext &DC) + ScopDetection::DetectionContext &DC, OptimizationRemarkEmitter &ORE) : SE(&ScalarEvolution), R(R), name(R.getNameStr()), IsOptimized(false), HasSingleExitEdge(R.getExitingBlock()), HasErrorBlock(false), - MaxLoopDepth(0), CopyStmtsNum(0), SkipScop(false), DC(DC), + MaxLoopDepth(0), CopyStmtsNum(0), SkipScop(false), DC(DC), ORE(ORE), IslCtx(isl_ctx_alloc(), isl_ctx_free), Context(nullptr), Affinator(this, LI), AssumedContext(nullptr), InvalidContext(nullptr), Schedule(nullptr), @@ -3850,7 +3845,7 @@ if (isl_set_n_basic_set(DomainCtx) >= MaxDisjunctsInDomain) { auto *AccInst = InvMAs.front().MA->getAccessInstruction(); - invalidate(COMPLEXITY, AccInst->getDebugLoc()); + invalidate(COMPLEXITY, AccInst->getDebugLoc(), AccInst->getParent()); isl_set_free(DomainCtx); for (auto &InvMA : InvMAs) isl_set_free(InvMA.NonHoistableCtx); @@ -4024,7 +4019,7 @@ return nullptr; addAssumption(INVARIANTLOAD, WrittenCtx.copy(), LI->getDebugLoc(), - AS_RESTRICTION); + AS_RESTRICTION, LI->getParent()); return WrittenCtx; } @@ -4034,7 +4029,7 @@ assert(LI && contains(LI)); ScopStmt *Stmt = getStmtFor(LI); if (Stmt && Stmt->getArrayAccessOrNULLFor(LI)) { - invalidate(INVARIANTLOAD, LI->getDebugLoc()); + invalidate(INVARIANTLOAD, LI->getDebugLoc(), LI->getParent()); return; } } @@ -4319,7 +4314,7 @@ } bool Scop::trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set, - DebugLoc Loc, AssumptionSign Sign) { + DebugLoc Loc, AssumptionSign Sign, BasicBlock *BB) { if (PollyRemarksMinimal && !isEffectiveAssumption(Set, Sign)) return false; @@ -4370,19 +4365,24 @@ break; } - auto &F = getFunction(); auto Suffix = Sign == AS_ASSUMPTION ? " assumption:\t" : " restriction:\t"; std::string Msg = toString(Kind) + Suffix + stringFromIslObj(Set); - emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F, Loc, Msg); + if (BB) + ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc, BB) + << Msg); + else + ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "AssumpRestrict", Loc, + R.getEntry()) + << Msg); return true; } void Scop::addAssumption(AssumptionKind Kind, __isl_take isl_set *Set, - DebugLoc Loc, AssumptionSign Sign) { + DebugLoc Loc, AssumptionSign Sign, BasicBlock *BB) { // Simplify the assumptions/restrictions first. Set = isl_set_gist_params(Set, getContext()); - if (!trackAssumption(Kind, Set, Loc, Sign)) { + if (!trackAssumption(Kind, Set, Loc, Sign, BB)) { isl_set_free(Set); return; } @@ -4408,7 +4408,7 @@ const Assumption &AS = RecordedAssumptions.pop_back_val(); if (!AS.BB) { - addAssumption(AS.Kind, AS.Set, AS.Loc, AS.Sign); + addAssumption(AS.Kind, AS.Set, AS.Loc, AS.Sign, nullptr /* BasicBlock */); continue; } @@ -4434,12 +4434,12 @@ else /* (AS.Sign == AS_ASSUMPTION) */ S = isl_set_params(isl_set_subtract(Dom, S)); - addAssumption(AS.Kind, S, AS.Loc, AS_RESTRICTION); + addAssumption(AS.Kind, S, AS.Loc, AS_RESTRICTION, AS.BB); } } -void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc) { - addAssumption(Kind, isl_set_empty(getParamSpace()), Loc, AS_ASSUMPTION); +void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB) { + addAssumption(Kind, isl_set_empty(getParamSpace()), Loc, AS_ASSUMPTION, BB); } __isl_give isl_set *Scop::getInvalidContext() const { @@ -4571,7 +4571,7 @@ } auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc(); - invalidate(COMPLEXITY, DL); + invalidate(COMPLEXITY, DL, BB); return Affinator.getPwAff(SE->getZero(E->getType()), BB); } Index: polly/trunk/test/ScopDetectionDiagnostics/ReportUnprofitable.ll =================================================================== --- polly/trunk/test/ScopDetectionDiagnostics/ReportUnprofitable.ll +++ polly/trunk/test/ScopDetectionDiagnostics/ReportUnprofitable.ll @@ -1,13 +1,18 @@ ; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \ ; RUN: -polly-detect-track-failures -polly-detect -analyze \ ; RUN: -polly-process-unprofitable=false < %s 2>&1| FileCheck %s + +; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" \ +; RUN: -polly-detect-track-failures -polly-detect -analyze \ +; RUN: -polly-process-unprofitable=false < %s 2>&1 -pass-remarks-output=%t.yaml +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; void onlyWrite(float *A) { ; for (long i = 0; i < 100; i++) ; A[i] = 0; ; } -; +; ; void onlyRead(float *A) { ; for (long i = 0; i < 100; i++) ; A[i]; @@ -21,6 +26,54 @@ ; CHECK: remark: /tmp/test.c:7:3: No profitable polyhedral optimization found ; CHECK: remark: /tmp/test.c:8:10: Invalid Scop candidate ends here. +; YAML: --- !Missed +; YAML: Pass: polly-detect +; YAML: Name: RejectionErrors +; YAML: DebugLoc: { File: /tmp/test.c, Line: 2, Column: 3 } +; YAML: Function: onlyWrite +; YAML: Args: +; YAML: - String: The following errors keep this region from being a Scop. +; YAML: ... +; YAML: --- !Missed +; YAML: Pass: polly-detect +; YAML: Name: Unprofitable +; YAML: DebugLoc: { File: /tmp/test.c, Line: 2, Column: 3 } +; YAML: Function: onlyWrite +; YAML: Args: +; YAML: - String: No profitable polyhedral optimization found +; YAML: ... +; YAML: --- !Missed +; YAML: Pass: polly-detect +; YAML: Name: InvalidScopEnd +; YAML: DebugLoc: { File: /tmp/test.c, Line: 3, Column: 10 } +; YAML: Function: onlyWrite +; YAML: Args: +; YAML: - String: Invalid Scop candidate ends here. +; YAML: ... +; YAML: --- !Missed +; YAML: Pass: polly-detect +; YAML: Name: RejectionErrors +; YAML: DebugLoc: { File: /tmp/test.c, Line: 7, Column: 3 } +; YAML: Function: onlyRead +; YAML: Args: +; YAML: - String: The following errors keep this region from being a Scop. +; YAML: ... +; YAML: --- !Missed +; YAML: Pass: polly-detect +; YAML: Name: Unprofitable +; YAML: DebugLoc: { File: /tmp/test.c, Line: 7, Column: 3 } +; YAML: Function: onlyRead +; YAML: Args: +; YAML: - String: No profitable polyhedral optimization found +; YAML: ... +; YAML: --- !Missed +; YAML: Pass: polly-detect +; YAML: Name: InvalidScopEnd +; YAML: DebugLoc: { File: /tmp/test.c, Line: 8, Column: 10 } +; YAML: Function: onlyRead +; YAML: Args: +; YAML: - String: Invalid Scop candidate ends here. + ; Function Attrs: nounwind uwtable define void @onlyWrite(float* %A) #0 !dbg !4 { Index: polly/trunk/test/ScopInfo/user_provided_non_dominating_assumptions.ll =================================================================== --- polly/trunk/test/ScopInfo/user_provided_non_dominating_assumptions.ll +++ polly/trunk/test/ScopInfo/user_provided_non_dominating_assumptions.ll @@ -16,6 +16,41 @@ ; } ; } ; + + +; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops \ +; RUN: -polly-precise-inbounds -disable-output < %s 2>&1 -pass-remarks-output=%t.yaml +; RUN: cat %t.yaml | FileCheck -check-prefix=YAML %s +; YAML: --- !Analysis +; YAML: Pass: polly-scops +; YAML: Name: ScopEntry +; YAML: Function: f +; YAML: Args: +; YAML: - String: SCoP begins here. +; YAML: ... +; YAML: --- !Analysis +; YAML: Pass: polly-scops +; YAML: Name: UserAssumption +; YAML: Function: f +; YAML: Args: +; YAML: - String: 'Use user assumption: ' +; YAML: - String: '[i, N, M] -> { : N <= i or (N > i and N >= 0) }' +; YAML: ... +; YAML: --- !Analysis +; YAML: Pass: polly-scops +; YAML: Name: AssumpRestrict +; YAML: Function: f +; YAML: Args: +; YAML: - String: 'Inbounds assumption: [i, N, M] -> { : N <= i or (N > i and M <= 100) }' +; YAML: ... +; YAML: --- !Analysis +; YAML: Pass: polly-scops +; YAML: Name: ScopEnd +; YAML: Function: f +; YAML: Args: +; YAML: - String: SCoP ends here. +; YAML: ... + target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" define void @f(i32* noalias %A, i32* noalias %B, i32 %i, i32 %N, i32 %M, [100 x i32]* %C) {