Replace the dependences parallelism check by the IslAst one

llvm-svn: 214061
This commit is contained in:
Johannes Doerfert 2014-07-28 03:46:28 +00:00
parent 636b6a2fd7
commit 515f85770c
4 changed files with 60 additions and 121 deletions

View File

@ -85,17 +85,15 @@ public:
// dependences.
bool isValidScattering(StatementToIslMapTy *NewScatterings);
/// @brief Check if a dimension of the Scop can be executed in parallel.
/// @brief Check if a partial schedule is parallel wrt to @p Deps.
///
/// @param LoopDomain The subset of the scattering space that is executed in
/// parallel.
/// @param ParallelDimension The scattering dimension that is being executed
/// in parallel.
/// @param Schedule The subset of the scattering space that we want to check.
/// @param Deps The dependences @p Schedule needs to respect.
///
/// @return bool Returns true, if executing parallelDimension in parallel is
/// valid for the scattering domain subset given.
bool isParallelDimension(__isl_take isl_set *LoopDomain,
unsigned ParallelDimension);
/// @return Returns true, if executing parallel the outermost dimension of
/// @p Schedule is valid according to the dependences @p Deps.
bool isParallel(__isl_keep isl_union_map *Schedule,
__isl_take isl_union_map *Deps);
/// @brief Get the dependences in this Scop.
///

View File

