ScheduleOpt: Use band forest to get the schedules

isl introduced a new representation for the schedules it calculates. The new
representation uses a forest of bands and is closer to the structure of the
data as the old interface. Switch to the new interface, as it is nicer to use
and as the old interface will soon be removed from isl.

WARNING: This commit needs a version of isl that is more recent that the one
         included in CLooG. See:
	 http://polly.grosser.es/get_started.html#islTrunk
llvm-svn: 134181
This commit is contained in:
Tobias Grosser 2011-06-30 20:01:02 +00:00
parent 080307119e
commit de68cc91cf
3 changed files with 165 additions and 74 deletions

View File

@ -21,6 +21,7 @@ struct isl_map;
struct isl_union_map;
struct isl_set;
struct isl_union_set;
struct isl_schedule;
namespace polly {
@ -41,6 +42,8 @@ std::string stringFromIslObj(/*__isl_keep*/ isl_map *map);
std::string stringFromIslObj(/*__isl_keep*/ isl_union_map *umap);
std::string stringFromIslObj(/*__isl_keep*/ isl_set *set);
std::string stringFromIslObj(/*__isl_keep*/ isl_union_set *uset);
std::string stringFromIslObj(/*__isl_keep*/ isl_schedule *schedule);
//@}
} //end namespace polly

View File

@ -20,6 +20,7 @@
#include "polly/Cloog.h"
#include "polly/LinkAllPasses.h"
#include "polly/Support/GICHelper.h"
#include "polly/Dependences.h"
#include "polly/ScopInfo.h"
@ -27,6 +28,7 @@
#include "isl/map.h"
#include "isl/constraint.h"
#include "isl/schedule.h"
#include "isl/band.h"
#define DEBUG_TYPE "polly-optimize-isl"
#include "llvm/Support/Debug.h"
@ -91,57 +93,154 @@ static void extendScattering(Scop &S, unsigned scatDimensions) {
}
}
// @brief Tile a band.
// getTileMap - Create a map that describes a n-dimensonal tiling.
//
// This function recieves a map that assigns to the instances of a statement
// an execution time.
// getTileMap creates a map from a n-dimensional scattering space into an
// 2*n-dimensional scattering space. The map describes a rectangular tiling.
//
// [i_0, i_1, i_2] -> [o_0, o_1, o_2, i_0, i_1, i_2]:
// o_0 % 32 = 0 and o_1 % 32 = 0 and o_2 % 32 = 0
// and o0 <= i0 <= o0 + 32 and o1 <= i1 <= o1 + 32 and o2 <= i2 <= o2 + 32
// Example:
// scheduleDimensions = 2, parameterDimensions = 1, tileSize = 32
//
// tileMap := [p0] -> {[s0, s1] -> [t0, t1, s0, s1]:
// t0 % 32 = 0 and t0 <= s0 < t0 + 32 and
// t1 % 32 = 0 and t1 <= s1 < t1 + 32}
//
// Before tiling:
//
// for (i = 0; i < N; i++)
// for (j = 0; j < M; j++)
// S(i,j)
//
// After tiling:
//
// for (t_i = 0; t_i < N; i+=32)
// for (t_j = 0; t_j < M; j+=32)
// for (i = t_i; i < min(t_i + 32, N); i++) | Unknown that N % 32 = 0
// for (j = t_j; j < t_j + 32; j++) | Known that M % 32 = 0
// S(i,j)
//
static isl_basic_map *getTileMap(isl_ctx *ctx, int scheduleDimensions,
int parameterDimensions, int tileSize = 32) {
// We construct
//
// tileMap := [p0] -> {[s0, s1] -> [t0, t1, p0, p1, a0, a1]:
// s0 = a0 * 32 and s0 = p0 and t0 <= p0 < t0 + 32 and
// s1 = a1 * 32 and s1 = p1 and t1 <= p1 < t1 + 32}
//
// and project out the auxilary dimensions a0 and a1.
isl_dim *dim = isl_dim_alloc(ctx, parameterDimensions, scheduleDimensions,
scheduleDimensions * 3);
isl_basic_map *tileMap = isl_basic_map_universe(isl_dim_copy(dim));
static isl_map *tileBand(isl_map *band) {
int dimensions = isl_map_n_out(band);
int tileSize = 32;
isl_dim *dim = isl_dim_alloc(isl_map_get_ctx(band), isl_map_n_param(band),
dimensions, dimensions * 3);
isl_basic_map *tiledBand = isl_basic_map_universe(isl_dim_copy(dim));
for (int i = 0; i < dimensions; i++) {
isl_constraint *c = isl_equality_alloc(isl_dim_copy(dim));
isl_constraint_set_coefficient_si(c, isl_dim_out, i, 1);
isl_constraint_set_coefficient_si(c, isl_dim_out, 2 * dimensions + i,
-tileSize);
tiledBand = isl_basic_map_add_constraint(tiledBand, c);
for (int x = 0; x < scheduleDimensions; x++) {
int sX = x;
int tX = x;
int pX = scheduleDimensions + x;
int aX = 2 * scheduleDimensions + x;
isl_constraint *c;
// sX = aX * tileSize;
c = isl_equality_alloc(isl_dim_copy(dim));
isl_constraint_set_coefficient_si(c, isl_dim_in, i, -1);
isl_constraint_set_coefficient_si(c, isl_dim_out, dimensions + i, 1);
tiledBand = isl_basic_map_add_constraint(tiledBand, c);
isl_constraint_set_coefficient_si(c, isl_dim_out, sX, 1);
isl_constraint_set_coefficient_si(c, isl_dim_out, aX, -tileSize);
tileMap = isl_basic_map_add_constraint(tileMap, c);
c = isl_inequality_alloc(isl_dim_copy(dim));
isl_constraint_set_coefficient_si(c, isl_dim_out, i, -1);
isl_constraint_set_coefficient_si(c, isl_dim_out, dimensions + i, 1);
tiledBand = isl_basic_map_add_constraint(tiledBand, c);
// pX = sX;
c = isl_equality_alloc(isl_dim_copy(dim));
isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1);
isl_constraint_set_coefficient_si(c, isl_dim_in, sX, -1);
tileMap = isl_basic_map_add_constraint(tileMap, c);
// tX <= pX
c = isl_inequality_alloc(isl_dim_copy(dim));
isl_constraint_set_coefficient_si(c, isl_dim_out, i, 1);
isl_constraint_set_coefficient_si(c, isl_dim_out, dimensions + i, -1);
isl_constraint_set_coefficient_si(c, isl_dim_out, pX, 1);
isl_constraint_set_coefficient_si(c, isl_dim_out, tX, -1);
tileMap = isl_basic_map_add_constraint(tileMap, c);
// pX <= tX + (tileSize - 1)
c = isl_inequality_alloc(isl_dim_copy(dim));
isl_constraint_set_coefficient_si(c, isl_dim_out, tX, 1);
isl_constraint_set_coefficient_si(c, isl_dim_out, pX, -1);
isl_constraint_set_constant_si(c, tileSize - 1);
tiledBand = isl_basic_map_add_constraint(tiledBand, c);
tileMap = isl_basic_map_add_constraint(tileMap, c);
}
// Project out auxilary dimensions (introduced to ensure 'ii % tileSize = 0')
// Project out auxilary dimensions.
//
// The real dimensions are transformed into existentially quantified ones.
// This reduces the number of visible scattering dimensions. Also, Cloog
// produces better code, if auxilary dimensions are existentially quantified.
tiledBand = isl_basic_map_project_out(tiledBand, isl_dim_out, 2 * dimensions,
dimensions);
// The auxilary dimensions are transformed into existentially quantified ones.
// This reduces the number of visible scattering dimensions and allows Cloog
// to produces better code.
tileMap = isl_basic_map_project_out(tileMap, isl_dim_out,
2 * scheduleDimensions,
scheduleDimensions);
isl_dim_free(dim);
return tileMap;
}
return isl_map_apply_range(band, isl_map_from_basic_map(tiledBand));
isl_union_map *getTiledPartialSchedule(isl_band *band) {
isl_union_map *partialSchedule;
int scheduleDimensions, parameterDimensions;
isl_ctx *ctx;
isl_dim *dim;
isl_basic_map *tileMap;
isl_union_map *tileUnionMap;
partialSchedule = isl_band_get_partial_schedule(band);
ctx = isl_union_map_get_ctx(partialSchedule);
dim = isl_union_map_get_dim(partialSchedule);
scheduleDimensions = isl_band_n_member(band);
parameterDimensions = isl_dim_size(dim, isl_dim_param);
tileMap = getTileMap(ctx, scheduleDimensions, parameterDimensions);
tileUnionMap = isl_union_map_from_map(isl_map_from_basic_map(tileMap));
partialSchedule = isl_union_map_apply_range(partialSchedule, tileUnionMap);
isl_dim_free(dim);
isl_ctx_free(ctx);
return partialSchedule;
}
// tileBandList - Tile all bands contained in a band forest.
//
// Recursively walk the band forest and tile all bands in the forest. Return
// a schedule that describes the tiled scattering.
static isl_union_map *tileBandList(isl_band_list *blist) {
int numBands = isl_band_list_n_band(blist);
isl_union_map *finalSchedule = 0;
for (int i = 0; i < numBands; i++) {
isl_band *band;
isl_union_map *partialSchedule;
band = isl_band_list_get_band(blist, i);
partialSchedule = getTiledPartialSchedule(band);
if (isl_band_has_children(band)) {
isl_band_list *children = isl_band_get_children(band);
isl_union_map *suffixSchedule = tileBandList(children);
partialSchedule = isl_union_map_flat_range_product(partialSchedule,
suffixSchedule);
}
if (finalSchedule)
isl_union_map_union(finalSchedule, partialSchedule);
else
finalSchedule = partialSchedule;
isl_band_free(band);
}
return finalSchedule;
}
static isl_union_map *tileSchedule(isl_schedule *schedule) {
isl_band_list *blist = isl_schedule_get_band_forest(schedule);
isl_union_map *tiledSchedule = tileBandList(blist);
isl_band_list_free(blist);
return tiledSchedule;
}
bool ScheduleOptimizer::runOnScop(Scop &S) {
@ -179,57 +278,36 @@ bool ScheduleOptimizer::runOnScop(Scop &S) {
schedule = isl_union_set_compute_schedule(domain, validity, proximity);
// Get the complete schedule.
isl_union_map *scheduleMap = isl_schedule_get_map(schedule);
DEBUG(dbgs() << "Computed schedule: ");
DEBUG(isl_union_map_dump(scheduleMap));
DEBUG(dbgs() << stringFromIslObj(schedule));
DEBUG(dbgs() << "Individual bands: ");
// Get individual tileable bands.
for (int i = 0; i < isl_schedule_n_band(schedule); i++) {
isl_union_map *band = isl_schedule_get_band(schedule, i);
isl_union_map *tiledSchedule = tileSchedule(schedule);
DEBUG(dbgs() << "Band " << i << ": ");
DEBUG(isl_union_map_dump(band));
for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) {
ScopStmt *stmt = *SI;
for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI) {
ScopStmt *stmt = *SI;
if (stmt->isFinalRead())
continue;
isl_set *domain = stmt->getDomain();
isl_union_map *stmtBand;
stmtBand = isl_union_map_intersect_domain(isl_union_map_copy(band),
isl_union_set_from_set(domain));
isl_map *sband;
isl_union_map_foreach_map(stmtBand, getSingleMap, &sband);
sband = tileBand(sband);
DEBUG(dbgs() << "tiled band: ");
DEBUG(isl_map_dump(sband));
if (i == 0)
stmt->setScattering(sband);
else {
isl_map *scattering = stmt->getScattering();
scattering = isl_map_range_product(scattering, sband);
scattering = isl_map_flatten(scattering);
stmt->setScattering(scattering);
}
}
if (stmt->isFinalRead())
continue;
isl_set *domain = stmt->getDomain();
isl_union_map *stmtBand;
stmtBand = isl_union_map_intersect_domain(isl_union_map_copy(tiledSchedule),
isl_union_set_from_set(domain));
isl_map *stmtSchedule;
isl_union_map_foreach_map(stmtBand, getSingleMap, &stmtSchedule);
stmt->setScattering(stmtSchedule);
}
isl_union_map_free(tiledSchedule);
isl_schedule_free(schedule);
unsigned maxScatDims = 0;
for (Scop::iterator SI = S.begin(), SE = S.end(); SI != SE; ++SI)
maxScatDims = std::max(isl_map_n_out((*SI)->getScattering()), maxScatDims);
extendScattering(S, maxScatDims);
isl_schedule_free(schedule);
return false;
}

View File

@ -16,6 +16,7 @@
#include "isl/union_set.h"
#include "isl/map.h"
#include "isl/union_map.h"
#include "isl/schedule.h"
using namespace llvm;
@ -89,3 +90,12 @@ std::string polly::stringFromIslObj(/*__isl_keep*/ isl_union_set *uset) {
isl_printer_free(p);
return string;
}
std::string polly::stringFromIslObj(/*__isl_keep*/ isl_schedule *schedule) {
isl_ctx *ctx = isl_union_map_get_ctx(isl_schedule_get_map(schedule));
isl_printer *p = isl_printer_to_str(ctx);
isl_printer_print_schedule(p, schedule);
std::string string(isl_printer_get_str(p));
isl_printer_free(p);
return string;
}