summaryrefslogtreecommitdiffstats
path: root/polly/lib/External/isl/isl_ast_build.c
diff options
context:
space:
mode:
Diffstat (limited to 'polly/lib/External/isl/isl_ast_build.c')
-rw-r--r--polly/lib/External/isl/isl_ast_build.c394
1 files changed, 377 insertions, 17 deletions
diff --git a/polly/lib/External/isl/isl_ast_build.c b/polly/lib/External/isl/isl_ast_build.c
index 0fef62bf350..77d652f6db1 100644
--- a/polly/lib/External/isl/isl_ast_build.c
+++ b/polly/lib/External/isl/isl_ast_build.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Ecole Normale Superieure
+ * Copyright 2012-2013 Ecole Normale Superieure
* Copyright 2014 INRIA Rocquencourt
*
* Use of this software is governed by the MIT license
@@ -66,10 +66,12 @@ static __isl_give isl_ast_build *isl_ast_build_init_derived(
isl_multi_aff_free(build->offsets);
build->offsets = isl_multi_aff_zero(isl_space_copy(space));
isl_multi_aff_free(build->values);
- build->values = isl_multi_aff_identity(space);
+ build->values = isl_multi_aff_identity(isl_space_copy(space));
+ isl_multi_aff_free(build->internal2input);
+ build->internal2input = isl_multi_aff_identity(space);
if (!build->iterators || !build->domain || !build->generated ||
- !build->pending || !build->values ||
+ !build->pending || !build->values || !build->internal2input ||
!build->strides || !build->offsets || !build->options)
return isl_ast_build_free(build);
@@ -146,6 +148,19 @@ error:
return NULL;
}
+/* Create an isl_ast_build with a universe (parametric) context.
+ */
+__isl_give isl_ast_build *isl_ast_build_alloc(isl_ctx *ctx)
+{
+ isl_space *space;
+ isl_set *context;
+
+ space = isl_space_params_alloc(ctx, 0);
+ context = isl_set_universe(space);
+
+ return isl_ast_build_from_context(context);
+}
+
__isl_give isl_ast_build *isl_ast_build_copy(__isl_keep isl_ast_build *build)
{
if (!build)
@@ -176,6 +191,7 @@ __isl_give isl_ast_build *isl_ast_build_dup(__isl_keep isl_ast_build *build)
dup->generated = isl_set_copy(build->generated);
dup->pending = isl_set_copy(build->pending);
dup->values = isl_multi_aff_copy(build->values);
+ dup->internal2input = isl_multi_aff_copy(build->internal2input);
dup->value = isl_pw_aff_copy(build->value);
dup->strides = isl_vec_copy(build->strides);
dup->offsets = isl_multi_aff_copy(build->offsets);
@@ -190,12 +206,26 @@ __isl_give isl_ast_build *isl_ast_build_dup(__isl_keep isl_ast_build *build)
dup->after_each_for_user = build->after_each_for_user;
dup->create_leaf = build->create_leaf;
dup->create_leaf_user = build->create_leaf_user;
+ dup->node = isl_schedule_node_copy(build->node);
+ if (build->loop_type) {
+ int i;
+
+ dup->n = build->n;
+ dup->loop_type = isl_alloc_array(ctx,
+ enum isl_ast_loop_type, dup->n);
+ if (dup->n && !dup->loop_type)
+ return isl_ast_build_free(dup);
+ for (i = 0; i < dup->n; ++i)
+ dup->loop_type[i] = build->loop_type[i];
+ }
if (!dup->iterators || !dup->domain || !dup->generated ||
!dup->pending || !dup->values ||
!dup->strides || !dup->offsets || !dup->options ||
+ (build->internal2input && !dup->internal2input) ||
(build->executed && !dup->executed) ||
- (build->value && !dup->value))
+ (build->value && !dup->value) ||
+ (build->node && !dup->node))
return isl_ast_build_free(dup);
return dup;
@@ -223,7 +253,15 @@ __isl_give isl_ast_build *isl_ast_build_align_params(
isl_space_copy(model));
build->options = isl_union_map_align_params(build->options,
isl_space_copy(model));
- isl_space_free(model);
+ if (build->internal2input) {
+ build->internal2input =
+ isl_multi_aff_align_params(build->internal2input,
+ model);
+ if (!build->internal2input)
+ return isl_ast_build_free(build);
+ } else {
+ isl_space_free(model);
+ }
if (!build->domain || !build->values || !build->offsets ||
!build->options)
@@ -260,12 +298,16 @@ __isl_null isl_ast_build *isl_ast_build_free(
isl_set_free(build->generated);
isl_set_free(build->pending);
isl_multi_aff_free(build->values);
+ isl_multi_aff_free(build->internal2input);
isl_pw_aff_free(build->value);
isl_vec_free(build->strides);
isl_multi_aff_free(build->offsets);
isl_multi_aff_free(build->schedule_map);
isl_union_map_free(build->executed);
isl_union_map_free(build->options);
+ isl_schedule_node_free(build->node);
+ free(build->loop_type);
+ isl_set_free(build->isolated);
free(build);
@@ -586,6 +628,8 @@ void isl_ast_build_dump(__isl_keep isl_ast_build *build)
isl_vec_dump(build->strides);
fprintf(stderr, "offsets: ");
isl_multi_aff_dump(build->offsets);
+ fprintf(stderr, "internal2input: ");
+ isl_multi_aff_dump(build->internal2input);
}
/* Initialize "build" for AST construction in schedule space "space"
@@ -919,6 +963,95 @@ error:
return NULL;
}
+/* Does "build" point to a band node?
+ * That is, are we currently handling a band node inside a schedule tree?
+ */
+int isl_ast_build_has_schedule_node(__isl_keep isl_ast_build *build)
+{
+ if (!build)
+ return -1;
+ return build->node != NULL;
+}
+
+/* Return a copy of the band node that "build" refers to.
+ */
+__isl_give isl_schedule_node *isl_ast_build_get_schedule_node(
+ __isl_keep isl_ast_build *build)
+{
+ if (!build)
+ return NULL;
+ return isl_schedule_node_copy(build->node);
+}
+
+/* Extract the loop AST generation types for the members of build->node
+ * and store them in build->loop_type.
+ */
+static __isl_give isl_ast_build *extract_loop_types(
+ __isl_take isl_ast_build *build)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_schedule_node *node;
+
+ if (!build)
+ return NULL;
+ ctx = isl_ast_build_get_ctx(build);
+ if (!build->node)
+ isl_die(ctx, isl_error_internal, "missing AST node",
+ return isl_ast_build_free(build));
+
+ free(build->loop_type);
+ build->n = isl_schedule_node_band_n_member(build->node);
+ build->loop_type = isl_alloc_array(ctx,
+ enum isl_ast_loop_type, build->n);
+ if (build->n && !build->loop_type)
+ return isl_ast_build_free(build);
+ node = build->node;
+ for (i = 0; i < build->n; ++i)
+ build->loop_type[i] =
+ isl_schedule_node_band_member_get_ast_loop_type(node, i);
+
+ return build;
+}
+
+/* Replace the band node that "build" refers to by "node" and
+ * extract the corresponding loop AST generation types.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_schedule_node(
+ __isl_take isl_ast_build *build,
+ __isl_take isl_schedule_node *node)
+{
+ build = isl_ast_build_cow(build);
+ if (!build || !node)
+ goto error;
+
+ isl_schedule_node_free(build->node);
+ build->node = node;
+
+ build = extract_loop_types(build);
+
+ return build;
+error:
+ isl_ast_build_free(build);
+ isl_schedule_node_free(node);
+ return NULL;
+}
+
+/* Remove any reference to a band node from "build".
+ */
+__isl_give isl_ast_build *isl_ast_build_reset_schedule_node(
+ __isl_take isl_ast_build *build)
+{
+ build = isl_ast_build_cow(build);
+ if (!build)
+ return NULL;
+
+ isl_schedule_node_free(build->node);
+ build->node = NULL;
+
+ return build;
+}
+
/* Return a copy of the current schedule domain.
*/
__isl_give isl_set *isl_ast_build_get_domain(__isl_keep isl_ast_build *build)
@@ -942,6 +1075,15 @@ __isl_give isl_set *isl_ast_build_get_generated(
return build ? isl_set_copy(build->generated) : NULL;
}
+/* Return a copy of the map from the internal schedule domain
+ * to the original input schedule domain.
+ */
+__isl_give isl_multi_aff *isl_ast_build_get_internal2input(
+ __isl_keep isl_ast_build *build)
+{
+ return build ? isl_multi_aff_copy(build->internal2input) : NULL;
+}
+
/* Return the number of variables of the given type
* in the (internal) schedule space.
*/
@@ -1428,9 +1570,9 @@ static __isl_give isl_map *construct_insertion_map(__isl_take isl_space *space,
}
static const char *option_str[] = {
- [atomic] = "atomic",
- [unroll] = "unroll",
- [separate] = "separate"
+ [isl_ast_loop_atomic] = "atomic",
+ [isl_ast_loop_unroll] = "unroll",
+ [isl_ast_loop_separate] = "separate"
};
/* Update the "options" to reflect the insertion of a dimension
@@ -1459,7 +1601,7 @@ static __isl_give isl_union_map *options_insert_dim(
{
isl_map *map;
isl_union_map *insertion;
- enum isl_ast_build_domain_type type;
+ enum isl_ast_loop_type type;
const char *name = "separation_class";
space = isl_space_map_from_set(space);
@@ -1475,7 +1617,8 @@ static __isl_give isl_union_map *options_insert_dim(
insertion = isl_union_map_empty(isl_union_map_get_space(options));
- for (type = atomic; type <= separate; ++type) {
+ for (type = isl_ast_loop_atomic;
+ type <= isl_ast_loop_separate; ++type) {
isl_map *map_type = isl_map_copy(map);
const char *name = option_str[type];
map_type = isl_map_set_tuple_name(map_type, isl_dim_in, name);
@@ -1493,6 +1636,42 @@ static __isl_give isl_union_map *options_insert_dim(
return options;
}
+/* If we are generating an AST from a schedule tree (build->node is set),
+ * then update the loop AST generation types
+ * to reflect the insertion of a dimension at (global) position "pos"
+ * in the schedule domain space.
+ * We do not need to adjust any isolate option since we would not be inserting
+ * any dimensions if there were any isolate option.
+ */
+static __isl_give isl_ast_build *node_insert_dim(
+ __isl_take isl_ast_build *build, int pos)
+{
+ int i;
+ int local_pos;
+ enum isl_ast_loop_type *loop_type;
+ isl_ctx *ctx;
+
+ build = isl_ast_build_cow(build);
+ if (!build)
+ return NULL;
+ if (!build->node)
+ return build;
+
+ ctx = isl_ast_build_get_ctx(build);
+ local_pos = pos - build->outer_pos;
+ loop_type = isl_realloc_array(ctx, build->loop_type,
+ enum isl_ast_loop_type, build->n + 1);
+ if (!loop_type)
+ return isl_ast_build_free(build);
+ build->loop_type = loop_type;
+ for (i = build->n - 1; i >= local_pos; --i)
+ loop_type[i + 1] = loop_type[i];
+ loop_type[local_pos] = isl_ast_loop_default;
+ build->n++;
+
+ return build;
+}
+
/* Insert a single dimension in the schedule domain at position "pos".
* The new dimension is given an isl_id with the empty string as name.
*
@@ -1504,6 +1683,12 @@ static __isl_give isl_union_map *options_insert_dim(
* However, the original schedule domain space may be named and/or
* structured, so we have to take this possibility into account
* while performing the transformations.
+ *
+ * Since the inserted schedule dimension is used by the caller
+ * to differentiate between different domain spaces, there is
+ * no longer a uniform mapping from the internal schedule space
+ * to the input schedule space. The internal2input mapping is
+ * therefore removed.
*/
__isl_give isl_ast_build *isl_ast_build_insert_dim(
__isl_take isl_ast_build *build, int pos)
@@ -1519,7 +1704,8 @@ __isl_give isl_ast_build *isl_ast_build_insert_dim(
ctx = isl_ast_build_get_ctx(build);
id = isl_id_alloc(ctx, "", NULL);
- space = isl_ast_build_get_space(build, 1);
+ if (!build->node)
+ space = isl_ast_build_get_space(build, 1);
build->iterators = isl_id_list_insert(build->iterators, pos, id);
build->domain = isl_set_insert_dims(build->domain,
isl_dim_set, pos, 1);
@@ -1537,13 +1723,17 @@ __isl_give isl_ast_build *isl_ast_build_insert_dim(
build->offsets = isl_multi_aff_splice(build->offsets, pos, pos, ma);
ma = isl_multi_aff_identity(ma_space);
build->values = isl_multi_aff_splice(build->values, pos, pos, ma);
- build->options = options_insert_dim(build->options, space, pos);
+ if (!build->node)
+ build->options = options_insert_dim(build->options, space, pos);
+ build->internal2input = isl_multi_aff_free(build->internal2input);
if (!build->iterators || !build->domain || !build->generated ||
!build->pending || !build->values ||
!build->strides || !build->offsets || !build->options)
return isl_ast_build_free(build);
+ build = node_insert_dim(build, pos);
+
return build;
}
@@ -1556,7 +1746,11 @@ __isl_give isl_ast_build *isl_ast_build_insert_dim(
* This function is called right after the strides have been
* detected, but before any constraints on the current dimension
* have been included in build->domain.
- * We therefore only need to update stride, offset and the options.
+ * We therefore only need to update stride, offset, the options and
+ * the mapping from internal schedule space to the original schedule
+ * space, if we are still keeping track of such a mapping.
+ * The latter mapping is updated by plugging in
+ * { [... i ...] -> [... m i ... ] }.
*/
__isl_give isl_ast_build *isl_ast_build_scale_down(
__isl_take isl_ast_build *build, __isl_take isl_val *m,
@@ -1572,6 +1766,23 @@ __isl_give isl_ast_build *isl_ast_build_scale_down(
depth = build->depth;
+ if (build->internal2input) {
+ isl_space *space;
+ isl_multi_aff *ma;
+ isl_aff *aff;
+
+ space = isl_multi_aff_get_space(build->internal2input);
+ space = isl_space_map_from_set(isl_space_domain(space));
+ ma = isl_multi_aff_identity(space);
+ aff = isl_multi_aff_get_aff(ma, depth);
+ aff = isl_aff_scale_val(aff, isl_val_copy(m));
+ ma = isl_multi_aff_set_aff(ma, depth, aff);
+ build->internal2input =
+ isl_multi_aff_pullback_multi_aff(build->internal2input, ma);
+ if (!build->internal2input)
+ goto error;
+ }
+
v = isl_vec_get_element_val(build->strides, depth);
v = isl_val_div(v, isl_val_copy(m));
build->strides = isl_vec_set_element_val(build->strides, depth, v);
@@ -1614,7 +1825,7 @@ static __isl_give isl_id_list *generate_names(isl_ctx *ctx, int n, int first,
/* Embed "options" into the given isl_ast_build space.
*
* This function is called from within a nested call to
- * isl_ast_build_ast_from_schedule.
+ * isl_ast_build_node_from_schedule_map.
* "options" refers to the additional schedule,
* while space refers to both the space of the outer isl_ast_build and
* that of the additional schedule.
@@ -1716,7 +1927,18 @@ __isl_give isl_ast_build *isl_ast_build_product(
build->values = isl_multi_aff_align_params(build->values,
isl_space_copy(space));
embedding = isl_multi_aff_identity(space);
- build->values = isl_multi_aff_product(build->values, embedding);
+ build->values = isl_multi_aff_product(build->values,
+ isl_multi_aff_copy(embedding));
+ if (build->internal2input) {
+ build->internal2input =
+ isl_multi_aff_product(build->internal2input, embedding);
+ build->internal2input =
+ isl_multi_aff_flatten_range(build->internal2input);
+ if (!build->internal2input)
+ return isl_ast_build_free(build);
+ } else {
+ isl_multi_aff_free(embedding);
+ }
space = isl_ast_build_get_space(build, 1);
build->options = embed_options(build->options, space);
@@ -2020,8 +2242,7 @@ error:
* but the position is still that within the current code generation.
*/
__isl_give isl_set *isl_ast_build_get_option_domain(
- __isl_keep isl_ast_build *build,
- enum isl_ast_build_domain_type type)
+ __isl_keep isl_ast_build *build, enum isl_ast_loop_type type)
{
const char *name;
isl_space *space;
@@ -2049,6 +2270,145 @@ __isl_give isl_set *isl_ast_build_get_option_domain(
return domain;
}
+/* How does the user want the current schedule dimension to be generated?
+ * These choices have been extracted from the schedule node
+ * in extract_loop_types and stored in build->loop_type.
+ * They have been updated to reflect any dimension insertion in
+ * node_insert_dim.
+ * Return isl_ast_domain_error on error.
+ *
+ * If "isolated" is set, then we get the loop AST generation type
+ * directly from the band node since node_insert_dim cannot have been
+ * called on a band with the isolate option.
+ */
+enum isl_ast_loop_type isl_ast_build_get_loop_type(
+ __isl_keep isl_ast_build *build, int isolated)
+{
+ int local_pos;
+ isl_ctx *ctx;
+
+ if (!build)
+ return isl_ast_loop_error;
+ ctx = isl_ast_build_get_ctx(build);
+ if (!build->node)
+ isl_die(ctx, isl_error_internal,
+ "only works for schedule tree based AST generation",
+ return isl_ast_loop_error);
+
+ local_pos = build->depth - build->outer_pos;
+ if (!isolated)
+ return build->loop_type[local_pos];
+ return isl_schedule_node_band_member_get_isolate_ast_loop_type(
+ build->node, local_pos);
+}
+
+/* Extract the isolated set from the isolate option, if any,
+ * and store in the build.
+ * If there is no isolate option, then the isolated set is
+ * set to the empty set.
+ *
+ * The isolate option is of the form
+ *
+ * isolate[[outer bands] -> current_band]
+ *
+ * We flatten this set and then map it back to the internal
+ * schedule space.
+ *
+ * If we have already extracted the isolated set
+ * or if internal2input is no longer set, then we do not
+ * need to do anything. In the latter case, we know
+ * that the current band cannot have any isolate option.
+ */
+__isl_give isl_ast_build *isl_ast_build_extract_isolated(
+ __isl_take isl_ast_build *build)
+{
+ isl_space *space, *space2;
+ isl_union_set *options;
+ int n, n2;
+ isl_set *isolated;
+
+ if (!build)
+ return NULL;
+ if (!build->internal2input)
+ return build;
+ if (build->isolated)
+ return build;
+
+ build = isl_ast_build_cow(build);
+ if (!build)
+ return NULL;
+
+ options = isl_schedule_node_band_get_ast_build_options(build->node);
+
+ space = isl_multi_aff_get_space(build->internal2input);
+ space = isl_space_range(space);
+ space2 = isl_set_get_space(build->domain);
+ if (isl_space_is_wrapping(space2))
+ space2 = isl_space_range(isl_space_unwrap(space2));
+ n2 = isl_space_dim(space2, isl_dim_set);
+ n = isl_space_dim(space, isl_dim_set);
+ if (n < n2)
+ isl_die(isl_ast_build_get_ctx(build), isl_error_internal,
+ "total input space dimension cannot be smaller "
+ "than dimension of innermost band",
+ space = isl_space_free(space));
+ space = isl_space_drop_dims(space, isl_dim_set, n - n2, n2);
+ space = isl_space_map_from_domain_and_range(space, space2);
+ space = isl_space_wrap(space);
+ space = isl_space_set_tuple_name(space, isl_dim_set, "isolate");
+ isolated = isl_union_set_extract_set(options, space);
+ isl_union_set_free(options);
+
+ isolated = isl_set_flatten(isolated);
+ isolated = isl_set_preimage_multi_aff(isolated,
+ isl_multi_aff_copy(build->internal2input));
+
+ build->isolated = isolated;
+ if (!build->isolated)
+ return isl_ast_build_free(build);
+
+ return build;
+}
+
+/* Does "build" have a non-empty isolated set?
+ *
+ * The caller is assumed to have called isl_ast_build_extract_isolated first.
+ */
+int isl_ast_build_has_isolated(__isl_keep isl_ast_build *build)
+{
+ int empty;
+
+ if (!build)
+ return -1;
+ if (!build->internal2input)
+ return 0;
+ if (!build->isolated)
+ isl_die(isl_ast_build_get_ctx(build), isl_error_internal,
+ "isolated set not extracted yet", return -1);
+
+ empty = isl_set_plain_is_empty(build->isolated);
+ return empty < 0 ? -1 : !empty;
+}
+
+/* Return a copy of the isolated set of "build".
+ *
+ * The caller is assume to have called isl_ast_build_has_isolated first,
+ * with this function returning true.
+ * In particular, this function should not be called if we are no
+ * longer keeping track of internal2input (and there therefore could
+ * not possibly be any isolated set).
+ */
+__isl_give isl_set *isl_ast_build_get_isolated(__isl_keep isl_ast_build *build)
+{
+ if (!build)
+ return NULL;
+ if (!build->internal2input)
+ isl_die(isl_ast_build_get_ctx(build), isl_error_internal,
+ "build cannot have isolated set", return NULL);
+
+ return isl_set_copy(build->isolated);
+}
+
/* Extract the separation class mapping at the current depth.
*
* In particular, find and return the subset of build->options that is of
OpenPOWER on IntegriCloud