Index: polly/trunk/include/polly/ScopInfo.h =================================================================== --- polly/trunk/include/polly/ScopInfo.h +++ polly/trunk/include/polly/ScopInfo.h @@ -66,6 +66,17 @@ //===---------------------------------------------------------------------===// +/// @brief Enumeration of assumptions Polly can take. +enum AssumptionKind { + ALIASING, + INBOUNDS, + WRAPPING, + ERRORBLOCK, + INFINITELOOP, + INVARIANTLOAD, + DELINEARIZATION, +}; + /// 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. @@ -1453,6 +1464,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 @@ -1464,9 +1486,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: polly/trunk/lib/Analysis/ScopInfo.cpp =================================================================== --- polly/trunk/lib/Analysis/ScopInfo.cpp +++ polly/trunk/lib/Analysis/ScopInfo.cpp @@ -512,7 +512,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); } @@ -1175,7 +1176,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); @@ -1607,6 +1608,7 @@ isl_ctx_reset_operations(getIslCtx()); isl_ctx_set_max_operations(getIslCtx(), MaxOpsOld); BoundaryContext = isl_set_gist_params(BoundaryContext, getContext()); + trackAssumption(WRAPPING, BoundaryContext, DebugLoc()); } void Scop::addUserContext() { @@ -2181,7 +2183,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()); } } } @@ -2282,7 +2285,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) { @@ -2295,7 +2299,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 " @@ -2802,7 +2806,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; } } @@ -2820,7 +2825,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(DELINEARIZATION, isl_set_empty(getParamSpace()), + DebugLoc()); } return SAI.get(); } @@ -2882,7 +2888,42 @@ 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 DELINEARIZATION: + return "Delinearization"; + } + llvm_unreachable("Unknown AssumptionKind!"); +} + +void Scop::trackAssumption(AssumptionKind Kind, __isl_keep isl_set *Set, + DebugLoc Loc) { + 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); int NSets = isl_set_n_basic_set(AssumedContext); Index: polly/trunk/test/ScopInfo/remarks.ll =================================================================== --- polly/trunk/test/ScopInfo/remarks.ll +++ polly/trunk/test/ScopInfo/remarks.ll @@ -1,11 +1,16 @@ ; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops < %s 2>&1| FileCheck %s ; ; CHECK: remark: test/ScopInfo/remarks.c:4:7: SCoP begins here. +; CHECK: remark: test/ScopInfo/remarks.c:8:5: Finite loop assumption: [M, N, Debug] -> { : M >= 0 or (M <= -2 and N <= 0) or (M = -1 and N <= 0) } +; CHECK: remark: test/ScopInfo/remarks.c:13:7: No-error assumption: [M, N, Debug] -> { : M <= -1 or (M >= 0 and N <= 0) or (Debug = 0 and M >= 0 and N >= 1) } +; CHECK: remark: test/ScopInfo/remarks.c:9:15: Inbounds assumption: [M, N, Debug] -> { : M <= 100 or (M >= 101 and N <= 0) } +; CHECK: remark: :0:0: No-overflows assumption: [N, M, Debug] -> { : M <= 2147483647 - N and M >= -2147483648 - N } ; CHECK: remark: test/ScopInfo/remarks.c:9:18: Possibly aliasing pointer, use restrict keyword. ; CHECK: remark: test/ScopInfo/remarks.c:9:33: Possibly aliasing pointer, use restrict keyword. ; CHECK: remark: test/ScopInfo/remarks.c:9:15: Possibly aliasing pointer, use restrict keyword. ; CHECK: remark: test/ScopInfo/remarks.c:14:3: SCoP ends here. ; CHECK: remark: test/ScopInfo/remarks.c:19:3: SCoP begins here. +; CHECK: remark: test/ScopInfo/remarks.c:21:11: Invariant load assumption: [tmp] -> { : 1 = 0 } ; CHECK: remark: test/ScopInfo/remarks.c:22:16: SCoP ends here but was dismissed. ; ; #include