forked from OSchip/llvm-project
274 lines
9.9 KiB
C++
274 lines
9.9 KiB
C++
//===- 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/Options.h"
|
|
#include "polly/ScopInfo.h"
|
|
#include "polly/Support/GICHelper.h"
|
|
|
|
#define DEBUG_TYPE "polly-opt-pluto"
|
|
#include "llvm/Support/Debug.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), cl::ZeroOrMore,
|
|
cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> EnableIntraTiling("polly-pluto-intratileopt",
|
|
cl::desc("Enable intratiling"),
|
|
cl::Hidden, cl::init(true),
|
|
cl::ZeroOrMore, cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoDebug("polly-pluto-debug",
|
|
cl::desc("Enable pluto debug"), cl::Hidden,
|
|
cl::init(false), cl::ZeroOrMore,
|
|
cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoMoreDebug("polly-pluto-moredebug",
|
|
cl::desc("Enable more pluto debugging"),
|
|
cl::Hidden, cl::init(false), cl::ZeroOrMore,
|
|
cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoParallel("polly-pluto-parallel",
|
|
cl::desc("Enable pluto parallel transforms"),
|
|
cl::Hidden, cl::init(false), cl::ZeroOrMore,
|
|
cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool>
|
|
PlutoInnerParallel("polly-pluto-innerpara",
|
|
cl::desc("Enable inner parallelism instead of piped."),
|
|
cl::Hidden, cl::init(false), cl::ZeroOrMore,
|
|
cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool>
|
|
PlutoIdentity("polly-pluto-identity",
|
|
cl::desc("Enable pluto identity transformation"), cl::Hidden,
|
|
cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoUnroll("polly-pluto-unroll",
|
|
cl::desc("Enable pluto unrolling"), cl::Hidden,
|
|
cl::init(false), cl::ZeroOrMore,
|
|
cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoRar("polly-pluto-rar",
|
|
cl::desc("Enable pluto rar deps"), cl::Hidden,
|
|
cl::init(false), cl::ZeroOrMore,
|
|
cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoParaPipe("polly-pluto-multipipe",
|
|
cl::desc("Enable multipipe parallelism"),
|
|
cl::Hidden, cl::init(false), cl::ZeroOrMore,
|
|
cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoL2Tile("polly-pluto-l2tile",
|
|
cl::desc("Enable L2 tiling"), cl::Hidden,
|
|
cl::init(false), cl::ZeroOrMore,
|
|
cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoPollyUnroll("polly-pluto-pollyunroll",
|
|
cl::desc("Enable pluto polly unrolling"),
|
|
cl::Hidden, cl::init(false),
|
|
cl::ZeroOrMore, cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool>
|
|
PlutoIslDep("polly-pluto-isldep",
|
|
cl::desc("Enable pluto isl dependency scanning"), cl::Hidden,
|
|
cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoIslDepCompact(
|
|
"polly-pluto-isldepcom", cl::desc("Enable pluto isl dependency compaction"),
|
|
cl::Hidden, cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoIslSolve("polly-pluto-islsolve",
|
|
cl::desc("Enable pluto isl solver"),
|
|
cl::Hidden, cl::init(false), cl::ZeroOrMore,
|
|
cl::cat(PollyCategory));
|
|
|
|
static cl::opt<bool> PlutoLastWriter("polly-pluto-lastwriter",
|
|
cl::desc("Enable pluto lastwriter"),
|
|
cl::Hidden, cl::init(false),
|
|
cl::ZeroOrMore, cl::cat(PollyCategory));
|
|
|
|
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->debug = PlutoDebug;
|
|
Options->fuse = 2;
|
|
Options->identity = PlutoIdentity;
|
|
Options->innerpar = PlutoInnerParallel;
|
|
Options->intratileopt = EnableIntraTiling;
|
|
Options->isldep = PlutoIslDep;
|
|
Options->isldepcompact = PlutoIslDepCompact;
|
|
Options->islsolve = PlutoIslSolve;
|
|
Options->l2tile = PlutoL2Tile;
|
|
Options->lastwriter = PlutoLastWriter;
|
|
Options->moredebug = PlutoMoreDebug;
|
|
Options->multipipe = PlutoParaPipe;
|
|
Options->parallel = PlutoParallel;
|
|
Options->polyunroll = PlutoPollyUnroll;
|
|
Options->rar = PlutoRar;
|
|
Options->tile = EnableTiling;
|
|
Options->unroll = PlutoUnroll;
|
|
|
|
DEBUG(dbgs() << "Domain: " << stringFromIslObj(Domain) << "\n";
|
|
dbgs() << "Dependences: " << stringFromIslObj(Deps) << "\n";);
|
|
Schedule = pluto_schedule(Domain, Deps, Options);
|
|
pluto_options_free(Options);
|
|
|
|
isl_union_set_free(Domain);
|
|
isl_union_map_free(Deps);
|
|
|
|
if (!Schedule)
|
|
return false;
|
|
|
|
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>();
|
|
}
|
|
|
|
Pass *polly::createPlutoOptimizerPass() { return new PlutoOptimizer(); }
|
|
|
|
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)
|
|
|
|
#endif // PLUTO_FOUND
|