forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			187 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			187 lines
		
	
	
		
			5.4 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/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
 |