// The Scop
std::unique_ptr<Scop> scop;
+ /// Collection to hold taken assumptions.
+ ///
+ /// There are two reasons why we want to record assumptions first before we
+ /// add them to the assumed/invalid context:
+ /// 1) If the SCoP is not profitable or otherwise invalid without the
+ /// assumed/invalid context we do not have to compute it.
+ /// 2) Information about the context are gathered rather late in the SCoP
+ /// construction (basically after we know all parameters), thus the user
+ /// might see overly complicated assumptions to be taken while they will
+ /// only be simplified later on.
+ RecordedAssumptionsTy RecordedAssumptions;
+
// Methods for pattern matching against Fortran code generated by dragonegg.
// @{
#include "polly/ScopDetection.h"
#include "polly/Support/SCEVAffinator.h"
+#include "polly/Support/ScopHelper.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
// are also unlikely to result in good code.
extern int const MaxDisjunctsInDomain;
-/// Enumeration of assumptions Polly can take.
-enum AssumptionKind {
- ALIASING,
- INBOUNDS,
- WRAPPING,
- UNSIGNED,
- PROFITABLE,
- ERRORBLOCK,
- COMPLEXITY,
- INFINITELOOP,
- INVARIANTLOAD,
- DELINEARIZATION,
-};
-
-/// Enum to distinguish between assumptions and restrictions.
-enum AssumptionSign { AS_ASSUMPTION, AS_RESTRICTION };
-
/// The different memory kinds used in Polly.
///
/// We distinguish between arrays and various scalar memory objects. We use
RT_BAND, ///< Bitwise And
};
+ using SubscriptsTy = SmallVector<const SCEV *, 4>;
+
private:
/// A unique identifier for this memory access.
///
bool IsAffine = true;
/// Subscript expression for each dimension.
- SmallVector<const SCEV *, 4> Subscripts;
+ SubscriptsTy Subscripts;
/// Relation from statement instances to the accessed array elements.
///
isl::basic_map createBasicAccessMap(ScopStmt *Statement);
- void assumeNoOutOfBound();
+ isl::set assumeNoOutOfBound();
/// Compute bounds on an over approximated access relation.
///
/// Return the access instruction of this memory access.
Instruction *getAccessInstruction() const { return AccessInstruction; }
+ /// Return an iterator range containing the subscripts.
+ iterator_range<SubscriptsTy::const_iterator> subscripts() const {
+ return make_range(Subscripts.begin(), Subscripts.end());
+ }
+
/// Return the number of access function subscript.
unsigned getNumSubscripts() const { return Subscripts.size(); }
/// Print ScopStmt S to raw_ostream OS.
raw_ostream &operator<<(raw_ostream &OS, const ScopStmt &S);
-/// Helper struct to remember assumptions.
-struct Assumption {
- /// The kind of the assumption (e.g., WRAPPING).
- AssumptionKind Kind;
-
- /// Flag to distinguish assumptions and restrictions.
- AssumptionSign Sign;
-
- /// The valid/invalid context if this is an assumption/restriction.
- isl::set Set;
-
- /// The location that caused this assumption.
- DebugLoc Loc;
-
- /// An optional block whose domain can simplify the assumption.
- BasicBlock *BB;
-};
-
/// Build the conditions sets for the branch condition @p Condition in
/// the @p Domain.
///
/// need to be "false". Otherwise they behave the same.
isl::set InvalidContext;
- using RecordedAssumptionsTy = SmallVector<Assumption, 8>;
- /// Collection to hold taken assumptions.
- ///
- /// There are two reasons why we want to record assumptions first before we
- /// add them to the assumed/invalid context:
- /// 1) If the SCoP is not profitable or otherwise invalid without the
- /// assumed/invalid context we do not have to compute it.
- /// 2) Information about the context are gathered rather late in the SCoP
- /// construction (basically after we know all parameters), thus the user
- /// might see overly complicated assumptions to be taken while they will
- /// only be simplified later on.
- RecordedAssumptionsTy RecordedAssumptions;
-
/// The schedule of the SCoP
///
/// The schedule of the SCoP describes the execution order of the statements
InvariantEquivClasses.end());
}
- /// Return an iterator range containing hold assumptions.
- iterator_range<RecordedAssumptionsTy::const_iterator>
- recorded_assumptions() const {
- return make_range(RecordedAssumptions.begin(), RecordedAssumptions.end());
- }
-
/// Return an iterator range containing all the MemoryAccess objects of the
/// Scop.
iterator_range<AccFuncVector::iterator> access_functions() {
/// @returns True if the optimized SCoP can be executed.
bool hasFeasibleRuntimeContext() const;
- /// Clear assumptions which have been already processed.
- void clearRecordedAssumptions() { return RecordedAssumptions.clear(); }
-
/// Check if the assumption in @p Set is trivial or not.
///
/// @param Set The relations between parameters that are assumed to hold.
void addAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
AssumptionSign Sign, BasicBlock *BB);
- /// Record an assumption for later addition to the assumed context.
- ///
- /// This function will add the assumption to the RecordedAssumptions. This
- /// collection will be added (@see addAssumption) to the assumed context once
- /// all paramaters are known and the context is fully built.
- ///
- /// @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.
- /// @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::set Set, DebugLoc Loc,
- AssumptionSign Sign, BasicBlock *BB = nullptr);
-
/// Mark the scop as invalid.
///
/// This method adds an assumption to the scop that is always invalid. As a
///
/// @returns The ScopArrayInfo pointer or NULL if no such pointer is
/// available.
- const ScopArrayInfo *getScopArrayInfoOrNull(Value *BasePtr, MemoryKind Kind);
+ ScopArrayInfo *getScopArrayInfoOrNull(Value *BasePtr, MemoryKind Kind);
/// Return the cached ScopArrayInfo object for @p BasePtr.
///
///
/// @returns The ScopArrayInfo pointer (may assert if no such pointer is
/// available).
- const ScopArrayInfo *getScopArrayInfo(Value *BasePtr, MemoryKind Kind);
+ ScopArrayInfo *getScopArrayInfo(Value *BasePtr, MemoryKind Kind);
/// Invalidate ScopArrayInfo object for base address.
///
/// a dummy value of appropriate dimension is returned. This allows to bail
/// for complex cases without "error handling code" needed on the users side.
PWACtx getPwAff(const SCEV *E, BasicBlock *BB = nullptr,
- bool NonNegative = false);
+ bool NonNegative = false,
+ RecordedAssumptionsTy *RecordedAssumptions = nullptr);
/// Compute the isl representation for the SCEV @p E
///
/// This function is like @see Scop::getPwAff() but strips away the invalid
/// domain part associated with the piecewise affine function.
- isl::pw_aff getPwAffOnly(const SCEV *E, BasicBlock *BB = nullptr);
+ isl::pw_aff
+ getPwAffOnly(const SCEV *E, BasicBlock *BB = nullptr,
+ RecordedAssumptionsTy *RecordedAssumptions = nullptr);
/// Check if an <nsw> AddRec for the loop L is cached.
bool hasNSWAddRecForLoop(Loop *L) { return Affinator.hasNSWAddRecForLoop(L); }
#ifndef POLLY_SCEV_AFFINATOR_H
#define POLLY_SCEV_AFFINATOR_H
+#include "polly/Support/ScopHelper.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "isl/isl-noexceptions.h"
/// @param BB The block in which @p E is executed.
///
/// @returns The isl representation of the SCEV @p E in @p Domain.
- PWACtx getPwAff(const llvm::SCEV *E, llvm::BasicBlock *BB = nullptr);
+ PWACtx getPwAff(const llvm::SCEV *E, llvm::BasicBlock *BB = nullptr,
+ RecordedAssumptionsTy *RecordedAssumptions = nullptr);
/// Take the assumption that @p PWAC is non-negative.
- void takeNonNegativeAssumption(PWACtx &PWAC);
+ void takeNonNegativeAssumption(
+ PWACtx &PWAC, RecordedAssumptionsTy *RecordedAssumptions = nullptr);
/// Interpret the PWA in @p PWAC as an unsigned value.
void interpretAsUnsigned(PWACtx &PWAC, unsigned Width);
llvm::ScalarEvolution &SE;
llvm::LoopInfo &LI;
llvm::BasicBlock *BB;
+ RecordedAssumptionsTy *RecordedAssumptions = nullptr;
/// Target data for element size computing.
const llvm::DataLayout &TD;
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/ValueHandle.h"
+#include "isl/isl-noexceptions.h"
namespace llvm {
class LoopInfo;
class Scop;
class ScopStmt;
+/// Enumeration of assumptions Polly can take.
+enum AssumptionKind {
+ ALIASING,
+ INBOUNDS,
+ WRAPPING,
+ UNSIGNED,
+ PROFITABLE,
+ ERRORBLOCK,
+ COMPLEXITY,
+ INFINITELOOP,
+ INVARIANTLOAD,
+ DELINEARIZATION,
+};
+
+/// Enum to distinguish between assumptions and restrictions.
+enum AssumptionSign { AS_ASSUMPTION, AS_RESTRICTION };
+
+/// Helper struct to remember assumptions.
+struct Assumption {
+ /// The kind of the assumption (e.g., WRAPPING).
+ AssumptionKind Kind;
+
+ /// Flag to distinguish assumptions and restrictions.
+ AssumptionSign Sign;
+
+ /// The valid/invalid context if this is an assumption/restriction.
+ isl::set Set;
+
+ /// The location that caused this assumption.
+ llvm::DebugLoc Loc;
+
+ /// An optional block whose domain can simplify the assumption.
+ llvm::BasicBlock *BB;
+};
+
+using RecordedAssumptionsTy = llvm::SmallVector<Assumption, 8>;
+
+/// Record an assumption for later addition to the assumed context.
+///
+/// This function will add the assumption to the RecordedAssumptions. This
+/// collection will be added (@see addAssumption) to the assumed context once
+/// all paramaters are known and the context is fully built.
+///
+/// @param RecordedAssumption container which keeps all recorded 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.
+/// @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(RecordedAssumptionsTy *RecordedAssumptions,
+ AssumptionKind Kind, isl::set Set, llvm::DebugLoc Loc,
+ AssumptionSign Sign, llvm::BasicBlock *BB = nullptr);
+
/// Type to remap values.
using ValueMapT = llvm::DenseMap<llvm::AssertingVH<llvm::Value>,
llvm::AssertingVH<llvm::Value>>;
" their loads. "),
cl::Hidden, cl::init(false), cl::cat(PollyCategory));
+static cl::opt<bool>
+ PollyIgnoreInbounds("polly-ignore-inbounds",
+ cl::desc("Do not take inbounds assumptions at all"),
+ cl::Hidden, cl::init(false), cl::cat(PollyCategory));
+
static cl::opt<unsigned> RunTimeChecksMaxArraysPerGroup(
"polly-rtc-max-arrays-per-group",
cl::desc("The maximal number of arrays to compare in each alias group."),
ScopBuilder::getPwAff(BasicBlock *BB,
DenseMap<BasicBlock *, isl::set> &InvalidDomainMap,
const SCEV *E, bool NonNegative) {
- PWACtx PWAC = scop->getPwAff(E, BB, NonNegative);
+ PWACtx PWAC = scop->getPwAff(E, BB, NonNegative, &RecordedAssumptions);
InvalidDomainMap[BB] = InvalidDomainMap[BB].unite(PWAC.second);
return PWAC.first.release();
}
return true;
isl::set UnboundedCtx = Parts.first.params();
- scop->recordAssumption(INFINITELOOP, UnboundedCtx,
- HeaderBB->getTerminator()->getDebugLoc(),
- AS_RESTRICTION);
+ recordAssumption(&RecordedAssumptions, INFINITELOOP, UnboundedCtx,
+ HeaderBB->getTerminator()->getDebugLoc(), AS_RESTRICTION);
return true;
}
} else {
InvalidDomain = Domain;
isl::set DomPar = Domain.params();
- scop->recordAssumption(ERRORBLOCK, DomPar,
- BB->getTerminator()->getDebugLoc(),
- AS_RESTRICTION);
+ recordAssumption(&RecordedAssumptions, ERRORBLOCK, DomPar,
+ BB->getTerminator()->getDebugLoc(), AS_RESTRICTION);
Domain = isl::set::empty(Domain.get_space());
}
}
void ScopBuilder::addRecordedAssumptions() {
- for (auto &AS : llvm::reverse(scop->recorded_assumptions())) {
+ for (auto &AS : llvm::reverse(RecordedAssumptions)) {
if (!AS.BB) {
scop->addAssumption(AS.Kind, AS.Set, AS.Loc, AS.Sign,
scop->addAssumption(AS.Kind, isl::manage(S), AS.Loc, AS_RESTRICTION, AS.BB);
}
- scop->clearRecordedAssumptions();
}
void ScopBuilder::addUserAssumptions(
}
void ScopBuilder::assumeNoOutOfBounds() {
+ if (PollyIgnoreInbounds)
+ return;
for (auto &Stmt : *scop)
- for (auto &Access : Stmt)
- Access->assumeNoOutOfBound();
+ for (auto &Access : Stmt) {
+ isl::set Outside = Access->assumeNoOutOfBound();
+ const auto &Loc = Access->getAccessInstruction()
+ ? Access->getAccessInstruction()->getDebugLoc()
+ : DebugLoc();
+ recordAssumption(&RecordedAssumptions, INBOUNDS, Outside, Loc,
+ AS_ASSUMPTION);
+ }
}
void ScopBuilder::ensureValueWrite(Instruction *Inst) {
// Even if the statement is not modeled precisely we can hoist the load if it
// does not involve any parameters that might have been specialized by the
// statement domain.
- for (unsigned u = 0, e = MA->getNumSubscripts(); u < e; u++)
- if (!isa<SCEVConstant>(MA->getSubscript(u)))
+ for (const SCEV *Subscript : MA->subscripts())
+ if (!isa<SCEVConstant>(Subscript))
return false;
return true;
}
else
Ty = MemoryKind::Array;
+ // Create isl::pw_aff for SCEVs which describe sizes. Collect all
+ // assumptions which are taken. isl::pw_aff objects are cached internally
+ // and they are used later by scop.
+ for (const SCEV *Size : Access->Sizes) {
+ if (!Size)
+ continue;
+ scop->getPwAff(Size, nullptr, false, &RecordedAssumptions);
+ }
auto *SAI = scop->getOrCreateScopArrayInfo(Access->getOriginalBaseAddr(),
ElementType, Access->Sizes, Ty);
+
+ // Create isl::pw_aff for SCEVs which describe subscripts. Collect all
+ // assumptions which are taken. isl::pw_aff objects are cached internally
+ // and they are used later by scop.
+ for (const SCEV *Subscript : Access->subscripts()) {
+ if (!Access->isAffine() || !Subscript)
+ continue;
+ scop->getPwAff(Subscript, Stmt.getEntryBlock(), false,
+ &RecordedAssumptions);
+ }
Access->buildAccessRelation(SAI);
scop->addAccessData(Access);
}
InfeasibleScops++;
Msg = "SCoP ends here but was dismissed.";
LLVM_DEBUG(dbgs() << "SCoP detected but dismissed\n");
+ RecordedAssumptions.clear();
scop.reset();
} else {
Msg = "SCoP ends here.";
cl::desc("Take more precise inbounds assumptions (do not scale well)"),
cl::Hidden, cl::init(false), cl::cat(PollyCategory));
-static cl::opt<bool>
- PollyIgnoreInbounds("polly-ignore-inbounds",
- cl::desc("Do not take inbounds assumptions at all"),
- cl::Hidden, cl::init(false), cl::cat(PollyCategory));
-
static cl::opt<bool> PollyIgnoreParamBounds(
"polly-ignore-parameter-bounds",
cl::desc(
// possibly yield out of bound memory accesses. The complement of these
// constraints is the set of constraints that needs to be assumed to ensure such
// statement instances are never executed.
-void MemoryAccess::assumeNoOutOfBound() {
- if (PollyIgnoreInbounds)
- return;
+isl::set MemoryAccess::assumeNoOutOfBound() {
auto *SAI = getScopArrayInfo();
isl::space Space = getOriginalAccessRelationSpace().range();
isl::set Outside = isl::set::empty(Space);
// bail out more often than strictly necessary.
Outside = Outside.remove_divs();
Outside = Outside.complement();
- const auto &Loc = getAccessInstruction()
- ? getAccessInstruction()->getDebugLoc()
- : DebugLoc();
+
if (!PollyPreciseInbounds)
Outside = Outside.gist_params(Statement->getDomain().params());
- Statement->getParent()->recordAssumption(INBOUNDS, Outside, Loc,
- AS_ASSUMPTION);
+ return Outside;
}
void MemoryAccess::buildMemIntrinsicAccessRelation() {
return SAI;
}
-const ScopArrayInfo *Scop::getScopArrayInfoOrNull(Value *BasePtr,
- MemoryKind Kind) {
+ScopArrayInfo *Scop::getScopArrayInfoOrNull(Value *BasePtr, MemoryKind Kind) {
auto *SAI = ScopArrayInfoMap[std::make_pair(BasePtr, Kind)].get();
return SAI;
}
-const ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, MemoryKind Kind) {
+ScopArrayInfo *Scop::getScopArrayInfo(Value *BasePtr, MemoryKind Kind) {
auto *SAI = getScopArrayInfoOrNull(BasePtr, Kind);
assert(SAI && "No ScopArrayInfo available for this base pointer");
return SAI;
InvalidContext = InvalidContext.unite(Set).coalesce();
}
-void Scop::recordAssumption(AssumptionKind Kind, isl::set Set, DebugLoc Loc,
- AssumptionSign Sign, BasicBlock *BB) {
- assert((Set.is_params() || BB) &&
- "Assumptions without a basic block must be parameter sets");
- RecordedAssumptions.push_back({Kind, Sign, Set, Loc, BB});
-}
-
void Scop::invalidate(AssumptionKind Kind, DebugLoc Loc, BasicBlock *BB) {
LLVM_DEBUG(dbgs() << "Invalidate SCoP because of reason " << Kind << "\n");
addAssumption(Kind, isl::set::empty(getParamSpace()), Loc, AS_ASSUMPTION, BB);
isl::ctx Scop::getIslCtx() const { return IslCtx.get(); }
__isl_give PWACtx Scop::getPwAff(const SCEV *E, BasicBlock *BB,
- bool NonNegative) {
+ bool NonNegative,
+ RecordedAssumptionsTy *RecordedAssumptions) {
// First try to use the SCEVAffinator to generate a piecewise defined
// affine function from @p E in the context of @p BB. If that tasks becomes to
// complex the affinator might return a nullptr. In such a case we invalidate
// the SCoP and return a dummy value. This way we do not need to add error
// handling code to all users of this function.
- auto PWAC = Affinator.getPwAff(E, BB);
+ auto PWAC = Affinator.getPwAff(E, BB, RecordedAssumptions);
if (PWAC.first) {
// TODO: We could use a heuristic and either use:
// SCEVAffinator::takeNonNegativeAssumption
// SCEVAffinator::interpretAsUnsigned
// to deal with unsigned or "NonNegative" SCEVs.
if (NonNegative)
- Affinator.takeNonNegativeAssumption(PWAC);
+ Affinator.takeNonNegativeAssumption(PWAC, RecordedAssumptions);
return PWAC;
}
auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
invalidate(COMPLEXITY, DL, BB);
- return Affinator.getPwAff(SE->getZero(E->getType()), BB);
+ return Affinator.getPwAff(SE->getZero(E->getType()), BB, RecordedAssumptions);
}
isl::union_set Scop::getDomains() const {
return isl::manage(Domain);
}
-isl::pw_aff Scop::getPwAffOnly(const SCEV *E, BasicBlock *BB) {
- PWACtx PWAC = getPwAff(E, BB);
+isl::pw_aff Scop::getPwAffOnly(const SCEV *E, BasicBlock *BB,
+ RecordedAssumptionsTy *RecordedAssumptions) {
+ PWACtx PWAC = getPwAff(E, BB, RecordedAssumptions);
return PWAC.first;
}
NonNegPWA, isl_pw_aff_add(PWAC.first.release(), ExpPWA)));
}
-void SCEVAffinator::takeNonNegativeAssumption(PWACtx &PWAC) {
+void SCEVAffinator::takeNonNegativeAssumption(
+ PWACtx &PWAC, RecordedAssumptionsTy *RecordedAssumptions) {
+ this->RecordedAssumptions = RecordedAssumptions;
+
auto *NegPWA = isl_pw_aff_neg(PWAC.first.copy());
auto *NegDom = isl_pw_aff_pos_set(NegPWA);
PWAC.second =
isl::manage(isl_set_union(PWAC.second.release(), isl_set_copy(NegDom)));
auto *Restriction = BB ? NegDom : isl_set_params(NegDom);
auto DL = BB ? BB->getTerminator()->getDebugLoc() : DebugLoc();
- S->recordAssumption(UNSIGNED, isl::manage(Restriction), DL, AS_RESTRICTION,
- BB);
+ recordAssumption(RecordedAssumptions, UNSIGNED, isl::manage(Restriction), DL,
+ AS_RESTRICTION, BB);
}
PWACtx SCEVAffinator::getPWACtxFromPWA(isl::pw_aff PWA) {
return std::make_pair(PWA, isl::set::empty(isl::space(Ctx, 0, NumIterators)));
}
-PWACtx SCEVAffinator::getPwAff(const SCEV *Expr, BasicBlock *BB) {
+PWACtx SCEVAffinator::getPwAff(const SCEV *Expr, BasicBlock *BB,
+ RecordedAssumptionsTy *RecordedAssumptions) {
this->BB = BB;
+ this->RecordedAssumptions = RecordedAssumptions;
if (BB) {
auto *DC = S->getDomainConditions(BB).release();
NotEqualSet = NotEqualSet.coalesce();
if (!NotEqualSet.is_empty())
- S->recordAssumption(WRAPPING, NotEqualSet, Loc, AS_RESTRICTION, BB);
+ recordAssumption(RecordedAssumptions, WRAPPING, NotEqualSet, Loc,
+ AS_RESTRICTION, BB);
return PWAC;
}
OutOfBoundsDom = isl_set_params(OutOfBoundsDom);
}
- S->recordAssumption(UNSIGNED, isl::manage(OutOfBoundsDom), DebugLoc(),
- AS_RESTRICTION, BB);
+ recordAssumption(RecordedAssumptions, UNSIGNED, isl::manage(OutOfBoundsDom),
+ DebugLoc(), AS_RESTRICTION, BB);
return OpPWAC;
}
// If the width is to big we assume the negative part does not occur.
if (!computeModuloForExpr(Op)) {
- takeNonNegativeAssumption(OpPWAC);
+ takeNonNegativeAssumption(OpPWAC, RecordedAssumptions);
return OpPWAC;
}
// precise but therefor a heuristic is needed.
// Assume a non-negative dividend.
- takeNonNegativeAssumption(DividendPWAC);
+ takeNonNegativeAssumption(DividendPWAC, RecordedAssumptions);
DividendPWAC = combine(DividendPWAC, DivisorPWAC, isl_pw_aff_div);
DividendPWAC.first = DividendPWAC.first.floor();
polly::splitEntryBlockForAlloca(EntryBlock, DT, LI, RI);
}
+void polly::recordAssumption(polly::RecordedAssumptionsTy *RecordedAssumptions,
+ polly::AssumptionKind Kind, isl::set Set,
+ DebugLoc Loc, polly::AssumptionSign Sign,
+ BasicBlock *BB) {
+ assert((Set.is_params() || BB) &&
+ "Assumptions without a basic block must be parameter sets");
+ if (RecordedAssumptions)
+ RecordedAssumptions->push_back({Kind, Sign, Set, Loc, BB});
+}
+
/// The SCEVExpander will __not__ generate any code for an existing SDiv/SRem
/// instruction but just use it, if it is referenced as a SCEVUnknown. We want
/// however to generate new code if the instruction is in the analyzed region