/// compute for one SCoP. It also offers an interface that allows users to
/// query only specific parts.
struct Dependences {
+ // Granularities of the current dependence analysis
+ enum AnalyisLevel {
+ AL_Statement = 0,
+ // Distinguish accessed memory references in the same statement
+ AL_Reference,
+ // Distinguish memory access instances in the same statement
+ AL_Access,
+
+ NumAnalysisLevels
+ };
/// @brief Map type for reduction dependences.
using ReductionDependencesMapTy = DenseMap<MemoryAccess *, isl_map *>;
~Dependences() { releaseMemory(); }
private:
- /// @brief Create an empty Dependences struct.
- explicit Dependences(const std::shared_ptr<isl_ctx> &IslCtx)
+ /// @brief Create an empty dependences struct.
+ explicit Dependences(const std::shared_ptr<isl_ctx> &IslCtx,
+ AnalyisLevel Level)
: RAW(nullptr), WAR(nullptr), WAW(nullptr), RED(nullptr), TC_RED(nullptr),
- IslCtx(IslCtx) {}
+ IslCtx(IslCtx), Level(Level) {}
/// @brief Calculate and add at the privatization dependences.
void addPrivatizationDependences();
/// @brief Isl context from the SCoP.
std::shared_ptr<isl_ctx> IslCtx;
+
+ /// @brief Granularity of this dependence analysis
+ const AnalyisLevel Level;
};
class DependenceInfo : public ScopPass {
DependenceInfo() : ScopPass(ID) {}
/// @brief Return the dependence information for the current SCoP.
- const Dependences &getDependences() { return *D; }
+ ///
+ /// @param Level The granularity of dependence analysis result.
+ ///
+ /// @return The dependence analysis result
+ ///
+ const Dependences &getDependences(Dependences::AnalyisLevel Level);
/// @brief Recompute dependences from schedule and memory accesses.
- void recomputeDependences();
+ const Dependences &recomputeDependences(Dependences::AnalyisLevel Level);
/// @brief Compute the dependence information for the SCoP @p S.
bool runOnScop(Scop &S) override;
/// @brief Print the dependences for the given SCoP to @p OS.
- void printScop(raw_ostream &OS, Scop &) const override { D->print(OS); }
+ void printScop(raw_ostream &OS, Scop &) const override;
/// @brief Release the internal memory.
- void releaseMemory() override { D.reset(); }
+ void releaseMemory() override {
+ for (auto &d : D)
+ d.reset();
+ }
/// @brief Register all analyses and transformation required.
void getAnalysisUsage(AnalysisUsage &AU) const override;
Scop *S;
/// @brief Dependences struct for the current SCoP.
- std::unique_ptr<Dependences> D;
+ std::unique_ptr<Dependences> D[Dependences::NumAnalysisLevels];
};
} // End polly namespace.
cl::Hidden, cl::init(VALUE_BASED_ANALYSIS), cl::ZeroOrMore,
cl::cat(PollyCategory));
-enum AnalyisLevel {
- STATEMENT_LEVEL_ANALYSIS = 0,
- REFERENCE_LEVEL_ANALYSIS,
- ACCESS_LEVEL_ANALYSIS
-};
-static cl::opt<enum AnalyisLevel> OptAnalysisLevel(
+static cl::opt<Dependences::AnalyisLevel> OptAnalysisLevel(
"polly-dependences-analysis-level",
cl::desc("The level of dependence analysis"),
- cl::values(clEnumValN(STATEMENT_LEVEL_ANALYSIS, "statement-level",
+ cl::values(clEnumValN(Dependences::AL_Statement, "statement-level",
"Statement-level analysis"),
- clEnumValN(REFERENCE_LEVEL_ANALYSIS, "reference-level",
+ clEnumValN(Dependences::AL_Reference, "reference-level",
"Memory reference level analysis that distinguish"
" accessed references in the same statement"),
- clEnumValN(ACCESS_LEVEL_ANALYSIS, "access-level",
+ clEnumValN(Dependences::AL_Access, "access-level",
"Memory reference level analysis that distinguish"
" access instructions in the same statement"),
clEnumValEnd),
- cl::Hidden, cl::init(STATEMENT_LEVEL_ANALYSIS), cl::ZeroOrMore,
+ cl::Hidden, cl::init(Dependences::AL_Statement), cl::ZeroOrMore,
cl::cat(PollyCategory));
//===----------------------------------------------------------------------===//
/// @brief Tag the @p Relation domain with either MA->getArrayId() or
/// MA->getId() based on @p TagLevel
static __isl_give isl_map *tag(__isl_take isl_map *Relation, MemoryAccess *MA,
- AnalyisLevel TagLevel) {
- if (TagLevel == REFERENCE_LEVEL_ANALYSIS)
+ Dependences::AnalyisLevel TagLevel) {
+ if (TagLevel == Dependences::AL_Reference)
return tag(Relation, MA->getArrayId());
- if (TagLevel == ACCESS_LEVEL_ANALYSIS)
+ if (TagLevel == Dependences::AL_Access)
return tag(Relation, MA->getId());
// No need to tag at the statement level.
static void collectInfo(Scop &S, isl_union_map **Read, isl_union_map **Write,
isl_union_map **MayWrite,
isl_union_map **AccessSchedule,
- isl_union_map **StmtSchedule) {
+ isl_union_map **StmtSchedule,
+ Dependences::AnalyisLevel Level) {
isl_space *Space = S.getParamSpace();
*Read = isl_union_map_empty(isl_space_copy(Space));
*Write = isl_union_map_empty(isl_space_copy(Space));
*AccessSchedule = isl_union_map_add_map(*AccessSchedule, Schedule);
} else {
- accdom = tag(accdom, MA, OptAnalysisLevel);
- if (OptAnalysisLevel > STATEMENT_LEVEL_ANALYSIS) {
- isl_map *Schedule = tag(Stmt.getSchedule(), MA, OptAnalysisLevel);
+ accdom = tag(accdom, MA, Level);
+ if (Level > Dependences::AL_Statement) {
+ isl_map *Schedule = tag(Stmt.getSchedule(), MA, Level);
*StmtSchedule = isl_union_map_add_map(*StmtSchedule, Schedule);
}
}
*Write = isl_union_map_add_map(*Write, accdom);
}
- if (OptAnalysisLevel == STATEMENT_LEVEL_ANALYSIS)
+ if (Level == Dependences::AL_Statement)
*StmtSchedule = isl_union_map_add_map(*StmtSchedule, Stmt.getSchedule());
}
DEBUG(dbgs() << "Scop: \n" << S << "\n");
- collectInfo(S, &Read, &Write, &MayWrite, &AccessSchedule, &StmtSchedule);
+ collectInfo(S, &Read, &Write, &MayWrite, &AccessSchedule, &StmtSchedule,
+ Level);
DEBUG(dbgs() << "Read: " << Read << '\n';
dbgs() << "Write: " << Write << '\n';
isl_union_map_free(AccessSchedule);
Schedule = S.getScheduleTree();
// Tag the schedule tree if we want fine-grain dependence info
- if (OptAnalysisLevel > STATEMENT_LEVEL_ANALYSIS) {
+ if (Level > AL_Statement) {
auto TaggedDom = isl_union_map_domain((isl_union_map_copy(StmtSchedule)));
auto TaggedMap = isl_union_set_unwrap(TaggedDom);
auto Tags = isl_union_map_domain_map_union_pw_multi_aff(TaggedMap);
ReductionDependences[MA] = D;
}
-void DependenceInfo::recomputeDependences() {
- D.reset(new Dependences(S->getSharedIslCtx()));
- D->calculateDependences(*S);
+const Dependences &
+DependenceInfo::getDependences(Dependences::AnalyisLevel Level) {
+ if (Dependences *d = D[Level].get())
+ return *d;
+
+ return recomputeDependences(Level);
+}
+
+const Dependences &
+DependenceInfo::recomputeDependences(Dependences::AnalyisLevel Level) {
+ D[Level].reset(new Dependences(S->getSharedIslCtx(), Level));
+ D[Level]->calculateDependences(*S);
+ return *D[Level];
}
bool DependenceInfo::runOnScop(Scop &ScopVar) {
S = &ScopVar;
- recomputeDependences();
return false;
}
+/// @brief Print the dependences for the given SCoP to @p OS.
+
+void polly::DependenceInfo::printScop(raw_ostream &OS, Scop &S) const {
+ if (auto d = D[OptAnalysisLevel].get()) {
+ d->print(OS);
+ return;
+ }
+
+ // Otherwise create the dependences on-the-fly and print it
+ Dependences D(S.getSharedIslCtx(), OptAnalysisLevel);
+ D.calculateDependences(S);
+ D.print(OS);
+}
+
void DependenceInfo::getAnalysisUsage(AnalysisUsage &AU) const {
- ScopPass::getAnalysisUsage(AU);
+ AU.addRequiredTransitive<ScopInfo>();
+ AU.setPreservesAll();
}
char DependenceInfo::ID = 0;