forked from OSchip/llvm-project
Replace the dependences parallelism check by the IslAst one
llvm-svn: 214061
This commit is contained in:
parent
636b6a2fd7
commit
515f85770c
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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);
|
||||
// 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.
|
||||
bool Dependences::isParallel(isl_union_map *Schedule, isl_union_map *Deps) {
|
||||
isl_map *ScheduleDeps, *Test;
|
||||
unsigned Dimension, IsParallel;
|
||||
|
||||
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:
|
||||
//
|
||||
// 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.
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue