diff options
Diffstat (limited to 'polly/lib/Pluto.cpp')
-rw-r--r-- | polly/lib/Pluto.cpp | 186 |
1 files changed, 186 insertions, 0 deletions
diff --git a/polly/lib/Pluto.cpp b/polly/lib/Pluto.cpp new file mode 100644 index 00000000000..5e78a54d292 --- /dev/null +++ b/polly/lib/Pluto.cpp @@ -0,0 +1,186 @@ +//===- Pluto.cpp - Calculate an optimized schedule ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Use libpluto to optimize the schedule. +// +//===----------------------------------------------------------------------===// + +#include "polly/Config/config.h" + +#ifdef PLUTO_FOUND +#include "polly/CodeGen/CodeGeneration.h" +#include "polly/Dependences.h" +#include "polly/LinkAllPasses.h" +#include "polly/ScopInfo.h" + +#define DEBUG_TYPE "polly-opt-pluto" +#include "llvm/Support/Debug.h" +#include "llvm/Support/CommandLine.h" + +#include "pluto/libpluto.h" +#include "isl/map.h" + + +using namespace llvm; +using namespace polly; + +static cl::opt<bool> +EnableTiling("polly-pluto-tile", + cl::desc("Enable tiling"), + cl::Hidden, cl::init(false)); + +namespace { +/// Convert an int into a string. +static std::string convertInt(int number) +{ + if (number == 0) + return "0"; + std::string temp = ""; + std::string returnvalue = ""; + while (number > 0) + { + temp += number % 10 + 48; + number /= 10; + } + for (unsigned i = 0; i < temp.length(); i++) + returnvalue+=temp[temp.length() - i - 1]; + return returnvalue; +} + + + class PlutoOptimizer : public ScopPass { + + public: + static char ID; + explicit PlutoOptimizer() : ScopPass(ID) {} + + virtual bool runOnScop(Scop &S); + void printScop(llvm::raw_ostream &OS) const; + void getAnalysisUsage(AnalysisUsage &AU) const; + static void extendScattering(Scop &S, unsigned NewDimensions); + }; +} + +char PlutoOptimizer::ID = 0; + +static int getSingleMap(__isl_take isl_map *map, void *user) { + isl_map **singleMap = (isl_map **) user; + *singleMap = map; + + return 0; +} + +void PlutoOptimizer::extendScattering(Scop &S, unsigned NewDimensions) { + for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) { + ScopStmt *Stmt = *SI; + unsigned OldDimensions = Stmt->getNumScattering(); + isl_space *Space; + isl_map *Map, *New; + + Space = isl_space_alloc(Stmt->getIslCtx(), 0, OldDimensions, NewDimensions); + Map = isl_map_universe(Space); + + for (unsigned i = 0; i < OldDimensions; i++) + Map = isl_map_equate(Map, isl_dim_in, i, isl_dim_out, i); + + for (unsigned i = OldDimensions; i < NewDimensions; i++) + Map = isl_map_fix_si(Map, isl_dim_out, i, 0); + + + Map = isl_map_align_params(Map, S.getParamSpace()); + New = isl_map_apply_range(Stmt->getScattering(), Map); + Stmt->setScattering(New); + } +} + +bool PlutoOptimizer::runOnScop(Scop &S) { + isl_union_set *Domain; + isl_union_map *Deps, *ToPlutoNames, *Schedule; + PlutoOptions *Options; + + Dependences *D = &getAnalysis<Dependences>(); + + int DependencesKinds = Dependences::TYPE_RAW | Dependences::TYPE_WAR + | Dependences::TYPE_WAW; + + Deps = D->getDependences(DependencesKinds); + Domain = S.getDomains(); + ToPlutoNames = isl_union_map_empty(S.getParamSpace()); + + int counter = 0; + for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) { + ScopStmt *Stmt = *SI; + std::string Name = "S_" + convertInt(counter); + isl_map *Identity = isl_map_identity(isl_space_map_from_domain_and_range( + Stmt->getDomainSpace(), Stmt->getDomainSpace())); + Identity = isl_map_set_tuple_name(Identity, isl_dim_out, Name.c_str()); + ToPlutoNames = isl_union_map_add_map(ToPlutoNames, Identity); + counter++; + } + + Deps = isl_union_map_apply_domain(Deps, isl_union_map_copy(ToPlutoNames)); + Deps = isl_union_map_apply_range(Deps, isl_union_map_copy(ToPlutoNames)); + Domain = isl_union_set_apply(Domain, isl_union_map_copy(ToPlutoNames)); + + Options = pluto_options_alloc(); + Options->fuse = 0; + Options->tile = EnableTiling; + + Schedule = pluto_schedule(Domain, Deps, Options); + pluto_options_free(Options); + + isl_union_set_free(Domain); + isl_union_map_free(Deps); + + Schedule = isl_union_map_apply_domain(Schedule, + isl_union_map_reverse(ToPlutoNames)); + + for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) { + ScopStmt *Stmt = *SI; + isl_set *Domain = Stmt->getDomain(); + isl_union_map *StmtBand; + StmtBand = isl_union_map_intersect_domain(isl_union_map_copy(Schedule), + isl_union_set_from_set(Domain)); + isl_map *StmtSchedule; + isl_union_map_foreach_map(StmtBand, getSingleMap, &StmtSchedule); + Stmt->setScattering(StmtSchedule); + isl_union_map_free(StmtBand); + } + + isl_union_map_free(Schedule); + + unsigned MaxScatDims = 0; + + for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) + MaxScatDims = std::max((*SI)->getNumScattering(), MaxScatDims); + + extendScattering(S, MaxScatDims); + return false; +} + +void PlutoOptimizer::printScop(raw_ostream &OS) const { +} + +void PlutoOptimizer::getAnalysisUsage(AnalysisUsage &AU) const { + ScopPass::getAnalysisUsage(AU); + AU.addRequired<Dependences>(); +} + +INITIALIZE_PASS_BEGIN(PlutoOptimizer, "polly-opt-pluto", + "Polly - Optimize schedule of SCoP (Pluto)", false, false) +INITIALIZE_PASS_DEPENDENCY(Dependences) +INITIALIZE_PASS_DEPENDENCY(ScopInfo) +INITIALIZE_PASS_END(PlutoOptimizer, "polly-opt-pluto", + "Polly - Optimize schedule of SCoP (Pluto)", false, false) + +Pass* polly::createPlutoOptimizerPass() { + return new PlutoOptimizer(); +} + +#endif // PLUTO_FOUND |