@ -437,76 +437,43 @@ bool Dependences::isValidScattering(StatementToIslMapTy *NewScattering) {
return IsValid;
}
isl_union_map *getCombinedScheduleForSpace(Scop *scop, unsigned dimLevel) {
isl_space *Space = scop->getParamSpace();
isl_union_map *schedule = isl_union_map_empty(Space);
for (ScopStmt *Stmt : *scop) {
unsigned remainingDimensions = Stmt->getNumScattering() - dimLevel;
isl_map *Scattering = isl_map_project_out(
Stmt->getScattering(), isl_dim_out, dimLevel, remainingDimensions);
schedule = isl_union_map_add_map(schedule, Scattering);
}
return schedule;
}
bool Dependences::isParallelDimension(__isl_take isl_set *ScheduleSubset,
unsigned ParallelDim) {
// To check if a loop is parallel, we perform the following steps:
// Check if the current scheduling dimension is parallel.
//
// o Move dependences from 'Domain -> Domain' to 'Schedule -> Schedule' space.
// o Limit dependences to the schedule space enumerated by the loop.
// o Calculate distances of the dependences.
// o Check if one of the distances is invalid in presence of parallelism.
// We check for parallelism by verifying that the loop does not carry any
// dependences.
//
// Parallelism test: if the distance is zero in all outer dimensions, then it
// has to be zero in the current dimension as well.
//
// Implementation: first, translate dependences into time space, then force
// outer dimensions to be equal. If the distance is zero in the current
// dimension, then the loop is parallel. The distance is zero in the current
// dimension if it is a subset of a map with equal values for the current
// dimension.
bool Dependences::isParallel(isl_union_map *Schedule, isl_union_map *Deps) {
isl_map *ScheduleDeps, *Test;
unsigned Dimension, IsParallel;
isl_union_map *Schedule, *Deps;
isl_map *ScheduleDeps;
Scop *S = &getCurScop();
if (!hasValidDependences()) {
isl_set_free(ScheduleSubset);
return false;
}
// FIXME: We can remove ignore reduction dependences in case we privatize the
// memory locations the reduction statements reduce into.
Deps = getDependences(TYPE_RAW | TYPE_WAW | TYPE_WAR | TYPE_RED);
if (isl_union_map_is_empty(Deps)) {
isl_union_map_free(Deps);
isl_set_free(ScheduleSubset);
return true;
}
Schedule = getCombinedScheduleForSpace(S, ParallelDim);
Deps = isl_union_map_apply_range(Deps, isl_union_map_copy(Schedule));
Deps = isl_union_map_apply_domain(Deps, Schedule);
Deps = isl_union_map_apply_domain(Deps, isl_union_map_copy(Schedule));
if (isl_union_map_is_empty(Deps)) {
isl_union_map_free(Deps);
isl_set_free(ScheduleSubset);
return true;
}
ScheduleDeps = isl_map_from_union_map(Deps);
ScheduleDeps =
isl_map_intersect_domain(ScheduleDeps, isl_set_copy(ScheduleSubset));
ScheduleDeps = isl_map_intersect_range(ScheduleDeps, ScheduleSubset);
Dimension = isl_map_dim(ScheduleDeps, isl_dim_out) - 1;
isl_set *Distances = isl_map_deltas(ScheduleDeps);
isl_space *Space = isl_set_get_space(Distances);
isl_set *Invalid = isl_set_universe(Space);
for (unsigned i = 0; i < Dimension; i++)
ScheduleDeps = isl_map_equate(ScheduleDeps, isl_dim_out, i, isl_dim_in, i);
// [0, ..., 0, +] - All zeros and last dimension larger than zero
for (unsigned i = 0; i < ParallelDim - 1; i++)
Invalid = isl_set_fix_si(Invalid, isl_dim_set, i, 0);
Test = isl_map_universe(isl_map_get_space(ScheduleDeps));
Test = isl_map_equate(Test, isl_dim_out, Dimension, isl_dim_in, Dimension);
IsParallel = isl_map_is_subset(ScheduleDeps, Test);
Invalid = isl_set_lower_bound_si(Invalid, isl_dim_set, ParallelDim - 1, 1);
Invalid = isl_set_intersect(Invalid, Distances);
bool IsParallel = isl_set_is_empty(Invalid);
isl_set_free(Invalid);
isl_map_free(Test);
isl_map_free(ScheduleDeps);
return IsParallel;
}

View File

@ -861,13 +861,35 @@ void ClastStmtCodeGen::codegenForVector(const clast_for *F) {
ClastVars.erase(F->iterator);
}
static isl_union_map *getCombinedScheduleForSpace(Scop *S, unsigned dimLevel) {
isl_space *Space = S->getParamSpace();
isl_union_map *schedule = isl_union_map_empty(Space);
for (ScopStmt *Stmt : *S) {
unsigned remainingDimensions = Stmt->getNumScattering() - dimLevel;
isl_map *Scattering = isl_map_project_out(
Stmt->getScattering(), isl_dim_out, dimLevel, remainingDimensions);
schedule = isl_union_map_add_map(schedule, Scattering);
}
return schedule;
}
bool ClastStmtCodeGen::isParallelFor(const clast_for *f) {
isl_set *Domain = isl_set_copy(isl_set_from_cloog_domain(f->domain));
assert(Domain && "Cannot access domain of loop");
Dependences &D = P->getAnalysis<Dependences>();
return D.isParallelDimension(Domain, isl_set_n_dim(Domain));
isl_union_map *Deps =
D.getDependences(Dependences::TYPE_RAW | Dependences::TYPE_WAW |
Dependences::TYPE_WAR | Dependences::TYPE_RAW);
isl_union_map *Schedule =
getCombinedScheduleForSpace(S, isl_set_n_dim(Domain));
Schedule =
isl_union_map_intersect_range(Schedule, isl_union_set_from_set(Domain));
bool IsParallel = D.isParallel(Schedule, Deps);
isl_union_map_free(Schedule);
return IsParallel;
}
void ClastStmtCodeGen::codegen(const clast_for *f) {

View File

@ -139,56 +139,6 @@ printFor(__isl_take isl_printer *Printer,
return Printer;
}
// Check if the current scheduling dimension is parallel.
//
// We check for parallelism by verifying that the loop does not carry any
// dependences.
//
// Parallelism test: if the distance is zero in all outer dimensions, then it
// has to be zero in the current dimension as well.
//
// Implementation: first, translate dependences into time space, then force
// outer dimensions to be equal. If the distance is zero in the current
// dimension, then the loop is parallel. The distance is zero in the current
// dimension if it is a subset of a map with equal values for the current
// dimension.
static bool astScheduleDimIsParallel(__isl_keep isl_ast_build *Build,
__isl_take isl_union_map *Deps) {
isl_union_map *Schedule;
isl_map *ScheduleDeps, *Test;
isl_space *ScheduleSpace;
unsigned Dimension, IsParallel;
Schedule = isl_ast_build_get_schedule(Build);
ScheduleSpace = isl_ast_build_get_schedule_space(Build);
Dimension = isl_space_dim(ScheduleSpace, isl_dim_out) - 1;
Deps = isl_union_map_apply_range(Deps, isl_union_map_copy(Schedule));
Deps = isl_union_map_apply_domain(Deps, Schedule);
if (isl_union_map_is_empty(Deps)) {
isl_union_map_free(Deps);
isl_space_free(ScheduleSpace);
return true;
}
ScheduleDeps = isl_map_from_union_map(Deps);
for (unsigned i = 0; i < Dimension; i++)
ScheduleDeps = isl_map_equate(ScheduleDeps, isl_dim_out, i, isl_dim_in, i);
Test = isl_map_universe(isl_map_get_space(ScheduleDeps));
Test = isl_map_equate(Test, isl_dim_out, Dimension, isl_dim_in, Dimension);
IsParallel = isl_map_is_subset(ScheduleDeps, Test);
isl_space_free(ScheduleSpace);
isl_map_free(Test);
isl_map_free(ScheduleDeps);
return IsParallel;
}
/// @brief Check if the current scheduling dimension is parallel
///
/// In case the dimension is parallel we also check if any reduction
@ -205,15 +155,17 @@ static bool astScheduleDimIsParallel(__isl_keep isl_ast_build *Build,
if (!D->hasValidDependences())
return false;
isl_union_map *Schedule = isl_ast_build_get_schedule(Build);
isl_union_map *Deps = D->getDependences(
Dependences::TYPE_RAW | Dependences::TYPE_WAW | Dependences::TYPE_WAR);
if (!astScheduleDimIsParallel(Build, Deps))
if (!D->isParallel(Schedule, Deps) && !isl_union_map_free(Schedule))
return false;
isl_union_map *RedDeps = D->getDependences(Dependences::TYPE_TC_RED);
if (!astScheduleDimIsParallel(Build, RedDeps))
if (!D->isParallel(Schedule, RedDeps))
IsReductionParallel = true;
isl_union_map_free(Schedule);
return true;
}