Index: include/polly/ScopDetectionDiagnostic.h =================================================================== --- include/polly/ScopDetectionDiagnostic.h +++ include/polly/ScopDetectionDiagnostic.h @@ -43,6 +43,9 @@ namespace polly { +/// @brief Set the begin and end source location for the given region @p R. +void getDebugLocations(const Region *R, DebugLoc &Begin, DebugLoc &End); + class RejectLog; /// @brief Emit optimization remarks about the rejected regions to the user. /// Index: include/polly/ScopInfo.h =================================================================== --- include/polly/ScopInfo.h +++ include/polly/ScopInfo.h @@ -66,6 +66,17 @@ //===---------------------------------------------------------------------===// +/// @brief Enumeration of assumptions Polly can take. +enum AssumptionKind { + ALIASING, + INBOUNDS, + WRAPPING, + ERRORBLOCK, + INFINITELOOP, + INVARIANTLOAD, + DELINIARIZATION, +}; + /// Maps from a loop to the affine function expressing its backedge taken count. /// The backedge taken count already enough to express iteration domain as we /// only allow loops with canonical induction variable. @@ -1428,6 +1439,17 @@ /// @returns True if the optimized SCoP can be executed. bool hasFeasibleRuntimeContext() const; + /// @brief Track and report an assumption. + /// + /// Use 'clang -Rpass-analysis=polly-scops' or 'opt -pass-remarks=polly-scops' + /// to output the assumptions. + /// + /// @param Kind The assumption kind describing the underlying cause. + /// @param Set The relations between parameters that are assumed to hold. + /// @param Loc The location in the source that caused this assumption. + void trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set, + DebugLoc Loc); + /// @brief Add assumptions to assumed context. /// /// The assumptions added will be assumed to hold during the execution of the @@ -1439,9 +1461,11 @@ /// that assumptions do not change the set of statement instances /// executed. /// - /// @param Set A set describing relations between parameters that are assumed - /// to hold. - void addAssumption(__isl_take isl_set *Set); + /// @param Kind The assumption kind describing the underlying cause. + /// @param Set The relations between parameters that are assumed to hold. + /// @param Loc The location in the source that caused this assumption. + void addAssumption(AssumptionKind Kind, __isl_take isl_set *Set, + DebugLoc Loc); /// @brief Get the boundary context for this Scop. /// Index: lib/Analysis/ScopDetectionDiagnostic.cpp =================================================================== --- lib/Analysis/ScopDetectionDiagnostic.cpp +++ lib/Analysis/ScopDetectionDiagnostic.cpp @@ -68,7 +68,7 @@ } namespace polly { -static void getDebugLocations(const Region *R, DebugLoc &Begin, DebugLoc &End) { +void getDebugLocations(const Region *R, DebugLoc &Begin, DebugLoc &End) { for (const BasicBlock *BB : R->blocks()) for (const Instruction &Inst : *BB) { DebugLoc DL = Inst.getDebugLoc(); Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -34,6 +34,7 @@ #include "llvm/Analysis/LoopIterator.h" #include "llvm/Analysis/RegionIterator.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/Support/Debug.h" #include "isl/aff.h" #include "isl/constraint.h" @@ -91,6 +92,14 @@ cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::cat(PollyCategory)); +static cl::opt + TrackAssumptions("polly-track-assumptions", + cl::desc("Track optimistic assumptions and emit them via " + "'clang -Rpass-analysis=polly-scops' or 'opt " + "-pass-remarks=polly-scops'."), + cl::Hidden, cl::ZeroOrMore, cl::init(true), + cl::cat(PollyCategory)); + //===----------------------------------------------------------------------===// // Create a sequence of two schedules. Either argument may be null and is @@ -496,7 +505,8 @@ // bail out more often than strictly necessary. Outside = isl_set_remove_divs(Outside); Outside = isl_set_complement(Outside); - Statement->getParent()->addAssumption(Outside); + Statement->getParent()->addAssumption(INBOUNDS, Outside, + getAccessInstruction()->getDebugLoc()); isl_space_free(Space); } @@ -1147,7 +1157,7 @@ isl_set *InBoundIfExecuted = isl_set_union(isl_set_complement(Executed), InBound); - Parent.addAssumption(InBoundIfExecuted); + Parent.addAssumption(INBOUNDS, InBoundIfExecuted, GEP->getDebugLoc()); } isl_local_space_free(LSpace); @@ -1559,6 +1569,7 @@ BoundaryContext = Affinator.getWrappingContext(); BoundaryContext = isl_set_complement(BoundaryContext); BoundaryContext = isl_set_gist_params(BoundaryContext, getContext()); + trackAssumption(WRAPPING, BoundaryContext, DebugLoc()); } void Scop::addUserContext() { @@ -2125,7 +2136,8 @@ if (containsErrorBlock(RN, getRegion(), LI, DT)) { IsOptimized = true; isl_set *DomPar = isl_set_params(isl_set_copy(Domain)); - addAssumption(isl_set_complement(DomPar)); + addAssumption(ERRORBLOCK, isl_set_complement(DomPar), + BB->getTerminator()->getDebugLoc()); } } } @@ -2226,7 +2238,8 @@ isl_set *UnboundedCtx = isl_set_params(Parts.first); isl_set *BoundedCtx = isl_set_complement(UnboundedCtx); - addAssumption(BoundedCtx); + addAssumption(INFINITELOOP, BoundedCtx, + HeaderBB->getTerminator()->getDebugLoc()); } void Scop::buildAliasChecks(AliasAnalysis &AA) { @@ -2239,7 +2252,7 @@ // If a problem occurs while building the alias groups we need to delete // this SCoP and pretend it wasn't valid in the first place. To this end // we make the assumed context infeasible. - addAssumption(isl_set_empty(getParamSpace())); + addAssumption(ALIASING, isl_set_empty(getParamSpace()), DebugLoc()); DEBUG(dbgs() << "\n\nNOTE: Run time checks for " << getNameStr() << " could not be created as the number of parameters involved " @@ -2325,6 +2338,7 @@ isl_set_free(AGDomain); } + auto &F = *getRegion().getEntry()->getParent(); MapVector> ReadOnlyPairs; SmallPtrSet NonReadOnlyBaseValues; for (AliasGroupTy &AG : AliasGroups) { @@ -2337,6 +2351,11 @@ } for (auto II = AG.begin(); II != AG.end();) { + emitOptimizationRemarkAnalysis( + F.getContext(), DEBUG_TYPE, F, + (*II)->getAccessInstruction()->getDebugLoc(), + "Possible aliasing pointer, use restrict keyword."); + Value *BaseAddr = (*II)->getBaseAddr(); if (HasWriteAccess.count(BaseAddr)) { NonReadOnlyBaseValues.insert(BaseAddr); @@ -2732,7 +2751,8 @@ << ") is required to be invariant but was not marked as " "such. SCoP for " << getRegion() << " will be dropped\n\n"); - addAssumption(isl_set_empty(getParamSpace())); + addAssumption(INVARIANTLOAD, isl_set_empty(getParamSpace()), + LI->getDebugLoc()); return; } } @@ -2749,7 +2769,8 @@ // In case of mismatching array sizes, we bail out by setting the run-time // context to false. if (!SAI->updateSizes(Sizes)) - addAssumption(isl_set_empty(getParamSpace())); + addAssumption(DELINIARIZATION, isl_set_empty(getParamSpace()), + DebugLoc()); } return SAI.get(); } @@ -2810,7 +2831,45 @@ return IsFeasible; } -void Scop::addAssumption(__isl_take isl_set *Set) { +static std::string toString(AssumptionKind Kind) { + switch (Kind) { + case ALIASING: + return "No-aliasing"; + case INBOUNDS: + return "Inbounds"; + case WRAPPING: + return "No-overflows"; + case ERRORBLOCK: + return "No-error"; + case INFINITELOOP: + return "Finite loop"; + case INVARIANTLOAD: + return "Invariant load"; + case DELINIARIZATION: + return "Delinearization"; + } + llvm_unreachable("Unknown AssumptionKind!"); +} + +void Scop::trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set, + DebugLoc Loc) { + if (!TrackAssumptions) + return; + + if (isl_set_is_subset(Context, Set)) + return; + + if (isl_set_is_subset(AssumedContext, Set)) + return; + + auto &F = *getRegion().getEntry()->getParent(); + std::string Msg = toString(Kind) + " assumption:\t" + stringFromIslObj(Set); + emitOptimizationRemarkAnalysis(F.getContext(), DEBUG_TYPE, F, Loc, Msg); +} + +void Scop::addAssumption(AssumptionKind Kind, __isl_take isl_set *Set, + DebugLoc Loc) { + trackAssumption(Kind, Set, Loc); AssumedContext = isl_set_intersect(AssumedContext, Set); AssumedContext = isl_set_coalesce(AssumedContext); } @@ -3765,8 +3824,16 @@ TD = &F->getParent()->getDataLayout(); DominatorTree &DT = getAnalysis().getDomTree(); + DebugLoc Beg, End; + getDebugLocations(R, Beg, End); + emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, Beg, + "SCoP begins here."); + buildScop(*R, DT); + emitOptimizationRemarkAnalysis(F->getContext(), DEBUG_TYPE, *F, End, + "SCoP ends here."); + DEBUG(scop->print(dbgs())); if (scop->isEmpty() || !scop->hasFeasibleRuntimeContext()) {