forked from OSchip/llvm-project
[RTC] Runtime Alias Checks for the ISL backend
This change will build all alias groups (minimal/maximal accesses to possible aliasing base pointers) we have to check before we can assume an alias free environment. It will also use these to create Runtime Alias Checks (RTC) in the ISL code generation backend, thus allow us to optimize SCoPs despite possibly aliasing pointers when this backend is used. This feature will be enabled for the isl code generator, e.g., --polly-code-generator=isl, but disabled for: - The cloog code generator (still the default). - The case delinearization is enabled. - The case non-affine accesses are allowed. llvm-svn: 218046
This commit is contained in:
parent
dcb5f1dcf6
commit
b164c795b7
|
@ -27,6 +27,15 @@ enum VectorizerChoice {
|
|||
};
|
||||
extern VectorizerChoice PollyVectorizerChoice;
|
||||
|
||||
enum CodeGenChoice {
|
||||
#ifdef CLOOG_FOUND
|
||||
CODEGEN_CLOOG,
|
||||
#endif
|
||||
CODEGEN_ISL,
|
||||
CODEGEN_NONE
|
||||
};
|
||||
extern CodeGenChoice PollyCodeGenChoice;
|
||||
|
||||
static inline int getNumberOfIterations(__isl_take isl_set *Domain) {
|
||||
int Dim = isl_set_dim(Domain, isl_dim_set);
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ typedef std::map<const SCEVUnknown *, const SCEV *> BaseToElSize;
|
|||
|
||||
extern bool PollyTrackFailures;
|
||||
extern bool PollyDelinearize;
|
||||
extern bool PollyUseRuntimeAliasChecks;
|
||||
|
||||
/// @brief A function attribute which will cause Polly to skip the function
|
||||
extern llvm::StringRef PollySkipFnAttr;
|
||||
|
@ -278,7 +279,7 @@ class ScopDetection : public FunctionPass {
|
|||
|
||||
public:
|
||||
static char ID;
|
||||
explicit ScopDetection() : FunctionPass(ID) {}
|
||||
explicit ScopDetection();
|
||||
|
||||
/// @brief Get the RegionInfo stored in this pass.
|
||||
///
|
||||
|
|
|
@ -47,6 +47,7 @@ struct isl_union_set;
|
|||
struct isl_union_map;
|
||||
struct isl_space;
|
||||
struct isl_constraint;
|
||||
struct isl_pw_multi_aff;
|
||||
|
||||
namespace polly {
|
||||
|
||||
|
@ -493,7 +494,17 @@ static inline raw_ostream &operator<<(raw_ostream &O, const ScopStmt &S) {
|
|||
/// This context contains information about the values the parameters
|
||||
/// can take and relations between different parameters.
|
||||
class Scop {
|
||||
//===-------------------------------------------------------------------===//
|
||||
public:
|
||||
/// @brief Type to represent a pair of minimal/maximal access to an array.
|
||||
using MinMaxAccessTy = std::pair<isl_pw_multi_aff *, isl_pw_multi_aff *>;
|
||||
|
||||
/// @brief Vector of minimal/maximal accesses to different arrays.
|
||||
using MinMaxVectorTy = SmallVector<MinMaxAccessTy, 4>;
|
||||
|
||||
/// @brief Vector of minimal/maximal access vectors one for each alias group.
|
||||
using MinMaxVectorVectorTy = SmallVector<MinMaxVectorTy *, 4>;
|
||||
|
||||
private:
|
||||
Scop(const Scop &) LLVM_DELETED_FUNCTION;
|
||||
const Scop &operator=(const Scop &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
|
@ -532,6 +543,21 @@ class Scop {
|
|||
/// this scop and that need to be code generated as a run-time test.
|
||||
isl_set *AssumedContext;
|
||||
|
||||
/// @brief The set of minimal/maximal accesses for each alias group.
|
||||
///
|
||||
/// When building runtime alias checks we look at all memory instructions and
|
||||
/// build so called alias groups. Each group contains a set of accesses to
|
||||
/// different base arrays which might alias with each other. However, between
|
||||
/// alias groups there is no aliasing possible.
|
||||
///
|
||||
/// In a program with int and float pointers annotated with tbaa information
|
||||
/// we would probably generate two alias groups, one for the int pointers and
|
||||
/// one for the float pointers.
|
||||
///
|
||||
/// During code generation we will create a runtime alias check for each alias
|
||||
/// group to ensure the SCoP is executed in an alias free environment.
|
||||
MinMaxVectorVectorTy MinMaxAliasGroups;
|
||||
|
||||
/// Create the static control part with a region, max loop depth of this
|
||||
/// region and parameters used in this region.
|
||||
Scop(TempScop &TempScop, LoopInfo &LI, ScalarEvolution &SE, isl_ctx *ctx);
|
||||
|
@ -563,9 +589,13 @@ class Scop {
|
|||
// The scattering numbers
|
||||
SmallVectorImpl<unsigned> &Scatter, LoopInfo &LI);
|
||||
|
||||
/// Helper function for printing the Scop.
|
||||
/// @name Helper function for printing the Scop.
|
||||
///
|
||||
///{
|
||||
void printContext(raw_ostream &OS) const;
|
||||
void printStatements(raw_ostream &OS) const;
|
||||
void printAliasAssumptions(raw_ostream &OS) const;
|
||||
///}
|
||||
|
||||
friend class ScopInfo;
|
||||
|
||||
|
@ -661,6 +691,14 @@ public:
|
|||
/// to hold.
|
||||
void addAssumption(__isl_take isl_set *Set);
|
||||
|
||||
/// @brief Build all alias groups for this SCoP.
|
||||
void buildAliasGroups(AliasAnalysis &AA);
|
||||
|
||||
/// @brief Return all alias groups for this SCoP.
|
||||
const MinMaxVectorVectorTy &getAliasGroups() const {
|
||||
return MinMaxAliasGroups;
|
||||
}
|
||||
|
||||
/// @brief Get an isl string representing the context.
|
||||
std::string getContextStr() const;
|
||||
|
||||
|
|
|
@ -65,6 +65,12 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
|
|||
return OS;
|
||||
}
|
||||
|
||||
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
|
||||
__isl_keep isl_pw_multi_aff *PMA) {
|
||||
OS << polly::stringFromIslObj(PMA);
|
||||
return OS;
|
||||
}
|
||||
|
||||
/// @brief Return @p Prefix + @p Val->getName() + @p Suffix but Isl compatible.
|
||||
std::string getIslCompatibleName(std::string Prefix, const llvm::Value *Val,
|
||||
std::string Suffix);
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "polly/ScopDetection.h"
|
||||
#include "polly/Support/SCEVValidator.h"
|
||||
#include "polly/Support/ScopHelper.h"
|
||||
#include "polly/CodeGen/CodeGeneration.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
|
@ -101,6 +102,13 @@ static cl::opt<bool>
|
|||
cl::Hidden, cl::init(false), cl::ZeroOrMore,
|
||||
cl::cat(PollyCategory));
|
||||
|
||||
bool polly::PollyUseRuntimeAliasChecks;
|
||||
static cl::opt<bool, true> XPollyUseRuntimeAliasChecks(
|
||||
"polly-use-runtime-alias-checks",
|
||||
cl::desc("Use runtime alias checks to resolve possible aliasing."),
|
||||
cl::location(PollyUseRuntimeAliasChecks), cl::Hidden, cl::ZeroOrMore,
|
||||
cl::init(true), cl::cat(PollyCategory));
|
||||
|
||||
static cl::opt<bool>
|
||||
ReportLevel("polly-report",
|
||||
cl::desc("Print information about the activities of Polly"),
|
||||
|
@ -184,6 +192,31 @@ void DiagnosticScopFound::print(DiagnosticPrinter &DP) const {
|
|||
//===----------------------------------------------------------------------===//
|
||||
// ScopDetection.
|
||||
|
||||
ScopDetection::ScopDetection() : FunctionPass(ID) {
|
||||
if (!PollyUseRuntimeAliasChecks)
|
||||
return;
|
||||
|
||||
if (PollyDelinearize) {
|
||||
DEBUG(errs() << "WARNING: We disable runtime alias checks as "
|
||||
"delinearization is enabled.\n");
|
||||
PollyUseRuntimeAliasChecks = false;
|
||||
}
|
||||
|
||||
if (AllowNonAffine) {
|
||||
DEBUG(errs() << "WARNING: We disable runtime alias checks as non affine "
|
||||
"accesses are enabled.\n");
|
||||
PollyUseRuntimeAliasChecks = false;
|
||||
}
|
||||
|
||||
#ifdef CLOOG_FOUND
|
||||
if (PollyCodeGenChoice == CODEGEN_CLOOG) {
|
||||
DEBUG(errs() << "WARNING: We disable runtime alias checks as the cloog "
|
||||
"code generation cannot emit them.\n");
|
||||
PollyUseRuntimeAliasChecks = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class RR, typename... Args>
|
||||
inline bool ScopDetection::invalid(DetectionContext &Context, bool Assert,
|
||||
Args &&... Arguments) const {
|
||||
|
@ -499,7 +532,7 @@ bool ScopDetection::isValidMemoryAccess(Instruction &Inst,
|
|||
if (IntToPtrInst *Inst = dyn_cast<IntToPtrInst>(BaseValue))
|
||||
return invalid<ReportIntToPtr>(Context, /*Assert=*/true, Inst);
|
||||
|
||||
if (IgnoreAliasing)
|
||||
if (PollyUseRuntimeAliasChecks || IgnoreAliasing)
|
||||
return true;
|
||||
|
||||
// Check if the base pointer of the memory access does alias with
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
#include "llvm/Analysis/RegionIterator.h"
|
||||
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
@ -1128,6 +1129,104 @@ void Scop::simplifyAssumedContext() {
|
|||
isl_set_gist_params(AssumedContext, isl_union_set_params(getDomains()));
|
||||
}
|
||||
|
||||
/// @brief Add the minimal/maximal access in @p Set to @p User.
|
||||
static int buildMinMaxAccess(__isl_take isl_set *Set, void *User) {
|
||||
Scop::MinMaxVectorTy *MinMaxAccesses = (Scop::MinMaxVectorTy *)User;
|
||||
isl_pw_multi_aff *MinPMA, *MaxPMA;
|
||||
isl_pw_aff *LastDimAff;
|
||||
isl_aff *OneAff;
|
||||
unsigned Pos;
|
||||
|
||||
MinPMA = isl_set_lexmin_pw_multi_aff(isl_set_copy(Set));
|
||||
MaxPMA = isl_set_lexmax_pw_multi_aff(isl_set_copy(Set));
|
||||
|
||||
// Adjust the last dimension of the maximal access by one as we want to
|
||||
// enclose the accessed memory region by MinPMA and MaxPMA. The pointer
|
||||
// we test during code generation might now point after the end of the
|
||||
// allocated array but we will never dereference it anyway.
|
||||
assert(isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) &&
|
||||
"Assumed at least one output dimension");
|
||||
Pos = isl_pw_multi_aff_dim(MaxPMA, isl_dim_out) - 1;
|
||||
LastDimAff = isl_pw_multi_aff_get_pw_aff(MaxPMA, Pos);
|
||||
OneAff = isl_aff_zero_on_domain(
|
||||
isl_local_space_from_space(isl_pw_aff_get_domain_space(LastDimAff)));
|
||||
OneAff = isl_aff_add_constant_si(OneAff, 1);
|
||||
LastDimAff = isl_pw_aff_add(LastDimAff, isl_pw_aff_from_aff(OneAff));
|
||||
MaxPMA = isl_pw_multi_aff_set_pw_aff(MaxPMA, Pos, LastDimAff);
|
||||
|
||||
MinMaxAccesses->push_back(std::make_pair(MinPMA, MaxPMA));
|
||||
|
||||
isl_set_free(Set);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Scop::buildAliasGroups(AliasAnalysis &AA) {
|
||||
// To create sound alias checks we perform the following steps:
|
||||
// o) Use the alias analysis and an alias set tracker to build alias sets
|
||||
// for all memory accesses inside the SCoP.
|
||||
// o) For each alias set we then map the aliasing pointers back to the
|
||||
// memory accesses we know, thus obtain groups of memory accesses which
|
||||
// might alias.
|
||||
// o) For each group with more then one base pointer we then compute minimal
|
||||
// and maximal accesses to each array in this group.
|
||||
using AliasGroupTy = SmallVector<MemoryAccess *, 4>;
|
||||
|
||||
AliasSetTracker AST(AA);
|
||||
|
||||
DenseMap<Value *, MemoryAccess *> PtrToAcc;
|
||||
for (ScopStmt *Stmt : *this) {
|
||||
for (MemoryAccess *MA : *Stmt) {
|
||||
if (MA->isScalar())
|
||||
continue;
|
||||
Instruction *Acc = MA->getAccessInstruction();
|
||||
PtrToAcc[getPointerOperand(*Acc)] = MA;
|
||||
AST.add(Acc);
|
||||
}
|
||||
}
|
||||
|
||||
SmallVector<AliasGroupTy, 4> AliasGroups;
|
||||
for (AliasSet &AS : AST) {
|
||||
if (AS.isMustAlias())
|
||||
continue;
|
||||
AliasGroupTy AG;
|
||||
for (auto PR : AS)
|
||||
AG.push_back(PtrToAcc[PR.getValue()]);
|
||||
assert(AG.size() > 1 &&
|
||||
"Alias groups should contain at least two accesses");
|
||||
AliasGroups.push_back(std::move(AG));
|
||||
}
|
||||
|
||||
SmallPtrSet<const Value *, 4> BaseValues;
|
||||
for (auto I = AliasGroups.begin(); I != AliasGroups.end();) {
|
||||
BaseValues.clear();
|
||||
for (MemoryAccess *MA : *I)
|
||||
BaseValues.insert(MA->getBaseAddr());
|
||||
if (BaseValues.size() > 1)
|
||||
I++;
|
||||
else
|
||||
I = AliasGroups.erase(I);
|
||||
}
|
||||
|
||||
for (AliasGroupTy &AG : AliasGroups) {
|
||||
MinMaxVectorTy *MinMaxAccesses = new MinMaxVectorTy();
|
||||
MinMaxAccesses->reserve(AG.size());
|
||||
|
||||
isl_union_map *Accesses = isl_union_map_empty(getParamSpace());
|
||||
for (MemoryAccess *MA : AG)
|
||||
Accesses = isl_union_map_add_map(Accesses, MA->getAccessRelation());
|
||||
Accesses = isl_union_map_intersect_domain(Accesses, getDomains());
|
||||
|
||||
isl_union_set *Locations = isl_union_map_range(Accesses);
|
||||
Locations = isl_union_set_intersect_params(Locations, getAssumedContext());
|
||||
Locations = isl_union_set_coalesce(Locations);
|
||||
Locations = isl_union_set_detect_equalities(Locations);
|
||||
isl_union_set_foreach_set(Locations, buildMinMaxAccess, MinMaxAccesses);
|
||||
isl_union_set_free(Locations);
|
||||
|
||||
MinMaxAliasGroups.push_back(MinMaxAccesses);
|
||||
}
|
||||
}
|
||||
|
||||
Scop::Scop(TempScop &tempScop, LoopInfo &LI, ScalarEvolution &ScalarEvolution,
|
||||
isl_ctx *Context)
|
||||
: SE(&ScalarEvolution), R(tempScop.getMaxRegion()),
|
||||
|
@ -1158,6 +1257,15 @@ Scop::~Scop() {
|
|||
// Free the statements;
|
||||
for (ScopStmt *Stmt : *this)
|
||||
delete Stmt;
|
||||
|
||||
// Free the alias groups
|
||||
for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) {
|
||||
for (MinMaxAccessTy &MMA : *MinMaxAccesses) {
|
||||
isl_pw_multi_aff_free(MMA.first);
|
||||
isl_pw_multi_aff_free(MMA.second);
|
||||
}
|
||||
delete MinMaxAccesses;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Scop::getContextStr() const { return stringFromIslObj(Context); }
|
||||
|
@ -1219,6 +1327,20 @@ void Scop::printContext(raw_ostream &OS) const {
|
|||
}
|
||||
}
|
||||
|
||||
void Scop::printAliasAssumptions(raw_ostream &OS) const {
|
||||
OS.indent(4) << "Alias Groups (" << MinMaxAliasGroups.size() << "):\n";
|
||||
if (MinMaxAliasGroups.empty()) {
|
||||
OS.indent(8) << "n/a\n";
|
||||
return;
|
||||
}
|
||||
for (MinMaxVectorTy *MinMaxAccesses : MinMaxAliasGroups) {
|
||||
OS.indent(8) << "[[";
|
||||
for (MinMaxAccessTy &MinMacAccess : *MinMaxAccesses)
|
||||
OS << " <" << MinMacAccess.first << ", " << MinMacAccess.second << ">";
|
||||
OS << " ]]\n";
|
||||
}
|
||||
}
|
||||
|
||||
void Scop::printStatements(raw_ostream &OS) const {
|
||||
OS << "Statements {\n";
|
||||
|
||||
|
@ -1233,6 +1355,7 @@ void Scop::print(raw_ostream &OS) const {
|
|||
<< "\n";
|
||||
OS.indent(4) << "Region: " << getNameStr() << "\n";
|
||||
printContext(OS.indent(4));
|
||||
printAliasAssumptions(OS);
|
||||
printStatements(OS.indent(4));
|
||||
}
|
||||
|
||||
|
@ -1419,11 +1542,13 @@ void ScopInfo::getAnalysisUsage(AnalysisUsage &AU) const {
|
|||
AU.addRequired<RegionInfoPass>();
|
||||
AU.addRequired<ScalarEvolution>();
|
||||
AU.addRequired<TempScopInfo>();
|
||||
AU.addRequired<AliasAnalysis>();
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) {
|
||||
LoopInfo &LI = getAnalysis<LoopInfo>();
|
||||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||
ScalarEvolution &SE = getAnalysis<ScalarEvolution>();
|
||||
|
||||
TempScop *tempScop = getAnalysis<TempScopInfo>().getTempScop(R);
|
||||
|
@ -1441,6 +1566,9 @@ bool ScopInfo::runOnRegion(Region *R, RGPassManager &RGM) {
|
|||
|
||||
scop = new Scop(*tempScop, LI, SE, ctx);
|
||||
|
||||
if (PollyUseRuntimeAliasChecks)
|
||||
scop->buildAliasGroups(AA);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1451,6 +1579,7 @@ Pass *polly::createScopInfoPass() { return new ScopInfo(); }
|
|||
INITIALIZE_PASS_BEGIN(ScopInfo, "polly-scops",
|
||||
"Polly - Create polyhedral description of Scops", false,
|
||||
false);
|
||||
INITIALIZE_AG_DEPENDENCY(AliasAnalysis);
|
||||
INITIALIZE_PASS_DEPENDENCY(LoopInfo);
|
||||
INITIALIZE_PASS_DEPENDENCY(RegionInfoPass);
|
||||
INITIALIZE_PASS_DEPENDENCY(ScalarEvolution);
|
||||
|
|
|
@ -310,6 +310,34 @@ void IslAst::buildRunCondition(__isl_keep isl_ast_build *Build) {
|
|||
isl_pw_aff *Cond = isl_pw_aff_union_max(PwOne, PwZero);
|
||||
|
||||
RunCondition = isl_ast_build_expr_from_pw_aff(Build, Cond);
|
||||
|
||||
// Create the alias checks from the minimal/maximal accesses in each alias
|
||||
// group. This operation is by construction quadratic in the number of
|
||||
// elements in each alias group.
|
||||
isl_ast_expr *NonAliasGroup, *MinExpr, *MaxExpr;
|
||||
for (const Scop::MinMaxVectorTy *MinMaxAccesses : S->getAliasGroups()) {
|
||||
auto AccEnd = MinMaxAccesses->end();
|
||||
for (auto AccIt0 = MinMaxAccesses->begin(); AccIt0 != AccEnd; ++AccIt0) {
|
||||
for (auto AccIt1 = AccIt0 + 1; AccIt1 != AccEnd; ++AccIt1) {
|
||||
MinExpr =
|
||||
isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff(
|
||||
Build, isl_pw_multi_aff_copy(AccIt0->first)));
|
||||
MaxExpr =
|
||||
isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff(
|
||||
Build, isl_pw_multi_aff_copy(AccIt1->second)));
|
||||
NonAliasGroup = isl_ast_expr_le(MaxExpr, MinExpr);
|
||||
MinExpr =
|
||||
isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff(
|
||||
Build, isl_pw_multi_aff_copy(AccIt1->first)));
|
||||
MaxExpr =
|
||||
isl_ast_expr_address_of(isl_ast_build_access_from_pw_multi_aff(
|
||||
Build, isl_pw_multi_aff_copy(AccIt0->second)));
|
||||
NonAliasGroup =
|
||||
isl_ast_expr_or(NonAliasGroup, isl_ast_expr_le(MaxExpr, MinExpr));
|
||||
RunCondition = isl_ast_expr_and(RunCondition, NonAliasGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IslAst::IslAst(Scop *Scop, Dependences &D) : S(Scop) {
|
||||
|
|
|
@ -591,7 +591,9 @@ public:
|
|||
Value *buildRTC(PollyIRBuilder &Builder, IslExprBuilder &ExprBuilder) {
|
||||
Builder.SetInsertPoint(Builder.GetInsertBlock()->getTerminator());
|
||||
Value *RTC = ExprBuilder.create(AI->getRunCondition());
|
||||
return Builder.CreateIsNotNull(RTC);
|
||||
if (!RTC->getType()->isIntegerTy(1))
|
||||
RTC = Builder.CreateIsNotNull(RTC);
|
||||
return RTC;
|
||||
}
|
||||
|
||||
bool runOnScop(Scop &S) {
|
||||
|
|
|
@ -333,8 +333,10 @@ Value *IslExprBuilder::createOpBoolean(__isl_take isl_ast_expr *Expr) {
|
|||
//
|
||||
// TODO: Document in isl itself, that the unconditionally evaluating the
|
||||
// second part of '||' or '&&' expressions is safe.
|
||||
assert(LHS->getType() == Builder.getInt1Ty() && "Expected i1 type");
|
||||
assert(RHS->getType() == Builder.getInt1Ty() && "Expected i1 type");
|
||||
if (!LHS->getType()->isIntegerTy(1))
|
||||
LHS = Builder.CreateIsNotNull(LHS);
|
||||
if (!RHS->getType()->isIntegerTy(1))
|
||||
RHS = Builder.CreateIsNotNull(RHS);
|
||||
|
||||
switch (OpType) {
|
||||
default:
|
||||
|
|
|
@ -66,21 +66,14 @@ static cl::opt<OptimizerChoice> Optimizer(
|
|||
cl::Hidden, cl::init(OPTIMIZER_ISL), cl::ZeroOrMore,
|
||||
cl::cat(PollyCategory));
|
||||
|
||||
enum CodeGenChoice {
|
||||
#ifdef CLOOG_FOUND
|
||||
CODEGEN_CLOOG,
|
||||
#endif
|
||||
CODEGEN_ISL,
|
||||
CODEGEN_NONE
|
||||
};
|
||||
|
||||
#ifdef CLOOG_FOUND
|
||||
enum CodeGenChoice DefaultCodeGen = CODEGEN_CLOOG;
|
||||
#else
|
||||
enum CodeGenChoice DefaultCodeGen = CODEGEN_ISL;
|
||||
#endif
|
||||
|
||||
static cl::opt<CodeGenChoice> CodeGenerator(
|
||||
CodeGenChoice polly::PollyCodeGenChoice;
|
||||
static cl::opt<CodeGenChoice, true> XCodeGenerator(
|
||||
"polly-code-generator", cl::desc("Select the code generator"),
|
||||
cl::values(
|
||||
#ifdef CLOOG_FOUND
|
||||
|
@ -88,8 +81,8 @@ static cl::opt<CodeGenChoice> CodeGenerator(
|
|||
#endif
|
||||
clEnumValN(CODEGEN_ISL, "isl", "isl code generator"),
|
||||
clEnumValN(CODEGEN_NONE, "none", "no code generation"), clEnumValEnd),
|
||||
cl::Hidden, cl::init(DefaultCodeGen), cl::ZeroOrMore,
|
||||
cl::cat(PollyCategory));
|
||||
cl::Hidden, cl::location(PollyCodeGenChoice), cl::init(DefaultCodeGen),
|
||||
cl::ZeroOrMore, cl::cat(PollyCategory));
|
||||
|
||||
VectorizerChoice polly::PollyVectorizerChoice;
|
||||
static cl::opt<polly::VectorizerChoice, true> Vectorizer(
|
||||
|
@ -238,7 +231,7 @@ static void registerPollyPasses(llvm::PassManagerBase &PM) {
|
|||
if (ExportJScop)
|
||||
PM.add(polly::createJSONExporterPass());
|
||||
|
||||
switch (CodeGenerator) {
|
||||
switch (PollyCodeGenChoice) {
|
||||
#ifdef CLOOG_FOUND
|
||||
case CODEGEN_CLOOG:
|
||||
PM.add(polly::createCodeGenerationPass());
|
||||
|
|
|
@ -43,5 +43,5 @@ for.inc11: ; preds = %for.body7
|
|||
for.end14: ; preds = %for.cond4
|
||||
ret i32 0
|
||||
}
|
||||
; CHECK: New access function '{ Stmt_for_body7[i0] -> MemRef_B[0] }'detected in JSCOP file
|
||||
; CHECK: New access function '{ Stmt_for_body[i0] -> MemRef_A[0] }'detected in JSCOP file
|
||||
; CHECK-DAG: New access function '{ Stmt_for_body7[i0] -> MemRef_B[0] }'detected in JSCOP file
|
||||
; CHECK-DAG: New access function '{ Stmt_for_body[i0] -> MemRef_A[0] }'detected in JSCOP file
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
; RUN: opt %loadPolly -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1| FileCheck %s
|
||||
; RUN: opt %loadPolly -polly-use-runtime-alias-checks=false -pass-remarks-missed="polly-detect" -polly-detect-track-failures -polly-detect -analyze < %s 2>&1| FileCheck %s
|
||||
|
||||
;void f(int A[], int B[]) {
|
||||
; for (int i=0; i<42; i++)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
; RUN: opt %loadPolly -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s
|
||||
; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
|
||||
; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
|
||||
; REQUIRES: asserts
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||
|
@ -32,4 +33,5 @@ return: ; preds = %bb3
|
|||
declare i32 @rnd(...)
|
||||
|
||||
|
||||
; CHECK: 1 polly-detect - Number of bad regions for Scop: Found base address alias
|
||||
; RTA: 1 polly-detect - Number of regions that a valid part of Scop
|
||||
; NORTA: 1 polly-detect - Number of bad regions for Scop: Found base address alias
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
; RUN: opt %loadPolly -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s
|
||||
; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
|
||||
; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
|
||||
; REQUIRES: asserts
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||
|
@ -33,4 +34,5 @@ return: ; preds = %bb3
|
|||
declare i32 @rnd(...)
|
||||
|
||||
|
||||
; CHECK: 1 polly-detect - Number of bad regions for Scop: Found base address alias
|
||||
; RTA: 1 polly-detect - Number of regions that a valid part of Scop
|
||||
; NORTA: 1 polly-detect - Number of bad regions for Scop: Found base address alias
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
; RUN: opt %loadPolly -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s
|
||||
; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
|
||||
; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
|
||||
; REQUIRES: asserts
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||
|
@ -31,4 +32,5 @@ return: ; preds = %bb
|
|||
ret void
|
||||
}
|
||||
|
||||
; CHECK: 1 polly-detect - Number of bad regions for Scop: Found base address alias
|
||||
; RTA: 1 polly-detect - Number of regions that a valid part of Scop
|
||||
; NORTA: 1 polly-detect - Number of bad regions for Scop: Found base address alias
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
; RUN: opt %loadPolly -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s
|
||||
; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
|
||||
; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
|
||||
; REQUIRES: asserts
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||
|
@ -24,4 +25,5 @@ return: ; preds = %bb
|
|||
}
|
||||
|
||||
|
||||
; CHECK: 1 polly-detect - Number of bad regions for Scop: Found base address alias
|
||||
; RTA: 1 polly-detect - Number of regions that a valid part of Scop
|
||||
; NORTA: 1 polly-detect - Number of bad regions for Scop: Found base address alias
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
; RUN: opt %loadPolly -basicaa -polly-analyze-ir -analyze < %s -stats 2>&1 | not FileCheck %s
|
||||
; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=RTA
|
||||
; RUN: opt %loadPolly -polly-code-generator=isl -polly-analyze-ir -polly-use-runtime-alias-checks=false -analyze < %s -stats 2>&1 | FileCheck %s --check-prefix=NORTA
|
||||
; REQUIRES: asserts
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
|
||||
|
@ -24,4 +25,5 @@ return: ; preds = %bb
|
|||
}
|
||||
|
||||
|
||||
; CHECK: Found base address alias
|
||||
; RTA: 1 polly-detect - Number of regions that a valid part of Scop
|
||||
; NORTA: 1 polly-detect - Number of bad regions for Scop: Found base address alias
|
||||
|
|
Loading…
Reference in New Issue