summaryrefslogtreecommitdiffstats
path: root/polly/lib/Analysis/Dependences.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'polly/lib/Analysis/Dependences.cpp')
-rw-r--r--polly/lib/Analysis/Dependences.cpp414
1 files changed, 414 insertions, 0 deletions
diff --git a/polly/lib/Analysis/Dependences.cpp b/polly/lib/Analysis/Dependences.cpp
new file mode 100644
index 00000000000..8b3600226a2
--- /dev/null
+++ b/polly/lib/Analysis/Dependences.cpp
@@ -0,0 +1,414 @@
+//===- Dependency.cpp - Calculate dependency information for a Scop. -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Calculate the data dependency relations for a Scop using ISL.
+//
+// The integer set library (ISL) from Sven, has a integrated dependency analysis
+// to calculate data dependences. This pass takes advantage of this and
+// calculate those dependences a Scop.
+//
+// The dependences in this pass are exact in terms that for a specific read
+// statement instance only the last write statement instance is returned. In
+// case of may writes a set of possible write instances is returned. This
+// analysis will never produce redundant dependences.
+//
+//===----------------------------------------------------------------------===//
+//
+#include "polly/Dependences.h"
+
+#include "polly/LinkAllPasses.h"
+#include "polly/ScopInfo.h"
+#include "polly/Support/GICHelper.h"
+
+#define DEBUG_TYPE "polly-dependences"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/CommandLine.h"
+
+#include <isl/flow.h>
+#include <isl/map.h>
+#include <isl/constraint.h>
+
+using namespace polly;
+using namespace llvm;
+
+static cl::opt<bool>
+ LegalityCheckDisabled("disable-polly-legality",
+ cl::desc("Disable polly legality check"), cl::Hidden,
+ cl::init(false));
+
+//===----------------------------------------------------------------------===//
+Dependences::Dependences() : ScopPass(ID) {
+ must_dep = may_dep = NULL;
+ must_no_source = may_no_source = NULL;
+ sink = must_source = may_source = NULL;
+ war_dep = waw_dep = NULL;
+}
+
+bool Dependences::runOnScop(Scop &S) {
+ isl_dim *dim = isl_dim_alloc(S.getCtx(), S.getNumParams(), 0, 0);
+
+ if (sink)
+ isl_union_map_free(sink);
+
+ if (must_source)
+ isl_union_map_free(must_source);
+
+ if (may_source)
+ isl_union_map_free(may_source);
+
+ sink = isl_union_map_empty(isl_dim_copy(dim));
+ must_source = isl_union_map_empty(isl_dim_copy(dim));
+ may_source = isl_union_map_empty(isl_dim_copy(dim));
+ isl_union_map *schedule = isl_union_map_empty(dim);
+
+ if (must_dep)
+ isl_union_map_free(must_dep);
+
+ if (may_dep)
+ isl_union_map_free(may_dep);
+
+ if (must_no_source)
+ isl_union_map_free(must_no_source);
+
+ if (may_no_source)
+ isl_union_map_free(may_no_source);
+
+ if (war_dep)
+ isl_union_map_free(war_dep);
+
+ if (waw_dep)
+ isl_union_map_free(waw_dep);
+
+ must_dep = may_dep = NULL;
+ must_no_source = may_no_source = NULL;
+
+ war_dep = waw_dep = NULL;
+
+ for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) {
+ ScopStmt *Stmt = *SI;
+
+ for (ScopStmt::memacc_iterator MI = Stmt->memacc_begin(),
+ ME = Stmt->memacc_end(); MI != ME; ++MI) {
+ isl_set *domcp = isl_set_copy(Stmt->getDomain());
+ isl_map *accdom = isl_map_copy((*MI)->getAccessFunction());
+
+ accdom = isl_map_intersect_domain(accdom, domcp);
+
+ if ((*MI)->isRead())
+ isl_union_map_add_map(sink, accdom);
+ else
+ isl_union_map_add_map(must_source, accdom);
+ }
+ isl_map *scattering = isl_map_copy(Stmt->getScattering());
+ isl_union_map_add_map(schedule, scattering);
+ }
+
+ DEBUG(
+ dbgs().indent(4) << "Sink:\n";
+ dbgs().indent(8) << stringFromIslObj(sink) << "\n";
+
+ dbgs().indent(4) << "MustSource:\n";
+ dbgs().indent(8) << stringFromIslObj(must_source) << "\n";
+
+ dbgs().indent(4) << "MaySource:\n";
+ dbgs().indent(8) << stringFromIslObj(may_source) << "\n";
+
+ dbgs().indent(4) << "Schedule:\n";
+ dbgs().indent(8) << stringFromIslObj(schedule) << "\n";
+ );
+
+ isl_union_map_compute_flow(isl_union_map_copy(sink),
+ isl_union_map_copy(must_source),
+ isl_union_map_copy(may_source),
+ isl_union_map_copy(schedule),
+ &must_dep, &may_dep, &must_no_source,
+ &may_no_source);
+
+ isl_union_map_compute_flow(isl_union_map_copy(must_source),
+ isl_union_map_copy(must_source),
+ isl_union_map_copy(sink), schedule,
+ &waw_dep, &war_dep, NULL, NULL);
+
+ // Remove redundant statements.
+ must_dep = isl_union_map_coalesce(must_dep);
+ may_dep = isl_union_map_coalesce(may_dep);
+ must_no_source = isl_union_map_coalesce(must_no_source);
+ may_no_source = isl_union_map_coalesce(may_no_source);
+ waw_dep = isl_union_map_coalesce(waw_dep);
+ war_dep = isl_union_map_coalesce(war_dep);
+
+ return false;
+}
+
+bool Dependences::isValidScattering(StatementToIslMapTy *NewScattering) {
+ Scop &S = getCurScop();
+
+ if (LegalityCheckDisabled)
+ return true;
+
+ isl_dim *dim = isl_dim_alloc(S.getCtx(), S.getNumParams(), 0, 0);
+
+ isl_union_map *schedule = isl_union_map_empty(dim);
+
+ for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) {
+ ScopStmt *Stmt = *SI;
+
+ isl_map *scattering;
+
+ if (NewScattering->find(*SI) == NewScattering->end())
+ scattering = isl_map_copy(Stmt->getScattering());
+ else
+ scattering = isl_map_copy((*NewScattering)[Stmt]);
+
+ isl_union_map_add_map(schedule, scattering);
+ }
+
+ isl_union_map *temp_must_dep, *temp_may_dep;
+ isl_union_map *temp_must_no_source, *temp_may_no_source;
+
+ DEBUG(
+ dbgs().indent(4) << "Sink :=\n";
+ dbgs().indent(8) << stringFromIslObj(sink) << ";\n";
+
+ dbgs().indent(4) << "MustSource :=\n";
+ dbgs().indent(8) << stringFromIslObj(must_source) << ";\n";
+
+ dbgs().indent(4) << "MaySource :=\n";
+ dbgs().indent(8) << stringFromIslObj(may_source) << ";\n";
+
+ dbgs().indent(4) << "Schedule :=\n";
+ dbgs().indent(8) << stringFromIslObj(schedule) << ";\n";
+ );
+
+ isl_union_map_compute_flow(isl_union_map_copy(sink),
+ isl_union_map_copy(must_source),
+ isl_union_map_copy(may_source), schedule,
+ &temp_must_dep, &temp_may_dep,
+ &temp_must_no_source, &temp_may_no_source);
+
+ DEBUG(dbgs().indent(4) << "\nDependences calculated\n");
+ DEBUG(
+ dbgs().indent(4) << "TempMustDep:=\n";
+ dbgs().indent(8) << stringFromIslObj(temp_must_dep) << ";\n";
+
+ dbgs().indent(4) << "MustDep:=\n";
+ dbgs().indent(8) << stringFromIslObj(must_dep) << ";\n";
+ );
+
+ // Remove redundant statements.
+ temp_must_dep = isl_union_map_coalesce(temp_must_dep);
+ temp_may_dep = isl_union_map_coalesce(temp_may_dep);
+ temp_must_no_source = isl_union_map_coalesce(temp_must_no_source);
+ temp_may_no_source = isl_union_map_coalesce(temp_may_no_source);
+
+ if (!isl_union_map_is_equal(temp_must_dep, must_dep)) {
+ DEBUG(dbgs().indent(4) << "\nEqual 1 calculated\n");
+ return false;
+ }
+
+ DEBUG(dbgs().indent(4) << "\nEqual 1 calculated\n");
+
+ if (!isl_union_map_is_equal(temp_may_dep, may_dep))
+ return false;
+
+ DEBUG(dbgs().indent(4) << "\nEqual 2 calculated\n");
+
+ if (!isl_union_map_is_equal(temp_must_no_source, must_no_source))
+ return false;
+
+ if (!isl_union_map_is_equal(temp_may_no_source, may_no_source))
+ return false;
+
+ return true;
+}
+
+isl_union_map* getCombinedScheduleForDim(Scop *scop, unsigned dimLevel) {
+ isl_dim *dim = isl_dim_alloc(scop->getCtx(), scop->getNumParams(), 0, 0);
+
+ isl_union_map *schedule = isl_union_map_empty(dim);
+
+ for (Scop::iterator SI = scop->begin(), SE = scop->end(); SI != SE; ++SI) {
+ ScopStmt *Stmt = *SI;
+ isl_map *scattering = isl_map_copy(Stmt->getScattering());
+ unsigned remainingDimensions = isl_map_n_out(scattering) - dimLevel;
+ scattering = isl_map_project_out(scattering, isl_dim_out, dimLevel,
+ remainingDimensions);
+ isl_union_map_add_map(schedule, scattering);
+ }
+
+ return schedule;
+}
+
+bool Dependences::isParallelDimension(isl_set *loopDomain,
+ unsigned parallelDimension) {
+ Scop *S = &getCurScop();
+ isl_union_map *schedule = getCombinedScheduleForDim(S, parallelDimension);
+
+ // Calculate distance vector.
+ isl_union_set *scheduleSubset;
+ isl_union_map *scheduleDeps, *restrictedDeps;
+ isl_union_map *scheduleDeps_war, *restrictedDeps_war;
+ isl_union_map *scheduleDeps_waw, *restrictedDeps_waw;
+
+ scheduleSubset = isl_union_set_from_set(isl_set_copy(loopDomain));
+
+ scheduleDeps = isl_union_map_apply_range(isl_union_map_copy(must_dep),
+ isl_union_map_copy(schedule));
+ scheduleDeps = isl_union_map_apply_domain(scheduleDeps,
+ isl_union_map_copy(schedule));
+
+ scheduleDeps_war = isl_union_map_apply_range(isl_union_map_copy(war_dep),
+ isl_union_map_copy(schedule));
+ scheduleDeps_war = isl_union_map_apply_domain(scheduleDeps_war,
+ isl_union_map_copy(schedule));
+
+ scheduleDeps_waw = isl_union_map_apply_range(isl_union_map_copy(waw_dep),
+ isl_union_map_copy(schedule));
+ scheduleDeps_waw = isl_union_map_apply_domain(scheduleDeps_waw,
+ isl_union_map_copy(schedule));
+
+ // Dependences need to originate and to terminate in the scheduling space
+ // enumerated by this loop.
+ restrictedDeps = isl_union_map_intersect_domain(scheduleDeps,
+ isl_union_set_copy(scheduleSubset));
+ restrictedDeps = isl_union_map_intersect_range(restrictedDeps,
+ isl_union_set_copy(scheduleSubset));
+
+ isl_union_set *distance = isl_union_map_deltas(restrictedDeps);
+
+ restrictedDeps_war = isl_union_map_intersect_domain(scheduleDeps_war,
+ isl_union_set_copy(scheduleSubset));
+ restrictedDeps_war = isl_union_map_intersect_range(restrictedDeps_war,
+ isl_union_set_copy(scheduleSubset));
+
+ isl_union_set *distance_war = isl_union_map_deltas(restrictedDeps_war);
+
+ restrictedDeps_waw = isl_union_map_intersect_domain(scheduleDeps_waw,
+ isl_union_set_copy(scheduleSubset));
+ restrictedDeps_waw = isl_union_map_intersect_range(restrictedDeps_waw,
+ isl_union_set_copy(scheduleSubset));
+
+ isl_union_set *distance_waw = isl_union_map_deltas(restrictedDeps_waw);
+
+ isl_dim *dim = isl_dim_set_alloc(S->getCtx(), S->getNumParams(),
+ parallelDimension);
+
+ // [0, 0, 0, 0] - All zero
+ isl_basic_set *allZeroBS = isl_basic_set_universe(isl_dim_copy(dim));
+ unsigned dimensions = isl_dim_size(dim, isl_dim_set);
+
+ for (unsigned i = 0; i < dimensions; i++) {
+ isl_constraint *c = isl_equality_alloc(isl_dim_copy(dim));
+ isl_int v;
+ isl_int_init(v);
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, i, v);
+ allZeroBS = isl_basic_set_add_constraint(allZeroBS, c);
+ isl_int_clear(v);
+ }
+
+ isl_set *allZero = isl_set_from_basic_set(allZeroBS);
+
+ // All zero, last unknown.
+ // [0, 0, 0, ?]
+ isl_basic_set *lastUnknownBS = isl_basic_set_universe(isl_dim_copy(dim));
+ dimensions = isl_dim_size(dim, isl_dim_set);
+
+ for (unsigned i = 0; i < dimensions - 1; i++) {
+ isl_constraint *c = isl_equality_alloc(isl_dim_copy(dim));
+ isl_int v;
+ isl_int_init(v);
+ isl_int_set_si(v, -1);
+ isl_constraint_set_coefficient(c, isl_dim_set, i, v);
+ lastUnknownBS = isl_basic_set_add_constraint(lastUnknownBS, c);
+ isl_int_clear(v);
+ }
+
+ isl_set *lastUnknown = isl_set_from_basic_set(lastUnknownBS);
+
+ // Valid distance vectors
+ isl_set *validDistances = isl_set_subtract(lastUnknown, allZero);
+ validDistances = isl_set_complement(validDistances);
+ isl_union_set *validDistancesUS = isl_union_set_from_set(validDistances);
+
+ isl_union_set *nonValid = isl_union_set_subtract(distance,
+ isl_union_set_copy(validDistancesUS));
+
+ isl_union_set *nonValid_war = isl_union_set_subtract(distance_war,
+ isl_union_set_copy(validDistancesUS));
+
+ isl_union_set *nonValid_waw = isl_union_set_subtract(distance_waw,
+ validDistancesUS);
+
+ return isl_union_set_is_empty(nonValid)
+ && isl_union_set_is_empty(nonValid_war)
+ && isl_union_set_is_empty(nonValid_waw);
+}
+
+void Dependences::printScop(raw_ostream &OS) const {
+ OS.indent(4) << "Must dependences:\n";
+ OS.indent(8) << stringFromIslObj(must_dep) << "\n";
+
+ OS.indent(4) << "May dependences:\n";
+ OS.indent(8) << stringFromIslObj(may_dep) << "\n";
+
+ OS.indent(4) << "Must no source:\n";
+ OS.indent(8) << stringFromIslObj(must_no_source) << "\n";
+
+ OS.indent(4) << "May no source:\n";
+ OS.indent(8) << stringFromIslObj(may_no_source) << "\n";
+}
+
+void Dependences::releaseMemory() {
+ if (must_dep)
+ isl_union_map_free(must_dep);
+
+ if (may_dep)
+ isl_union_map_free(may_dep);
+
+ if (must_no_source)
+ isl_union_map_free(must_no_source);
+
+ if (may_no_source)
+ isl_union_map_free(may_no_source);
+
+ if (war_dep)
+ isl_union_map_free(war_dep);
+
+ if (waw_dep)
+ isl_union_map_free(waw_dep);
+
+ must_dep = may_dep = NULL;
+ must_no_source = may_no_source = NULL;
+ war_dep = waw_dep = NULL;
+
+ if (sink)
+ isl_union_map_free(sink);
+
+ if (must_source)
+ isl_union_map_free(must_source);
+
+ if (may_source)
+ isl_union_map_free(may_source);
+
+ sink = must_source = may_source = NULL;
+}
+
+void Dependences::getAnalysisUsage(AnalysisUsage &AU) const {
+ ScopPass::getAnalysisUsage(AU);
+}
+
+char Dependences::ID = 0;
+
+static RegisterPass<Dependences>
+X("polly-dependences", "Polly - Calculate dependences for Scop");
+
+Pass* polly::createDependencesPass() {
+ return new Dependences();
+}
OpenPOWER on IntegriCloud