mirror of
https://github.com/intel/llvm.git
synced 2026-01-28 01:04:49 +08:00
[ScheduleOptimizer] Move isolateFullPartialTiles and isolateAndUnrollMatMulInnerLoops to C++
llvm-svn: 305676
This commit is contained in:
@@ -124,8 +124,8 @@ public:
|
||||
/// @param Node A schedule node band, which is a parent of a band node,
|
||||
/// that contains a vector loop.
|
||||
/// @return Modified isl_schedule_node.
|
||||
static __isl_give isl_schedule_node *
|
||||
isolateFullPartialTiles(__isl_take isl_schedule_node *Node, int VectorWidth);
|
||||
static isl::schedule_node isolateFullPartialTiles(isl::schedule_node Node,
|
||||
int VectorWidth);
|
||||
|
||||
private:
|
||||
/// Tile a schedule node.
|
||||
|
||||
@@ -2033,6 +2033,7 @@ public:
|
||||
inline isl::schedule_node ancestor(int generation) const;
|
||||
inline isl::boolean band_member_get_coincident(int pos) const;
|
||||
inline isl::schedule_node band_member_set_coincident(int pos, int coincident) const;
|
||||
inline isl::schedule_node band_set_ast_build_options(isl::union_set options) const;
|
||||
inline isl::schedule_node child(int pos) const;
|
||||
inline isl::set context_get_context() const;
|
||||
inline isl::schedule_node cut() const;
|
||||
@@ -9959,6 +9960,11 @@ isl::schedule_node schedule_node::band_member_set_coincident(int pos, int coinci
|
||||
return manage(res);
|
||||
}
|
||||
|
||||
isl::schedule_node schedule_node::band_set_ast_build_options(isl::union_set options) const {
|
||||
auto res = isl_schedule_node_band_set_ast_build_options(copy(), options.release());
|
||||
return manage(res);
|
||||
}
|
||||
|
||||
isl::schedule_node schedule_node::child(int pos) const {
|
||||
auto res = isl_schedule_node_child(copy(), pos);
|
||||
return manage(res);
|
||||
|
||||
@@ -236,79 +236,76 @@ static cl::opt<bool> OptimizedScops(
|
||||
"transformations is applied on the schedule tree"),
|
||||
cl::init(false), cl::ZeroOrMore, cl::cat(PollyCategory));
|
||||
|
||||
/// Create an isl_union_set, which describes the isolate option based on
|
||||
/// IsoalteDomain.
|
||||
/// Create an isl::union_set, which describes the isolate option based on
|
||||
/// IsolateDomain.
|
||||
///
|
||||
/// @param IsolateDomain An isl_set whose @p OutDimsNum last dimensions should
|
||||
/// @param IsolateDomain An isl::set whose @p OutDimsNum last dimensions should
|
||||
/// belong to the current band node.
|
||||
/// @param OutDimsNum A number of dimensions that should belong to
|
||||
/// the current band node.
|
||||
static __isl_give isl_union_set *
|
||||
getIsolateOptions(__isl_take isl_set *IsolateDomain, unsigned OutDimsNum) {
|
||||
auto Dims = isl_set_dim(IsolateDomain, isl_dim_set);
|
||||
static isl::union_set getIsolateOptions(isl::set IsolateDomain,
|
||||
unsigned OutDimsNum) {
|
||||
unsigned Dims = IsolateDomain.dim(isl::dim::set);
|
||||
assert(OutDimsNum <= Dims &&
|
||||
"The isl_set IsolateDomain is used to describe the range of schedule "
|
||||
"dimensions values, which should be isolated. Consequently, the "
|
||||
"number of its dimensions should be greater than or equal to the "
|
||||
"number of the schedule dimensions.");
|
||||
auto *IsolateRelation = isl_map_from_domain(IsolateDomain);
|
||||
IsolateRelation =
|
||||
isl_map_move_dims(IsolateRelation, isl_dim_out, 0, isl_dim_in,
|
||||
Dims - OutDimsNum, OutDimsNum);
|
||||
auto *IsolateOption = isl_map_wrap(IsolateRelation);
|
||||
auto *Id = isl_id_alloc(isl_set_get_ctx(IsolateOption), "isolate", nullptr);
|
||||
return isl_union_set_from_set(isl_set_set_tuple_id(IsolateOption, Id));
|
||||
isl::map IsolateRelation = isl::map::from_domain(IsolateDomain);
|
||||
IsolateRelation = IsolateRelation.move_dims(isl::dim::out, 0, isl::dim::in,
|
||||
Dims - OutDimsNum, OutDimsNum);
|
||||
isl::set IsolateOption = IsolateRelation.wrap();
|
||||
isl::id Id = isl::id::alloc(IsolateOption.get_ctx(), "isolate", nullptr);
|
||||
IsolateOption = IsolateOption.set_tuple_id(Id);
|
||||
return isl::union_set(IsolateOption);
|
||||
}
|
||||
|
||||
/// Create an isl_union_set, which describes the atomic option for the dimension
|
||||
/// of the current node.
|
||||
/// Create an isl::union_set, which describes the atomic option for the
|
||||
/// dimension of the current node.
|
||||
///
|
||||
/// It may help to reduce the size of generated code.
|
||||
///
|
||||
/// @param Ctx An isl_ctx, which is used to create the isl_union_set.
|
||||
static __isl_give isl_union_set *getAtomicOptions(isl_ctx *Ctx) {
|
||||
auto *Space = isl_space_set_alloc(Ctx, 0, 1);
|
||||
auto *AtomicOption = isl_set_universe(Space);
|
||||
auto *Id = isl_id_alloc(Ctx, "atomic", nullptr);
|
||||
return isl_union_set_from_set(isl_set_set_tuple_id(AtomicOption, Id));
|
||||
/// @param Ctx An isl::ctx, which is used to create the isl::union_set.
|
||||
static isl::union_set getAtomicOptions(isl::ctx Ctx) {
|
||||
isl::space Space(Ctx, 0, 1);
|
||||
isl::set AtomicOption = isl::set::universe(Space);
|
||||
isl::id Id = isl::id::alloc(Ctx, "atomic", nullptr);
|
||||
AtomicOption = AtomicOption.set_tuple_id(Id);
|
||||
return isl::union_set(AtomicOption);
|
||||
}
|
||||
|
||||
/// Create an isl_union_set, which describes the option of the form
|
||||
/// Create an isl::union_set, which describes the option of the form
|
||||
/// [isolate[] -> unroll[x]].
|
||||
///
|
||||
/// @param Ctx An isl_ctx, which is used to create the isl_union_set.
|
||||
static __isl_give isl_union_set *getUnrollIsolatedSetOptions(isl_ctx *Ctx) {
|
||||
auto *Space = isl_space_alloc(Ctx, 0, 0, 1);
|
||||
auto *UnrollIsolatedSetOption = isl_map_universe(Space);
|
||||
auto *DimInId = isl_id_alloc(Ctx, "isolate", nullptr);
|
||||
auto *DimOutId = isl_id_alloc(Ctx, "unroll", nullptr);
|
||||
/// @param Ctx An isl::ctx, which is used to create the isl::union_set.
|
||||
static isl::union_set getUnrollIsolatedSetOptions(isl::ctx Ctx) {
|
||||
isl::space Space = isl::space(Ctx, 0, 0, 1);
|
||||
isl::map UnrollIsolatedSetOption = isl::map::universe(Space);
|
||||
isl::id DimInId = isl::id::alloc(Ctx, "isolate", nullptr);
|
||||
isl::id DimOutId = isl::id::alloc(Ctx, "unroll", nullptr);
|
||||
UnrollIsolatedSetOption =
|
||||
isl_map_set_tuple_id(UnrollIsolatedSetOption, isl_dim_in, DimInId);
|
||||
UnrollIsolatedSetOption.set_tuple_id(isl::dim::in, DimInId);
|
||||
UnrollIsolatedSetOption =
|
||||
isl_map_set_tuple_id(UnrollIsolatedSetOption, isl_dim_out, DimOutId);
|
||||
return isl_union_set_from_set(isl_map_wrap(UnrollIsolatedSetOption));
|
||||
UnrollIsolatedSetOption.set_tuple_id(isl::dim::out, DimOutId);
|
||||
return UnrollIsolatedSetOption.wrap();
|
||||
}
|
||||
|
||||
/// Make the last dimension of Set to take values from 0 to VectorWidth - 1.
|
||||
///
|
||||
/// @param Set A set, which should be modified.
|
||||
/// @param VectorWidth A parameter, which determines the constraint.
|
||||
static __isl_give isl_set *addExtentConstraints(__isl_take isl_set *Set,
|
||||
int VectorWidth) {
|
||||
auto Dims = isl_set_dim(Set, isl_dim_set);
|
||||
auto Space = isl_set_get_space(Set);
|
||||
auto *LocalSpace = isl_local_space_from_space(Space);
|
||||
auto *ExtConstr =
|
||||
isl_constraint_alloc_inequality(isl_local_space_copy(LocalSpace));
|
||||
ExtConstr = isl_constraint_set_constant_si(ExtConstr, 0);
|
||||
ExtConstr =
|
||||
isl_constraint_set_coefficient_si(ExtConstr, isl_dim_set, Dims - 1, 1);
|
||||
Set = isl_set_add_constraint(Set, ExtConstr);
|
||||
ExtConstr = isl_constraint_alloc_inequality(LocalSpace);
|
||||
ExtConstr = isl_constraint_set_constant_si(ExtConstr, VectorWidth - 1);
|
||||
ExtConstr =
|
||||
isl_constraint_set_coefficient_si(ExtConstr, isl_dim_set, Dims - 1, -1);
|
||||
return isl_set_add_constraint(Set, ExtConstr);
|
||||
static isl::set addExtentConstraints(isl::set Set, int VectorWidth) {
|
||||
unsigned Dims = Set.dim(isl::dim::set);
|
||||
isl::space Space = Set.get_space();
|
||||
isl::local_space LocalSpace = isl::local_space(Space);
|
||||
isl::constraint ExtConstr = isl::constraint::alloc_inequality(LocalSpace);
|
||||
ExtConstr = ExtConstr.set_constant_si(0);
|
||||
ExtConstr = ExtConstr.set_coefficient_si(isl::dim::set, Dims - 1, 1);
|
||||
Set = Set.add_constraint(ExtConstr);
|
||||
ExtConstr = isl::constraint::alloc_inequality(LocalSpace);
|
||||
ExtConstr = ExtConstr.set_constant_si(VectorWidth - 1);
|
||||
ExtConstr = ExtConstr.set_coefficient_si(isl::dim::set, Dims - 1, -1);
|
||||
return Set.add_constraint(ExtConstr);
|
||||
}
|
||||
|
||||
/// Build the desired set of partial tile prefixes.
|
||||
@@ -326,34 +323,31 @@ static __isl_give isl_set *addExtentConstraints(__isl_take isl_set *Set,
|
||||
///
|
||||
/// @param ScheduleRange A range of a map, which describes a prefix schedule
|
||||
/// relation.
|
||||
static __isl_give isl_set *
|
||||
getPartialTilePrefixes(__isl_take isl_set *ScheduleRange, int VectorWidth) {
|
||||
auto Dims = isl_set_dim(ScheduleRange, isl_dim_set);
|
||||
auto *LoopPrefixes = isl_set_project_out(isl_set_copy(ScheduleRange),
|
||||
isl_dim_set, Dims - 1, 1);
|
||||
auto *ExtentPrefixes =
|
||||
isl_set_add_dims(isl_set_copy(LoopPrefixes), isl_dim_set, 1);
|
||||
static isl::set getPartialTilePrefixes(isl::set ScheduleRange,
|
||||
int VectorWidth) {
|
||||
unsigned Dims = ScheduleRange.dim(isl::dim::set);
|
||||
isl::set LoopPrefixes = ScheduleRange.project_out(isl::dim::set, Dims - 1, 1);
|
||||
isl::set ExtentPrefixes = LoopPrefixes.add_dims(isl::dim::set, 1);
|
||||
ExtentPrefixes = addExtentConstraints(ExtentPrefixes, VectorWidth);
|
||||
auto *BadPrefixes = isl_set_subtract(ExtentPrefixes, ScheduleRange);
|
||||
BadPrefixes = isl_set_project_out(BadPrefixes, isl_dim_set, Dims - 1, 1);
|
||||
return isl_set_subtract(LoopPrefixes, BadPrefixes);
|
||||
isl::set BadPrefixes = ExtentPrefixes.subtract(ScheduleRange);
|
||||
BadPrefixes = BadPrefixes.project_out(isl::dim::set, Dims - 1, 1);
|
||||
return LoopPrefixes.subtract(BadPrefixes);
|
||||
}
|
||||
|
||||
__isl_give isl_schedule_node *ScheduleTreeOptimizer::isolateFullPartialTiles(
|
||||
__isl_take isl_schedule_node *Node, int VectorWidth) {
|
||||
assert(isl_schedule_node_get_type(Node) == isl_schedule_node_band);
|
||||
Node = isl_schedule_node_child(Node, 0);
|
||||
Node = isl_schedule_node_child(Node, 0);
|
||||
auto *SchedRelUMap = isl_schedule_node_get_prefix_schedule_relation(Node);
|
||||
auto *ScheduleRelation = isl_map_from_union_map(SchedRelUMap);
|
||||
auto *ScheduleRange = isl_map_range(ScheduleRelation);
|
||||
auto *IsolateDomain = getPartialTilePrefixes(ScheduleRange, VectorWidth);
|
||||
auto *AtomicOption = getAtomicOptions(isl_set_get_ctx(IsolateDomain));
|
||||
auto *IsolateOption = getIsolateOptions(IsolateDomain, 1);
|
||||
Node = isl_schedule_node_parent(Node);
|
||||
Node = isl_schedule_node_parent(Node);
|
||||
auto *Options = isl_union_set_union(IsolateOption, AtomicOption);
|
||||
Node = isl_schedule_node_band_set_ast_build_options(Node, Options);
|
||||
isl::schedule_node
|
||||
ScheduleTreeOptimizer::isolateFullPartialTiles(isl::schedule_node Node,
|
||||
int VectorWidth) {
|
||||
assert(isl_schedule_node_get_type(Node.get()) == isl_schedule_node_band);
|
||||
Node = Node.child(0).child(0);
|
||||
isl::union_map SchedRelUMap = Node.get_prefix_schedule_relation();
|
||||
isl::map ScheduleRelation = isl::map::from_union_map(SchedRelUMap);
|
||||
isl::set ScheduleRange = ScheduleRelation.range();
|
||||
isl::set IsolateDomain = getPartialTilePrefixes(ScheduleRange, VectorWidth);
|
||||
isl::union_set AtomicOption = getAtomicOptions(IsolateDomain.get_ctx());
|
||||
isl::union_set IsolateOption = getIsolateOptions(IsolateDomain, 1);
|
||||
Node = Node.parent().parent();
|
||||
isl::union_set Options = IsolateOption.unite(AtomicOption);
|
||||
Node = Node.band_set_ast_build_options(Options);
|
||||
return Node;
|
||||
}
|
||||
|
||||
@@ -380,7 +374,7 @@ ScheduleTreeOptimizer::prevectSchedBand(__isl_take isl_schedule_node *Node,
|
||||
Sizes =
|
||||
isl_multi_val_set_val(Sizes, 0, isl_val_int_from_si(Ctx, VectorWidth));
|
||||
Node = isl_schedule_node_band_tile(Node, Sizes);
|
||||
Node = isolateFullPartialTiles(Node, VectorWidth);
|
||||
Node = isolateFullPartialTiles(give(Node), VectorWidth).release();
|
||||
Node = isl_schedule_node_child(Node, 0);
|
||||
// Make sure the "trivially vectorizable loop" is not unrolled. Otherwise,
|
||||
// we will have troubles to match it in the backend.
|
||||
@@ -1227,30 +1221,29 @@ getInductionVariablesSubstitution(__isl_take isl_schedule_node *Node,
|
||||
/// @param MicroKernelParams Parameters of the micro-kernel
|
||||
/// to be taken into account.
|
||||
/// @return The modified isl_schedule_node.
|
||||
static __isl_give isl_schedule_node *
|
||||
isolateAndUnrollMatMulInnerLoops(__isl_take isl_schedule_node *Node,
|
||||
static isl::schedule_node
|
||||
isolateAndUnrollMatMulInnerLoops(isl::schedule_node Node,
|
||||
struct MicroKernelParamsTy MicroKernelParams) {
|
||||
auto *Child = isl_schedule_node_get_child(Node, 0);
|
||||
auto *UnMapOldIndVar = isl_schedule_node_get_prefix_schedule_relation(Child);
|
||||
isl_schedule_node_free(Child);
|
||||
auto *Prefix = isl_map_range(isl_map_from_union_map(UnMapOldIndVar));
|
||||
auto Dims = isl_set_dim(Prefix, isl_dim_set);
|
||||
Prefix = isl_set_project_out(Prefix, isl_dim_set, Dims - 1, 1);
|
||||
isl::schedule_node Child = Node.get_child(0);
|
||||
isl::union_map UnMapOldIndVar = Child.get_prefix_schedule_relation();
|
||||
isl::set Prefix = isl::map::from_union_map(UnMapOldIndVar).range();
|
||||
unsigned Dims = Prefix.dim(isl::dim::set);
|
||||
Prefix = Prefix.project_out(isl::dim::set, Dims - 1, 1);
|
||||
Prefix = getPartialTilePrefixes(Prefix, MicroKernelParams.Nr);
|
||||
Prefix = getPartialTilePrefixes(Prefix, MicroKernelParams.Mr);
|
||||
auto *IsolateOption = getIsolateOptions(
|
||||
isl_set_add_dims(isl_set_copy(Prefix), isl_dim_set, 3), 3);
|
||||
auto *Ctx = isl_schedule_node_get_ctx(Node);
|
||||
auto *AtomicOption = getAtomicOptions(Ctx);
|
||||
auto *Options =
|
||||
isl_union_set_union(IsolateOption, isl_union_set_copy(AtomicOption));
|
||||
Options = isl_union_set_union(Options, getUnrollIsolatedSetOptions(Ctx));
|
||||
Node = isl_schedule_node_band_set_ast_build_options(Node, Options);
|
||||
Node = isl_schedule_node_parent(isl_schedule_node_parent(Node));
|
||||
|
||||
isl::union_set IsolateOption =
|
||||
getIsolateOptions(Prefix.add_dims(isl::dim::set, 3), 3);
|
||||
isl::ctx Ctx = Node.get_ctx();
|
||||
isl::union_set AtomicOption = getAtomicOptions(Ctx);
|
||||
isl::union_set Options = IsolateOption.unite(AtomicOption);
|
||||
Options = Options.unite(getUnrollIsolatedSetOptions(Ctx));
|
||||
Node = Node.band_set_ast_build_options(Options);
|
||||
Node = Node.parent().parent();
|
||||
IsolateOption = getIsolateOptions(Prefix, 3);
|
||||
Options = isl_union_set_union(IsolateOption, AtomicOption);
|
||||
Node = isl_schedule_node_band_set_ast_build_options(Node, Options);
|
||||
Node = isl_schedule_node_child(isl_schedule_node_child(Node, 0), 0);
|
||||
Options = IsolateOption.unite(AtomicOption);
|
||||
Node = Node.band_set_ast_build_options(Options);
|
||||
Node = Node.child(0).child(0);
|
||||
return Node;
|
||||
}
|
||||
|
||||
@@ -1329,7 +1322,8 @@ __isl_give isl_schedule_node *ScheduleTreeOptimizer::optimizeMatMulPattern(
|
||||
Node, MicroKernelParams, MacroKernelParams);
|
||||
if (!MapOldIndVar)
|
||||
return Node;
|
||||
Node = isolateAndUnrollMatMulInnerLoops(Node, MicroKernelParams);
|
||||
Node =
|
||||
isolateAndUnrollMatMulInnerLoops(give(Node), MicroKernelParams).release();
|
||||
return optimizeDataLayoutMatrMulPattern(Node, MapOldIndVar, MicroKernelParams,
|
||||
MacroKernelParams, MMI);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user