From 615e0b85f83f3dc030aeec617f0393d2f7c401b3 Mon Sep 17 00:00:00 2001 From: Johannes Doerfert Date: Tue, 12 Apr 2016 13:28:39 +0000 Subject: [PATCH] Record wrapping assumptions early Utilizing the record option for assumptions we can simplify the wrapping assumption generation a lot. Additionally, we can now report locations together with wrapping assumptions, though they might not be accurate yet. llvm-svn: 266069 --- polly/include/polly/ScopInfo.h | 13 ++-- polly/include/polly/Support/SCEVAffinator.h | 12 ++-- polly/lib/Analysis/ScopInfo.cpp | 27 +++----- polly/lib/Support/SCEVAffinator.cpp | 61 +++++++------------ .../test/Isl/Ast/simple-run-time-condition.ll | 2 +- .../ScopInfo/multidim_2d_with_modref_call.ll | 2 +- .../multidim_2d_with_modref_call_2.ll | 2 +- .../multidim_fortran_2d_with_modref_call.ll | 2 +- .../ScopInfo/pointer-comparison-no-nsw.ll | 2 +- polly/test/ScopInfo/pointer-comparison.ll | 2 +- polly/test/ScopInfo/remarks.ll | 2 +- polly/test/ScopInfo/wraping_signed_expr_5.ll | 2 +- 12 files changed, 53 insertions(+), 76 deletions(-) diff --git a/polly/include/polly/ScopInfo.h b/polly/include/polly/ScopInfo.h index 521aa5e9167b..78f649f2fd85 100644 --- a/polly/include/polly/ScopInfo.h +++ b/polly/include/polly/ScopInfo.h @@ -1398,6 +1398,9 @@ private: /// @brief The location that caused this assumption. DebugLoc Loc; + + /// @brief An optional block whos domain can simplify the assumption. + BasicBlock *BB; }; /// @brief Collection to hold taken assumptions. @@ -1673,9 +1676,6 @@ private: /// @brief Build the Context of the Scop. void buildContext(); - /// @brief Add the restrictions based on the wrapping of expressions. - void addWrappingContext(); - /// @brief Add user provided parameter constraints to context (source code). void addUserAssumptions(AssumptionCache &AC, DominatorTree &DT, LoopInfo &LI); @@ -1965,8 +1965,13 @@ public: /// @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. If it is + /// set, the domain of that block will be used to simplify the + /// actual assumption in @p Set once it is added. This is useful + /// if the assumption was created prior to the domain. void recordAssumption(AssumptionKind Kind, __isl_take isl_set *Set, - DebugLoc Loc, AssumptionSign Sign); + DebugLoc Loc, AssumptionSign Sign, + BasicBlock *BB = nullptr); /// @brief Add all recorded assumptions to the assumed context. void addRecordedAssumptions(); diff --git a/polly/include/polly/Support/SCEVAffinator.h b/polly/include/polly/Support/SCEVAffinator.h index e462c9510716..924cf647b718 100644 --- a/polly/include/polly/Support/SCEVAffinator.h +++ b/polly/include/polly/Support/SCEVAffinator.h @@ -96,14 +96,12 @@ private: __isl_give isl_pw_aff *addModuloSemantic(__isl_take isl_pw_aff *PWA, llvm::Type *ExprType) const; - /// @brief Compute the context in which integer wrapping for @p PWA happens. + /// @brief If @p Expr might cause an integer wrap record an assumption. /// - /// @returns The context in which integer wrapping happens or nullptr if - /// empty. - __isl_give isl_set *getWrappingContext(llvm::SCEV::NoWrapFlags Flags, - llvm::Type *ExprType, - __isl_keep isl_pw_aff *PWA, - __isl_keep isl_set *ExprDomain) const; + /// @param Expr The SCEV expression that might wrap. + /// @param PWA The isl representation of @p Expr. + void checkForWrapping(const llvm::SCEV *Expr, + __isl_keep isl_pw_aff *PWA) const; __isl_give isl_pw_aff *visit(const llvm::SCEV *E); __isl_give isl_pw_aff *visitConstant(const llvm::SCEVConstant *E); diff --git a/polly/lib/Analysis/ScopInfo.cpp b/polly/lib/Analysis/ScopInfo.cpp index 97c3804cc3fd..27c20028ceda 100644 --- a/polly/lib/Analysis/ScopInfo.cpp +++ b/polly/lib/Analysis/ScopInfo.cpp @@ -99,12 +99,6 @@ static cl::opt DetectReductions("polly-detect-reductions", cl::Hidden, cl::ZeroOrMore, cl::init(true), cl::cat(PollyCategory)); -static cl::opt IgnoreIntegerWrapping( - "polly-ignore-integer-wrapping", - cl::desc("Do not build run-time checks to proof absence of integer " - "wrapping"), - cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory)); - //===----------------------------------------------------------------------===// // Create a sequence of two schedules. Either argument may be null and is @@ -1847,14 +1841,6 @@ __isl_give isl_set *Scop::addNonEmptyDomainConstraints(isl_set *C) const { return isl_set_intersect_params(C, DomainContext); } -void Scop::addWrappingContext() { - if (IgnoreIntegerWrapping) - return; - - auto *WrappingContext = Affinator.getWrappingContext(); - addAssumption(WRAPPING, WrappingContext, DebugLoc(), AS_RESTRICTION); -} - void Scop::addUserAssumptions(AssumptionCache &AC, DominatorTree &DT, LoopInfo &LI) { auto *R = &getRegion(); @@ -3026,7 +3012,6 @@ void Scop::init(AliasAnalysis &AA, AssumptionCache &AC, ScopDetection &SD, realignParams(); addParameterBounds(); addUserContext(); - addWrappingContext(); // After the context was fully constructed, thus all our knowledge about // the parameters is in there, we add all recorded assumptions to the @@ -3506,14 +3491,20 @@ void Scop::addAssumption(AssumptionKind Kind, __isl_take isl_set *Set, } void Scop::recordAssumption(AssumptionKind Kind, __isl_take isl_set *Set, - DebugLoc Loc, AssumptionSign Sign) { - RecordedAssumptions.push_back({Kind, Sign, Set, Loc}); + DebugLoc Loc, AssumptionSign Sign, BasicBlock *BB) { + RecordedAssumptions.push_back({Kind, Sign, Set, Loc, BB}); } void Scop::addRecordedAssumptions() { while (!RecordedAssumptions.empty()) { const Assumption &AS = RecordedAssumptions.pop_back_val(); - addAssumption(AS.Kind, AS.Set, AS.Loc, AS.Sign); + + isl_set *S = AS.Set; + // If a basic block was given use its domain to simplify the assumption. + if (AS.BB) + S = isl_set_params(isl_set_intersect(S, getDomainConditions(AS.BB))); + + addAssumption(AS.Kind, S, AS.Loc, AS.Sign); } } diff --git a/polly/lib/Support/SCEVAffinator.cpp b/polly/lib/Support/SCEVAffinator.cpp index f2db2dd18eb2..72c27d2e9c67 100644 --- a/polly/lib/Support/SCEVAffinator.cpp +++ b/polly/lib/Support/SCEVAffinator.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "polly/Support/SCEVAffinator.h" +#include "polly/Options.h" #include "polly/ScopInfo.h" #include "polly/Support/GICHelper.h" #include "polly/Support/SCEVValidator.h" @@ -24,6 +25,12 @@ using namespace llvm; using namespace polly; +static cl::opt IgnoreIntegerWrapping( + "polly-ignore-integer-wrapping", + cl::desc("Do not build run-time checks to proof absence of integer " + "wrapping"), + cl::Hidden, cl::ZeroOrMore, cl::init(false), cl::cat(PollyCategory)); + // The maximal number of basic sets we allow during the construction of a // piecewise affine function. More complex ones will result in very high // compile time. @@ -84,10 +91,8 @@ __isl_give isl_pw_aff *SCEVAffinator::getPwAff(const SCEV *Expr, return visit(Expr); } -__isl_give isl_set * -SCEVAffinator::getWrappingContext(SCEV::NoWrapFlags Flags, Type *ExprType, - __isl_keep isl_pw_aff *PWA, - __isl_take isl_set *ExprDomain) const { +void SCEVAffinator::checkForWrapping(const SCEV *Expr, + __isl_keep isl_pw_aff *PWA) const { // If the SCEV flags do contain NSW (no signed wrap) then PWA already // represents Expr in modulo semantic (it is not allowed to overflow), thus we // are done. Otherwise, we will compute: @@ -95,44 +100,19 @@ SCEVAffinator::getWrappingContext(SCEV::NoWrapFlags Flags, Type *ExprType, // whereas n is the number of bits of the Expr, hence: // n = bitwidth(ExprType) - if (Flags & SCEV::FlagNSW) - return nullptr; + if (IgnoreIntegerWrapping || (getNoWrapFlags(Expr) & SCEV::FlagNSW)) + return; - isl_pw_aff *PWAMod = addModuloSemantic(isl_pw_aff_copy(PWA), ExprType); - if (isl_pw_aff_is_equal(PWA, PWAMod)) { - isl_pw_aff_free(PWAMod); - return nullptr; - } + auto *PWAMod = addModuloSemantic(isl_pw_aff_copy(PWA), Expr->getType()); + auto *NotEqualSet = isl_pw_aff_ne_set(isl_pw_aff_copy(PWA), PWAMod); - PWA = isl_pw_aff_copy(PWA); + const DebugLoc &Loc = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc(); + NotEqualSet = BB ? NotEqualSet : isl_set_params(NotEqualSet); - auto *NotEqualSet = isl_pw_aff_ne_set(PWA, PWAMod); - NotEqualSet = isl_set_intersect(NotEqualSet, isl_set_copy(ExprDomain)); - NotEqualSet = isl_set_gist_params(NotEqualSet, S->getContext()); - NotEqualSet = isl_set_params(NotEqualSet); - return NotEqualSet; -} - -__isl_give isl_set *SCEVAffinator::getWrappingContext() const { - - isl_set *WrappingCtx = isl_set_empty(S->getParamSpace()); - - for (const auto &CachedPair : CachedExpressions) { - const SCEV *Expr = CachedPair.first.first; - SCEV::NoWrapFlags Flags = getNoWrapFlags(Expr); - - isl_pw_aff *PWA = CachedPair.second; - BasicBlock *BB = CachedPair.first.second; - isl_set *ExprDomain = BB ? S->getDomainConditions(BB) : nullptr; - - isl_set *WPWACtx = - getWrappingContext(Flags, Expr->getType(), PWA, ExprDomain); - isl_set_free(ExprDomain); - - WrappingCtx = WPWACtx ? isl_set_union(WrappingCtx, WPWACtx) : WrappingCtx; - } - - return WrappingCtx; + if (isl_set_is_empty(NotEqualSet)) + isl_set_free(NotEqualSet); + else + S->recordAssumption(WRAPPING, NotEqualSet, Loc, AS_RESTRICTION, BB); } __isl_give isl_pw_aff * @@ -198,6 +178,7 @@ __isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) { PWA = isl_pw_aff_alloc(Domain, Affine); } else { PWA = SCEVVisitor::visit(Expr); + checkForWrapping(Expr, PWA); } PWA = isl_pw_aff_mul(visitConstant(Factor), PWA); @@ -205,6 +186,8 @@ __isl_give isl_pw_aff *SCEVAffinator::visit(const SCEV *Expr) { // For compile time reasons we need to simplify the PWA before we cache and // return it. PWA = isl_pw_aff_coalesce(PWA); + checkForWrapping(Key.first, PWA); + CachedExpressions[Key] = isl_pw_aff_copy(PWA); return PWA; } diff --git a/polly/test/Isl/Ast/simple-run-time-condition.ll b/polly/test/Isl/Ast/simple-run-time-condition.ll index 46b929266af5..ed48c4128a14 100644 --- a/polly/test/Isl/Ast/simple-run-time-condition.ll +++ b/polly/test/Isl/Ast/simple-run-time-condition.ll @@ -17,7 +17,7 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3 ; for the delinearization is simplified such that conditions that would not ; cause any code to be executed are not generated. -; CHECK: if (((o >= 1 && q <= 0 && m + q >= 0) || (o <= 0 && m + q >= 100 && q <= 100)) && 0 == ((m >= 1 && n + p >= 9223372036854775809) || (o <= 0 && n >= 1 && m + q >= 9223372036854775909) || (o <= 0 && m >= 1 && n >= 1 && q <= -9223372036854775709))) +; CHECK: if (((o >= 1 && q <= 0 && m + q >= 0) || (o <= 0 && m + q >= 100 && q <= 100)) && 0 == ((o <= 0 && n >= 1 && m + q >= 9223372036854775909) || (m >= 1 && n + p >= 9223372036854775809) || (o <= 0 && m >= 1 && n >= 1 && q <= -9223372036854775709))) ; CHECK: if (o <= 0) { ; CHECK: for (int c0 = 0; c0 < n; c0 += 1) diff --git a/polly/test/ScopInfo/multidim_2d_with_modref_call.ll b/polly/test/ScopInfo/multidim_2d_with_modref_call.ll index d8b720da0600..457250eaea3e 100644 --- a/polly/test/ScopInfo/multidim_2d_with_modref_call.ll +++ b/polly/test/ScopInfo/multidim_2d_with_modref_call.ll @@ -19,7 +19,7 @@ ; CHECK-NEXT: Assumed Context: ; CHECK-NEXT: [tmp14, p_1] -> { : } ; CHECK-NEXT: Invalid Context: -; CHECK-NEXT: [tmp14, p_1] -> { : tmp14 > 0 and (tmp14 >= 1152921504606846977 or p_1 <= -1152921504606846977 or p_1 >= 1152921504606846977 - tmp14) +; CHECK-NEXT: [tmp14, p_1] -> { : tmp14 > 0 and (p_1 <= -1152921504606846977 or tmp14 >= 1152921504606846977 or p_1 >= 1152921504606846977 - tmp14) } ; CHECK-NEXT: p0: %tmp14 ; CHECK-NEXT: p1: {0,+,(0 smax %tmp)}<%bb12> ; CHECK-NEXT: Arrays { diff --git a/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll b/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll index 133de691628b..609d74639cd0 100644 --- a/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll +++ b/polly/test/ScopInfo/multidim_2d_with_modref_call_2.ll @@ -19,7 +19,7 @@ ; CHECK-NEXT: Assumed Context: ; CHECK-NEXT: [tmp14, p_1] -> { : } ; CHECK-NEXT: Invalid Context: -; CHECK-NEXT: [tmp14, p_1] -> { : tmp14 > 0 and (tmp14 >= 1152921504606846977 or p_1 <= -1152921504606846977 or p_1 >= 1152921504606846977 - tmp14) } +; CHECK-NEXT: [tmp14, p_1] -> { : tmp14 > 0 and (p_1 <= -1152921504606846977 or tmp14 >= 1152921504606846977 or p_1 >= 1152921504606846977 - tmp14) } ; CHECK-NEXT: p0: %tmp14 ; CHECK-NEXT: p1: {0,+,(0 smax %tmp)}<%bb12> ; CHECK-NEXT: Arrays { diff --git a/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll b/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll index 7e87427b1b4a..3f2257a2540f 100644 --- a/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll +++ b/polly/test/ScopInfo/multidim_fortran_2d_with_modref_call.ll @@ -19,7 +19,7 @@ ; CHECK-NEXT: Assumed Context: ; CHECK-NEXT: [tmp14, p_1] -> { : } ; CHECK-NEXT: Invalid Context: -; CHECK-NEXT: [tmp14, p_1] -> { : tmp14 > 0 and (tmp14 >= 1152921504606846977 or p_1 <= -1152921504606846977 or p_1 >= 1152921504606846977 - tmp14) } +; CHECK-NEXT: [tmp14, p_1] -> { : tmp14 > 0 and (p_1 <= -1152921504606846977 or tmp14 >= 1152921504606846977 or p_1 >= 1152921504606846977 - tmp14) } ; CHECK-NEXT: p0: %tmp14 ; CHECK-NEXT: p1: {0,+,(0 smax %tmp)}<%bb12> ; CHECK-NEXT: Arrays { diff --git a/polly/test/ScopInfo/pointer-comparison-no-nsw.ll b/polly/test/ScopInfo/pointer-comparison-no-nsw.ll index d51148567e7f..473eb60c96b6 100644 --- a/polly/test/ScopInfo/pointer-comparison-no-nsw.ll +++ b/polly/test/ScopInfo/pointer-comparison-no-nsw.ll @@ -8,7 +8,7 @@ ; } ; ; CHECK: Invalid Context: -; CHECK-NEXT: [A, B] -> { : (4*floor((-A + B)/4) = -A + B and B >= 9223372036854775808 + A) or (4*floor((A - B)/4) < A - B) or (4*floor((-A + B)/4) = -A + B and B <= -4 + A) } +; CHECK-NEXT: [A, B] -> { : (4*floor((A - B)/4) < A - B) or (4*floor((-A + B)/4) = -A + B and B >= 9223372036854775808 + A) or (4*floor((-A + B)/4) = -A + B and B <= -4 + A) } ; ; CHECK: Domain := ; CHECK-NEXT: [A, B] -> { Stmt_while_body[i0] : 4*floor((A - B)/4) = A - B and B >= A and i0 >= 0 and 4i0 < -A + B } diff --git a/polly/test/ScopInfo/pointer-comparison.ll b/polly/test/ScopInfo/pointer-comparison.ll index 6069048524e6..14b41509d211 100644 --- a/polly/test/ScopInfo/pointer-comparison.ll +++ b/polly/test/ScopInfo/pointer-comparison.ll @@ -10,7 +10,7 @@ ; } ; ; CHECK: Invalid Context: -; CHECK-NEXT: [A, B] -> { : (4*floor((-A + B)/4) = -A + B and B >= 9223372036854775808 + A) or (4*floor((A - B)/4) < A - B) or (4*floor((-A + B)/4) = -A + B and B <= -4 + A) } +; CHECK-NEXT: [A, B] -> { : (4*floor((A - B)/4) < A - B) or (4*floor((-A + B)/4) = -A + B and B >= 9223372036854775808 + A) or (4*floor((-A + B)/4) = -A + B and B <= -4 + A) } ; ; CHECK: Domain := ; CHECK-NEXT: [A, B] -> { Stmt_while_body[i0] : 4*floor((A - B)/4) = A - B and B >= A and i0 >= 0 and 4i0 < -A + B } diff --git a/polly/test/ScopInfo/remarks.ll b/polly/test/ScopInfo/remarks.ll index b45bdf892737..d1cbff23f449 100644 --- a/polly/test/ScopInfo/remarks.ll +++ b/polly/test/ScopInfo/remarks.ll @@ -1,10 +1,10 @@ ; RUN: opt %loadPolly -pass-remarks-analysis="polly-scops" -polly-scops -disable-output < %s 2>&1 | FileCheck %s ; ; CHECK: remark: test/ScopInfo/remarks.c:4:7: SCoP begins here. -; CHECK: remark: :0:0: No-overflows restriction: [N, M, Debug] -> { : M <= -2147483649 - N or M >= 2147483648 - N } ; CHECK: remark: test/ScopInfo/remarks.c:9:15: Inbounds assumption: [N, M, Debug] -> { : N <= 0 or (N > 0 and M <= 100) } ; CHECK: remark: test/ScopInfo/remarks.c:13:7: No-error restriction: [N, M, Debug] -> { : N > 0 and M >= 0 and (Debug < 0 or Debug > 0) } ; CHECK: remark: test/ScopInfo/remarks.c:8:5: Finite loop restriction: [N, M, Debug] -> { : N > 0 and (M <= -2 or M = -1) } +; CHECK: remark: test/ScopInfo/remarks.c:4:7: No-overflows restriction: [N, M, Debug] -> { : M <= -2147483649 - N or 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. diff --git a/polly/test/ScopInfo/wraping_signed_expr_5.ll b/polly/test/ScopInfo/wraping_signed_expr_5.ll index 0e2f746d1f76..ab2f71d60a2a 100644 --- a/polly/test/ScopInfo/wraping_signed_expr_5.ll +++ b/polly/test/ScopInfo/wraping_signed_expr_5.ll @@ -4,7 +4,7 @@ ; to overflow. However (p + q) can, thus checks are needed. ; ; CHECK: Invalid Context: -; CHECK-NEXT: [r1, r2, q, p] -> { : r2 > r1 and (r2 >= 128 + r1 or p <= -2147483649 - q or p >= 2147483648 - q) } +; CHECK-NEXT: [r1, r2, q, p] -> { : r2 > r1 and (p <= -2147483649 - q or r2 >= 128 + r1 or p >= 2147483648 - q) } ; ; void wraps(int *A, int p, short q, char r1, char r2) { ; for (char i = r1; i < r2; i++)