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
This commit is contained in:
Johannes Doerfert 2016-04-12 13:28:39 +00:00
parent 3bf6e4129f
commit 615e0b85f8
12 changed files with 53 additions and 76 deletions

View File

@ -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();

View File

@ -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);

View File

@ -99,12 +99,6 @@ static cl::opt<bool> DetectReductions("polly-detect-reductions",
cl::Hidden, cl::ZeroOrMore,
cl::init(true), cl::cat(PollyCategory));
static cl::opt<bool> 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);
}
}

View File

@ -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<bool> 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<SCEVAffinator, isl_pw_aff *>::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;
}

View File

@ -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)

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 }

View File

@ -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 }

View File

@ -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: <unknown>: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.

View File

@ -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++)