[polly] r229423 - Update to isl 99d53692ba
Tobias Grosser
tobias at grosser.es
Mon Feb 16 11:33:42 PST 2015
Author: grosser
Date: Mon Feb 16 13:33:40 2015
New Revision: 229423
URL: http://llvm.org/viewvc/llvm-project?rev=229423&view=rev
Log:
Update to isl 99d53692ba
This commit imports the latest isl version into lib/External/isl. The changes
relavant for Polly are:
1) Schedule trees [1] have been introduced as a more structured way to
describe schedules. Polly does not yet use them, but we may switch to them
in the near future.
2) Another set of coalescing changes [2] simplifies some data dependences and
removes a couple of code generation artifacts.
We now understand that the following sets can be merged:
{ Stmt_S1[i0, i1] -> Stmt_S2[i0 + i1] :
i0 >= 0 and i1 <= 1023 - i0 and i1 >= 1
Stmt_S1[i0, 0] -> Stmt_S2[i0] : i0 <= 1023 and i0 >= 1}
into:
{ Stmt_S1[i0, i1] -> Stmt_S2[i0 + i1] : i1 <= 1023 - i0 and i1 >= 0 and
i1 >= 1 - i0 and i0 >= 0 }
Changes of this kind reduce unnecessary specialization during code
generation.
- for (int c3 = 0; c3 <= 1023; c3 += 1) {
- if (c3 % 2 == 0) {
- Stmt_for_body3(c1, c3);
- } else
- Stmt_for_body3(c1, c3);
- }
+ for (int c3 = 0; c3 <= 1023; c3 += 1)
+ Stmt_for_body3(c1, c3);
[1] http://impact.gforge.inria.fr/impact2014/papers/impact2014-verdoolaege.pdf
[2] http://impact.gforge.inria.fr/impact2015/papers/impact2015-verdoolaege.pdf
Added:
polly/trunk/lib/External/isl/include/isl/schedule_node.h
polly/trunk/lib/External/isl/include/isl/schedule_type.h
polly/trunk/lib/External/isl/isl_map_list.c
polly/trunk/lib/External/isl/isl_multi_apply_set.c
polly/trunk/lib/External/isl/isl_multi_apply_templ.c
polly/trunk/lib/External/isl/isl_multi_apply_union_set.c
polly/trunk/lib/External/isl/isl_multi_floor.c
polly/trunk/lib/External/isl/isl_multi_gist.c
polly/trunk/lib/External/isl/isl_multi_intersect.c
polly/trunk/lib/External/isl/isl_multi_macro.h
polly/trunk/lib/External/isl/isl_schedule_band.c
polly/trunk/lib/External/isl/isl_schedule_band.h
polly/trunk/lib/External/isl/isl_schedule_node.c
polly/trunk/lib/External/isl/isl_schedule_node_private.h
polly/trunk/lib/External/isl/isl_schedule_read.c
polly/trunk/lib/External/isl/isl_schedule_tree.c
polly/trunk/lib/External/isl/isl_schedule_tree.h
polly/trunk/lib/External/isl/isl_yaml.h
polly/trunk/lib/External/isl/test_inputs/codegen/unroll11.c
polly/trunk/lib/External/isl/test_inputs/codegen/unroll11.in
Modified:
polly/trunk/lib/CMakeLists.txt
polly/trunk/lib/External/isl/Makefile.am
polly/trunk/lib/External/isl/bound.c
polly/trunk/lib/External/isl/cat.c
polly/trunk/lib/External/isl/closure.c
polly/trunk/lib/External/isl/doc/user.pod
polly/trunk/lib/External/isl/include/isl/aff.h
polly/trunk/lib/External/isl/include/isl/aff_type.h
polly/trunk/lib/External/isl/include/isl/local_space.h
polly/trunk/lib/External/isl/include/isl/map.h
polly/trunk/lib/External/isl/include/isl/map_type.h
polly/trunk/lib/External/isl/include/isl/multi.h
polly/trunk/lib/External/isl/include/isl/obj.h
polly/trunk/lib/External/isl/include/isl/polynomial.h
polly/trunk/lib/External/isl/include/isl/printer.h
polly/trunk/lib/External/isl/include/isl/schedule.h
polly/trunk/lib/External/isl/include/isl/set.h
polly/trunk/lib/External/isl/include/isl/stream.h
polly/trunk/lib/External/isl/include/isl/union_map.h
polly/trunk/lib/External/isl/include/isl/union_map_type.h
polly/trunk/lib/External/isl/include/isl/union_set.h
polly/trunk/lib/External/isl/include/isl/val.h
polly/trunk/lib/External/isl/interface/extract_interface.cc
polly/trunk/lib/External/isl/interface/python.cc
polly/trunk/lib/External/isl/isl_aff.c
polly/trunk/lib/External/isl/isl_aff_private.h
polly/trunk/lib/External/isl/isl_affine_hull.c
polly/trunk/lib/External/isl/isl_ast_build.c
polly/trunk/lib/External/isl/isl_ast_build_expr.c
polly/trunk/lib/External/isl/isl_ast_codegen.c
polly/trunk/lib/External/isl/isl_coalesce.c
polly/trunk/lib/External/isl/isl_convex_hull.c
polly/trunk/lib/External/isl/isl_fold.c
polly/trunk/lib/External/isl/isl_input.c
polly/trunk/lib/External/isl/isl_local_space.c
polly/trunk/lib/External/isl/isl_map.c
polly/trunk/lib/External/isl/isl_map_private.h
polly/trunk/lib/External/isl/isl_map_simplify.c
polly/trunk/lib/External/isl/isl_morph.c
polly/trunk/lib/External/isl/isl_multi_templ.c
polly/trunk/lib/External/isl/isl_multi_templ.h
polly/trunk/lib/External/isl/isl_obj.c
polly/trunk/lib/External/isl/isl_output.c
polly/trunk/lib/External/isl/isl_polynomial.c
polly/trunk/lib/External/isl/isl_printer.c
polly/trunk/lib/External/isl/isl_printer_private.h
polly/trunk/lib/External/isl/isl_pw_templ.c
polly/trunk/lib/External/isl/isl_schedule.c
polly/trunk/lib/External/isl/isl_schedule_private.h
polly/trunk/lib/External/isl/isl_scheduler.c
polly/trunk/lib/External/isl/isl_set_list.c
polly/trunk/lib/External/isl/isl_stream.c
polly/trunk/lib/External/isl/isl_stream_private.h
polly/trunk/lib/External/isl/isl_tab.c
polly/trunk/lib/External/isl/isl_tab.h
polly/trunk/lib/External/isl/isl_test.c
polly/trunk/lib/External/isl/isl_union_map.c
polly/trunk/lib/External/isl/isl_union_map_private.h
polly/trunk/lib/External/isl/isl_union_templ.c
polly/trunk/lib/External/isl/isl_val.c
polly/trunk/lib/External/isl/isl_val_private.h
polly/trunk/lib/External/isl/polyhedron_detect_equalities.c
polly/trunk/lib/External/isl/print.c
polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c
polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.c
polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.c
polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c
polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c
polly/trunk/lib/External/isl/test_inputs/codegen/cloog/vivien.c
polly/trunk/lib/External/isl/test_inputs/codegen/cloog/vivien2.c
polly/trunk/lib/External/isl/test_inputs/codegen/cloog/yosr.c
polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur00-0.c
polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur01-0.c
polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur01-1.c
polly/trunk/lib/External/isl/test_inputs/codegen/omega/substitution-1.c
polly/trunk/test/Dependences/reduction_dependences_equal_non_reduction_dependences.ll
polly/trunk/test/Dependences/reduction_mixed_reduction_and_non_reduction_dependences.ll
polly/trunk/test/Dependences/reduction_privatization_deps.ll
polly/trunk/test/Dependences/reduction_privatization_deps_3.ll
polly/trunk/test/Dependences/reduction_two_reductions_different_rloops.ll
polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions.ll
polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_2.ll
polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_3.ll
polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_4.ll
Modified: polly/trunk/lib/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/CMakeLists.txt?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/CMakeLists.txt (original)
+++ polly/trunk/lib/CMakeLists.txt Mon Feb 16 13:33:40 2015
@@ -56,6 +56,7 @@ set (ISL_FILES
External/isl/isl_local_space.c
External/isl/isl_lp.c
External/isl/isl_map.c
+ External/isl/isl_map_list.c
External/isl/isl_map_simplify.c
External/isl/isl_map_subtract.c
External/isl/isl_map_to_basic_set.c
@@ -72,6 +73,10 @@ set (ISL_FILES
External/isl/isl_sample.c
External/isl/isl_scan.c
External/isl/isl_schedule.c
+ External/isl/isl_schedule_band.c
+ External/isl/isl_schedule_node.c
+ External/isl/isl_schedule_read.c
+ External/isl/isl_schedule_tree.c
External/isl/isl_scheduler.c
External/isl/isl_seq.c
External/isl/isl_set_list.c
Modified: polly/trunk/lib/External/isl/Makefile.am
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/Makefile.am?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/Makefile.am (original)
+++ polly/trunk/lib/External/isl/Makefile.am Mon Feb 16 13:33:40 2015
@@ -107,6 +107,7 @@ libisl_la_SOURCES = \
isl_lp.c \
isl_lp_private.h \
isl_map.c \
+ isl_map_list.c \
isl_map_simplify.c \
isl_map_subtract.c \
isl_map_private.h \
@@ -137,6 +138,13 @@ libisl_la_SOURCES = \
isl_scan.c \
isl_scan.h \
isl_schedule.c \
+ isl_schedule_band.c \
+ isl_schedule_band.h \
+ isl_schedule_node.c \
+ isl_schedule_node_private.h \
+ isl_schedule_read.c \
+ isl_schedule_tree.c \
+ isl_schedule_tree.h \
isl_schedule_private.h \
isl_scheduler.c \
isl_set_list.c \
@@ -162,7 +170,8 @@ libisl_la_SOURCES = \
isl_vec.c \
isl_version.c \
isl_vertices_private.h \
- isl_vertices.c
+ isl_vertices.c \
+ isl_yaml.h
libisl_la_LIBADD = @MP_LIBS@
libisl_la_LDFLAGS = -version-info @versioninfo@ \
@MP_LDFLAGS@
@@ -246,6 +255,8 @@ pkginclude_HEADERS = \
include/isl/polynomial_type.h \
include/isl/printer.h \
include/isl/schedule.h \
+ include/isl/schedule_node.h \
+ include/isl/schedule_type.h \
include/isl/set.h \
include/isl/set_type.h \
include/isl/space.h \
@@ -282,8 +293,15 @@ EXTRA_DIST = \
isl_list_templ.c \
isl_list_templ.h \
isl_map_lexopt_templ.c \
+ isl_multi_macro.h \
isl_multi_templ.c \
isl_multi_templ.h \
+ isl_multi_apply_templ.c \
+ isl_multi_apply_set.c \
+ isl_multi_apply_union_set.c \
+ isl_multi_floor.c \
+ isl_multi_gist.c \
+ isl_multi_intersect.c \
print_templ.c \
isl_power_templ.c \
isl_pw_templ.c \
Modified: polly/trunk/lib/External/isl/bound.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/bound.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/bound.c (original)
+++ polly/trunk/lib/External/isl/bound.c Mon Feb 16 13:33:40 2015
@@ -242,7 +242,7 @@ int main(int argc, char **argv)
isl_ctx *ctx;
isl_pw_qpolynomial_fold *copy;
isl_pw_qpolynomial_fold *pwf;
- struct isl_stream *s;
+ isl_stream *s;
struct isl_obj obj;
struct bound_options *options;
int exact;
Modified: polly/trunk/lib/External/isl/cat.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/cat.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/cat.c (original)
+++ polly/trunk/lib/External/isl/cat.c Mon Feb 16 13:33:40 2015
@@ -13,15 +13,24 @@ struct isl_arg_choice cat_format[] = {
{0}
};
+struct isl_arg_choice cat_yaml_style[] = {
+ { "block", ISL_YAML_STYLE_BLOCK },
+ { "flow", ISL_YAML_STYLE_FLOW },
+ { 0 }
+};
+
struct cat_options {
struct isl_options *isl;
unsigned format;
+ unsigned yaml_style;
};
ISL_ARGS_START(struct cat_options, cat_options_args)
ISL_ARG_CHILD(struct cat_options, isl, "isl", &isl_options_args, "isl options")
ISL_ARG_CHOICE(struct cat_options, format, 0, "format", \
cat_format, ISL_FORMAT_ISL, "output format")
+ISL_ARG_CHOICE(struct cat_options, yaml_style, 0, "yaml-style", \
+ cat_yaml_style, ISL_YAML_STYLE_BLOCK, "output YAML style")
ISL_ARGS_END
ISL_ARG_DEF(cat_options, struct cat_options, cat_options_args)
@@ -29,7 +38,7 @@ ISL_ARG_DEF(cat_options, struct cat_opti
int main(int argc, char **argv)
{
struct isl_ctx *ctx;
- struct isl_stream *s;
+ isl_stream *s;
struct isl_obj obj;
struct cat_options *options;
isl_printer *p;
@@ -46,6 +55,7 @@ int main(int argc, char **argv)
p = isl_printer_to_file(ctx, stdout);
p = isl_printer_set_output_format(p, options->format);
+ p = isl_printer_set_yaml_style(p, options->yaml_style);
p = obj.type->print(p, obj.v);
p = isl_printer_end_line(p);
isl_printer_free(p);
Modified: polly/trunk/lib/External/isl/closure.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/closure.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/closure.c (original)
+++ polly/trunk/lib/External/isl/closure.c Mon Feb 16 13:33:40 2015
@@ -7,6 +7,7 @@ int main(int argc, char **argv)
struct isl_ctx *ctx;
struct isl_map *map;
struct isl_options *options;
+ isl_printer *p;
int exact;
options = isl_options_new_with_defaults();
@@ -15,19 +16,23 @@ int main(int argc, char **argv)
ctx = isl_ctx_alloc_with_options(&isl_options_args, options);
+ p = isl_printer_to_file(ctx, stdout);
+
map = isl_map_read_from_file(ctx, stdin);
map = isl_map_transitive_closure(map, &exact);
if (!exact)
- printf("# NOT exact\n");
- isl_map_print(map, stdout, 0, ISL_FORMAT_ISL);
- printf("\n");
+ p = isl_printer_print_str(p, "# NOT exact\n");
+ p = isl_printer_print_map(p, map);
+ p = isl_printer_end_line(p);
map = isl_map_compute_divs(map);
map = isl_map_coalesce(map);
- printf("# coalesced\n");
- isl_map_print(map, stdout, 0, ISL_FORMAT_ISL);
- printf("\n");
+ p = isl_printer_print_str(p, "# coalesced\n");
+ p = isl_printer_print_map(p, map);
+ p = isl_printer_end_line(p);
isl_map_free(map);
+ isl_printer_free(p);
+
isl_ctx_free(ctx);
return 0;
Modified: polly/trunk/lib/External/isl/doc/user.pod
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/doc/user.pod?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/doc/user.pod (original)
+++ polly/trunk/lib/External/isl/doc/user.pod Mon Feb 16 13:33:40 2015
@@ -492,12 +492,16 @@ in which the object was created.
__isl_keep isl_pw_multi_aff *pma);
isl_ctx *isl_multi_pw_aff_get_ctx(
__isl_keep isl_multi_pw_aff *mpa);
+ isl_ctx *isl_union_pw_aff_get_ctx(
+ __isl_keep isl_union_pw_aff *upa);
isl_ctx *isl_union_pw_multi_aff_get_ctx(
__isl_keep isl_union_pw_multi_aff *upma);
+ isl_ctx *isl_multi_union_pw_aff_get_ctx(
+ __isl_keep isl_multi_union_pw_aff *mupa);
#include <isl/id_to_ast_expr.h>
isl_ctx *isl_id_to_ast_expr_get_ctx(
- __isl_keep id_to_ast_expr *id2expr);
+ __isl_keep isl_id_to_ast_expr *id2expr);
#include <isl/point.h>
isl_ctx *isl_point_get_ctx(__isl_keep isl_point *pnt);
@@ -519,9 +523,15 @@ in which the object was created.
__isl_keep isl_restriction *restr);
#include <isl/schedule.h>
+ isl_ctx *isl_schedule_get_ctx(
+ __isl_keep isl_schedule *sched);
isl_ctx *isl_schedule_constraints_get_ctx(
__isl_keep isl_schedule_constraints *sc);
+ #include <isl/schedule_node.h>
+ isl_ctx *isl_schedule_node_get_ctx(
+ __isl_keep isl_schedule_node *node);
+
#include <isl/band.h>
isl_ctx *isl_band_get_ctx(__isl_keep isl_band *band);
@@ -954,12 +964,20 @@ of the original object.
__isl_keep isl_pw_multi_aff *pma);
__isl_give isl_space *isl_pw_multi_aff_get_space(
__isl_keep isl_pw_multi_aff *pma);
+ __isl_give isl_space *isl_union_pw_aff_get_space(
+ __isl_keep isl_union_pw_aff *upa);
__isl_give isl_space *isl_union_pw_multi_aff_get_space(
__isl_keep isl_union_pw_multi_aff *upma);
__isl_give isl_space *isl_multi_pw_aff_get_domain_space(
__isl_keep isl_multi_pw_aff *mpa);
__isl_give isl_space *isl_multi_pw_aff_get_space(
__isl_keep isl_multi_pw_aff *mpa);
+ __isl_give isl_space *
+ isl_multi_union_pw_aff_get_domain_space(
+ __isl_keep isl_multi_union_pw_aff *mupa);
+ __isl_give isl_space *
+ isl_multi_union_pw_aff_get_space(
+ __isl_keep isl_multi_union_pw_aff *mupa);
#include <isl/point.h>
__isl_give isl_space *isl_point_get_space(
@@ -1018,9 +1036,15 @@ C<isl_dim_out> (only for relations), C<i
unsigned isl_multi_pw_aff_dim(
__isl_keep isl_multi_pw_aff *mpa,
enum isl_dim_type type);
+ unsigned isl_union_pw_aff_dim(
+ __isl_keep isl_union_pw_aff *upa,
+ enum isl_dim_type type);
unsigned isl_union_pw_multi_aff_dim(
__isl_keep isl_union_pw_multi_aff *upma,
enum isl_dim_type type);
+ unsigned isl_multi_union_pw_aff_dim(
+ __isl_keep isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type);
#include <isl/polynomial.h>
unsigned isl_union_pw_qpolynomial_dim(
@@ -1164,6 +1188,11 @@ operations and may not be preserved acro
__isl_take isl_multi_pw_aff *mpa,
enum isl_dim_type type, unsigned pos,
__isl_take isl_id *id);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_set_dim_id(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type, unsigned pos,
+ __isl_take isl_id *id);
__isl_give isl_id *isl_multi_aff_get_dim_id(
__isl_keep isl_multi_aff *ma,
enum isl_dim_type type, unsigned pos);
@@ -1178,6 +1207,9 @@ operations and may not be preserved acro
__isl_give isl_id *isl_multi_pw_aff_get_dim_id(
__isl_keep isl_multi_pw_aff *mpa,
enum isl_dim_type type, unsigned pos);
+ __isl_give isl_id *isl_multi_union_pw_aff_get_dim_id(
+ __isl_keep isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type, unsigned pos);
__isl_give isl_aff *isl_aff_set_dim_name(
__isl_take isl_aff *aff, enum isl_dim_type type,
unsigned pos, const char *s);
@@ -1188,6 +1220,20 @@ operations and may not be preserved acro
isl_multi_pw_aff_set_dim_name(
__isl_take isl_multi_pw_aff *mpa,
enum isl_dim_type type, unsigned pos, const char *s);
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_aff_set_dim_name(
+ __isl_take isl_union_pw_aff *upa,
+ enum isl_dim_type type, unsigned pos,
+ const char *s);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_set_dim_name(
+ __isl_take isl_union_pw_multi_aff *upma,
+ enum isl_dim_type type, unsigned pos,
+ const char *s);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_set_dim_name(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type, unsigned pos,
const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
enum isl_dim_type type, unsigned pos);
const char *isl_pw_aff_get_dim_name(
@@ -1212,6 +1258,16 @@ operations and may not be preserved acro
__isl_take isl_pw_qpolynomial_fold *pwf,
enum isl_dim_type type, unsigned pos,
const char *s);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_set_dim_name(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ enum isl_dim_type type, unsigned pos,
+ const char *s);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_set_dim_name(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ enum isl_dim_type type, unsigned pos,
+ const char *s);
Note that C<isl_space_get_name> returns a pointer to some internal
data structure, so the result can only be used while the
@@ -1272,6 +1328,9 @@ its position can be obtained from the fo
int isl_multi_pw_aff_find_dim_by_id(
__isl_keep isl_multi_pw_aff *mpa,
enum isl_dim_type type, __isl_keep isl_id *id);
+ int isl_multi_union_pw_aff_find_dim_by_id(
+ __isl_keep isl_union_multi_pw_aff *mupa,
+ enum isl_dim_type type, __isl_keep isl_id *id);
int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff,
enum isl_dim_type type, const char *name);
int isl_multi_aff_find_dim_by_name(
@@ -1285,9 +1344,15 @@ its position can be obtained from the fo
int isl_pw_multi_aff_find_dim_by_name(
__isl_keep isl_pw_multi_aff *pma,
enum isl_dim_type type, const char *name);
+ int isl_union_pw_aff_find_dim_by_name(
+ __isl_keep isl_union_pw_aff *upa,
+ enum isl_dim_type type, const char *name);
int isl_union_pw_multi_aff_find_dim_by_name(
__isl_keep isl_union_pw_multi_aff *upma,
enum isl_dim_type type, const char *name);
+ int isl_multi_union_pw_aff_find_dim_by_name(
+ __isl_keep isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type, const char *name);
#include <isl/polynomial.h>
int isl_pw_qpolynomial_find_dim_by_name(
@@ -1410,6 +1475,10 @@ using the following functions.
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_tuple_id(
__isl_take isl_pw_multi_aff *pma,
enum isl_dim_type type, __isl_take isl_id *id);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_set_tuple_id(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type, __isl_take isl_id *id);
__isl_give isl_multi_aff *isl_multi_aff_reset_tuple_id(
__isl_take isl_multi_aff *ma,
enum isl_dim_type type);
@@ -1424,6 +1493,10 @@ using the following functions.
isl_pw_multi_aff_reset_tuple_id(
__isl_take isl_pw_multi_aff *pma,
enum isl_dim_type type);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_reset_tuple_id(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type);
int isl_multi_aff_has_tuple_id(__isl_keep isl_multi_aff *ma,
enum isl_dim_type type);
__isl_give isl_id *isl_multi_aff_get_tuple_id(
@@ -1446,6 +1519,12 @@ using the following functions.
__isl_give isl_id *isl_multi_pw_aff_get_tuple_id(
__isl_keep isl_multi_pw_aff *mpa,
enum isl_dim_type type);
+ int isl_multi_union_pw_aff_has_tuple_id(
+ __isl_keep isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type);
+ __isl_give isl_id *isl_multi_union_pw_aff_get_tuple_id(
+ __isl_keep isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type);
__isl_give isl_multi_aff *isl_multi_aff_set_tuple_name(
__isl_take isl_multi_aff *maff,
enum isl_dim_type type, const char *s);
@@ -1453,6 +1532,10 @@ using the following functions.
isl_multi_pw_aff_set_tuple_name(
__isl_take isl_multi_pw_aff *mpa,
enum isl_dim_type type, const char *s);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_set_tuple_name(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type, const char *s);
const char *isl_multi_aff_get_tuple_name(
__isl_keep isl_multi_aff *multi,
enum isl_dim_type type);
@@ -1462,6 +1545,9 @@ using the following functions.
const char *isl_pw_multi_aff_get_tuple_name(
__isl_keep isl_pw_multi_aff *pma,
enum isl_dim_type type);
+ const char *isl_multi_union_pw_aff_get_tuple_name(
+ __isl_keep isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type);
The C<type> argument needs to be one of C<isl_dim_in>, C<isl_dim_out>
or C<isl_dim_set>. As with C<isl_space_get_name>,
@@ -1500,8 +1586,34 @@ of all the corresponding identifiers, us
#include <isl/aff.h>
__isl_give isl_multi_aff *isl_multi_aff_reset_user(
__isl_take isl_multi_aff *ma);
+ __isl_give isl_pw_aff *isl_pw_aff_reset_user(
+ __isl_take isl_pw_aff *pa);
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_reset_user(
__isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_reset_user(
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_user(
+ __isl_take isl_union_pw_aff *upa);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_reset_user(
+ __isl_take isl_multi_union_pw_aff *mupa);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_reset_user(
+ __isl_take isl_union_pw_multi_aff *upma);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *
+ isl_pw_qpolynomial_reset_user(
+ __isl_take isl_pw_qpolynomial *pwqp);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_reset_user(
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_reset_user(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_reset_user(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf);
Spaces can be nested. In particular, the domain of a set or
the domain or range of a relation can be a nested relation.
@@ -1851,13 +1963,21 @@ or a list of affine expressions
__isl_take isl_multi_pw_aff *mpa);
__isl_give isl_map *isl_map_from_multi_pw_aff(
__isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_union_map *isl_union_map_from_union_pw_aff(
+ __isl_take isl_union_pw_aff *upa);
__isl_give isl_union_map *
isl_union_map_from_union_pw_multi_aff(
__isl_take isl_union_pw_multi_aff *upma);
+ __isl_give isl_union_map *
+ isl_union_map_from_multi_union_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa);
The C<domain_space> argument describes the domain of the resulting
basic relation. It is required because the C<list> may consist
of zero affine expressions.
+The C<mupa> passed to C<isl_union_map_from_multi_union_pw_aff>
+is not allowed to be zero-dimensional. The domain of the result
+is the shared domain of the union piecewise affine elements.
=head2 Inspecting Sets and Relations
@@ -2442,9 +2562,12 @@ a set space, the corresponding multiple
also has a set space.
Objects of the value type do not have an associated space.
The space of a multiple value is therefore always a set space.
+Similarly, the space of a multiple union piecewise
+affine expression is always a set space.
The multiple expression types defined by C<isl>
-are C<isl_multi_val>, C<isl_multi_aff> and C<isl_multi_pw_aff>.
+are C<isl_multi_val>, C<isl_multi_aff>, C<isl_multi_pw_aff>,
+C<isl_multi_union_pw_aff>.
A multiple expression with the value zero for
each output (or set) dimension can be created
@@ -2459,6 +2582,13 @@ using the following functions.
__isl_take isl_space *space);
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_zero(
__isl_take isl_space *space);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_zero(
+ __isl_take isl_space *space);
+
+Since there is no canonical way of representing a zero
+value of type C<isl_union_pw_aff>, the space passed
+to C<isl_multi_union_pw_aff_zero> needs to be zero-dimensional.
An identity function can be created using the following
functions. The space needs to be that of a relation
@@ -2488,13 +2618,19 @@ projection operations in L</"Unary Opera
A multiple expression can be created from a single
base expression using the following functions.
The space of the created multiple expression is the same
-as that of the base expression.
+as that of the base expression, except for
+C<isl_multi_union_pw_aff_from_union_pw_aff> where the input
+lives in a parameter space and the output lives
+in a single-dimensional set space.
#include <isl/aff.h>
__isl_give isl_multi_aff *isl_multi_aff_from_aff(
__isl_take isl_aff *aff);
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_aff(
__isl_take isl_pw_aff *pa);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_from_union_pw_aff(
+ __isl_take isl_union_pw_aff *upa);
A multiple expression can be created from a list
of base expression in a specified space.
@@ -2512,6 +2648,10 @@ then this space also needs to be a set s
__isl_give isl_multi_aff *isl_multi_aff_from_aff_list(
__isl_take isl_space *space,
__isl_take isl_aff_list *list);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_from_union_pw_aff_list(
+ __isl_take isl_space *space,
+ __isl_take isl_union_pw_aff_list *list);
As a convenience, a multiple piecewise expression can
also be created from a multiple expression.
@@ -2523,6 +2663,17 @@ universe cell.
isl_multi_pw_aff_from_multi_aff(
__isl_take isl_multi_aff *ma);
+Similarly, a multiple union expression can be
+created from a multiple expression.
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_from_multi_aff(
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_from_multi_pw_aff(
+ __isl_take isl_multi_pw_aff *mpa);
+
A multiple quasi-affine expression can be created from
a multiple value with a given domain space using the following
function.
@@ -2533,6 +2684,22 @@ function.
__isl_take isl_space *space,
__isl_take isl_multi_val *mv);
+Similarly,
+a multiple union piecewise affine expression can be created from
+a multiple value with a given domain or
+a multiple affine expression with a given domain
+using the following functions.
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_multi_val_on_domain(
+ __isl_take isl_union_set *domain,
+ __isl_take isl_multi_val *mv);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_multi_aff_on_domain(
+ __isl_take isl_union_set *domain,
+ __isl_take isl_multi_aff *ma);
+
Multiple expressions can be copied and freed using
the following functions.
@@ -2551,6 +2718,12 @@ the following functions.
__isl_keep isl_multi_pw_aff *mpa);
__isl_null isl_multi_pw_aff *isl_multi_pw_aff_free(
__isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_copy(
+ __isl_keep isl_multi_union_pw_aff *mupa);
+ __isl_null isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_free(
+ __isl_take isl_multi_union_pw_aff *mupa);
The base expression at a given position of a multiple
expression can be extracted using the following functions.
@@ -2564,6 +2737,9 @@ expression can be extracted using the fo
__isl_keep isl_multi_aff *multi, int pos);
__isl_give isl_pw_aff *isl_multi_pw_aff_get_pw_aff(
__isl_keep isl_multi_pw_aff *mpa, int pos);
+ __isl_give isl_union_pw_aff *
+ isl_multi_union_pw_aff_get_union_pw_aff(
+ __isl_keep isl_multi_union_pw_aff *mupa, int pos);
It can be replaced using the following functions.
@@ -2576,6 +2752,48 @@ It can be replaced using the following f
__isl_give isl_multi_aff *isl_multi_aff_set_aff(
__isl_take isl_multi_aff *multi, int pos,
__isl_take isl_aff *aff);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_set_union_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa, int pos,
+ __isl_take isl_union_pw_aff *upa);
+
+As a convenience, a sequence of base expressions that have
+their domains in a given space can be extracted from a sequence
+of union expressions using the following function.
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_pw_aff *
+ isl_multi_union_pw_aff_extract_multi_pw_aff(
+ __isl_keep isl_multi_union_pw_aff *mupa,
+ __isl_take isl_space *space);
+
+Note that there is a difference between C<isl_multi_union_pw_aff>
+and C<isl_union_pw_multi_aff> objects. The first is a sequence
+of unions of piecewise expressions, while the second is a union
+of piecewise sequences. In particular, multiple affine expressions
+in an C<isl_union_pw_multi_aff> may live in different spaces,
+while there is only a single multiple expression in
+an C<isl_multi_union_pw_aff>, which can therefore only live
+in a single space. This means that not every
+C<isl_union_pw_multi_aff> can be converted to
+an C<isl_multi_union_pw_aff>. Conversely, a zero-dimensional
+C<isl_multi_union_pw_aff> carries no information
+about any possible domain and therefore cannot be converted
+to an C<isl_union_pw_multi_aff>. Moreover, the elements
+of an C<isl_multi_union_pw_aff> may be defined over different domains,
+while each multiple expression inside an C<isl_union_pw_multi_aff>
+has a single domain. The conversion of an C<isl_union_pw_multi_aff>
+of dimension greater than one may therefore not be exact.
+The following functions can
+be used to perform these conversions when they are possible.
+
+ #include <isl/aff.h>
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_from_union_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_from_multi_union_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa);
=head3 Piecewise Expressions
@@ -2663,6 +2881,8 @@ then create a piecewise expression over
__isl_take isl_space *space);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity(
__isl_take isl_space *space);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_map(
+ __isl_take isl_space *space);
__isl_give isl_pw_multi_aff *
isl_pw_multi_aff_project_out_map(
__isl_take isl_space *space,
@@ -2822,12 +3042,14 @@ over different domains. The space of a
is that of the shared parameter space.
The union expression types defined by C<isl>
-are C<isl_union_pw_multi_aff>, C<isl_union_pw_qpolynomial> and
-C<isl_union_pw_qpolynomial_fold>.
+are C<isl_union_pw_aff>, C<isl_union_pw_multi_aff>,
+C<isl_union_pw_qpolynomial> and C<isl_union_pw_qpolynomial_fold>.
An empty union expression can be created using the following functions.
#include <isl/aff.h>
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_empty(
+ __isl_take isl_space *space);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_empty(
__isl_take isl_space *space);
@@ -2841,6 +3063,12 @@ A union expression containing a single b
can be created using the following functions.
#include <isl/aff.h>
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_aff_from_pw_aff(
+ __isl_take isl_pw_aff *pa);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_from_aff(
+ __isl_take isl_aff *aff);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_from_pw_multi_aff(
__isl_take isl_pw_multi_aff *pma);
@@ -2850,19 +3078,43 @@ can be created using the following funct
isl_union_pw_qpolynomial_from_pw_qpolynomial(
__isl_take isl_pw_qpolynomial *pwqp);
-The following function creates a base expression on each
-of the sets in the union set and collects the results.
+The following functions create a base expression on each
+of the sets in the union set and collect the results.
#include <isl/aff.h>
__isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_from_union_pw_aff(
+ __isl_take isl_union_pw_aff *upa);
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_multi_aff_get_union_pw_aff(
+ __isl_keep isl_union_pw_multi_aff *upma, int pos);
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_aff_val_on_domain(
+ __isl_take isl_union_set *domain,
+ __isl_take isl_val *v);
+ __isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_multi_val_on_domain(
__isl_take isl_union_set *domain,
__isl_take isl_multi_val *mv);
+An C<isl_union_pw_aff> that is equal to a (parametric) affine
+expression on a given domain can be created using the following
+function.
+
+ #include <isl/aff.h>
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_aff_aff_on_domain(
+ __isl_take isl_union_set *domain,
+ __isl_take isl_aff *aff);
+
A base expression can be added to a union expression using
the following functions.
#include <isl/aff.h>
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_aff_add_pw_aff(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_pw_aff *pa);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_add_pw_multi_aff(
__isl_take isl_union_pw_multi_aff *upma,
@@ -2878,6 +3130,10 @@ Union expressions can be copied and free
the following functions.
#include <isl/aff.h>
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_copy(
+ __isl_keep isl_union_pw_aff *upa);
+ __isl_null isl_union_pw_aff *isl_union_pw_aff_free(
+ __isl_take isl_union_pw_aff *upa);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_copy(
__isl_keep isl_union_pw_multi_aff *upma);
@@ -2903,16 +3159,28 @@ To iterate over the base expressions in
use the following functions.
#include <isl/aff.h>
+ int isl_union_pw_aff_n_pw_aff(
+ __isl_keep isl_union_pw_aff *upa);
+ int isl_union_pw_aff_foreach_pw_aff(
+ __isl_keep isl_union_pw_aff *upa,
+ int (*fn)(__isl_take isl_pw_aff *ma, void *user),
+ void *user);
+ int isl_union_pw_multi_aff_n_pw_multi_aff(
+ __isl_keep isl_union_pw_multi_aff *upma);
int isl_union_pw_multi_aff_foreach_pw_multi_aff(
__isl_keep isl_union_pw_multi_aff *upma,
int (*fn)(__isl_take isl_pw_multi_aff *pma,
void *user), void *user);
#include <isl/polynomial.h>
+ int isl_union_pw_qpolynomial_n_pw_qpolynomial(
+ __isl_keep isl_union_pw_qpolynomial *upwqp);
int isl_union_pw_qpolynomial_foreach_pw_qpolynomial(
__isl_keep isl_union_pw_qpolynomial *upwqp,
int (*fn)(__isl_take isl_pw_qpolynomial *pwqp,
void *user), void *user);
+ int isl_union_pw_qpolynomial_fold_n_pw_qpolynomial_fold(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
int isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(
__isl_keep isl_union_pw_qpolynomial_fold *upwf,
int (*fn)(__isl_take isl_pw_qpolynomial_fold *pwf,
@@ -2922,6 +3190,9 @@ To extract the base expression in a give
the following functions.
#include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_union_pw_aff_extract_pw_aff(
+ __isl_keep isl_union_pw_aff *upa,
+ __isl_take isl_space *space);
__isl_give isl_pw_multi_aff *
isl_union_pw_multi_aff_extract_pw_multi_aff(
__isl_keep isl_union_pw_multi_aff *upma,
@@ -3000,6 +3271,8 @@ Objects can be read from input using the
#include <isl/val.h>
__isl_give isl_val *isl_val_read_from_str(isl_ctx *ctx,
const char *str);
+ __isl_give isl_multi_val *isl_multi_val_read_from_str(
+ isl_ctx *ctx, const char *str);
#include <isl/set.h>
__isl_give isl_basic_set *isl_basic_set_read_from_file(
@@ -3047,6 +3320,9 @@ Objects can be read from input using the
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_read_from_str(
isl_ctx *ctx, const char *str);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_read_from_str(
+ isl_ctx *ctx, const char *str);
#include <isl/polynomial.h>
__isl_give isl_union_pw_qpolynomial *
@@ -3076,6 +3352,7 @@ The printer can be inspected using the f
__isl_keep isl_printer *printer);
int isl_printer_get_output_format(
__isl_keep isl_printer *p);
+ int isl_printer_get_yaml_style(__isl_keep isl_printer *p);
The behavior of the printer can be modified in various ways
@@ -3091,6 +3368,8 @@ The behavior of the printer can be modif
__isl_take isl_printer *p, const char *prefix);
__isl_give isl_printer *isl_printer_set_suffix(
__isl_take isl_printer *p, const char *suffix);
+ __isl_give isl_printer *isl_printer_set_yaml_style(
+ __isl_take isl_printer *p, int yaml_style);
The C<output_format> may be either C<ISL_FORMAT_ISL>, C<ISL_FORMAT_OMEGA>,
C<ISL_FORMAT_POLYLIB>, C<ISL_FORMAT_EXT_POLYLIB> or C<ISL_FORMAT_LATEX>
@@ -3104,6 +3383,9 @@ appear between those of the set variable
of the parameters.
The function C<isl_printer_indent> increases the indentation
by the specified amount (which may be negative).
+The YAML style may be either C<ISL_YAML_STYLE_BLOCK> or
+C<ISL_YAML_STYLE_FLOW> and when we are printing something
+in YAML format.
To actually print something, use
@@ -3161,9 +3443,16 @@ To actually print something, use
__isl_give isl_printer *isl_printer_print_multi_pw_aff(
__isl_take isl_printer *p,
__isl_keep isl_multi_pw_aff *mpa);
+ __isl_give isl_printer *isl_printer_print_union_pw_aff(
+ __isl_take isl_printer *p,
+ __isl_keep isl_union_pw_aff *upa);
__isl_give isl_printer *isl_printer_print_union_pw_multi_aff(
__isl_take isl_printer *p,
__isl_keep isl_union_pw_multi_aff *upma);
+ __isl_give isl_printer *
+ isl_printer_print_multi_union_pw_aff(
+ __isl_take isl_printer *p,
+ __isl_keep isl_multi_union_pw_aff *mupa);
#include <isl/polynomial.h>
__isl_give isl_printer *isl_printer_print_qpolynomial(
@@ -3196,6 +3485,34 @@ is supported.
In case of printing in C<ISL_FORMAT_C>, the user may want
to set the names of all dimensions first.
+C<isl> also provides limited support for printing YAML documents,
+just enough for the internal use for printing such documents.
+
+ #include <isl/printer.h>
+ __isl_give isl_printer *isl_printer_yaml_start_mapping(
+ __isl_take isl_printer *p);
+ __isl_give isl_printer *isl_printer_yaml_end_mapping(
+ __isl_take isl_printer *p);
+ __isl_give isl_printer *isl_printer_yaml_start_sequence(
+ __isl_take isl_printer *p);
+ __isl_give isl_printer *isl_printer_yaml_end_sequence(
+ __isl_take isl_printer *p);
+ __isl_give isl_printer *isl_printer_yaml_next(
+ __isl_take isl_printer *p);
+
+A document is started by a call to either
+C<isl_printer_yaml_start_mapping> or C<isl_printer_yaml_start_sequence>.
+Anything printed to the printer after such a call belong to the
+first key of the mapping or the first element in the sequence.
+The function C<isl_printer_yaml_next> moves to the value if
+we are currently printing a mapping key, the next key if we
+are printing a value or the next element if we are printing
+an element in a sequence.
+Nested mappings and sequences are initiated by the same
+C<isl_printer_yaml_start_mapping> or C<isl_printer_yaml_start_sequence>.
+Each call to these functions needs to have a corresponding call to
+C<isl_printer_yaml_end_mapping> or C<isl_printer_yaml_end_sequence>.
+
When called on a file printer, the following function flushes
the file. When called on a string printer, the buffer is cleared.
@@ -3234,8 +3551,12 @@ in isl format.
#include <isl/aff.h>
__isl_give char *isl_multi_aff_to_str(
__isl_keep isl_multi_aff *aff);
+ __isl_give char *isl_union_pw_aff_to_str(
+ __isl_keep isl_union_pw_aff *upa);
__isl_give char *isl_union_pw_multi_aff_to_str(
__isl_keep isl_union_pw_multi_aff *upma);
+ __isl_give char *isl_multi_union_pw_aff_to_str(
+ __isl_keep isl_multi_union_pw_aff *mupa);
=head2 Properties
@@ -3431,6 +3752,8 @@ The following functions check whether th
__isl_keep isl_multi_aff *ma);
int isl_multi_pw_aff_range_is_wrapping(
__isl_keep isl_multi_pw_aff *mpa);
+ int isl_multi_union_pw_aff_range_is_wrapping(
+ __isl_keep isl_multi_union_pw_aff *mupa);
The input to C<isl_space_is_wrapping> should
be the space of a set, while that of
@@ -3541,9 +3864,15 @@ return true if the objects are not the s
int isl_multi_pw_aff_is_equal(
__isl_keep isl_multi_pw_aff *mpa1,
__isl_keep isl_multi_pw_aff *mpa2);
+ int isl_union_pw_aff_plain_is_equal(
+ __isl_keep isl_union_pw_aff *upa1,
+ __isl_keep isl_union_pw_aff *upa2);
int isl_union_pw_multi_aff_plain_is_equal(
__isl_keep isl_union_pw_multi_aff *upma1,
__isl_keep isl_union_pw_multi_aff *upma2);
+ int isl_multi_union_pw_aff_plain_is_equal(
+ __isl_keep isl_multi_union_pw_aff *mupa1,
+ __isl_keep isl_multi_union_pw_aff *mupa2);
#include <isl/polynomial.h>
int isl_union_pw_qpolynomial_plain_is_equal(
@@ -3555,6 +3884,7 @@ return true if the objects are not the s
=item * Disjointness
+ #include <isl/set.h>
int isl_basic_set_is_disjoint(
__isl_keep isl_basic_set *bset1,
__isl_keep isl_basic_set *bset2);
@@ -3562,12 +3892,24 @@ return true if the objects are not the s
__isl_keep isl_set *set2);
int isl_set_is_disjoint(__isl_keep isl_set *set1,
__isl_keep isl_set *set2);
+
+ #include <isl/map.h>
int isl_basic_map_is_disjoint(
__isl_keep isl_basic_map *bmap1,
__isl_keep isl_basic_map *bmap2);
int isl_map_is_disjoint(__isl_keep isl_map *map1,
__isl_keep isl_map *map2);
+ #include <isl/union_set.h>
+ int isl_union_set_is_disjoint(
+ __isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2);
+
+ #include <isl/union_map.h>
+ int isl_union_map_is_disjoint(
+ __isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2);
+
=item * Subset
int isl_basic_set_is_subset(
@@ -3726,9 +4068,16 @@ earlier dimensions before those that inv
__isl_take isl_map *map);
#include <isl/union_set.h>
+ __isl_give isl_union_set *isl_union_set_project_out(
+ __isl_take isl_union_set *uset,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
__isl_give isl_set *isl_union_set_params(
__isl_take isl_union_set *uset);
+The function C<isl_union_set_project_out> can only project out
+parameters.
+
#include <isl/union_map.h>
__isl_give isl_union_map *isl_union_map_project_out(
__isl_take isl_union_map *umap,
@@ -3755,11 +4104,19 @@ parameters.
__isl_take isl_pw_multi_aff *pma);
__isl_give isl_set *isl_multi_pw_aff_domain(
__isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_union_set *isl_union_pw_aff_domain(
+ __isl_take isl_union_pw_aff *upa);
__isl_give isl_union_set *isl_union_pw_multi_aff_domain(
__isl_take isl_union_pw_multi_aff *upma);
+ __isl_give isl_union_set *
+ isl_multi_union_pw_aff_domain(
+ __isl_take isl_multi_union_pw_aff *mupa);
__isl_give isl_set *isl_pw_aff_params(
__isl_take isl_pw_aff *pwa);
+The function C<isl_multi_union_pw_aff_domain> requires its
+input to have at least one set dimension.
+
#include <isl/polynomial.h>
__isl_give isl_qpolynomial *
isl_qpolynomial_project_domain_on_params(
@@ -3796,6 +4153,9 @@ parameters.
#include <isl/union_map.h>
__isl_give isl_union_map *isl_union_map_domain_map(
__isl_take isl_union_map *umap);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_map_domain_map_union_pw_multi_aff(
+ __isl_take isl_union_map *umap);
__isl_give isl_union_map *isl_union_map_range_map(
__isl_take isl_union_map *umap);
__isl_give isl_union_map *
@@ -3880,6 +4240,9 @@ flat anonymous space.
__isl_take isl_pw_aff *pwa);
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_range(
__isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_from_range(
+ __isl_take isl_multi_union_pw_aff *mupa);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain(
__isl_take isl_set *set);
__isl_give isl_union_pw_multi_aff *
@@ -4017,12 +4380,20 @@ dimensions satisfy the given ordering.
__isl_take isl_aff *aff);
__isl_give isl_basic_set *isl_aff_neg_basic_set(
__isl_take isl_aff *aff);
+ __isl_give isl_set *isl_pw_aff_pos_set(
+ __isl_take isl_pw_aff *pa);
__isl_give isl_set *isl_pw_aff_nonneg_set(
__isl_take isl_pw_aff *pwaff);
__isl_give isl_set *isl_pw_aff_zero_set(
__isl_take isl_pw_aff *pwaff);
__isl_give isl_set *isl_pw_aff_non_zero_set(
__isl_take isl_pw_aff *pwaff);
+ __isl_give isl_union_set *
+ isl_union_pw_aff_zero_union_set(
+ __isl_take isl_union_pw_aff *upa);
+ __isl_give isl_union_set *
+ isl_multi_union_pw_aff_zero_union_set(
+ __isl_take isl_multi_union_pw_aff *mupa);
The function C<isl_aff_neg_basic_set> returns a basic set
containing those elements in the domain space
@@ -4030,6 +4401,9 @@ of C<aff> where C<aff> is negative.
The function C<isl_pw_aff_nonneg_set> returns a set
containing those elements in the domain
of C<pwaff> where C<pwaff> is non-negative.
+The function C<isl_multi_union_pw_aff_zero_union_set>
+returns a union set containing those elements
+in the domains of its elements where they are all zero.
=item * Identity
@@ -4037,6 +4411,9 @@ of C<pwaff> where C<pwaff> is non-negati
__isl_take isl_set *set);
__isl_give isl_union_map *isl_union_set_identity(
__isl_take isl_union_set *uset);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_set_identity_union_pw_multi_aff(
+ __isl_take isl_union_set *uset);
Construct an identity relation on the given (union) set.
@@ -4055,7 +4432,11 @@ and the C<isl_map> is single-valued.
In case of a conversion from an C<isl_union_map>
to an C<isl_union_pw_multi_aff>, these properties need to hold
in each domain space.
+A conversion to a C<isl_multi_union_pw_aff> additionally
+requires that the input is non-empty and involves only a single
+range space.
+ #include <isl/aff.h>
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_set(
__isl_take isl_set *set);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(
@@ -4068,6 +4449,10 @@ in each domain space.
isl_union_pw_multi_aff_from_union_map(
__isl_take isl_union_map *umap);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_from_union_map(
+ __isl_take isl_union_map *umap);
+
=item * Deltas
__isl_give isl_basic_set *isl_basic_map_deltas(
@@ -4116,6 +4501,8 @@ basic set or relation.
__isl_take isl_pw_multi_aff *pma);
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_coalesce(
__isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_coalesce(
+ __isl_take isl_union_pw_aff *upa);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_coalesce(
__isl_take isl_union_pw_multi_aff *upma);
@@ -4162,15 +4549,28 @@ equalities.
=item * Removing redundant constraints
+ #include <isl/set.h>
__isl_give isl_basic_set *isl_basic_set_remove_redundancies(
__isl_take isl_basic_set *bset);
__isl_give isl_set *isl_set_remove_redundancies(
__isl_take isl_set *set);
+
+ #include <isl/union_set.h>
+ __isl_give isl_union_set *
+ isl_union_set_remove_redundancies(
+ __isl_take isl_union_set *uset);
+
+ #include <isl/map.h>
__isl_give isl_basic_map *isl_basic_map_remove_redundancies(
__isl_take isl_basic_map *bmap);
__isl_give isl_map *isl_map_remove_redundancies(
__isl_take isl_map *map);
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *
+ isl_union_map_remove_redundancies(
+ __isl_take isl_union_map *umap);
+
=item * Convex hull
__isl_give isl_basic_set *isl_set_convex_hull(
@@ -4200,6 +4600,10 @@ variables, then the result of these oper
__isl_take isl_map *map);
__isl_give isl_basic_map *isl_map_simple_hull(
__isl_take isl_map *map);
+ __isl_give isl_basic_map *
+ isl_map_unshifted_simple_hull_from_map_list(
+ __isl_take isl_map *map,
+ __isl_take isl_map_list *list);
#include <isl/union_map.h>
__isl_give isl_union_map *isl_union_map_simple_hull(
@@ -4211,7 +4615,8 @@ In particular, the output is described b
of the constraints describing the basic sets or relations in the input.
In case of C<isl_set_unshifted_simple_hull>, only the original
constraints are used, without any translation.
-In case of C<isl_set_unshifted_simple_hull_from_set_list>, the
+In case of C<isl_set_unshifted_simple_hull_from_set_list> and
+C<isl_map_unshifted_simple_hull_from_map_list>, the
constraints are taken from the elements of the second argument.
=begin latex
@@ -4437,6 +4842,10 @@ the overapproximation), then you will ge
__isl_give isl_space *isl_space_unwrap(
__isl_take isl_space *space);
+ #include <isl/local_space.h>
+ __isl_give isl_local_space *isl_local_space_wrap(
+ __isl_take isl_local_space *ls);
+
#include <isl/set.h>
__isl_give isl_basic_map *isl_basic_set_unwrap(
__isl_take isl_basic_set *bset);
@@ -4509,6 +4918,9 @@ then the name of the space is also remov
__isl_give isl_multi_pw_aff *
isl_multi_pw_aff_flatten_range(
__isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_flatten_range(
+ __isl_take isl_multi_union_pw_aff *mupa);
#include <isl/map.h>
__isl_give isl_map *isl_set_flatten_map(
@@ -4648,10 +5060,18 @@ All parameters need to be named.
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_align_params(
__isl_take isl_pw_multi_aff *pma,
__isl_take isl_space *model);
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_aff_align_params(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_space *model);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_align_params(
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_space *model);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_align_params(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_space *model);
#include <isl/polynomial.h>
__isl_give isl_qpolynomial *isl_qpolynomial_align_params(
@@ -4660,11 +5080,29 @@ All parameters need to be named.
=item * Unary Arithmethic Operations
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_neg(
+ __isl_take isl_multi_val *mv);
+
#include <isl/aff.h>
__isl_give isl_aff *isl_aff_neg(
__isl_take isl_aff *aff);
+ __isl_give isl_multi_aff *isl_multi_aff_neg(
+ __isl_take isl_multi_aff *ma);
__isl_give isl_pw_aff *isl_pw_aff_neg(
__isl_take isl_pw_aff *pwaff);
+ __isl_give isl_pw_multi_aff *isl_pw_multi_aff_neg(
+ __isl_take isl_pw_multi_aff *pma);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_neg(
+ __isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_neg(
+ __isl_take isl_union_pw_aff *upa);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_neg(
+ __isl_take isl_union_pw_multi_aff *upma);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_neg(
+ __isl_take isl_multi_union_pw_aff *mupa);
__isl_give isl_aff *isl_aff_ceil(
__isl_take isl_aff *aff);
__isl_give isl_pw_aff *isl_pw_aff_ceil(
@@ -4675,6 +5113,11 @@ All parameters need to be named.
__isl_take isl_multi_aff *ma);
__isl_give isl_pw_aff *isl_pw_aff_floor(
__isl_take isl_pw_aff *pwaff);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_floor(
+ __isl_take isl_union_pw_aff *upa);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_floor(
+ __isl_take isl_multi_union_pw_aff *mupa);
#include <isl/aff.h>
__isl_give isl_pw_aff *isl_pw_aff_list_min(
@@ -4846,6 +5289,19 @@ are not sufficient.
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_drop_dims(
__isl_take isl_pw_multi_aff *pma,
enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_drop_dims(
+ __isl_take isl_union_pw_aff *upa,
+ enum isl_dim_type type, unsigned first, unsigned n);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_drop_dims(
+ __isl_take isl_union_pw_multi_aff *upma,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_drop_dims(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ enum isl_dim_type type, unsigned first,
+ unsigned n);
__isl_give isl_aff *isl_aff_move_dims(
__isl_take isl_aff *aff,
enum isl_dim_type dst_type, unsigned dst_pos,
@@ -4867,6 +5323,20 @@ are not sufficient.
enum isl_dim_type src_type, unsigned src_pos,
unsigned n);
+ #include <isl/polynomial.h>
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_drop_dims(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_drop_dims(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ enum isl_dim_type type,
+ unsigned first, unsigned n);
+
+The operations on union expressions can only manipulate parameters.
+
=back
=head2 Binary Operations
@@ -4912,6 +5382,8 @@ the same (number of) parameters.
__isl_give isl_basic_map *isl_basic_map_intersect(
__isl_take isl_basic_map *bmap1,
__isl_take isl_basic_map *bmap2);
+ __isl_give isl_basic_map *isl_basic_map_list_intersect(
+ __isl_take isl_basic_map_list *list);
__isl_give isl_map *isl_map_intersect_params(
__isl_take isl_map *map,
__isl_take isl_set *params);
@@ -4958,10 +5430,17 @@ the same (number of) parameters.
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_intersect_domain(
__isl_take isl_pw_multi_aff *pma,
__isl_take isl_set *set);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_intersect_domain(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_union_set *uset);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_intersect_domain(
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_union_set *uset);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_intersect_domain(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_union_set *uset);
__isl_give isl_pw_aff *isl_pw_aff_intersect_params(
__isl_take isl_pw_aff *pa,
__isl_take isl_set *set);
@@ -4972,10 +5451,20 @@ the same (number of) parameters.
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_intersect_params(
__isl_take isl_pw_multi_aff *pma,
__isl_take isl_set *set);
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_aff_intersect_params(
+ __isl_take isl_union_pw_aff *upa,
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_intersect_params(
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_set *set);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_intersect_params(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_set *params);
+ isl_multi_union_pw_aff_intersect_range(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_set *set);
#include <isl/polynomial.h>
__isl_give isl_pw_qpolynomial *
@@ -5013,33 +5502,48 @@ for either argument is only allowed if t
a parametric set as well.
The list passed to C<isl_basic_set_list_intersect> needs to have
at least one element and all elements need to live in the same space.
+The function C<isl_multi_union_pw_aff_intersect_range>
+restricts the input function to those shared domain elements
+that map to the specified range.
=item * Union
+ #include <isl/set.h>
__isl_give isl_set *isl_basic_set_union(
__isl_take isl_basic_set *bset1,
__isl_take isl_basic_set *bset2);
- __isl_give isl_map *isl_basic_map_union(
- __isl_take isl_basic_map *bmap1,
- __isl_take isl_basic_map *bmap2);
__isl_give isl_set *isl_set_union(
__isl_take isl_set *set1,
__isl_take isl_set *set2);
+
+ #include <isl/map.h>
+ __isl_give isl_map *isl_basic_map_union(
+ __isl_take isl_basic_map *bmap1,
+ __isl_take isl_basic_map *bmap2);
__isl_give isl_map *isl_map_union(
__isl_take isl_map *map1,
__isl_take isl_map *map2);
+
+ #include <isl/union_set.h>
__isl_give isl_union_set *isl_union_set_union(
__isl_take isl_union_set *uset1,
__isl_take isl_union_set *uset2);
+ __isl_give isl_union_set *isl_union_set_list_union(
+ __isl_take isl_union_set_list *list);
+
+ #include <isl/union_map.h>
__isl_give isl_union_map *isl_union_map_union(
__isl_take isl_union_map *umap1,
__isl_take isl_union_map *umap2);
=item * Set difference
+ #include <isl/set.h>
__isl_give isl_set *isl_set_subtract(
__isl_take isl_set *set1,
__isl_take isl_set *set2);
+
+ #include <isl/map.h>
__isl_give isl_map *isl_map_subtract(
__isl_take isl_map *map1,
__isl_take isl_map *map2);
@@ -5049,9 +5553,13 @@ at least one element and all elements ne
__isl_give isl_map *isl_map_subtract_range(
__isl_take isl_map *map,
__isl_take isl_set *dom);
+
+ #include <isl/union_set.h>
__isl_give isl_union_set *isl_union_set_subtract(
__isl_take isl_union_set *uset1,
__isl_take isl_union_set *uset2);
+
+ #include <isl/union_map.h>
__isl_give isl_union_map *isl_union_map_subtract(
__isl_take isl_union_map *umap1,
__isl_take isl_union_map *umap2);
@@ -5062,6 +5570,41 @@ at least one element and all elements ne
__isl_take isl_union_map *umap,
__isl_take isl_union_set *dom);
+ #include <isl/aff.h>
+ __isl_give isl_pw_aff *isl_pw_aff_subtract_domain(
+ __isl_take isl_pw_aff *pa,
+ __isl_take isl_set *set);
+ __isl_give isl_pw_multi_aff *
+ isl_pw_multi_aff_subtract_domain(
+ __isl_take isl_pw_multi_aff *pma,
+ __isl_take isl_set *set);
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_aff_subtract_domain(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_subtract_domain(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_set *set);
+
+ #include <isl/polynomial.h>
+ __isl_give isl_pw_qpolynomial *
+ isl_pw_qpolynomial_subtract_domain(
+ __isl_take isl_pw_qpolynomial *pwpq,
+ __isl_take isl_set *set);
+ __isl_give isl_pw_qpolynomial_fold *
+ isl_pw_qpolynomial_fold_subtract_domain(
+ __isl_take isl_pw_qpolynomial_fold *pwf,
+ __isl_take isl_set *set);
+ __isl_give isl_union_pw_qpolynomial *
+ isl_union_pw_qpolynomial_subtract_domain(
+ __isl_take isl_union_pw_qpolynomial *upwpq,
+ __isl_take isl_union_set *uset);
+ __isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_subtract_domain(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_union_set *uset);
+
=item * Application
#include <isl/space.h>
@@ -5100,6 +5643,33 @@ at least one element and all elements ne
__isl_take isl_union_map *umap1,
__isl_take isl_union_map *umap2);
+ #include <isl/aff.h>
+ __isl_give isl_union_pw_aff *
+ isl_multi_union_pw_aff_apply_aff(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_aff *aff);
+ __isl_give isl_union_pw_aff *
+ isl_multi_union_pw_aff_apply_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_pw_aff *pa);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_apply_multi_aff(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_multi_aff *ma);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_apply_pw_multi_aff(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_pw_multi_aff *pma);
+
+The result of C<isl_multi_union_pw_aff_apply_aff> is defined
+over the shared domain of the elements of the input. The dimension is
+required to be greater than zero.
+The C<isl_multi_union_pw_aff> argument of
+C<isl_multi_union_pw_aff_apply_multi_aff> is allowed to be zero-dimensional,
+but only if the range of the C<isl_multi_aff> argument
+is also zero-dimensional.
+Similarly for C<isl_multi_union_pw_aff_apply_pw_multi_aff>.
+
#include <isl/polynomial.h>
__isl_give isl_pw_qpolynomial_fold *
isl_set_apply_pw_qpolynomial_fold(
@@ -5262,6 +5832,18 @@ into the set description or into the dom
isl_multi_pw_aff_pullback_multi_pw_aff(
__isl_take isl_multi_pw_aff *mpa1,
__isl_take isl_multi_pw_aff *mpa2);
+ __isl_give isl_union_pw_aff *
+ isl_union_pw_aff_pullback_union_pw_multi_aff(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_union_pw_multi_aff *upma);
+ __isl_give isl_union_pw_multi_aff *
+ isl_union_pw_multi_aff_pullback_union_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma1,
+ __isl_take isl_union_pw_multi_aff *upma2);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_union_pw_multi_aff *upma);
These functions precompose the first expression by the second function.
In other words, the second function is plugged
@@ -5335,6 +5917,47 @@ equal to C<ma2>.
The functions operating on C<isl_pw_aff_list> apply the corresponding
C<isl_pw_aff> function to each pair of elements in the two lists.
+ #include <isl/aff.h>
+ __isl_give isl_map *isl_pw_aff_eq_map(
+ __isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2);
+ __isl_give isl_map *isl_pw_aff_lt_map(
+ __isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2);
+ __isl_give isl_map *isl_pw_aff_gt_map(
+ __isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2);
+
+ __isl_give isl_map *isl_multi_pw_aff_eq_map(
+ __isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2);
+ __isl_give isl_map *isl_multi_pw_aff_lex_lt_map(
+ __isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2);
+ __isl_give isl_map *isl_multi_pw_aff_lex_gt_map(
+ __isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2);
+
+These functions return a map between domain elements of the arguments
+where the function values satisfy the given relation.
+
+ #include <isl/union_map.h>
+ __isl_give isl_union_map *
+ isl_union_map_eq_at_multi_union_pw_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_union_pw_aff *mupa);
+ __isl_give isl_union_map *
+ isl_union_map_lex_lt_at_multi_union_pw_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_union_pw_aff *mupa);
+ __isl_give isl_union_map *
+ isl_union_map_lex_gt_at_multi_union_pw_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_union_pw_aff *mupa);
+
+These functions select the subset of elements in the union map
+that have an equal or lexicographically smaller function value.
+
=item * Cartesian Product
#include <isl/space.h>
@@ -5430,6 +6053,10 @@ two input spaces.
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_product(
__isl_take isl_pw_multi_aff *pma1,
__isl_take isl_pw_multi_aff *pma2);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_range_product(
+ __isl_take isl_multi_union_pw_aff *mupa1,
+ __isl_take isl_multi_union_pw_aff *mupa2);
The above functions compute the cross product of the given
sets, relations or functions. The domains and ranges of the results
@@ -5464,6 +6091,10 @@ instead.
#include <isl/union_map.h>
__isl_give isl_union_map *
+ isl_union_map_flat_domain_product(
+ __isl_take isl_union_map *umap1,
+ __isl_take isl_union_map *umap2);
+ __isl_give isl_union_map *
isl_union_map_flat_range_product(
__isl_take isl_union_map *umap1,
__isl_take isl_union_map *umap2);
@@ -5489,6 +6120,10 @@ instead.
isl_union_pw_multi_aff_flat_range_product(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_flat_range_product(
+ __isl_take isl_multi_union_pw_aff *mupa1,
+ __isl_take isl_multi_union_pw_aff *mupa2);
#include <isl/space.h>
__isl_give isl_space *isl_space_factor_domain(
@@ -5561,6 +6196,12 @@ from the result using the following func
__isl_give isl_multi_pw_aff *
isl_multi_pw_aff_range_factor_range(
__isl_take isl_multi_pw_aff *mpa);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_range_factor_domain(
+ __isl_take isl_multi_union_pw_aff *mupa);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_range_factor_range(
+ __isl_take isl_multi_union_pw_aff *mupa);
The splice functions are a generalization of the flat product functions,
where the second argument may be inserted at any position inside
@@ -5587,6 +6228,11 @@ the first argument rather than being pla
__isl_take isl_multi_pw_aff *mpa1,
unsigned in_pos, unsigned out_pos,
__isl_take isl_multi_pw_aff *mpa2);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_range_splice(
+ __isl_take isl_multi_union_pw_aff *mupa1,
+ unsigned pos,
+ __isl_take isl_multi_union_pw_aff *mupa2);
=item * Simplification
@@ -5619,6 +6265,9 @@ to simplify the expression associated to
__isl_give isl_basic_map *isl_basic_map_gist(
__isl_take isl_basic_map *bmap,
__isl_take isl_basic_map *context);
+ __isl_give isl_basic_map *isl_basic_map_gist_domain(
+ __isl_take isl_basic_map *bmap,
+ __isl_take isl_basic_set *context);
__isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
__isl_take isl_map *context);
__isl_give isl_map *isl_map_gist_params(
@@ -5683,6 +6332,12 @@ to simplify the expression associated to
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_gist(
__isl_take isl_multi_pw_aff *mpa,
__isl_take isl_set *set);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_gist(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_union_set *context);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_gist_params(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_set *context);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_gist_params(
__isl_take isl_union_pw_multi_aff *upma,
@@ -5691,6 +6346,14 @@ to simplify the expression associated to
isl_union_pw_multi_aff_gist(
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_union_set *context);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_gist_params(
+ __isl_take isl_multi_union_pw_aff *aff,
+ __isl_take isl_set *context);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_gist(
+ __isl_take isl_multi_union_pw_aff *aff,
+ __isl_take isl_union_set *context);
#include <isl/polynomial.h>
__isl_give isl_qpolynomial *isl_qpolynomial_gist_params(
@@ -5738,6 +6401,11 @@ to simplify the expression associated to
=item * Binary Arithmethic Operations
+ #include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_sub(
+ __isl_take isl_multi_val *mv1,
+ __isl_take isl_multi_val *mv2);
+
#include <isl/aff.h>
__isl_give isl_aff *isl_aff_add(
__isl_take isl_aff *aff1,
@@ -5751,6 +6419,9 @@ to simplify the expression associated to
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_add(
__isl_take isl_pw_multi_aff *pma1,
__isl_take isl_pw_multi_aff *pma2);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_add(
+ __isl_take isl_union_pw_aff *upa1,
+ __isl_take isl_union_pw_aff *upa2);
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_add(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2);
@@ -5769,12 +6440,22 @@ to simplify the expression associated to
__isl_give isl_pw_aff *isl_pw_aff_sub(
__isl_take isl_pw_aff *pwaff1,
__isl_take isl_pw_aff *pwaff2);
+ __isl_give isl_multi_pw_aff *isl_multi_pw_aff_sub(
+ __isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub(
__isl_take isl_pw_multi_aff *pma1,
__isl_take isl_pw_multi_aff *pma2);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_sub(
+ __isl_take isl_union_pw_aff *upa1,
+ __isl_take isl_union_pw_aff *upa2);
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_sub(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_sub(
+ __isl_take isl_multi_union_pw_aff *mupa1,
+ __isl_take isl_multi_union_pw_aff *mupa2);
C<isl_aff_sub> subtracts the second argument from the first.
@@ -5818,10 +6499,17 @@ C<isl_aff_sub> subtracts the second argu
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_add(
__isl_take isl_pw_multi_aff *pma1,
__isl_take isl_pw_multi_aff *pma2);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_union_add(
+ __isl_take isl_union_pw_aff *upa1,
+ __isl_take isl_union_pw_aff *upa2);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_union_add(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_union_add(
+ __isl_take isl_multi_union_pw_aff *mupa1,
+ __isl_take isl_multi_union_pw_aff *mupa2);
__isl_give isl_pw_aff *isl_pw_aff_union_min(
__isl_take isl_pw_aff *pwaff1,
__isl_take isl_pw_aff *pwaff2);
@@ -5858,6 +6546,9 @@ only defined on the shared definition do
__isl_give isl_pw_aff *isl_pw_aff_mod_val(
__isl_take isl_pw_aff *pa,
__isl_take isl_val *mod);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_mod_val(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_val *f);
__isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff,
__isl_take isl_val *v);
__isl_give isl_multi_aff *isl_multi_aff_scale_val(
@@ -5872,9 +6563,16 @@ only defined on the shared definition do
__isl_take isl_pw_multi_aff *pma,
__isl_take isl_val *v);
__isl_give isl_union_pw_multi_aff *
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_scale_val(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_val *f);
isl_union_pw_multi_aff_scale_val(
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_val *val);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_scale_val(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_val *v);
__isl_give isl_aff *isl_aff_scale_down_ui(
__isl_take isl_aff *aff, unsigned f);
__isl_give isl_aff *isl_aff_scale_down_val(
@@ -5891,10 +6589,17 @@ only defined on the shared definition do
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_down_val(
__isl_take isl_pw_multi_aff *pma,
__isl_take isl_val *v);
+ __isl_give isl_union_pw_aff *isl_union_pw_aff_scale_down_val(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_val *v);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_scale_down_val(
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_val *val);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_scale_down_val(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_val *v);
#include <isl/polynomial.h>
__isl_give isl_qpolynomial *isl_qpolynomial_scale_val(
@@ -5946,6 +6651,9 @@ only defined on the shared definition do
__isl_take isl_val *v);
#include <isl/val.h>
+ __isl_give isl_multi_val *isl_multi_val_mod_multi_val(
+ __isl_take isl_multi_val *mv1,
+ __isl_take isl_multi_val *mv2);
__isl_give isl_multi_val *isl_multi_val_scale_multi_val(
__isl_take isl_multi_val *mv1,
__isl_take isl_multi_val *mv2);
@@ -5955,6 +6663,17 @@ only defined on the shared definition do
__isl_take isl_multi_val *mv2);
#include <isl/aff.h>
+ __isl_give isl_multi_aff *isl_multi_aff_mod_multi_val(
+ __isl_take isl_multi_aff *ma,
+ __isl_take isl_multi_val *mv);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_mod_multi_val(
+ __isl_take isl_multi_union_pw_aff *upma,
+ __isl_take isl_multi_val *mv);
+ __isl_give isl_multi_pw_aff *
+ isl_multi_pw_aff_mod_multi_val(
+ __isl_take isl_multi_pw_aff *mpa,
+ __isl_take isl_multi_val *mv);
__isl_give isl_multi_aff *isl_multi_aff_scale_multi_val(
__isl_take isl_multi_aff *ma,
__isl_take isl_multi_val *mv);
@@ -5966,6 +6685,10 @@ only defined on the shared definition do
isl_multi_pw_aff_scale_multi_val(
__isl_take isl_multi_pw_aff *mpa,
__isl_take isl_multi_val *mv);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_scale_multi_val(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_multi_val *mv);
__isl_give isl_union_pw_multi_aff *
isl_union_pw_multi_aff_scale_multi_val(
__isl_take isl_union_pw_multi_aff *upma,
@@ -5978,6 +6701,10 @@ only defined on the shared definition do
isl_multi_pw_aff_scale_down_multi_val(
__isl_take isl_multi_pw_aff *mpa,
__isl_take isl_multi_val *mv);
+ __isl_give isl_multi_union_pw_aff *
+ isl_multi_union_pw_aff_scale_down_multi_val(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_multi_val *mv);
C<isl_multi_aff_scale_multi_val> scales the elements of C<ma>
by the corresponding elements of C<mv>.
@@ -6187,8 +6914,10 @@ where C<cond> is zero.
=head2 Lists
Lists are defined over several element types, including
-C<isl_val>, C<isl_id>, C<isl_aff>, C<isl_pw_aff>, C<isl_constraint>,
-C<isl_basic_set>, C<isl_set>, C<isl_ast_expr> and C<isl_ast_node>.
+C<isl_val>, C<isl_id>, C<isl_aff>, C<isl_pw_aff>, C<isl_union_pw_aff>,
+C<isl_union_pw_multi_aff>, C<isl_constraint>,
+C<isl_basic_set>, C<isl_set>, C<isl_basic_map>, C<isl_map>, C<isl_union_set>,
+C<isl_union_map>, C<isl_ast_expr> and C<isl_ast_node>.
Here we take lists of C<isl_set>s as an example.
Lists can be created, copied, modified and freed using the following functions.
@@ -6222,9 +6951,10 @@ Lists can be created, copied, modified a
__isl_null isl_set_list *isl_set_list_free(
__isl_take isl_set_list *list);
-C<isl_set_list_alloc> creates an empty list with a capacity for
-C<n> elements. C<isl_set_list_from_set> creates a list with a single
-element.
+C<isl_set_list_alloc> creates an empty list with an initial capacity
+for C<n> elements. C<isl_set_list_insert> and C<isl_set_list_add>
+add elements to a list, increasing its capacity as needed.
+C<isl_set_list_from_set> creates a list with a single element.
Lists can be inspected using the following functions.
@@ -6269,12 +6999,12 @@ Associative arrays can be created, copie
the following functions.
#include <isl/id_to_ast_expr.h>
- __isl_give id_to_ast_expr *isl_id_to_ast_expr_alloc(
+ __isl_give isl_id_to_ast_expr *isl_id_to_ast_expr_alloc(
isl_ctx *ctx, int min_size);
- __isl_give id_to_ast_expr *isl_id_to_ast_expr_copy(
- __isl_keep id_to_ast_expr *id2expr);
- __isl_null id_to_ast_expr *isl_id_to_ast_expr_free(
- __isl_take id_to_ast_expr *id2expr);
+ __isl_give isl_id_to_ast_expr *isl_id_to_ast_expr_copy(
+ __isl_keep isl_id_to_ast_expr *id2expr);
+ __isl_null isl_id_to_ast_expr *isl_id_to_ast_expr_free(
+ __isl_take isl_id_to_ast_expr *id2expr);
The C<min_size> argument to C<isl_id_to_ast_expr_alloc> can be used
to specify the expected size of the associative array.
@@ -6284,13 +7014,13 @@ Associative arrays can be inspected usin
#include <isl/id_to_ast_expr.h>
int isl_id_to_ast_expr_has(
- __isl_keep id_to_ast_expr *id2expr,
+ __isl_keep isl_id_to_ast_expr *id2expr,
__isl_keep isl_id *key);
__isl_give isl_ast_expr *isl_id_to_ast_expr_get(
- __isl_keep id_to_ast_expr *id2expr,
+ __isl_keep isl_id_to_ast_expr *id2expr,
__isl_take isl_id *key);
int isl_id_to_ast_expr_foreach(
- __isl_keep id_to_ast_expr *id2expr,
+ __isl_keep isl_id_to_ast_expr *id2expr,
int (*fn)(__isl_take isl_id *key,
__isl_take isl_ast_expr *val, void *user),
void *user);
@@ -6298,12 +7028,12 @@ Associative arrays can be inspected usin
They can be modified using the following function.
#include <isl/id_to_ast_expr.h>
- __isl_give id_to_ast_expr *isl_id_to_ast_expr_set(
- __isl_take id_to_ast_expr *id2expr,
+ __isl_give isl_id_to_ast_expr *isl_id_to_ast_expr_set(
+ __isl_take isl_id_to_ast_expr *id2expr,
__isl_take isl_id *key,
__isl_take isl_ast_expr *val);
- __isl_give id_to_ast_expr *isl_id_to_ast_expr_drop(
- __isl_take id_to_ast_expr *id2expr,
+ __isl_give isl_id_to_ast_expr *isl_id_to_ast_expr_drop(
+ __isl_take isl_id_to_ast_expr *id2expr,
__isl_take isl_id *key);
Associative arrays can be printed using the following function.
@@ -6311,7 +7041,7 @@ Associative arrays can be printed using
#include <isl/id_to_ast_expr.h>
__isl_give isl_printer *isl_printer_print_id_to_ast_expr(
__isl_take isl_printer *p,
- __isl_keep id_to_ast_expr *id2expr);
+ __isl_keep isl_id_to_ast_expr *id2expr);
=head2 Vectors
@@ -6476,6 +7206,443 @@ Chambers can be inspected and destroyed
This section collects functionality in C<isl> that has been specifically
designed for use during polyhedral compilation.
+=head2 Schedule Trees
+
+A schedule tree is a structured representation of a schedule,
+assigning a relative order to a set of domain elements.
+The relative order expressed by the schedule tree is
+defined recursively. In particular, the order between
+two domain elements is determined by the node that is closest
+to the root that refers to both elements and that orders them apart.
+Each node in the tree is of one of several types.
+The root node is always of type C<isl_schedule_node_domain>
+and it describes the domain elements to which the schedule applies.
+The other types of nodes are as follows.
+
+=over
+
+=item C<isl_schedule_node_band>
+
+A band of schedule dimensions. Each schedule dimension is represented
+by a union piecewise quasi-affine expression. If this expression
+assigns a different value to two domain elements, while all previous
+schedule dimensions in the same band assign them the same value,
+then the two domain elements are ordered according to these two
+different values.
+
+=item C<isl_schedule_node_filter>
+
+A filter node does not impose any ordering, but rather intersects
+the set of domain elements that the current subtree refers to
+with a given union set. The subtree of the filter node only
+refers to domain elements in the intersection.
+A filter node is typically only used a child of a sequence or
+set node.
+
+=item C<isl_schedule_node_leaf>
+
+A leaf of the schedule tree. Leaf nodes do not impose any ordering.
+
+=item C<isl_schedule_node_sequence>
+
+A sequence node has one or more children, each of which is a filter node.
+The filters on these filter nodes form a partition of
+the domain elements that the current subtree refers to.
+If two domain elements appear in distinct filters then the sequence
+node orders them according to the child positions of the corresponding
+filter nodes.
+
+=item C<isl_schedule_node_set>
+
+A set node is similar to a sequence node, except that
+it expresses that domain elements appearing in distinct filters
+may have any order. The order of the children of a set node
+is therefore also immaterial.
+
+=back
+
+A schedule tree is encapsulated in an C<isl_schedule> object.
+The simplest such objects, those with a tree consisting of single domain node,
+can be created using the following functions with either an empty
+domain or a given domain.
+
+ #include <isl/schedule.h>
+ __isl_give isl_schedule *isl_schedule_empty(
+ __isl_take isl_space *space);
+ __isl_give isl_schedule *isl_schedule_from_domain(
+ __isl_take isl_union_set *domain);
+
+The function C<isl_schedule_constraints_compute_schedule> described
+in L</"Scheduling"> can also be used to construct schedules.
+
+C<isl_schedule> objects may be copied and freed using the following functions.
+
+ #include <isl/schedule.h>
+ __isl_give isl_schedule *isl_schedule_copy(
+ __isl_keep isl_schedule *sched);
+ __isl_null isl_schedule *isl_schedule_free(
+ __isl_take isl_schedule *sched);
+
+The domain of the schedule, i.e., the domain described by the root node,
+can be obtained using the following function.
+
+ #include <isl/schedule.h>
+ __isl_give isl_union_set *isl_schedule_get_domain(
+ __isl_keep isl_schedule *schedule);
+
+An C<isl_union_map> representation of the schedule can be obtained
+from an C<isl_schedule> using the following function.
+
+ #include <isl/schedule.h>
+ __isl_give isl_union_map *isl_schedule_get_map(
+ __isl_keep isl_schedule *sched);
+
+The resulting relation encodes the same relative ordering as
+the schedule by mapping the domain elements to a common schedule space.
+If the schedule_separate_components option is set, then the order
+of the children of a set node is explicitly encoded in the result.
+
+Schedules can be read from input using the following functions.
+
+ #include <isl/schedule.h>
+ __isl_give isl_schedule *isl_schedule_read_from_file(
+ isl_ctx *ctx, FILE *input);
+ __isl_give isl_schedule *isl_schedule_read_from_str(
+ isl_ctx *ctx, const char *str);
+
+A representation of the schedule can be printed using
+
+ #include <isl/schedule.h>
+ __isl_give isl_printer *isl_printer_print_schedule(
+ __isl_take isl_printer *p,
+ __isl_keep isl_schedule *schedule);
+
+The schedule tree can be traversed through the use of
+C<isl_schedule_node> objects that point to a particular
+position in the schedule tree. Whenever a C<isl_schedule_node>
+is use to modify a node in the schedule tree, the original schedule
+tree is left untouched and the modifications are performed to a copy
+of the tree. The returned C<isl_schedule_node> then points to
+this modified copy of the tree.
+
+The root of the schedule tree can be obtained using the following function.
+
+ #include <isl/schedule.h>
+ __isl_give isl_schedule_node *isl_schedule_get_root(
+ __isl_keep isl_schedule *schedule);
+
+A pointer to a newly created schedule tree with a single domain
+node can be created using the following function.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *
+ isl_schedule_node_from_domain(
+ __isl_take isl_union_set *domain);
+
+Schedule nodes can be copied and freed using the following functions.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *isl_schedule_node_copy(
+ __isl_keep isl_schedule_node *node);
+ __isl_null isl_schedule_node *isl_schedule_node_free(
+ __isl_take isl_schedule_node *node);
+
+The following properties can be obtained from a schedule node.
+
+ #include <isl/schedule_node.h>
+ enum isl_schedule_node_type isl_schedule_node_get_type(
+ __isl_keep isl_schedule_node *node);
+ enum isl_schedule_node_type
+ isl_schedule_node_get_parent_type(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_schedule *isl_schedule_node_get_schedule(
+ __isl_keep isl_schedule_node *node);
+
+The function C<isl_schedule_node_get_type> returns the type of
+the node, while C<isl_schedule_node_get_parent_type> returns
+type of the parent of the node, which is required to exist.
+The function C<isl_schedule_node_get_schedule> returns a copy
+to the schedule to which the node belongs.
+
+The following functions can be used to move the schedule node
+to a different position in the tree or to check if such a position
+exists.
+
+ #include <isl/schedule_node.h>
+ int isl_schedule_node_has_parent(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_schedule_node *isl_schedule_node_parent(
+ __isl_take isl_schedule_node *node);
+ int isl_schedule_node_n_children(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_schedule_node *isl_schedule_node_child(
+ __isl_take isl_schedule_node *node, int pos);
+ int isl_schedule_node_has_children(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_schedule_node *isl_schedule_node_first_child(
+ __isl_take isl_schedule_node *node);
+ int isl_schedule_node_has_previous_sibling(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_schedule_node *
+ isl_schedule_node_previous_sibling(
+ __isl_take isl_schedule_node *node);
+ int isl_schedule_node_has_next_sibling(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_schedule_node *
+ isl_schedule_node_next_sibling(
+ __isl_take isl_schedule_node *node);
+
+It is also possible to query the number of ancestors of a node,
+the position of the current node
+within the children of its parent or to obtain a copy of a given
+child without destroying the current node.
+
+ #include <isl/schedule_node.h>
+ int isl_schedule_node_get_tree_depth(
+ __isl_keep isl_schedule_node *node);
+ int isl_schedule_node_get_child_position(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_schedule_node *isl_schedule_node_get_child(
+ __isl_keep isl_schedule_node *node, int pos);
+
+All nodes in a schedule tree or
+all descendants of a specific node (including the node) can be visited
+in depth-first pre-order using the following functions.
+
+ #include <isl/schedule.h>
+ int isl_schedule_foreach_schedule_node(
+ __isl_keep isl_schedule *sched,
+ int (*fn)(__isl_keep isl_schedule_node *node,
+ void *user), void *user);
+
+ #include <isl/schedule_node.h>
+ int isl_schedule_node_foreach_descendant(
+ __isl_keep isl_schedule_node *node,
+ int (*fn)(__isl_keep isl_schedule_node *node,
+ void *user), void *user);
+
+The callback function is slightly different from the usual
+callbacks in that it not only indicates success (non-negative result)
+or failure (negative result), but also indicates whether the children
+of the given node should be visited. In particular, if the callback
+returns a positive value, then the children are visited, but if
+the callback returns zero, then the children are not visited.
+
+The following functions allows for a depth-first post-order
+traversal of the nodes in a schedule tree or
+of the descendants of a specific node (including the node
+itself), where the user callback is allowed to modify the
+visited node.
+
+ #include <isl/schedule.h>
+ __isl_give isl_schedule *isl_schedule_map_schedule_node(
+ __isl_take isl_schedule *schedule,
+ __isl_give isl_schedule_node *(*fn)(
+ __isl_take isl_schedule_node *node,
+ void *user), void *user);
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *
+ isl_schedule_node_map_descendant(
+ __isl_take isl_schedule_node *node,
+ __isl_give isl_schedule_node *(*fn)(
+ __isl_take isl_schedule_node *node,
+ void *user), void *user);
+
+The traversal continues from the node returned by the callback function.
+It is the responsibility of the user to ensure that this does not
+lead to an infinite loop. It is safest to always return a pointer
+to the same position (same ancestors and child positions) as the input node.
+
+Several node types have their own functions for querying
+(and in some cases setting) some node type specific properties.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_space *isl_schedule_node_band_get_space(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_multi_union_pw_aff *
+ isl_schedule_node_band_get_partial_schedule(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_union_map *
+ isl_schedule_node_band_get_partial_schedule_union_map(
+ __isl_keep isl_schedule_node *node);
+ unsigned isl_schedule_node_band_n_member(
+ __isl_keep isl_schedule_node *node);
+ int isl_schedule_node_band_member_get_coincident(
+ __isl_keep isl_schedule_node *node, int pos);
+ __isl_give isl_schedule_node *
+ isl_schedule_node_band_member_set_coincident(
+ __isl_take isl_schedule_node *node, int pos,
+ int coincident);
+ int isl_schedule_node_band_get_permutable(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_schedule_node *
+ isl_schedule_node_band_set_permutable(
+ __isl_take isl_schedule_node *node, int permutable);
+
+The function C<isl_schedule_node_band_get_space> returns the space
+of the partial schedule of the band.
+The function C<isl_schedule_node_band_get_partial_schedule_union_map>
+returns a representation of the partial schedule of the band node
+in the form of an C<isl_union_map>.
+The coincident and permutable properties are set by
+C<isl_schedule_constraints_compute_schedule> on the schedule tree
+it produces.
+A scheduling dimension is considered to be ``coincident''
+if it satisfies the coincidence constraints within its band.
+That is, if the dependence distances of the coincidence
+constraints are all zero in that direction (for fixed
+iterations of outer bands).
+A band is marked permutable if it was produced using the Pluto-like scheduler.
+Note that the scheduler may have to resort to a Feautrier style scheduling
+step even if the default scheduler is used.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_union_set *
+ isl_schedule_node_domain_get_domain(
+ __isl_keep isl_schedule_node *node);
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_union_set *
+ isl_schedule_node_filter_get_filter(
+ __isl_keep isl_schedule_node *node);
+
+The following functions can be used to obtain an C<isl_union_pw_multi_aff>
+or C<isl_union_map> representation of partial schedules related to the node.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_union_pw_multi_aff *
+ isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_union_map *
+ isl_schedule_node_get_prefix_schedule_union_map(
+ __isl_keep isl_schedule_node *node);
+ __isl_give isl_union_map *
+ isl_schedule_node_get_subtree_schedule_union_map(
+ __isl_keep isl_schedule_node *node);
+
+In particular, the functions
+C<isl_schedule_node_get_prefix_schedule_union_pw_multi_aff>
+and C<isl_schedule_node_get_prefix_schedule_union_map>
+return a relative ordering on the domain elements that reach the given
+node determined by its ancestors.
+The function C<isl_schedule_node_get_subtree_schedule_union_map>
+returns a representation of the partial schedule defined by the
+subtree rooted at the given node.
+
+The following function returns the union of universes in the spaces that
+contain elements that reach the given node.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_union_set *
+ isl_schedule_node_get_universe_domain(
+ __isl_keep isl_schedule_node *node);
+
+The following functions can be used to introduce additional nodes
+in the schedule tree. The new node is introduced at the point
+in the tree where the C<isl_schedule_node> points to and
+the results points to the new node.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *
+ isl_schedule_node_insert_partial_schedule(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_multi_union_pw_aff *schedule);
+
+This function inserts a new band node with (the greatest integer
+part of) the given partial schedule.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *
+ isl_schedule_node_insert_filter(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_union_set *filter);
+
+This function inserts a new filter node with the given filter.
+If the original node already pointed to a filter node, then the
+two filter nodes are merged into one.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *
+ isl_schedule_node_insert_sequence(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_union_set_list *filters);
+ __isl_give isl_schedule_node *
+ isl_schedule_node_insert_set(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_union_set_list *filters);
+
+These functions insert a new sequence or set node with the given
+filters as children.
+
+The partial schedule of a band node can be scaled (down) using
+the following functions.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *
+ isl_schedule_node_band_scale(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_multi_val *mv);
+ __isl_give isl_schedule_node *
+ isl_schedule_node_band_scale_down(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_multi_val *mv);
+
+The spaces of the two arguments need to match.
+After scaling, the partial schedule is replaced by its greatest
+integer part to ensure that the schedule remains integral.
+
+A band node can be tiled using the following function.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *isl_schedule_node_band_tile(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_multi_val *sizes);
+
+ int isl_options_set_tile_scale_tile_loops(isl_ctx *ctx,
+ int val);
+ int isl_options_get_tile_scale_tile_loops(isl_ctx *ctx);
+ int isl_options_set_tile_shift_point_loops(isl_ctx *ctx,
+ int val);
+ int isl_options_get_tile_shift_point_loops(isl_ctx *ctx);
+
+The C<isl_schedule_node_band_tile> function tiles
+the band using the given tile sizes inside its schedule.
+A new child band node is created to represent the point loops and it is
+inserted between the modified band and its children.
+The C<tile_scale_tile_loops> option specifies whether the tile
+loops iterators should be scaled by the tile sizes.
+If the C<tile_shift_point_loops> option is set, then the point loops
+are shifted to start at zero.
+
+A band node can be split into two nested band nodes
+using the following function.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *isl_schedule_node_band_split(
+ __isl_take isl_schedule_node *node, int pos);
+
+The resulting outer band node contains the first C<pos> dimensions of
+the schedule of C<node> while the inner band contains the remaining dimensions.
+The schedules of the two band nodes live in anonymous spaces.
+
+A band node can be moved down to the leaves of the subtree rooted
+at the band node using the following function.
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_schedule_node *isl_schedule_node_band_sink(
+ __isl_take isl_schedule_node *node);
+
+The result points to the node in the resulting tree that is in the same
+position as the node pointed to by C<node> in the original tree.
+
+A representation of the schedule node can be printed using
+
+ #include <isl/schedule_node.h>
+ __isl_give isl_printer *isl_printer_print_schedule_node(
+ __isl_take isl_printer *p,
+ __isl_keep isl_schedule_node *node);
+
=head2 Dependence Analysis
C<isl> contains specialized functionality for performing
@@ -6694,8 +7861,6 @@ and may be subject to change.>
__isl_give isl_schedule *
isl_schedule_constraints_compute_schedule(
__isl_take isl_schedule_constraints *sc);
- __isl_null isl_schedule *isl_schedule_free(
- __isl_take isl_schedule *sched);
The function C<isl_schedule_constraints_compute_schedule> can be
used to compute a schedule that satisfies the given schedule constraints.
@@ -6731,6 +7896,10 @@ and manipulated using the following func
isl_schedule_constraints_on_domain(
__isl_take isl_union_set *domain);
__isl_give isl_schedule_constraints *
+ isl_schedule_constraints_set_context(
+ __isl_take isl_schedule_constraints *sc,
+ __isl_take isl_set *context);
+ __isl_give isl_schedule_constraints *
isl_schedule_constraints_set_validity(
__isl_take isl_schedule_constraints *sc,
__isl_take isl_union_map *validity);
@@ -6754,6 +7923,9 @@ and manipulated using the following func
The initial C<isl_schedule_constraints> object created by
C<isl_schedule_constraints_on_domain> does not impose any constraints.
That is, it has an empty set of dependences.
+The function C<isl_schedule_constraints_set_context> allows the user
+to specify additional constraints on the parameters that may
+be assumed to hold during the construction of the schedule.
The function C<isl_schedule_constraints_set_validity> replaces the
validity dependences, mapping domain elements I<i> to domain
elements that should be scheduled after I<i>.
@@ -6800,17 +7972,9 @@ The use of C<isl_union_set_compute_sched
__isl_take isl_union_map *validity,
__isl_take isl_union_map *proximity);
-A mapping from the domains to the scheduled space can be obtained
-from an C<isl_schedule> using the following function.
-
- __isl_give isl_union_map *isl_schedule_get_map(
- __isl_keep isl_schedule *sched);
-
-A representation of the schedule can be printed using
-
- __isl_give isl_printer *isl_printer_print_schedule(
- __isl_take isl_printer *p,
- __isl_keep isl_schedule *schedule);
+The generated schedule represents a schedule tree.
+For more information on schedule trees, see
+L</"Schedule Trees">.
A representation of the schedule as a forest of bands can be obtained
using the following function.
@@ -6818,6 +7982,10 @@ using the following function.
__isl_give isl_band_list *isl_schedule_get_band_forest(
__isl_keep isl_schedule *schedule);
+If the input schedule is represented by a schedule tree, then a call
+to C<isl_schedule_get_band_forest> replaces the internal schedule tree
+representation by a band forest representation.
+
The individual bands can be visited in depth-first post-order
using the following function.
@@ -7011,12 +8179,8 @@ and C<ISL_SCHEDULE_ALGORITHM_FEAUTRIER>.
=item * schedule_separate_components
-If at any point the dependence graph contains any (weakly connected) components,
-then these components are scheduled separately.
-If this option is not set, then some iterations of the domains
-in these components may be scheduled together.
-If this option is set, then the components are given consecutive
-schedules.
+If this option is set then the function C<isl_schedule_get_map>
+will treat set nodes in the same way as sequence nodes.
=back
Modified: polly/trunk/lib/External/isl/include/isl/aff.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/aff.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/aff.h (original)
+++ polly/trunk/lib/External/isl/include/isl/aff.h Mon Feb 16 13:33:40 2015
@@ -200,6 +200,7 @@ __isl_give isl_pw_aff *isl_pw_aff_set_tu
enum isl_dim_type type, __isl_take isl_id *id);
__isl_give isl_pw_aff *isl_pw_aff_reset_tuple_id(__isl_take isl_pw_aff *pa,
enum isl_dim_type type);
+__isl_give isl_pw_aff *isl_pw_aff_reset_user(__isl_take isl_pw_aff *pa);
__isl_give isl_set *isl_pw_aff_params(__isl_take isl_pw_aff *pwa);
__isl_give isl_set *isl_pw_aff_domain(__isl_take isl_pw_aff *pwaff);
@@ -231,6 +232,8 @@ __isl_give isl_pw_aff *isl_pw_aff_inters
__isl_take isl_set *set);
__isl_give isl_pw_aff *isl_pw_aff_intersect_domain(__isl_take isl_pw_aff *pa,
__isl_take isl_set *set);
+__isl_give isl_pw_aff *isl_pw_aff_subtract_domain(__isl_take isl_pw_aff *pa,
+ __isl_take isl_set *set);
__isl_give isl_pw_aff *isl_pw_aff_cond(__isl_take isl_pw_aff *cond,
__isl_take isl_pw_aff *pwaff_true, __isl_take isl_pw_aff *pwaff_false);
@@ -271,6 +274,7 @@ int isl_pw_aff_foreach_piece(__isl_keep
__isl_give isl_set *isl_set_from_pw_aff(__isl_take isl_pw_aff *pwaff);
__isl_give isl_map *isl_map_from_pw_aff(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_set *isl_pw_aff_pos_set(__isl_take isl_pw_aff *pa);
__isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff);
__isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff);
__isl_give isl_set *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff);
@@ -288,6 +292,13 @@ __isl_give isl_set *isl_pw_aff_ge_set(__
__isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_map *isl_pw_aff_eq_map(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2);
+__isl_give isl_map *isl_pw_aff_lt_map(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2);
+__isl_give isl_map *isl_pw_aff_gt_map(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2);
+
__isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str);
__isl_give isl_printer *isl_printer_print_pw_aff(__isl_take isl_printer *p,
__isl_keep isl_pw_aff *pwaff);
@@ -310,6 +321,9 @@ __isl_give isl_set *isl_pw_aff_list_gt_s
__isl_take isl_pw_aff_list *list2);
ISL_DECLARE_MULTI(aff)
+ISL_DECLARE_MULTI_NEG(aff)
+ISL_DECLARE_MULTI_DIMS(aff)
+ISL_DECLARE_MULTI_WITH_DOMAIN(aff)
__isl_give isl_multi_aff *isl_multi_aff_from_aff(__isl_take isl_aff *aff);
__isl_give isl_multi_aff *isl_multi_aff_identity(__isl_take isl_space *space);
@@ -326,8 +340,6 @@ __isl_give isl_multi_aff *isl_multi_aff_
__isl_give isl_multi_aff *isl_multi_aff_add(__isl_take isl_multi_aff *maff1,
__isl_take isl_multi_aff *maff2);
-__isl_give isl_multi_aff *isl_multi_aff_sub(__isl_take isl_multi_aff *ma1,
- __isl_take isl_multi_aff *ma2);
__isl_give isl_multi_aff *isl_multi_aff_product(
__isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2);
@@ -361,10 +373,15 @@ __isl_give isl_multi_aff *isl_multi_aff_
void isl_multi_aff_dump(__isl_keep isl_multi_aff *maff);
ISL_DECLARE_MULTI(pw_aff)
+ISL_DECLARE_MULTI_NEG(pw_aff)
+ISL_DECLARE_MULTI_DIMS(pw_aff)
+ISL_DECLARE_MULTI_WITH_DOMAIN(pw_aff)
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_zero(__isl_take isl_space *space);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity(
__isl_take isl_space *space);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_map(
+ __isl_take isl_space *space);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_out_map(
__isl_take isl_space *space, enum isl_dim_type type,
unsigned first, unsigned n);
@@ -405,6 +422,8 @@ __isl_give isl_pw_multi_aff *isl_pw_mult
enum isl_dim_type type, __isl_take isl_id *id);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_reset_tuple_id(
__isl_take isl_pw_multi_aff *pma, enum isl_dim_type type);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_reset_user(
+ __isl_take isl_pw_multi_aff *pma);
int isl_pw_multi_aff_find_dim_by_name(__isl_keep isl_pw_multi_aff *pma,
enum isl_dim_type type, const char *name);
@@ -441,6 +460,9 @@ __isl_give isl_pw_multi_aff *isl_pw_mult
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_add(
__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_neg(
+ __isl_take isl_pw_multi_aff *pma);
+
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_add(
__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_sub(
@@ -474,6 +496,8 @@ __isl_give isl_pw_multi_aff *isl_pw_mult
__isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_intersect_domain(
__isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_subtract_domain(
+ __isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_domain_on_params(
__isl_take isl_pw_multi_aff *pma);
@@ -513,6 +537,8 @@ void isl_pw_multi_aff_dump(__isl_keep is
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_empty(
__isl_take isl_space *space);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_aff(
+ __isl_take isl_aff *aff);
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_pw_multi_aff(
__isl_take isl_pw_multi_aff *pma);
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain(
@@ -524,6 +550,12 @@ __isl_give isl_union_pw_multi_aff *isl_u
__isl_null isl_union_pw_multi_aff *isl_union_pw_multi_aff_free(
__isl_take isl_union_pw_multi_aff *upma);
+__isl_give isl_union_pw_multi_aff *isl_union_set_identity_union_pw_multi_aff(
+ __isl_take isl_union_set *uset);
+
+__isl_give isl_union_pw_aff *isl_union_pw_multi_aff_get_union_pw_aff(
+ __isl_keep isl_union_pw_multi_aff *upma, int pos);
+
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_add_pw_multi_aff(
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_pw_multi_aff *pma);
@@ -535,10 +567,20 @@ __isl_give isl_space *isl_union_pw_multi
unsigned isl_union_pw_multi_aff_dim(__isl_keep isl_union_pw_multi_aff *upma,
enum isl_dim_type type);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_set_dim_name(
+ __isl_take isl_union_pw_multi_aff *upma,
+ enum isl_dim_type type, unsigned pos, const char *s);
+
int isl_union_pw_multi_aff_find_dim_by_name(
__isl_keep isl_union_pw_multi_aff *upma, enum isl_dim_type type,
const char *name);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_drop_dims(
+ __isl_take isl_union_pw_multi_aff *upma,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_reset_user(
+ __isl_take isl_union_pw_multi_aff *upma);
+
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_coalesce(
__isl_take isl_union_pw_multi_aff *upma);
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_gist_params(
@@ -547,9 +589,17 @@ __isl_give isl_union_pw_multi_aff *isl_u
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_union_set *context);
+__isl_give isl_union_pw_multi_aff *
+isl_union_pw_multi_aff_pullback_union_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma1,
+ __isl_take isl_union_pw_multi_aff *upma2);
+
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_align_params(
__isl_take isl_union_pw_multi_aff *upma, __isl_take isl_space *model);
+int isl_union_pw_multi_aff_n_pw_multi_aff(
+ __isl_keep isl_union_pw_multi_aff *upma);
+
int isl_union_pw_multi_aff_foreach_pw_multi_aff(
__isl_keep isl_union_pw_multi_aff *upma,
int (*fn)(__isl_take isl_pw_multi_aff *pma, void *user), void *user);
@@ -563,6 +613,9 @@ int isl_union_pw_multi_aff_plain_is_equa
__isl_give isl_union_set *isl_union_pw_multi_aff_domain(
__isl_take isl_union_pw_multi_aff *upma);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_neg(
+ __isl_take isl_union_pw_multi_aff *upma);
+
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_add(
__isl_take isl_union_pw_multi_aff *upma1,
__isl_take isl_union_pw_multi_aff *upma2);
@@ -589,6 +642,9 @@ __isl_give isl_union_pw_multi_aff *isl_u
__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_intersect_domain(
__isl_take isl_union_pw_multi_aff *upma,
__isl_take isl_union_set *uset);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_subtract_domain(
+ __isl_take isl_union_pw_multi_aff *upma,
+ __isl_take isl_union_set *uset);
__isl_give isl_union_map *isl_union_map_from_union_pw_multi_aff(
__isl_take isl_union_pw_multi_aff *upma);
@@ -648,12 +704,208 @@ __isl_give isl_pw_multi_aff *isl_pw_mult
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
__isl_take isl_pw_multi_aff *pma);
+__isl_give isl_map *isl_multi_pw_aff_eq_map(__isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2);
+__isl_give isl_map *isl_multi_pw_aff_lex_lt_map(
+ __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2);
+__isl_give isl_map *isl_multi_pw_aff_lex_gt_map(
+ __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2);
+
__isl_give isl_multi_pw_aff *isl_multi_pw_aff_read_from_str(isl_ctx *ctx,
const char *str);
__isl_give isl_printer *isl_printer_print_multi_pw_aff(
__isl_take isl_printer *p, __isl_keep isl_multi_pw_aff *mpa);
void isl_multi_pw_aff_dump(__isl_keep isl_multi_pw_aff *mpa);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_copy(
+ __isl_keep isl_union_pw_aff *upa);
+__isl_null isl_union_pw_aff *isl_union_pw_aff_free(
+ __isl_take isl_union_pw_aff *upa);
+
+isl_ctx *isl_union_pw_aff_get_ctx(__isl_keep isl_union_pw_aff *upa);
+__isl_give isl_space *isl_union_pw_aff_get_space(
+ __isl_keep isl_union_pw_aff *upa);
+
+unsigned isl_union_pw_aff_dim(__isl_keep isl_union_pw_aff *upa,
+ enum isl_dim_type type);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_set_dim_name(
+ __isl_take isl_union_pw_aff *upa, enum isl_dim_type type,
+ unsigned pos, const char *s);
+
+int isl_union_pw_aff_find_dim_by_name(__isl_keep isl_union_pw_aff *upa,
+ enum isl_dim_type type, const char *name);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_drop_dims(
+ __isl_take isl_union_pw_aff *upa,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_reset_user(
+ __isl_take isl_union_pw_aff *upa);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_empty(
+ __isl_take isl_space *space);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_from_pw_aff(
+ __isl_take isl_pw_aff *pa);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_val_on_domain(
+ __isl_take isl_union_set *domain, __isl_take isl_val *v);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_aff_on_domain(
+ __isl_take isl_union_set *domain, __isl_take isl_aff *aff);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_add_pw_aff(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_pw_aff *pa);
+
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_pw_aff(
+ __isl_take isl_union_pw_aff *upa);
+
+int isl_union_pw_aff_n_pw_aff(__isl_keep isl_union_pw_aff *upa);
+
+int isl_union_pw_aff_foreach_pw_aff(__isl_keep isl_union_pw_aff *upa,
+ int (*fn)(__isl_take isl_pw_aff *ma, void *user), void *user);
+__isl_give isl_pw_aff *isl_union_pw_aff_extract_pw_aff(
+ __isl_keep isl_union_pw_aff *upa, __isl_take isl_space *space);
+
+int isl_union_pw_aff_plain_is_equal(__isl_keep isl_union_pw_aff *upa1,
+ __isl_keep isl_union_pw_aff *upa2);
+
+__isl_give isl_union_set *isl_union_pw_aff_domain(
+ __isl_take isl_union_pw_aff *upa);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_neg(
+ __isl_take isl_union_pw_aff *upa);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_add(
+ __isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_union_add(
+ __isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_sub(
+ __isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_coalesce(
+ __isl_take isl_union_pw_aff *upa);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_gist(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_union_set *context);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_gist_params(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_set *context);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_union_pw_multi_aff *upma);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_floor(
+ __isl_take isl_union_pw_aff *upa);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_scale_val(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_val *v);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_scale_down_val(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_val *v);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_mod_val(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_val *f);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_align_params(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_space *model);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_intersect_params(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_set *set);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_intersect_domain(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_union_set *uset);
+__isl_give isl_union_pw_aff *isl_union_pw_aff_subtract_domain(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_union_set *uset);
+
+__isl_give isl_union_pw_aff *isl_union_pw_aff_set_dim_name(
+ __isl_take isl_union_pw_aff *upa,
+ enum isl_dim_type type, unsigned pos, const char *s);
+
+__isl_give isl_union_set *isl_union_pw_aff_zero_union_set(
+ __isl_take isl_union_pw_aff *upa);
+
+__isl_give isl_union_map *isl_union_map_from_union_pw_aff(
+ __isl_take isl_union_pw_aff *upa);
+
+__isl_give char *isl_union_pw_aff_to_str(__isl_keep isl_union_pw_aff *upa);
+__isl_give isl_printer *isl_printer_print_union_pw_aff(
+ __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa);
+
+ISL_DECLARE_MULTI(union_pw_aff)
+ISL_DECLARE_MULTI_NEG(union_pw_aff)
+
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_aff(
+ __isl_take isl_multi_aff *ma);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_union_pw_aff(
+ __isl_take isl_union_pw_aff *upa);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_pw_aff(
+ __isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_val_on_domain(
+ __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_aff_on_domain(
+ __isl_take isl_union_set *domain, __isl_take isl_multi_aff *ma);
+
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_floor(
+ __isl_take isl_multi_union_pw_aff *mupa);
+
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_domain(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_union_set *uset);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_params(
+ __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *params);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_range(
+ __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *set);
+
+__isl_give isl_union_set *isl_multi_union_pw_aff_domain(
+ __isl_take isl_multi_union_pw_aff *mupa);
+
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_gist(
+ __isl_take isl_multi_union_pw_aff *aff,
+ __isl_take isl_union_set *context);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_gist_params(
+ __isl_take isl_multi_union_pw_aff *aff, __isl_take isl_set *context);
+
+__isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_aff(
+ __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff(
+ __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_multi_aff *ma);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff(
+ __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_multi_aff *ma);
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_pw_multi_aff *pma);
+
+__isl_give isl_multi_union_pw_aff *
+isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_union_pw_multi_aff *upma);
+
+__isl_give isl_union_pw_multi_aff *
+isl_union_pw_multi_aff_from_multi_union_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa);
+
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_union_add(
+ __isl_take isl_multi_union_pw_aff *mupa1,
+ __isl_take isl_multi_union_pw_aff *mupa2);
+
+__isl_give isl_multi_union_pw_aff *
+isl_multi_union_pw_aff_from_union_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma);
+
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_union_map(
+ __isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa);
+
+__isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
+ __isl_take isl_multi_union_pw_aff *mupa);
+
+__isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff(
+ __isl_keep isl_multi_union_pw_aff *mupa, __isl_take isl_space *space);
+
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_read_from_str(
+ isl_ctx *ctx, const char *str);
+__isl_give char *isl_multi_union_pw_aff_to_str(
+ __isl_keep isl_multi_union_pw_aff *mupa);
+__isl_give isl_printer *isl_printer_print_multi_union_pw_aff(
+ __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa);
+void isl_multi_union_pw_aff_dump(__isl_keep isl_multi_union_pw_aff *mupa);
+
+ISL_DECLARE_LIST_FN(union_pw_aff)
+ISL_DECLARE_LIST_FN(union_pw_multi_aff)
+
#if defined(__cplusplus)
}
#endif
Modified: polly/trunk/lib/External/isl/include/isl/aff_type.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/aff_type.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/aff_type.h (original)
+++ polly/trunk/lib/External/isl/include/isl/aff_type.h Mon Feb 16 13:33:40 2015
@@ -17,6 +17,11 @@ typedef struct isl_pw_aff isl_pw_aff;
ISL_DECLARE_LIST(pw_aff)
+struct isl_union_pw_aff;
+typedef struct isl_union_pw_aff isl_union_pw_aff;
+
+ISL_DECLARE_LIST_TYPE(union_pw_aff)
+
struct isl_multi_aff;
typedef struct isl_multi_aff isl_multi_aff;
@@ -26,9 +31,14 @@ typedef struct isl_pw_multi_aff isl_pw_m
struct isl_union_pw_multi_aff;
typedef struct isl_union_pw_multi_aff isl_union_pw_multi_aff;
+ISL_DECLARE_LIST_TYPE(union_pw_multi_aff)
+
struct isl_multi_pw_aff;
typedef struct isl_multi_pw_aff isl_multi_pw_aff;
+struct isl_multi_union_pw_aff;
+typedef struct isl_multi_union_pw_aff isl_multi_union_pw_aff;
+
#if defined(__cplusplus)
}
#endif
Modified: polly/trunk/lib/External/isl/include/isl/local_space.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/local_space.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/local_space.h (original)
+++ polly/trunk/lib/External/isl/include/isl/local_space.h Mon Feb 16 13:33:40 2015
@@ -70,6 +70,9 @@ __isl_give isl_local_space *isl_local_sp
__isl_give isl_local_space *isl_local_space_intersect(
__isl_take isl_local_space *ls1, __isl_take isl_local_space *ls2);
+__isl_give isl_local_space *isl_local_space_wrap(
+ __isl_take isl_local_space *ls);
+
int isl_local_space_is_equal(__isl_keep isl_local_space *ls1,
__isl_keep isl_local_space *ls2);
Modified: polly/trunk/lib/External/isl/include/isl/map.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/map.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/map.h (original)
+++ polly/trunk/lib/External/isl/include/isl/map.h Mon Feb 16 13:33:40 2015
@@ -147,6 +147,8 @@ __isl_give isl_map *isl_map_remove_redun
__isl_give isl_basic_map *isl_map_simple_hull(__isl_take isl_map *map);
__isl_give isl_basic_map *isl_map_unshifted_simple_hull(
__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_map_unshifted_simple_hull_from_map_list(
+ __isl_take isl_map *map, __isl_take isl_map_list *list);
__isl_export
__isl_give isl_basic_map *isl_basic_map_intersect_domain(
@@ -160,6 +162,8 @@ __isl_export
__isl_give isl_basic_map *isl_basic_map_intersect(
__isl_take isl_basic_map *bmap1,
__isl_take isl_basic_map *bmap2);
+__isl_give isl_basic_map *isl_basic_map_list_intersect(
+ __isl_take isl_basic_map_list *list);
__isl_export
__isl_give isl_map *isl_basic_map_union(
__isl_take isl_basic_map *bmap1,
@@ -211,11 +215,7 @@ __isl_give isl_map *isl_map_read_from_fi
__isl_constructor
__isl_give isl_map *isl_map_read_from_str(isl_ctx *ctx, const char *str);
void isl_basic_map_dump(__isl_keep isl_basic_map *bmap);
-void isl_basic_map_print(__isl_keep isl_basic_map *bmap, FILE *out, int indent,
- const char *prefix, const char *suffix, unsigned output_format);
void isl_map_dump(__isl_keep isl_map *map);
-void isl_map_print(__isl_keep isl_map *map, FILE *out, int indent,
- unsigned output_format);
__isl_give isl_printer *isl_printer_print_basic_map(
__isl_take isl_printer *printer, __isl_keep isl_basic_map *bmap);
__isl_give char *isl_map_to_str(__isl_keep isl_map *map);
@@ -609,6 +609,8 @@ void isl_map_print_internal(__isl_keep i
__isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
enum isl_dim_type type, unsigned pos);
+__isl_give isl_basic_map *isl_basic_map_gist_domain(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *context);
__isl_export
__isl_give isl_basic_map *isl_basic_map_gist(__isl_take isl_basic_map *bmap,
__isl_take isl_basic_map *context);
@@ -688,6 +690,9 @@ __isl_give isl_map *isl_map_from_multi_a
__isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos);
+ISL_DECLARE_LIST_FN(basic_map)
+ISL_DECLARE_LIST_FN(map)
+
#if defined(__cplusplus)
}
#endif
Modified: polly/trunk/lib/External/isl/include/isl/map_type.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/map_type.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/map_type.h (original)
+++ polly/trunk/lib/External/isl/include/isl/map_type.h Mon Feb 16 13:33:40 2015
@@ -10,8 +10,10 @@ extern "C" {
struct __isl_subclass(isl_map) isl_basic_map;
typedef struct isl_basic_map isl_basic_map;
+ISL_DECLARE_LIST_TYPE(basic_map)
struct __isl_subclass(isl_union_map) isl_map;
typedef struct isl_map isl_map;
+ISL_DECLARE_LIST_TYPE(map)
#ifndef isl_basic_set
struct __isl_subclass(isl_set) isl_basic_set;
Modified: polly/trunk/lib/External/isl/include/isl/multi.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/multi.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/multi.h (original)
+++ polly/trunk/lib/External/isl/include/isl/multi.h Mon Feb 16 13:33:40 2015
@@ -60,15 +60,6 @@ __isl_give isl_multi_##BASE *isl_multi_#
__isl_take isl_multi_##BASE *multi, enum isl_dim_type type); \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_reset_user( \
__isl_take isl_multi_##BASE *multi); \
-int isl_multi_##BASE##_involves_dims( \
- __isl_keep isl_multi_##BASE *multi, enum isl_dim_type type, \
- unsigned first, unsigned n); \
-__isl_give isl_multi_##BASE *isl_multi_##BASE##_insert_dims( \
- __isl_take isl_multi_##BASE *multi, enum isl_dim_type type, \
- unsigned first, unsigned n); \
-__isl_give isl_multi_##BASE *isl_multi_##BASE##_add_dims( \
- __isl_take isl_multi_##BASE *multi, enum isl_dim_type type, \
- unsigned n); \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_drop_dims( \
__isl_take isl_multi_##BASE *multi, enum isl_dim_type type, \
unsigned first, unsigned n); \
@@ -80,9 +71,6 @@ __isl_give isl_multi_##BASE *isl_multi_#
__isl_give isl_multi_##BASE *isl_multi_##BASE##_range_splice( \
__isl_take isl_multi_##BASE *multi1, unsigned pos, \
__isl_take isl_multi_##BASE *multi2); \
-__isl_give isl_multi_##BASE *isl_multi_##BASE##_splice( \
- __isl_take isl_multi_##BASE *multi1, unsigned in_pos, \
- unsigned out_pos, __isl_take isl_multi_##BASE *multi2); \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_flatten_range( \
__isl_take isl_multi_##BASE *multi); \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_flat_range_product( \
@@ -91,9 +79,6 @@ __isl_give isl_multi_##BASE *isl_multi_#
__isl_give isl_multi_##BASE *isl_multi_##BASE##_range_product( \
__isl_take isl_multi_##BASE *multi1, \
__isl_take isl_multi_##BASE *multi2); \
-__isl_give isl_multi_##BASE *isl_multi_##BASE##_product( \
- __isl_take isl_multi_##BASE *multi1, \
- __isl_take isl_multi_##BASE *multi2); \
int isl_multi_##BASE##_range_is_wrapping( \
__isl_keep isl_multi_##BASE *multi); \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_range_factor_domain( \
@@ -110,12 +95,41 @@ __isl_give isl_multi_##BASE *isl_multi_#
__isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_down_multi_val( \
__isl_take isl_multi_##BASE *multi, \
__isl_take isl_multi_val *mv); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_mod_multi_val( \
+ __isl_take isl_multi_##BASE *multi, \
+ __isl_take isl_multi_val *mv); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_sub( \
+ __isl_take isl_multi_##BASE *multi1, \
+ __isl_take isl_multi_##BASE *multi2); \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_align_params( \
__isl_take isl_multi_##BASE *multi, \
__isl_take isl_space *model); \
__isl_give isl_multi_##BASE *isl_multi_##BASE##_from_range( \
__isl_take isl_multi_##BASE *multi);
+#define ISL_DECLARE_MULTI_NEG(BASE) \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_neg( \
+ __isl_take isl_multi_##BASE *multi);
+
+#define ISL_DECLARE_MULTI_DIMS(BASE) \
+int isl_multi_##BASE##_involves_dims( \
+ __isl_keep isl_multi_##BASE *multi, enum isl_dim_type type, \
+ unsigned first, unsigned n); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_insert_dims( \
+ __isl_take isl_multi_##BASE *multi, enum isl_dim_type type, \
+ unsigned first, unsigned n); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_add_dims( \
+ __isl_take isl_multi_##BASE *multi, enum isl_dim_type type, \
+ unsigned n);
+
+#define ISL_DECLARE_MULTI_WITH_DOMAIN(BASE) \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_product( \
+ __isl_take isl_multi_##BASE *multi1, \
+ __isl_take isl_multi_##BASE *multi2); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_splice( \
+ __isl_take isl_multi_##BASE *multi1, unsigned in_pos, \
+ unsigned out_pos, __isl_take isl_multi_##BASE *multi2);
+
#if defined(__cplusplus)
}
#endif
Modified: polly/trunk/lib/External/isl/include/isl/obj.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/obj.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/obj.h (original)
+++ polly/trunk/lib/External/isl/include/isl/obj.h Mon Feb 16 13:33:40 2015
@@ -43,6 +43,8 @@ extern struct isl_obj_vtable isl_obj_pw_
#define isl_obj_pw_qpolynomial_fold (&isl_obj_pw_qpolynomial_fold_vtable)
extern struct isl_obj_vtable isl_obj_union_pw_qpolynomial_fold_vtable;
#define isl_obj_union_pw_qpolynomial_fold (&isl_obj_union_pw_qpolynomial_fold_vtable)
+extern struct isl_obj_vtable isl_obj_schedule_vtable;
+#define isl_obj_schedule (&isl_obj_schedule_vtable)
struct isl_obj {
isl_obj_type type;
void *v;
Modified: polly/trunk/lib/External/isl/include/isl/polynomial.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/polynomial.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/polynomial.h (original)
+++ polly/trunk/lib/External/isl/include/isl/polynomial.h Mon Feb 16 13:33:40 2015
@@ -170,11 +170,16 @@ __isl_give isl_pw_qpolynomial *isl_pw_qp
int isl_pw_qpolynomial_find_dim_by_name(__isl_keep isl_pw_qpolynomial *pwqp,
enum isl_dim_type type, const char *name);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_reset_user(
+ __isl_take isl_pw_qpolynomial *pwqp);
+
__isl_give isl_set *isl_pw_qpolynomial_domain(__isl_take isl_pw_qpolynomial *pwqp);
__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_intersect_domain(
__isl_take isl_pw_qpolynomial *pwpq, __isl_take isl_set *set);
__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_intersect_params(
__isl_take isl_pw_qpolynomial *pwpq, __isl_take isl_set *set);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_subtract_domain(
+ __isl_take isl_pw_qpolynomial *pwpq, __isl_take isl_set *set);
__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_project_domain_on_params(
__isl_take isl_pw_qpolynomial *pwqp);
@@ -361,12 +366,17 @@ int isl_pw_qpolynomial_fold_find_dim_by_
__isl_keep isl_pw_qpolynomial_fold *pwf,
enum isl_dim_type type, const char *name);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_reset_user(
+ __isl_take isl_pw_qpolynomial_fold *pwf);
+
__isl_give isl_set *isl_pw_qpolynomial_fold_domain(
__isl_take isl_pw_qpolynomial_fold *pwf);
__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_intersect_domain(
__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *set);
__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_intersect_params(
__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *set);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_subtract_domain(
+ __isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *set);
__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_add(
__isl_take isl_pw_qpolynomial_fold *pwf1,
@@ -486,14 +496,27 @@ __isl_give isl_union_pw_qpolynomial *isl
__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_intersect_params(
__isl_take isl_union_pw_qpolynomial *upwpq,
__isl_take isl_set *set);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_subtract_domain(
+ __isl_take isl_union_pw_qpolynomial *upwpq,
+ __isl_take isl_union_set *uset);
__isl_give isl_space *isl_union_pw_qpolynomial_get_space(
__isl_keep isl_union_pw_qpolynomial *upwqp);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_set_dim_name(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ enum isl_dim_type type, unsigned pos, const char *s);
+
int isl_union_pw_qpolynomial_find_dim_by_name(
__isl_keep isl_union_pw_qpolynomial *upwqp,
enum isl_dim_type type, const char *name);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_drop_dims(
+ __isl_take isl_union_pw_qpolynomial *upwqp,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_reset_user(
+ __isl_take isl_union_pw_qpolynomial *upwqp);
+
__isl_give isl_val *isl_union_pw_qpolynomial_eval(
__isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_point *pnt);
@@ -510,6 +533,8 @@ __isl_give isl_union_pw_qpolynomial *isl
__isl_take isl_union_pw_qpolynomial *upwqp,
__isl_take isl_space *model);
+int isl_union_pw_qpolynomial_n_pw_qpolynomial(
+ __isl_keep isl_union_pw_qpolynomial *upwqp);
int isl_union_pw_qpolynomial_foreach_pw_qpolynomial(
__isl_keep isl_union_pw_qpolynomial *upwqp,
int (*fn)(__isl_take isl_pw_qpolynomial *pwqp, void *user), void *user);
@@ -562,16 +587,33 @@ __isl_give isl_union_pw_qpolynomial_fold
isl_union_pw_qpolynomial_fold_intersect_params(
__isl_take isl_union_pw_qpolynomial_fold *upwf,
__isl_take isl_set *set);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_subtract_domain(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ __isl_take isl_union_set *uset);
enum isl_fold isl_union_pw_qpolynomial_fold_get_type(
__isl_keep isl_union_pw_qpolynomial_fold *upwf);
__isl_give isl_space *isl_union_pw_qpolynomial_fold_get_space(
__isl_keep isl_union_pw_qpolynomial_fold *upwf);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_set_dim_name(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ enum isl_dim_type type, unsigned pos, const char *s);
+
int isl_union_pw_qpolynomial_fold_find_dim_by_name(
__isl_keep isl_union_pw_qpolynomial_fold *upwf,
enum isl_dim_type type, const char *name);
+__isl_give isl_union_pw_qpolynomial_fold *
+ isl_union_pw_qpolynomial_fold_drop_dims(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf,
+ enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_reset_user(
+ __isl_take isl_union_pw_qpolynomial_fold *upwf);
+
__isl_give isl_val *isl_union_pw_qpolynomial_fold_eval(
__isl_take isl_union_pw_qpolynomial_fold *upwf,
__isl_take isl_point *pnt);
@@ -590,6 +632,8 @@ __isl_give isl_union_pw_qpolynomial_fold
__isl_take isl_union_pw_qpolynomial_fold *upwf,
__isl_take isl_space *model);
+int isl_union_pw_qpolynomial_fold_n_pw_qpolynomial_fold(
+ __isl_keep isl_union_pw_qpolynomial_fold *upwf);
int isl_union_pw_qpolynomial_fold_foreach_pw_qpolynomial_fold(
__isl_keep isl_union_pw_qpolynomial_fold *upwf,
int (*fn)(__isl_take isl_pw_qpolynomial_fold *pwf,
Modified: polly/trunk/lib/External/isl/include/isl/printer.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/printer.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/printer.h (original)
+++ polly/trunk/lib/External/isl/include/isl/printer.h Mon Feb 16 13:33:40 2015
@@ -36,6 +36,12 @@ __isl_give isl_printer *isl_printer_set_
int output_format);
int isl_printer_get_output_format(__isl_keep isl_printer *p);
+#define ISL_YAML_STYLE_BLOCK 0
+#define ISL_YAML_STYLE_FLOW 1
+__isl_give isl_printer *isl_printer_set_yaml_style(__isl_take isl_printer *p,
+ int yaml_style);
+int isl_printer_get_yaml_style(__isl_keep isl_printer *p);
+
__isl_give isl_printer *isl_printer_set_indent_prefix(__isl_take isl_printer *p,
const char *prefix);
__isl_give isl_printer *isl_printer_set_prefix(__isl_take isl_printer *p,
@@ -53,6 +59,16 @@ __isl_give isl_printer *isl_printer_prin
__isl_give isl_printer *isl_printer_print_str(__isl_take isl_printer *p,
const char *s);
+__isl_give isl_printer *isl_printer_yaml_start_mapping(
+ __isl_take isl_printer *p);
+__isl_give isl_printer *isl_printer_yaml_end_mapping(
+ __isl_take isl_printer *p);
+__isl_give isl_printer *isl_printer_yaml_start_sequence(
+ __isl_take isl_printer *p);
+__isl_give isl_printer *isl_printer_yaml_end_sequence(
+ __isl_take isl_printer *p);
+__isl_give isl_printer *isl_printer_yaml_next(__isl_take isl_printer *p);
+
__isl_give isl_printer *isl_printer_flush(__isl_take isl_printer *p);
#if defined(__cplusplus)
Modified: polly/trunk/lib/External/isl/include/isl/schedule.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/schedule.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/schedule.h (original)
+++ polly/trunk/lib/External/isl/include/isl/schedule.h Mon Feb 16 13:33:40 2015
@@ -3,7 +3,9 @@
#include <isl/union_set_type.h>
#include <isl/union_map_type.h>
+#include <isl/schedule_type.h>
#include <isl/band.h>
+#include <isl/space.h>
#include <isl/list.h>
#if defined(__cplusplus)
@@ -12,8 +14,6 @@ extern "C" {
struct isl_schedule_constraints;
typedef struct isl_schedule_constraints isl_schedule_constraints;
-struct isl_schedule;
-typedef struct isl_schedule isl_schedule;
int isl_options_set_schedule_max_coefficient(isl_ctx *ctx, int val);
int isl_options_get_schedule_max_coefficient(isl_ctx *ctx);
@@ -42,6 +42,8 @@ __isl_give isl_schedule_constraints *isl
__isl_keep isl_schedule_constraints *sc);
__isl_give isl_schedule_constraints *isl_schedule_constraints_on_domain(
__isl_take isl_union_set *domain);
+__isl_give isl_schedule_constraints *isl_schedule_constraints_set_context(
+ __isl_take isl_schedule_constraints *sc, __isl_take isl_set *context);
__isl_give isl_schedule_constraints *isl_schedule_constraints_set_validity(
__isl_take isl_schedule_constraints *sc,
__isl_take isl_union_map *validity);
@@ -71,14 +73,34 @@ __isl_give isl_schedule *isl_union_set_c
__isl_take isl_union_set *domain,
__isl_take isl_union_map *validity,
__isl_take isl_union_map *proximity);
+
+__isl_give isl_schedule *isl_schedule_empty(__isl_take isl_space *space);
+__isl_give isl_schedule *isl_schedule_from_domain(
+ __isl_take isl_union_set *domain);
+__isl_give isl_schedule *isl_schedule_copy(__isl_keep isl_schedule *sched);
__isl_null isl_schedule *isl_schedule_free(__isl_take isl_schedule *sched);
__isl_give isl_union_map *isl_schedule_get_map(__isl_keep isl_schedule *sched);
isl_ctx *isl_schedule_get_ctx(__isl_keep isl_schedule *sched);
+__isl_give isl_schedule_node *isl_schedule_get_root(
+ __isl_keep isl_schedule *schedule);
+__isl_give isl_union_set *isl_schedule_get_domain(
+ __isl_keep isl_schedule *schedule);
+
+int isl_schedule_foreach_schedule_node(__isl_keep isl_schedule *sched,
+ int (*fn)(__isl_keep isl_schedule_node *node, void *user), void *user);
+__isl_give isl_schedule *isl_schedule_map_schedule_node(
+ __isl_take isl_schedule *schedule,
+ __isl_give isl_schedule_node *(*fn)(
+ __isl_take isl_schedule_node *node, void *user), void *user);
+
__isl_give isl_band_list *isl_schedule_get_band_forest(
__isl_keep isl_schedule *schedule);
+__isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input);
+__isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
+ const char *str);
__isl_give isl_printer *isl_printer_print_schedule(__isl_take isl_printer *p,
__isl_keep isl_schedule *schedule);
void isl_schedule_dump(__isl_keep isl_schedule *schedule);
Added: polly/trunk/lib/External/isl/include/isl/schedule_node.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/schedule_node.h?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/schedule_node.h (added)
+++ polly/trunk/lib/External/isl/include/isl/schedule_node.h Mon Feb 16 13:33:40 2015
@@ -0,0 +1,123 @@
+#ifndef ISL_SCHEDULE_NODE_H
+#define ISL_SCHEDULE_NODE_H
+
+#include <isl/schedule_type.h>
+#include <isl/union_set_type.h>
+#include <isl/aff_type.h>
+#include <isl/val.h>
+#include <isl/space.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_schedule_node *isl_schedule_node_from_domain(
+ __isl_take isl_union_set *domain);
+__isl_give isl_schedule_node *isl_schedule_node_copy(
+ __isl_keep isl_schedule_node *node);
+__isl_null isl_schedule_node *isl_schedule_node_free(
+ __isl_take isl_schedule_node *node);
+
+isl_ctx *isl_schedule_node_get_ctx(__isl_keep isl_schedule_node *node);
+enum isl_schedule_node_type isl_schedule_node_get_type(
+ __isl_keep isl_schedule_node *node);
+enum isl_schedule_node_type isl_schedule_node_get_parent_type(
+ __isl_keep isl_schedule_node *node);
+__isl_give isl_schedule *isl_schedule_node_get_schedule(
+ __isl_keep isl_schedule_node *node);
+
+int isl_schedule_node_foreach_descendant(__isl_keep isl_schedule_node *node,
+ int (*fn)(__isl_keep isl_schedule_node *node, void *user), void *user);
+__isl_give isl_schedule_node *isl_schedule_node_map_descendant(
+ __isl_take isl_schedule_node *node,
+ __isl_give isl_schedule_node *(*fn)(__isl_take isl_schedule_node *node,
+ void *user), void *user);
+
+int isl_schedule_node_get_tree_depth(__isl_keep isl_schedule_node *node);
+int isl_schedule_node_has_parent(__isl_keep isl_schedule_node *node);
+int isl_schedule_node_has_children(__isl_keep isl_schedule_node *node);
+int isl_schedule_node_has_previous_sibling(__isl_keep isl_schedule_node *node);
+int isl_schedule_node_has_next_sibling(__isl_keep isl_schedule_node *node);
+int isl_schedule_node_n_children(__isl_keep isl_schedule_node *node);
+int isl_schedule_node_get_child_position(__isl_keep isl_schedule_node *node);
+__isl_give isl_schedule_node *isl_schedule_node_get_child(
+ __isl_keep isl_schedule_node *node, int pos);
+
+__isl_give isl_schedule_node *isl_schedule_node_parent(
+ __isl_take isl_schedule_node *node);
+__isl_give isl_schedule_node *isl_schedule_node_child(
+ __isl_take isl_schedule_node *node, int pos);
+__isl_give isl_schedule_node *isl_schedule_node_first_child(
+ __isl_take isl_schedule_node *node);
+__isl_give isl_schedule_node *isl_schedule_node_previous_sibling(
+ __isl_take isl_schedule_node *node);
+__isl_give isl_schedule_node *isl_schedule_node_next_sibling(
+ __isl_take isl_schedule_node *node);
+
+__isl_give isl_space *isl_schedule_node_band_get_space(
+ __isl_keep isl_schedule_node *node);
+__isl_give isl_multi_union_pw_aff *isl_schedule_node_band_get_partial_schedule(
+ __isl_keep isl_schedule_node *node);
+__isl_give isl_union_map *isl_schedule_node_band_get_partial_schedule_union_map(
+ __isl_keep isl_schedule_node *node);
+unsigned isl_schedule_node_band_n_member(__isl_keep isl_schedule_node *node);
+int isl_schedule_node_band_member_get_coincident(
+ __isl_keep isl_schedule_node *node, int pos);
+__isl_give isl_schedule_node *isl_schedule_node_band_member_set_coincident(
+ __isl_take isl_schedule_node *node, int pos, int coincident);
+int isl_schedule_node_band_get_permutable(__isl_keep isl_schedule_node *node);
+__isl_give isl_schedule_node *isl_schedule_node_band_set_permutable(
+ __isl_take isl_schedule_node *node, int permutable);
+
+int isl_options_set_tile_scale_tile_loops(isl_ctx *ctx, int val);
+int isl_options_get_tile_scale_tile_loops(isl_ctx *ctx);
+int isl_options_set_tile_shift_point_loops(isl_ctx *ctx, int val);
+int isl_options_get_tile_shift_point_loops(isl_ctx *ctx);
+
+__isl_give isl_schedule_node *isl_schedule_node_band_scale(
+ __isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv);
+__isl_give isl_schedule_node *isl_schedule_node_band_scale_down(
+ __isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv);
+__isl_give isl_schedule_node *isl_schedule_node_band_tile(
+ __isl_take isl_schedule_node *node, __isl_take isl_multi_val *sizes);
+__isl_give isl_schedule_node *isl_schedule_node_band_sink(
+ __isl_take isl_schedule_node *node);
+__isl_give isl_schedule_node *isl_schedule_node_band_split(
+ __isl_take isl_schedule_node *node, int pos);
+
+__isl_give isl_union_set *isl_schedule_node_domain_get_domain(
+ __isl_keep isl_schedule_node *node);
+__isl_give isl_union_set *isl_schedule_node_filter_get_filter(
+ __isl_keep isl_schedule_node *node);
+
+__isl_give isl_union_set *isl_schedule_node_get_universe_domain(
+ __isl_keep isl_schedule_node *node);
+__isl_give isl_union_pw_multi_aff *
+isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(
+ __isl_keep isl_schedule_node *node);
+__isl_give isl_union_map *isl_schedule_node_get_prefix_schedule_union_map(
+ __isl_keep isl_schedule_node *node);
+__isl_give isl_union_map *isl_schedule_node_get_subtree_schedule_union_map(
+ __isl_keep isl_schedule_node *node);
+
+__isl_give isl_schedule_node *isl_schedule_node_insert_partial_schedule(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_multi_union_pw_aff *schedule);
+__isl_give isl_schedule_node *isl_schedule_node_insert_filter(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *filter);
+__isl_give isl_schedule_node *isl_schedule_node_insert_sequence(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_union_set_list *filters);
+__isl_give isl_schedule_node *isl_schedule_node_insert_set(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_union_set_list *filters);
+
+__isl_give isl_printer *isl_printer_print_schedule_node(
+ __isl_take isl_printer *p, __isl_keep isl_schedule_node *node);
+void isl_schedule_node_dump(__isl_keep isl_schedule_node *node);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
Added: polly/trunk/lib/External/isl/include/isl/schedule_type.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/schedule_type.h?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/schedule_type.h (added)
+++ polly/trunk/lib/External/isl/include/isl/schedule_type.h Mon Feb 16 13:33:40 2015
@@ -0,0 +1,28 @@
+#ifndef ISL_SCHEDULE_TYPE_H
+#define ISL_SCHEDULE_TYPE_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+enum isl_schedule_node_type {
+ isl_schedule_node_error = -1,
+ isl_schedule_node_band,
+ isl_schedule_node_domain,
+ isl_schedule_node_filter,
+ isl_schedule_node_leaf,
+ isl_schedule_node_sequence,
+ isl_schedule_node_set
+};
+
+struct isl_schedule_node;
+typedef struct isl_schedule_node isl_schedule_node;
+
+struct isl_schedule;
+typedef struct isl_schedule isl_schedule;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
Modified: polly/trunk/lib/External/isl/include/isl/set.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/set.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/set.h (original)
+++ polly/trunk/lib/External/isl/include/isl/set.h Mon Feb 16 13:33:40 2015
@@ -158,10 +158,6 @@ __isl_give isl_printer *isl_printer_prin
__isl_take isl_printer *printer, __isl_keep isl_basic_set *bset);
__isl_give isl_printer *isl_printer_print_set(__isl_take isl_printer *printer,
__isl_keep isl_set *map);
-void isl_basic_set_print(__isl_keep isl_basic_set *bset, FILE *out, int indent,
- const char *prefix, const char *suffix, unsigned output_format);
-void isl_set_print(__isl_keep struct isl_set *set, FILE *out, int indent,
- unsigned output_format);
__isl_give isl_basic_set *isl_basic_set_fix_si(__isl_take isl_basic_set *bset,
enum isl_dim_type type, unsigned pos, int value);
__isl_give isl_basic_set *isl_basic_set_fix_val(__isl_take isl_basic_set *bset,
Modified: polly/trunk/lib/External/isl/include/isl/stream.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/stream.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/stream.h (original)
+++ polly/trunk/lib/External/isl/include/isl/stream.h Mon Feb 16 13:33:40 2015
@@ -15,6 +15,7 @@
#include <isl/aff_type.h>
#include <isl/obj.h>
#include <isl/val.h>
+#include <isl/schedule_type.h>
#if defined(__cplusplus)
extern "C" {
@@ -46,55 +47,47 @@ __isl_give char *isl_token_get_str(isl_c
int isl_token_get_type(struct isl_token *tok);
void isl_token_free(struct isl_token *tok);
-struct isl_stream {
- struct isl_ctx *ctx;
- FILE *file;
- const char *str;
- int line;
- int col;
- int eof;
-
- char *buffer;
- size_t size;
- size_t len;
- int c;
- int un[5];
- int n_un;
-
- struct isl_token *tokens[5];
- int n_token;
-
- struct isl_hash_table *keywords;
- enum isl_token_type next_type;
-};
-
-struct isl_stream* isl_stream_new_file(struct isl_ctx *ctx, FILE *file);
-struct isl_stream* isl_stream_new_str(struct isl_ctx *ctx, const char *str);
-void isl_stream_free(struct isl_stream *s);
-
-void isl_stream_error(struct isl_stream *s, struct isl_token *tok, char *msg);
-
-struct isl_token *isl_stream_next_token(struct isl_stream *s);
-struct isl_token *isl_stream_next_token_on_same_line(struct isl_stream *s);
-int isl_stream_next_token_is(struct isl_stream *s, int type);
-void isl_stream_push_token(struct isl_stream *s, struct isl_token *tok);
-void isl_stream_flush_tokens(struct isl_stream *s);
-int isl_stream_eat_if_available(struct isl_stream *s, int type);
-char *isl_stream_read_ident_if_available(struct isl_stream *s);
-int isl_stream_eat(struct isl_stream *s, int type);
-int isl_stream_is_empty(struct isl_stream *s);
-int isl_stream_skip_line(struct isl_stream *s);
+struct isl_stream;
+typedef struct isl_stream isl_stream;
-enum isl_token_type isl_stream_register_keyword(struct isl_stream *s,
+__isl_give isl_stream *isl_stream_new_file(isl_ctx *ctx, FILE *file);
+__isl_give isl_stream *isl_stream_new_str(isl_ctx *ctx, const char *str);
+void isl_stream_free(__isl_take isl_stream *s);
+
+isl_ctx *isl_stream_get_ctx(__isl_keep isl_stream *s);
+
+void isl_stream_error(__isl_keep isl_stream *s, struct isl_token *tok,
+ char *msg);
+
+struct isl_token *isl_stream_next_token(__isl_keep isl_stream *s);
+struct isl_token *isl_stream_next_token_on_same_line(__isl_keep isl_stream *s);
+int isl_stream_next_token_is(__isl_keep isl_stream *s, int type);
+void isl_stream_push_token(__isl_keep isl_stream *s, struct isl_token *tok);
+void isl_stream_flush_tokens(__isl_keep isl_stream *s);
+int isl_stream_eat_if_available(__isl_keep isl_stream *s, int type);
+char *isl_stream_read_ident_if_available(__isl_keep isl_stream *s);
+int isl_stream_eat(__isl_keep isl_stream *s, int type);
+int isl_stream_is_empty(__isl_keep isl_stream *s);
+int isl_stream_skip_line(__isl_keep isl_stream *s);
+
+enum isl_token_type isl_stream_register_keyword(__isl_keep isl_stream *s,
const char *name);
-struct isl_obj isl_stream_read_obj(struct isl_stream *s);
-__isl_give isl_multi_aff *isl_stream_read_multi_aff(struct isl_stream *s);
-__isl_give isl_map *isl_stream_read_map(struct isl_stream *s);
-__isl_give isl_set *isl_stream_read_set(struct isl_stream *s);
+struct isl_obj isl_stream_read_obj(__isl_keep isl_stream *s);
+__isl_give isl_val *isl_stream_read_val(__isl_keep isl_stream *s);
+__isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s);
+__isl_give isl_map *isl_stream_read_map(__isl_keep isl_stream *s);
+__isl_give isl_set *isl_stream_read_set(__isl_keep isl_stream *s);
__isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial(
- struct isl_stream *s);
-__isl_give isl_union_map *isl_stream_read_union_map(struct isl_stream *s);
+ __isl_keep isl_stream *s);
+__isl_give isl_union_map *isl_stream_read_union_map(__isl_keep isl_stream *s);
+__isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s);
+
+int isl_stream_yaml_read_start_mapping(__isl_keep isl_stream *s);
+int isl_stream_yaml_read_end_mapping(__isl_keep isl_stream *s);
+int isl_stream_yaml_read_start_sequence(__isl_keep isl_stream *s);
+int isl_stream_yaml_read_end_sequence(__isl_keep isl_stream *s);
+int isl_stream_yaml_next(__isl_keep isl_stream *s);
#if defined(__cplusplus)
}
Modified: polly/trunk/lib/External/isl/include/isl/union_map.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/union_map.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/union_map.h (original)
+++ polly/trunk/lib/External/isl/include/isl/union_map.h Mon Feb 16 13:33:40 2015
@@ -43,6 +43,8 @@ __isl_give isl_union_set *isl_union_map_
__isl_give isl_union_set *isl_union_map_range(__isl_take isl_union_map *umap);
__isl_give isl_union_map *isl_union_map_domain_map(
__isl_take isl_union_map *umap);
+__isl_give isl_union_pw_multi_aff *isl_union_map_domain_map_union_pw_multi_aff(
+ __isl_take isl_union_map *umap);
__isl_give isl_union_map *isl_union_map_range_map(
__isl_take isl_union_map *umap);
__isl_give isl_union_map *isl_union_set_wrapped_domain_map(
@@ -58,6 +60,8 @@ __isl_give isl_union_map *isl_union_map_
__isl_export
__isl_give isl_union_map *isl_union_map_polyhedral_hull(
__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_remove_redundancies(
+ __isl_take isl_union_map *umap);
__isl_give isl_union_map *isl_union_map_simple_hull(
__isl_take isl_union_map *umap);
__isl_export
@@ -88,6 +92,8 @@ __isl_give isl_union_map *isl_union_map_
__isl_take isl_union_map *umap2);
__isl_give isl_union_map *isl_union_map_domain_product(
__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_flat_domain_product(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
__isl_give isl_union_map *isl_union_map_range_product(
__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
__isl_give isl_union_map *isl_union_map_flat_range_product(
@@ -186,6 +192,8 @@ int isl_union_map_is_subset(__isl_keep i
__isl_export
int isl_union_map_is_equal(__isl_keep isl_union_map *umap1,
__isl_keep isl_union_map *umap2);
+int isl_union_map_is_disjoint(__isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2);
__isl_export
int isl_union_map_is_strict_subset(__isl_keep isl_union_map *umap1,
__isl_keep isl_union_map *umap2);
@@ -218,6 +226,16 @@ __isl_give isl_union_map *isl_union_map_
__isl_give isl_union_map *isl_union_map_lex_ge_union_map(
__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_eq_at_multi_union_pw_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_union_pw_aff *mupa);
+__isl_give isl_union_map *isl_union_map_lex_lt_at_multi_union_pw_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_union_pw_aff *mupa);
+__isl_give isl_union_map *isl_union_map_lex_gt_at_multi_union_pw_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_union_pw_aff *mupa);
+
__isl_give isl_union_map *isl_union_map_read_from_file(isl_ctx *ctx,
FILE *input);
__isl_constructor
@@ -240,6 +258,8 @@ __isl_give isl_union_map *isl_union_map_
__isl_give isl_union_set *isl_union_set_align_params(
__isl_take isl_union_set *uset, __isl_take isl_space *model);
+ISL_DECLARE_LIST_FN(union_map)
+
#if defined(__cplusplus)
}
#endif
Modified: polly/trunk/lib/External/isl/include/isl/union_map_type.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/union_map_type.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/union_map_type.h (original)
+++ polly/trunk/lib/External/isl/include/isl/union_map_type.h Mon Feb 16 13:33:40 2015
@@ -2,6 +2,7 @@
#define ISL_UNION_MAP_TYPE_H
#include <isl/ctx.h>
+#include <isl/list.h>
#if defined(__cplusplus)
extern "C" {
@@ -9,9 +10,11 @@ extern "C" {
struct __isl_export isl_union_map;
typedef struct isl_union_map isl_union_map;
+ISL_DECLARE_LIST_TYPE(union_map)
#ifndef isl_union_set
struct __isl_export isl_union_set;
typedef struct isl_union_set isl_union_set;
+ISL_DECLARE_LIST_TYPE(union_set)
#endif
#if defined(__cplusplus)
Modified: polly/trunk/lib/External/isl/include/isl/union_set.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/union_set.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/union_set.h (original)
+++ polly/trunk/lib/External/isl/include/isl/union_set.h Mon Feb 16 13:33:40 2015
@@ -39,6 +39,8 @@ __isl_give isl_union_set *isl_union_set_
__isl_export
__isl_give isl_union_set *isl_union_set_polyhedral_hull(
__isl_take isl_union_set *uset);
+__isl_give isl_union_set *isl_union_set_remove_redundancies(
+ __isl_take isl_union_set *uset);
__isl_give isl_union_set *isl_union_set_simple_hull(
__isl_take isl_union_set *uset);
__isl_export
@@ -84,6 +86,10 @@ __isl_give isl_union_set *isl_union_set_
__isl_take isl_union_set *uset,
__isl_take isl_union_pw_multi_aff *upma);
+__isl_give isl_union_set *isl_union_set_project_out(
+ __isl_take isl_union_set *uset,
+ enum isl_dim_type type, unsigned first, unsigned n);
+
int isl_union_set_is_params(__isl_keep isl_union_set *uset);
__isl_export
int isl_union_set_is_empty(__isl_keep isl_union_set *uset);
@@ -94,6 +100,8 @@ int isl_union_set_is_subset(__isl_keep i
__isl_export
int isl_union_set_is_equal(__isl_keep isl_union_set *uset1,
__isl_keep isl_union_set *uset2);
+int isl_union_set_is_disjoint(__isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2);
__isl_export
int isl_union_set_is_strict_subset(__isl_keep isl_union_set *uset1,
__isl_keep isl_union_set *uset2);
@@ -138,6 +146,11 @@ __isl_give isl_printer *isl_printer_prin
__isl_keep isl_union_set *uset);
void isl_union_set_dump(__isl_keep isl_union_set *uset);
+ISL_DECLARE_LIST_FN(union_set)
+
+__isl_give isl_union_set *isl_union_set_list_union(
+ __isl_take isl_union_set_list *list);
+
#if defined(__cplusplus)
}
#endif
Modified: polly/trunk/lib/External/isl/include/isl/val.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/val.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/val.h (original)
+++ polly/trunk/lib/External/isl/include/isl/val.h Mon Feb 16 13:33:40 2015
@@ -19,6 +19,9 @@ struct isl_multi_val;
typedef struct isl_multi_val isl_multi_val;
ISL_DECLARE_MULTI(val)
+ISL_DECLARE_MULTI_NEG(val)
+ISL_DECLARE_MULTI_DIMS(val)
+ISL_DECLARE_MULTI_WITH_DOMAIN(val)
__isl_give isl_val *isl_val_zero(isl_ctx *ctx);
__isl_give isl_val *isl_val_one(isl_ctx *ctx);
@@ -102,6 +105,8 @@ __isl_give isl_multi_val *isl_multi_val_
__isl_give isl_multi_val *isl_multi_val_mod_val(__isl_take isl_multi_val *mv,
__isl_take isl_val *v);
+__isl_give isl_multi_val *isl_multi_val_read_from_str(isl_ctx *ctx,
+ const char *str);
__isl_give isl_printer *isl_printer_print_multi_val(__isl_take isl_printer *p,
__isl_keep isl_multi_val *mv);
void isl_multi_val_dump(__isl_keep isl_multi_val *mv);
Modified: polly/trunk/lib/External/isl/interface/extract_interface.cc
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/interface/extract_interface.cc?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/interface/extract_interface.cc (original)
+++ polly/trunk/lib/External/isl/interface/extract_interface.cc Mon Feb 16 13:33:40 2015
@@ -174,6 +174,14 @@ static Driver *construct_driver(const ch
}
#endif
+/* Clang changed its API from 3.5 to 3.6, we fix this with a simple overloaded
+ * function here.
+ */
+struct ClangAPI {
+ static Job *command(Job *J) { return J; }
+ static Job *command(Job &J) { return &J; }
+};
+
/* Create a CompilerInvocation object that stores the command line
* arguments constructed by the driver.
* The arguments are mainly useful for setting up the system include
@@ -191,7 +199,7 @@ static CompilerInvocation *construct_inv
driver->BuildCompilation(llvm::ArrayRef<const char *>(Argv)));
JobList &Jobs = compilation->getJobs();
- Command *cmd = cast<Command>(*Jobs.begin());
+ Command *cmd = cast<Command>(ClangAPI::command(*Jobs.begin()));
if (strcmp(cmd->getCreator().getName(), "clang"))
return NULL;
Modified: polly/trunk/lib/External/isl/interface/python.cc
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/interface/python.cc?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/interface/python.cc (original)
+++ polly/trunk/lib/External/isl/interface/python.cc Mon Feb 16 13:33:40 2015
@@ -220,8 +220,8 @@ static void print_callback(QualType type
for (int i = 0; i < n_arg - 1; ++i) {
string arg_type;
arg_type = type2python(extract_type(fn->getArgType(i)));
- printf(" cb_arg%d = %s(ctx=arg0.ctx, ptr=cb_arg%d)\n",
- i, arg_type.c_str(), i);
+ printf(" cb_arg%d = %s(ctx=arg0.ctx, "
+ "ptr=cb_arg%d)\n", i, arg_type.c_str(), i);
}
printf(" try:\n");
printf(" arg%d(", arg);
@@ -446,7 +446,8 @@ void isl_class::print(map<string, isl_cl
printf(" libc.free(ptr)\n");
printf(" return res\n");
printf(" def __repr__(self):\n");
- printf(" return 'isl.%s(\"%%s\")' %% str(self)\n", p_name.c_str());
+ printf(" return 'isl.%s(\"%%s\")' %% str(self)\n",
+ p_name.c_str());
for (in = methods.begin(); in != methods.end(); ++in)
print_method(*in, subclass, super);
Modified: polly/trunk/lib/External/isl/isl_aff.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_aff.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_aff.c (original)
+++ polly/trunk/lib/External/isl/isl_aff.c Mon Feb 16 13:33:40 2015
@@ -2,6 +2,7 @@
* Copyright 2011 INRIA Saclay
* Copyright 2011 Sven Verdoolaege
* Copyright 2012-2014 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
*
* Use of this software is governed by the MIT license
*
@@ -9,6 +10,8 @@
* Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
* 91893 Orsay, France
* and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
*/
#include <isl_ctx_private.h>
@@ -37,6 +40,16 @@
#include <isl_list_templ.c>
+#undef BASE
+#define BASE union_pw_aff
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE union_pw_multi_aff
+
+#include <isl_list_templ.c>
+
__isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls,
__isl_take isl_vec *v)
{
@@ -2097,8 +2110,8 @@ error:
/* Exploit the equalities in "eq" to simplify the affine expression
* and the expressions of the integer divisions in the local space.
*/
-static __isl_give isl_aff *isl_aff_substitute_equalities(
- __isl_take isl_aff *aff, __isl_take isl_basic_set *eq)
+__isl_give isl_aff *isl_aff_substitute_equalities(__isl_take isl_aff *aff,
+ __isl_take isl_basic_set *eq)
{
int n_div;
@@ -2157,6 +2170,42 @@ __isl_give isl_aff *isl_aff_gist_params(
}
/* Return a basic set containing those elements in the space
+ * of aff where it is positive. "rational" should not be set.
+ *
+ * If "aff" is NaN, then it is not positive.
+ */
+static __isl_give isl_basic_set *aff_pos_basic_set(__isl_take isl_aff *aff,
+ int rational)
+{
+ isl_constraint *ineq;
+ isl_basic_set *bset;
+ isl_val *c;
+
+ if (!aff)
+ return NULL;
+ if (isl_aff_is_nan(aff)) {
+ isl_space *space = isl_aff_get_domain_space(aff);
+ isl_aff_free(aff);
+ return isl_basic_set_empty(space);
+ }
+ if (rational)
+ isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
+ "rational sets not supported", goto error);
+
+ ineq = isl_inequality_from_aff(aff);
+ c = isl_constraint_get_constant_val(ineq);
+ c = isl_val_sub_ui(c, 1);
+ ineq = isl_constraint_set_constant_val(ineq, c);
+
+ bset = isl_basic_set_from_constraint(ineq);
+ bset = isl_basic_set_simplify(bset);
+ return bset;
+error:
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Return a basic set containing those elements in the space
* of aff where it is non-negative.
* If "rational" is set, then return a rational basic set.
*
@@ -2522,6 +2571,17 @@ __isl_give isl_pw_aff *isl_pw_aff_from_a
#include <isl_pw_templ.c>
+#undef UNION
+#define UNION isl_union_pw_aff
+#undef PART
+#define PART isl_pw_aff
+#undef PARTS
+#define PARTS pw_aff
+
+#define NO_EVAL
+
+#include <isl_union_templ.c>
+
static __isl_give isl_set *align_params_pw_pw_set_and(
__isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2,
__isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
@@ -2545,6 +2605,31 @@ error:
return NULL;
}
+/* Align the parameters of the to isl_pw_aff arguments and
+ * then apply a function "fn" on them that returns an isl_map.
+ */
+static __isl_give isl_map *align_params_pw_pw_map_and(
+ __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2,
+ __isl_give isl_map *(*fn)(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2))
+{
+ if (!pa1 || !pa2)
+ goto error;
+ if (isl_space_match(pa1->dim, isl_dim_param, pa2->dim, isl_dim_param))
+ return fn(pa1, pa2);
+ if (!isl_space_has_named_params(pa1->dim) ||
+ !isl_space_has_named_params(pa2->dim))
+ isl_die(isl_pw_aff_get_ctx(pa1), isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ pa1 = isl_pw_aff_align_params(pa1, isl_pw_aff_get_space(pa2));
+ pa2 = isl_pw_aff_align_params(pa2, isl_pw_aff_get_space(pa1));
+ return fn(pa1, pa2);
+error:
+ isl_pw_aff_free(pa1);
+ isl_pw_aff_free(pa2);
+ return NULL;
+}
+
/* Compute a piecewise quasi-affine expression with a domain that
* is the union of those of pwaff1 and pwaff2 and such that on each
* cell, the quasi-affine expression is the better (according to cmp)
@@ -2740,44 +2825,14 @@ error:
}
/* Return a set containing those elements in the domain
- * of pwaff where it is non-negative.
- */
-__isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff)
-{
- int i;
- isl_set *set;
-
- if (!pwaff)
- return NULL;
-
- set = isl_set_empty(isl_pw_aff_get_domain_space(pwaff));
-
- for (i = 0; i < pwaff->n; ++i) {
- isl_basic_set *bset;
- isl_set *set_i;
- int rational;
-
- rational = isl_set_has_rational(pwaff->p[i].set);
- bset = aff_nonneg_basic_set(isl_aff_copy(pwaff->p[i].aff),
- rational);
- set_i = isl_set_from_basic_set(bset);
- set_i = isl_set_intersect(set_i, isl_set_copy(pwaff->p[i].set));
- set = isl_set_union_disjoint(set, set_i);
- }
-
- isl_pw_aff_free(pwaff);
-
- return set;
-}
-
-/* Return a set containing those elements in the domain
- * of pwaff where it is zero (if complement is 0) or not zero
- * (if complement is 1).
+ * of "pwaff" where it satisfies "fn" (if complement is 0) or
+ * does not satisfy "fn" (if complement is 1).
*
* The pieces with a NaN never belong to the result since
- * NaN is neither zero nor non-zero.
+ * NaN does not satisfy any property.
*/
-static __isl_give isl_set *pw_aff_zero_set(__isl_take isl_pw_aff *pwaff,
+static __isl_give isl_set *pw_aff_locus(__isl_take isl_pw_aff *pwaff,
+ __isl_give isl_basic_set *(*fn)(__isl_take isl_aff *aff, int rational),
int complement)
{
int i;
@@ -2790,21 +2845,20 @@ static __isl_give isl_set *pw_aff_zero_s
for (i = 0; i < pwaff->n; ++i) {
isl_basic_set *bset;
- isl_set *set_i, *zero;
+ isl_set *set_i, *locus;
int rational;
if (isl_aff_is_nan(pwaff->p[i].aff))
continue;
rational = isl_set_has_rational(pwaff->p[i].set);
- bset = aff_zero_basic_set(isl_aff_copy(pwaff->p[i].aff),
- rational);
- zero = isl_set_from_basic_set(bset);
+ bset = fn(isl_aff_copy(pwaff->p[i].aff), rational);
+ locus = isl_set_from_basic_set(bset);
set_i = isl_set_copy(pwaff->p[i].set);
if (complement)
- set_i = isl_set_subtract(set_i, zero);
+ set_i = isl_set_subtract(set_i, locus);
else
- set_i = isl_set_intersect(set_i, zero);
+ set_i = isl_set_intersect(set_i, locus);
set = isl_set_union_disjoint(set, set_i);
}
@@ -2814,11 +2868,27 @@ static __isl_give isl_set *pw_aff_zero_s
}
/* Return a set containing those elements in the domain
+ * of "pa" where it is positive.
+ */
+__isl_give isl_set *isl_pw_aff_pos_set(__isl_take isl_pw_aff *pa)
+{
+ return pw_aff_locus(pa, &aff_pos_basic_set, 0);
+}
+
+/* Return a set containing those elements in the domain
+ * of pwaff where it is non-negative.
+ */
+__isl_give isl_set *isl_pw_aff_nonneg_set(__isl_take isl_pw_aff *pwaff)
+{
+ return pw_aff_locus(pwaff, &aff_nonneg_basic_set, 0);
+}
+
+/* Return a set containing those elements in the domain
* of pwaff where it is zero.
*/
__isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff)
{
- return pw_aff_zero_set(pwaff, 0);
+ return pw_aff_locus(pwaff, &aff_zero_basic_set, 0);
}
/* Return a set containing those elements in the domain
@@ -2826,7 +2896,7 @@ __isl_give isl_set *isl_pw_aff_zero_set(
*/
__isl_give isl_set *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff)
{
- return pw_aff_zero_set(pwaff, 1);
+ return pw_aff_locus(pwaff, &aff_zero_basic_set, 1);
}
/* Return a set containing those elements in the shared domain
@@ -2921,6 +2991,97 @@ __isl_give isl_set *isl_pw_aff_lt_set(__
return isl_pw_aff_gt_set(pwaff2, pwaff1);
}
+/* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
+ * where the function values are ordered in the same way as "order",
+ * which returns a set in the shared domain of its two arguments.
+ * The parameters of "pa1" and "pa2" are assumed to have been aligned.
+ *
+ * Let "pa1" and "pa2" be defined on domains A and B respectively.
+ * We first pull back the two functions such that they are defined on
+ * the domain [A -> B]. Then we apply "order", resulting in a set
+ * in the space [A -> B]. Finally, we unwrap this set to obtain
+ * a map in the space A -> B.
+ */
+static __isl_give isl_map *isl_pw_aff_order_map_aligned(
+ __isl_take isl_pw_aff *pa1, __isl_take isl_pw_aff *pa2,
+ __isl_give isl_set *(*order)(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2))
+{
+ isl_space *space1, *space2;
+ isl_multi_aff *ma;
+ isl_set *set;
+
+ space1 = isl_space_domain(isl_pw_aff_get_space(pa1));
+ space2 = isl_space_domain(isl_pw_aff_get_space(pa2));
+ space1 = isl_space_map_from_domain_and_range(space1, space2);
+ ma = isl_multi_aff_domain_map(isl_space_copy(space1));
+ pa1 = isl_pw_aff_pullback_multi_aff(pa1, ma);
+ ma = isl_multi_aff_range_map(space1);
+ pa2 = isl_pw_aff_pullback_multi_aff(pa2, ma);
+ set = order(pa1, pa2);
+
+ return isl_set_unwrap(set);
+}
+
+/* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
+ * where the function values are equal.
+ * The parameters of "pa1" and "pa2" are assumed to have been aligned.
+ */
+static __isl_give isl_map *isl_pw_aff_eq_map_aligned(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2)
+{
+ return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_eq_set);
+}
+
+/* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
+ * where the function values are equal.
+ */
+__isl_give isl_map *isl_pw_aff_eq_map(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2)
+{
+ return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_eq_map_aligned);
+}
+
+/* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
+ * where the function value of "pa1" is less than the function value of "pa2".
+ * The parameters of "pa1" and "pa2" are assumed to have been aligned.
+ */
+static __isl_give isl_map *isl_pw_aff_lt_map_aligned(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2)
+{
+ return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_lt_set);
+}
+
+/* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
+ * where the function value of "pa1" is less than the function value of "pa2".
+ */
+__isl_give isl_map *isl_pw_aff_lt_map(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2)
+{
+ return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_lt_map_aligned);
+}
+
+/* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
+ * where the function value of "pa1" is greater than the function value
+ * of "pa2".
+ * The parameters of "pa1" and "pa2" are assumed to have been aligned.
+ */
+static __isl_give isl_map *isl_pw_aff_gt_map_aligned(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2)
+{
+ return isl_pw_aff_order_map_aligned(pa1, pa2, &isl_pw_aff_gt_set);
+}
+
+/* Return a map containing pairs of elements in the domains of "pa1" and "pa2"
+ * where the function value of "pa1" is greater than the function value
+ * of "pa2".
+ */
+__isl_give isl_map *isl_pw_aff_gt_map(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2)
+{
+ return align_params_pw_pw_map_and(pa1, pa2, &isl_pw_aff_gt_map_aligned);
+}
+
/* Return a set containing those elements in the shared domain
* of the elements of list1 and list2 where each element in list1
* has the relation specified by "fn" with each element in list2.
@@ -3576,13 +3737,16 @@ error:
#undef BASE
#define BASE aff
-#define NO_INTERSECT_DOMAIN
+#undef DOMBASE
+#define DOMBASE set
#define NO_DOMAIN
#include <isl_multi_templ.c>
+#include <isl_multi_apply_set.c>
+#include <isl_multi_floor.c>
+#include <isl_multi_gist.c>
#undef NO_DOMAIN
-#undef NO_INTERSECT_DOMAIN
/* Remove any internal structure of the domain of "ma".
* If there is any such internal structure in the input,
@@ -3687,6 +3851,15 @@ error:
return NULL;
}
+/* Given a map space, return an isl_pw_multi_aff that maps a wrapped copy
+ * of the space to its range.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_map(
+ __isl_take isl_space *space)
+{
+ return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_range_map(space));
+}
+
/* Given the space of a set and a range of set dimensions,
* construct an isl_multi_aff that projects out those dimensions.
*/
@@ -3796,25 +3969,6 @@ __isl_give isl_multi_aff *isl_multi_aff_
&isl_multi_aff_add_aligned);
}
-/* Subtract "ma2" from "ma1" and return the result.
- *
- * The parameters of "ma1" and "ma2" are assumed to have been aligned.
- */
-static __isl_give isl_multi_aff *isl_multi_aff_sub_aligned(
- __isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
-{
- return isl_multi_aff_bin_op(ma1, ma2, &isl_aff_sub);
-}
-
-/* Subtract "ma2" from "ma1" and return the result.
- */
-__isl_give isl_multi_aff *isl_multi_aff_sub(__isl_take isl_multi_aff *ma1,
- __isl_take isl_multi_aff *ma2)
-{
- return isl_multi_aff_align_params_multi_multi_and(ma1, ma2,
- &isl_multi_aff_sub_aligned);
-}
-
/* Exploit the equalities in "eq" to simplify the affine expressions.
*/
static __isl_give isl_multi_aff *isl_multi_aff_substitute_equalities(
@@ -3841,25 +3995,6 @@ error:
return NULL;
}
-/* Given f, return floor(f).
- */
-__isl_give isl_multi_aff *isl_multi_aff_floor(__isl_take isl_multi_aff *ma)
-{
- int i;
-
- ma = isl_multi_aff_cow(ma);
- if (!ma)
- return NULL;
-
- for (i = 0; i < ma->n; ++i) {
- ma->p[i] = isl_aff_floor(ma->p[i]);
- if (!ma->p[i])
- return isl_multi_aff_free(ma);
- }
-
- return ma;
-}
-
__isl_give isl_multi_aff *isl_multi_aff_scale(__isl_take isl_multi_aff *maff,
isl_int f)
{
@@ -3939,7 +4074,7 @@ __isl_give isl_set *isl_multi_aff_lex_ge
#undef DEFAULT_IS_ZERO
#define DEFAULT_IS_ZERO 0
-#define NO_NEG
+#define NO_SUB
#define NO_EVAL
#define NO_OPT
#define NO_INVOLVES_DIMS
@@ -3949,13 +4084,14 @@ __isl_give isl_set *isl_multi_aff_lex_ge
#include <isl_pw_templ.c>
+#undef NO_SUB
+
#undef UNION
#define UNION isl_union_pw_multi_aff
#undef PART
#define PART isl_pw_multi_aff
#undef PARTS
#define PARTS pw_multi_aff
-#define ALIGN_DOMAIN
#define NO_EVAL
@@ -4149,6 +4285,16 @@ __isl_give isl_pw_multi_aff *isl_pw_mult
return isl_pw_multi_aff_union_add_(pma1, pma2);
}
+/* Compute the sum of "upa1" and "upa2" on the union of their domains,
+ * with the actual sum on the shared domain and
+ * the defined expression on the symmetric difference of the domains.
+ */
+__isl_give isl_union_pw_aff *isl_union_pw_aff_union_add(
+ __isl_take isl_union_pw_aff *upa1, __isl_take isl_union_pw_aff *upa2)
+{
+ return isl_union_pw_aff_union_add_(upa1, upa2);
+}
+
/* Compute the sum of "upma1" and "upma2" on the union of their domains,
* with the actual sum on the shared domain and
* the defined expression on the symmetric difference of the domains.
@@ -4885,6 +5031,20 @@ static int pw_multi_aff_from_map(__isl_t
return *upma ? 0 : -1;
}
+/* Create an isl_union_pw_multi_aff with the given isl_aff on a universe
+ * domain.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_aff(
+ __isl_take isl_aff *aff)
+{
+ isl_multi_aff *ma;
+ isl_pw_multi_aff *pma;
+
+ ma = isl_multi_aff_from_aff(aff);
+ pma = isl_pw_multi_aff_from_multi_aff(ma);
+ return isl_union_pw_multi_aff_from_pw_multi_aff(pma);
+}
+
/* Try and create an isl_union_pw_multi_aff that is equivalent
* to the given isl_union_map.
* The isl_union_map is required to be single-valued in each space.
@@ -5859,8 +6019,13 @@ error:
#undef BASE
#define BASE pw_aff
+#undef DOMBASE
+#define DOMBASE set
#include <isl_multi_templ.c>
+#include <isl_multi_apply_set.c>
+#include <isl_multi_gist.c>
+#include <isl_multi_intersect.c>
/* Scale the elements of "pma" by the corresponding elements of "mv".
*/
@@ -6618,6 +6783,189 @@ __isl_give isl_multi_pw_aff *isl_multi_p
&isl_multi_pw_aff_pullback_multi_pw_aff_aligned);
}
+/* Align the parameters of "mpa1" and "mpa2", check that the ranges
+ * of "mpa1" and "mpa2" live in the same space, construct map space
+ * between the domain spaces of "mpa1" and "mpa2" and call "order"
+ * with this map space as extract argument.
+ */
+static __isl_give isl_map *isl_multi_pw_aff_order_map(
+ __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
+ __isl_give isl_map *(*order)(__isl_keep isl_multi_pw_aff *mpa1,
+ __isl_keep isl_multi_pw_aff *mpa2, __isl_take isl_space *space))
+{
+ int match;
+ isl_space *space1, *space2;
+ isl_map *res;
+
+ mpa1 = isl_multi_pw_aff_align_params(mpa1,
+ isl_multi_pw_aff_get_space(mpa2));
+ mpa2 = isl_multi_pw_aff_align_params(mpa2,
+ isl_multi_pw_aff_get_space(mpa1));
+ if (!mpa1 || !mpa2)
+ goto error;
+ match = isl_space_tuple_is_equal(mpa1->space, isl_dim_out,
+ mpa2->space, isl_dim_out);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_multi_pw_aff_get_ctx(mpa1), isl_error_invalid,
+ "range spaces don't match", goto error);
+ space1 = isl_space_domain(isl_multi_pw_aff_get_space(mpa1));
+ space2 = isl_space_domain(isl_multi_pw_aff_get_space(mpa2));
+ space1 = isl_space_map_from_domain_and_range(space1, space2);
+
+ res = order(mpa1, mpa2, space1);
+ isl_multi_pw_aff_free(mpa1);
+ isl_multi_pw_aff_free(mpa2);
+ return res;
+error:
+ isl_multi_pw_aff_free(mpa1);
+ isl_multi_pw_aff_free(mpa2);
+ return NULL;
+}
+
+/* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
+ * where the function values are equal. "space" is the space of the result.
+ * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
+ *
+ * "mpa1" and "mpa2" are equal when each of the pairs of elements
+ * in the sequences are equal.
+ */
+static __isl_give isl_map *isl_multi_pw_aff_eq_map_on_space(
+ __isl_keep isl_multi_pw_aff *mpa1, __isl_keep isl_multi_pw_aff *mpa2,
+ __isl_take isl_space *space)
+{
+ int i, n;
+ isl_map *res;
+
+ res = isl_map_universe(space);
+
+ n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa1, *pa2;
+ isl_map *map;
+
+ pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
+ pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
+ map = isl_pw_aff_eq_map(pa1, pa2);
+ res = isl_map_intersect(res, map);
+ }
+
+ return res;
+}
+
+/* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
+ * where the function values are equal.
+ */
+__isl_give isl_map *isl_multi_pw_aff_eq_map(__isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2)
+{
+ return isl_multi_pw_aff_order_map(mpa1, mpa2,
+ &isl_multi_pw_aff_eq_map_on_space);
+}
+
+/* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
+ * where the function values of "mpa1" is lexicographically satisfies "base"
+ * compared to that of "mpa2". "space" is the space of the result.
+ * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
+ *
+ * "mpa1" lexicographically satisfies "base" compared to "mpa2"
+ * if its i-th element satisfies "base" when compared to
+ * the i-th element of "mpa2" while all previous elements are
+ * pairwise equal.
+ */
+static __isl_give isl_map *isl_multi_pw_aff_lex_map_on_space(
+ __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
+ __isl_give isl_map *(*base)(__isl_take isl_pw_aff *pa1,
+ __isl_take isl_pw_aff *pa2),
+ __isl_take isl_space *space)
+{
+ int i, n;
+ isl_map *res, *rest;
+
+ res = isl_map_empty(isl_space_copy(space));
+ rest = isl_map_universe(space);
+
+ n = isl_multi_pw_aff_dim(mpa1, isl_dim_out);
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa1, *pa2;
+ isl_map *map;
+
+ pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
+ pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
+ map = base(pa1, pa2);
+ map = isl_map_intersect(map, isl_map_copy(rest));
+ res = isl_map_union(res, map);
+
+ if (i == n - 1)
+ continue;
+
+ pa1 = isl_multi_pw_aff_get_pw_aff(mpa1, i);
+ pa2 = isl_multi_pw_aff_get_pw_aff(mpa2, i);
+ map = isl_pw_aff_eq_map(pa1, pa2);
+ rest = isl_map_intersect(rest, map);
+ }
+
+ isl_map_free(rest);
+ return res;
+}
+
+/* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
+ * where the function value of "mpa1" is lexicographically less than that
+ * of "mpa2". "space" is the space of the result.
+ * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
+ *
+ * "mpa1" is less than "mpa2" if its i-th element is smaller
+ * than the i-th element of "mpa2" while all previous elements are
+ * pairwise equal.
+ */
+__isl_give isl_map *isl_multi_pw_aff_lex_lt_map_on_space(
+ __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
+ __isl_take isl_space *space)
+{
+ return isl_multi_pw_aff_lex_map_on_space(mpa1, mpa2,
+ &isl_pw_aff_lt_map, space);
+}
+
+/* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
+ * where the function value of "mpa1" is lexicographically less than that
+ * of "mpa2".
+ */
+__isl_give isl_map *isl_multi_pw_aff_lex_lt_map(
+ __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
+{
+ return isl_multi_pw_aff_order_map(mpa1, mpa2,
+ &isl_multi_pw_aff_lex_lt_map_on_space);
+}
+
+/* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
+ * where the function value of "mpa1" is lexicographically greater than that
+ * of "mpa2". "space" is the space of the result.
+ * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
+ *
+ * "mpa1" is greater than "mpa2" if its i-th element is greater
+ * than the i-th element of "mpa2" while all previous elements are
+ * pairwise equal.
+ */
+__isl_give isl_map *isl_multi_pw_aff_lex_gt_map_on_space(
+ __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2,
+ __isl_take isl_space *space)
+{
+ return isl_multi_pw_aff_lex_map_on_space(mpa1, mpa2,
+ &isl_pw_aff_gt_map, space);
+}
+
+/* Return a map containing pairs of elements in the domains of "mpa1" and "mpa2"
+ * where the function value of "mpa1" is lexicographically greater than that
+ * of "mpa2".
+ */
+__isl_give isl_map *isl_multi_pw_aff_lex_gt_map(
+ __isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
+{
+ return isl_multi_pw_aff_order_map(mpa1, mpa2,
+ &isl_multi_pw_aff_lex_gt_map_on_space);
+}
+
/* Compare two isl_affs.
*
* Return -1 if "aff1" is "smaller" than "aff2", 1 if "aff1" is "greater"
@@ -6807,3 +7155,1546 @@ __isl_give isl_union_pw_multi_aff *isl_u
isl_multi_val_free(mv);
return data.res;
}
+
+/* Compute the pullback of data->pma by the function represented by "pma2",
+ * provided the spaces match, and add the results to data->res.
+ */
+static int pullback_entry(void **entry, void *user)
+{
+ struct isl_union_pw_multi_aff_bin_data *data = user;
+ isl_pw_multi_aff *pma2 = *entry;
+
+ if (!isl_space_tuple_is_equal(data->pma->dim, isl_dim_in,
+ pma2->dim, isl_dim_out))
+ return 0;
+
+ pma2 = isl_pw_multi_aff_pullback_pw_multi_aff(
+ isl_pw_multi_aff_copy(data->pma),
+ isl_pw_multi_aff_copy(pma2));
+
+ data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma2);
+ if (!data->res)
+ return -1;
+
+ return 0;
+}
+
+/* Compute the pullback of "upma1" by the function represented by "upma2".
+ */
+__isl_give isl_union_pw_multi_aff *
+isl_union_pw_multi_aff_pullback_union_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma1,
+ __isl_take isl_union_pw_multi_aff *upma2)
+{
+ return bin_op(upma1, upma2, &pullback_entry);
+}
+
+/* Check that the domain space of "upa" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ *
+ * This function is called from isl_multi_union_pw_aff_set_union_pw_aff and
+ * can in principle never fail since the space "space" is that
+ * of the isl_multi_union_pw_aff and is a set space such that
+ * there is no domain space to match.
+ *
+ * We check the parameters and double-check that "space" is
+ * indeed that of a set.
+ */
+static int isl_union_pw_aff_check_match_domain_space(
+ __isl_keep isl_union_pw_aff *upa, __isl_keep isl_space *space)
+{
+ isl_space *upa_space;
+ int match;
+
+ if (!upa || !space)
+ return -1;
+
+ match = isl_space_is_set(space);
+ if (match < 0)
+ return -1;
+ if (!match)
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "expecting set space", return -1);
+
+ upa_space = isl_union_pw_aff_get_space(upa);
+ match = isl_space_match(space, isl_dim_param, upa_space, isl_dim_param);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "parameters don't match", goto error);
+
+ isl_space_free(upa_space);
+ return 0;
+error:
+ isl_space_free(upa_space);
+ return -1;
+}
+
+/* Do the parameters of "upa" match those of "space"?
+ */
+static int isl_union_pw_aff_matching_params(__isl_keep isl_union_pw_aff *upa,
+ __isl_keep isl_space *space)
+{
+ isl_space *upa_space;
+ int match;
+
+ if (!upa || !space)
+ return -1;
+
+ upa_space = isl_union_pw_aff_get_space(upa);
+
+ match = isl_space_match(space, isl_dim_param, upa_space, isl_dim_param);
+
+ isl_space_free(upa_space);
+ return match;
+}
+
+/* Internal data structure for isl_union_pw_aff_reset_domain_space.
+ * space represents the new parameters.
+ * res collects the results.
+ */
+struct isl_union_pw_aff_reset_params_data {
+ isl_space *space;
+ isl_union_pw_aff *res;
+};
+
+/* Replace the parameters of "pa" by data->space and
+ * add the result to data->res.
+ */
+static int reset_params(__isl_take isl_pw_aff *pa, void *user)
+{
+ struct isl_union_pw_aff_reset_params_data *data = user;
+ isl_space *space;
+
+ space = isl_pw_aff_get_space(pa);
+ space = isl_space_replace(space, isl_dim_param, data->space);
+ pa = isl_pw_aff_reset_space(pa, space);
+ data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
+
+ return data->res ? 0 : -1;
+}
+
+/* Replace the domain space of "upa" by "space".
+ * Since a union expression does not have a (single) domain space,
+ * "space" is necessarily a parameter space.
+ *
+ * Since the order and the names of the parameters determine
+ * the hash value, we need to create a new hash table.
+ */
+static __isl_give isl_union_pw_aff *isl_union_pw_aff_reset_domain_space(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_space *space)
+{
+ struct isl_union_pw_aff_reset_params_data data = { space };
+ int match;
+
+ match = isl_union_pw_aff_matching_params(upa, space);
+ if (match < 0)
+ upa = isl_union_pw_aff_free(upa);
+ else if (match) {
+ isl_space_free(space);
+ return upa;
+ }
+
+ data.res = isl_union_pw_aff_empty(isl_space_copy(space));
+ if (isl_union_pw_aff_foreach_pw_aff(upa, &reset_params, &data) < 0)
+ data.res = isl_union_pw_aff_free(data.res);
+
+ isl_union_pw_aff_free(upa);
+ isl_space_free(space);
+ return data.res;
+}
+
+/* Replace the entry of isl_union_pw_aff to which "entry" points
+ * by its floor.
+ */
+static int floor_entry(void **entry, void *user)
+{
+ isl_pw_aff **pa = (isl_pw_aff **) entry;
+
+ *pa = isl_pw_aff_floor(*pa);
+ if (!*pa)
+ return -1;
+
+ return 0;
+}
+
+/* Given f, return floor(f).
+ */
+__isl_give isl_union_pw_aff *isl_union_pw_aff_floor(
+ __isl_take isl_union_pw_aff *upa)
+{
+ isl_ctx *ctx;
+
+ upa = isl_union_pw_aff_cow(upa);
+ if (!upa)
+ return NULL;
+
+ ctx = isl_union_pw_aff_get_ctx(upa);
+ if (isl_hash_table_foreach(ctx, &upa->table, &floor_entry, NULL) < 0)
+ upa = isl_union_pw_aff_free(upa);
+
+ return upa;
+}
+
+/* Compute
+ *
+ * upa mod m = upa - m * floor(upa/m)
+ *
+ * with m an integer value.
+ */
+__isl_give isl_union_pw_aff *isl_union_pw_aff_mod_val(
+ __isl_take isl_union_pw_aff *upa, __isl_take isl_val *m)
+{
+ isl_union_pw_aff *res;
+
+ if (!upa || !m)
+ goto error;
+
+ if (!isl_val_is_int(m))
+ isl_die(isl_val_get_ctx(m), isl_error_invalid,
+ "expecting integer modulo", goto error);
+ if (!isl_val_is_pos(m))
+ isl_die(isl_val_get_ctx(m), isl_error_invalid,
+ "expecting positive modulo", goto error);
+
+ res = isl_union_pw_aff_copy(upa);
+ upa = isl_union_pw_aff_scale_down_val(upa, isl_val_copy(m));
+ upa = isl_union_pw_aff_floor(upa);
+ upa = isl_union_pw_aff_scale_val(upa, m);
+ res = isl_union_pw_aff_sub(res, upa);
+
+ return res;
+error:
+ isl_val_free(m);
+ isl_union_pw_aff_free(upa);
+ return NULL;
+}
+
+/* Internal data structure for isl_union_pw_aff_aff_on_domain.
+ * "aff" is the symbolic value that the resulting isl_union_pw_aff
+ * needs to attain.
+ * "res" collects the results.
+ */
+struct isl_union_pw_aff_aff_on_domain_data {
+ isl_aff *aff;
+ isl_union_pw_aff *res;
+};
+
+/* Construct a piecewise affine expression that is equal to data->aff
+ * on "domain" and add the result to data->res.
+ */
+static int pw_aff_aff_on_domain(__isl_take isl_set *domain, void *user)
+{
+ struct isl_union_pw_aff_aff_on_domain_data *data = user;
+ isl_pw_aff *pa;
+ isl_aff *aff;
+ int dim;
+
+ aff = isl_aff_copy(data->aff);
+ dim = isl_set_dim(domain, isl_dim_set);
+ aff = isl_aff_add_dims(aff, isl_dim_in, dim);
+ aff = isl_aff_reset_domain_space(aff, isl_set_get_space(domain));
+ pa = isl_pw_aff_alloc(domain, aff);
+ data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
+
+ return data->res ? 0 : -1;
+}
+
+/* Internal data structure for isl_union_pw_multi_aff_get_union_pw_aff.
+ * pos is the output position that needs to be extracted.
+ * res collects the results.
+ */
+struct isl_union_pw_multi_aff_get_union_pw_aff_data {
+ int pos;
+ isl_union_pw_aff *res;
+};
+
+/* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma"
+ * (assuming it has such a dimension) and add it to data->res.
+ */
+static int get_union_pw_aff(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+ struct isl_union_pw_multi_aff_get_union_pw_aff_data *data = user;
+ int n_out;
+ isl_pw_aff *pa;
+
+ if (!pma)
+ return -1;
+
+ n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
+ if (data->pos >= n_out) {
+ isl_pw_multi_aff_free(pma);
+ return 0;
+ }
+
+ pa = isl_pw_multi_aff_get_pw_aff(pma, data->pos);
+ isl_pw_multi_aff_free(pma);
+
+ data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
+
+ return data->res ? 0 : -1;
+}
+
+/* Extract an isl_union_pw_aff corresponding to
+ * output dimension "pos" of "upma".
+ */
+__isl_give isl_union_pw_aff *isl_union_pw_multi_aff_get_union_pw_aff(
+ __isl_keep isl_union_pw_multi_aff *upma, int pos)
+{
+ struct isl_union_pw_multi_aff_get_union_pw_aff_data data;
+ isl_space *space;
+
+ if (!upma)
+ return NULL;
+
+ if (pos < 0)
+ isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid,
+ "cannot extract at negative position", return NULL);
+
+ space = isl_union_pw_multi_aff_get_space(upma);
+ data.res = isl_union_pw_aff_empty(space);
+ data.pos = pos;
+ if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
+ &get_union_pw_aff, &data) < 0)
+ data.res = isl_union_pw_aff_free(data.res);
+
+ return data.res;
+}
+
+/* Return a union piecewise affine expression
+ * that is equal to "aff" on "domain".
+ *
+ * Construct an isl_pw_aff on each of the sets in "domain" and
+ * collect the results.
+ */
+__isl_give isl_union_pw_aff *isl_union_pw_aff_aff_on_domain(
+ __isl_take isl_union_set *domain, __isl_take isl_aff *aff)
+{
+ struct isl_union_pw_aff_aff_on_domain_data data;
+ isl_space *space;
+
+ if (!domain || !aff)
+ goto error;
+ if (!isl_local_space_is_params(aff->ls))
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "expecting parametric expression", goto error);
+
+ space = isl_union_set_get_space(domain);
+ data.res = isl_union_pw_aff_empty(space);
+ data.aff = aff;
+ if (isl_union_set_foreach_set(domain, &pw_aff_aff_on_domain, &data) < 0)
+ data.res = isl_union_pw_aff_free(data.res);
+ isl_union_set_free(domain);
+ isl_aff_free(aff);
+ return data.res;
+error:
+ isl_union_set_free(domain);
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Internal data structure for isl_union_pw_aff_val_on_domain.
+ * "v" is the value that the resulting isl_union_pw_aff needs to attain.
+ * "res" collects the results.
+ */
+struct isl_union_pw_aff_val_on_domain_data {
+ isl_val *v;
+ isl_union_pw_aff *res;
+};
+
+/* Construct a piecewise affine expression that is equal to data->v
+ * on "domain" and add the result to data->res.
+ */
+static int pw_aff_val_on_domain(__isl_take isl_set *domain, void *user)
+{
+ struct isl_union_pw_aff_val_on_domain_data *data = user;
+ isl_pw_aff *pa;
+ isl_val *v;
+
+ v = isl_val_copy(data->v);
+ pa = isl_pw_aff_val_on_domain(domain, v);
+ data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
+
+ return data->res ? 0 : -1;
+}
+
+/* Return a union piecewise affine expression
+ * that is equal to "v" on "domain".
+ *
+ * Construct an isl_pw_aff on each of the sets in "domain" and
+ * collect the results.
+ */
+__isl_give isl_union_pw_aff *isl_union_pw_aff_val_on_domain(
+ __isl_take isl_union_set *domain, __isl_take isl_val *v)
+{
+ struct isl_union_pw_aff_val_on_domain_data data;
+ isl_space *space;
+
+ space = isl_union_set_get_space(domain);
+ data.res = isl_union_pw_aff_empty(space);
+ data.v = v;
+ if (isl_union_set_foreach_set(domain, &pw_aff_val_on_domain, &data) < 0)
+ data.res = isl_union_pw_aff_free(data.res);
+ isl_union_set_free(domain);
+ isl_val_free(v);
+ return data.res;
+}
+
+/* Construct a piecewise multi affine expression
+ * that is equal to "pa" and add it to upma.
+ */
+static int pw_multi_aff_from_pw_aff_entry(__isl_take isl_pw_aff *pa, void *user)
+{
+ isl_union_pw_multi_aff **upma = user;
+ isl_pw_multi_aff *pma;
+
+ pma = isl_pw_multi_aff_from_pw_aff(pa);
+ *upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
+
+ return *upma ? 0 : -1;
+}
+
+/* Construct and return a union piecewise multi affine expression
+ * that is equal to the given union piecewise affine expression.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_pw_aff(
+ __isl_take isl_union_pw_aff *upa)
+{
+ isl_space *space;
+ isl_union_pw_multi_aff *upma;
+
+ if (!upa)
+ return NULL;
+
+ space = isl_union_pw_aff_get_space(upa);
+ upma = isl_union_pw_multi_aff_empty(space);
+
+ if (isl_union_pw_aff_foreach_pw_aff(upa,
+ &pw_multi_aff_from_pw_aff_entry, &upma) < 0)
+ upma = isl_union_pw_multi_aff_free(upma);
+
+ isl_union_pw_aff_free(upa);
+ return upma;
+}
+
+/* Compute the set of elements in the domain of "pa" where it is zero and
+ * add this set to "uset".
+ */
+static int zero_union_set(__isl_take isl_pw_aff *pa, void *user)
+{
+ isl_union_set **uset = (isl_union_set **)user;
+
+ *uset = isl_union_set_add_set(*uset, isl_pw_aff_zero_set(pa));
+
+ return *uset ? 0 : -1;
+}
+
+/* Return a union set containing those elements in the domain
+ * of "upa" where it is zero.
+ */
+__isl_give isl_union_set *isl_union_pw_aff_zero_union_set(
+ __isl_take isl_union_pw_aff *upa)
+{
+ isl_union_set *zero;
+
+ zero = isl_union_set_empty(isl_union_pw_aff_get_space(upa));
+ if (isl_union_pw_aff_foreach_pw_aff(upa, &zero_union_set, &zero) < 0)
+ zero = isl_union_set_free(zero);
+
+ isl_union_pw_aff_free(upa);
+ return zero;
+}
+
+/* Convert "pa" to an isl_map and add it to *umap.
+ */
+static int map_from_pw_aff_entry(__isl_take isl_pw_aff *pa, void *user)
+{
+ isl_union_map **umap = user;
+ isl_map *map;
+
+ map = isl_map_from_pw_aff(pa);
+ *umap = isl_union_map_add_map(*umap, map);
+
+ return *umap ? 0 : -1;
+}
+
+/* Construct a union map mapping the domain of the union
+ * piecewise affine expression to its range, with the single output dimension
+ * equated to the corresponding affine expressions on their cells.
+ */
+__isl_give isl_union_map *isl_union_map_from_union_pw_aff(
+ __isl_take isl_union_pw_aff *upa)
+{
+ isl_space *space;
+ isl_union_map *umap;
+
+ if (!upa)
+ return NULL;
+
+ space = isl_union_pw_aff_get_space(upa);
+ umap = isl_union_map_empty(space);
+
+ if (isl_union_pw_aff_foreach_pw_aff(upa, &map_from_pw_aff_entry,
+ &umap) < 0)
+ umap = isl_union_map_free(umap);
+
+ isl_union_pw_aff_free(upa);
+ return umap;
+}
+
+/* Internal data structure for isl_union_pw_aff_pullback_union_pw_multi_aff.
+ * upma is the function that is plugged in.
+ * pa is the current part of the function in which upma is plugged in.
+ * res collects the results.
+ */
+struct isl_union_pw_aff_pullback_upma_data {
+ isl_union_pw_multi_aff *upma;
+ isl_pw_aff *pa;
+ isl_union_pw_aff *res;
+};
+
+/* Check if "pma" can be plugged into data->pa.
+ * If so, perform the pullback and add the result to data->res.
+ */
+static int pa_pb_pma(void **entry, void *user)
+{
+ struct isl_union_pw_aff_pullback_upma_data *data = user;
+ isl_pw_multi_aff *pma = *entry;
+ isl_pw_aff *pa;
+
+ if (!isl_space_tuple_is_equal(data->pa->dim, isl_dim_in,
+ pma->dim, isl_dim_out))
+ return 0;
+
+ pma = isl_pw_multi_aff_copy(pma);
+ pa = isl_pw_aff_copy(data->pa);
+ pa = isl_pw_aff_pullback_pw_multi_aff(pa, pma);
+
+ data->res = isl_union_pw_aff_add_pw_aff(data->res, pa);
+
+ return data->res ? 0 : -1;
+}
+
+/* Check if any of the elements of data->upma can be plugged into pa,
+ * add if so add the result to data->res.
+ */
+static int upa_pb_upma(void **entry, void *user)
+{
+ struct isl_union_pw_aff_pullback_upma_data *data = user;
+ isl_ctx *ctx;
+ isl_pw_aff *pa = *entry;
+
+ data->pa = pa;
+ ctx = isl_union_pw_multi_aff_get_ctx(data->upma);
+ if (isl_hash_table_foreach(ctx, &data->upma->table,
+ &pa_pb_pma, data) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Compute the pullback of "upa" by the function represented by "upma".
+ * In other words, plug in "upma" in "upa". The result contains
+ * expressions defined over the domain space of "upma".
+ *
+ * Run over all pairs of elements in "upa" and "upma", perform
+ * the pullback when appropriate and collect the results.
+ * If the hash value were based on the domain space rather than
+ * the function space, then we could run through all elements
+ * of "upma" and directly pick out the corresponding element of "upa".
+ */
+__isl_give isl_union_pw_aff *isl_union_pw_aff_pullback_union_pw_multi_aff(
+ __isl_take isl_union_pw_aff *upa,
+ __isl_take isl_union_pw_multi_aff *upma)
+{
+ struct isl_union_pw_aff_pullback_upma_data data = { NULL, NULL };
+ isl_ctx *ctx;
+ isl_space *space;
+
+ space = isl_union_pw_multi_aff_get_space(upma);
+ upa = isl_union_pw_aff_align_params(upa, space);
+ space = isl_union_pw_aff_get_space(upa);
+ upma = isl_union_pw_multi_aff_align_params(upma, space);
+
+ if (!upa || !upma)
+ goto error;
+
+ ctx = isl_union_pw_aff_get_ctx(upa);
+ data.upma = upma;
+ space = isl_union_pw_aff_get_space(upa);
+ data.res = isl_union_pw_aff_alloc(space, upa->table.n);
+ if (isl_hash_table_foreach(ctx, &upa->table, &upa_pb_upma, &data) < 0)
+ data.res = isl_union_pw_aff_free(data.res);
+
+ isl_union_pw_aff_free(upa);
+ isl_union_pw_multi_aff_free(upma);
+ return data.res;
+error:
+ isl_union_pw_aff_free(upa);
+ isl_union_pw_multi_aff_free(upma);
+ return NULL;
+}
+
+#undef BASE
+#define BASE union_pw_aff
+#undef DOMBASE
+#define DOMBASE union_set
+
+#define NO_MOVE_DIMS
+#define NO_DIMS
+#define NO_DOMAIN
+#define NO_PRODUCT
+#define NO_SPLICE
+#define NO_ZERO
+#define NO_IDENTITY
+#define NO_GIST
+
+#include <isl_multi_templ.c>
+#include <isl_multi_apply_set.c>
+#include <isl_multi_apply_union_set.c>
+#include <isl_multi_floor.c>
+#include <isl_multi_gist.c>
+#include <isl_multi_intersect.c>
+
+/* Construct a multiple union piecewise affine expression
+ * in the given space with value zero in each of the output dimensions.
+ *
+ * Since there is no canonical zero value for
+ * a union piecewise affine expression, we can only construct
+ * zero-dimensional "zero" value.
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_zero(
+ __isl_take isl_space *space)
+{
+ if (!space)
+ return NULL;
+
+ if (!isl_space_is_set(space))
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "expecting set space", goto error);
+ if (isl_space_dim(space , isl_dim_out) != 0)
+ isl_die(isl_space_get_ctx(space), isl_error_invalid,
+ "expecting 0D space", goto error);
+
+ return isl_multi_union_pw_aff_alloc(space);
+error:
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Compute the sum of "mupa1" and "mupa2" on the union of their domains,
+ * with the actual sum on the shared domain and
+ * the defined expression on the symmetric difference of the domains.
+ *
+ * We simply iterate over the elements in both arguments and
+ * call isl_union_pw_aff_union_add on each of them.
+ */
+static __isl_give isl_multi_union_pw_aff *
+isl_multi_union_pw_aff_union_add_aligned(
+ __isl_take isl_multi_union_pw_aff *mupa1,
+ __isl_take isl_multi_union_pw_aff *mupa2)
+{
+ return isl_multi_union_pw_aff_bin_op(mupa1, mupa2,
+ &isl_union_pw_aff_union_add);
+}
+
+/* Compute the sum of "mupa1" and "mupa2" on the union of their domains,
+ * with the actual sum on the shared domain and
+ * the defined expression on the symmetric difference of the domains.
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_union_add(
+ __isl_take isl_multi_union_pw_aff *mupa1,
+ __isl_take isl_multi_union_pw_aff *mupa2)
+{
+ return isl_multi_union_pw_aff_align_params_multi_multi_and(mupa1, mupa2,
+ &isl_multi_union_pw_aff_union_add_aligned);
+}
+
+/* Construct and return a multi union piecewise affine expression
+ * that is equal to the given multi affine expression.
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_aff(
+ __isl_take isl_multi_aff *ma)
+{
+ isl_multi_pw_aff *mpa;
+
+ mpa = isl_multi_pw_aff_from_multi_aff(ma);
+ return isl_multi_union_pw_aff_from_multi_pw_aff(mpa);
+}
+
+/* Construct and return a multi union piecewise affine expression
+ * that is equal to the given multi piecewise affine expression.
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_multi_pw_aff(
+ __isl_take isl_multi_pw_aff *mpa)
+{
+ int i, n;
+ isl_space *space;
+ isl_multi_union_pw_aff *mupa;
+
+ if (!mpa)
+ return NULL;
+
+ space = isl_multi_pw_aff_get_space(mpa);
+ space = isl_space_range(space);
+ mupa = isl_multi_union_pw_aff_alloc(space);
+
+ n = isl_multi_pw_aff_dim(mpa, isl_dim_out);
+ for (i = 0; i < n; ++i) {
+ isl_pw_aff *pa;
+ isl_union_pw_aff *upa;
+
+ pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
+ upa = isl_union_pw_aff_from_pw_aff(pa);
+ mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
+ }
+
+ isl_multi_pw_aff_free(mpa);
+
+ return mupa;
+}
+
+/* Extract the range space of "pma" and assign it to *space.
+ * If *space has already been set (through a previous call to this function),
+ * then check that the range space is the same.
+ */
+static int extract_space(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+ isl_space **space = user;
+ isl_space *pma_space;
+ int equal;
+
+ pma_space = isl_space_range(isl_pw_multi_aff_get_space(pma));
+ isl_pw_multi_aff_free(pma);
+
+ if (!pma_space)
+ return -1;
+ if (!*space) {
+ *space = pma_space;
+ return 0;
+ }
+
+ equal = isl_space_is_equal(pma_space, *space);
+ isl_space_free(pma_space);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(isl_space_get_ctx(*space), isl_error_invalid,
+ "range spaces not the same", return -1);
+ return 0;
+}
+
+/* Construct and return a multi union piecewise affine expression
+ * that is equal to the given union piecewise multi affine expression.
+ *
+ * In order to be able to perform the conversion, the input
+ * needs to be non-empty and may only involve a single range space.
+ */
+__isl_give isl_multi_union_pw_aff *
+isl_multi_union_pw_aff_from_union_pw_multi_aff(
+ __isl_take isl_union_pw_multi_aff *upma)
+{
+ isl_space *space = NULL;
+ isl_multi_union_pw_aff *mupa;
+ int i, n;
+
+ if (!upma)
+ return NULL;
+ if (isl_union_pw_multi_aff_n_pw_multi_aff(upma) == 0)
+ isl_die(isl_union_pw_multi_aff_get_ctx(upma), isl_error_invalid,
+ "cannot extract range space from empty input",
+ goto error);
+ if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma, &extract_space,
+ &space) < 0)
+ goto error;
+
+ if (!space)
+ goto error;
+
+ n = isl_space_dim(space, isl_dim_set);
+ mupa = isl_multi_union_pw_aff_alloc(space);
+
+ for (i = 0; i < n; ++i) {
+ isl_union_pw_aff *upa;
+
+ upa = isl_union_pw_multi_aff_get_union_pw_aff(upma, i);
+ mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
+ }
+
+ isl_union_pw_multi_aff_free(upma);
+ return mupa;
+error:
+ isl_space_free(space);
+ isl_union_pw_multi_aff_free(upma);
+ return NULL;
+}
+
+/* Try and create an isl_multi_union_pw_aff that is equivalent
+ * to the given isl_union_map.
+ * The isl_union_map is required to be single-valued in each space.
+ * Moreover, it cannot be empty and all range spaces need to be the same.
+ * Otherwise, an error is produced.
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_from_union_map(
+ __isl_take isl_union_map *umap)
+{
+ isl_union_pw_multi_aff *upma;
+
+ upma = isl_union_pw_multi_aff_from_union_map(umap);
+ return isl_multi_union_pw_aff_from_union_pw_multi_aff(upma);
+}
+
+/* Return a multiple union piecewise affine expression
+ * that is equal to "mv" on "domain", assuming "domain" and "mv"
+ * have been aligned.
+ */
+static __isl_give isl_multi_union_pw_aff *
+isl_multi_union_pw_aff_multi_val_on_domain_aligned(
+ __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
+{
+ int i, n;
+ isl_space *space;
+ isl_multi_union_pw_aff *mupa;
+
+ if (!domain || !mv)
+ goto error;
+
+ n = isl_multi_val_dim(mv, isl_dim_set);
+ space = isl_multi_val_get_space(mv);
+ mupa = isl_multi_union_pw_aff_alloc(space);
+ for (i = 0; i < n; ++i) {
+ isl_val *v;
+ isl_union_pw_aff *upa;
+
+ v = isl_multi_val_get_val(mv, i);
+ upa = isl_union_pw_aff_val_on_domain(isl_union_set_copy(domain),
+ v);
+ mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
+ }
+
+ isl_union_set_free(domain);
+ isl_multi_val_free(mv);
+ return mupa;
+error:
+ isl_union_set_free(domain);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Return a multiple union piecewise affine expression
+ * that is equal to "mv" on "domain".
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_val_on_domain(
+ __isl_take isl_union_set *domain, __isl_take isl_multi_val *mv)
+{
+ if (!domain || !mv)
+ goto error;
+ if (isl_space_match(domain->dim, isl_dim_param,
+ mv->space, isl_dim_param))
+ return isl_multi_union_pw_aff_multi_val_on_domain_aligned(
+ domain, mv);
+ domain = isl_union_set_align_params(domain,
+ isl_multi_val_get_space(mv));
+ mv = isl_multi_val_align_params(mv, isl_union_set_get_space(domain));
+ return isl_multi_union_pw_aff_multi_val_on_domain_aligned(domain, mv);
+error:
+ isl_union_set_free(domain);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Return a multiple union piecewise affine expression
+ * that is equal to "ma" on "domain", assuming "domain" and "ma"
+ * have been aligned.
+ */
+static __isl_give isl_multi_union_pw_aff *
+isl_multi_union_pw_aff_multi_aff_on_domain_aligned(
+ __isl_take isl_union_set *domain, __isl_take isl_multi_aff *ma)
+{
+ int i, n;
+ isl_space *space;
+ isl_multi_union_pw_aff *mupa;
+
+ if (!domain || !ma)
+ goto error;
+
+ n = isl_multi_aff_dim(ma, isl_dim_set);
+ space = isl_multi_aff_get_space(ma);
+ mupa = isl_multi_union_pw_aff_alloc(space);
+ for (i = 0; i < n; ++i) {
+ isl_aff *aff;
+ isl_union_pw_aff *upa;
+
+ aff = isl_multi_aff_get_aff(ma, i);
+ upa = isl_union_pw_aff_aff_on_domain(isl_union_set_copy(domain),
+ aff);
+ mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
+ }
+
+ isl_union_set_free(domain);
+ isl_multi_aff_free(ma);
+ return mupa;
+error:
+ isl_union_set_free(domain);
+ isl_multi_aff_free(ma);
+ return NULL;
+}
+
+/* Return a multiple union piecewise affine expression
+ * that is equal to "ma" on "domain".
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_multi_aff_on_domain(
+ __isl_take isl_union_set *domain, __isl_take isl_multi_aff *ma)
+{
+ if (!domain || !ma)
+ goto error;
+ if (isl_space_match(domain->dim, isl_dim_param,
+ ma->space, isl_dim_param))
+ return isl_multi_union_pw_aff_multi_aff_on_domain_aligned(
+ domain, ma);
+ domain = isl_union_set_align_params(domain,
+ isl_multi_aff_get_space(ma));
+ ma = isl_multi_aff_align_params(ma, isl_union_set_get_space(domain));
+ return isl_multi_union_pw_aff_multi_aff_on_domain_aligned(domain, ma);
+error:
+ isl_union_set_free(domain);
+ isl_multi_aff_free(ma);
+ return NULL;
+}
+
+/* Return a union set containing those elements in the domains
+ * of the elements of "mupa" where they are all zero.
+ */
+__isl_give isl_union_set *isl_multi_union_pw_aff_zero_union_set(
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ int i, n;
+ isl_union_pw_aff *upa;
+ isl_union_set *zero;
+
+ if (!mupa)
+ return NULL;
+
+ n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+ if (n == 0)
+ isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
+ "cannot determine zero set "
+ "of zero-dimensional function", goto error);
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
+ zero = isl_union_pw_aff_zero_union_set(upa);
+
+ for (i = 1; i < n; ++i) {
+ isl_union_set *zero_i;
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
+ zero_i = isl_union_pw_aff_zero_union_set(upa);
+
+ zero = isl_union_set_intersect(zero, zero_i);
+ }
+
+ isl_multi_union_pw_aff_free(mupa);
+ return zero;
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ return NULL;
+}
+
+/* Construct a union map mapping the shared domain
+ * of the union piecewise affine expressions to the range of "mupa"
+ * with each dimension in the range equated to the
+ * corresponding union piecewise affine expression.
+ *
+ * The input cannot be zero-dimensional as there is
+ * no way to extract a domain from a zero-dimensional isl_multi_union_pw_aff.
+ */
+__isl_give isl_union_map *isl_union_map_from_multi_union_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ int i, n;
+ isl_space *space;
+ isl_union_map *umap;
+ isl_union_pw_aff *upa;
+
+ if (!mupa)
+ return NULL;
+
+ n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+ if (n == 0)
+ isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
+ "cannot determine domain of zero-dimensional "
+ "isl_multi_union_pw_aff", goto error);
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
+ umap = isl_union_map_from_union_pw_aff(upa);
+
+ for (i = 1; i < n; ++i) {
+ isl_union_map *umap_i;
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
+ umap_i = isl_union_map_from_union_pw_aff(upa);
+ umap = isl_union_map_flat_range_product(umap, umap_i);
+ }
+
+ space = isl_multi_union_pw_aff_get_space(mupa);
+ umap = isl_union_map_reset_range_space(umap, space);
+
+ isl_multi_union_pw_aff_free(mupa);
+ return umap;
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ return NULL;
+}
+
+/* Internal data structure for isl_union_pw_multi_aff_reset_range_space.
+ * "range" is the space from which to set the range space.
+ * "res" collects the results.
+ */
+struct isl_union_pw_multi_aff_reset_range_space_data {
+ isl_space *range;
+ isl_union_pw_multi_aff *res;
+};
+
+/* Replace the range space of "pma" by the range space of data->range and
+ * add the result to data->res.
+ */
+static int reset_range_space(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+ struct isl_union_pw_multi_aff_reset_range_space_data *data = user;
+ isl_space *space;
+
+ space = isl_pw_multi_aff_get_space(pma);
+ space = isl_space_domain(space);
+ space = isl_space_extend_domain_with_range(space,
+ isl_space_copy(data->range));
+ pma = isl_pw_multi_aff_reset_space(pma, space);
+ data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
+
+ return data->res ? 0 : -1;
+}
+
+/* Replace the range space of all the piecewise affine expressions in "upma" by
+ * the range space of "space".
+ *
+ * This assumes that all these expressions have the same output dimension.
+ *
+ * Since the spaces of the expressions change, so do their hash values.
+ * We therefore need to create a new isl_union_pw_multi_aff.
+ * Note that the hash value is currently computed based on the entire
+ * space even though there can only be a single expression with a given
+ * domain space.
+ */
+static __isl_give isl_union_pw_multi_aff *
+isl_union_pw_multi_aff_reset_range_space(
+ __isl_take isl_union_pw_multi_aff *upma, __isl_take isl_space *space)
+{
+ struct isl_union_pw_multi_aff_reset_range_space_data data = { space };
+ isl_space *space_upma;
+
+ space_upma = isl_union_pw_multi_aff_get_space(upma);
+ data.res = isl_union_pw_multi_aff_empty(space_upma);
+ if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
+ &reset_range_space, &data) < 0)
+ data.res = isl_union_pw_multi_aff_free(data.res);
+
+ isl_space_free(space);
+ isl_union_pw_multi_aff_free(upma);
+ return data.res;
+}
+
+/* Construct and return a union piecewise multi affine expression
+ * that is equal to the given multi union piecewise affine expression.
+ *
+ * In order to be able to perform the conversion, the input
+ * needs to have a least one output dimension.
+ */
+__isl_give isl_union_pw_multi_aff *
+isl_union_pw_multi_aff_from_multi_union_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ int i, n;
+ isl_space *space;
+ isl_union_pw_multi_aff *upma;
+ isl_union_pw_aff *upa;
+
+ if (!mupa)
+ return NULL;
+
+ space = isl_multi_union_pw_aff_get_space(mupa);
+
+ n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+ if (n == 0)
+ isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
+ "cannot determine domain of zero-dimensional "
+ "isl_multi_union_pw_aff", goto error);
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
+ upma = isl_union_pw_multi_aff_from_union_pw_aff(upa);
+
+ for (i = 1; i < n; ++i) {
+ isl_union_pw_multi_aff *upma_i;
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
+ upma_i = isl_union_pw_multi_aff_from_union_pw_aff(upa);
+ upma = isl_union_pw_multi_aff_flat_range_product(upma, upma_i);
+ }
+
+ upma = isl_union_pw_multi_aff_reset_range_space(upma, space);
+
+ isl_multi_union_pw_aff_free(mupa);
+ return upma;
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ return NULL;
+}
+
+/* Intersect the range of "mupa" with "range".
+ * That is, keep only those domain elements that have a function value
+ * in "range".
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_intersect_range(
+ __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_set *range)
+{
+ isl_union_pw_multi_aff *upma;
+ isl_union_set *domain;
+ isl_space *space;
+ int n;
+ int match;
+
+ if (!mupa || !range)
+ goto error;
+
+ space = isl_set_get_space(range);
+ match = isl_space_tuple_is_equal(mupa->space, isl_dim_set,
+ space, isl_dim_set);
+ isl_space_free(space);
+ if (match < 0)
+ goto error;
+ if (!match)
+ isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
+ "space don't match", goto error);
+ n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+ if (n == 0)
+ isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
+ "cannot intersect range of zero-dimensional "
+ "isl_multi_union_pw_aff", goto error);
+
+ upma = isl_union_pw_multi_aff_from_multi_union_pw_aff(
+ isl_multi_union_pw_aff_copy(mupa));
+ domain = isl_union_set_from_set(range);
+ domain = isl_union_set_preimage_union_pw_multi_aff(domain, upma);
+ mupa = isl_multi_union_pw_aff_intersect_domain(mupa, domain);
+
+ return mupa;
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ isl_set_free(range);
+ return NULL;
+}
+
+/* Return the shared domain of the elements of "mupa".
+ */
+__isl_give isl_union_set *isl_multi_union_pw_aff_domain(
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ int i, n;
+ isl_union_pw_aff *upa;
+ isl_union_set *dom;
+
+ if (!mupa)
+ return NULL;
+
+ n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+ if (n == 0)
+ isl_die(isl_multi_union_pw_aff_get_ctx(mupa), isl_error_invalid,
+ "cannot determine domain", goto error);
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, 0);
+ dom = isl_union_pw_aff_domain(upa);
+ for (i = 1; i < n; ++i) {
+ isl_union_set *dom_i;
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
+ dom_i = isl_union_pw_aff_domain(upa);
+ dom = isl_union_set_intersect(dom, dom_i);
+ }
+
+ isl_multi_union_pw_aff_free(mupa);
+ return dom;
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ return NULL;
+}
+
+/* Apply "aff" to "mupa". The space of "mupa" is equal to the domain of "aff".
+ * In particular, the spaces have been aligned.
+ * The result is defined over the shared domain of the elements of "mupa"
+ *
+ * We first extract the parametric constant part of "aff" and
+ * define that over the shared domain.
+ * Then we iterate over all input dimensions of "aff" and add the corresponding
+ * multiples of the elements of "mupa".
+ * Finally, we consider the integer divisions, calling the function
+ * recursively to obtain an isl_union_pw_aff corresponding to the
+ * integer division argument.
+ */
+static __isl_give isl_union_pw_aff *multi_union_pw_aff_apply_aff(
+ __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff)
+{
+ int i, n_in, n_div;
+ isl_union_pw_aff *upa;
+ isl_union_set *uset;
+ isl_val *v;
+ isl_aff *cst;
+
+ n_in = isl_aff_dim(aff, isl_dim_in);
+ n_div = isl_aff_dim(aff, isl_dim_div);
+
+ uset = isl_multi_union_pw_aff_domain(isl_multi_union_pw_aff_copy(mupa));
+ cst = isl_aff_copy(aff);
+ cst = isl_aff_drop_dims(cst, isl_dim_div, 0, n_div);
+ cst = isl_aff_drop_dims(cst, isl_dim_in, 0, n_in);
+ cst = isl_aff_project_domain_on_params(cst);
+ upa = isl_union_pw_aff_aff_on_domain(uset, cst);
+
+ for (i = 0; i < n_in; ++i) {
+ isl_union_pw_aff *upa_i;
+
+ if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1))
+ continue;
+ v = isl_aff_get_coefficient_val(aff, isl_dim_in, i);
+ upa_i = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
+ upa_i = isl_union_pw_aff_scale_val(upa_i, v);
+ upa = isl_union_pw_aff_add(upa, upa_i);
+ }
+
+ for (i = 0; i < n_div; ++i) {
+ isl_aff *div;
+ isl_union_pw_aff *upa_i;
+
+ if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1))
+ continue;
+ div = isl_aff_get_div(aff, i);
+ upa_i = multi_union_pw_aff_apply_aff(
+ isl_multi_union_pw_aff_copy(mupa), div);
+ upa_i = isl_union_pw_aff_floor(upa_i);
+ v = isl_aff_get_coefficient_val(aff, isl_dim_div, i);
+ upa_i = isl_union_pw_aff_scale_val(upa_i, v);
+ upa = isl_union_pw_aff_add(upa, upa_i);
+ }
+
+ isl_multi_union_pw_aff_free(mupa);
+ isl_aff_free(aff);
+
+ return upa;
+}
+
+/* Apply "aff" to "mupa". The space of "mupa" needs to be compatible
+ * with the domain of "aff".
+ * Furthermore, the dimension of this space needs to be greater than zero.
+ * The result is defined over the shared domain of the elements of "mupa"
+ *
+ * We perform these checks and then hand over control to
+ * multi_union_pw_aff_apply_aff.
+ */
+__isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_aff(
+ __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_aff *aff)
+{
+ isl_space *space1, *space2;
+ int equal;
+
+ mupa = isl_multi_union_pw_aff_align_params(mupa,
+ isl_aff_get_space(aff));
+ aff = isl_aff_align_params(aff, isl_multi_union_pw_aff_get_space(mupa));
+ if (!mupa || !aff)
+ goto error;
+
+ space1 = isl_multi_union_pw_aff_get_space(mupa);
+ space2 = isl_aff_get_domain_space(aff);
+ equal = isl_space_is_equal(space1, space2);
+ isl_space_free(space1);
+ isl_space_free(space2);
+ if (equal < 0)
+ goto error;
+ if (!equal)
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "spaces don't match", goto error);
+ if (isl_aff_dim(aff, isl_dim_in) == 0)
+ isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+ "cannot determine domains", goto error);
+
+ return multi_union_pw_aff_apply_aff(mupa, aff);
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ isl_aff_free(aff);
+ return NULL;
+}
+
+/* Apply "ma" to "mupa". The space of "mupa" needs to be compatible
+ * with the domain of "ma".
+ * Furthermore, the dimension of this space needs to be greater than zero,
+ * unless the dimension of the target space of "ma" is also zero.
+ * The result is defined over the shared domain of the elements of "mupa"
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_multi_aff(
+ __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_multi_aff *ma)
+{
+ isl_space *space1, *space2;
+ isl_multi_union_pw_aff *res;
+ int equal;
+ int i, n_out;
+
+ mupa = isl_multi_union_pw_aff_align_params(mupa,
+ isl_multi_aff_get_space(ma));
+ ma = isl_multi_aff_align_params(ma,
+ isl_multi_union_pw_aff_get_space(mupa));
+ if (!mupa || !ma)
+ goto error;
+
+ space1 = isl_multi_union_pw_aff_get_space(mupa);
+ space2 = isl_multi_aff_get_domain_space(ma);
+ equal = isl_space_is_equal(space1, space2);
+ isl_space_free(space1);
+ isl_space_free(space2);
+ if (equal < 0)
+ goto error;
+ if (!equal)
+ isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid,
+ "spaces don't match", goto error);
+ n_out = isl_multi_aff_dim(ma, isl_dim_out);
+ if (isl_multi_aff_dim(ma, isl_dim_in) == 0 && n_out != 0)
+ isl_die(isl_multi_aff_get_ctx(ma), isl_error_invalid,
+ "cannot determine domains", goto error);
+
+ space1 = isl_space_range(isl_multi_aff_get_space(ma));
+ res = isl_multi_union_pw_aff_alloc(space1);
+
+ for (i = 0; i < n_out; ++i) {
+ isl_aff *aff;
+ isl_union_pw_aff *upa;
+
+ aff = isl_multi_aff_get_aff(ma, i);
+ upa = multi_union_pw_aff_apply_aff(
+ isl_multi_union_pw_aff_copy(mupa), aff);
+ res = isl_multi_union_pw_aff_set_union_pw_aff(res, i, upa);
+ }
+
+ isl_multi_aff_free(ma);
+ isl_multi_union_pw_aff_free(mupa);
+ return res;
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ isl_multi_aff_free(ma);
+ return NULL;
+}
+
+/* Apply "pa" to "mupa". The space of "mupa" needs to be compatible
+ * with the domain of "pa".
+ * Furthermore, the dimension of this space needs to be greater than zero.
+ * The result is defined over the shared domain of the elements of "mupa"
+ */
+__isl_give isl_union_pw_aff *isl_multi_union_pw_aff_apply_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa, __isl_take isl_pw_aff *pa)
+{
+ int i;
+ int equal;
+ isl_space *space, *space2;
+ isl_union_pw_aff *upa;
+
+ mupa = isl_multi_union_pw_aff_align_params(mupa,
+ isl_pw_aff_get_space(pa));
+ pa = isl_pw_aff_align_params(pa,
+ isl_multi_union_pw_aff_get_space(mupa));
+ if (!mupa || !pa)
+ goto error;
+
+ space = isl_multi_union_pw_aff_get_space(mupa);
+ space2 = isl_pw_aff_get_domain_space(pa);
+ equal = isl_space_is_equal(space, space2);
+ isl_space_free(space);
+ isl_space_free(space2);
+ if (equal < 0)
+ goto error;
+ if (!equal)
+ isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+ "spaces don't match", goto error);
+ if (isl_pw_aff_dim(pa, isl_dim_in) == 0)
+ isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+ "cannot determine domains", goto error);
+
+ space = isl_space_params(isl_multi_union_pw_aff_get_space(mupa));
+ upa = isl_union_pw_aff_empty(space);
+
+ for (i = 0; i < pa->n; ++i) {
+ isl_aff *aff;
+ isl_set *domain;
+ isl_multi_union_pw_aff *mupa_i;
+ isl_union_pw_aff *upa_i;
+
+ mupa_i = isl_multi_union_pw_aff_copy(mupa);
+ domain = isl_set_copy(pa->p[i].set);
+ mupa_i = isl_multi_union_pw_aff_intersect_range(mupa_i, domain);
+ aff = isl_aff_copy(pa->p[i].aff);
+ upa_i = multi_union_pw_aff_apply_aff(mupa_i, aff);
+ upa = isl_union_pw_aff_union_add(upa, upa_i);
+ }
+
+ isl_multi_union_pw_aff_free(mupa);
+ isl_pw_aff_free(pa);
+ return upa;
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ isl_pw_aff_free(pa);
+ return NULL;
+}
+
+/* Apply "pma" to "mupa". The space of "mupa" needs to be compatible
+ * with the domain of "pma".
+ * Furthermore, the dimension of this space needs to be greater than zero,
+ * unless the dimension of the target space of "pma" is also zero.
+ * The result is defined over the shared domain of the elements of "mupa"
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_apply_pw_multi_aff(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_pw_multi_aff *pma)
+{
+ isl_space *space1, *space2;
+ isl_multi_union_pw_aff *res;
+ int equal;
+ int i, n_out;
+
+ mupa = isl_multi_union_pw_aff_align_params(mupa,
+ isl_pw_multi_aff_get_space(pma));
+ pma = isl_pw_multi_aff_align_params(pma,
+ isl_multi_union_pw_aff_get_space(mupa));
+ if (!mupa || !pma)
+ goto error;
+
+ space1 = isl_multi_union_pw_aff_get_space(mupa);
+ space2 = isl_pw_multi_aff_get_domain_space(pma);
+ equal = isl_space_is_equal(space1, space2);
+ isl_space_free(space1);
+ isl_space_free(space2);
+ if (equal < 0)
+ goto error;
+ if (!equal)
+ isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+ "spaces don't match", goto error);
+ n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
+ if (isl_pw_multi_aff_dim(pma, isl_dim_in) == 0 && n_out != 0)
+ isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+ "cannot determine domains", goto error);
+
+ space1 = isl_space_range(isl_pw_multi_aff_get_space(pma));
+ res = isl_multi_union_pw_aff_alloc(space1);
+
+ for (i = 0; i < n_out; ++i) {
+ isl_pw_aff *pa;
+ isl_union_pw_aff *upa;
+
+ pa = isl_pw_multi_aff_get_pw_aff(pma, i);
+ upa = isl_multi_union_pw_aff_apply_pw_aff(
+ isl_multi_union_pw_aff_copy(mupa), pa);
+ res = isl_multi_union_pw_aff_set_union_pw_aff(res, i, upa);
+ }
+
+ isl_pw_multi_aff_free(pma);
+ isl_multi_union_pw_aff_free(mupa);
+ return res;
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ isl_pw_multi_aff_free(pma);
+ return NULL;
+}
+
+/* Compute the pullback of "mupa" by the function represented by "upma".
+ * In other words, plug in "upma" in "mupa". The result contains
+ * expressions defined over the domain space of "upma".
+ *
+ * Run over all elements of "mupa" and plug in "upma" in each of them.
+ */
+__isl_give isl_multi_union_pw_aff *
+isl_multi_union_pw_aff_pullback_union_pw_multi_aff(
+ __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_take isl_union_pw_multi_aff *upma)
+{
+ int i, n;
+
+ mupa = isl_multi_union_pw_aff_align_params(mupa,
+ isl_union_pw_multi_aff_get_space(upma));
+ upma = isl_union_pw_multi_aff_align_params(upma,
+ isl_multi_union_pw_aff_get_space(mupa));
+ if (!mupa || !upma)
+ goto error;
+
+ n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+ for (i = 0; i < n; ++i) {
+ isl_union_pw_aff *upa;
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
+ upa = isl_union_pw_aff_pullback_union_pw_multi_aff(upa,
+ isl_union_pw_multi_aff_copy(upma));
+ mupa = isl_multi_union_pw_aff_set_union_pw_aff(mupa, i, upa);
+ }
+
+ isl_union_pw_multi_aff_free(upma);
+ return mupa;
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ isl_union_pw_multi_aff_free(upma);
+ return NULL;
+}
+
+/* Extract the sequence of elements in "mupa" with domain space "space"
+ * (ignoring parameters).
+ *
+ * For the elements of "mupa" that are not defined on the specified space,
+ * the corresponding element in the result is empty.
+ */
+__isl_give isl_multi_pw_aff *isl_multi_union_pw_aff_extract_multi_pw_aff(
+ __isl_keep isl_multi_union_pw_aff *mupa, __isl_take isl_space *space)
+{
+ int i, n;
+ isl_space *space_mpa = NULL;
+ isl_multi_pw_aff *mpa;
+
+ if (!mupa || !space)
+ goto error;
+
+ space_mpa = isl_multi_union_pw_aff_get_space(mupa);
+ if (!isl_space_match(space_mpa, isl_dim_param, space, isl_dim_param)) {
+ space = isl_space_drop_dims(space, isl_dim_param,
+ 0, isl_space_dim(space, isl_dim_param));
+ space = isl_space_align_params(space,
+ isl_space_copy(space_mpa));
+ if (!space)
+ goto error;
+ }
+ space_mpa = isl_space_map_from_domain_and_range(isl_space_copy(space),
+ space_mpa);
+ mpa = isl_multi_pw_aff_alloc(space_mpa);
+
+ space = isl_space_from_domain(space);
+ space = isl_space_add_dims(space, isl_dim_out, 1);
+ n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+ for (i = 0; i < n; ++i) {
+ isl_union_pw_aff *upa;
+ isl_pw_aff *pa;
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, i);
+ pa = isl_union_pw_aff_extract_pw_aff(upa,
+ isl_space_copy(space));
+ mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
+ isl_union_pw_aff_free(upa);
+ }
+
+ isl_space_free(space);
+ return mpa;
+error:
+ isl_space_free(space_mpa);
+ isl_space_free(space);
+ return NULL;
+}
Modified: polly/trunk/lib/External/isl/isl_aff_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_aff_private.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_aff_private.h (original)
+++ polly/trunk/lib/External/isl/isl_aff_private.h Mon Feb 16 13:33:40 2015
@@ -141,6 +141,8 @@ void isl_seq_preimage(isl_int *dst, isl_
int n_div_ma, int n_div_bmap,
isl_int f, isl_int c1, isl_int c2, isl_int g, int has_denom);
+__isl_give isl_aff *isl_aff_substitute_equalities(__isl_take isl_aff *aff,
+ __isl_take isl_basic_set *eq);
__isl_give isl_pw_multi_aff *isl_pw_multi_aff_substitute(
__isl_take isl_pw_multi_aff *pma, enum isl_dim_type type, unsigned pos,
__isl_keep isl_pw_aff *subs);
@@ -155,4 +157,19 @@ int isl_pw_aff_check_match_domain_space(
#include <isl_multi_templ.h>
+#undef EL
+#define EL isl_union_pw_aff
+
+#include <isl_list_templ.h>
+
+#undef BASE
+#define BASE union_pw_aff
+
+#include <isl_multi_templ.h>
+
+#undef EL
+#define EL isl_union_pw_multi_aff
+
+#include <isl_list_templ.h>
+
#endif
Modified: polly/trunk/lib/External/isl/isl_affine_hull.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_affine_hull.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_affine_hull.c (original)
+++ polly/trunk/lib/External/isl/isl_affine_hull.c Mon Feb 16 13:33:40 2015
@@ -1147,6 +1147,19 @@ __isl_give isl_set *isl_set_detect_equal
return (isl_set *)isl_map_detect_equalities((isl_map *)set);
}
+/* Return the superset of "bmap" described by the equalities
+ * satisfied by "bmap" that are already known.
+ */
+__isl_give isl_basic_map *isl_basic_map_plain_affine_hull(
+ __isl_take isl_basic_map *bmap)
+{
+ bmap = isl_basic_map_cow(bmap);
+ if (bmap)
+ isl_basic_map_free_inequality(bmap, bmap->n_ineq);
+ bmap = isl_basic_map_finalize(bmap);
+ return bmap;
+}
+
/* After computing the rational affine hull (by detecting the implicit
* equalities), we compute the additional equalities satisfied by
* the integer points (if any) and add the original equalities back in.
@@ -1154,10 +1167,7 @@ __isl_give isl_set *isl_set_detect_equal
struct isl_basic_map *isl_basic_map_affine_hull(struct isl_basic_map *bmap)
{
bmap = isl_basic_map_detect_equalities(bmap);
- bmap = isl_basic_map_cow(bmap);
- if (bmap)
- isl_basic_map_free_inequality(bmap, bmap->n_ineq);
- bmap = isl_basic_map_finalize(bmap);
+ bmap = isl_basic_map_plain_affine_hull(bmap);
return bmap;
}
Modified: polly/trunk/lib/External/isl/isl_ast_build.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_ast_build.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_build.c (original)
+++ polly/trunk/lib/External/isl/isl_ast_build.c Mon Feb 16 13:33:40 2015
@@ -1807,7 +1807,7 @@ __isl_give isl_aff *isl_ast_build_get_of
* value that, moreover, can be described by a single affine expression
* in terms of the outer dimensions and parameters?
*
- * If not, then the correponding affine expression in build->values
+ * If not, then the corresponding affine expression in build->values
* is set to be equal to the same input dimension.
* Otherwise, it is set to the requested expression in terms of
* outer dimensions and parameters.
Modified: polly/trunk/lib/External/isl/isl_ast_build_expr.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_ast_build_expr.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_build_expr.c (original)
+++ polly/trunk/lib/External/isl/isl_ast_build_expr.c Mon Feb 16 13:33:40 2015
@@ -1,10 +1,13 @@
/*
* Copyright 2012-2014 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege,
* Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
*/
#include <isl/ilp.h>
@@ -29,11 +32,120 @@ static __isl_give isl_aff *oppose_div_ar
return aff;
}
+/* Internal data structure used inside isl_ast_expr_add_term.
+ * The domain of "build" is used to simplify the expressions.
+ * "build" needs to be set by the caller of isl_ast_expr_add_term.
+ * "cst" is the constant term of the expression in which the added term
+ * appears. It may be modified by isl_ast_expr_add_term.
+ *
+ * "v" is the coefficient of the term that is being constructed and
+ * is set internally by isl_ast_expr_add_term.
+ */
+struct isl_ast_add_term_data {
+ isl_ast_build *build;
+ isl_val *cst;
+ isl_val *v;
+};
+
+/* Given the numerator "aff" of the argument of an integer division
+ * with denominator "d", check if it can be made non-negative over
+ * data->build->domain by stealing part of the constant term of
+ * the expression in which the integer division appears.
+ *
+ * In particular, the outer expression is of the form
+ *
+ * v * floor(aff/d) + cst
+ *
+ * We already know that "aff" itself may attain negative values.
+ * Here we check if aff + d*floor(cst/v) is non-negative, such
+ * that we could rewrite the expression to
+ *
+ * v * floor((aff + d*floor(cst/v))/d) + cst - v*floor(cst/v)
+ *
+ * Note that aff + d*floor(cst/v) can only possibly be non-negative
+ * if data->cst and data->v have the same sign.
+ * Similarly, if floor(cst/v) is zero, then there is no point in
+ * checking again.
+ */
+static int is_non_neg_after_stealing(__isl_keep isl_aff *aff,
+ __isl_keep isl_val *d, struct isl_ast_add_term_data *data)
+{
+ isl_aff *shifted;
+ isl_val *shift;
+ int is_zero;
+ int non_neg;
+
+ if (isl_val_sgn(data->cst) != isl_val_sgn(data->v))
+ return 0;
+
+ shift = isl_val_div(isl_val_copy(data->cst), isl_val_copy(data->v));
+ shift = isl_val_floor(shift);
+ is_zero = isl_val_is_zero(shift);
+ if (is_zero < 0 || is_zero) {
+ isl_val_free(shift);
+ return is_zero < 0 ? -1 : 0;
+ }
+ shift = isl_val_mul(shift, isl_val_copy(d));
+ shifted = isl_aff_copy(aff);
+ shifted = isl_aff_add_constant_val(shifted, shift);
+ non_neg = isl_ast_build_aff_is_nonneg(data->build, shifted);
+ isl_aff_free(shifted);
+
+ return non_neg;
+}
+
+/* Given the numerator "aff' of the argument of an integer division
+ * with denominator "d", steal part of the constant term of
+ * the expression in which the integer division appears to make it
+ * non-negative over data->build->domain.
+ *
+ * In particular, the outer expression is of the form
+ *
+ * v * floor(aff/d) + cst
+ *
+ * We know that "aff" itself may attain negative values,
+ * but that aff + d*floor(cst/v) is non-negative.
+ * Find the minimal positive value that we need to add to "aff"
+ * to make it positive and adjust data->cst accordingly.
+ * That is, compute the minimal value "m" of "aff" over
+ * data->build->domain and take
+ *
+ * s = ceil(m/d)
+ *
+ * such that
+ *
+ * aff + d * s >= 0
+ *
+ * and rewrite the expression to
+ *
+ * v * floor((aff + s*d)/d) + (cst - v*s)
+ */
+static __isl_give isl_aff *steal_from_cst(__isl_take isl_aff *aff,
+ __isl_keep isl_val *d, struct isl_ast_add_term_data *data)
+{
+ isl_set *domain;
+ isl_val *shift, *t;
+
+ domain = isl_ast_build_get_domain(data->build);
+ shift = isl_set_min_val(domain, aff);
+ isl_set_free(domain);
+
+ shift = isl_val_neg(shift);
+ shift = isl_val_div(shift, isl_val_copy(d));
+ shift = isl_val_ceil(shift);
+
+ t = isl_val_copy(shift);
+ t = isl_val_mul(t, isl_val_copy(data->v));
+ data->cst = isl_val_sub(data->cst, t);
+
+ shift = isl_val_mul(shift, isl_val_copy(d));
+ return isl_aff_add_constant_val(aff, shift);
+}
+
/* Create an isl_ast_expr evaluating the div at position "pos" in "ls".
- * The result is simplified in terms of build->domain.
+ * The result is simplified in terms of data->build->domain.
+ * This function may change (the sign of) data->v.
*
- * *change_sign is set by this function if the sign of
- * the expression has changed.
* "ls" is known to be non-NULL.
*
* Let the div be of the form floor(e/d).
@@ -52,11 +164,20 @@ static __isl_give isl_aff *oppose_div_ar
*
* floor(e/d) = -ceil(-e/d) = -floor((-e + d - 1)/d)
*
- * and still use pdiv_q.
+ * and still use pdiv_q, while changing the sign of data->v.
+ *
+ * Otherwise, we check if
+ *
+ * e + d*floor(cst/v)
+ *
+ * is non-negative and if so, replace floor(e/d) by
+ *
+ * floor((e + s*d)/d) - s
+ *
+ * with s the minimal shift that makes the argument non-negative.
*/
-static __isl_give isl_ast_expr *var_div(int *change_sign,
- __isl_keep isl_local_space *ls,
- int pos, __isl_keep isl_ast_build *build)
+static __isl_give isl_ast_expr *var_div(struct isl_ast_add_term_data *data,
+ __isl_keep isl_local_space *ls, int pos)
{
isl_ctx *ctx = isl_local_space_get_ctx(ls);
isl_aff *aff;
@@ -71,18 +192,23 @@ static __isl_give isl_ast_expr *var_div(
type = isl_ast_op_fdiv_q;
if (isl_options_get_ast_build_prefer_pdiv(ctx)) {
- int non_neg = isl_ast_build_aff_is_nonneg(build, aff);
+ int non_neg = isl_ast_build_aff_is_nonneg(data->build, aff);
if (non_neg >= 0 && !non_neg) {
isl_aff *opp = oppose_div_arg(isl_aff_copy(aff),
isl_val_copy(d));
- non_neg = isl_ast_build_aff_is_nonneg(build, opp);
+ non_neg = isl_ast_build_aff_is_nonneg(data->build, opp);
if (non_neg >= 0 && non_neg) {
- *change_sign = 1;
+ data->v = isl_val_neg(data->v);
isl_aff_free(aff);
aff = opp;
} else
isl_aff_free(opp);
}
+ if (non_neg >= 0 && !non_neg) {
+ non_neg = is_non_neg_after_stealing(aff, d, data);
+ if (non_neg >= 0 && non_neg)
+ aff = steal_from_cst(aff, d, data);
+ }
if (non_neg < 0)
aff = isl_aff_free(aff);
else if (non_neg)
@@ -90,33 +216,30 @@ static __isl_give isl_ast_expr *var_div(
}
isl_val_free(d);
- num = isl_ast_expr_from_aff(aff, build);
+ num = isl_ast_expr_from_aff(aff, data->build);
return isl_ast_expr_alloc_binary(type, num, den);
}
/* Create an isl_ast_expr evaluating the specified dimension of "ls".
- * The result is simplified in terms of build->domain.
- *
- * *change_sign is set by this function if the sign of
- * the expression has changed.
+ * The result is simplified in terms of data->build->domain.
+ * This function may change (the sign of) data->v.
*
* The isl_ast_expr is constructed based on the type of the dimension.
* - divs are constructed by var_div
- * - set variables are constructed from the iterator isl_ids in "build"
+ * - set variables are constructed from the iterator isl_ids in data->build
* - parameters are constructed from the isl_ids in "ls"
*/
-static __isl_give isl_ast_expr *var(int *change_sign,
- __isl_keep isl_local_space *ls,
- enum isl_dim_type type, int pos, __isl_keep isl_ast_build *build)
+static __isl_give isl_ast_expr *var(struct isl_ast_add_term_data *data,
+ __isl_keep isl_local_space *ls, enum isl_dim_type type, int pos)
{
isl_ctx *ctx = isl_local_space_get_ctx(ls);
isl_id *id;
if (type == isl_dim_div)
- return var_div(change_sign, ls, pos, build);
+ return var_div(data, ls, pos);
if (type == isl_dim_set) {
- id = isl_ast_build_get_iterator_id(build, pos);
+ id = isl_ast_build_get_iterator_id(data->build, pos);
return isl_ast_expr_from_id(id);
}
@@ -270,6 +393,9 @@ error:
/* Add an expression for "*v" times the specified dimension of "ls"
* to expr.
+ * If the dimension is an integer division, then this function
+ * may modify data->cst in order to make the numerator non-negative.
+ * The result is simplified in terms of data->build->domain.
*
* Let e be the expression for the specified dimension,
* multiplied by the absolute value of "*v".
@@ -291,18 +417,16 @@ error:
static __isl_give isl_ast_expr *isl_ast_expr_add_term(
__isl_take isl_ast_expr *expr,
__isl_keep isl_local_space *ls, enum isl_dim_type type, int pos,
- __isl_take isl_val *v, __isl_keep isl_ast_build *build)
+ __isl_take isl_val *v, struct isl_ast_add_term_data *data)
{
isl_ast_expr *term;
- int change_sign;
if (!expr)
return NULL;
- change_sign = 0;
- term = var(&change_sign, ls, type, pos, build);
- if (change_sign)
- v = isl_val_neg(v);
+ data->v = v;
+ term = var(data, ls, type, pos);
+ v = data->v;
if (isl_val_is_neg(v) && !ast_expr_is_zero(expr)) {
v = isl_val_neg(v);
@@ -683,12 +807,12 @@ static int try_extract_mod(struct isl_ex
{
isl_basic_set *hull;
isl_val *v1, *v2;
- int r;
+ int r, n;
if (!data->build)
goto error;
- int n = isl_aff_dim(data->div, isl_dim_div);
+ n = isl_aff_dim(data->div, isl_dim_div);
if (isl_aff_involves_dims(data->div, isl_dim_div, 0, n))
return extract_nonneg_mod(data);
@@ -948,6 +1072,7 @@ __isl_give isl_ast_expr *isl_ast_expr_fr
enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_div };
enum isl_dim_type l[] = { isl_dim_param, isl_dim_set, isl_dim_div };
isl_local_space *ls;
+ struct isl_ast_add_term_data data;
if (!aff)
return NULL;
@@ -962,6 +1087,8 @@ __isl_give isl_ast_expr *isl_ast_expr_fr
ls = isl_aff_get_domain_local_space(aff);
+ data.build = build;
+ data.cst = isl_aff_get_constant_val(aff);
for (i = 0; i < 3; ++i) {
n = isl_aff_dim(aff, t[i]);
for (j = 0; j < n; ++j) {
@@ -973,12 +1100,11 @@ __isl_give isl_ast_expr *isl_ast_expr_fr
continue;
}
expr = isl_ast_expr_add_term(expr,
- ls, l[i], j, v, build);
+ ls, l[i], j, v, &data);
}
}
- v = isl_aff_get_constant_val(aff);
- expr = isl_ast_expr_add_int(expr, v);
+ expr = isl_ast_expr_add_int(expr, data.cst);
isl_local_space_free(ls);
isl_aff_free(aff);
@@ -987,10 +1113,10 @@ __isl_give isl_ast_expr *isl_ast_expr_fr
/* Add terms to "expr" for each variable in "aff" with a coefficient
* with sign equal to "sign".
- * The result is simplified in terms of build->domain.
+ * The result is simplified in terms of data->build->domain.
*/
static __isl_give isl_ast_expr *add_signed_terms(__isl_take isl_ast_expr *expr,
- __isl_keep isl_aff *aff, int sign, __isl_keep isl_ast_build *build)
+ __isl_keep isl_aff *aff, int sign, struct isl_ast_add_term_data *data)
{
int i, j;
isl_val *v;
@@ -1010,7 +1136,7 @@ static __isl_give isl_ast_expr *add_sign
}
v = isl_val_abs(v);
expr = isl_ast_expr_add_term(expr,
- ls, l[i], j, v, build);
+ ls, l[i], j, v, data);
}
}
@@ -1204,9 +1330,9 @@ static __isl_give isl_ast_expr *isl_ast_
isl_ast_expr *expr_neg;
isl_ast_expr *expr;
isl_aff *aff;
- isl_val *v;
int eq;
enum isl_ast_op_type type;
+ struct isl_ast_add_term_data data;
if (!constraint)
return NULL;
@@ -1232,15 +1358,18 @@ static __isl_give isl_ast_expr *isl_ast_
aff = extract_modulos(aff, &expr_pos, &expr_neg, build);
- expr_pos = add_signed_terms(expr_pos, aff, 1, build);
- expr_neg = add_signed_terms(expr_neg, aff, -1, build);
+ data.build = build;
+ data.cst = isl_aff_get_constant_val(aff);
+ expr_pos = add_signed_terms(expr_pos, aff, 1, &data);
+ data.cst = isl_val_neg(data.cst);
+ expr_neg = add_signed_terms(expr_neg, aff, -1, &data);
+ data.cst = isl_val_neg(data.cst);
- v = isl_aff_get_constant_val(aff);
- if (constant_is_considered_positive(v, expr_pos, expr_neg)) {
- expr_pos = isl_ast_expr_add_int(expr_pos, v);
+ if (constant_is_considered_positive(data.cst, expr_pos, expr_neg)) {
+ expr_pos = isl_ast_expr_add_int(expr_pos, data.cst);
} else {
- v = isl_val_neg(v);
- expr_neg = isl_ast_expr_add_int(expr_neg, v);
+ data.cst = isl_val_neg(data.cst);
+ expr_neg = isl_ast_expr_add_int(expr_neg, data.cst);
}
if (isl_ast_expr_get_type(expr_pos) == isl_ast_expr_int &&
@@ -1406,7 +1535,7 @@ struct isl_from_pw_aff_data {
* If this is the last pair, then data->next is set to evaluate aff
* and the domain is ignored.
* Otherwise, data->next is set to a select operation that selects
- * an isl_ast_expr correponding to "aff" on "set" and to an expression
+ * an isl_ast_expr corresponding to "aff" on "set" and to an expression
* that will be filled in by later calls otherwise.
*
* In both cases, the constraints of "set" are added to the generated
Modified: polly/trunk/lib/External/isl/isl_ast_codegen.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_ast_codegen.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_codegen.c (original)
+++ polly/trunk/lib/External/isl/isl_ast_codegen.c Mon Feb 16 13:33:40 2015
@@ -665,36 +665,43 @@ error:
* If we have generated a degenerate loop, then add the guard
* implied by "bounds" on the outer dimensions, i.e., the guard
* that ensures that the single value actually exists.
+ * Since there may also be guards implied by a combination
+ * of these constraints, we first combine them before
+ * deriving the implied constraints.
*/
static __isl_give isl_set *add_implied_guards(__isl_take isl_set *guard,
int degenerate, __isl_keep isl_basic_set *bounds,
__isl_keep isl_ast_build *build)
{
int depth, has_stride;
- isl_set *dom;
+ isl_space *space;
+ isl_set *dom, *set;
depth = isl_ast_build_get_depth(build);
has_stride = isl_ast_build_has_stride(build, depth);
if (!has_stride && !degenerate)
return guard;
+ space = isl_basic_set_get_space(bounds);
+ dom = isl_set_universe(space);
+
if (degenerate) {
bounds = isl_basic_set_copy(bounds);
bounds = isl_basic_set_drop_constraints_not_involving_dims(
bounds, isl_dim_set, depth, 1);
- dom = isl_set_from_basic_set(bounds);
- dom = isl_set_eliminate(dom, isl_dim_set, depth, 1);
- dom = isl_ast_build_compute_gist(build, dom);
- guard = isl_set_intersect(guard, dom);
+ set = isl_set_from_basic_set(bounds);
+ dom = isl_set_intersect(dom, set);
}
if (has_stride) {
- dom = isl_ast_build_get_stride_constraint(build);
- dom = isl_set_eliminate(dom, isl_dim_set, depth, 1);
- dom = isl_ast_build_compute_gist(build, dom);
- guard = isl_set_intersect(guard, dom);
+ set = isl_ast_build_get_stride_constraint(build);
+ dom = isl_set_intersect(dom, set);
}
+ dom = isl_set_eliminate(dom, isl_dim_set, depth, 1);
+ dom = isl_ast_build_compute_gist(build, dom);
+ guard = isl_set_intersect(guard, dom);
+
return guard;
}
@@ -2228,22 +2235,143 @@ static __isl_give isl_set *separate_sche
/* Temporary data used during the search for a lower bound for unrolling.
*
+ * "build" is the build in which the unrolling will be performed
* "domain" is the original set for which to find a lower bound
* "depth" is the dimension for which to find a lower boudn
+ * "expansion" is the expansion that needs to be applied to "domain"
+ * in the unrolling that will be performed
*
* "lower" is the best lower bound found so far. It is NULL if we have not
* found any yet.
* "n" is the corresponding size. If lower is NULL, then the value of n
* is undefined.
+ * "n_div" is the maximal number of integer divisions in the first
+ * unrolled iteration (after expansion). It is set to -1 if it hasn't
+ * been computed yet.
*/
struct isl_find_unroll_data {
+ isl_ast_build *build;
isl_set *domain;
int depth;
+ isl_basic_map *expansion;
isl_aff *lower;
int *n;
+ int n_div;
};
+/* Return the constraint
+ *
+ * i_"depth" = aff + offset
+ */
+static __isl_give isl_constraint *at_offset(int depth, __isl_keep isl_aff *aff,
+ int offset)
+{
+ aff = isl_aff_copy(aff);
+ aff = isl_aff_add_coefficient_si(aff, isl_dim_in, depth, -1);
+ aff = isl_aff_add_constant_si(aff, offset);
+ return isl_equality_from_aff(aff);
+}
+
+/* Update *user to the number of integer divsions in the first element
+ * of "ma", if it is larger than the current value.
+ */
+static int update_n_div(__isl_take isl_set *set, __isl_take isl_multi_aff *ma,
+ void *user)
+{
+ isl_aff *aff;
+ int *n = user;
+ int n_div;
+
+ aff = isl_multi_aff_get_aff(ma, 0);
+ n_div = isl_aff_dim(aff, isl_dim_div);
+ isl_aff_free(aff);
+ isl_multi_aff_free(ma);
+ isl_set_free(set);
+
+ if (n_div > *n)
+ *n = n_div;
+
+ return aff ? 0 : -1;
+}
+
+/* Get the number of integer divisions in the expression for the iterator
+ * value at the first slice in the unrolling based on lower bound "lower",
+ * taking into account the expansion that needs to be performed on this slice.
+ */
+static int get_expanded_n_div(struct isl_find_unroll_data *data,
+ __isl_keep isl_aff *lower)
+{
+ isl_constraint *c;
+ isl_set *set;
+ isl_map *it_map, *expansion;
+ isl_pw_multi_aff *pma;
+ int n;
+
+ c = at_offset(data->depth, lower, 0);
+ set = isl_set_copy(data->domain);
+ set = isl_set_add_constraint(set, c);
+ expansion = isl_map_from_basic_map(isl_basic_map_copy(data->expansion));
+ set = isl_set_apply(set, expansion);
+ it_map = isl_ast_build_map_to_iterator(data->build, set);
+ pma = isl_pw_multi_aff_from_map(it_map);
+ n = 0;
+ if (isl_pw_multi_aff_foreach_piece(pma, &update_n_div, &n) < 0)
+ n = -1;
+ isl_pw_multi_aff_free(pma);
+
+ return n;
+}
+
+/* Is the lower bound "lower" with corresponding iteration count "n"
+ * better than the one stored in "data"?
+ * If there is no upper bound on the iteration count ("n" is infinity) or
+ * if the count is too large, then we cannot use this lower bound.
+ * Otherwise, if there was no previous lower bound or
+ * if the iteration count of the new lower bound is smaller than
+ * the iteration count of the previous lower bound, then we consider
+ * the new lower bound to be better.
+ * If the iteration count is the same, then compare the number
+ * of integer divisions that would be needed to express
+ * the iterator value at the first slice in the unrolling
+ * according to the lower bound. If we end up computing this
+ * number, then store the lowest value in data->n_div.
+ */
+static int is_better_lower_bound(struct isl_find_unroll_data *data,
+ __isl_keep isl_aff *lower, __isl_keep isl_val *n)
+{
+ int cmp;
+ int n_div;
+
+ if (!n)
+ return -1;
+ if (isl_val_is_infty(n))
+ return 0;
+ if (isl_val_cmp_si(n, INT_MAX) > 0)
+ return 0;
+ if (!data->lower)
+ return 1;
+ cmp = isl_val_cmp_si(n, *data->n);
+ if (cmp < 0)
+ return 1;
+ if (cmp > 0)
+ return 0;
+ if (data->n_div < 0)
+ data->n_div = get_expanded_n_div(data, data->lower);
+ if (data->n_div < 0)
+ return -1;
+ if (data->n_div == 0)
+ return 0;
+ n_div = get_expanded_n_div(data, lower);
+ if (n_div < 0)
+ return -1;
+ if (n_div >= data->n_div)
+ return 0;
+ data->n_div = n_div;
+
+ return 1;
+}
+
/* Check if we can use "c" as a lower bound and if it is better than
* any previously found lower bound.
*
@@ -2267,14 +2395,15 @@ struct isl_find_unroll_data {
*
* meaning that we can use ceil(f(j)/a)) as a lower bound for unrolling.
* We just need to check if we have found any lower bound before and
- * if the new lower bound is better (smaller n) than the previously found
- * lower bounds.
+ * if the new lower bound is better (smaller n or fewer integer divisions)
+ * than the previously found lower bounds.
*/
static int update_unrolling_lower_bound(struct isl_find_unroll_data *data,
__isl_keep isl_constraint *c)
{
isl_aff *aff, *lower;
isl_val *max;
+ int better;
if (!isl_constraint_is_lower_bound(c, isl_dim_set, data->depth))
return 0;
@@ -2288,27 +2417,19 @@ static int update_unrolling_lower_bound(
max = isl_set_max_val(data->domain, aff);
isl_aff_free(aff);
- if (!max)
- goto error;
- if (isl_val_is_infty(max)) {
+ better = is_better_lower_bound(data, lower, max);
+ if (better < 0 || !better) {
isl_val_free(max);
isl_aff_free(lower);
- return 0;
+ return better < 0 ? -1 : 0;
}
- if (isl_val_cmp_si(max, INT_MAX) <= 0 &&
- (!data->lower || isl_val_cmp_si(max, *data->n) < 0)) {
- isl_aff_free(data->lower);
- data->lower = lower;
- *data->n = isl_val_get_num_si(max);
- } else
- isl_aff_free(lower);
+ isl_aff_free(data->lower);
+ data->lower = lower;
+ *data->n = isl_val_get_num_si(max);
isl_val_free(max);
return 1;
-error:
- isl_aff_free(lower);
- return -1;
}
/* Check if we can use "c" as a lower bound and if it is better than
@@ -2334,6 +2455,9 @@ static int constraint_find_unroll(__isl_
* where d is "depth" and l(i) depends only on earlier dimensions.
* Furthermore, try and find a lower bound such that n is as small as possible.
* In particular, "n" needs to be finite.
+ * "build" is the build in which the unrolling will be performed.
+ * "expansion" is the expansion that needs to be applied to "domain"
+ * in the unrolling that will be performed.
*
* Inner dimensions have been eliminated from "domain" by the caller.
*
@@ -2347,10 +2471,12 @@ static int constraint_find_unroll(__isl_
* If we cannot find a suitable lower bound, then we consider that
* to be an error.
*/
-static __isl_give isl_aff *find_unroll_lower_bound(__isl_keep isl_set *domain,
- int depth, int *n)
+static __isl_give isl_aff *find_unroll_lower_bound(
+ __isl_keep isl_ast_build *build, __isl_keep isl_set *domain,
+ int depth, __isl_keep isl_basic_map *expansion, int *n)
{
- struct isl_find_unroll_data data = { domain, depth, NULL, n };
+ struct isl_find_unroll_data data =
+ { build, domain, depth, expansion, NULL, n, -1 };
isl_basic_set *hull;
hull = isl_set_simple_hull(isl_set_copy(domain));
@@ -2371,19 +2497,6 @@ error:
return isl_aff_free(data.lower);
}
-/* Return the constraint
- *
- * i_"depth" = aff + offset
- */
-static __isl_give isl_constraint *at_offset(int depth, __isl_keep isl_aff *aff,
- int offset)
-{
- aff = isl_aff_copy(aff);
- aff = isl_aff_add_coefficient_si(aff, isl_dim_in, depth, -1);
- aff = isl_aff_add_constant_si(aff, offset);
- return isl_equality_from_aff(aff);
-}
-
/* Data structure for storing the results and the intermediate objects
* of compute_domains.
*
@@ -2482,12 +2595,13 @@ static __isl_give isl_set *do_unroll(str
isl_ast_build_free(build);
- lower = find_unroll_lower_bound(domain, depth, &n);
+ bmap = isl_basic_map_from_multi_aff(expansion);
+
+ lower = find_unroll_lower_bound(domains->build, domain, depth, bmap,
+ &n);
if (!lower)
class_domain = isl_set_free(class_domain);
- bmap = isl_basic_map_from_multi_aff(expansion);
-
unroll_domain = isl_set_empty(isl_set_get_space(domain));
for (i = 0; class_domain && i < n; ++i) {
@@ -3912,6 +4026,7 @@ __isl_give isl_ast_node *isl_ast_build_a
build = isl_ast_build_copy(build);
build = isl_ast_build_set_single_valued(build, 0);
schedule = isl_union_map_coalesce(schedule);
+ schedule = isl_union_map_remove_redundancies(schedule);
executed = isl_union_map_reverse(schedule);
list = generate_code(executed, isl_ast_build_copy(build), 0);
node = isl_ast_node_from_graft_list(list, build);
Modified: polly/trunk/lib/External/isl/isl_coalesce.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_coalesce.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_coalesce.c (original)
+++ polly/trunk/lib/External/isl/isl_coalesce.c Mon Feb 16 13:33:40 2015
@@ -2,6 +2,7 @@
* Copyright 2008-2009 Katholieke Universiteit Leuven
* Copyright 2010 INRIA Saclay
* Copyright 2012-2013 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
*
* Use of this software is governed by the MIT license
*
@@ -10,6 +11,8 @@
* and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
* ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
* and Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
*/
#include "isl_map_private.h"
@@ -19,6 +22,7 @@
#include <isl_mat_private.h>
#include <isl_local_space_private.h>
#include <isl_vec_private.h>
+#include <isl_aff_private.h>
#define STATUS_ERROR -1
#define STATUS_REDUNDANT 1
@@ -143,83 +147,250 @@ static int all(int *con, unsigned len, i
return 1;
}
-static void drop(struct isl_map *map, int i, struct isl_tab **tabs)
+/* Internal information associated to a basic map in a map
+ * that is to be coalesced by isl_map_coalesce.
+ *
+ * "bmap" is the basic map itself (or NULL if "removed" is set)
+ * "tab" is the corresponding tableau (or NULL if "removed" is set)
+ * "hull_hash" identifies the affine space in which "bmap" lives.
+ * "removed" is set if this basic map has been removed from the map
+ * "simplify" is set if this basic map may have some unknown integer
+ * divisions that were not present in the input basic maps. The basic
+ * map should then be simplified such that we may be able to find
+ * a definition among the constraints.
+ *
+ * "eq" and "ineq" are only set if we are currently trying to coalesce
+ * this basic map with another basic map, in which case they represent
+ * the position of the inequalities of this basic map with respect to
+ * the other basic map. The number of elements in the "eq" array
+ * is twice the number of equalities in the "bmap", corresponding
+ * to the two inequalities that make up each equality.
+ */
+struct isl_coalesce_info {
+ isl_basic_map *bmap;
+ struct isl_tab *tab;
+ uint32_t hull_hash;
+ int removed;
+ int simplify;
+ int *eq;
+ int *ineq;
+};
+
+/* Compute the hash of the (apparent) affine hull of info->bmap (with
+ * the existentially quantified variables removed) and store it
+ * in info->hash.
+ */
+static int coalesce_info_set_hull_hash(struct isl_coalesce_info *info)
{
- isl_basic_map_free(map->p[i]);
- isl_tab_free(tabs[i]);
+ isl_basic_map *hull;
+ unsigned n_div;
- if (i != map->n - 1) {
- map->p[i] = map->p[map->n - 1];
- tabs[i] = tabs[map->n - 1];
- }
- tabs[map->n - 1] = NULL;
- map->n--;
+ hull = isl_basic_map_copy(info->bmap);
+ hull = isl_basic_map_plain_affine_hull(hull);
+ n_div = isl_basic_map_dim(hull, isl_dim_div);
+ hull = isl_basic_map_drop_constraints_involving_dims(hull,
+ isl_dim_div, 0, n_div);
+ info->hull_hash = isl_basic_map_get_hash(hull);
+ isl_basic_map_free(hull);
+
+ return hull ? 0 : -1;
}
-/* Replace the pair of basic maps i and j by the basic map bounded
- * by the valid constraints in both basic maps and the constraint
- * in extra (if not NULL).
+/* Free all the allocated memory in an array
+ * of "n" isl_coalesce_info elements.
*/
-static int fuse(struct isl_map *map, int i, int j,
- struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j,
- __isl_keep isl_mat *extra)
+static void clear_coalesce_info(int n, struct isl_coalesce_info *info)
{
- int k, l;
- struct isl_basic_map *fused = NULL;
- struct isl_tab *fused_tab = NULL;
- unsigned total = isl_basic_map_total_dim(map->p[i]);
- unsigned extra_rows = extra ? extra->n_row : 0;
+ int i;
- fused = isl_basic_map_alloc_space(isl_space_copy(map->p[i]->dim),
- map->p[i]->n_div,
- map->p[i]->n_eq + map->p[j]->n_eq,
- map->p[i]->n_ineq + map->p[j]->n_ineq + extra_rows);
- if (!fused)
- goto error;
+ if (!info)
+ return;
- for (k = 0; k < map->p[i]->n_eq; ++k) {
- if (eq_i && (eq_i[2 * k] != STATUS_VALID ||
- eq_i[2 * k + 1] != STATUS_VALID))
- continue;
- l = isl_basic_map_alloc_equality(fused);
- if (l < 0)
- goto error;
- isl_seq_cpy(fused->eq[l], map->p[i]->eq[k], 1 + total);
+ for (i = 0; i < n; ++i) {
+ isl_basic_map_free(info[i].bmap);
+ isl_tab_free(info[i].tab);
}
- for (k = 0; k < map->p[j]->n_eq; ++k) {
- if (eq_j && (eq_j[2 * k] != STATUS_VALID ||
- eq_j[2 * k + 1] != STATUS_VALID))
- continue;
- l = isl_basic_map_alloc_equality(fused);
- if (l < 0)
- goto error;
- isl_seq_cpy(fused->eq[l], map->p[j]->eq[k], 1 + total);
+ free(info);
+}
+
+/* Drop the basic map represented by "info".
+ * That is, clear the memory associated to the entry and
+ * mark it as having been removed.
+ */
+static void drop(struct isl_coalesce_info *info)
+{
+ info->bmap = isl_basic_map_free(info->bmap);
+ isl_tab_free(info->tab);
+ info->tab = NULL;
+ info->removed = 1;
+}
+
+/* Exchange the information in "info1" with that in "info2".
+ */
+static void exchange(struct isl_coalesce_info *info1,
+ struct isl_coalesce_info *info2)
+{
+ struct isl_coalesce_info info;
+
+ info = *info1;
+ *info1 = *info2;
+ *info2 = info;
+}
+
+/* This type represents the kind of change that has been performed
+ * while trying to coalesce two basic maps.
+ *
+ * isl_change_none: nothing was changed
+ * isl_change_drop_first: the first basic map was removed
+ * isl_change_drop_second: the second basic map was removed
+ * isl_change_fuse: the two basic maps were replaced by a new basic map.
+ */
+enum isl_change {
+ isl_change_error = -1,
+ isl_change_none = 0,
+ isl_change_drop_first,
+ isl_change_drop_second,
+ isl_change_fuse,
+};
+
+/* Update "change" based on an interchange of the first and the second
+ * basic map. That is, interchange isl_change_drop_first and
+ * isl_change_drop_second.
+ */
+static enum isl_change invert_change(enum isl_change change)
+{
+ switch (change) {
+ case isl_change_error:
+ return isl_change_error;
+ case isl_change_none:
+ return isl_change_none;
+ case isl_change_drop_first:
+ return isl_change_drop_second;
+ case isl_change_drop_second:
+ return isl_change_drop_first;
+ case isl_change_fuse:
+ return isl_change_fuse;
}
+}
- for (k = 0; k < map->p[i]->n_ineq; ++k) {
- if (ineq_i[k] != STATUS_VALID)
- continue;
- l = isl_basic_map_alloc_inequality(fused);
- if (l < 0)
- goto error;
- isl_seq_cpy(fused->ineq[l], map->p[i]->ineq[k], 1 + total);
+/* Add the valid constraints of the basic map represented by "info"
+ * to "bmap". "len" is the size of the constraints.
+ * If only one of the pair of inequalities that make up an equality
+ * is valid, then add that inequality.
+ */
+static __isl_give isl_basic_map *add_valid_constraints(
+ __isl_take isl_basic_map *bmap, struct isl_coalesce_info *info,
+ unsigned len)
+{
+ int k, l;
+
+ if (!bmap)
+ return NULL;
+
+ for (k = 0; k < info->bmap->n_eq; ++k) {
+ if (info->eq[2 * k] == STATUS_VALID &&
+ info->eq[2 * k + 1] == STATUS_VALID) {
+ l = isl_basic_map_alloc_equality(bmap);
+ if (l < 0)
+ return isl_basic_map_free(bmap);
+ isl_seq_cpy(bmap->eq[l], info->bmap->eq[k], len);
+ } else if (info->eq[2 * k] == STATUS_VALID) {
+ l = isl_basic_map_alloc_inequality(bmap);
+ if (l < 0)
+ return isl_basic_map_free(bmap);
+ isl_seq_neg(bmap->ineq[l], info->bmap->eq[k], len);
+ } else if (info->eq[2 * k + 1] == STATUS_VALID) {
+ l = isl_basic_map_alloc_inequality(bmap);
+ if (l < 0)
+ return isl_basic_map_free(bmap);
+ isl_seq_cpy(bmap->ineq[l], info->bmap->eq[k], len);
+ }
}
- for (k = 0; k < map->p[j]->n_ineq; ++k) {
- if (ineq_j[k] != STATUS_VALID)
+ for (k = 0; k < info->bmap->n_ineq; ++k) {
+ if (info->ineq[k] != STATUS_VALID)
continue;
- l = isl_basic_map_alloc_inequality(fused);
+ l = isl_basic_map_alloc_inequality(bmap);
if (l < 0)
- goto error;
- isl_seq_cpy(fused->ineq[l], map->p[j]->ineq[k], 1 + total);
+ return isl_basic_map_free(bmap);
+ isl_seq_cpy(bmap->ineq[l], info->bmap->ineq[k], len);
}
- for (k = 0; k < map->p[i]->n_div; ++k) {
+ return bmap;
+}
+
+/* Is "bmap" defined by a number of (non-redundant) constraints that
+ * is greater than the number of constraints of basic maps i and j combined?
+ * Equalities are counted as two inequalities.
+ */
+static int number_of_constraints_increases(int i, int j,
+ struct isl_coalesce_info *info,
+ __isl_keep isl_basic_map *bmap, struct isl_tab *tab)
+{
+ int k, n_old, n_new;
+
+ n_old = 2 * info[i].bmap->n_eq + info[i].bmap->n_ineq;
+ n_old += 2 * info[j].bmap->n_eq + info[j].bmap->n_ineq;
+
+ n_new = 2 * bmap->n_eq;
+ for (k = 0; k < bmap->n_ineq; ++k)
+ if (!isl_tab_is_redundant(tab, bmap->n_eq + k))
+ ++n_new;
+
+ return n_new > n_old;
+}
+
+/* Replace the pair of basic maps i and j by the basic map bounded
+ * by the valid constraints in both basic maps and the constraints
+ * in extra (if not NULL).
+ * Place the fused basic map in the position that is the smallest of i and j.
+ *
+ * If "detect_equalities" is set, then look for equalities encoded
+ * as pairs of inequalities.
+ * If "check_number" is set, then the original basic maps are only
+ * replaced if the total number of constraints does not increase.
+ * While the number of integer divisions in the two basic maps
+ * is assumed to be the same, the actual definitions may be different.
+ * We only copy the definition from one of the basic map if it is
+ * the same as that of the other basic map. Otherwise, we mark
+ * the integer division as unknown and schedule for the basic map
+ * to be simplified in an attempt to recover the integer division definition.
+ */
+static enum isl_change fuse(int i, int j, struct isl_coalesce_info *info,
+ __isl_keep isl_mat *extra, int detect_equalities, int check_number)
+{
+ int k, l;
+ struct isl_basic_map *fused = NULL;
+ struct isl_tab *fused_tab = NULL;
+ unsigned total = isl_basic_map_total_dim(info[i].bmap);
+ unsigned extra_rows = extra ? extra->n_row : 0;
+ unsigned n_eq, n_ineq;
+
+ if (j < i)
+ return fuse(j, i, info, extra, detect_equalities, check_number);
+
+ n_eq = info[i].bmap->n_eq + info[j].bmap->n_eq;
+ n_ineq = info[i].bmap->n_ineq + info[j].bmap->n_ineq;
+ fused = isl_basic_map_alloc_space(isl_space_copy(info[i].bmap->dim),
+ info[i].bmap->n_div, n_eq, n_eq + n_ineq + extra_rows);
+ fused = add_valid_constraints(fused, &info[i], 1 + total);
+ fused = add_valid_constraints(fused, &info[j], 1 + total);
+ if (!fused)
+ goto error;
+
+ for (k = 0; k < info[i].bmap->n_div; ++k) {
int l = isl_basic_map_alloc_div(fused);
if (l < 0)
goto error;
- isl_seq_cpy(fused->div[l], map->p[i]->div[k], 1 + 1 + total);
+ if (isl_seq_eq(info[i].bmap->div[k], info[j].bmap->div[k],
+ 1 + 1 + total)) {
+ isl_seq_cpy(fused->div[l], info[i].bmap->div[k],
+ 1 + 1 + total);
+ } else {
+ isl_int_set_si(fused->div[l][0], 0);
+ info[i].simplify = 1;
+ }
}
for (k = 0; k < extra_rows; ++k) {
@@ -229,27 +400,37 @@ static int fuse(struct isl_map *map, int
isl_seq_cpy(fused->ineq[l], extra->row[k], 1 + total);
}
+ if (detect_equalities)
+ fused = isl_basic_map_detect_inequality_pairs(fused, NULL);
fused = isl_basic_map_gauss(fused, NULL);
ISL_F_SET(fused, ISL_BASIC_MAP_FINAL);
- if (ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_RATIONAL) &&
- ISL_F_ISSET(map->p[j], ISL_BASIC_MAP_RATIONAL))
+ if (ISL_F_ISSET(info[i].bmap, ISL_BASIC_MAP_RATIONAL) &&
+ ISL_F_ISSET(info[j].bmap, ISL_BASIC_MAP_RATIONAL))
ISL_F_SET(fused, ISL_BASIC_MAP_RATIONAL);
fused_tab = isl_tab_from_basic_map(fused, 0);
if (isl_tab_detect_redundant(fused_tab) < 0)
goto error;
- isl_basic_map_free(map->p[i]);
- map->p[i] = fused;
- isl_tab_free(tabs[i]);
- tabs[i] = fused_tab;
- drop(map, j, tabs);
+ if (check_number &&
+ number_of_constraints_increases(i, j, info, fused, fused_tab)) {
+ isl_tab_free(fused_tab);
+ isl_basic_map_free(fused);
+ return isl_change_none;
+ }
- return 1;
+ info[i].simplify |= info[j].simplify;
+ isl_basic_map_free(info[i].bmap);
+ info[i].bmap = fused;
+ isl_tab_free(info[i].tab);
+ info[i].tab = fused_tab;
+ drop(&info[j]);
+
+ return isl_change_fuse;
error:
isl_tab_free(fused_tab);
isl_basic_map_free(fused);
- return -1;
+ return isl_change_error;
}
/* Given a pair of basic maps i and j such that all constraints are either
@@ -257,79 +438,99 @@ error:
* constraints of i lie entirely within basic map j.
* If so, replace the pair by the basic map consisting of the valid
* constraints in both basic maps.
+ * Checking whether the facet lies entirely within basic map j
+ * is performed by checking whether the constraints of basic map j
+ * are valid for the facet. These tests are performed on a rational
+ * tableau to avoid the theoretical possibility that a constraint
+ * that was considered to be a cut constraint for the entire basic map i
+ * happens to be considered to be a valid constraint for the facet,
+ * even though it cuts off the same rational points.
*
* To see that we are not introducing any extra points, call the
* two basic maps A and B and the resulting map U and let x
* be an element of U \setminus ( A \cup B ).
- * Then there is a pair of cut constraints c_1 and c_2 in A and B such that x
- * violates them. Let X be the intersection of U with the opposites
- * of these constraints. Then x \in X.
- * The facet corresponding to c_1 contains the corresponding facet of A.
- * This facet is entirely contained in B, so c_2 is valid on the facet.
- * However, since it is also (part of) a facet of X, -c_2 is also valid
- * on the facet. This means c_2 is saturated on the facet, so c_1 and
- * c_2 must be opposites of each other, but then x could not violate
- * both of them.
+ * A line connecting x with an element of A \cup B meets a facet F
+ * of either A or B. Assume it is a facet of B and let c_1 be
+ * the corresponding facet constraint. We have c_1(x) < 0 and
+ * so c_1 is a cut constraint. This implies that there is some
+ * (possibly rational) point x' satisfying the constraints of A
+ * and the opposite of c_1 as otherwise c_1 would have been marked
+ * valid for A. The line connecting x and x' meets a facet of A
+ * in a (possibly rational) point that also violates c_1, but this
+ * is impossible since all cut constraints of B are valid for all
+ * cut facets of A.
+ * In case F is a facet of A rather than B, then we can apply the
+ * above reasoning to find a facet of B separating x from A \cup B first.
*/
-static int check_facets(struct isl_map *map, int i, int j,
- struct isl_tab **tabs, int *ineq_i, int *ineq_j)
+static enum isl_change check_facets(int i, int j,
+ struct isl_coalesce_info *info)
{
int k, l;
- struct isl_tab_undo *snap;
- unsigned n_eq = map->p[i]->n_eq;
+ struct isl_tab_undo *snap, *snap2;
+ unsigned n_eq = info[i].bmap->n_eq;
- snap = isl_tab_snap(tabs[i]);
+ snap = isl_tab_snap(info[i].tab);
+ if (isl_tab_mark_rational(info[i].tab) < 0)
+ return isl_change_error;
+ snap2 = isl_tab_snap(info[i].tab);
- for (k = 0; k < map->p[i]->n_ineq; ++k) {
- if (ineq_i[k] != STATUS_CUT)
+ for (k = 0; k < info[i].bmap->n_ineq; ++k) {
+ if (info[i].ineq[k] != STATUS_CUT)
continue;
- if (isl_tab_select_facet(tabs[i], n_eq + k) < 0)
- return -1;
- for (l = 0; l < map->p[j]->n_ineq; ++l) {
+ if (isl_tab_select_facet(info[i].tab, n_eq + k) < 0)
+ return isl_change_error;
+ for (l = 0; l < info[j].bmap->n_ineq; ++l) {
int stat;
- if (ineq_j[l] != STATUS_CUT)
+ if (info[j].ineq[l] != STATUS_CUT)
continue;
- stat = status_in(map->p[j]->ineq[l], tabs[i]);
+ stat = status_in(info[j].bmap->ineq[l], info[i].tab);
if (stat != STATUS_VALID)
break;
}
- if (isl_tab_rollback(tabs[i], snap) < 0)
- return -1;
- if (l < map->p[j]->n_ineq)
+ if (isl_tab_rollback(info[i].tab, snap2) < 0)
+ return isl_change_error;
+ if (l < info[j].bmap->n_ineq)
break;
}
- if (k < map->p[i]->n_ineq)
- /* BAD CUT PAIR */
- return 0;
- return fuse(map, i, j, tabs, NULL, ineq_i, NULL, ineq_j, NULL);
+ if (k < info[i].bmap->n_ineq) {
+ if (isl_tab_rollback(info[i].tab, snap) < 0)
+ return isl_change_error;
+ return isl_change_none;
+ }
+ return fuse(i, j, info, NULL, 0, 0);
}
-/* Check if basic map "i" contains the basic map represented
+/* Check if info->bmap contains the basic map represented
* by the tableau "tab".
+ * For each equality, we check both the constraint itself
+ * (as an inequality) and its negation. Make sure the
+ * equality is returned to its original state before returning.
*/
-static int contains(struct isl_map *map, int i, int *ineq_i,
- struct isl_tab *tab)
+static int contains(struct isl_coalesce_info *info, struct isl_tab *tab)
{
- int k, l;
+ int k;
unsigned dim;
+ isl_basic_map *bmap = info->bmap;
- dim = isl_basic_map_total_dim(map->p[i]);
- for (k = 0; k < map->p[i]->n_eq; ++k) {
- for (l = 0; l < 2; ++l) {
- int stat;
- isl_seq_neg(map->p[i]->eq[k], map->p[i]->eq[k], 1+dim);
- stat = status_in(map->p[i]->eq[k], tab);
- if (stat != STATUS_VALID)
- return 0;
- }
+ dim = isl_basic_map_total_dim(bmap);
+ for (k = 0; k < bmap->n_eq; ++k) {
+ int stat;
+ isl_seq_neg(bmap->eq[k], bmap->eq[k], 1 + dim);
+ stat = status_in(bmap->eq[k], tab);
+ isl_seq_neg(bmap->eq[k], bmap->eq[k], 1 + dim);
+ if (stat != STATUS_VALID)
+ return 0;
+ stat = status_in(bmap->eq[k], tab);
+ if (stat != STATUS_VALID)
+ return 0;
}
- for (k = 0; k < map->p[i]->n_ineq; ++k) {
+ for (k = 0; k < bmap->n_ineq; ++k) {
int stat;
- if (ineq_i[k] == STATUS_REDUNDANT)
+ if (info->ineq[k] == STATUS_REDUNDANT)
continue;
- stat = status_in(map->p[i]->ineq[k], tab);
+ stat = status_in(bmap->ineq[k], tab);
if (stat != STATUS_VALID)
return 0;
}
@@ -373,53 +574,53 @@ static int contains(struct isl_map *map,
* | || | | |
* |__||_/ |_____/
*/
-static int is_adj_ineq_extension(__isl_keep isl_map *map, int i, int j,
- struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+static enum isl_change is_adj_ineq_extension(int i, int j,
+ struct isl_coalesce_info *info)
{
int k;
struct isl_tab_undo *snap;
- unsigned n_eq = map->p[i]->n_eq;
- unsigned total = isl_basic_map_total_dim(map->p[i]);
+ unsigned n_eq = info[i].bmap->n_eq;
+ unsigned total = isl_basic_map_total_dim(info[i].bmap);
int r;
- if (isl_tab_extend_cons(tabs[i], 1 + map->p[j]->n_ineq) < 0)
- return -1;
+ if (isl_tab_extend_cons(info[i].tab, 1 + info[j].bmap->n_ineq) < 0)
+ return isl_change_error;
- for (k = 0; k < map->p[i]->n_ineq; ++k)
- if (ineq_i[k] == STATUS_ADJ_INEQ)
+ for (k = 0; k < info[i].bmap->n_ineq; ++k)
+ if (info[i].ineq[k] == STATUS_ADJ_INEQ)
break;
- if (k >= map->p[i]->n_ineq)
- isl_die(isl_map_get_ctx(map), isl_error_internal,
- "ineq_i should have exactly one STATUS_ADJ_INEQ",
- return -1);
-
- snap = isl_tab_snap(tabs[i]);
-
- if (isl_tab_unrestrict(tabs[i], n_eq + k) < 0)
- return -1;
-
- isl_seq_neg(map->p[i]->ineq[k], map->p[i]->ineq[k], 1 + total);
- isl_int_sub_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1);
- r = isl_tab_add_ineq(tabs[i], map->p[i]->ineq[k]);
- isl_seq_neg(map->p[i]->ineq[k], map->p[i]->ineq[k], 1 + total);
- isl_int_sub_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1);
+ if (k >= info[i].bmap->n_ineq)
+ isl_die(isl_basic_map_get_ctx(info[i].bmap), isl_error_internal,
+ "info[i].ineq should have exactly one STATUS_ADJ_INEQ",
+ return isl_change_error);
+
+ snap = isl_tab_snap(info[i].tab);
+
+ if (isl_tab_unrestrict(info[i].tab, n_eq + k) < 0)
+ return isl_change_error;
+
+ isl_seq_neg(info[i].bmap->ineq[k], info[i].bmap->ineq[k], 1 + total);
+ isl_int_sub_ui(info[i].bmap->ineq[k][0], info[i].bmap->ineq[k][0], 1);
+ r = isl_tab_add_ineq(info[i].tab, info[i].bmap->ineq[k]);
+ isl_seq_neg(info[i].bmap->ineq[k], info[i].bmap->ineq[k], 1 + total);
+ isl_int_sub_ui(info[i].bmap->ineq[k][0], info[i].bmap->ineq[k][0], 1);
if (r < 0)
- return -1;
+ return isl_change_error;
- for (k = 0; k < map->p[j]->n_ineq; ++k) {
- if (ineq_j[k] != STATUS_VALID)
+ for (k = 0; k < info[j].bmap->n_ineq; ++k) {
+ if (info[j].ineq[k] != STATUS_VALID)
continue;
- if (isl_tab_add_ineq(tabs[i], map->p[j]->ineq[k]) < 0)
- return -1;
+ if (isl_tab_add_ineq(info[i].tab, info[j].bmap->ineq[k]) < 0)
+ return isl_change_error;
}
- if (contains(map, j, ineq_j, tabs[i]))
- return fuse(map, i, j, tabs, eq_i, ineq_i, eq_j, ineq_j, NULL);
+ if (contains(&info[j], info[i].tab))
+ return fuse(i, j, info, NULL, 0, 0);
- if (isl_tab_rollback(tabs[i], snap) < 0)
- return -1;
+ if (isl_tab_rollback(info[i].tab, snap) < 0)
+ return isl_change_error;
- return 0;
+ return isl_change_none;
}
@@ -454,35 +655,33 @@ static int is_adj_ineq_extension(__isl_k
* still be able to fuse the two basic maps, but we need to perform
* some additional checks in is_adj_ineq_extension.
*/
-static int check_adj_ineq(struct isl_map *map, int i, int j,
- struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+static enum isl_change check_adj_ineq(int i, int j,
+ struct isl_coalesce_info *info)
{
int count_i, count_j;
int cut_i, cut_j;
- count_i = count(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_INEQ);
- count_j = count(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_INEQ);
+ count_i = count(info[i].ineq, info[i].bmap->n_ineq, STATUS_ADJ_INEQ);
+ count_j = count(info[j].ineq, info[j].bmap->n_ineq, STATUS_ADJ_INEQ);
if (count_i != 1 && count_j != 1)
- return 0;
+ return isl_change_none;
- cut_i = any(eq_i, 2 * map->p[i]->n_eq, STATUS_CUT) ||
- any(ineq_i, map->p[i]->n_ineq, STATUS_CUT);
- cut_j = any(eq_j, 2 * map->p[j]->n_eq, STATUS_CUT) ||
- any(ineq_j, map->p[j]->n_ineq, STATUS_CUT);
+ cut_i = any(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_CUT) ||
+ any(info[i].ineq, info[i].bmap->n_ineq, STATUS_CUT);
+ cut_j = any(info[j].eq, 2 * info[j].bmap->n_eq, STATUS_CUT) ||
+ any(info[j].ineq, info[j].bmap->n_ineq, STATUS_CUT);
if (!cut_i && !cut_j && count_i == 1 && count_j == 1)
- return fuse(map, i, j, tabs, NULL, ineq_i, NULL, ineq_j, NULL);
+ return fuse(i, j, info, NULL, 0, 0);
if (count_i == 1 && !cut_i)
- return is_adj_ineq_extension(map, i, j, tabs,
- eq_i, ineq_i, eq_j, ineq_j);
+ return is_adj_ineq_extension(i, j, info);
if (count_j == 1 && !cut_j)
- return is_adj_ineq_extension(map, j, i, tabs,
- eq_j, ineq_j, eq_i, ineq_i);
+ return is_adj_ineq_extension(j, i, info);
- return 0;
+ return isl_change_none;
}
/* Basic map "i" has an inequality "k" that is adjacent to some equality
@@ -496,6 +695,11 @@ static int check_adj_ineq(struct isl_map
* other basic map is included in the extension, because there
* were no "cut" inequalities in "i") and we can replace the
* two basic maps by this extension.
+ * Each integer division that does not have exactly the same
+ * definition in "i" and "j" is marked unknown and the basic map
+ * is scheduled to be simplified in an attempt to recover
+ * the integer division definition.
+ * Place this extension in the position that is the smallest of i and j.
* ____ _____
* / || / |
* / || / |
@@ -503,38 +707,52 @@ static int check_adj_ineq(struct isl_map
* \ || \ |
* \___|| \____|
*/
-static int is_adj_eq_extension(struct isl_map *map, int i, int j, int k,
- struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+static enum isl_change is_adj_eq_extension(int i, int j, int k,
+ struct isl_coalesce_info *info)
{
- int changed = 0;
+ int change = isl_change_none;
int super;
struct isl_tab_undo *snap, *snap2;
- unsigned n_eq = map->p[i]->n_eq;
+ unsigned n_eq = info[i].bmap->n_eq;
- if (isl_tab_is_equality(tabs[i], n_eq + k))
- return 0;
+ if (isl_tab_is_equality(info[i].tab, n_eq + k))
+ return isl_change_none;
- snap = isl_tab_snap(tabs[i]);
- tabs[i] = isl_tab_relax(tabs[i], n_eq + k);
- snap2 = isl_tab_snap(tabs[i]);
- if (isl_tab_select_facet(tabs[i], n_eq + k) < 0)
- return -1;
- super = contains(map, j, ineq_j, tabs[i]);
+ snap = isl_tab_snap(info[i].tab);
+ if (isl_tab_relax(info[i].tab, n_eq + k) < 0)
+ return isl_change_error;
+ snap2 = isl_tab_snap(info[i].tab);
+ if (isl_tab_select_facet(info[i].tab, n_eq + k) < 0)
+ return isl_change_error;
+ super = contains(&info[j], info[i].tab);
if (super) {
- if (isl_tab_rollback(tabs[i], snap2) < 0)
- return -1;
- map->p[i] = isl_basic_map_cow(map->p[i]);
- if (!map->p[i])
- return -1;
- isl_int_add_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1);
- ISL_F_SET(map->p[i], ISL_BASIC_MAP_FINAL);
- drop(map, j, tabs);
- changed = 1;
+ int l;
+ unsigned total;
+
+ if (isl_tab_rollback(info[i].tab, snap2) < 0)
+ return isl_change_error;
+ info[i].bmap = isl_basic_map_cow(info[i].bmap);
+ if (!info[i].bmap)
+ return isl_change_error;
+ total = isl_basic_map_total_dim(info[i].bmap);
+ for (l = 0; l < info[i].bmap->n_div; ++l)
+ if (!isl_seq_eq(info[i].bmap->div[l],
+ info[j].bmap->div[l], 1 + 1 + total)) {
+ isl_int_set_si(info[i].bmap->div[l][0], 0);
+ info[i].simplify = 1;
+ }
+ isl_int_add_ui(info[i].bmap->ineq[k][0],
+ info[i].bmap->ineq[k][0], 1);
+ ISL_F_SET(info[i].bmap, ISL_BASIC_MAP_FINAL);
+ drop(&info[j]);
+ if (j < i)
+ exchange(&info[i], &info[j]);
+ change = isl_change_fuse;
} else
- if (isl_tab_rollback(tabs[i], snap) < 0)
- return -1;
+ if (isl_tab_rollback(info[i].tab, snap) < 0)
+ return isl_change_error;
- return changed;
+ return change;
}
/* Data structure that keeps track of the wrapping constraints
@@ -551,31 +769,32 @@ struct isl_wraps {
};
/* Update wraps->max to be greater than or equal to the coefficients
- * in the equalities and inequalities of bmap that can be removed if we end up
- * applying wrapping.
+ * in the equalities and inequalities of info->bmap that can be removed
+ * if we end up applying wrapping.
*/
static void wraps_update_max(struct isl_wraps *wraps,
- __isl_keep isl_basic_map *bmap, int *eq, int *ineq)
+ struct isl_coalesce_info *info)
{
int k;
isl_int max_k;
- unsigned total = isl_basic_map_total_dim(bmap);
+ unsigned total = isl_basic_map_total_dim(info->bmap);
isl_int_init(max_k);
- for (k = 0; k < bmap->n_eq; ++k) {
- if (eq[2 * k] == STATUS_VALID &&
- eq[2 * k + 1] == STATUS_VALID)
+ for (k = 0; k < info->bmap->n_eq; ++k) {
+ if (info->eq[2 * k] == STATUS_VALID &&
+ info->eq[2 * k + 1] == STATUS_VALID)
continue;
- isl_seq_abs_max(bmap->eq[k] + 1, total, &max_k);
+ isl_seq_abs_max(info->bmap->eq[k] + 1, total, &max_k);
if (isl_int_abs_gt(max_k, wraps->max))
isl_int_set(wraps->max, max_k);
}
- for (k = 0; k < bmap->n_ineq; ++k) {
- if (ineq[k] == STATUS_VALID || ineq[k] == STATUS_REDUNDANT)
+ for (k = 0; k < info->bmap->n_ineq; ++k) {
+ if (info->ineq[k] == STATUS_VALID ||
+ info->ineq[k] == STATUS_REDUNDANT)
continue;
- isl_seq_abs_max(bmap->ineq[k] + 1, total, &max_k);
+ isl_seq_abs_max(info->bmap->ineq[k] + 1, total, &max_k);
if (isl_int_abs_gt(max_k, wraps->max))
isl_int_set(wraps->max, max_k);
}
@@ -590,8 +809,7 @@ static void wraps_update_max(struct isl_
* applying wrapping.
*/
static void wraps_init(struct isl_wraps *wraps, __isl_take isl_mat *mat,
- __isl_keep isl_map *map, int i, int j,
- int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+ struct isl_coalesce_info *info, int i, int j)
{
isl_ctx *ctx;
@@ -605,8 +823,8 @@ static void wraps_init(struct isl_wraps
return;
isl_int_init(wraps->max);
isl_int_set_si(wraps->max, 0);
- wraps_update_max(wraps, map->p[i], eq_i, ineq_i);
- wraps_update_max(wraps, map->p[j], eq_j, ineq_j);
+ wraps_update_max(wraps, &info[i]);
+ wraps_update_max(wraps, &info[j]);
}
/* Free the contents of the isl_wraps data structure.
@@ -637,9 +855,40 @@ static int allow_wrap(struct isl_wraps *
return 1;
}
-/* For each non-redundant constraint in "bmap" (as determined by "tab"),
+/* Wrap "ineq" (or its opposite if "negate" is set) around "bound"
+ * to include "set" and add the result in position "w" of "wraps".
+ * "len" is the total number of coefficients in "bound" and "ineq".
+ * Return 1 on success, 0 on failure and -1 on error.
+ * Wrapping can fail if the result of wrapping is equal to "bound"
+ * or if we want to bound the sizes of the coefficients and
+ * the wrapped constraint does not satisfy this bound.
+ */
+static int add_wrap(struct isl_wraps *wraps, int w, isl_int *bound,
+ isl_int *ineq, unsigned len, __isl_keep isl_set *set, int negate)
+{
+ isl_seq_cpy(wraps->mat->row[w], bound, len);
+ if (negate) {
+ isl_seq_neg(wraps->mat->row[w + 1], ineq, len);
+ ineq = wraps->mat->row[w + 1];
+ }
+ if (!isl_set_wrap_facet(set, wraps->mat->row[w], ineq))
+ return -1;
+ if (isl_seq_eq(wraps->mat->row[w], bound, len))
+ return 0;
+ if (!allow_wrap(wraps, w))
+ return 0;
+ return 1;
+}
+
+/* For each constraint in info->bmap that is not redundant (as determined
+ * by info->tab) and that is not a valid constraint for the other basic map,
* wrap the constraint around "bound" such that it includes the whole
* set "set" and append the resulting constraint to "wraps".
+ * Note that the constraints that are valid for the other basic map
+ * will be added to the combined basic map by default, so there is
+ * no need to wrap them.
+ * The caller wrap_in_facets even relies on this function not wrapping
+ * any constraints that are already valid.
* "wraps" is assumed to have been pre-allocated to the appropriate size.
* wraps->n_row is the number of actual wrapped constraints that have
* been added.
@@ -651,57 +900,52 @@ static int allow_wrap(struct isl_wraps *
* constraints and a newly added wrapping constraint does not
* satisfy the bound, then wraps->n_row is also reset to zero.
*/
-static int add_wraps(struct isl_wraps *wraps, __isl_keep isl_basic_map *bmap,
- struct isl_tab *tab, isl_int *bound, __isl_keep isl_set *set)
+static int add_wraps(struct isl_wraps *wraps, struct isl_coalesce_info *info,
+ isl_int *bound, __isl_keep isl_set *set)
{
- int l;
+ int l, m;
int w;
- unsigned total = isl_basic_map_total_dim(bmap);
+ int added;
+ isl_basic_map *bmap = info->bmap;
+ unsigned len = 1 + isl_basic_map_total_dim(bmap);
w = wraps->mat->n_row;
for (l = 0; l < bmap->n_ineq; ++l) {
- if (isl_seq_is_neg(bound, bmap->ineq[l], 1 + total))
+ if (info->ineq[l] == STATUS_VALID ||
+ info->ineq[l] == STATUS_REDUNDANT)
continue;
- if (isl_seq_eq(bound, bmap->ineq[l], 1 + total))
+ if (isl_seq_is_neg(bound, bmap->ineq[l], len))
continue;
- if (isl_tab_is_redundant(tab, bmap->n_eq + l))
+ if (isl_seq_eq(bound, bmap->ineq[l], len))
+ continue;
+ if (isl_tab_is_redundant(info->tab, bmap->n_eq + l))
continue;
- isl_seq_cpy(wraps->mat->row[w], bound, 1 + total);
- if (!isl_set_wrap_facet(set, wraps->mat->row[w], bmap->ineq[l]))
+ added = add_wrap(wraps, w, bound, bmap->ineq[l], len, set, 0);
+ if (added < 0)
return -1;
- if (isl_seq_eq(wraps->mat->row[w], bound, 1 + total))
- goto unbounded;
- if (!allow_wrap(wraps, w))
+ if (!added)
goto unbounded;
++w;
}
for (l = 0; l < bmap->n_eq; ++l) {
- if (isl_seq_is_neg(bound, bmap->eq[l], 1 + total))
+ if (isl_seq_is_neg(bound, bmap->eq[l], len))
continue;
- if (isl_seq_eq(bound, bmap->eq[l], 1 + total))
+ if (isl_seq_eq(bound, bmap->eq[l], len))
continue;
- isl_seq_cpy(wraps->mat->row[w], bound, 1 + total);
- isl_seq_neg(wraps->mat->row[w + 1], bmap->eq[l], 1 + total);
- if (!isl_set_wrap_facet(set, wraps->mat->row[w],
- wraps->mat->row[w + 1]))
- return -1;
- if (isl_seq_eq(wraps->mat->row[w], bound, 1 + total))
- goto unbounded;
- if (!allow_wrap(wraps, w))
- goto unbounded;
- ++w;
-
- isl_seq_cpy(wraps->mat->row[w], bound, 1 + total);
- if (!isl_set_wrap_facet(set, wraps->mat->row[w], bmap->eq[l]))
- return -1;
- if (isl_seq_eq(wraps->mat->row[w], bound, 1 + total))
- goto unbounded;
- if (!allow_wrap(wraps, w))
- goto unbounded;
- ++w;
+ for (m = 0; m < 2; ++m) {
+ if (info->eq[2 * l + m] == STATUS_VALID)
+ continue;
+ added = add_wrap(wraps, w, bound, bmap->eq[l], len,
+ set, !m);
+ if (added < 0)
+ return -1;
+ if (!added)
+ goto unbounded;
+ ++w;
+ }
}
wraps->mat->n_row = w;
@@ -734,7 +978,7 @@ static int check_wraps(__isl_keep isl_ma
return 0;
}
-/* Return a set that corresponds to the non-redudant constraints
+/* Return a set that corresponds to the non-redundant constraints
* (as recorded in tab) of bmap.
*
* It's important to remove the redundant constraints as some
@@ -745,34 +989,73 @@ static int check_wraps(__isl_keep isl_ma
* and should therefore continue to be ignored ever after.
* Otherwise, the relaxation might be thwarted by some of
* these constraints.
+ *
+ * Update the underlying set to ensure that the dimension doesn't change.
+ * Otherwise the integer divisions could get dropped if the tab
+ * turns out to be empty.
*/
static __isl_give isl_set *set_from_updated_bmap(__isl_keep isl_basic_map *bmap,
struct isl_tab *tab)
{
+ isl_basic_set *bset;
+
bmap = isl_basic_map_copy(bmap);
- bmap = isl_basic_map_cow(bmap);
- bmap = isl_basic_map_update_from_tab(bmap, tab);
- return isl_set_from_basic_set(isl_basic_map_underlying_set(bmap));
+ bset = isl_basic_map_underlying_set(bmap);
+ bset = isl_basic_set_cow(bset);
+ bset = isl_basic_set_update_from_tab(bset, tab);
+ return isl_set_from_basic_set(bset);
+}
+
+/* Wrap the constraints of info->bmap that bound the facet defined
+ * by inequality "k" around (the opposite of) this inequality to
+ * include "set". "bound" may be used to store the negated inequality.
+ * Since the wrapped constraints are not guaranteed to contain the whole
+ * of info->bmap, we check them in check_wraps.
+ * If any of the wrapped constraints turn out to be invalid, then
+ * check_wraps will reset wrap->n_row to zero.
+ */
+static int add_wraps_around_facet(struct isl_wraps *wraps,
+ struct isl_coalesce_info *info, int k, isl_int *bound,
+ __isl_keep isl_set *set)
+{
+ struct isl_tab_undo *snap;
+ int n;
+ unsigned total = isl_basic_map_total_dim(info->bmap);
+
+ snap = isl_tab_snap(info->tab);
+
+ if (isl_tab_select_facet(info->tab, info->bmap->n_eq + k) < 0)
+ return -1;
+ if (isl_tab_detect_redundant(info->tab) < 0)
+ return -1;
+
+ isl_seq_neg(bound, info->bmap->ineq[k], 1 + total);
+
+ n = wraps->mat->n_row;
+ if (add_wraps(wraps, info, bound, set) < 0)
+ return -1;
+
+ if (isl_tab_rollback(info->tab, snap) < 0)
+ return -1;
+ if (check_wraps(wraps->mat, n, info->tab) < 0)
+ return -1;
+
+ return 0;
}
-/* Given a basic set i with a constraint k that is adjacent to either the
- * whole of basic set j or a facet of basic set j, check if we can wrap
- * both the facet corresponding to k and the facet of j (or the whole of j)
- * around their ridges to include the other set.
+/* Given a basic set i with a constraint k that is adjacent to
+ * basic set j, check if we can wrap
+ * both the facet corresponding to k (if "wrap_facet" is set) and basic map j
+ * (always) around their ridges to include the other set.
* If so, replace the pair of basic sets by their union.
*
- * All constraints of i (except k) are assumed to be valid for j.
- *
- * However, the constraints of j may not be valid for i and so
- * we have to check that the wrapping constraints for j are valid for i.
- *
- * In the case where j has a facet adjacent to i, tab[j] is assumed
- * to have been restricted to this facet, so that the non-redundant
- * constraints in tab[j] are the ridges of the facet.
- * Note that for the purpose of wrapping, it does not matter whether
- * we wrap the ridges of i around the whole of j or just around
- * the facet since all the other constraints are assumed to be valid for j.
- * In practice, we wrap to include the whole of j.
+ * All constraints of i (except k) are assumed to be valid or
+ * cut constraints for j.
+ * Wrapping the cut constraints to include basic map j may result
+ * in constraints that are no longer valid of basic map i
+ * we have to check that the resulting wrapping constraints are valid for i.
+ * If "wrap_facet" is not set, then all constraints of i (except k)
+ * are assumed to be valid for j.
* ____ _____
* / | / \
* / || / |
@@ -781,61 +1064,49 @@ static __isl_give isl_set *set_from_upda
* \___|| \____|
*
*/
-static int can_wrap_in_facet(struct isl_map *map, int i, int j, int k,
- struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+static enum isl_change can_wrap_in_facet(int i, int j, int k,
+ struct isl_coalesce_info *info, int wrap_facet)
{
- int changed = 0;
+ enum isl_change change = isl_change_none;
struct isl_wraps wraps;
+ isl_ctx *ctx;
isl_mat *mat;
struct isl_set *set_i = NULL;
struct isl_set *set_j = NULL;
struct isl_vec *bound = NULL;
- unsigned total = isl_basic_map_total_dim(map->p[i]);
- struct isl_tab_undo *snap;
- int n;
+ unsigned total = isl_basic_map_total_dim(info[i].bmap);
- set_i = set_from_updated_bmap(map->p[i], tabs[i]);
- set_j = set_from_updated_bmap(map->p[j], tabs[j]);
- mat = isl_mat_alloc(map->ctx, 2 * (map->p[i]->n_eq + map->p[j]->n_eq) +
- map->p[i]->n_ineq + map->p[j]->n_ineq,
- 1 + total);
- wraps_init(&wraps, mat, map, i, j, eq_i, ineq_i, eq_j, ineq_j);
- bound = isl_vec_alloc(map->ctx, 1 + total);
+ set_i = set_from_updated_bmap(info[i].bmap, info[i].tab);
+ set_j = set_from_updated_bmap(info[j].bmap, info[j].tab);
+ ctx = isl_basic_map_get_ctx(info[i].bmap);
+ mat = isl_mat_alloc(ctx, 2 * (info[i].bmap->n_eq + info[j].bmap->n_eq) +
+ info[i].bmap->n_ineq + info[j].bmap->n_ineq,
+ 1 + total);
+ wraps_init(&wraps, mat, info, i, j);
+ bound = isl_vec_alloc(ctx, 1 + total);
if (!set_i || !set_j || !wraps.mat || !bound)
goto error;
- isl_seq_cpy(bound->el, map->p[i]->ineq[k], 1 + total);
+ isl_seq_cpy(bound->el, info[i].bmap->ineq[k], 1 + total);
isl_int_add_ui(bound->el[0], bound->el[0], 1);
isl_seq_cpy(wraps.mat->row[0], bound->el, 1 + total);
wraps.mat->n_row = 1;
- if (add_wraps(&wraps, map->p[j], tabs[j], bound->el, set_i) < 0)
+ if (add_wraps(&wraps, &info[j], bound->el, set_i) < 0)
goto error;
if (!wraps.mat->n_row)
goto unbounded;
- snap = isl_tab_snap(tabs[i]);
-
- if (isl_tab_select_facet(tabs[i], map->p[i]->n_eq + k) < 0)
- goto error;
- if (isl_tab_detect_redundant(tabs[i]) < 0)
- goto error;
-
- isl_seq_neg(bound->el, map->p[i]->ineq[k], 1 + total);
-
- n = wraps.mat->n_row;
- if (add_wraps(&wraps, map->p[i], tabs[i], bound->el, set_j) < 0)
- goto error;
-
- if (isl_tab_rollback(tabs[i], snap) < 0)
- goto error;
- if (check_wraps(wraps.mat, n, tabs[i]) < 0)
- goto error;
- if (!wraps.mat->n_row)
- goto unbounded;
+ if (wrap_facet) {
+ if (add_wraps_around_facet(&wraps, &info[i], k,
+ bound->el, set_j) < 0)
+ goto error;
+ if (!wraps.mat->n_row)
+ goto unbounded;
+ }
- changed = fuse(map, i, j, tabs, eq_i, ineq_i, eq_j, ineq_j, wraps.mat);
+ change = fuse(i, j, info, wraps.mat, 0, 0);
unbounded:
wraps_free(&wraps);
@@ -845,38 +1116,13 @@ unbounded:
isl_vec_free(bound);
- return changed;
+ return change;
error:
wraps_free(&wraps);
isl_vec_free(bound);
isl_set_free(set_i);
isl_set_free(set_j);
- return -1;
-}
-
-/* Set the is_redundant property of the "n" constraints in "cuts",
- * except "k" to "v".
- * This is a fairly tricky operation as it bypasses isl_tab.c.
- * The reason we want to temporarily mark some constraints redundant
- * is that we want to ignore them in add_wraps.
- *
- * Initially all cut constraints are non-redundant, but the
- * selection of a facet right before the call to this function
- * may have made some of them redundant.
- * Likewise, the same constraints are marked non-redundant
- * in the second call to this function, before they are officially
- * made non-redundant again in the subsequent rollback.
- */
-static void set_is_redundant(struct isl_tab *tab, unsigned n_eq,
- int *cuts, int n, int k, int v)
-{
- int l;
-
- for (l = 0; l < n; ++l) {
- if (l == k)
- continue;
- tab->con[n_eq + cuts[l]].is_redundant = v;
- }
+ return isl_change_error;
}
/* Given a pair of basic maps i and j such that j sticks out
@@ -885,91 +1131,75 @@ static void set_is_redundant(struct isl_
* basic maps by a single basic map.
* The other constraints of i are assumed to be valid for j.
*
- * The facets of i corresponding to the cut constraints are
- * wrapped around their ridges, except those ridges determined
- * by any of the other cut constraints.
- * The intersections of cut constraints need to be ignored
- * as the result of wrapping one cut constraint around another
- * would result in a constraint cutting the union.
- * In each case, the facets are wrapped to include the union
- * of the two basic maps.
- *
- * The pieces of j that lie at an offset of exactly one from
- * one of the cut constraints of i are wrapped around their edges.
- * Here, there is no need to ignore intersections because we
- * are wrapping around the union of the two basic maps.
+ * For each cut constraint t(x) >= 0 of i, we add the relaxed version
+ * t(x) + 1 >= 0, along with wrapping constraints for all constraints
+ * of basic map j that bound the part of basic map j that sticks out
+ * of the cut constraint.
+ * In particular, we first intersect basic map j with t(x) + 1 = 0.
+ * If the result is empty, then t(x) >= 0 was actually a valid constraint
+ * (with respect to the integer points), so we add t(x) >= 0 instead.
+ * Otherwise, we wrap the constraints of basic map j that are not
+ * redundant in this intersection and that are not already valid
+ * for basic map i over basic map i.
+ * Note that it is sufficient to wrap the constraints to include
+ * basic map i, because we will only wrap the constraints that do
+ * not include basic map i already. The wrapped constraint will
+ * therefore be more relaxed compared to the original constraint.
+ * Since the original constraint is valid for basic map j, so is
+ * the wrapped constraint.
*
* If any wrapping fails, i.e., if we cannot wrap to touch
* the union, then we give up.
* Otherwise, the pair of basic maps is replaced by their union.
*/
-static int wrap_in_facets(struct isl_map *map, int i, int j,
- int *cuts, int n, struct isl_tab **tabs,
- int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+static enum isl_change wrap_in_facets(int i, int j, int *cuts, int n,
+ struct isl_coalesce_info *info)
{
- int changed = 0;
+ enum isl_change change = isl_change_none;
struct isl_wraps wraps;
+ isl_ctx *ctx;
isl_mat *mat;
- isl_set *set = NULL;
- isl_vec *bound = NULL;
- unsigned total = isl_basic_map_total_dim(map->p[i]);
+ isl_set *set_i = NULL;
+ unsigned total = isl_basic_map_total_dim(info[i].bmap);
int max_wrap;
- int k;
- struct isl_tab_undo *snap_i, *snap_j;
+ int k, w;
+ struct isl_tab_undo *snap;
- if (isl_tab_extend_cons(tabs[j], 1) < 0)
+ if (isl_tab_extend_cons(info[j].tab, 1) < 0)
goto error;
- max_wrap = 2 * (map->p[i]->n_eq + map->p[j]->n_eq) +
- map->p[i]->n_ineq + map->p[j]->n_ineq;
+ max_wrap = 1 + 2 * info[j].bmap->n_eq + info[j].bmap->n_ineq;
max_wrap *= n;
- set = isl_set_union(set_from_updated_bmap(map->p[i], tabs[i]),
- set_from_updated_bmap(map->p[j], tabs[j]));
- mat = isl_mat_alloc(map->ctx, max_wrap, 1 + total);
- wraps_init(&wraps, mat, map, i, j, eq_i, ineq_i, eq_j, ineq_j);
- bound = isl_vec_alloc(map->ctx, 1 + total);
- if (!set || !wraps.mat || !bound)
+ set_i = set_from_updated_bmap(info[i].bmap, info[i].tab);
+ ctx = isl_basic_map_get_ctx(info[i].bmap);
+ mat = isl_mat_alloc(ctx, max_wrap, 1 + total);
+ wraps_init(&wraps, mat, info, i, j);
+ if (!set_i || !wraps.mat)
goto error;
- snap_i = isl_tab_snap(tabs[i]);
- snap_j = isl_tab_snap(tabs[j]);
+ snap = isl_tab_snap(info[j].tab);
wraps.mat->n_row = 0;
for (k = 0; k < n; ++k) {
- if (isl_tab_select_facet(tabs[i], map->p[i]->n_eq + cuts[k]) < 0)
- goto error;
- if (isl_tab_detect_redundant(tabs[i]) < 0)
- goto error;
- set_is_redundant(tabs[i], map->p[i]->n_eq, cuts, n, k, 1);
-
- isl_seq_neg(bound->el, map->p[i]->ineq[cuts[k]], 1 + total);
- if (!tabs[i]->empty &&
- add_wraps(&wraps, map->p[i], tabs[i], bound->el, set) < 0)
- goto error;
-
- set_is_redundant(tabs[i], map->p[i]->n_eq, cuts, n, k, 0);
- if (isl_tab_rollback(tabs[i], snap_i) < 0)
- goto error;
-
- if (tabs[i]->empty)
- break;
- if (!wraps.mat->n_row)
- break;
-
- isl_seq_cpy(bound->el, map->p[i]->ineq[cuts[k]], 1 + total);
- isl_int_add_ui(bound->el[0], bound->el[0], 1);
- if (isl_tab_add_eq(tabs[j], bound->el) < 0)
+ w = wraps.mat->n_row++;
+ isl_seq_cpy(wraps.mat->row[w],
+ info[i].bmap->ineq[cuts[k]], 1 + total);
+ isl_int_add_ui(wraps.mat->row[w][0], wraps.mat->row[w][0], 1);
+ if (isl_tab_add_eq(info[j].tab, wraps.mat->row[w]) < 0)
goto error;
- if (isl_tab_detect_redundant(tabs[j]) < 0)
+ if (isl_tab_detect_redundant(info[j].tab) < 0)
goto error;
- if (!tabs[j]->empty &&
- add_wraps(&wraps, map->p[j], tabs[j], bound->el, set) < 0)
+ if (info[j].tab->empty)
+ isl_int_sub_ui(wraps.mat->row[w][0],
+ wraps.mat->row[w][0], 1);
+ else if (add_wraps(&wraps, &info[j],
+ wraps.mat->row[w], set_i) < 0)
goto error;
- if (isl_tab_rollback(tabs[j], snap_j) < 0)
+ if (isl_tab_rollback(info[j].tab, snap) < 0)
goto error;
if (!wraps.mat->n_row)
@@ -977,19 +1207,16 @@ static int wrap_in_facets(struct isl_map
}
if (k == n)
- changed = fuse(map, i, j, tabs,
- eq_i, ineq_i, eq_j, ineq_j, wraps.mat);
+ change = fuse(i, j, info, wraps.mat, 0, 1);
- isl_vec_free(bound);
wraps_free(&wraps);
- isl_set_free(set);
+ isl_set_free(set_i);
- return changed;
+ return change;
error:
- isl_vec_free(bound);
wraps_free(&wraps);
- isl_set_free(set);
- return -1;
+ isl_set_free(set_i);
+ return isl_change_error;
}
/* Given two basic sets i and j such that i has no cut equalities,
@@ -1051,35 +1278,39 @@ error:
* |
* \______________________________________________________________________
*/
-static int can_wrap_in_set(struct isl_map *map, int i, int j,
- struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+static enum isl_change can_wrap_in_set(int i, int j,
+ struct isl_coalesce_info *info)
{
- int changed = 0;
+ enum isl_change change = isl_change_none;
int k, m;
int n;
int *cuts = NULL;
+ isl_ctx *ctx;
- if (ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_RATIONAL) ||
- ISL_F_ISSET(map->p[j], ISL_BASIC_MAP_RATIONAL))
- return 0;
+ if (ISL_F_ISSET(info[i].bmap, ISL_BASIC_MAP_RATIONAL) ||
+ ISL_F_ISSET(info[j].bmap, ISL_BASIC_MAP_RATIONAL))
+ return isl_change_none;
- n = count(ineq_i, map->p[i]->n_ineq, STATUS_CUT);
+ n = count(info[i].ineq, info[i].bmap->n_ineq, STATUS_CUT);
if (n == 0)
- return 0;
+ return isl_change_none;
- cuts = isl_alloc_array(map->ctx, int, n);
+ ctx = isl_basic_map_get_ctx(info[i].bmap);
+ cuts = isl_alloc_array(ctx, int, n);
if (!cuts)
- return -1;
+ return isl_change_error;
for (k = 0, m = 0; m < n; ++k) {
enum isl_ineq_type type;
- if (ineq_i[k] != STATUS_CUT)
+ if (info[i].ineq[k] != STATUS_CUT)
continue;
- isl_int_add_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1);
- type = isl_tab_ineq_type(tabs[j], map->p[i]->ineq[k]);
- isl_int_sub_ui(map->p[i]->ineq[k][0], map->p[i]->ineq[k][0], 1);
+ isl_int_add_ui(info[i].bmap->ineq[k][0],
+ info[i].bmap->ineq[k][0], 1);
+ type = isl_tab_ineq_type(info[j].tab, info[i].bmap->ineq[k]);
+ isl_int_sub_ui(info[i].bmap->ineq[k][0],
+ info[i].bmap->ineq[k][0], 1);
if (type == isl_ineq_error)
goto error;
if (type != isl_ineq_redundant)
@@ -1089,36 +1320,32 @@ static int can_wrap_in_set(struct isl_ma
}
if (m == n)
- changed = wrap_in_facets(map, i, j, cuts, n, tabs,
- eq_i, ineq_i, eq_j, ineq_j);
+ change = wrap_in_facets(i, j, cuts, n, info);
free(cuts);
- return changed;
+ return change;
error:
free(cuts);
- return -1;
+ return isl_change_error;
}
-/* Check if either i or j has a single cut constraint that can
+/* Check if either i or j has only cut inequalities that can
* be used to wrap in (a facet of) the other basic set.
* if so, replace the pair by their union.
*/
-static int check_wrap(struct isl_map *map, int i, int j,
- struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+static enum isl_change check_wrap(int i, int j, struct isl_coalesce_info *info)
{
- int changed = 0;
+ enum isl_change change = isl_change_none;
- if (!any(eq_i, 2 * map->p[i]->n_eq, STATUS_CUT))
- changed = can_wrap_in_set(map, i, j, tabs,
- eq_i, ineq_i, eq_j, ineq_j);
- if (changed)
- return changed;
-
- if (!any(eq_j, 2 * map->p[j]->n_eq, STATUS_CUT))
- changed = can_wrap_in_set(map, j, i, tabs,
- eq_j, ineq_j, eq_i, ineq_i);
- return changed;
+ if (!any(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_CUT))
+ change = can_wrap_in_set(i, j, info);
+ if (change != isl_change_none)
+ return change;
+
+ if (!any(info[j].eq, 2 * info[j].bmap->n_eq, STATUS_CUT))
+ change = can_wrap_in_set(j, i, info);
+ return change;
}
/* At least one of the basic maps has an equality that is adjacent
@@ -1129,52 +1356,49 @@ static int check_wrap(struct isl_map *ma
* map that has the equality "j".
* If "i" has any "cut" (in)equality, then relaxing the inequality
* by one would not result in a basic map that contains the other
+ * basic map. However, it may still be possible to wrap in the other
* basic map.
*/
-static int check_adj_eq(struct isl_map *map, int i, int j,
- struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+static enum isl_change check_adj_eq(int i, int j,
+ struct isl_coalesce_info *info)
{
- int changed = 0;
+ enum isl_change change = isl_change_none;
int k;
+ int any_cut;
- if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_INEQ) &&
- any(eq_j, 2 * map->p[j]->n_eq, STATUS_ADJ_INEQ))
+ if (any(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_ADJ_INEQ) &&
+ any(info[j].eq, 2 * info[j].bmap->n_eq, STATUS_ADJ_INEQ))
/* ADJ EQ TOO MANY */
- return 0;
+ return isl_change_none;
- if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_INEQ))
- return check_adj_eq(map, j, i, tabs,
- eq_j, ineq_j, eq_i, ineq_i);
+ if (any(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_ADJ_INEQ))
+ return check_adj_eq(j, i, info);
/* j has an equality adjacent to an inequality in i */
- if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_CUT))
- return 0;
- if (any(ineq_i, map->p[i]->n_ineq, STATUS_CUT))
- /* ADJ EQ CUT */
- return 0;
- if (count(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_EQ) != 1 ||
- any(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_EQ) ||
- any(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_INEQ) ||
- any(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_INEQ))
+ if (any(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_CUT))
+ return isl_change_none;
+ any_cut = any(info[i].ineq, info[i].bmap->n_ineq, STATUS_CUT);
+ if (count(info[i].ineq, info[i].bmap->n_ineq, STATUS_ADJ_EQ) != 1 ||
+ any(info[j].ineq, info[j].bmap->n_ineq, STATUS_ADJ_EQ) ||
+ any(info[i].ineq, info[i].bmap->n_ineq, STATUS_ADJ_INEQ) ||
+ any(info[j].ineq, info[j].bmap->n_ineq, STATUS_ADJ_INEQ))
/* ADJ EQ TOO MANY */
- return 0;
+ return isl_change_none;
- for (k = 0; k < map->p[i]->n_ineq; ++k)
- if (ineq_i[k] == STATUS_ADJ_EQ)
+ for (k = 0; k < info[i].bmap->n_ineq; ++k)
+ if (info[i].ineq[k] == STATUS_ADJ_EQ)
break;
- changed = is_adj_eq_extension(map, i, j, k, tabs,
- eq_i, ineq_i, eq_j, ineq_j);
- if (changed)
- return changed;
-
- if (count(eq_j, 2 * map->p[j]->n_eq, STATUS_ADJ_INEQ) != 1)
- return 0;
+ if (!any_cut) {
+ change = is_adj_eq_extension(i, j, k, info);
+ if (change != isl_change_none)
+ return change;
+ }
- changed = can_wrap_in_facet(map, i, j, k, tabs, eq_i, ineq_i, eq_j, ineq_j);
+ change = can_wrap_in_facet(i, j, k, info, any_cut);
- return changed;
+ return change;
}
/* The two basic maps lie on adjacent hyperplanes. In particular,
@@ -1189,60 +1413,54 @@ static int check_adj_eq(struct isl_map *
* \\ => \\
* \ \|
*
- * We only allow one equality of "i" to be adjacent to an equality of "j"
- * to avoid coalescing
- *
- * [m, n] -> { [x, y] -> [x, 1 + y] : x >= 1 and y >= 1 and
- * x <= 10 and y <= 10;
- * [x, y] -> [1 + x, y] : x >= 1 and x <= 20 and
- * y >= 5 and y <= 15 }
- *
- * to
- *
- * [m, n] -> { [x, y] -> [x2, y2] : x >= 1 and 10y2 <= 20 - x + 10y and
- * 4y2 >= 5 + 3y and 5y2 <= 15 + 4y and
- * y2 <= 1 + x + y - x2 and y2 >= y and
- * y2 >= 1 + x + y - x2 }
+ * If there is more than one equality of "i" adjacent to an equality of "j",
+ * then the result will satisfy one or more equalities that are a linear
+ * combination of these equalities. These will be encoded as pairs
+ * of inequalities in the wrapping constraints and need to be made
+ * explicit.
*/
-static int check_eq_adj_eq(struct isl_map *map, int i, int j,
- struct isl_tab **tabs, int *eq_i, int *ineq_i, int *eq_j, int *ineq_j)
+static enum isl_change check_eq_adj_eq(int i, int j,
+ struct isl_coalesce_info *info)
{
int k;
- int changed = 0;
+ enum isl_change change = isl_change_none;
+ int detect_equalities = 0;
struct isl_wraps wraps;
+ isl_ctx *ctx;
isl_mat *mat;
struct isl_set *set_i = NULL;
struct isl_set *set_j = NULL;
struct isl_vec *bound = NULL;
- unsigned total = isl_basic_map_total_dim(map->p[i]);
+ unsigned total = isl_basic_map_total_dim(info[i].bmap);
- if (count(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_EQ) != 1)
- return 0;
+ if (count(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_ADJ_EQ) != 1)
+ detect_equalities = 1;
- for (k = 0; k < 2 * map->p[i]->n_eq ; ++k)
- if (eq_i[k] == STATUS_ADJ_EQ)
+ for (k = 0; k < 2 * info[i].bmap->n_eq ; ++k)
+ if (info[i].eq[k] == STATUS_ADJ_EQ)
break;
- set_i = set_from_updated_bmap(map->p[i], tabs[i]);
- set_j = set_from_updated_bmap(map->p[j], tabs[j]);
- mat = isl_mat_alloc(map->ctx, 2 * (map->p[i]->n_eq + map->p[j]->n_eq) +
- map->p[i]->n_ineq + map->p[j]->n_ineq,
- 1 + total);
- wraps_init(&wraps, mat, map, i, j, eq_i, ineq_i, eq_j, ineq_j);
- bound = isl_vec_alloc(map->ctx, 1 + total);
+ set_i = set_from_updated_bmap(info[i].bmap, info[i].tab);
+ set_j = set_from_updated_bmap(info[j].bmap, info[j].tab);
+ ctx = isl_basic_map_get_ctx(info[i].bmap);
+ mat = isl_mat_alloc(ctx, 2 * (info[i].bmap->n_eq + info[j].bmap->n_eq) +
+ info[i].bmap->n_ineq + info[j].bmap->n_ineq,
+ 1 + total);
+ wraps_init(&wraps, mat, info, i, j);
+ bound = isl_vec_alloc(ctx, 1 + total);
if (!set_i || !set_j || !wraps.mat || !bound)
goto error;
if (k % 2 == 0)
- isl_seq_neg(bound->el, map->p[i]->eq[k / 2], 1 + total);
+ isl_seq_neg(bound->el, info[i].bmap->eq[k / 2], 1 + total);
else
- isl_seq_cpy(bound->el, map->p[i]->eq[k / 2], 1 + total);
+ isl_seq_cpy(bound->el, info[i].bmap->eq[k / 2], 1 + total);
isl_int_add_ui(bound->el[0], bound->el[0], 1);
isl_seq_cpy(wraps.mat->row[0], bound->el, 1 + total);
wraps.mat->n_row = 1;
- if (add_wraps(&wraps, map->p[j], tabs[j], bound->el, set_i) < 0)
+ if (add_wraps(&wraps, &info[j], bound->el, set_i) < 0)
goto error;
if (!wraps.mat->n_row)
goto unbounded;
@@ -1253,15 +1471,15 @@ static int check_eq_adj_eq(struct isl_ma
isl_seq_cpy(wraps.mat->row[wraps.mat->n_row], bound->el, 1 + total);
wraps.mat->n_row++;
- if (add_wraps(&wraps, map->p[i], tabs[i], bound->el, set_j) < 0)
+ if (add_wraps(&wraps, &info[i], bound->el, set_j) < 0)
goto error;
if (!wraps.mat->n_row)
goto unbounded;
- changed = fuse(map, i, j, tabs, eq_i, ineq_i, eq_j, ineq_j, wraps.mat);
+ change = fuse(i, j, info, wraps.mat, detect_equalities, 0);
if (0) {
-error: changed = -1;
+error: change = isl_change_error;
}
unbounded:
@@ -1270,13 +1488,14 @@ unbounded:
isl_set_free(set_j);
isl_vec_free(bound);
- return changed;
+ return change;
}
/* Check if the union of the given pair of basic maps
* can be represented by a single basic map.
- * If so, replace the pair by the single basic map and return 1.
- * Otherwise, return 0;
+ * If so, replace the pair by the single basic map and return
+ * isl_change_drop_first, isl_change_drop_second or isl_change_fuse.
+ * Otherwise, return isl_change_none.
* The two basic maps are assumed to live in the same local space.
*
* We first check the effect of each constraint of one basic map
@@ -1355,94 +1574,184 @@ unbounded:
* corresponding to the basic maps. When the basic maps are dropped
* or combined, the tableaus are modified accordingly.
*/
-static int coalesce_local_pair(__isl_keep isl_map *map, int i, int j,
- struct isl_tab **tabs)
+static enum isl_change coalesce_local_pair(int i, int j,
+ struct isl_coalesce_info *info)
{
- int changed = 0;
- int *eq_i = NULL;
- int *eq_j = NULL;
- int *ineq_i = NULL;
- int *ineq_j = NULL;
+ enum isl_change change = isl_change_none;
- eq_i = eq_status_in(map->p[i], tabs[j]);
- if (map->p[i]->n_eq && !eq_i)
+ info[i].eq = info[i].ineq = NULL;
+ info[j].eq = info[j].ineq = NULL;
+
+ info[i].eq = eq_status_in(info[i].bmap, info[j].tab);
+ if (info[i].bmap->n_eq && !info[i].eq)
goto error;
- if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ERROR))
+ if (any(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_ERROR))
goto error;
- if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_SEPARATE))
+ if (any(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_SEPARATE))
goto done;
- eq_j = eq_status_in(map->p[j], tabs[i]);
- if (map->p[j]->n_eq && !eq_j)
+ info[j].eq = eq_status_in(info[j].bmap, info[i].tab);
+ if (info[j].bmap->n_eq && !info[j].eq)
goto error;
- if (any(eq_j, 2 * map->p[j]->n_eq, STATUS_ERROR))
+ if (any(info[j].eq, 2 * info[j].bmap->n_eq, STATUS_ERROR))
goto error;
- if (any(eq_j, 2 * map->p[j]->n_eq, STATUS_SEPARATE))
+ if (any(info[j].eq, 2 * info[j].bmap->n_eq, STATUS_SEPARATE))
goto done;
- ineq_i = ineq_status_in(map->p[i], tabs[i], tabs[j]);
- if (map->p[i]->n_ineq && !ineq_i)
+ info[i].ineq = ineq_status_in(info[i].bmap, info[i].tab, info[j].tab);
+ if (info[i].bmap->n_ineq && !info[i].ineq)
goto error;
- if (any(ineq_i, map->p[i]->n_ineq, STATUS_ERROR))
+ if (any(info[i].ineq, info[i].bmap->n_ineq, STATUS_ERROR))
goto error;
- if (any(ineq_i, map->p[i]->n_ineq, STATUS_SEPARATE))
+ if (any(info[i].ineq, info[i].bmap->n_ineq, STATUS_SEPARATE))
goto done;
- ineq_j = ineq_status_in(map->p[j], tabs[j], tabs[i]);
- if (map->p[j]->n_ineq && !ineq_j)
+ info[j].ineq = ineq_status_in(info[j].bmap, info[j].tab, info[i].tab);
+ if (info[j].bmap->n_ineq && !info[j].ineq)
goto error;
- if (any(ineq_j, map->p[j]->n_ineq, STATUS_ERROR))
+ if (any(info[j].ineq, info[j].bmap->n_ineq, STATUS_ERROR))
goto error;
- if (any(ineq_j, map->p[j]->n_ineq, STATUS_SEPARATE))
+ if (any(info[j].ineq, info[j].bmap->n_ineq, STATUS_SEPARATE))
goto done;
- if (all(eq_i, 2 * map->p[i]->n_eq, STATUS_VALID) &&
- all(ineq_i, map->p[i]->n_ineq, STATUS_VALID)) {
- drop(map, j, tabs);
- changed = 1;
- } else if (all(eq_j, 2 * map->p[j]->n_eq, STATUS_VALID) &&
- all(ineq_j, map->p[j]->n_ineq, STATUS_VALID)) {
- drop(map, i, tabs);
- changed = 1;
- } else if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_EQ)) {
- changed = check_eq_adj_eq(map, i, j, tabs,
- eq_i, ineq_i, eq_j, ineq_j);
- } else if (any(eq_j, 2 * map->p[j]->n_eq, STATUS_ADJ_EQ)) {
- changed = check_eq_adj_eq(map, j, i, tabs,
- eq_j, ineq_j, eq_i, ineq_i);
- } else if (any(eq_i, 2 * map->p[i]->n_eq, STATUS_ADJ_INEQ) ||
- any(eq_j, 2 * map->p[j]->n_eq, STATUS_ADJ_INEQ)) {
- changed = check_adj_eq(map, i, j, tabs,
- eq_i, ineq_i, eq_j, ineq_j);
- } else if (any(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_EQ) ||
- any(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_EQ)) {
+ if (all(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_VALID) &&
+ all(info[i].ineq, info[i].bmap->n_ineq, STATUS_VALID)) {
+ drop(&info[j]);
+ change = isl_change_drop_second;
+ } else if (all(info[j].eq, 2 * info[j].bmap->n_eq, STATUS_VALID) &&
+ all(info[j].ineq, info[j].bmap->n_ineq, STATUS_VALID)) {
+ drop(&info[i]);
+ change = isl_change_drop_first;
+ } else if (any(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_ADJ_EQ)) {
+ change = check_eq_adj_eq(i, j, info);
+ } else if (any(info[j].eq, 2 * info[j].bmap->n_eq, STATUS_ADJ_EQ)) {
+ change = check_eq_adj_eq(j, i, info);
+ } else if (any(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_ADJ_INEQ) ||
+ any(info[j].eq, 2 * info[j].bmap->n_eq, STATUS_ADJ_INEQ)) {
+ change = check_adj_eq(i, j, info);
+ } else if (any(info[i].ineq, info[i].bmap->n_ineq, STATUS_ADJ_EQ) ||
+ any(info[j].ineq, info[j].bmap->n_ineq, STATUS_ADJ_EQ)) {
/* Can't happen */
/* BAD ADJ INEQ */
- } else if (any(ineq_i, map->p[i]->n_ineq, STATUS_ADJ_INEQ) ||
- any(ineq_j, map->p[j]->n_ineq, STATUS_ADJ_INEQ)) {
- changed = check_adj_ineq(map, i, j, tabs,
- eq_i, ineq_i, eq_j, ineq_j);
+ } else if (any(info[i].ineq, info[i].bmap->n_ineq, STATUS_ADJ_INEQ) ||
+ any(info[j].ineq, info[j].bmap->n_ineq, STATUS_ADJ_INEQ)) {
+ change = check_adj_ineq(i, j, info);
} else {
- if (!any(eq_i, 2 * map->p[i]->n_eq, STATUS_CUT) &&
- !any(eq_j, 2 * map->p[j]->n_eq, STATUS_CUT))
- changed = check_facets(map, i, j, tabs, ineq_i, ineq_j);
- if (!changed)
- changed = check_wrap(map, i, j, tabs,
- eq_i, ineq_i, eq_j, ineq_j);
+ if (!any(info[i].eq, 2 * info[i].bmap->n_eq, STATUS_CUT) &&
+ !any(info[j].eq, 2 * info[j].bmap->n_eq, STATUS_CUT))
+ change = check_facets(i, j, info);
+ if (change == isl_change_none)
+ change = check_wrap(i, j, info);
}
done:
- free(eq_i);
- free(eq_j);
- free(ineq_i);
- free(ineq_j);
- return changed;
+ free(info[i].eq);
+ free(info[j].eq);
+ free(info[i].ineq);
+ free(info[j].ineq);
+ return change;
error:
- free(eq_i);
- free(eq_j);
- free(ineq_i);
- free(ineq_j);
- return -1;
+ free(info[i].eq);
+ free(info[j].eq);
+ free(info[i].ineq);
+ free(info[j].ineq);
+ return isl_change_error;
+}
+
+/* Shift the integer division at position "div" of the basic map
+ * represented by "info" by "shift".
+ *
+ * That is, if the integer division has the form
+ *
+ * floor(f(x)/d)
+ *
+ * then replace it by
+ *
+ * floor((f(x) + shift * d)/d) - shift
+ */
+static int shift_div(struct isl_coalesce_info *info, int div, isl_int shift)
+{
+ unsigned total;
+
+ info->bmap = isl_basic_map_shift_div(info->bmap, div, shift);
+ if (!info->bmap)
+ return -1;
+
+ total = isl_basic_map_dim(info->bmap, isl_dim_all);
+ total -= isl_basic_map_dim(info->bmap, isl_dim_div);
+ if (isl_tab_shift_var(info->tab, total + div, shift) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Check if some of the divs in the basic map represented by "info1"
+ * are shifts of the corresponding divs in the basic map represented
+ * by "info2". If so, align them with those of "info2".
+ * Only do this if "info1" and "info2" have the same number
+ * of integer divisions.
+ *
+ * An integer division is considered to be a shift of another integer
+ * division if one is equal to the other plus a constant.
+ *
+ * In particular, for each pair of integer divisions, if both are known,
+ * have identical coefficients (apart from the constant term) and
+ * if the difference between the constant terms (taking into account
+ * the denominator) is an integer, then move the difference outside.
+ * That is, if one integer division is of the form
+ *
+ * floor((f(x) + c_1)/d)
+ *
+ * while the other is of the form
+ *
+ * floor((f(x) + c_2)/d)
+ *
+ * and n = (c_2 - c_1)/d is an integer, then replace the first
+ * integer division by
+ *
+ * floor((f(x) + c_1 + n * d)/d) - n = floor((f(x) + c_2)/d) - n
+ */
+static int harmonize_divs(struct isl_coalesce_info *info1,
+ struct isl_coalesce_info *info2)
+{
+ int i;
+ int total;
+
+ if (!info1->bmap || !info2->bmap)
+ return -1;
+
+ if (info1->bmap->n_div != info2->bmap->n_div)
+ return 0;
+ if (info1->bmap->n_div == 0)
+ return 0;
+
+ total = isl_basic_map_total_dim(info1->bmap);
+ for (i = 0; i < info1->bmap->n_div; ++i) {
+ isl_int d;
+ int r = 0;
+
+ if (isl_int_is_zero(info1->bmap->div[i][0]) ||
+ isl_int_is_zero(info2->bmap->div[i][0]))
+ continue;
+ if (isl_int_ne(info1->bmap->div[i][0], info2->bmap->div[i][0]))
+ continue;
+ if (isl_int_eq(info1->bmap->div[i][1], info2->bmap->div[i][1]))
+ continue;
+ if (!isl_seq_eq(info1->bmap->div[i] + 2,
+ info2->bmap->div[i] + 2, total))
+ continue;
+ isl_int_init(d);
+ isl_int_sub(d, info2->bmap->div[i][1], info1->bmap->div[i][1]);
+ if (isl_int_is_divisible_by(d, info1->bmap->div[i][0])) {
+ isl_int_divexact(d, d, info1->bmap->div[i][0]);
+ r = shift_div(info1, i, d);
+ }
+ isl_int_clear(d);
+ if (r < 0)
+ return -1;
+ }
+
+ return 0;
}
/* Do the two basic maps live in the same local space, i.e.,
@@ -1480,29 +1789,26 @@ static int same_divs(__isl_keep isl_basi
return 1;
}
-/* Given two basic maps "i" and "j", where the divs of "i" form a subset
- * of those of "j", check if basic map "j" is a subset of basic map "i"
- * and, if so, drop basic map "j".
- *
- * We first expand the divs of basic map "i" to match those of basic map "j",
- * using the divs and expansion computed by the caller.
- * Then we check if all constraints of the expanded "i" are valid for "j".
+/* Does "bmap" contain the basic map represented by the tableau "tab"
+ * after expanding the divs of "bmap" to match those of "tab"?
+ * The expansion is performed using the divs "div" and expansion "exp"
+ * computed by the caller.
+ * Then we check if all constraints of the expanded "bmap" are valid for "tab".
*/
-static int coalesce_subset(__isl_keep isl_map *map, int i, int j,
- struct isl_tab **tabs, __isl_keep isl_mat *div, int *exp)
+static int contains_with_expanded_divs(__isl_keep isl_basic_map *bmap,
+ struct isl_tab *tab, __isl_keep isl_mat *div, int *exp)
{
- isl_basic_map *bmap;
- int changed = 0;
+ int superset = 0;
int *eq_i = NULL;
int *ineq_i = NULL;
- bmap = isl_basic_map_copy(map->p[i]);
+ bmap = isl_basic_map_copy(bmap);
bmap = isl_basic_set_expand_divs(bmap, isl_mat_copy(div), exp);
if (!bmap)
goto error;
- eq_i = eq_status_in(bmap, tabs[j]);
+ eq_i = eq_status_in(bmap, tab);
if (bmap->n_eq && !eq_i)
goto error;
if (any(eq_i, 2 * bmap->n_eq, STATUS_ERROR))
@@ -1510,7 +1816,7 @@ static int coalesce_subset(__isl_keep is
if (any(eq_i, 2 * bmap->n_eq, STATUS_SEPARATE))
goto done;
- ineq_i = ineq_status_in(bmap, NULL, tabs[j]);
+ ineq_i = ineq_status_in(bmap, NULL, tab);
if (bmap->n_ineq && !ineq_i)
goto error;
if (any(ineq_i, bmap->n_ineq, STATUS_ERROR))
@@ -1518,17 +1824,15 @@ static int coalesce_subset(__isl_keep is
if (any(ineq_i, bmap->n_ineq, STATUS_SEPARATE))
goto done;
- if (all(eq_i, 2 * map->p[i]->n_eq, STATUS_VALID) &&
- all(ineq_i, map->p[i]->n_ineq, STATUS_VALID)) {
- drop(map, j, tabs);
- changed = 1;
- }
+ if (all(eq_i, 2 * bmap->n_eq, STATUS_VALID) &&
+ all(ineq_i, bmap->n_ineq, STATUS_VALID))
+ superset = 1;
done:
isl_basic_map_free(bmap);
free(eq_i);
free(ineq_i);
- return 0;
+ return superset;
error:
isl_basic_map_free(bmap);
free(eq_i);
@@ -1536,20 +1840,17 @@ error:
return -1;
}
-/* Check if the basic map "j" is a subset of basic map "i",
- * assuming that "i" has fewer divs that "j".
- * If not, then we change the order.
- *
- * If the two basic maps have the same number of divs, then
- * they must necessarily be different. Otherwise, we would have
- * called coalesce_local_pair. We therefore don't try anything
- * in this case.
- *
- * We first check if the divs of "i" are all known and form a subset
- * of those of "j". If so, we pass control over to coalesce_subset.
+/* Does "bmap_i" contain the basic map represented by "info_j"
+ * after aligning the divs of "bmap_i" to those of "info_j".
+ * Note that this can only succeed if the number of divs of "bmap_i"
+ * is smaller than (or equal to) the number of divs of "info_j".
+ *
+ * We first check if the divs of "bmap_i" are all known and form a subset
+ * of those of "bmap_j". If so, we pass control over to
+ * contains_with_expanded_divs.
*/
-static int check_coalesce_subset(__isl_keep isl_map *map, int i, int j,
- struct isl_tab **tabs)
+static int contains_after_aligning_divs(__isl_keep isl_basic_map *bmap_i,
+ struct isl_coalesce_info *info_j)
{
int known;
isl_mat *div_i, *div_j, *div;
@@ -1558,19 +1859,14 @@ static int check_coalesce_subset(__isl_k
isl_ctx *ctx;
int subset;
- if (map->p[i]->n_div == map->p[j]->n_div)
- return 0;
- if (map->p[j]->n_div < map->p[i]->n_div)
- return check_coalesce_subset(map, j, i, tabs);
-
- known = isl_basic_map_divs_known(map->p[i]);
+ known = isl_basic_map_divs_known(bmap_i);
if (known < 0 || !known)
return known;
- ctx = isl_map_get_ctx(map);
+ ctx = isl_basic_map_get_ctx(bmap_i);
- div_i = isl_basic_map_get_divs(map->p[i]);
- div_j = isl_basic_map_get_divs(map->p[j]);
+ div_i = isl_basic_map_get_divs(bmap_i);
+ div_j = isl_basic_map_get_divs(info_j->bmap);
if (!div_i || !div_j)
goto error;
@@ -1585,7 +1881,8 @@ static int check_coalesce_subset(__isl_k
goto error;
if (div->n_row == div_j->n_row)
- subset = coalesce_subset(map, i, j, tabs, div, exp1);
+ subset = contains_with_expanded_divs(bmap_i,
+ info_j->tab, div, exp1);
else
subset = 0;
@@ -1606,53 +1903,682 @@ error:
return -1;
}
+/* Check if the basic map "j" is a subset of basic map "i",
+ * if "i" has fewer divs that "j".
+ * If so, remove basic map "j".
+ *
+ * If the two basic maps have the same number of divs, then
+ * they must necessarily be different. Otherwise, we would have
+ * called coalesce_local_pair. We therefore don't try anything
+ * in this case.
+ */
+static int coalesced_subset(int i, int j, struct isl_coalesce_info *info)
+{
+ int superset;
+
+ if (info[i].bmap->n_div >= info[j].bmap->n_div)
+ return 0;
+
+ superset = contains_after_aligning_divs(info[i].bmap, &info[j]);
+ if (superset < 0)
+ return -1;
+ if (superset)
+ drop(&info[j]);
+
+ return superset;
+}
+
+/* Check if basic map "j" is a subset of basic map "i" after
+ * exploiting the extra equalities of "j" to simplify the divs of "i".
+ * If so, remove basic map "j".
+ *
+ * If "j" does not have any equalities or if they are the same
+ * as those of "i", then we cannot exploit them to simplify the divs.
+ * Similarly, if there are no divs in "i", then they cannot be simplified.
+ * If, on the other hand, the affine hulls of "i" and "j" do not intersect,
+ * then "j" cannot be a subset of "i".
+ *
+ * Otherwise, we intersect "i" with the affine hull of "j" and then
+ * check if "j" is a subset of the result after aligning the divs.
+ * If so, then "j" is definitely a subset of "i" and can be removed.
+ * Note that if after intersection with the affine hull of "j".
+ * "i" still has more divs than "j", then there is no way we can
+ * align the divs of "i" to those of "j".
+ */
+static int coalesced_subset_with_equalities(int i, int j,
+ struct isl_coalesce_info *info)
+{
+ isl_basic_map *hull_i, *hull_j, *bmap_i;
+ int equal, empty, subset;
+
+ if (info[j].bmap->n_eq == 0)
+ return 0;
+ if (info[i].bmap->n_div == 0)
+ return 0;
+
+ hull_i = isl_basic_map_copy(info[i].bmap);
+ hull_i = isl_basic_map_plain_affine_hull(hull_i);
+ hull_j = isl_basic_map_copy(info[j].bmap);
+ hull_j = isl_basic_map_plain_affine_hull(hull_j);
+
+ hull_j = isl_basic_map_intersect(hull_j, isl_basic_map_copy(hull_i));
+ equal = isl_basic_map_plain_is_equal(hull_i, hull_j);
+ empty = isl_basic_map_plain_is_empty(hull_j);
+ isl_basic_map_free(hull_i);
+
+ if (equal < 0 || equal || empty < 0 || empty) {
+ isl_basic_map_free(hull_j);
+ return equal < 0 || empty < 0 ? -1 : 0;
+ }
+
+ bmap_i = isl_basic_map_copy(info[i].bmap);
+ bmap_i = isl_basic_map_intersect(bmap_i, hull_j);
+ if (!bmap_i)
+ return -1;
+
+ if (bmap_i->n_div > info[j].bmap->n_div) {
+ isl_basic_map_free(bmap_i);
+ return 0;
+ }
+
+ subset = contains_after_aligning_divs(bmap_i, &info[j]);
+
+ isl_basic_map_free(bmap_i);
+
+ if (subset < 0)
+ return -1;
+ if (subset)
+ drop(&info[j]);
+
+ return subset;
+}
+
+/* Check if one of the basic maps is a subset of the other and, if so,
+ * drop the subset.
+ * Note that we only perform any test if the number of divs is different
+ * in the two basic maps. In case the number of divs is the same,
+ * we have already established that the divs are different
+ * in the two basic maps.
+ * In particular, if the number of divs of basic map i is smaller than
+ * the number of divs of basic map j, then we check if j is a subset of i
+ * and vice versa.
+ */
+static enum isl_change check_coalesce_subset(int i, int j,
+ struct isl_coalesce_info *info)
+{
+ int changed;
+
+ changed = coalesced_subset(i, j, info);
+ if (changed < 0 || changed)
+ return changed < 0 ? isl_change_error : isl_change_drop_second;
+
+ changed = coalesced_subset(j, i, info);
+ if (changed < 0 || changed)
+ return changed < 0 ? isl_change_error : isl_change_drop_first;
+
+ changed = coalesced_subset_with_equalities(i, j, info);
+ if (changed < 0 || changed)
+ return changed < 0 ? isl_change_error : isl_change_drop_second;
+
+ changed = coalesced_subset_with_equalities(j, i, info);
+ if (changed < 0 || changed)
+ return changed < 0 ? isl_change_error : isl_change_drop_first;
+
+ return isl_change_none;
+}
+
+/* Does "bmap" involve any divs that themselves refer to divs?
+ */
+static int has_nested_div(__isl_keep isl_basic_map *bmap)
+{
+ int i;
+ unsigned total;
+ unsigned n_div;
+
+ total = isl_basic_map_dim(bmap, isl_dim_all);
+ n_div = isl_basic_map_dim(bmap, isl_dim_div);
+ total -= n_div;
+
+ for (i = 0; i < n_div; ++i)
+ if (isl_seq_first_non_zero(bmap->div[i] + 2 + total,
+ n_div) != -1)
+ return 1;
+
+ return 0;
+}
+
+/* Return a list of affine expressions, one for each integer division
+ * in "bmap_i". For each integer division that also appears in "bmap_j",
+ * the affine expression is set to NaN. The number of NaNs in the list
+ * is equal to the number of integer divisions in "bmap_j".
+ * For the other integer divisions of "bmap_i", the corresponding
+ * element in the list is a purely affine expression equal to the integer
+ * division in "hull".
+ * If no such list can be constructed, then the number of elements
+ * in the returned list is smaller than the number of integer divisions
+ * in "bmap_i".
+ */
+static __isl_give isl_aff_list *set_up_substitutions(
+ __isl_keep isl_basic_map *bmap_i, __isl_keep isl_basic_map *bmap_j,
+ __isl_take isl_basic_map *hull)
+{
+ unsigned n_div_i, n_div_j, total;
+ isl_ctx *ctx;
+ isl_local_space *ls;
+ isl_basic_set *wrap_hull;
+ isl_aff *aff_nan;
+ isl_aff_list *list;
+ int i, j;
+
+ if (!hull)
+ return NULL;
+
+ ctx = isl_basic_map_get_ctx(hull);
+
+ n_div_i = isl_basic_map_dim(bmap_i, isl_dim_div);
+ n_div_j = isl_basic_map_dim(bmap_j, isl_dim_div);
+ total = isl_basic_map_total_dim(bmap_i) - n_div_i;
+
+ ls = isl_basic_map_get_local_space(bmap_i);
+ ls = isl_local_space_wrap(ls);
+ wrap_hull = isl_basic_map_wrap(hull);
+
+ aff_nan = isl_aff_nan_on_domain(isl_local_space_copy(ls));
+ list = isl_aff_list_alloc(ctx, n_div_i);
+
+ j = 0;
+ for (i = 0; i < n_div_i; ++i) {
+ isl_aff *aff;
+
+ if (j < n_div_j &&
+ isl_seq_eq(bmap_i->div[i], bmap_j->div[j], 2 + total)) {
+ ++j;
+ list = isl_aff_list_add(list, isl_aff_copy(aff_nan));
+ continue;
+ }
+ if (n_div_i - i <= n_div_j - j)
+ break;
+
+ aff = isl_local_space_get_div(ls, i);
+ aff = isl_aff_substitute_equalities(aff,
+ isl_basic_set_copy(wrap_hull));
+ aff = isl_aff_floor(aff);
+ if (!aff)
+ goto error;
+ if (isl_aff_dim(aff, isl_dim_div) != 0) {
+ isl_aff_free(aff);
+ break;
+ }
+
+ list = isl_aff_list_add(list, aff);
+ }
+
+ isl_aff_free(aff_nan);
+ isl_local_space_free(ls);
+ isl_basic_set_free(wrap_hull);
+
+ return list;
+error:
+ isl_local_space_free(ls);
+ isl_basic_set_free(wrap_hull);
+ isl_aff_list_free(list);
+ return NULL;
+}
+
+/* Add variables to "tab" corresponding to the elements in "list"
+ * that are not set to NaN.
+ * "dim" is the offset in the variables of "tab" where we should
+ * start considering the elements in "list".
+ * When this function returns, the total number of variables in "tab"
+ * is equal to "dim" plus the number of elements in "list".
+ */
+static int add_sub_vars(struct isl_tab *tab, __isl_keep isl_aff_list *list,
+ int dim)
+{
+ int i, n;
+
+ n = isl_aff_list_n_aff(list);
+ for (i = 0; i < n; ++i) {
+ int is_nan;
+ isl_aff *aff;
+
+ aff = isl_aff_list_get_aff(list, i);
+ is_nan = isl_aff_is_nan(aff);
+ isl_aff_free(aff);
+ if (is_nan < 0)
+ return -1;
+
+ if (!is_nan && isl_tab_insert_var(tab, dim + i) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* For each element in "list" that is not set to NaN, fix the corresponding
+ * variable in "tab" to the purely affine expression defined by the element.
+ * "dim" is the offset in the variables of "tab" where we should
+ * start considering the elements in "list".
+ */
+static int add_sub_equalities(struct isl_tab *tab,
+ __isl_keep isl_aff_list *list, int dim)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_vec *sub;
+ isl_aff *aff;
+
+ n = isl_aff_list_n_aff(list);
+
+ ctx = isl_tab_get_ctx(tab);
+ sub = isl_vec_alloc(ctx, 1 + dim + n);
+ if (!sub)
+ return -1;
+ isl_seq_clr(sub->el + 1 + dim, n);
+
+ for (i = 0; i < n; ++i) {
+ aff = isl_aff_list_get_aff(list, i);
+ if (!aff)
+ goto error;
+ if (isl_aff_is_nan(aff)) {
+ isl_aff_free(aff);
+ continue;
+ }
+ isl_seq_cpy(sub->el, aff->v->el + 1, 1 + dim);
+ isl_int_neg(sub->el[1 + dim + i], aff->v->el[0]);
+ if (isl_tab_add_eq(tab, sub->el) < 0)
+ goto error;
+ isl_int_set_si(sub->el[1 + dim + i], 0);
+ isl_aff_free(aff);
+ }
+
+ isl_vec_free(sub);
+ return 0;
+error:
+ isl_aff_free(aff);
+ isl_vec_free(sub);
+ return -1;
+}
+
+/* Add variables to info->tab corresponding to the elements in "list"
+ * that are not set to NaN. The value of the added variable
+ * is fixed to the purely affine expression defined by the element.
+ * "dim" is the offset in the variables of info->tab where we should
+ * start considering the elements in "list".
+ * When this function returns, the total number of variables in info->tab
+ * is equal to "dim" plus the number of elements in "list".
+ * Additionally, add the div constraints that have been added info->bmap
+ * after the tableau was constructed to info->tab. These constraints
+ * start at position "n_ineq" in info->bmap.
+ * The constraints need to be added to the tableau before
+ * the equalities assigning the purely affine expression
+ * because the position needs to match that in info->bmap.
+ * They are frozen because the corresponding added equality is a consequence
+ * of the two div constraints and the other equalities, meaning that
+ * the div constraints would otherwise get marked as redundant,
+ * while they are only redundant with respect to the extra equalities
+ * added to the tableau, which do not appear explicitly in the basic map.
+ */
+static int add_subs(struct isl_coalesce_info *info,
+ __isl_keep isl_aff_list *list, int dim, int n_ineq)
+{
+ int i, extra_var, extra_con;
+ int n;
+ unsigned n_eq = info->bmap->n_eq;
+
+ if (!list)
+ return -1;
+
+ n = isl_aff_list_n_aff(list);
+ extra_var = n - (info->tab->n_var - dim);
+ extra_con = info->bmap->n_ineq - n_ineq;
+
+ if (isl_tab_extend_vars(info->tab, extra_var) < 0)
+ return -1;
+ if (isl_tab_extend_cons(info->tab, extra_con + 2 * extra_var) < 0)
+ return -1;
+ if (add_sub_vars(info->tab, list, dim) < 0)
+ return -1;
+
+ for (i = n_ineq; i < info->bmap->n_ineq; ++i) {
+ if (isl_tab_add_ineq(info->tab, info->bmap->ineq[i]) < 0)
+ return -1;
+ if (isl_tab_freeze_constraint(info->tab, n_eq + i) < 0)
+ return -1;
+ }
+
+ return add_sub_equalities(info->tab, list, dim);
+}
+
+/* Coalesce basic map "j" into basic map "i" after adding the extra integer
+ * divisions in "i" but not in "j" to basic map "j", with values
+ * specified by "list". The total number of elements in "list"
+ * is equal to the number of integer divisions in "i", while the number
+ * of NaN elements in the list is equal to the number of integer divisions
+ * in "j".
+ * Adding extra integer divisions to "j" through isl_basic_map_align_divs
+ * also adds the corresponding div constraints. These need to be added
+ * to the corresponding tableau as well in add_subs to maintain consistency.
+ *
+ * If no coalescing can be performed, then we need to revert basic map "j"
+ * to its original state. We do the same if basic map "i" gets dropped
+ * during the coalescing, even though this should not happen in practice
+ * since we have already checked for "j" being a subset of "i"
+ * before we reach this stage.
+ */
+static enum isl_change coalesce_with_subs(int i, int j,
+ struct isl_coalesce_info *info, __isl_keep isl_aff_list *list)
+{
+ isl_basic_map *bmap_j;
+ struct isl_tab_undo *snap;
+ unsigned dim;
+ enum isl_change change;
+ int n_ineq;
+
+ bmap_j = isl_basic_map_copy(info[j].bmap);
+ n_ineq = info[j].bmap->n_ineq;
+ info[j].bmap = isl_basic_map_align_divs(info[j].bmap, info[i].bmap);
+ if (!info[j].bmap)
+ goto error;
+
+ snap = isl_tab_snap(info[j].tab);
+
+ dim = isl_basic_map_dim(bmap_j, isl_dim_all);
+ dim -= isl_basic_map_dim(bmap_j, isl_dim_div);
+ if (add_subs(&info[j], list, dim, n_ineq) < 0)
+ goto error;
+
+ change = coalesce_local_pair(i, j, info);
+ if (change != isl_change_none && change != isl_change_drop_first) {
+ isl_basic_map_free(bmap_j);
+ } else {
+ isl_basic_map_free(info[j].bmap);
+ info[j].bmap = bmap_j;
+
+ if (isl_tab_rollback(info[j].tab, snap) < 0)
+ return isl_change_error;
+ }
+
+ return change;
+error:
+ isl_basic_map_free(bmap_j);
+ return isl_change_error;
+}
+
+/* Check if we can coalesce basic map "j" into basic map "i" after copying
+ * those extra integer divisions in "i" that can be simplified away
+ * using the extra equalities in "j".
+ * All divs are assumed to be known and not contain any nested divs.
+ *
+ * We first check if there are any extra equalities in "j" that we
+ * can exploit. Then we check if every integer division in "i"
+ * either already appears in "j" or can be simplified using the
+ * extra equalities to a purely affine expression.
+ * If these tests succeed, then we try to coalesce the two basic maps
+ * by introducing extra dimensions in "j" corresponding to
+ * the extra integer divsisions "i" fixed to the corresponding
+ * purely affine expression.
+ */
+static enum isl_change check_coalesce_into_eq(int i, int j,
+ struct isl_coalesce_info *info)
+{
+ unsigned n_div_i, n_div_j;
+ isl_basic_map *hull_i, *hull_j;
+ int equal, empty;
+ isl_aff_list *list;
+ enum isl_change change;
+
+ n_div_i = isl_basic_map_dim(info[i].bmap, isl_dim_div);
+ n_div_j = isl_basic_map_dim(info[j].bmap, isl_dim_div);
+ if (n_div_i <= n_div_j)
+ return isl_change_none;
+ if (info[j].bmap->n_eq == 0)
+ return isl_change_none;
+
+ hull_i = isl_basic_map_copy(info[i].bmap);
+ hull_i = isl_basic_map_plain_affine_hull(hull_i);
+ hull_j = isl_basic_map_copy(info[j].bmap);
+ hull_j = isl_basic_map_plain_affine_hull(hull_j);
+
+ hull_j = isl_basic_map_intersect(hull_j, isl_basic_map_copy(hull_i));
+ equal = isl_basic_map_plain_is_equal(hull_i, hull_j);
+ empty = isl_basic_map_plain_is_empty(hull_j);
+ isl_basic_map_free(hull_i);
+
+ if (equal < 0 || empty < 0)
+ goto error;
+ if (equal || empty) {
+ isl_basic_map_free(hull_j);
+ return isl_change_none;
+ }
+
+ list = set_up_substitutions(info[i].bmap, info[j].bmap, hull_j);
+ if (!list)
+ goto error;
+ if (isl_aff_list_n_aff(list) < n_div_i)
+ change = isl_change_none;
+ else
+ change = coalesce_with_subs(i, j, info, list);
+
+ isl_aff_list_free(list);
+
+ return change;
+error:
+ isl_basic_map_free(hull_j);
+ return isl_change_error;
+}
+
+/* Check if we can coalesce basic maps "i" and "j" after copying
+ * those extra integer divisions in one of the basic maps that can
+ * be simplified away using the extra equalities in the other basic map.
+ * We require all divs to be known in both basic maps.
+ * Furthermore, to simplify the comparison of div expressions,
+ * we do not allow any nested integer divisions.
+ */
+static enum isl_change check_coalesce_eq(int i, int j,
+ struct isl_coalesce_info *info)
+{
+ int known, nested;
+ enum isl_change change;
+
+ known = isl_basic_map_divs_known(info[i].bmap);
+ if (known < 0 || !known)
+ return known < 0 ? isl_change_error : isl_change_none;
+ known = isl_basic_map_divs_known(info[j].bmap);
+ if (known < 0 || !known)
+ return known < 0 ? isl_change_error : isl_change_none;
+ nested = has_nested_div(info[i].bmap);
+ if (nested < 0 || nested)
+ return nested < 0 ? isl_change_error : isl_change_none;
+ nested = has_nested_div(info[j].bmap);
+ if (nested < 0 || nested)
+ return nested < 0 ? isl_change_error : isl_change_none;
+
+ change = check_coalesce_into_eq(i, j, info);
+ if (change != isl_change_none)
+ return change;
+ change = check_coalesce_into_eq(j, i, info);
+ if (change != isl_change_none)
+ return invert_change(change);
+
+ return isl_change_none;
+}
+
/* Check if the union of the given pair of basic maps
* can be represented by a single basic map.
- * If so, replace the pair by the single basic map and return 1.
- * Otherwise, return 0;
- *
- * We first check if the two basic maps live in the same local space.
- * If so, we do the complete check. Otherwise, we check if one is
- * an obvious subset of the other.
+ * If so, replace the pair by the single basic map and return
+ * isl_change_drop_first, isl_change_drop_second or isl_change_fuse.
+ * Otherwise, return isl_change_none.
+ *
+ * We first check if the two basic maps live in the same local space,
+ * after aligning the divs that differ by only an integer constant.
+ * If so, we do the complete check. Otherwise, we check if they have
+ * the same number of integer divisions and can be coalesced, if one is
+ * an obvious subset of the other or if the extra integer divisions
+ * of one basic map can be simplified away using the extra equalities
+ * of the other basic map.
*/
-static int coalesce_pair(__isl_keep isl_map *map, int i, int j,
- struct isl_tab **tabs)
+static enum isl_change coalesce_pair(int i, int j,
+ struct isl_coalesce_info *info)
{
int same;
+ enum isl_change change;
- same = same_divs(map->p[i], map->p[j]);
+ if (harmonize_divs(&info[i], &info[j]) < 0)
+ return isl_change_error;
+ same = same_divs(info[i].bmap, info[j].bmap);
if (same < 0)
- return -1;
+ return isl_change_error;
if (same)
- return coalesce_local_pair(map, i, j, tabs);
+ return coalesce_local_pair(i, j, info);
+
+ if (info[i].bmap->n_div == info[j].bmap->n_div) {
+ change = coalesce_local_pair(i, j, info);
+ if (change != isl_change_none)
+ return change;
+ }
+
+ change = check_coalesce_subset(i, j, info);
+ if (change != isl_change_none)
+ return change;
+
+ return check_coalesce_eq(i, j, info);
+}
- return check_coalesce_subset(map, i, j, tabs);
+/* Return the maximum of "a" and "b".
+ */
+static inline int max(int a, int b)
+{
+ return a > b ? a : b;
}
-static struct isl_map *coalesce(struct isl_map *map, struct isl_tab **tabs)
+/* Pairwise coalesce the basic maps in the range [start1, end1[ of "info"
+ * with those in the range [start2, end2[, skipping basic maps
+ * that have been removed (either before or within this function).
+ *
+ * For each basic map i in the first range, we check if it can be coalesced
+ * with respect to any previously considered basic map j in the second range.
+ * If i gets dropped (because it was a subset of some j), then
+ * we can move on to the next basic map.
+ * If j gets dropped, we need to continue checking against the other
+ * previously considered basic maps.
+ * If the two basic maps got fused, then we recheck the fused basic map
+ * against the previously considered basic maps, starting at i + 1
+ * (even if start2 is greater than i + 1).
+ */
+static int coalesce_range(isl_ctx *ctx, struct isl_coalesce_info *info,
+ int start1, int end1, int start2, int end2)
{
int i, j;
- for (i = map->n - 2; i >= 0; --i)
-restart:
- for (j = i + 1; j < map->n; ++j) {
- int changed;
- changed = coalesce_pair(map, i, j, tabs);
- if (changed < 0)
- goto error;
- if (changed)
- goto restart;
+ for (i = end1 - 1; i >= start1; --i) {
+ if (info[i].removed)
+ continue;
+ for (j = max(i + 1, start2); j < end2; ++j) {
+ enum isl_change changed;
+
+ if (info[j].removed)
+ continue;
+ if (info[i].removed)
+ isl_die(ctx, isl_error_internal,
+ "basic map unexpectedly removed",
+ return -1);
+ changed = coalesce_pair(i, j, info);
+ switch (changed) {
+ case isl_change_error:
+ return -1;
+ case isl_change_none:
+ case isl_change_drop_second:
+ continue;
+ case isl_change_drop_first:
+ j = end2;
+ break;
+ case isl_change_fuse:
+ j = i;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* Pairwise coalesce the basic maps described by the "n" elements of "info".
+ *
+ * We consider groups of basic maps that live in the same apparent
+ * affine hull and we first coalesce within such a group before we
+ * coalesce the elements in the group with elements of previously
+ * considered groups. If a fuse happens during the second phase,
+ * then we also reconsider the elements within the group.
+ */
+static int coalesce(isl_ctx *ctx, int n, struct isl_coalesce_info *info)
+{
+ int start, end;
+
+ for (end = n; end > 0; end = start) {
+ start = end - 1;
+ while (start >= 1 &&
+ info[start - 1].hull_hash == info[start].hull_hash)
+ start--;
+ if (coalesce_range(ctx, info, start, end, start, end) < 0)
+ return -1;
+ if (coalesce_range(ctx, info, start, end, end, n) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Update the basic maps in "map" based on the information in "info".
+ * In particular, remove the basic maps that have been marked removed and
+ * update the others based on the information in the corresponding tableau.
+ * Since we detected implicit equalities without calling
+ * isl_basic_map_gauss, we need to do it now.
+ * Also call isl_basic_map_simplify if we may have lost the definition
+ * of one or more integer divisions.
+ */
+static __isl_give isl_map *update_basic_maps(__isl_take isl_map *map,
+ int n, struct isl_coalesce_info *info)
+{
+ int i;
+
+ if (!map)
+ return NULL;
+
+ for (i = n - 1; i >= 0; --i) {
+ if (info[i].removed) {
+ isl_basic_map_free(map->p[i]);
+ if (i != map->n - 1)
+ map->p[i] = map->p[map->n - 1];
+ map->n--;
+ continue;
}
+
+ info[i].bmap = isl_basic_map_update_from_tab(info[i].bmap,
+ info[i].tab);
+ info[i].bmap = isl_basic_map_gauss(info[i].bmap, NULL);
+ if (info[i].simplify)
+ info[i].bmap = isl_basic_map_simplify(info[i].bmap);
+ info[i].bmap = isl_basic_map_finalize(info[i].bmap);
+ if (!info[i].bmap)
+ return isl_map_free(map);
+ ISL_F_SET(info[i].bmap, ISL_BASIC_MAP_NO_IMPLICIT);
+ ISL_F_SET(info[i].bmap, ISL_BASIC_MAP_NO_REDUNDANT);
+ isl_basic_map_free(map->p[i]);
+ map->p[i] = info[i].bmap;
+ info[i].bmap = NULL;
+ }
+
return map;
-error:
- isl_map_free(map);
- return NULL;
}
/* For each pair of basic maps in the map, check if the union of the two
* can be represented by a single basic map.
* If so, replace the pair by the single basic map and start over.
*
+ * We factor out any (hidden) common factor from the constraint
+ * coefficients to improve the detection of adjacent constraints.
+ *
* Since we are constructing the tableaus of the basic maps anyway,
* we exploit them to detect implicit equalities and redundant constraints.
* This also helps the coalescing as it can ignore the redundant constraints.
@@ -1660,14 +2586,17 @@ error:
* in the basic maps. We don't call isl_basic_map_gauss, though,
* as that may affect the number of constraints.
* This means that we have to call isl_basic_map_gauss at the end
- * of the computation to ensure that the basic maps are not left
- * in an unexpected state.
+ * of the computation (in update_basic_maps) to ensure that
+ * the basic maps are not left in an unexpected state.
+ * For each basic map, we also compute the hash of the apparent affine hull
+ * for use in coalesce.
*/
struct isl_map *isl_map_coalesce(struct isl_map *map)
{
int i;
unsigned n;
- struct isl_tab **tabs = NULL;
+ isl_ctx *ctx;
+ struct isl_coalesce_info *info = NULL;
map = isl_map_remove_empty_parts(map);
if (!map)
@@ -1676,61 +2605,54 @@ struct isl_map *isl_map_coalesce(struct
if (map->n <= 1)
return map;
+ ctx = isl_map_get_ctx(map);
map = isl_map_sort_divs(map);
map = isl_map_cow(map);
if (!map)
return NULL;
- tabs = isl_calloc_array(map->ctx, struct isl_tab *, map->n);
- if (!tabs)
+ n = map->n;
+
+ info = isl_calloc_array(map->ctx, struct isl_coalesce_info, n);
+ if (!info)
goto error;
- n = map->n;
for (i = 0; i < map->n; ++i) {
- tabs[i] = isl_tab_from_basic_map(map->p[i], 0);
- if (!tabs[i])
+ map->p[i] = isl_basic_map_reduce_coefficients(map->p[i]);
+ if (!map->p[i])
goto error;
- if (!ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_NO_IMPLICIT))
- if (isl_tab_detect_implicit_equalities(tabs[i]) < 0)
+ info[i].bmap = isl_basic_map_copy(map->p[i]);
+ info[i].tab = isl_tab_from_basic_map(info[i].bmap, 0);
+ if (!info[i].tab)
+ goto error;
+ if (!ISL_F_ISSET(info[i].bmap, ISL_BASIC_MAP_NO_IMPLICIT))
+ if (isl_tab_detect_implicit_equalities(info[i].tab) < 0)
goto error;
- map->p[i] = isl_tab_make_equalities_explicit(tabs[i],
- map->p[i]);
- if (!map->p[i])
+ info[i].bmap = isl_tab_make_equalities_explicit(info[i].tab,
+ info[i].bmap);
+ if (!info[i].bmap)
goto error;
- if (!ISL_F_ISSET(map->p[i], ISL_BASIC_MAP_NO_REDUNDANT))
- if (isl_tab_detect_redundant(tabs[i]) < 0)
+ if (!ISL_F_ISSET(info[i].bmap, ISL_BASIC_MAP_NO_REDUNDANT))
+ if (isl_tab_detect_redundant(info[i].tab) < 0)
goto error;
+ if (coalesce_info_set_hull_hash(&info[i]) < 0)
+ goto error;
}
for (i = map->n - 1; i >= 0; --i)
- if (tabs[i]->empty)
- drop(map, i, tabs);
-
- map = coalesce(map, tabs);
+ if (info[i].tab->empty)
+ drop(&info[i]);
- if (map)
- for (i = 0; i < map->n; ++i) {
- map->p[i] = isl_basic_map_update_from_tab(map->p[i],
- tabs[i]);
- map->p[i] = isl_basic_map_gauss(map->p[i], NULL);
- map->p[i] = isl_basic_map_finalize(map->p[i]);
- if (!map->p[i])
- goto error;
- ISL_F_SET(map->p[i], ISL_BASIC_MAP_NO_IMPLICIT);
- ISL_F_SET(map->p[i], ISL_BASIC_MAP_NO_REDUNDANT);
- }
+ if (coalesce(ctx, n, info) < 0)
+ goto error;
- for (i = 0; i < n; ++i)
- isl_tab_free(tabs[i]);
+ map = update_basic_maps(map, n, info);
- free(tabs);
+ clear_coalesce_info(n, info);
return map;
error:
- if (tabs)
- for (i = 0; i < n; ++i)
- isl_tab_free(tabs[i]);
- free(tabs);
+ clear_coalesce_info(n, info);
isl_map_free(map);
return NULL;
}
Modified: polly/trunk/lib/External/isl/isl_convex_hull.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_convex_hull.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_convex_hull.c (original)
+++ polly/trunk/lib/External/isl/isl_convex_hull.c Mon Feb 16 13:33:40 2015
@@ -595,8 +595,9 @@ static struct isl_basic_set *compute_fac
set = isl_set_preimage(set, U);
facet = uset_convex_hull_wrap_bounded(set);
facet = isl_basic_set_preimage(facet, Q);
- if (facet)
- isl_assert(ctx, facet->n_eq == 0, goto error);
+ if (facet && facet->n_eq != 0)
+ isl_die(ctx, isl_error_internal, "unexpected equality",
+ return isl_basic_set_free(facet));
return facet;
error:
isl_basic_set_free(facet);
@@ -2638,114 +2639,125 @@ error:
return NULL;
}
-/* Compute a superset of the convex hull of "set" that is described
+/* Compute a superset of the convex hull of "map" that is described
* by only constraints in the elements of "list".
*
* If the list is empty, then we can only describe the universe set.
- * If the input set is empty, then all constraints are valid, so
+ * If the input map is empty, then all constraints are valid, so
* we return the intersection of the elements in "list".
*
* Otherwise, we align all divs and temporarily treat them
* as regular variables, computing the unshifted simple hull in
* uset_unshifted_simple_hull_from_basic_set_list.
*/
-static __isl_give isl_basic_set *set_unshifted_simple_hull_from_basic_set_list(
- __isl_take isl_set *set, __isl_take isl_basic_set_list *list)
+static __isl_give isl_basic_map *map_unshifted_simple_hull_from_basic_map_list(
+ __isl_take isl_map *map, __isl_take isl_basic_map_list *list)
{
- isl_basic_set *model;
- isl_basic_set *hull;
+ isl_basic_map *model;
+ isl_basic_map *hull;
+ isl_set *set;
+ isl_basic_set_list *bset_list;
- if (!set || !list)
+ if (!map || !list)
goto error;
- if (isl_basic_set_list_n_basic_set(list) == 0) {
+ if (isl_basic_map_list_n_basic_map(list) == 0) {
isl_space *space;
- space = isl_set_get_space(set);
- isl_set_free(set);
- isl_basic_set_list_free(list);
- return isl_basic_set_universe(space);
+ space = isl_map_get_space(map);
+ isl_map_free(map);
+ isl_basic_map_list_free(list);
+ return isl_basic_map_universe(space);
}
- if (isl_set_plain_is_empty(set)) {
- isl_set_free(set);
- return isl_basic_set_list_intersect(list);
+ if (isl_map_plain_is_empty(map)) {
+ isl_map_free(map);
+ return isl_basic_map_list_intersect(list);
}
- set = isl_set_align_divs_to_basic_set_list(set, list);
- if (!set)
+ map = isl_map_align_divs_to_basic_map_list(map, list);
+ if (!map)
goto error;
- list = isl_basic_set_list_align_divs_to_basic_set(list, set->p[0]);
+ list = isl_basic_map_list_align_divs_to_basic_map(list, map->p[0]);
- model = isl_basic_set_list_get_basic_set(list, 0);
+ model = isl_basic_map_list_get_basic_map(list, 0);
- set = isl_set_to_underlying_set(set);
- list = isl_basic_set_list_underlying_set(list);
+ set = isl_map_underlying_set(map);
+ bset_list = isl_basic_map_list_underlying_set(list);
- hull = uset_unshifted_simple_hull_from_basic_set_list(set, list);
+ hull = uset_unshifted_simple_hull_from_basic_set_list(set, bset_list);
hull = isl_basic_map_overlying_set(hull, model);
return hull;
error:
- isl_set_free(set);
- isl_basic_set_list_free(list);
+ isl_map_free(map);
+ isl_basic_map_list_free(list);
return NULL;
}
-/* Return a sequence of the basic sets that make up the sets in "list".
+/* Return a sequence of the basic maps that make up the maps in "list".
*/
-static __isl_give isl_basic_set_list *collect_basic_sets(
- __isl_take isl_set_list *list)
+static __isl_give isl_basic_set_list *collect_basic_maps(
+ __isl_take isl_map_list *list)
{
int i, n;
isl_ctx *ctx;
- isl_basic_set_list *bset_list;
+ isl_basic_map_list *bmap_list;
if (!list)
return NULL;
- n = isl_set_list_n_set(list);
- ctx = isl_set_list_get_ctx(list);
- bset_list = isl_basic_set_list_alloc(ctx, 0);
+ n = isl_map_list_n_map(list);
+ ctx = isl_map_list_get_ctx(list);
+ bmap_list = isl_basic_map_list_alloc(ctx, 0);
for (i = 0; i < n; ++i) {
- isl_set *set;
- isl_basic_set_list *list_i;
+ isl_map *map;
+ isl_basic_map_list *list_i;
- set = isl_set_list_get_set(list, i);
- set = isl_set_compute_divs(set);
- list_i = isl_set_get_basic_set_list(set);
- isl_set_free(set);
- bset_list = isl_basic_set_list_concat(bset_list, list_i);
+ map = isl_map_list_get_map(list, i);
+ map = isl_map_compute_divs(map);
+ list_i = isl_map_get_basic_map_list(map);
+ isl_map_free(map);
+ bmap_list = isl_basic_map_list_concat(bmap_list, list_i);
}
- isl_set_list_free(list);
- return bset_list;
+ isl_map_list_free(list);
+ return bmap_list;
}
-/* Compute a superset of the convex hull of "set" that is described
+/* Compute a superset of the convex hull of "map" that is described
* by only constraints in the elements of "list".
*
- * If "set" is the universe, then the convex hull (and therefore
+ * If "map" is the universe, then the convex hull (and therefore
* any superset of the convexhull) is the universe as well.
*
- * Otherwise, we collect all the basic sets in the set list and
- * continue with set_unshifted_simple_hull_from_basic_set_list.
+ * Otherwise, we collect all the basic maps in the map list and
+ * continue with map_unshifted_simple_hull_from_basic_map_list.
*/
-__isl_give isl_basic_set *isl_set_unshifted_simple_hull_from_set_list(
- __isl_take isl_set *set, __isl_take isl_set_list *list)
+__isl_give isl_basic_map *isl_map_unshifted_simple_hull_from_map_list(
+ __isl_take isl_map *map, __isl_take isl_map_list *list)
{
- isl_basic_set_list *bset_list;
+ isl_basic_map_list *bmap_list;
int is_universe;
- is_universe = isl_set_plain_is_universe(set);
+ is_universe = isl_map_plain_is_universe(map);
if (is_universe < 0)
- set = isl_set_free(set);
+ map = isl_map_free(map);
if (is_universe < 0 || is_universe) {
- isl_set_list_free(list);
- return isl_set_unshifted_simple_hull(set);
+ isl_map_list_free(list);
+ return isl_map_unshifted_simple_hull(map);
}
- bset_list = collect_basic_sets(list);
- return set_unshifted_simple_hull_from_basic_set_list(set, bset_list);
+ bmap_list = collect_basic_maps(list);
+ return map_unshifted_simple_hull_from_basic_map_list(map, bmap_list);
+}
+
+/* Compute a superset of the convex hull of "set" that is described
+ * by only constraints in the elements of "list".
+ */
+__isl_give isl_basic_set *isl_set_unshifted_simple_hull_from_set_list(
+ __isl_take isl_set *set, __isl_take isl_set_list *list)
+{
+ return isl_map_unshifted_simple_hull_from_map_list(set, list);
}
/* Given a set "set", return parametric bounds on the dimension "dim".
Modified: polly/trunk/lib/External/isl/isl_fold.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_fold.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_fold.c (original)
+++ polly/trunk/lib/External/isl/isl_fold.c Mon Feb 16 13:33:40 2015
@@ -641,6 +641,7 @@ __isl_give isl_qpolynomial_fold *isl_qpo
#define DEFAULT_IS_ZERO 1
#define NO_NEG
+#define NO_SUB
#define NO_PULLBACK
#include <isl_pw_templ.c>
@@ -651,7 +652,6 @@ __isl_give isl_qpolynomial_fold *isl_qpo
#define PART isl_pw_qpolynomial_fold
#undef PARTS
#define PARTS pw_qpolynomial_fold
-#define ALIGN_DOMAIN
#define NO_SUB
@@ -901,7 +901,8 @@ __isl_give isl_union_pw_qpolynomial_fold
hash = isl_space_get_hash(part->dim);
entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
- &has_same_domain_space, part->dim, 1);
+ &isl_union_pw_qpolynomial_fold_has_same_domain_space,
+ part->dim, 1);
if (!entry)
goto error;
@@ -1366,7 +1367,8 @@ static int add_pwqp(__isl_take isl_pw_qp
ctx = pwqp->dim->ctx;
hash = isl_space_get_hash(pwqp->dim);
entry = isl_hash_table_find(ctx, &(*upwf)->table, hash,
- &has_same_domain_space, pwqp->dim, 1);
+ &isl_union_pw_qpolynomial_fold_has_same_domain_space,
+ pwqp->dim, 1);
if (!entry)
goto error;
Modified: polly/trunk/lib/External/isl/isl_input.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_input.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_input.c (original)
+++ polly/trunk/lib/External/isl/isl_input.c Mon Feb 16 13:33:40 2015
@@ -145,7 +145,7 @@ static int vars_add_anon(struct vars *v)
* In particular, evaluate expressions of the form x^y,
* with x and y values.
*/
-static struct isl_token *next_token(struct isl_stream *s)
+static struct isl_token *next_token(__isl_keep isl_stream *s)
{
struct isl_token *tok, *tok2;
@@ -182,7 +182,7 @@ error:
*
* where n, d and v are integer constants.
*/
-__isl_give isl_val *isl_stream_read_val(struct isl_stream *s)
+__isl_give isl_val *isl_stream_read_val(__isl_keep isl_stream *s)
{
struct isl_token *tok = NULL;
struct isl_token *tok2 = NULL;
@@ -242,7 +242,7 @@ struct isl_val *isl_val_read_from_str(st
const char *str)
{
isl_val *val;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
val = isl_stream_read_val(s);
@@ -250,7 +250,7 @@ struct isl_val *isl_val_read_from_str(st
return val;
}
-static int accept_cst_factor(struct isl_stream *s, isl_int *f)
+static int accept_cst_factor(__isl_keep isl_stream *s, isl_int *f)
{
struct isl_token *tok;
@@ -280,7 +280,7 @@ error:
* We introduce an integer division q = [aff/d] and the result
* is set to aff - d q.
*/
-static __isl_give isl_pw_aff *affine_mod(struct isl_stream *s,
+static __isl_give isl_pw_aff *affine_mod(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_pw_aff *aff)
{
struct isl_token *tok;
@@ -307,12 +307,12 @@ error:
return NULL;
}
-static __isl_give isl_pw_aff *accept_affine(struct isl_stream *s,
+static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s,
__isl_take isl_space *space, struct vars *v);
-static __isl_give isl_pw_aff_list *accept_affine_list(struct isl_stream *s,
+static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s,
__isl_take isl_space *dim, struct vars *v);
-static __isl_give isl_pw_aff *accept_minmax(struct isl_stream *s,
+static __isl_give isl_pw_aff *accept_minmax(__isl_keep isl_stream *s,
__isl_take isl_space *dim, struct vars *v)
{
struct isl_token *tok;
@@ -372,7 +372,7 @@ static int is_start_of_div(struct isl_to
* floord(<affine expression>,<denominator>)
* ceild(<affine expression>,<denominator>)
*/
-static __isl_give isl_pw_aff *accept_div(struct isl_stream *s,
+static __isl_give isl_pw_aff *accept_div(__isl_keep isl_stream *s,
__isl_take isl_space *dim, struct vars *v)
{
struct isl_token *tok;
@@ -436,7 +436,7 @@ error:
return NULL;
}
-static __isl_give isl_pw_aff *accept_affine_factor(struct isl_stream *s,
+static __isl_give isl_pw_aff *accept_affine_factor(__isl_keep isl_stream *s,
__isl_take isl_space *dim, struct vars *v)
{
struct isl_token *tok = NULL;
@@ -564,7 +564,7 @@ static __isl_give isl_pw_aff *nan_on_dom
return isl_pw_aff_nan_on_domain(ls);
}
-static __isl_give isl_pw_aff *accept_affine(struct isl_stream *s,
+static __isl_give isl_pw_aff *accept_affine(__isl_keep isl_stream *s,
__isl_take isl_space *space, struct vars *v)
{
struct isl_token *tok = NULL;
@@ -675,14 +675,14 @@ static int is_comparator(struct isl_toke
}
}
-static __isl_give isl_map *read_formula(struct isl_stream *s,
+static __isl_give isl_map *read_formula(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_map *map, int rational);
-static __isl_give isl_pw_aff *accept_extended_affine(struct isl_stream *s,
+static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
__isl_take isl_space *dim, struct vars *v, int rational);
/* Accept a ternary operator, given the first argument.
*/
-static __isl_give isl_pw_aff *accept_ternary(struct isl_stream *s,
+static __isl_give isl_pw_aff *accept_ternary(__isl_keep isl_stream *s,
__isl_take isl_map *cond, struct vars *v, int rational)
{
isl_space *dim;
@@ -718,7 +718,7 @@ error:
/* Set *line and *col to those of the next token, if any.
*/
-static void set_current_line_col(struct isl_stream *s, int *line, int *col)
+static void set_current_line_col(__isl_keep isl_stream *s, int *line, int *col)
{
struct isl_token *tok;
@@ -734,7 +734,7 @@ static void set_current_line_col(struct
/* Push a token encapsulating "pa" onto "s", with the given
* line and column.
*/
-static int push_aff(struct isl_stream *s, int line, int col,
+static int push_aff(__isl_keep isl_stream *s, int line, int col,
__isl_take isl_pw_aff *pa)
{
struct isl_token *tok;
@@ -758,7 +758,7 @@ error:
* Otherwise, we assume the affine expression is part of the first
* argument of a ternary operator and try to parse that.
*/
-static __isl_give isl_pw_aff *accept_extended_affine(struct isl_stream *s,
+static __isl_give isl_pw_aff *accept_extended_affine(__isl_keep isl_stream *s,
__isl_take isl_space *dim, struct vars *v, int rational)
{
isl_space *space;
@@ -798,7 +798,7 @@ static __isl_give isl_pw_aff *accept_ext
return accept_ternary(s, cond, v, rational);
}
-static __isl_give isl_map *read_var_def(struct isl_stream *s,
+static __isl_give isl_map *read_var_def(__isl_keep isl_stream *s,
__isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
int rational)
{
@@ -827,7 +827,7 @@ static __isl_give isl_map *read_var_def(
return map;
}
-static __isl_give isl_pw_aff_list *accept_affine_list(struct isl_stream *s,
+static __isl_give isl_pw_aff_list *accept_affine_list(__isl_keep isl_stream *s,
__isl_take isl_space *dim, struct vars *v)
{
isl_pw_aff *pwaff;
@@ -866,7 +866,7 @@ error:
return NULL;
}
-static __isl_give isl_map *read_defined_var_list(struct isl_stream *s,
+static __isl_give isl_map *read_defined_var_list(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_map *map, int rational)
{
struct isl_token *tok;
@@ -911,7 +911,7 @@ error:
return NULL;
}
-static int next_is_tuple(struct isl_stream *s)
+static int next_is_tuple(__isl_keep isl_stream *s)
{
struct isl_token *tok;
int is_tuple;
@@ -935,21 +935,6 @@ static int next_is_tuple(struct isl_stre
return is_tuple;
}
-/* Allocate an initial tuple with zero dimensions and an anonymous,
- * unstructured space.
- * A tuple is represented as an isl_multi_pw_aff.
- * The range space is the space of the tuple.
- * The domain space is an anonymous space
- * with a dimension for each variable in the set of variables in "v".
- * If a given dimension is not defined in terms of earlier dimensions in
- * the input, then the corresponding isl_pw_aff is set equal to one time
- * the variable corresponding to the dimension being defined.
- */
-static __isl_give isl_multi_pw_aff *tuple_alloc(struct vars *v)
-{
- return isl_multi_pw_aff_alloc(isl_space_alloc(v->ctx, 0, v->n, 0));
-}
-
/* Is "pa" an expression in term of earlier dimensions?
* The alternative is that the dimension is defined to be equal to itself,
* meaning that it has a universe domain and an expression that depends
@@ -997,49 +982,27 @@ static int tuple_has_expr(__isl_keep isl
return has_expr;
}
-/* Add a dimension to the given tuple.
- * The dimension is initially undefined, so it is encoded
- * as one times itself.
- */
-static __isl_give isl_multi_pw_aff *tuple_add_dim(
- __isl_take isl_multi_pw_aff *tuple, struct vars *v)
-{
- isl_space *space;
- isl_aff *aff;
- isl_pw_aff *pa;
-
- tuple = isl_multi_pw_aff_add_dims(tuple, isl_dim_in, 1);
- space = isl_multi_pw_aff_get_domain_space(tuple);
- aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
- aff = isl_aff_add_coefficient_si(aff, isl_dim_in, v->n, 1);
- pa = isl_pw_aff_from_aff(aff);
- tuple = isl_multi_pw_aff_flat_range_product(tuple,
- isl_multi_pw_aff_from_pw_aff(pa));
-
- return tuple;
-}
-
-/* Set the name of dimension "pos" in "tuple" to "name".
+/* Set the name of dimension "pos" in "space" to "name".
* During printing, we add primes if the same name appears more than once
* to distinguish the occurrences. Here, we remove those primes from "name"
* before setting the name of the dimension.
*/
-static __isl_give isl_multi_pw_aff *tuple_set_dim_name(
- __isl_take isl_multi_pw_aff *tuple, int pos, char *name)
+static __isl_give isl_space *space_set_dim_name(__isl_take isl_space *space,
+ int pos, char *name)
{
char *prime;
if (!name)
- return tuple;
+ return space;
prime = strchr(name, '\'');
if (prime)
*prime = '\0';
- tuple = isl_multi_pw_aff_set_dim_name(tuple, isl_dim_set, pos, name);
+ space = isl_space_set_dim_name(space, isl_dim_out, pos, name);
if (prime)
*prime = '\'';
- return tuple;
+ return space;
}
/* Accept a piecewise affine expression.
@@ -1063,7 +1026,7 @@ static __isl_give isl_multi_pw_aff *tupl
* expression, we push the parsed expression onto the stream and parse
* again in case the parentheses enclose some subexpression of "aff1".
*/
-static __isl_give isl_pw_aff *accept_piecewise_affine(struct isl_stream *s,
+static __isl_give isl_pw_aff *accept_piecewise_affine(__isl_keep isl_stream *s,
__isl_take isl_space *space, struct vars *v, int rational)
{
isl_pw_aff *res;
@@ -1116,17 +1079,15 @@ error:
return isl_pw_aff_free(res);
}
-/* Read an affine expression from "s" and replace the definition
- * of dimension "pos" in "tuple" by this expression.
+/* Read an affine expression from "s" for use in read_tuple.
*
* accept_extended_affine requires a wrapped space as input.
- * The domain space of "tuple", on the other hand is an anonymous space,
- * so we have to adjust the space of the isl_pw_aff before adding it
- * to "tuple".
+ * read_tuple on the other hand expects each isl_pw_aff
+ * to have an anonymous space. We therefore adjust the space
+ * of the isl_pw_aff before returning it.
*/
-static __isl_give isl_multi_pw_aff *read_tuple_var_def(struct isl_stream *s,
- __isl_take isl_multi_pw_aff *tuple, int pos, struct vars *v,
- int rational)
+static __isl_give isl_pw_aff *read_tuple_var_def(__isl_keep isl_stream *s,
+ struct vars *v, int rational)
{
isl_space *space;
isl_pw_aff *def;
@@ -1137,87 +1098,70 @@ static __isl_give isl_multi_pw_aff *read
space = isl_space_set_alloc(s->ctx, 0, v->n);
def = isl_pw_aff_reset_domain_space(def, space);
- tuple = isl_multi_pw_aff_set_pw_aff(tuple, pos, def);
- return tuple;
+ return def;
}
-/* Read a list of variables and/or affine expressions and return the list
- * as an isl_multi_pw_aff.
+/* Read a list of tuple elements by calling "read_el" on each of them and
+ * return a space with the same number of set dimensions derived from
+ * the parameter space "space" and possibly updated by "read_el".
* The elements in the list are separated by either "," or "][".
* If "comma" is set then only "," is allowed.
*/
-static __isl_give isl_multi_pw_aff *read_tuple_var_list(struct isl_stream *s,
- struct vars *v, int rational, int comma)
+static __isl_give isl_space *read_tuple_list(__isl_keep isl_stream *s,
+ struct vars *v, __isl_take isl_space *space, int rational, int comma,
+ __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s,
+ struct vars *v, __isl_take isl_space *space, int rational,
+ void *user),
+ void *user)
{
- int i = 0;
- struct isl_token *tok;
- isl_multi_pw_aff *res;
+ if (!space)
+ return NULL;
- res = tuple_alloc(v);
+ space = isl_space_set_from_params(space);
if (isl_stream_next_token_is(s, ']'))
- return res;
+ return space;
- while ((tok = next_token(s)) != NULL) {
- int new_name = 0;
-
- res = tuple_add_dim(res, v);
+ for (;;) {
+ struct isl_token *tok;
- if (tok->type == ISL_TOKEN_IDENT) {
- int n = v->n;
- int p = vars_pos(v, tok->u.s, -1);
- if (p < 0)
- goto error;
- new_name = p >= n;
- }
+ space = isl_space_add_dims(space, isl_dim_set, 1);
- if (tok->type == '*') {
- if (vars_add_anon(v) < 0)
- goto error;
- isl_token_free(tok);
- } else if (new_name) {
- res = tuple_set_dim_name(res, i, v->v->name);
- isl_token_free(tok);
- if (isl_stream_eat_if_available(s, '='))
- res = read_tuple_var_def(s, res, i, v,
- rational);
- } else {
- isl_stream_push_token(s, tok);
- tok = NULL;
- if (vars_add_anon(v) < 0)
- goto error;
- res = read_tuple_var_def(s, res, i, v, rational);
- }
+ space = read_el(s, v, space, rational, user);
+ if (!space)
+ return NULL;
tok = isl_stream_next_token(s);
if (!comma && tok && tok->type == ']' &&
isl_stream_next_token_is(s, '[')) {
isl_token_free(tok);
tok = isl_stream_next_token(s);
- } else if (!tok || tok->type != ',')
+ } else if (!tok || tok->type != ',') {
+ if (tok)
+ isl_stream_push_token(s, tok);
break;
+ }
isl_token_free(tok);
- i++;
}
- if (tok)
- isl_stream_push_token(s, tok);
- return res;
-error:
- isl_token_free(tok);
- return isl_multi_pw_aff_free(res);
+ return space;
}
-/* Read a tuple and represent it as an isl_multi_pw_aff. See tuple_alloc.
+/* Read a tuple space from "s" derived from the parameter space "space".
+ * Call "read_el" on each element in the tuples.
*/
-static __isl_give isl_multi_pw_aff *read_tuple(struct isl_stream *s,
- struct vars *v, int rational, int comma)
+static __isl_give isl_space *read_tuple_space(__isl_keep isl_stream *s,
+ struct vars *v, __isl_take isl_space *space, int rational, int comma,
+ __isl_give isl_space *(*read_el)(__isl_keep isl_stream *s,
+ struct vars *v, __isl_take isl_space *space, int rational,
+ void *user),
+ void *user)
{
struct isl_token *tok;
char *name = NULL;
- isl_multi_pw_aff *res = NULL;
+ isl_space *res = NULL;
tok = isl_stream_next_token(s);
if (!tok)
@@ -1232,29 +1176,149 @@ static __isl_give isl_multi_pw_aff *read
if (isl_stream_eat(s, '['))
goto error;
if (next_is_tuple(s)) {
- isl_multi_pw_aff *out;
- int n;
- res = read_tuple(s, v, rational, comma);
+ isl_space *out;
+ res = read_tuple_space(s, v, isl_space_copy(space),
+ rational, comma, read_el, user);
if (isl_stream_eat(s, ISL_TOKEN_TO))
goto error;
- out = read_tuple(s, v, rational, comma);
- n = isl_multi_pw_aff_dim(out, isl_dim_out);
- res = isl_multi_pw_aff_add_dims(res, isl_dim_in, n);
- res = isl_multi_pw_aff_range_product(res, out);
+ out = read_tuple_space(s, v, isl_space_copy(space),
+ rational, comma, read_el, user);
+ res = isl_space_range_product(res, out);
} else
- res = read_tuple_var_list(s, v, rational, comma);
+ res = read_tuple_list(s, v, isl_space_copy(space),
+ rational, comma, read_el, user);
if (isl_stream_eat(s, ']'))
goto error;
if (name) {
- res = isl_multi_pw_aff_set_tuple_name(res, isl_dim_out, name);
+ res = isl_space_set_tuple_name(res, isl_dim_set, name);
free(name);
}
+ isl_space_free(space);
return res;
error:
free(name);
- return isl_multi_pw_aff_free(res);
+ isl_space_free(res);
+ isl_space_free(space);
+ return NULL;
+}
+
+/* Construct an isl_pw_aff defined on a space with v->n variables
+ * that is equal to the last of those variables.
+ */
+static __isl_give isl_pw_aff *identity_tuple_el(struct vars *v)
+{
+ isl_space *space;
+ isl_aff *aff;
+
+ space = isl_space_set_alloc(v->ctx, 0, v->n);
+ aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
+ aff = isl_aff_add_coefficient_si(aff, isl_dim_in, v->n - 1, 1);
+ return isl_pw_aff_from_aff(aff);
+}
+
+/* This function is called for each element in a tuple inside read_tuple.
+ * Add a new variable to "v" and construct a corresponding isl_pw_aff defined
+ * over a space containing all variables in "v" defined so far.
+ * The isl_pw_aff expresses the new variable in terms of earlier variables
+ * if a definition is provided. Otherwise, it is represented as being
+ * equal to itself.
+ * Add the isl_pw_aff to *list.
+ * If the new variable was named, then adjust "space" accordingly and
+ * return the updated space.
+ */
+static __isl_give isl_space *read_tuple_pw_aff_el(__isl_keep isl_stream *s,
+ struct vars *v, __isl_take isl_space *space, int rational, void *user)
+{
+ isl_pw_aff_list **list = (isl_pw_aff_list **) user;
+ isl_pw_aff *pa;
+ struct isl_token *tok;
+ int new_name = 0;
+
+ tok = next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return isl_space_free(space);
+ }
+
+ if (tok->type == ISL_TOKEN_IDENT) {
+ int n = v->n;
+ int p = vars_pos(v, tok->u.s, -1);
+ if (p < 0)
+ goto error;
+ new_name = p >= n;
+ }
+
+ if (tok->type == '*') {
+ if (vars_add_anon(v) < 0)
+ goto error;
+ isl_token_free(tok);
+ pa = identity_tuple_el(v);
+ } else if (new_name) {
+ int pos = isl_space_dim(space, isl_dim_out) - 1;
+ space = space_set_dim_name(space, pos, v->v->name);
+ isl_token_free(tok);
+ if (isl_stream_eat_if_available(s, '='))
+ pa = read_tuple_var_def(s, v, rational);
+ else
+ pa = identity_tuple_el(v);
+ } else {
+ isl_stream_push_token(s, tok);
+ tok = NULL;
+ if (vars_add_anon(v) < 0)
+ goto error;
+ pa = read_tuple_var_def(s, v, rational);
+ }
+
+ *list = isl_pw_aff_list_add(*list, pa);
+ if (!*list)
+ return isl_space_free(space);
+
+ return space;
+error:
+ isl_token_free(tok);
+ return isl_space_free(space);
+}
+
+/* Read a tuple and represent it as an isl_multi_pw_aff.
+ * The range space of the isl_multi_pw_aff is the space of the tuple.
+ * The domain space is an anonymous space
+ * with a dimension for each variable in the set of variables in "v",
+ * including the variables in the range.
+ * If a given dimension is not defined in terms of earlier dimensions in
+ * the input, then the corresponding isl_pw_aff is set equal to one time
+ * the variable corresponding to the dimension being defined.
+ *
+ * The elements in the tuple are collected in a list by read_tuple_pw_aff_el.
+ * Each element in this list is defined over a space representing
+ * the variables defined so far. We need to adjust the earlier
+ * elements to have as many variables in the domain as the final
+ * element in the list.
+ */
+static __isl_give isl_multi_pw_aff *read_tuple(__isl_keep isl_stream *s,
+ struct vars *v, int rational, int comma)
+{
+ int i, n;
+ isl_space *space;
+ isl_pw_aff_list *list;
+
+ space = isl_space_params_alloc(v->ctx, 0);
+ list = isl_pw_aff_list_alloc(s->ctx, 0);
+ space = read_tuple_space(s, v, space, rational, comma,
+ &read_tuple_pw_aff_el, &list);
+ n = isl_space_dim(space, isl_dim_set);
+ for (i = 0; i + 1 < n; ++i) {
+ isl_pw_aff *pa;
+
+ pa = isl_pw_aff_list_get_pw_aff(list, i);
+ pa = isl_pw_aff_add_dims(pa, isl_dim_in, n - (i + 1));
+ list = isl_pw_aff_list_set_pw_aff(list, i, pa);
+ }
+
+ space = isl_space_from_range(space);
+ space = isl_space_add_dims(space, isl_dim_in, v->n);
+ return isl_multi_pw_aff_from_pw_aff_list(space, list);
}
/* Add the tuple represented by the isl_multi_pw_aff "tuple" to "map".
@@ -1348,7 +1412,7 @@ error:
* The tuple is initially represented as an isl_multi_pw_aff and
* then added to "map".
*/
-static __isl_give isl_map *read_map_tuple(struct isl_stream *s,
+static __isl_give isl_map *read_map_tuple(__isl_keep isl_stream *s,
__isl_take isl_map *map, enum isl_dim_type type, struct vars *v,
int rational, int comma)
{
@@ -1390,7 +1454,7 @@ static __isl_give isl_set *construct_con
return isl_set_intersect(set, cond);
}
-static __isl_give isl_map *add_constraint(struct isl_stream *s,
+static __isl_give isl_map *add_constraint(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_map *map, int rational)
{
struct isl_token *tok = NULL;
@@ -1439,7 +1503,7 @@ error:
return NULL;
}
-static __isl_give isl_map *read_exists(struct isl_stream *s,
+static __isl_give isl_map *read_exists(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_map *map, int rational)
{
int n = v->n;
@@ -1479,7 +1543,7 @@ error:
* Otherwise, we assume that the affine expression is the
* start of a condition and continue parsing.
*/
-static int resolve_paren_expr(struct isl_stream *s,
+static int resolve_paren_expr(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_map *map, int rational)
{
struct isl_token *tok, *tok2;
@@ -1551,7 +1615,7 @@ error:
return -1;
}
-static __isl_give isl_map *read_conjunct(struct isl_stream *s,
+static __isl_give isl_map *read_conjunct(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_map *map, int rational)
{
if (isl_stream_next_token_is(s, '('))
@@ -1587,7 +1651,7 @@ error:
return NULL;
}
-static __isl_give isl_map *read_conjuncts(struct isl_stream *s,
+static __isl_give isl_map *read_conjuncts(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_map *map, int rational)
{
isl_map *res;
@@ -1613,7 +1677,7 @@ static __isl_give isl_map *read_conjunct
return res;
}
-static struct isl_map *read_disjuncts(struct isl_stream *s,
+static struct isl_map *read_disjuncts(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_map *map, int rational)
{
isl_map *res;
@@ -1657,7 +1721,7 @@ static struct isl_map *read_disjuncts(st
*
* (map \setminus { [..] : a}) \cup (map \cap { [..] : b })
*/
-static __isl_give isl_map *read_formula(struct isl_stream *s,
+static __isl_give isl_map *read_formula(__isl_keep isl_stream *s,
struct vars *v, __isl_take isl_map *map, int rational)
{
isl_map *res;
@@ -1700,7 +1764,7 @@ static int polylib_pos_to_isl_pos(__isl_
}
static __isl_give isl_basic_map *basic_map_read_polylib_constraint(
- struct isl_stream *s, __isl_take isl_basic_map *bmap)
+ __isl_keep isl_stream *s, __isl_take isl_basic_map *bmap)
{
int j;
struct isl_token *tok;
@@ -1769,7 +1833,8 @@ error:
return NULL;
}
-static __isl_give isl_basic_map *basic_map_read_polylib(struct isl_stream *s)
+static __isl_give isl_basic_map *basic_map_read_polylib(
+ __isl_keep isl_stream *s)
{
int i;
struct isl_token *tok;
@@ -1885,7 +1950,7 @@ error:
return NULL;
}
-static struct isl_map *map_read_polylib(struct isl_stream *s)
+static struct isl_map *map_read_polylib(__isl_keep isl_stream *s)
{
struct isl_token *tok;
struct isl_token *tok2;
@@ -1923,7 +1988,7 @@ static struct isl_map *map_read_polylib(
return map;
}
-static int optional_power(struct isl_stream *s)
+static int optional_power(__isl_keep isl_stream *s)
{
int pow;
struct isl_token *tok;
@@ -1948,10 +2013,10 @@ static int optional_power(struct isl_str
return pow;
}
-static __isl_give isl_pw_qpolynomial *read_term(struct isl_stream *s,
+static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s,
__isl_keep isl_map *map, struct vars *v);
-static __isl_give isl_pw_qpolynomial *read_factor(struct isl_stream *s,
+static __isl_give isl_pw_qpolynomial *read_factor(__isl_keep isl_stream *s,
__isl_keep isl_map *map, struct vars *v)
{
isl_pw_qpolynomial *pwqp;
@@ -2059,7 +2124,7 @@ error:
return NULL;
}
-static __isl_give isl_pw_qpolynomial *read_term(struct isl_stream *s,
+static __isl_give isl_pw_qpolynomial *read_term(__isl_keep isl_stream *s,
__isl_keep isl_map *map, struct vars *v)
{
struct isl_token *tok;
@@ -2100,7 +2165,7 @@ static __isl_give isl_pw_qpolynomial *re
return pwqp;
}
-static __isl_give isl_map *read_optional_formula(struct isl_stream *s,
+static __isl_give isl_map *read_optional_formula(__isl_keep isl_stream *s,
__isl_take isl_map *map, struct vars *v, int rational)
{
struct isl_token *tok;
@@ -2123,7 +2188,7 @@ error:
return NULL;
}
-static struct isl_obj obj_read_poly(struct isl_stream *s,
+static struct isl_obj obj_read_poly(__isl_keep isl_stream *s,
__isl_take isl_map *map, struct vars *v, int n)
{
struct isl_obj obj = { isl_obj_pw_qpolynomial, NULL };
@@ -2142,7 +2207,7 @@ static struct isl_obj obj_read_poly(stru
return obj;
}
-static struct isl_obj obj_read_poly_or_fold(struct isl_stream *s,
+static struct isl_obj obj_read_poly_or_fold(__isl_keep isl_stream *s,
__isl_take isl_set *set, struct vars *v, int n)
{
struct isl_obj obj = { isl_obj_pw_qpolynomial_fold, NULL };
@@ -2183,7 +2248,7 @@ error:
return obj;
}
-static int is_rational(struct isl_stream *s)
+static int is_rational(__isl_keep isl_stream *s)
{
struct isl_token *tok;
@@ -2201,7 +2266,7 @@ static int is_rational(struct isl_stream
return 0;
}
-static struct isl_obj obj_read_body(struct isl_stream *s,
+static struct isl_obj obj_read_body(__isl_keep isl_stream *s,
__isl_take isl_map *map, struct vars *v)
{
struct isl_token *tok;
@@ -2278,47 +2343,54 @@ error:
return obj;
}
-static struct isl_obj obj_add(struct isl_ctx *ctx,
+static struct isl_obj obj_add(__isl_keep isl_stream *s,
struct isl_obj obj1, struct isl_obj obj2)
{
if (obj1.type == isl_obj_set && obj2.type == isl_obj_union_set)
- obj1 = to_union(ctx, obj1);
+ obj1 = to_union(s->ctx, obj1);
if (obj1.type == isl_obj_union_set && obj2.type == isl_obj_set)
- obj2 = to_union(ctx, obj2);
+ obj2 = to_union(s->ctx, obj2);
if (obj1.type == isl_obj_map && obj2.type == isl_obj_union_map)
- obj1 = to_union(ctx, obj1);
+ obj1 = to_union(s->ctx, obj1);
if (obj1.type == isl_obj_union_map && obj2.type == isl_obj_map)
- obj2 = to_union(ctx, obj2);
+ obj2 = to_union(s->ctx, obj2);
if (obj1.type == isl_obj_pw_qpolynomial &&
obj2.type == isl_obj_union_pw_qpolynomial)
- obj1 = to_union(ctx, obj1);
+ obj1 = to_union(s->ctx, obj1);
if (obj1.type == isl_obj_union_pw_qpolynomial &&
obj2.type == isl_obj_pw_qpolynomial)
- obj2 = to_union(ctx, obj2);
+ obj2 = to_union(s->ctx, obj2);
if (obj1.type == isl_obj_pw_qpolynomial_fold &&
obj2.type == isl_obj_union_pw_qpolynomial_fold)
- obj1 = to_union(ctx, obj1);
+ obj1 = to_union(s->ctx, obj1);
if (obj1.type == isl_obj_union_pw_qpolynomial_fold &&
obj2.type == isl_obj_pw_qpolynomial_fold)
- obj2 = to_union(ctx, obj2);
- isl_assert(ctx, obj1.type == obj2.type, goto error);
+ obj2 = to_union(s->ctx, obj2);
+ if (obj1.type != obj2.type) {
+ isl_stream_error(s, NULL,
+ "attempt to combine incompatible objects");
+ goto error;
+ }
+ if (!obj1.type->add)
+ isl_die(s->ctx, isl_error_internal,
+ "combination not supported on object type", goto error);
if (obj1.type == isl_obj_map && !isl_map_has_equal_space(obj1.v, obj2.v)) {
- obj1 = to_union(ctx, obj1);
- obj2 = to_union(ctx, obj2);
+ obj1 = to_union(s->ctx, obj1);
+ obj2 = to_union(s->ctx, obj2);
}
if (obj1.type == isl_obj_set && !isl_set_has_equal_space(obj1.v, obj2.v)) {
- obj1 = to_union(ctx, obj1);
- obj2 = to_union(ctx, obj2);
+ obj1 = to_union(s->ctx, obj1);
+ obj2 = to_union(s->ctx, obj2);
}
if (obj1.type == isl_obj_pw_qpolynomial &&
!isl_pw_qpolynomial_has_equal_space(obj1.v, obj2.v)) {
- obj1 = to_union(ctx, obj1);
- obj2 = to_union(ctx, obj2);
+ obj1 = to_union(s->ctx, obj1);
+ obj2 = to_union(s->ctx, obj2);
}
if (obj1.type == isl_obj_pw_qpolynomial_fold &&
!isl_pw_qpolynomial_fold_has_equal_space(obj1.v, obj2.v)) {
- obj1 = to_union(ctx, obj1);
- obj2 = to_union(ctx, obj2);
+ obj1 = to_union(s->ctx, obj1);
+ obj2 = to_union(s->ctx, obj2);
}
obj1.v = obj1.type->add(obj1.v, obj2.v);
return obj1;
@@ -2330,13 +2402,80 @@ error:
return obj1;
}
-static struct isl_obj obj_read(struct isl_stream *s)
+/* Are the first two tokens on "s", "domain" (either as a string
+ * or as an identifier) followed by ":"?
+ */
+static int next_is_domain_colon(__isl_keep isl_stream *s)
+{
+ struct isl_token *tok;
+ char *name;
+ int res;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ if (tok->type != ISL_TOKEN_IDENT && tok->type != ISL_TOKEN_STRING) {
+ isl_stream_push_token(s, tok);
+ return 0;
+ }
+
+ name = isl_token_get_str(s->ctx, tok);
+ res = !strcmp(name, "domain") && isl_stream_next_token_is(s, ':');
+ free(name);
+
+ isl_stream_push_token(s, tok);
+
+ return res;
+}
+
+/* Do the first tokens on "s" look like a schedule?
+ *
+ * The root of a schedule is always a domain node, so the first thing
+ * we expect in the stream is a domain key, i.e., "domain" followed
+ * by ":". If the schedule was printed in YAML flow style, then
+ * we additionally expect a "{" to open the outer mapping.
+ */
+static int next_is_schedule(__isl_keep isl_stream *s)
+{
+ struct isl_token *tok;
+ int is_schedule;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ if (tok->type != '{') {
+ isl_stream_push_token(s, tok);
+ return next_is_domain_colon(s);
+ }
+
+ is_schedule = next_is_domain_colon(s);
+ isl_stream_push_token(s, tok);
+
+ return is_schedule;
+}
+
+/* Read an isl_schedule from "s" and store it in an isl_obj.
+ */
+static struct isl_obj schedule_read(__isl_keep isl_stream *s)
+{
+ struct isl_obj obj;
+
+ obj.type = isl_obj_schedule;
+ obj.v = isl_stream_read_schedule(s);
+
+ return obj;
+}
+
+static struct isl_obj obj_read(__isl_keep isl_stream *s)
{
isl_map *map = NULL;
struct isl_token *tok;
struct vars *v = NULL;
struct isl_obj obj = { isl_obj_set, NULL };
+ if (next_is_schedule(s))
+ return schedule_read(s);
+
tok = next_token(s);
if (!tok) {
isl_stream_error(s, NULL, "unexpected EOF");
@@ -2425,7 +2564,7 @@ static struct isl_obj obj_read(struct is
if (!obj.v)
obj = o;
else {
- obj = obj_add(s->ctx, obj, o);
+ obj = obj_add(s, obj, o);
if (obj.type == isl_obj_none || !obj.v)
goto error;
}
@@ -2461,12 +2600,12 @@ error:
return obj;
}
-struct isl_obj isl_stream_read_obj(struct isl_stream *s)
+struct isl_obj isl_stream_read_obj(__isl_keep isl_stream *s)
{
return obj_read(s);
}
-__isl_give isl_map *isl_stream_read_map(struct isl_stream *s)
+__isl_give isl_map *isl_stream_read_map(__isl_keep isl_stream *s)
{
struct isl_obj obj;
@@ -2484,7 +2623,7 @@ error:
return NULL;
}
-__isl_give isl_set *isl_stream_read_set(struct isl_stream *s)
+__isl_give isl_set *isl_stream_read_set(__isl_keep isl_stream *s)
{
struct isl_obj obj;
@@ -2503,7 +2642,7 @@ error:
return NULL;
}
-__isl_give isl_union_map *isl_stream_read_union_map(struct isl_stream *s)
+__isl_give isl_union_map *isl_stream_read_union_map(__isl_keep isl_stream *s)
{
struct isl_obj obj;
@@ -2528,7 +2667,7 @@ error:
return NULL;
}
-__isl_give isl_union_set *isl_stream_read_union_set(struct isl_stream *s)
+__isl_give isl_union_set *isl_stream_read_union_set(__isl_keep isl_stream *s)
{
struct isl_obj obj;
@@ -2546,7 +2685,7 @@ error:
return NULL;
}
-static __isl_give isl_basic_map *basic_map_read(struct isl_stream *s)
+static __isl_give isl_basic_map *basic_map_read(__isl_keep isl_stream *s)
{
struct isl_obj obj;
struct isl_map *map;
@@ -2578,7 +2717,7 @@ error:
return NULL;
}
-static __isl_give isl_basic_set *basic_set_read(struct isl_stream *s)
+static __isl_give isl_basic_set *basic_set_read(__isl_keep isl_stream *s)
{
isl_basic_map *bmap;
bmap = basic_map_read(s);
@@ -2597,7 +2736,7 @@ __isl_give isl_basic_map *isl_basic_map_
FILE *input)
{
struct isl_basic_map *bmap;
- struct isl_stream *s = isl_stream_new_file(ctx, input);
+ isl_stream *s = isl_stream_new_file(ctx, input);
if (!s)
return NULL;
bmap = basic_map_read(s);
@@ -2609,7 +2748,7 @@ __isl_give isl_basic_set *isl_basic_set_
FILE *input)
{
isl_basic_set *bset;
- struct isl_stream *s = isl_stream_new_file(ctx, input);
+ isl_stream *s = isl_stream_new_file(ctx, input);
if (!s)
return NULL;
bset = basic_set_read(s);
@@ -2621,7 +2760,7 @@ struct isl_basic_map *isl_basic_map_read
const char *str)
{
struct isl_basic_map *bmap;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
bmap = basic_map_read(s);
@@ -2633,7 +2772,7 @@ struct isl_basic_set *isl_basic_set_read
const char *str)
{
isl_basic_set *bset;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
bset = basic_set_read(s);
@@ -2645,7 +2784,7 @@ __isl_give isl_map *isl_map_read_from_fi
FILE *input)
{
struct isl_map *map;
- struct isl_stream *s = isl_stream_new_file(ctx, input);
+ isl_stream *s = isl_stream_new_file(ctx, input);
if (!s)
return NULL;
map = isl_stream_read_map(s);
@@ -2657,7 +2796,7 @@ __isl_give isl_map *isl_map_read_from_st
const char *str)
{
struct isl_map *map;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
map = isl_stream_read_map(s);
@@ -2669,7 +2808,7 @@ __isl_give isl_set *isl_set_read_from_fi
FILE *input)
{
isl_set *set;
- struct isl_stream *s = isl_stream_new_file(ctx, input);
+ isl_stream *s = isl_stream_new_file(ctx, input);
if (!s)
return NULL;
set = isl_stream_read_set(s);
@@ -2681,7 +2820,7 @@ struct isl_set *isl_set_read_from_str(st
const char *str)
{
isl_set *set;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
set = isl_stream_read_set(s);
@@ -2693,7 +2832,7 @@ __isl_give isl_union_map *isl_union_map_
FILE *input)
{
isl_union_map *umap;
- struct isl_stream *s = isl_stream_new_file(ctx, input);
+ isl_stream *s = isl_stream_new_file(ctx, input);
if (!s)
return NULL;
umap = isl_stream_read_union_map(s);
@@ -2705,7 +2844,7 @@ __isl_give isl_union_map *isl_union_map_
const char *str)
{
isl_union_map *umap;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
umap = isl_stream_read_union_map(s);
@@ -2717,7 +2856,7 @@ __isl_give isl_union_set *isl_union_set_
FILE *input)
{
isl_union_set *uset;
- struct isl_stream *s = isl_stream_new_file(ctx, input);
+ isl_stream *s = isl_stream_new_file(ctx, input);
if (!s)
return NULL;
uset = isl_stream_read_union_set(s);
@@ -2729,7 +2868,7 @@ __isl_give isl_union_set *isl_union_set_
const char *str)
{
isl_union_set *uset;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
uset = isl_stream_read_union_set(s);
@@ -2737,7 +2876,7 @@ __isl_give isl_union_set *isl_union_set_
return uset;
}
-static __isl_give isl_vec *isl_vec_read_polylib(struct isl_stream *s)
+static __isl_give isl_vec *isl_vec_read_polylib(__isl_keep isl_stream *s)
{
struct isl_vec *vec = NULL;
struct isl_token *tok;
@@ -2772,7 +2911,7 @@ error:
return NULL;
}
-static __isl_give isl_vec *vec_read(struct isl_stream *s)
+static __isl_give isl_vec *vec_read(__isl_keep isl_stream *s)
{
return isl_vec_read_polylib(s);
}
@@ -2780,7 +2919,7 @@ static __isl_give isl_vec *vec_read(stru
__isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input)
{
isl_vec *v;
- struct isl_stream *s = isl_stream_new_file(ctx, input);
+ isl_stream *s = isl_stream_new_file(ctx, input);
if (!s)
return NULL;
v = vec_read(s);
@@ -2789,7 +2928,7 @@ __isl_give isl_vec *isl_vec_read_from_fi
}
__isl_give isl_pw_qpolynomial *isl_stream_read_pw_qpolynomial(
- struct isl_stream *s)
+ __isl_keep isl_stream *s)
{
struct isl_obj obj;
@@ -2808,7 +2947,7 @@ __isl_give isl_pw_qpolynomial *isl_pw_qp
const char *str)
{
isl_pw_qpolynomial *pwqp;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
pwqp = isl_stream_read_pw_qpolynomial(s);
@@ -2820,7 +2959,7 @@ __isl_give isl_pw_qpolynomial *isl_pw_qp
FILE *input)
{
isl_pw_qpolynomial *pwqp;
- struct isl_stream *s = isl_stream_new_file(ctx, input);
+ isl_stream *s = isl_stream_new_file(ctx, input);
if (!s)
return NULL;
pwqp = isl_stream_read_pw_qpolynomial(s);
@@ -2830,7 +2969,7 @@ __isl_give isl_pw_qpolynomial *isl_pw_qp
/* Is the next token an identifer not in "v"?
*/
-static int next_is_fresh_ident(struct isl_stream *s, struct vars *v)
+static int next_is_fresh_ident(__isl_keep isl_stream *s, struct vars *v)
{
int n = v->n;
int fresh;
@@ -2857,7 +2996,7 @@ static int next_is_fresh_ident(struct is
* or a new identifier, we again assume it's the domain.
* Otherwise, we assume we are reading an affine expression.
*/
-static __isl_give isl_set *read_aff_domain(struct isl_stream *s,
+static __isl_give isl_set *read_aff_domain(__isl_keep isl_stream *s,
__isl_take isl_set *dom, struct vars *v)
{
struct isl_token *tok;
@@ -2887,7 +3026,7 @@ error:
/* Read an affine expression from "s".
*/
-__isl_give isl_aff *isl_stream_read_aff(struct isl_stream *s)
+__isl_give isl_aff *isl_stream_read_aff(__isl_keep isl_stream *s)
{
isl_aff *aff;
isl_multi_aff *ma;
@@ -2910,7 +3049,7 @@ error:
/* Read a piecewise affine expression from "s" with domain (space) "dom".
*/
-static __isl_give isl_pw_aff *read_pw_aff_with_dom(struct isl_stream *s,
+static __isl_give isl_pw_aff *read_pw_aff_with_dom(__isl_keep isl_stream *s,
__isl_take isl_set *dom, struct vars *v)
{
isl_pw_aff *pwaff = NULL;
@@ -2936,7 +3075,7 @@ error:
return NULL;
}
-__isl_give isl_pw_aff *isl_stream_read_pw_aff(struct isl_stream *s)
+__isl_give isl_pw_aff *isl_stream_read_pw_aff(__isl_keep isl_stream *s)
{
struct vars *v;
isl_set *dom = NULL;
@@ -2989,7 +3128,7 @@ error:
__isl_give isl_aff *isl_aff_read_from_str(isl_ctx *ctx, const char *str)
{
isl_aff *aff;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
aff = isl_stream_read_aff(s);
@@ -3000,7 +3139,7 @@ __isl_give isl_aff *isl_aff_read_from_st
__isl_give isl_pw_aff *isl_pw_aff_read_from_str(isl_ctx *ctx, const char *str)
{
isl_pw_aff *pa;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
pa = isl_stream_read_pw_aff(s);
@@ -3014,7 +3153,8 @@ __isl_give isl_pw_aff *isl_pw_aff_read_f
* It would be more efficient if we were to construct the isl_pw_multi_aff
* directly.
*/
-__isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(struct isl_stream *s)
+__isl_give isl_pw_multi_aff *isl_stream_read_pw_multi_aff(
+ __isl_keep isl_stream *s)
{
struct isl_obj obj;
@@ -3036,7 +3176,7 @@ __isl_give isl_pw_multi_aff *isl_pw_mult
const char *str)
{
isl_pw_multi_aff *pma;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
pma = isl_stream_read_pw_multi_aff(s);
@@ -3051,7 +3191,7 @@ __isl_give isl_pw_multi_aff *isl_pw_mult
* the isl_union_pw_multi_aff directly.
*/
__isl_give isl_union_pw_multi_aff *isl_stream_read_union_pw_multi_aff(
- struct isl_stream *s)
+ __isl_keep isl_stream *s)
{
struct isl_obj obj;
@@ -3077,7 +3217,7 @@ __isl_give isl_union_pw_multi_aff *isl_u
isl_ctx *ctx, const char *str)
{
isl_union_pw_multi_aff *upma;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
upma = isl_stream_read_union_pw_multi_aff(s);
@@ -3111,6 +3251,86 @@ error:
return NULL;
}
+/* This function is called for each element in a tuple inside
+ * isl_stream_read_multi_val.
+ * Read an isl_val from "s" and add it to *list.
+ */
+static __isl_give isl_space *read_val_el(__isl_keep isl_stream *s,
+ struct vars *v, __isl_take isl_space *space, int rational, void *user)
+{
+ isl_val_list **list = (isl_val_list **) user;
+ isl_val *val;
+
+ val = isl_stream_read_val(s);
+ *list = isl_val_list_add(*list, val);
+ if (!*list)
+ return isl_space_free(space);
+
+ return space;
+}
+
+/* Read an isl_multi_val from "s".
+ *
+ * We first read a tuple space, collecting the element values in a list.
+ * Then we create an isl_multi_val from the space and the isl_val_list.
+ */
+__isl_give isl_multi_val *isl_stream_read_multi_val(__isl_keep isl_stream *s)
+{
+ struct vars *v;
+ isl_set *dom = NULL;
+ isl_space *space;
+ isl_multi_val *mv = NULL;
+ isl_val_list *list;
+
+ v = vars_new(s->ctx);
+ if (!v)
+ return NULL;
+
+ dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
+ if (next_is_tuple(s)) {
+ dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
+ if (isl_stream_eat(s, ISL_TOKEN_TO))
+ goto error;
+ }
+ if (!isl_set_plain_is_universe(dom))
+ isl_die(s->ctx, isl_error_invalid,
+ "expecting universe parameter domain", goto error);
+ if (isl_stream_eat(s, '{'))
+ goto error;
+
+ space = isl_set_get_space(dom);
+
+ list = isl_val_list_alloc(s->ctx, 0);
+ space = read_tuple_space(s, v, space, 1, 0, &read_val_el, &list);
+ mv = isl_multi_val_from_val_list(space, list);
+
+ if (isl_stream_eat(s, '}'))
+ goto error;
+
+ vars_free(v);
+ isl_set_free(dom);
+ return mv;
+error:
+ vars_free(v);
+ isl_set_free(dom);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Read an isl_multi_val from "str".
+ */
+__isl_give isl_multi_val *isl_multi_val_read_from_str(isl_ctx *ctx,
+ const char *str)
+{
+ isl_multi_val *mv;
+ isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ mv = isl_stream_read_multi_val(s);
+ isl_stream_free(s);
+ return mv;
+}
+
/* Read a multi-affine expression from "s".
* If the multi-affine expression has a domain, then the tuple
* representing this domain cannot involve any affine expressions.
@@ -3119,7 +3339,7 @@ error:
* only depend on parameters and input dimensions and not on other
* output dimensions.
*/
-__isl_give isl_multi_aff *isl_stream_read_multi_aff(struct isl_stream *s)
+__isl_give isl_multi_aff *isl_stream_read_multi_aff(__isl_keep isl_stream *s)
{
struct vars *v;
isl_set *dom = NULL;
@@ -3215,7 +3435,7 @@ __isl_give isl_multi_aff *isl_multi_aff_
const char *str)
{
isl_multi_aff *maff;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
maff = isl_stream_read_multi_aff(s);
@@ -3248,7 +3468,8 @@ __isl_give isl_multi_aff *isl_multi_aff_
* of read_tuple (which is of the form [input, output] -> [output],
* with anonymous domain) and reset the space.
*/
-__isl_give isl_multi_pw_aff *isl_stream_read_multi_pw_aff(struct isl_stream *s)
+__isl_give isl_multi_pw_aff *isl_stream_read_multi_pw_aff(
+ __isl_keep isl_stream *s)
{
struct vars *v;
isl_set *dom = NULL;
@@ -3329,7 +3550,7 @@ __isl_give isl_multi_pw_aff *isl_multi_p
const char *str)
{
isl_multi_pw_aff *mpa;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
mpa = isl_stream_read_multi_pw_aff(s);
@@ -3337,8 +3558,202 @@ __isl_give isl_multi_pw_aff *isl_multi_p
return mpa;
}
+/* Read the body of an isl_union_pw_aff from "s" with parameter domain "dom".
+ */
+static __isl_give isl_union_pw_aff *read_union_pw_aff_with_dom(
+ __isl_keep isl_stream *s, __isl_take isl_set *dom, struct vars *v)
+{
+ isl_pw_aff *pa;
+ isl_union_pw_aff *upa = NULL;
+ isl_set *aff_dom;
+ int n;
+
+ n = v->n;
+ aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
+ pa = read_pw_aff_with_dom(s, aff_dom, v);
+ vars_drop(v, v->n - n);
+
+ upa = isl_union_pw_aff_from_pw_aff(pa);
+
+ while (isl_stream_eat_if_available(s, ';')) {
+ isl_pw_aff *pa_i;
+ isl_union_pw_aff *upa_i;
+
+ n = v->n;
+ aff_dom = read_aff_domain(s, isl_set_copy(dom), v);
+ pa_i = read_pw_aff_with_dom(s, aff_dom, v);
+ vars_drop(v, v->n - n);
+
+ upa_i = isl_union_pw_aff_from_pw_aff(pa_i);
+ upa = isl_union_pw_aff_union_add(upa, upa_i);
+ }
+
+ isl_set_free(dom);
+ return upa;
+}
+
+/* This function is called for each element in a tuple inside
+ * isl_stream_read_multi_union_pw_aff.
+ *
+ * Read a '{', the union piecewise affine expression body and a '}' and
+ * add the isl_union_pw_aff to *list.
+ */
+static __isl_give isl_space *read_union_pw_aff_el(__isl_keep isl_stream *s,
+ struct vars *v, __isl_take isl_space *space, int rational, void *user)
+{
+ isl_set *dom;
+ isl_union_pw_aff *upa;
+ isl_union_pw_aff_list **list = (isl_union_pw_aff_list **) user;
+
+ dom = isl_set_universe(isl_space_params(isl_space_copy(space)));
+ if (isl_stream_eat(s, '{'))
+ goto error;
+ upa = read_union_pw_aff_with_dom(s, dom, v);
+ *list = isl_union_pw_aff_list_add(*list, upa);
+ if (isl_stream_eat(s, '}'))
+ return isl_space_free(space);
+ if (!*list)
+ return isl_space_free(space);
+ return space;
+error:
+ isl_set_free(dom);
+ return isl_space_free(space);
+}
+
+/* Do the next tokens in "s" correspond to an empty tuple?
+ * In particular, does the stream start with a '[', followed by a ']',
+ * not followed by a "->"?
+ */
+static int next_is_empty_tuple(__isl_keep isl_stream *s)
+{
+ struct isl_token *tok, *tok2, *tok3;
+ int is_empty_tuple = 0;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ if (tok->type != '[') {
+ isl_stream_push_token(s, tok);
+ return 0;
+ }
+
+ tok2 = isl_stream_next_token(s);
+ if (tok2 && tok2->type == ']') {
+ tok3 = isl_stream_next_token(s);
+ is_empty_tuple = !tok || tok->type != ISL_TOKEN_TO;
+ if (tok3)
+ isl_stream_push_token(s, tok3);
+ }
+ if (tok2)
+ isl_stream_push_token(s, tok2);
+ isl_stream_push_token(s, tok);
+
+ return is_empty_tuple;
+}
+
+/* Do the next tokens in "s" correspond to a tuple of parameters?
+ * In particular, does the stream start with a '[' that is not
+ * followed by a '{' or a nested tuple?
+ */
+static int next_is_param_tuple(__isl_keep isl_stream *s)
+{
+ struct isl_token *tok, *tok2;
+ int is_tuple;
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ if (tok->type != '[' || next_is_tuple(s)) {
+ isl_stream_push_token(s, tok);
+ return 0;
+ }
+
+ tok2 = isl_stream_next_token(s);
+ is_tuple = tok2 && tok2->type != '{';
+ if (tok2)
+ isl_stream_push_token(s, tok2);
+ isl_stream_push_token(s, tok);
+
+ return is_tuple;
+}
+
+/* Read an isl_multi_union_pw_aff from "s".
+ *
+ * The input has the form
+ *
+ * [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
+ *
+ * or
+ *
+ * [..] -> [{ [..] : ... ; [..] : ... }, { [..] : ... ; [..] : ... }]
+ *
+ * We first check for the special case of an empty tuple "[]".
+ * Then we check if there are any parameters.
+ * Finally, we read the tuple, collecting the individual isl_union_pw_aff
+ * elements in a list and construct the result from the tuple space and
+ * the list.
+ */
+__isl_give isl_multi_union_pw_aff *isl_stream_read_multi_union_pw_aff(
+ __isl_keep isl_stream *s)
+{
+ struct vars *v;
+ isl_set *dom = NULL;
+ isl_space *space;
+ isl_multi_union_pw_aff *mupa = NULL;
+ isl_union_pw_aff_list *list;
+
+ if (next_is_empty_tuple(s)) {
+ if (isl_stream_eat(s, '['))
+ return NULL;
+ if (isl_stream_eat(s, ']'))
+ return NULL;
+ space = isl_space_set_alloc(s->ctx, 0, 0);
+ return isl_multi_union_pw_aff_zero(space);
+ }
+
+ v = vars_new(s->ctx);
+ if (!v)
+ return NULL;
+
+ dom = isl_set_universe(isl_space_params_alloc(s->ctx, 0));
+ if (next_is_param_tuple(s)) {
+ dom = read_map_tuple(s, dom, isl_dim_param, v, 1, 0);
+ if (isl_stream_eat(s, ISL_TOKEN_TO))
+ goto error;
+ }
+ space = isl_set_get_space(dom);
+ isl_set_free(dom);
+ list = isl_union_pw_aff_list_alloc(s->ctx, 0);
+ space = read_tuple_space(s, v, space, 1, 0,
+ &read_union_pw_aff_el, &list);
+ mupa = isl_multi_union_pw_aff_from_union_pw_aff_list(space, list);
+
+ vars_free(v);
+
+ return mupa;
+error:
+ vars_free(v);
+ isl_set_free(dom);
+ isl_multi_union_pw_aff_free(mupa);
+ return NULL;
+}
+
+/* Read an isl_multi_union_pw_aff from "str".
+ */
+__isl_give isl_multi_union_pw_aff *isl_multi_union_pw_aff_read_from_str(
+ isl_ctx *ctx, const char *str)
+{
+ isl_multi_union_pw_aff *mupa;
+ isl_stream *s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ mupa = isl_stream_read_multi_union_pw_aff(s);
+ isl_stream_free(s);
+ return mupa;
+}
+
__isl_give isl_union_pw_qpolynomial *isl_stream_read_union_pw_qpolynomial(
- struct isl_stream *s)
+ __isl_keep isl_stream *s)
{
struct isl_obj obj;
@@ -3361,7 +3776,7 @@ __isl_give isl_union_pw_qpolynomial *isl
isl_ctx *ctx, const char *str)
{
isl_union_pw_qpolynomial *upwqp;
- struct isl_stream *s = isl_stream_new_str(ctx, str);
+ isl_stream *s = isl_stream_new_str(ctx, str);
if (!s)
return NULL;
upwqp = isl_stream_read_union_pw_qpolynomial(s);
Modified: polly/trunk/lib/External/isl/isl_local_space.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_local_space.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_local_space.c (original)
+++ polly/trunk/lib/External/isl/isl_local_space.c Mon Feb 16 13:33:40 2015
@@ -1361,3 +1361,20 @@ __isl_give isl_local_space *isl_local_sp
return ls;
}
+
+/* Given the local space "ls" of a map, return the local space of a set
+ * that lives in a space that wraps the space of "ls" and that has
+ * the same divs.
+ */
+__isl_give isl_local_space *isl_local_space_wrap(__isl_take isl_local_space *ls)
+{
+ ls = isl_local_space_cow(ls);
+ if (!ls)
+ return NULL;
+
+ ls->dim = isl_space_wrap(ls->dim);
+ if (!ls->dim)
+ return isl_local_space_free(ls);
+
+ return ls;
+}
Modified: polly/trunk/lib/External/isl/isl_map.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_map.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_map.c (original)
+++ polly/trunk/lib/External/isl/isl_map.c Mon Feb 16 13:33:40 2015
@@ -1626,8 +1626,10 @@ struct isl_basic_map *isl_basic_map_cow(
bmap->ref--;
bmap = isl_basic_map_dup(bmap);
}
- if (bmap)
+ if (bmap) {
ISL_F_CLR(bmap, ISL_BASIC_SET_FINAL);
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
+ }
return bmap;
}
@@ -4553,22 +4555,23 @@ __isl_give isl_basic_set *isl_basic_set_
}
/* Replace each element in "list" by the result of applying
- * isl_basic_set_underlying_set to the element.
+ * isl_basic_map_underlying_set to the element.
*/
-__isl_give isl_basic_set_list *isl_basic_set_list_underlying_set(
- __isl_take isl_basic_set_list *list)
+__isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
+ __isl_take isl_basic_map_list *list)
{
int i, n;
if (!list)
return NULL;
- n = isl_basic_set_list_n_basic_set(list);
+ n = isl_basic_map_list_n_basic_map(list);
for (i = 0; i < n; ++i) {
+ isl_basic_map *bmap;
isl_basic_set *bset;
- bset = isl_basic_set_list_get_basic_set(list, i);
- bset = isl_basic_set_underlying_set(bset);
+ bmap = isl_basic_map_list_get_basic_map(list, i);
+ bset = isl_basic_set_underlying_set(bmap);
list = isl_basic_set_list_set_basic_set(list, i, bset);
}
@@ -8405,54 +8408,54 @@ struct isl_set *isl_set_align_divs(struc
return (struct isl_set *)isl_map_align_divs((struct isl_map *)set);
}
-/* Align the divs of the basic sets in "set" to those
- * of the basic sets in "list", as well as to the other basic sets in "set".
+/* Align the divs of the basic maps in "map" to those
+ * of the basic maps in "list", as well as to the other basic maps in "map".
* The elements in "list" are assumed to have known divs.
*/
-__isl_give isl_set *isl_set_align_divs_to_basic_set_list(
- __isl_take isl_set *set, __isl_keep isl_basic_set_list *list)
+__isl_give isl_map *isl_map_align_divs_to_basic_map_list(
+ __isl_take isl_map *map, __isl_keep isl_basic_map_list *list)
{
int i, n;
- set = isl_set_compute_divs(set);
- set = isl_set_cow(set);
- if (!set || !list)
- return isl_set_free(set);
- if (set->n == 0)
- return set;
+ map = isl_map_compute_divs(map);
+ map = isl_map_cow(map);
+ if (!map || !list)
+ return isl_map_free(map);
+ if (map->n == 0)
+ return map;
- n = isl_basic_set_list_n_basic_set(list);
+ n = isl_basic_map_list_n_basic_map(list);
for (i = 0; i < n; ++i) {
- isl_basic_set *bset;
+ isl_basic_map *bmap;
- bset = isl_basic_set_list_get_basic_set(list, i);
- set->p[0] = isl_basic_set_align_divs(set->p[0], bset);
- isl_basic_set_free(bset);
+ bmap = isl_basic_map_list_get_basic_map(list, i);
+ map->p[0] = isl_basic_map_align_divs(map->p[0], bmap);
+ isl_basic_map_free(bmap);
}
- if (!set->p[0])
- return isl_set_free(set);
+ if (!map->p[0])
+ return isl_map_free(map);
- return isl_set_align_divs(set);
+ return isl_map_align_divs(map);
}
-/* Align the divs of each element of "list" to those of "bset".
- * Both "bset" and the elements of "list" are assumed to have known divs.
+/* Align the divs of each element of "list" to those of "bmap".
+ * Both "bmap" and the elements of "list" are assumed to have known divs.
*/
-__isl_give isl_basic_set_list *isl_basic_set_list_align_divs_to_basic_set(
- __isl_take isl_basic_set_list *list, __isl_keep isl_basic_set *bset)
+__isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
+ __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap)
{
int i, n;
- if (!list || !bset)
- return isl_basic_set_list_free(list);
+ if (!list || !bmap)
+ return isl_basic_map_list_free(list);
- n = isl_basic_set_list_n_basic_set(list);
+ n = isl_basic_map_list_n_basic_map(list);
for (i = 0; i < n; ++i) {
- isl_basic_set *bset_i;
+ isl_basic_map *bmap_i;
- bset_i = isl_basic_set_list_get_basic_set(list, i);
- bset_i = isl_basic_set_align_divs(bset_i, bset);
- list = isl_basic_set_list_set_basic_set(list, i, bset_i);
+ bmap_i = isl_basic_map_list_get_basic_map(list, i);
+ bmap_i = isl_basic_map_align_divs(bmap_i, bmap);
+ list = isl_basic_map_list_set_basic_map(list, i, bmap_i);
}
return list;
@@ -9326,25 +9329,25 @@ error:
return NULL;
}
-/* Return the basic sets in "set" as a list.
+/* Return the basic maps in "map" as a list.
*/
-__isl_give isl_basic_set_list *isl_set_get_basic_set_list(
- __isl_keep isl_set *set)
+__isl_give isl_basic_map_list *isl_map_get_basic_map_list(
+ __isl_keep isl_map *map)
{
int i;
isl_ctx *ctx;
- isl_basic_set_list *list;
+ isl_basic_map_list *list;
- if (!set)
+ if (!map)
return NULL;
- ctx = isl_set_get_ctx(set);
- list = isl_basic_set_list_alloc(ctx, set->n);
+ ctx = isl_map_get_ctx(map);
+ list = isl_basic_map_list_alloc(ctx, map->n);
- for (i = 0; i < set->n; ++i) {
- isl_basic_set *bset;
+ for (i = 0; i < map->n; ++i) {
+ isl_basic_map *bmap;
- bset = isl_basic_set_copy(set->p[i]);
- list = isl_basic_set_list_add(list, bset);
+ bmap = isl_basic_map_copy(map->p[i]);
+ list = isl_basic_map_list_add(list, bmap);
}
return list;
@@ -9353,34 +9356,43 @@ __isl_give isl_basic_set_list *isl_set_g
/* Return the intersection of the elements in the non-empty list "list".
* All elements are assumed to live in the same space.
*/
-__isl_give isl_basic_set *isl_basic_set_list_intersect(
- __isl_take struct isl_basic_set_list *list)
+__isl_give isl_basic_map *isl_basic_map_list_intersect(
+ __isl_take isl_basic_map_list *list)
{
int i, n;
- isl_basic_set *bset;
+ isl_basic_map *bmap;
if (!list)
return NULL;
- n = isl_basic_set_list_n_basic_set(list);
+ n = isl_basic_map_list_n_basic_map(list);
if (n < 1)
- isl_die(isl_basic_set_list_get_ctx(list), isl_error_invalid,
+ isl_die(isl_basic_map_list_get_ctx(list), isl_error_invalid,
"expecting non-empty list", goto error);
-
- bset = isl_basic_set_list_get_basic_set(list, 0);
+
+ bmap = isl_basic_map_list_get_basic_map(list, 0);
for (i = 1; i < n; ++i) {
- isl_basic_set *bset_i;
+ isl_basic_map *bmap_i;
- bset_i = isl_basic_set_list_get_basic_set(list, i);
- bset = isl_basic_set_intersect(bset, bset_i);
+ bmap_i = isl_basic_map_list_get_basic_map(list, i);
+ bmap = isl_basic_map_intersect(bmap, bmap_i);
}
- isl_basic_set_list_free(list);
- return bset;
+ isl_basic_map_list_free(list);
+ return bmap;
error:
- isl_basic_set_list_free(list);
+ isl_basic_map_list_free(list);
return NULL;
}
+/* Return the intersection of the elements in the non-empty list "list".
+ * All elements are assumed to live in the same space.
+ */
+__isl_give isl_basic_set *isl_basic_set_list_intersect(
+ __isl_take isl_basic_set_list *list)
+{
+ return isl_basic_map_list_intersect(list);
+}
+
/* Return the Cartesian product of the basic sets in list (in the given order).
*/
__isl_give isl_basic_set *isl_basic_set_list_product(
Added: polly/trunk/lib/External/isl/isl_map_list.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_map_list.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_map_list.c (added)
+++ polly/trunk/lib/External/isl/isl_map_list.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,31 @@
+#include <isl/map.h>
+
+#undef EL
+#define EL isl_basic_map
+
+#include <isl_list_templ.h>
+
+#undef BASE
+#define BASE basic_map
+
+#include <isl_list_templ.c>
+
+#undef EL
+#define EL isl_map
+
+#include <isl_list_templ.h>
+
+#undef BASE
+#define BASE map
+
+#include <isl_list_templ.c>
+
+#undef EL
+#define EL isl_union_map
+
+#include <isl_list_templ.h>
+
+#undef BASE
+#define BASE union_map
+
+#include <isl_list_templ.c>
Modified: polly/trunk/lib/External/isl/isl_map_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_map_private.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_map_private.h (original)
+++ polly/trunk/lib/External/isl/isl_map_private.h Mon Feb 16 13:33:40 2015
@@ -15,12 +15,11 @@
#define isl_basic_set_list isl_basic_map_list
#define isl_set_list isl_map_list
#include <isl/list.h>
-ISL_DECLARE_LIST(basic_map)
-ISL_DECLARE_LIST(map)
#include <isl/set.h>
#include <isl/map.h>
#include <isl_reordering.h>
#include <isl/vec.h>
+#include <isl/hash.h>
#include <isl_blk.h>
/* A "basic map" is a relation between two sets of variables,
@@ -43,6 +42,7 @@ struct isl_basic_map {
#define ISL_BASIC_MAP_NORMALIZED (1 << 5)
#define ISL_BASIC_MAP_NORMALIZED_DIVS (1 << 6)
#define ISL_BASIC_MAP_ALL_EQUALITIES (1 << 7)
+#define ISL_BASIC_MAP_REDUCED_COEFFICIENTS (1 << 8)
#define ISL_BASIC_SET_FINAL (1 << 0)
#define ISL_BASIC_SET_EMPTY (1 << 1)
#define ISL_BASIC_SET_NO_IMPLICIT (1 << 2)
@@ -51,6 +51,7 @@ struct isl_basic_map {
#define ISL_BASIC_SET_NORMALIZED (1 << 5)
#define ISL_BASIC_SET_NORMALIZED_DIVS (1 << 6)
#define ISL_BASIC_SET_ALL_EQUALITIES (1 << 7)
+#define ISL_BASIC_SET_REDUCED_COEFFICIENTS (1 << 8)
unsigned flags;
struct isl_ctx *ctx;
@@ -198,6 +199,8 @@ struct isl_basic_map *isl_basic_map_cow(
struct isl_set *isl_set_cow(struct isl_set *set);
struct isl_map *isl_map_cow(struct isl_map *map);
+uint32_t isl_basic_map_get_hash(__isl_keep isl_basic_map *bmap);
+
struct isl_basic_map *isl_basic_map_set_to_empty(struct isl_basic_map *bmap);
struct isl_basic_set *isl_basic_set_set_to_empty(struct isl_basic_set *bset);
struct isl_basic_set *isl_basic_set_order_divs(struct isl_basic_set *bset);
@@ -208,10 +211,10 @@ struct isl_basic_map *isl_basic_map_alig
struct isl_basic_map *dst, struct isl_basic_map *src);
struct isl_basic_set *isl_basic_set_align_divs(
struct isl_basic_set *dst, struct isl_basic_set *src);
-__isl_give isl_set *isl_set_align_divs_to_basic_set_list(
- __isl_take isl_set *set, __isl_keep isl_basic_set_list *list);
-__isl_give isl_basic_set_list *isl_basic_set_list_align_divs_to_basic_set(
- __isl_take isl_basic_set_list *list, __isl_keep isl_basic_set *bset);
+__isl_give isl_map *isl_map_align_divs_to_basic_map_list(
+ __isl_take isl_map *map, __isl_keep isl_basic_map_list *list);
+__isl_give isl_basic_map_list *isl_basic_map_list_align_divs_to_basic_map(
+ __isl_take isl_basic_map_list *list, __isl_keep isl_basic_map *bmap);
__isl_give isl_basic_map *isl_basic_map_sort_divs(
__isl_take isl_basic_map *bmap);
__isl_give isl_map *isl_map_sort_divs(__isl_take isl_map *map);
@@ -234,8 +237,8 @@ struct isl_basic_map *isl_basic_map_impl
struct isl_basic_set *isl_basic_map_underlying_set(struct isl_basic_map *bmap);
__isl_give isl_basic_set *isl_basic_set_underlying_set(
__isl_take isl_basic_set *bset);
-__isl_give isl_basic_set_list *isl_basic_set_list_underlying_set(
- __isl_take isl_basic_set_list *list);
+__isl_give isl_basic_set_list *isl_basic_map_list_underlying_set(
+ __isl_take isl_basic_map_list *list);
struct isl_set *isl_map_underlying_set(struct isl_map *map);
struct isl_basic_map *isl_basic_map_overlying_set(struct isl_basic_set *bset,
struct isl_basic_map *like);
@@ -258,6 +261,8 @@ struct isl_map *isl_map_drop(struct isl_
__isl_give isl_basic_map *isl_basic_map_remove_duplicate_constraints(
__isl_take isl_basic_map *bmap, int *progress, int detect_divs);
+__isl_give isl_basic_map *isl_basic_map_detect_inequality_pairs(
+ __isl_take isl_basic_map *bmap, int *progress);
struct isl_map *isl_map_remove_empty_parts(struct isl_map *map);
struct isl_set *isl_set_remove_empty_parts(struct isl_set *set);
@@ -381,6 +386,9 @@ int isl_map_is_set(__isl_keep isl_map *m
int isl_basic_set_plain_dim_is_fixed(__isl_keep isl_basic_set *bset,
unsigned dim, isl_int *val);
+__isl_give isl_basic_map *isl_basic_map_plain_affine_hull(
+ __isl_take isl_basic_map *bmap);
+
int isl_basic_set_dim_residue_class(struct isl_basic_set *bset,
int pos, isl_int *modulo, isl_int *residue);
int isl_set_dim_residue_class(struct isl_set *set,
@@ -396,8 +404,14 @@ int isl_map_plain_is_fixed(__isl_keep is
int isl_basic_map_output_defining_equality(__isl_keep isl_basic_map *bmap,
int pos);
-__isl_give isl_basic_set_list *isl_set_get_basic_set_list(
- __isl_keep isl_set *set);
+__isl_give isl_basic_map *isl_basic_map_reduce_coefficients(
+ __isl_take isl_basic_map *bmap);
+
+__isl_give isl_basic_map *isl_basic_map_shift_div(
+ __isl_take isl_basic_map *bmap, int div, isl_int shift);
+
+__isl_give isl_basic_map_list *isl_map_get_basic_map_list(
+ __isl_keep isl_map *map);
__isl_give isl_map *isl_map_fixed_power(__isl_take isl_map *map, isl_int exp);
Modified: polly/trunk/lib/External/isl/isl_map_simplify.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_map_simplify.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_map_simplify.c (original)
+++ polly/trunk/lib/External/isl/isl_map_simplify.c Mon Feb 16 13:33:40 2015
@@ -1,6 +1,6 @@
/*
* Copyright 2008-2009 Katholieke Universiteit Leuven
- * 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
@@ -1184,6 +1184,26 @@ __isl_give isl_basic_map *isl_basic_map_
return bmap;
}
+/* Detect all pairs of inequalities that form an equality.
+ *
+ * isl_basic_map_remove_duplicate_constraints detects at most one such pair.
+ * Call it repeatedly while it is making progress.
+ */
+__isl_give isl_basic_map *isl_basic_map_detect_inequality_pairs(
+ __isl_take isl_basic_map *bmap, int *progress)
+{
+ int duplicate;
+
+ do {
+ duplicate = 0;
+ bmap = isl_basic_map_remove_duplicate_constraints(bmap,
+ &duplicate, 0);
+ if (progress && duplicate)
+ *progress = 1;
+ } while (duplicate);
+
+ return bmap;
+}
/* Eliminate knowns divs from constraints where they appear with
* a (positive or negative) unit coefficient.
@@ -1300,6 +1320,8 @@ struct isl_basic_map *isl_basic_map_simp
bmap = normalize_divs(bmap, &progress);
bmap = isl_basic_map_remove_duplicate_constraints(bmap,
&progress, 1);
+ if (bmap && progress)
+ ISL_F_CLR(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
}
return bmap;
}
@@ -2352,12 +2374,21 @@ error:
* return the corresponding universe.
*
* If none of these cases apply, we have to work a bit harder.
+ * During this computation, we make use of a single disjunct context,
+ * so if the original context consists of more than one disjunct
+ * then we need to approximate the context by a single disjunct set.
+ * Simply taking the simple hull may drop constraints that are
+ * only implicitly available in each disjunct. We therefore also
+ * look for constraints among those defining "map" that are valid
+ * for the context. These can then be used to simplify away
+ * the corresponding constraints in "map".
*/
static __isl_give isl_map *map_gist(__isl_take isl_map *map,
__isl_take isl_map *context)
{
int equal;
int is_universe;
+ isl_basic_map *hull;
is_universe = isl_map_plain_is_universe(map);
if (is_universe >= 0 && !is_universe)
@@ -2380,7 +2411,22 @@ static __isl_give isl_map *map_gist(__is
}
context = isl_map_compute_divs(context);
- return isl_map_gist_basic_map(map, isl_map_simple_hull(context));
+ if (!context)
+ goto error;
+ if (isl_map_n_basic_map(context) == 1) {
+ hull = isl_map_simple_hull(context);
+ } else {
+ isl_ctx *ctx;
+ isl_map_list *list;
+
+ ctx = isl_map_get_ctx(map);
+ list = isl_map_list_alloc(ctx, 2);
+ list = isl_map_list_add(list, isl_map_copy(context));
+ list = isl_map_list_add(list, isl_map_copy(map));
+ hull = isl_map_unshifted_simple_hull_from_map_list(context,
+ list);
+ }
+ return isl_map_gist_basic_map(map, hull);
error:
isl_map_free(map);
isl_map_free(context);
@@ -2423,6 +2469,19 @@ __isl_give isl_set *isl_set_gist(__isl_t
(struct isl_map *)context);
}
+/* Compute the gist of "bmap" with respect to the constraints "context"
+ * on the domain.
+ */
+__isl_give isl_basic_map *isl_basic_map_gist_domain(
+ __isl_take isl_basic_map *bmap, __isl_take isl_basic_set *context)
+{
+ isl_space *space = isl_basic_map_get_space(bmap);
+ isl_basic_map *bmap_context = isl_basic_map_universe(space);
+
+ bmap_context = isl_basic_map_intersect_domain(bmap_context, context);
+ return isl_basic_map_gist(bmap, bmap_context);
+}
+
__isl_give isl_map *isl_map_gist_domain(__isl_take isl_map *map,
__isl_take isl_set *context)
{
@@ -3255,3 +3314,207 @@ struct isl_set *isl_set_drop_redundant_d
return (struct isl_set *)
isl_map_drop_redundant_divs((struct isl_map *)set);
}
+
+/* Does "bmap" satisfy any equality that involves more than 2 variables
+ * and/or has coefficients different from -1 and 1?
+ */
+static int has_multiple_var_equality(__isl_keep isl_basic_map *bmap)
+{
+ int i;
+ unsigned total;
+
+ total = isl_basic_map_dim(bmap, isl_dim_all);
+
+ for (i = 0; i < bmap->n_eq; ++i) {
+ int j, k;
+
+ j = isl_seq_first_non_zero(bmap->eq[i] + 1, total);
+ if (j < 0)
+ continue;
+ if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
+ !isl_int_is_negone(bmap->eq[i][1 + j]))
+ return 1;
+
+ j += 1;
+ k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j);
+ if (k < 0)
+ continue;
+ j += k;
+ if (!isl_int_is_one(bmap->eq[i][1 + j]) &&
+ !isl_int_is_negone(bmap->eq[i][1 + j]))
+ return 1;
+
+ j += 1;
+ k = isl_seq_first_non_zero(bmap->eq[i] + 1 + j, total - j);
+ if (k >= 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Remove any common factor g from the constraint coefficients in "v".
+ * The constant term is stored in the first position and is replaced
+ * by floor(c/g). If any common factor is removed and if this results
+ * in a tightening of the constraint, then set *tightened.
+ */
+static __isl_give isl_vec *normalize_constraint(__isl_take isl_vec *v,
+ int *tightened)
+{
+ isl_ctx *ctx;
+
+ if (!v)
+ return NULL;
+ ctx = isl_vec_get_ctx(v);
+ isl_seq_gcd(v->el + 1, v->size - 1, &ctx->normalize_gcd);
+ if (isl_int_is_zero(ctx->normalize_gcd))
+ return v;
+ if (isl_int_is_one(ctx->normalize_gcd))
+ return v;
+ v = isl_vec_cow(v);
+ if (!v)
+ return NULL;
+ if (tightened && !isl_int_is_divisible_by(v->el[0], ctx->normalize_gcd))
+ *tightened = 1;
+ isl_int_fdiv_q(v->el[0], v->el[0], ctx->normalize_gcd);
+ isl_seq_scale_down(v->el + 1, v->el + 1, ctx->normalize_gcd,
+ v->size - 1);
+ return v;
+}
+
+/* If "bmap" is an integer set that satisfies any equality involving
+ * more than 2 variables and/or has coefficients different from -1 and 1,
+ * then use variable compression to reduce the coefficients by removing
+ * any (hidden) common factor.
+ * In particular, apply the variable compression to each constraint,
+ * factor out any common factor in the non-constant coefficients and
+ * then apply the inverse of the compression.
+ * At the end, we mark the basic map as having reduced constants.
+ * If this flag is still set on the next invocation of this function,
+ * then we skip the computation.
+ *
+ * Removing a common factor may result in a tightening of some of
+ * the constraints. If this happens, then we may end up with two
+ * opposite inequalities that can be replaced by an equality.
+ * We therefore call isl_basic_map_detect_inequality_pairs,
+ * which checks for such pairs of inequalities as well as eliminate_divs_eq
+ * if such a pair was found.
+ */
+__isl_give isl_basic_map *isl_basic_map_reduce_coefficients(
+ __isl_take isl_basic_map *bmap)
+{
+ unsigned total;
+ isl_ctx *ctx;
+ isl_vec *v;
+ isl_mat *eq, *T, *T2;
+ int i;
+ int tightened;
+
+ if (!bmap)
+ return NULL;
+ if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS))
+ return bmap;
+ if (isl_basic_map_is_rational(bmap))
+ return bmap;
+ if (bmap->n_eq == 0)
+ return bmap;
+ if (!has_multiple_var_equality(bmap))
+ return bmap;
+
+ total = isl_basic_map_dim(bmap, isl_dim_all);
+ ctx = isl_basic_map_get_ctx(bmap);
+ v = isl_vec_alloc(ctx, 1 + total);
+ if (!v)
+ return isl_basic_map_free(bmap);
+
+ eq = isl_mat_sub_alloc6(ctx, bmap->eq, 0, bmap->n_eq, 0, 1 + total);
+ T = isl_mat_variable_compression(eq, &T2);
+ if (!T || !T2)
+ goto error;
+ if (T->n_col == 0) {
+ isl_mat_free(T);
+ isl_mat_free(T2);
+ isl_vec_free(v);
+ return isl_basic_map_set_to_empty(bmap);
+ }
+
+ tightened = 0;
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ isl_seq_cpy(v->el, bmap->ineq[i], 1 + total);
+ v = isl_vec_mat_product(v, isl_mat_copy(T));
+ v = normalize_constraint(v, &tightened);
+ v = isl_vec_mat_product(v, isl_mat_copy(T2));
+ if (!v)
+ goto error;
+ isl_seq_cpy(bmap->ineq[i], v->el, 1 + total);
+ }
+
+ isl_mat_free(T);
+ isl_mat_free(T2);
+ isl_vec_free(v);
+
+ ISL_F_SET(bmap, ISL_BASIC_MAP_REDUCED_COEFFICIENTS);
+
+ if (tightened) {
+ int progress = 0;
+
+ bmap = isl_basic_map_detect_inequality_pairs(bmap, &progress);
+ if (progress)
+ bmap = eliminate_divs_eq(bmap, &progress);
+ }
+
+ return bmap;
+error:
+ isl_mat_free(T);
+ isl_mat_free(T2);
+ isl_vec_free(v);
+ return isl_basic_map_free(bmap);
+}
+
+/* Shift the integer division at position "div" of "bmap" by "shift".
+ *
+ * That is, if the integer division has the form
+ *
+ * floor(f(x)/d)
+ *
+ * then replace it by
+ *
+ * floor((f(x) + shift * d)/d) - shift
+ */
+__isl_give isl_basic_map *isl_basic_map_shift_div(
+ __isl_take isl_basic_map *bmap, int div, isl_int shift)
+{
+ int i;
+ unsigned total;
+
+ if (!bmap)
+ return NULL;
+
+ total = isl_basic_map_dim(bmap, isl_dim_all);
+ total -= isl_basic_map_dim(bmap, isl_dim_div);
+
+ isl_int_addmul(bmap->div[div][1], shift, bmap->div[div][0]);
+
+ for (i = 0; i < bmap->n_eq; ++i) {
+ if (isl_int_is_zero(bmap->eq[i][1 + total + div]))
+ continue;
+ isl_int_submul(bmap->eq[i][0],
+ shift, bmap->eq[i][1 + total + div]);
+ }
+ for (i = 0; i < bmap->n_ineq; ++i) {
+ if (isl_int_is_zero(bmap->ineq[i][1 + total + div]))
+ continue;
+ isl_int_submul(bmap->ineq[i][0],
+ shift, bmap->ineq[i][1 + total + div]);
+ }
+ for (i = 0; i < bmap->n_div; ++i) {
+ if (isl_int_is_zero(bmap->div[i][0]))
+ continue;
+ if (isl_int_is_zero(bmap->div[i][1 + 1 + total + div]))
+ continue;
+ isl_int_submul(bmap->div[i][1],
+ shift, bmap->div[i][1 + 1 + total + div]);
+ }
+
+ return bmap;
+}
Modified: polly/trunk/lib/External/isl/isl_morph.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_morph.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_morph.c (original)
+++ polly/trunk/lib/External/isl/isl_morph.c Mon Feb 16 13:33:40 2015
@@ -304,8 +304,8 @@ void isl_morph_print_internal(__isl_take
if (!morph)
return;
- isl_basic_set_print(morph->dom, out, 0, "", "", ISL_FORMAT_ISL);
- isl_basic_set_print(morph->ran, out, 0, "", "", ISL_FORMAT_ISL);
+ isl_basic_set_dump(morph->dom);
+ isl_basic_set_dump(morph->ran);
isl_mat_print_internal(morph->map, out, 4);
isl_mat_print_internal(morph->inv, out, 4);
}
Added: polly/trunk/lib/External/isl/isl_multi_apply_set.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_multi_apply_set.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_multi_apply_set.c (added)
+++ polly/trunk/lib/External/isl/isl_multi_apply_set.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,7 @@
+#define APPLY_DOMBASE set
+#define APPLY_DOM isl_set
+
+#include <isl_multi_apply_templ.c>
+
+#undef APPLY_DOMBASE
+#undef APPLY_DOM
Added: polly/trunk/lib/External/isl/isl_multi_apply_templ.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_multi_apply_templ.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_multi_apply_templ.c (added)
+++ polly/trunk/lib/External/isl/isl_multi_apply_templ.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2011 Sven Verdoolaege
+ * Copyright 2012-2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ */
+
+#include <isl_multi_macro.h>
+
+/* Transform the elements of "multi" by applying "fn" to them
+ * with extra argument "set".
+ *
+ * The parameters of "multi" and "set" are assumed to have been aligned.
+ */
+__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),apply_aligned),APPLY_DOMBASE)(
+ __isl_take MULTI(BASE) *multi, __isl_take APPLY_DOM *set,
+ __isl_give EL *(*fn)(EL *el, __isl_take APPLY_DOM *set))
+{
+ int i;
+
+ if (!multi || !set)
+ goto error;
+
+ if (multi->n == 0) {
+ FN(APPLY_DOM,free)(set);
+ return multi;
+ }
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ goto error;
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = fn(multi->p[i], FN(APPLY_DOM,copy)(set));
+ if (!multi->p[i])
+ goto error;
+ }
+
+ FN(APPLY_DOM,free)(set);
+ return multi;
+error:
+ FN(APPLY_DOM,free)(set);
+ FN(MULTI(BASE),free)(multi);
+ return NULL;
+}
+
+/* Transform the elements of "multi" by applying "fn" to them
+ * with extra argument "set".
+ *
+ * Align the parameters if needed and call apply_set_aligned.
+ */
+static __isl_give MULTI(BASE) *FN(FN(MULTI(BASE),apply),APPLY_DOMBASE)(
+ __isl_take MULTI(BASE) *multi, __isl_take APPLY_DOM *set,
+ __isl_give EL *(*fn)(EL *el, __isl_take APPLY_DOM *set))
+{
+ isl_ctx *ctx;
+
+ if (!multi || !set)
+ goto error;
+
+ if (isl_space_match(multi->space, isl_dim_param,
+ set->dim, isl_dim_param))
+ return FN(FN(MULTI(BASE),apply_aligned),APPLY_DOMBASE)(multi,
+ set, fn);
+ ctx = FN(MULTI(BASE),get_ctx)(multi);
+ if (!isl_space_has_named_params(multi->space) ||
+ !isl_space_has_named_params(set->dim))
+ isl_die(ctx, isl_error_invalid,
+ "unaligned unnamed parameters", goto error);
+ multi = FN(MULTI(BASE),align_params)(multi,
+ FN(APPLY_DOM,get_space)(set));
+ set = FN(APPLY_DOM,align_params)(set, FN(MULTI(BASE),get_space)(multi));
+ return FN(FN(MULTI(BASE),apply_aligned),APPLY_DOMBASE)(multi, set, fn);
+error:
+ FN(MULTI(BASE),free)(multi);
+ FN(APPLY_DOM,free)(set);
+ return NULL;
+}
Added: polly/trunk/lib/External/isl/isl_multi_apply_union_set.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_multi_apply_union_set.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_multi_apply_union_set.c (added)
+++ polly/trunk/lib/External/isl/isl_multi_apply_union_set.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,7 @@
+#define APPLY_DOMBASE union_set
+#define APPLY_DOM isl_union_set
+
+#include <isl_multi_apply_templ.c>
+
+#undef APPLY_DOMBASE
+#undef APPLY_DOM
Added: polly/trunk/lib/External/isl/isl_multi_floor.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_multi_floor.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_multi_floor.c (added)
+++ polly/trunk/lib/External/isl/isl_multi_floor.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2014 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl_multi_macro.h>
+
+/* Given f, return floor(f).
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),floor)(__isl_take MULTI(BASE) *multi)
+{
+ int i;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,floor)(multi->p[i]);
+ if (!multi->p[i])
+ return FN(MULTI(BASE),free)(multi);
+ }
+
+ return multi;
+}
Added: polly/trunk/lib/External/isl/isl_multi_gist.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_multi_gist.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_multi_gist.c (added)
+++ polly/trunk/lib/External/isl/isl_multi_gist.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 Sven Verdoolaege
+ * Copyright 2012-2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ */
+
+#include <isl_multi_macro.h>
+
+/* Compute the gist of "multi" with respect to the domain constraints
+ * of "context".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),gist)(__isl_take MULTI(BASE) *multi,
+ __isl_take DOM *context)
+{
+ return FN(FN(MULTI(BASE),apply),DOMBASE)(multi, context, &FN(EL,gist));
+}
+
+/* Compute the gist of "multi" with respect to the parameter constraints
+ * of "context".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),gist_params)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *context)
+{
+ return FN(MULTI(BASE),apply_set)(multi, context, &FN(EL,gist_params));
+}
Added: polly/trunk/lib/External/isl/isl_multi_intersect.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_multi_intersect.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_multi_intersect.c (added)
+++ polly/trunk/lib/External/isl/isl_multi_intersect.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 Sven Verdoolaege
+ * Copyright 2012-2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d’Ulm, 75230 Paris, France
+ */
+
+#include <isl_multi_macro.h>
+
+/* Intersect the domain of "multi" with "domain".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_domain)(
+ __isl_take MULTI(BASE) *multi, __isl_take DOM *domain)
+{
+ return FN(FN(MULTI(BASE),apply),DOMBASE)(multi, domain,
+ &FN(EL,intersect_domain));
+}
+
+/* Intersect the parameter domain of "multi" with "domain".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_params)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
+{
+ return FN(MULTI(BASE),apply_set)(multi, domain,
+ &FN(EL,intersect_params));
+}
Added: polly/trunk/lib/External/isl/isl_multi_macro.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_multi_macro.h?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_multi_macro.h (added)
+++ polly/trunk/lib/External/isl/isl_multi_macro.h Mon Feb 16 13:33:40 2015
@@ -0,0 +1,10 @@
+#define xCAT(A,B) A ## B
+#define CAT(A,B) xCAT(A,B)
+#undef EL
+#define EL CAT(isl_,BASE)
+#define xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define FN(TYPE,NAME) xFN(TYPE,NAME)
+#define xMULTI(BASE) isl_multi_ ## BASE
+#define MULTI(BASE) xMULTI(BASE)
+#undef DOM
+#define DOM CAT(isl_,DOMBASE)
Modified: polly/trunk/lib/External/isl/isl_multi_templ.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_multi_templ.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_multi_templ.c (original)
+++ polly/trunk/lib/External/isl/isl_multi_templ.c Mon Feb 16 13:33:40 2015
@@ -12,14 +12,8 @@
#include <isl/set.h>
#include <isl_reordering.h>
-#define xCAT(A,B) A ## B
-#define CAT(A,B) xCAT(A,B)
-#undef EL
-#define EL CAT(isl_,BASE)
-#define xFN(TYPE,NAME) TYPE ## _ ## NAME
-#define FN(TYPE,NAME) xFN(TYPE,NAME)
-#define xMULTI(BASE) isl_multi_ ## BASE
-#define MULTI(BASE) xMULTI(BASE)
+#include <isl_multi_macro.h>
+
#define MULTI_NAME(BASE) "isl_multi_" #BASE
#define xLIST(EL) EL ## _list
#define LIST(EL) xLIST(EL)
@@ -135,6 +129,7 @@ __isl_null MULTI(BASE) *FN(MULTI(BASE),f
return NULL;
}
+#ifndef NO_DIMS
/* Check whether "multi" has non-zero coefficients for any dimension
* in the given range or if any of these dimensions appear
* with non-zero coefficients in any of the integer divisions involved.
@@ -201,6 +196,7 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),a
return FN(MULTI(BASE),insert_dims)(multi, type, pos, n);
}
+#endif
unsigned FN(MULTI(BASE),dim)(__isl_keep MULTI(BASE) *multi,
enum isl_dim_type type)
@@ -544,154 +540,6 @@ error:
return NULL;
}
-#if !defined(NO_GIST) || !defined(NO_INTERSECT_DOMAIN)
-static __isl_give MULTI(BASE) *FN(MULTI(BASE),align_params_multi_set_and)(
- __isl_take MULTI(BASE) *multi, __isl_take isl_set *set,
- __isl_give MULTI(BASE) *(*fn)(__isl_take MULTI(BASE) *multi,
- __isl_take isl_set *set))
-{
- isl_ctx *ctx;
-
- if (!multi || !set)
- goto error;
- if (isl_space_match(multi->space, isl_dim_param,
- set->dim, isl_dim_param))
- return fn(multi, set);
- ctx = FN(MULTI(BASE),get_ctx)(multi);
- if (!isl_space_has_named_params(multi->space) ||
- !isl_space_has_named_params(set->dim))
- isl_die(ctx, isl_error_invalid,
- "unaligned unnamed parameters", goto error);
- multi = FN(MULTI(BASE),align_params)(multi, isl_set_get_space(set));
- set = isl_set_align_params(set, FN(MULTI(BASE),get_space)(multi));
- return fn(multi, set);
-error:
- FN(MULTI(BASE),free)(multi);
- isl_set_free(set);
- return NULL;
-}
-#endif
-
-#ifndef NO_GIST
-__isl_give MULTI(BASE) *FN(MULTI(BASE),gist_aligned)(
- __isl_take MULTI(BASE) *multi, __isl_take isl_set *context)
-{
- int i;
-
- multi = FN(MULTI(BASE),cow)(multi);
- if (!multi || !context)
- goto error;
-
- for (i = 0; i < multi->n; ++i) {
- multi->p[i] = FN(EL,gist)(multi->p[i], isl_set_copy(context));
- if (!multi->p[i])
- goto error;
- }
-
- isl_set_free(context);
- return multi;
-error:
- isl_set_free(context);
- FN(MULTI(BASE),free)(multi);
- return NULL;
-}
-
-__isl_give MULTI(BASE) *FN(MULTI(BASE),gist)(__isl_take MULTI(BASE) *multi,
- __isl_take isl_set *context)
-{
- return FN(MULTI(BASE),align_params_multi_set_and)(multi, context,
- &FN(MULTI(BASE),gist_aligned));
-}
-
-__isl_give MULTI(BASE) *FN(MULTI(BASE),gist_params)(
- __isl_take MULTI(BASE) *multi, __isl_take isl_set *context)
-{
- isl_space *space = FN(MULTI(BASE),get_domain_space)(multi);
- isl_set *dom_context = isl_set_universe(space);
- dom_context = isl_set_intersect_params(dom_context, context);
- return FN(MULTI(BASE),gist)(multi, dom_context);
-}
-#endif
-
-#ifndef NO_INTERSECT_DOMAIN
-/* Transform the domain of "multi" by combining it with "domain"
- * using "fn".
- *
- * The parameters of "multi" and "domain" are assumed to have been aligned.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_aligned)(
- __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain,
- __isl_give EL *(*fn)(EL *el, __isl_take isl_set *set2))
-{
- int i;
-
- if (!multi || !domain)
- goto error;
-
- if (multi->n == 0) {
- isl_set_free(domain);
- return multi;
- }
-
- multi = FN(MULTI(BASE),cow)(multi);
- if (!multi)
- goto error;
-
- for (i = 0; i < multi->n; ++i) {
- multi->p[i] = fn(multi->p[i], isl_set_copy(domain));
- if (!multi->p[i])
- goto error;
- }
-
- isl_set_free(domain);
- return multi;
-error:
- isl_set_free(domain);
- FN(MULTI(BASE),free)(multi);
- return NULL;
-}
-
-/* Intersect the domain of "multi" with "domain".
- *
- * The parameters of "multi" and "domain" are assumed to have been aligned.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_domain_aligned)(
- __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
-{
- return FN(MULTI(BASE),intersect_aligned)(multi, domain,
- &FN(EL,intersect_domain));
-}
-
-/* Intersect the domain of "multi" with "domain".
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_domain)(
- __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
-{
- return FN(MULTI(BASE),align_params_multi_set_and)(multi, domain,
- &FN(MULTI(BASE),intersect_domain_aligned));
-}
-
-/* Intersect the parameter domain of "multi" with "domain".
- *
- * The parameters of "multi" and "domain" are assumed to have been aligned.
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_params_aligned)(
- __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
-{
- return FN(MULTI(BASE),intersect_aligned)(multi, domain,
- &FN(EL,intersect_params));
-}
-
-/* Intersect the parameter domain of "multi" with "domain".
- */
-__isl_give MULTI(BASE) *FN(MULTI(BASE),intersect_params)(
- __isl_take MULTI(BASE) *multi, __isl_take isl_set *domain)
-{
- return FN(MULTI(BASE),align_params_multi_set_and)(multi, domain,
- &FN(MULTI(BASE),intersect_params_aligned));
-}
-#endif
-
__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),LIST(BASE))(
__isl_take isl_space *space, __isl_take LIST(EL) *list)
{
@@ -773,6 +621,7 @@ error:
}
#endif
+#ifndef NO_ZERO
/* Construct a multi expression in the given space with value zero in
* each of the output dimensions.
*/
@@ -807,13 +656,29 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),z
return multi;
}
+#endif
#ifndef NO_FROM_BASE
+/* Create a multiple expression with a single output/set dimension
+ * equal to "el".
+ * For most multiple expression types, the base type has a single
+ * output/set dimension and the space of the result is therefore
+ * the same as the space of the input.
+ * In the case of isl_multi_union_pw_aff, however, the base type
+ * lives in a parameter space and we therefore need to add
+ * a single set dimension.
+ */
__isl_give MULTI(BASE) *FN(FN(MULTI(BASE),from),BASE)(__isl_take EL *el)
{
+ isl_space *space;
MULTI(BASE) *multi;
- multi = FN(MULTI(BASE),alloc)(FN(EL,get_space)(el));
+ space = FN(EL,get_space(el));
+ if (isl_space_is_params(space)) {
+ space = isl_space_set_from_params(space);
+ space = isl_space_add_dims(space, isl_dim_set, 1);
+ }
+ multi = FN(MULTI(BASE),alloc)(space);
multi = FN(FN(MULTI(BASE),set),BASE)(multi, 0, el);
return multi;
@@ -1002,6 +867,7 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),r
return multi;
}
+#ifndef NO_PRODUCT
/* Given two MULTI(BASE)s A -> B and C -> D,
* construct a MULTI(BASE) [A -> C] -> [B -> D].
*
@@ -1054,6 +920,7 @@ __isl_give MULTI(BASE) *FN(MULTI(BASE),p
return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
&FN(MULTI(BASE),product_aligned));
}
+#endif
__isl_give MULTI(BASE) *FN(MULTI(BASE),flatten_range)(
__isl_take MULTI(BASE) *multi)
@@ -1129,6 +996,7 @@ error:
return NULL;
}
+#ifndef NO_SPLICE
/* Given two multi expressions, "multi1"
*
* [A1 A2] -> [B1 B2]
@@ -1180,6 +1048,7 @@ error:
FN(MULTI(BASE),free)(multi2);
return NULL;
}
+#endif
/* This function is currently only used from isl_aff.c
*/
@@ -1221,6 +1090,25 @@ error:
return NULL;
}
+/* Subtract "multi2" from "multi1" and return the result.
+ *
+ * The parameters of "multi1" and "multi2" are assumed to have been aligned.
+ */
+static __isl_give MULTI(BASE) *FN(MULTI(BASE),sub_aligned)(
+ __isl_take MULTI(BASE) *multi1, __isl_take MULTI(BASE) *multi2)
+{
+ return FN(MULTI(BASE),bin_op)(multi1, multi2, &FN(EL,sub));
+}
+
+/* Subtract "multi2" from "multi1" and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),sub)(__isl_take MULTI(BASE) *multi1,
+ __isl_take MULTI(BASE) *multi2)
+{
+ return FN(MULTI(BASE),align_params_multi_multi_and)(multi1, multi2,
+ &FN(MULTI(BASE),sub_aligned));
+}
+
/* Multiply the elements of "multi" by "v" and return the result.
*/
__isl_give MULTI(BASE) *FN(MULTI(BASE),scale_val)(__isl_take MULTI(BASE) *multi,
@@ -1369,6 +1257,42 @@ error:
return FN(MULTI(BASE),free)(multi);
}
+/* Compute the residues of the elements of "multi" modulo
+ * the corresponding element of "mv" and return the result.
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),mod_multi_val)(
+ __isl_take MULTI(BASE) *multi, __isl_take isl_multi_val *mv)
+{
+ int i;
+
+ if (!multi || !mv)
+ goto error;
+
+ if (!isl_space_tuple_is_equal(multi->space, isl_dim_out,
+ mv->space, isl_dim_set))
+ isl_die(isl_multi_val_get_ctx(mv), isl_error_invalid,
+ "spaces don't match", goto error);
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ for (i = 0; i < multi->n; ++i) {
+ isl_val *v;
+
+ v = isl_multi_val_get_val(mv, i);
+ multi->p[i] = FN(EL,mod_val)(multi->p[i], v);
+ if (!multi->p[i])
+ goto error;
+ }
+
+ isl_multi_val_free(mv);
+ return multi;
+error:
+ isl_multi_val_free(mv);
+ return FN(MULTI(BASE),free)(multi);
+}
+
#ifndef NO_MOVE_DIMS
/* Move the "n" dimensions of "src_type" starting at "src_pos" of "multi"
* to dimensions of "dst_type" at "dst_pos".
@@ -1496,3 +1420,24 @@ __isl_give isl_set *FN(MULTI(BASE),domai
return dom;
}
#endif
+
+#ifndef NO_NEG
+/* Return the opposite of "multi".
+ */
+__isl_give MULTI(BASE) *FN(MULTI(BASE),neg)(__isl_take MULTI(BASE) *multi)
+{
+ int i;
+
+ multi = FN(MULTI(BASE),cow)(multi);
+ if (!multi)
+ return NULL;
+
+ for (i = 0; i < multi->n; ++i) {
+ multi->p[i] = FN(EL,neg)(multi->p[i]);
+ if (!multi->p[i])
+ return FN(MULTI(BASE),free)(multi);
+ }
+
+ return multi;
+}
+#endif
Modified: polly/trunk/lib/External/isl/isl_multi_templ.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_multi_templ.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_multi_templ.h (original)
+++ polly/trunk/lib/External/isl/isl_multi_templ.h Mon Feb 16 13:33:40 2015
@@ -1,11 +1,6 @@
#include <isl/space.h>
-#define xCAT(A,B) A ## B
-#define CAT(A,B) xCAT(A,B)
-#undef EL
-#define EL CAT(isl_,BASE)
-#define xMULTI(BASE) isl_multi_ ## BASE
-#define MULTI(BASE) xMULTI(BASE)
+#include <isl_multi_macro.h>
struct MULTI(BASE) {
int ref;
Modified: polly/trunk/lib/External/isl/isl_obj.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_obj.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_obj.c (original)
+++ polly/trunk/lib/External/isl/isl_obj.c Mon Feb 16 13:33:40 2015
@@ -1,6 +1,7 @@
/*
* Copyright 2010 INRIA Saclay
* Copyright 2014 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
*
* Use of this software is governed by the MIT license
*
@@ -8,12 +9,15 @@
* Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
* 91893 Orsay, France
* and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
*/
#include <isl/aff.h>
#include <isl/set.h>
#include <isl/map.h>
#include <isl/polynomial.h>
+#include <isl/schedule.h>
#include <isl/obj.h>
static void *isl_obj_val_copy(void *v)
@@ -333,3 +337,26 @@ struct isl_obj_vtable isl_obj_union_pw_q
isl_obj_union_pw_qpf_print,
isl_obj_union_pw_qpf_free
};
+
+static void *isl_obj_schedule_copy(void *v)
+{
+ return isl_schedule_copy((isl_schedule *) v);
+}
+
+static void isl_obj_schedule_free(void *v)
+{
+ isl_schedule_free((isl_schedule *) v);
+}
+
+static __isl_give isl_printer *isl_obj_schedule_print(
+ __isl_take isl_printer *p, void *v)
+{
+ return isl_printer_print_schedule(p, (isl_schedule *) v);
+}
+
+struct isl_obj_vtable isl_obj_schedule_vtable = {
+ isl_obj_schedule_copy,
+ NULL,
+ isl_obj_schedule_print,
+ isl_obj_schedule_free
+};
Modified: polly/trunk/lib/External/isl/isl_output.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_output.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_output.c (original)
+++ polly/trunk/lib/External/isl/isl_output.c Mon Feb 16 13:33:40 2015
@@ -1008,24 +1008,6 @@ error:
return NULL;
}
-void isl_basic_map_print(__isl_keep isl_basic_map *bmap, FILE *out, int indent,
- const char *prefix, const char *suffix, unsigned output_format)
-{
- isl_printer *printer;
-
- if (!bmap)
- return;
-
- printer = isl_printer_to_file(bmap->ctx, out);
- printer = isl_printer_set_indent(printer, indent);
- printer = isl_printer_set_prefix(printer, prefix);
- printer = isl_printer_set_suffix(printer, suffix);
- printer = isl_printer_set_output_format(printer, output_format);
- isl_printer_print_basic_map(printer, bmap);
-
- isl_printer_free(printer);
-}
-
__isl_give isl_printer *isl_printer_print_basic_set(__isl_take isl_printer *p,
__isl_keep isl_basic_set *bset)
{
@@ -1048,24 +1030,6 @@ error:
return NULL;
}
-void isl_basic_set_print(struct isl_basic_set *bset, FILE *out, int indent,
- const char *prefix, const char *suffix, unsigned output_format)
-{
- isl_printer *printer;
-
- if (!bset)
- return;
-
- printer = isl_printer_to_file(bset->ctx, out);
- printer = isl_printer_set_indent(printer, indent);
- printer = isl_printer_set_prefix(printer, prefix);
- printer = isl_printer_set_suffix(printer, suffix);
- printer = isl_printer_set_output_format(printer, output_format);
- isl_printer_print_basic_set(printer, bset);
-
- isl_printer_free(printer);
-}
-
__isl_give isl_printer *isl_printer_print_set(__isl_take isl_printer *p,
__isl_keep isl_set *set)
{
@@ -1087,22 +1051,6 @@ error:
return NULL;
}
-void isl_set_print(struct isl_set *set, FILE *out, int indent,
- unsigned output_format)
-{
- isl_printer *printer;
-
- if (!set)
- return;
-
- printer = isl_printer_to_file(set->ctx, out);
- printer = isl_printer_set_indent(printer, indent);
- printer = isl_printer_set_output_format(printer, output_format);
- printer = isl_printer_print_set(printer, set);
-
- isl_printer_free(printer);
-}
-
__isl_give isl_printer *isl_printer_print_map(__isl_take isl_printer *p,
__isl_keep isl_map *map)
{
@@ -1225,22 +1173,6 @@ error:
return NULL;
}
-void isl_map_print(__isl_keep isl_map *map, FILE *out, int indent,
- unsigned output_format)
-{
- isl_printer *printer;
-
- if (!map)
- return;
-
- printer = isl_printer_to_file(map->ctx, out);
- printer = isl_printer_set_indent(printer, indent);
- printer = isl_printer_set_output_format(printer, output_format);
- printer = isl_printer_print_map(printer, map);
-
- isl_printer_free(printer);
-}
-
static int upoly_rec_n_non_zero(__isl_keep struct isl_upoly_rec *rec)
{
int i;
@@ -2161,11 +2093,31 @@ error:
return NULL;
}
+/* Print the body of an isl_pw_aff, i.e., a semicolon delimited
+ * sequence of affine expressions, each followed by constraints.
+ */
+static __isl_give isl_printer *print_pw_aff_body(
+ __isl_take isl_printer *p, __isl_keep isl_pw_aff *pa)
+{
+ int i;
+
+ if (!pa)
+ return isl_printer_free(p);
+
+ for (i = 0; i < pa->n; ++i) {
+ if (i)
+ p = isl_printer_print_str(p, "; ");
+ p = print_aff(p, pa->p[i].aff);
+ p = print_disjuncts((isl_map *)pa->p[i].set, p, 0);
+ }
+
+ return p;
+}
+
static __isl_give isl_printer *print_pw_aff_isl(__isl_take isl_printer *p,
__isl_keep isl_pw_aff *pwaff)
{
struct isl_print_space_data data = { 0 };
- int i;
if (!pwaff)
goto error;
@@ -2175,12 +2127,7 @@ static __isl_give isl_printer *print_pw_
p = isl_printer_print_str(p, " -> ");
}
p = isl_printer_print_str(p, "{ ");
- for (i = 0; i < pwaff->n; ++i) {
- if (i)
- p = isl_printer_print_str(p, "; ");
- p = print_aff(p, pwaff->p[i].aff);
- p = print_disjuncts((isl_map *)pwaff->p[i].set, p, 0);
- }
+ p = print_pw_aff_body(p, pwaff);
p = isl_printer_print_str(p, " }");
return p;
error:
@@ -2345,6 +2292,84 @@ error:
return NULL;
}
+/* Print "pa" in a sequence of isl_pw_affs delimited by semicolons.
+ * Each isl_pw_aff itself is also printed as semicolon delimited
+ * sequence of pieces.
+ * If data->first = 1, then this is the first in the sequence.
+ * Update data->first to tell the next element that it is not the first.
+ */
+static int print_pw_aff_body_wrap(__isl_take isl_pw_aff *pa,
+ void *user)
+{
+ struct isl_union_print_data *data;
+ data = (struct isl_union_print_data *) user;
+
+ if (!data->first)
+ data->p = isl_printer_print_str(data->p, "; ");
+ data->first = 0;
+
+ data->p = print_pw_aff_body(data->p, pa);
+ isl_pw_aff_free(pa);
+
+ return data->p ? 0 : -1;
+}
+
+/* Print the body of an isl_union_pw_aff, i.e., a semicolon delimited
+ * sequence of affine expressions, each followed by constraints,
+ * with the sequence enclosed in braces.
+ */
+static __isl_give isl_printer *print_union_pw_aff_body(
+ __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa)
+{
+ struct isl_union_print_data data = { p, 1 };
+
+ p = isl_printer_print_str(p, s_open_set[0]);
+ data.p = p;
+ if (isl_union_pw_aff_foreach_pw_aff(upa,
+ &print_pw_aff_body_wrap, &data) < 0)
+ data.p = isl_printer_free(p);
+ p = data.p;
+ p = isl_printer_print_str(p, s_close_set[0]);
+
+ return p;
+}
+
+/* Print the isl_union_pw_aff "upa" to "p" in isl format.
+ *
+ * The individual isl_pw_affs are delimited by a semicolon.
+ */
+static __isl_give isl_printer *print_union_pw_aff_isl(
+ __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa)
+{
+ struct isl_print_space_data data = { 0 };
+ isl_space *space;
+
+ space = isl_union_pw_aff_get_space(upa);
+ if (isl_space_dim(space, isl_dim_param) > 0) {
+ p = print_tuple(space, p, isl_dim_param, &data);
+ p = isl_printer_print_str(p, s_to[0]);
+ }
+ isl_space_free(space);
+ p = print_union_pw_aff_body(p, upa);
+ return p;
+}
+
+/* Print the isl_union_pw_aff "upa" to "p".
+ *
+ * We currently only support an isl format.
+ */
+__isl_give isl_printer *isl_printer_print_union_pw_aff(
+ __isl_take isl_printer *p, __isl_keep isl_union_pw_aff *upa)
+{
+ if (!p || !upa)
+ return isl_printer_free(p);
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_union_pw_aff_isl(p, upa);
+ isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
+ "unsupported output format", return isl_printer_free(p));
+}
+
/* Print dimension "pos" of data->space to "p".
*
* data->user is assumed to be an isl_multi_aff.
@@ -2696,3 +2721,64 @@ __isl_give isl_printer *isl_printer_prin
isl_die(p->ctx, isl_error_unsupported, "unsupported output format",
return isl_printer_free(p));
}
+
+/* Print dimension "pos" of data->space to "p".
+ *
+ * data->user is assumed to be an isl_multi_union_pw_aff.
+ *
+ * The current dimension is necessarily a set dimension, so
+ * we print the corresponding isl_union_pw_aff, including
+ * the braces.
+ */
+static __isl_give isl_printer *print_union_pw_aff_dim(__isl_take isl_printer *p,
+ struct isl_print_space_data *data, unsigned pos)
+{
+ isl_multi_union_pw_aff *mupa = data->user;
+ isl_union_pw_aff *upa;
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(mupa, pos);
+ p = print_union_pw_aff_body(p, upa);
+ isl_union_pw_aff_free(upa);
+
+ return p;
+}
+
+/* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format.
+ */
+static __isl_give isl_printer *print_multi_union_pw_aff_isl(
+ __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa)
+{
+ struct isl_print_space_data data = { 0 };
+ isl_space *space;
+
+ space = isl_multi_union_pw_aff_get_space(mupa);
+ if (isl_space_dim(space, isl_dim_param) > 0) {
+ struct isl_print_space_data space_data = { 0 };
+ p = print_tuple(space, p, isl_dim_param, &space_data);
+ p = isl_printer_print_str(p, s_to[0]);
+ }
+
+ data.print_dim = &print_union_pw_aff_dim;
+ data.user = mupa;
+
+ p = print_space(space, p, 0, &data);
+ isl_space_free(space);
+
+ return p;
+}
+
+/* Print the isl_multi_union_pw_aff "mupa" to "p" in isl format.
+ *
+ * We currently only support an isl format.
+ */
+__isl_give isl_printer *isl_printer_print_multi_union_pw_aff(
+ __isl_take isl_printer *p, __isl_keep isl_multi_union_pw_aff *mupa)
+{
+ if (!p || !mupa)
+ return isl_printer_free(p);
+
+ if (p->output_format == ISL_FORMAT_ISL)
+ return print_multi_union_pw_aff_isl(p, mupa);
+ isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
+ "unsupported output format", return isl_printer_free(p));
+}
Modified: polly/trunk/lib/External/isl/isl_polynomial.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_polynomial.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_polynomial.c (original)
+++ polly/trunk/lib/External/isl/isl_polynomial.c Mon Feb 16 13:33:40 2015
@@ -2808,7 +2808,6 @@ __isl_give isl_pw_qpolynomial *isl_pw_qp
#define PART isl_pw_qpolynomial
#undef PARTS
#define PARTS pw_qpolynomial
-#define ALIGN_DOMAIN
#include <isl_union_templ.c>
@@ -4060,37 +4059,12 @@ error:
return NULL;
}
-static int neg_entry(void **entry, void *user)
-{
- isl_pw_qpolynomial **pwqp = (isl_pw_qpolynomial **)entry;
-
- *pwqp = isl_pw_qpolynomial_neg(*pwqp);
-
- return *pwqp ? 0 : -1;
-}
-
-__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_neg(
- __isl_take isl_union_pw_qpolynomial *upwqp)
-{
- upwqp = isl_union_pw_qpolynomial_cow(upwqp);
- if (!upwqp)
- return NULL;
-
- if (isl_hash_table_foreach(upwqp->space->ctx, &upwqp->table,
- &neg_entry, NULL) < 0)
- goto error;
-
- return upwqp;
-error:
- isl_union_pw_qpolynomial_free(upwqp);
- return NULL;
-}
-
__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_mul(
__isl_take isl_union_pw_qpolynomial *upwqp1,
__isl_take isl_union_pw_qpolynomial *upwqp2)
{
- return match_bin_op(upwqp1, upwqp2, &isl_pw_qpolynomial_mul);
+ return isl_union_pw_qpolynomial_match_bin_op(upwqp1, upwqp2,
+ &isl_pw_qpolynomial_mul);
}
/* Reorder the columns of the given div definitions according to the
Modified: polly/trunk/lib/External/isl/isl_printer.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_printer.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_printer.c (original)
+++ polly/trunk/lib/External/isl/isl_printer.c Mon Feb 16 13:33:40 2015
@@ -118,6 +118,7 @@ static __isl_give isl_printer *str_end_l
static __isl_give isl_printer *str_flush(__isl_take isl_printer *p)
{
p->buf_n = 0;
+ p->buf[p->buf_n] = '\0';
return p;
}
@@ -212,7 +213,7 @@ static struct isl_printer_ops str_ops =
__isl_give isl_printer *isl_printer_to_file(isl_ctx *ctx, FILE *file)
{
- struct isl_printer *p = isl_alloc_type(ctx, struct isl_printer);
+ struct isl_printer *p = isl_calloc_type(ctx, struct isl_printer);
if (!p)
return NULL;
p->ctx = ctx;
@@ -228,6 +229,7 @@ __isl_give isl_printer *isl_printer_to_f
p->prefix = NULL;
p->suffix = NULL;
p->width = 0;
+ p->yaml_style = ISL_YAML_STYLE_FLOW;
return p;
}
@@ -253,6 +255,7 @@ __isl_give isl_printer *isl_printer_to_s
p->prefix = NULL;
p->suffix = NULL;
p->width = 0;
+ p->yaml_style = ISL_YAML_STYLE_FLOW;
return p;
error:
@@ -268,6 +271,7 @@ __isl_null isl_printer *isl_printer_free
free(p->indent_prefix);
free(p->prefix);
free(p->suffix);
+ free(p->yaml_state);
isl_ctx_deref(p->ctx);
free(p);
@@ -380,6 +384,161 @@ int isl_printer_get_output_format(__isl_
return p->output_format;
}
+/* Set the YAML style of "p" to "yaml_style" and return the updated printer.
+ */
+__isl_give isl_printer *isl_printer_set_yaml_style(__isl_take isl_printer *p,
+ int yaml_style)
+{
+ if (!p)
+ return NULL;
+
+ p->yaml_style = yaml_style;
+
+ return p;
+}
+
+/* Return the YAML style of "p" or -1 on error.
+ */
+int isl_printer_get_yaml_style(__isl_keep isl_printer *p)
+{
+ if (!p)
+ return -1;
+ return p->yaml_style;
+}
+
+/* Push "state" onto the stack of currently active YAML elements and
+ * return the updated printer.
+ */
+static __isl_give isl_printer *push_state(__isl_take isl_printer *p,
+ enum isl_yaml_state state)
+{
+ if (!p)
+ return NULL;
+
+ if (p->yaml_size < p->yaml_depth + 1) {
+ enum isl_yaml_state *state;
+ state = isl_realloc_array(p->ctx, p->yaml_state,
+ enum isl_yaml_state, p->yaml_depth + 1);
+ if (!state)
+ return isl_printer_free(p);
+ p->yaml_state = state;
+ p->yaml_size = p->yaml_depth + 1;
+ }
+
+ p->yaml_state[p->yaml_depth] = state;
+ p->yaml_depth++;
+
+ return p;
+}
+
+/* Remove the innermost active YAML element from the stack and
+ * return the updated printer.
+ */
+static __isl_give isl_printer *pop_state(__isl_take isl_printer *p)
+{
+ if (!p)
+ return NULL;
+ p->yaml_depth--;
+ return p;
+}
+
+/* Set the state of the innermost active YAML element to "state" and
+ * return the updated printer.
+ */
+static __isl_give isl_printer *update_state(__isl_take isl_printer *p,
+ enum isl_yaml_state state)
+{
+ if (!p)
+ return NULL;
+ if (p->yaml_depth < 1)
+ isl_die(isl_printer_get_ctx(p), isl_error_invalid,
+ "not in YAML construct", return isl_printer_free(p));
+
+ p->yaml_state[p->yaml_depth - 1] = state;
+
+ return p;
+}
+
+/* Return the state of the innermost active YAML element.
+ * Return isl_yaml_none if we are not inside any YAML element.
+ */
+static enum isl_yaml_state current_state(__isl_keep isl_printer *p)
+{
+ if (!p)
+ return isl_yaml_none;
+ if (p->yaml_depth < 1)
+ return isl_yaml_none;
+ return p->yaml_state[p->yaml_depth - 1];
+}
+
+/* If we are printing a YAML document and we are at the start of an element,
+ * print whatever is needed before we can print the actual element and
+ * keep track of the fact that we are now printing the element.
+ * If "eol" is set, then whatever we print is going to be the last
+ * thing that gets printed on this line.
+ *
+ * If we are about the print the first key of a mapping, then nothing
+ * extra needs to be printed. For any other key, however, we need
+ * to either move to the next line (in block format) or print a comma
+ * (in flow format).
+ * Before printing a value in a mapping, we need to print a colon.
+ *
+ * For sequences, in flow format, we only need to print a comma
+ * for each element except the first.
+ * In block format, before the first element in the sequence,
+ * we move to a new line, print a dash and increase the indentation.
+ * Before any other element, we print a dash on a new line,
+ * temporarily moving the indentation back.
+ */
+static __isl_give isl_printer *enter_state(__isl_take isl_printer *p,
+ int eol)
+{
+ enum isl_yaml_state state;
+
+ if (!p)
+ return NULL;
+
+ state = current_state(p);
+ if (state == isl_yaml_mapping_val_start) {
+ if (eol)
+ p = p->ops->print_str(p, ":");
+ else
+ p = p->ops->print_str(p, ": ");
+ p = update_state(p, isl_yaml_mapping_val);
+ } else if (state == isl_yaml_mapping_first_key_start) {
+ p = update_state(p, isl_yaml_mapping_key);
+ } else if (state == isl_yaml_mapping_key_start) {
+ if (p->yaml_style == ISL_YAML_STYLE_FLOW)
+ p = p->ops->print_str(p, ", ");
+ else {
+ p = p->ops->end_line(p);
+ p = p->ops->start_line(p);
+ }
+ p = update_state(p, isl_yaml_mapping_key);
+ } else if (state == isl_yaml_sequence_first_start) {
+ if (p->yaml_style != ISL_YAML_STYLE_FLOW) {
+ p = p->ops->end_line(p);
+ p = p->ops->start_line(p);
+ p = p->ops->print_str(p, "- ");
+ p = isl_printer_indent(p, 2);
+ }
+ p = update_state(p, isl_yaml_sequence);
+ } else if (state == isl_yaml_sequence_start) {
+ if (p->yaml_style == ISL_YAML_STYLE_FLOW)
+ p = p->ops->print_str(p, ", ");
+ else {
+ p = p->ops->end_line(p);
+ p = isl_printer_indent(p, -2);
+ p = p->ops->start_line(p);
+ p = p->ops->print_str(p, "- ");
+ p = isl_printer_indent(p, 2);
+ }
+ p = update_state(p, isl_yaml_sequence);
+ }
+
+ return p;
+}
+
__isl_give isl_printer *isl_printer_print_str(__isl_take isl_printer *p,
const char *s)
{
@@ -387,13 +546,16 @@ __isl_give isl_printer *isl_printer_prin
return NULL;
if (!s)
return isl_printer_free(p);
-
+ p = enter_state(p, 0);
+ if (!p)
+ return NULL;
return p->ops->print_str(p, s);
}
__isl_give isl_printer *isl_printer_print_double(__isl_take isl_printer *p,
double d)
{
+ p = enter_state(p, 0);
if (!p)
return NULL;
@@ -402,6 +564,7 @@ __isl_give isl_printer *isl_printer_prin
__isl_give isl_printer *isl_printer_print_int(__isl_take isl_printer *p, int i)
{
+ p = enter_state(p, 0);
if (!p)
return NULL;
@@ -411,6 +574,7 @@ __isl_give isl_printer *isl_printer_prin
__isl_give isl_printer *isl_printer_print_isl_int(__isl_take isl_printer *p,
isl_int i)
{
+ p = enter_state(p, 0);
if (!p)
return NULL;
@@ -447,3 +611,154 @@ __isl_give isl_printer *isl_printer_flus
return p->ops->flush(p);
}
+
+/* Start a YAML mapping and push a new state to reflect that we
+ * are about to print the first key in a mapping.
+ *
+ * In flow style, print the opening brace.
+ * In block style, move to the next line with an increased indentation,
+ * except if this is the outer mapping or if we are inside a sequence
+ * (in which case we have already increased the indentation and we want
+ * to print the first key on the same line as the dash).
+ */
+__isl_give isl_printer *isl_printer_yaml_start_mapping(
+ __isl_take isl_printer *p)
+{
+ enum isl_yaml_state state;
+
+ p = enter_state(p, p->yaml_style == ISL_YAML_STYLE_BLOCK);
+ if (!p)
+ return NULL;
+ state = current_state(p);
+ if (p->yaml_style == ISL_YAML_STYLE_FLOW)
+ p = p->ops->print_str(p, "{ ");
+ else if (state != isl_yaml_none && state != isl_yaml_sequence) {
+ p = p->ops->end_line(p);
+ p = isl_printer_indent(p, 2);
+ p = p->ops->start_line(p);
+ }
+ p = push_state(p, isl_yaml_mapping_first_key_start);
+ return p;
+}
+
+/* Finish a YAML mapping and pop it from the state stack.
+ *
+ * In flow style, print the closing brace.
+ *
+ * In block style, first check if we are still in the
+ * isl_yaml_mapping_first_key_start state. If so, we have not printed
+ * anything yet, so print "{}" to indicate an empty mapping.
+ * If we increased the indentation in isl_printer_yaml_start_mapping,
+ * then decrease it again.
+ * If this is the outer mapping then print a newline.
+ */
+__isl_give isl_printer *isl_printer_yaml_end_mapping(
+ __isl_take isl_printer *p)
+{
+ enum isl_yaml_state state;
+
+ state = current_state(p);
+ p = pop_state(p);
+ if (!p)
+ return NULL;
+ if (p->yaml_style == ISL_YAML_STYLE_FLOW)
+ return p->ops->print_str(p, " }");
+ if (state == isl_yaml_mapping_first_key_start)
+ p = p->ops->print_str(p, "{}");
+ if (!p)
+ return NULL;
+ state = current_state(p);
+ if (state != isl_yaml_none && state != isl_yaml_sequence)
+ p = isl_printer_indent(p, -2);
+ if (state == isl_yaml_none)
+ p = p->ops->end_line(p);
+ return p;
+}
+
+/* Start a YAML sequence and push a new state to reflect that we
+ * are about to print the first element in a sequence.
+ *
+ * In flow style, print the opening bracket.
+ */
+__isl_give isl_printer *isl_printer_yaml_start_sequence(
+ __isl_take isl_printer *p)
+{
+ p = enter_state(p, p->yaml_style == ISL_YAML_STYLE_BLOCK);
+ p = push_state(p, isl_yaml_sequence_first_start);
+ if (!p)
+ return NULL;
+ if (p->yaml_style == ISL_YAML_STYLE_FLOW)
+ p = p->ops->print_str(p, "[ ");
+ return p;
+}
+
+/* Finish a YAML sequence and pop it from the state stack.
+ *
+ * In flow style, print the closing bracket.
+ *
+ * In block style, check if we are still in the
+ * isl_yaml_sequence_first_start state. If so, we have not printed
+ * anything yet, so print "[]" or " []" to indicate an empty sequence.
+ * We print the extra space when we instructed enter_state not
+ * to print a space at the end of the line.
+ * Otherwise, undo the increase in indentation performed by
+ * enter_state when moving away from the isl_yaml_sequence_first_start
+ * state.
+ * If this is the outer sequence then print a newline.
+ */
+__isl_give isl_printer *isl_printer_yaml_end_sequence(
+ __isl_take isl_printer *p)
+{
+ enum isl_yaml_state state, up;
+
+ state = current_state(p);
+ p = pop_state(p);
+ if (!p)
+ return NULL;
+ if (p->yaml_style == ISL_YAML_STYLE_FLOW)
+ return p->ops->print_str(p, " ]");
+ up = current_state(p);
+ if (state == isl_yaml_sequence_first_start) {
+ if (up == isl_yaml_mapping_val)
+ p = p->ops->print_str(p, " []");
+ else
+ p = p->ops->print_str(p, "[]");
+ } else {
+ p = isl_printer_indent(p, -2);
+ }
+ if (!p)
+ return NULL;
+ state = current_state(p);
+ if (state == isl_yaml_none)
+ p = p->ops->end_line(p);
+ return p;
+}
+
+/* Mark the fact that the current element is finished and that
+ * the next output belongs to the next element.
+ * In particular, if we are printing a key, then prepare for
+ * printing the subsequent value. If we are printing a value,
+ * prepare for printing the next key. If we are printing an
+ * element in a sequence, prepare for printing the next element.
+ */
+__isl_give isl_printer *isl_printer_yaml_next(__isl_take isl_printer *p)
+{
+ enum isl_yaml_state state;
+
+ if (!p)
+ return NULL;
+ if (p->yaml_depth < 1)
+ isl_die(isl_printer_get_ctx(p), isl_error_invalid,
+ "not in YAML construct", return isl_printer_free(p));
+
+ state = current_state(p);
+ if (state == isl_yaml_mapping_key)
+ state = isl_yaml_mapping_val_start;
+ else if (state == isl_yaml_mapping_val)
+ state = isl_yaml_mapping_key_start;
+ else if (state == isl_yaml_sequence)
+ state = isl_yaml_sequence_start;
+ p = update_state(p, state);
+
+ return p;
+}
Modified: polly/trunk/lib/External/isl/isl_printer_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_printer_private.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_printer_private.h (original)
+++ polly/trunk/lib/External/isl/isl_printer_private.h Mon Feb 16 13:33:40 2015
@@ -1,7 +1,18 @@
#include <isl/printer.h>
+#include <isl_yaml.h>
struct isl_printer_ops;
+/* A printer to a file or a string.
+ *
+ * yaml_style is the YAML style in which the next elements should
+ * be printed and may be either ISL_YAML_STYLE_BLOCK or ISL_YAML_STYLE_FLOW,
+ * with ISL_YAML_STYLE_FLOW being the default.
+ * yaml_state keeps track of the currently active YAML elements.
+ * yaml_size is the size of this arrays, while yaml_depth
+ * is the number of elements currently in use.
+ * yaml_state may be NULL if no YAML printing is being performed.
+ */
struct isl_printer {
struct isl_ctx *ctx;
struct isl_printer_ops *ops;
@@ -15,4 +26,9 @@ struct isl_printer {
char *prefix;
char *suffix;
int width;
+
+ int yaml_style;
+ int yaml_depth;
+ int yaml_size;
+ enum isl_yaml_state *yaml_state;
};
Modified: polly/trunk/lib/External/isl/isl_pw_templ.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_pw_templ.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_pw_templ.c (original)
+++ polly/trunk/lib/External/isl/isl_pw_templ.c Mon Feb 16 13:33:40 2015
@@ -644,7 +644,9 @@ __isl_give PW *FN(PW,neg)(__isl_take PW
return pw;
}
+#endif
+#ifndef NO_SUB
__isl_give PW *FN(PW,sub)(__isl_take PW *pw1, __isl_take PW *pw2)
{
return FN(PW,add)(pw1, FN(PW,neg)(pw2));
@@ -802,9 +804,9 @@ __isl_give PW *FN(PW,fix_si)(__isl_take
/* Restrict the domain of "pw" by combining each cell
* with "set" through a call to "fn", where "fn" may be
- * isl_set_intersect or isl_set_intersect_params.
+ * isl_set_intersect, isl_set_intersect_params or isl_set_subtract.
*/
-static __isl_give PW *FN(PW,intersect_aligned)(__isl_take PW *pw,
+static __isl_give PW *FN(PW,restrict_domain_aligned)(__isl_take PW *pw,
__isl_take isl_set *set,
__isl_give isl_set *(*fn)(__isl_take isl_set *set1,
__isl_take isl_set *set2))
@@ -840,7 +842,7 @@ error:
static __isl_give PW *FN(PW,intersect_domain_aligned)(__isl_take PW *pw,
__isl_take isl_set *set)
{
- return FN(PW,intersect_aligned)(pw, set, &isl_set_intersect);
+ return FN(PW,restrict_domain_aligned)(pw, set, &isl_set_intersect);
}
__isl_give PW *FN(PW,intersect_domain)(__isl_take PW *pw,
@@ -853,7 +855,8 @@ __isl_give PW *FN(PW,intersect_domain)(_
static __isl_give PW *FN(PW,intersect_params_aligned)(__isl_take PW *pw,
__isl_take isl_set *set)
{
- return FN(PW,intersect_aligned)(pw, set, &isl_set_intersect_params);
+ return FN(PW,restrict_domain_aligned)(pw, set,
+ &isl_set_intersect_params);
}
/* Intersect the domain of "pw" with the parameter domain "context".
@@ -865,6 +868,24 @@ __isl_give PW *FN(PW,intersect_params)(_
&FN(PW,intersect_params_aligned));
}
+/* Subtract "domain' from the domain of "pw", assuming their
+ * parameters have been aligned.
+ */
+static __isl_give PW *FN(PW,subtract_domain_aligned)(__isl_take PW *pw,
+ __isl_take isl_set *domain)
+{
+ return FN(PW,restrict_domain_aligned)(pw, domain, &isl_set_subtract);
+}
+
+/* Subtract "domain' from the domain of "pw".
+ */
+__isl_give PW *FN(PW,subtract_domain)(__isl_take PW *pw,
+ __isl_take isl_set *domain)
+{
+ return FN(PW,align_params_pw_set_and)(pw, domain,
+ &FN(PW,subtract_domain_aligned));
+}
+
/* Compute the gist of "pw" with respect to the domain constraints
* of "context" for the case where the domain of the last element
* of "pw" is equal to "context".
@@ -1514,6 +1535,19 @@ error:
}
#endif
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the space of "pw".
+ */
+__isl_give PW *FN(PW,reset_user)(__isl_take PW *pw)
+{
+ isl_space *space;
+
+ space = FN(PW,get_space)(pw);
+ space = isl_space_reset_user(space);
+
+ return FN(PW,reset_space)(pw, space);
+}
+
int FN(PW,has_equal_space)(__isl_keep PW *pw1, __isl_keep PW *pw2)
{
if (!pw1 || !pw2)
Modified: polly/trunk/lib/External/isl/isl_schedule.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_schedule.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_schedule.c (original)
+++ polly/trunk/lib/External/isl/isl_schedule.c Mon Feb 16 13:33:40 2015
@@ -14,34 +14,219 @@
#include <isl_aff_private.h>
#include <isl/map.h>
#include <isl/set.h>
+#include <isl/schedule.h>
+#include <isl/schedule_node.h>
#include <isl_sort.h>
#include <isl_schedule_private.h>
+#include <isl_schedule_tree.h>
+#include <isl_schedule_node_private.h>
#include <isl_band_private.h>
+/* Return a schedule encapsulating the given schedule tree.
+ *
+ * We currently only allow schedule trees with a domain as root.
+ *
+ * The leaf field is initialized as a leaf node so that it can be
+ * used to represent leaves in the constructed schedule.
+ * The reference count is set to -1 since the isl_schedule_tree
+ * should never be freed. It is up to the (internal) users of
+ * these leaves to ensure that they are only used while the schedule
+ * is still alive.
+ */
+__isl_give isl_schedule *isl_schedule_from_schedule_tree(isl_ctx *ctx,
+ __isl_take isl_schedule_tree *tree)
+{
+ isl_schedule *schedule;
+
+ if (!tree)
+ return NULL;
+ if (isl_schedule_tree_get_type(tree) != isl_schedule_node_domain)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_unsupported,
+ "root of schedule tree should be a domain",
+ goto error);
+
+ schedule = isl_calloc_type(ctx, isl_schedule);
+ if (!schedule)
+ goto error;
+
+ schedule->leaf.ctx = ctx;
+ isl_ctx_ref(ctx);
+ schedule->ref = 1;
+ schedule->root = tree;
+ schedule->leaf.ref = -1;
+ schedule->leaf.type = isl_schedule_node_leaf;
+
+ return schedule;
+error:
+ isl_schedule_tree_free(tree);
+ return NULL;
+}
+
+/* Return a pointer to a schedule with as single node
+ * a domain node with the given domain.
+ */
+__isl_give isl_schedule *isl_schedule_from_domain(
+ __isl_take isl_union_set *domain)
+{
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+
+ ctx = isl_union_set_get_ctx(domain);
+ tree = isl_schedule_tree_from_domain(domain);
+ return isl_schedule_from_schedule_tree(ctx, tree);
+}
+
+/* Return a pointer to a schedule with as single node
+ * a domain node with an empty domain.
+ */
+__isl_give isl_schedule *isl_schedule_empty(__isl_take isl_space *space)
+{
+ return isl_schedule_from_domain(isl_union_set_empty(space));
+}
+
+/* Return a new reference to "sched".
+ */
+__isl_give isl_schedule *isl_schedule_copy(__isl_keep isl_schedule *sched)
+{
+ if (!sched)
+ return NULL;
+
+ sched->ref++;
+ return sched;
+}
+
+/* Return an isl_schedule that is equal to "schedule" and that has only
+ * a single reference.
+ *
+ * We only need and support this function when the schedule is represented
+ * as a schedule tree.
+ */
+__isl_give isl_schedule *isl_schedule_cow(__isl_take isl_schedule *schedule)
+{
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+
+ if (!schedule)
+ return NULL;
+ if (schedule->ref == 1)
+ return schedule;
+
+ ctx = isl_schedule_get_ctx(schedule);
+ if (!schedule->root)
+ isl_die(ctx, isl_error_internal,
+ "only for schedule tree based schedules",
+ return isl_schedule_free(schedule));
+ schedule->ref--;
+ tree = isl_schedule_tree_copy(schedule->root);
+ return isl_schedule_from_schedule_tree(ctx, tree);
+}
+
__isl_null isl_schedule *isl_schedule_free(__isl_take isl_schedule *sched)
{
- int i;
if (!sched)
return NULL;
if (--sched->ref > 0)
return NULL;
- for (i = 0; i < sched->n; ++i) {
- isl_multi_aff_free(sched->node[i].sched);
- free(sched->node[i].band_end);
- free(sched->node[i].band_id);
- free(sched->node[i].coincident);
- }
- isl_space_free(sched->dim);
isl_band_list_free(sched->band_forest);
+ isl_schedule_tree_free(sched->root);
+ isl_ctx_deref(sched->leaf.ctx);
free(sched);
return NULL;
}
+/* Replace the root of "schedule" by "tree".
+ */
+__isl_give isl_schedule *isl_schedule_set_root(
+ __isl_take isl_schedule *schedule, __isl_take isl_schedule_tree *tree)
+{
+ if (!schedule || !tree)
+ goto error;
+ if (schedule->root == tree) {
+ isl_schedule_tree_free(tree);
+ return schedule;
+ }
+
+ schedule = isl_schedule_cow(schedule);
+ if (!schedule)
+ goto error;
+ isl_schedule_tree_free(schedule->root);
+ schedule->root = tree;
+
+ return schedule;
+error:
+ isl_schedule_free(schedule);
+ isl_schedule_tree_free(tree);
+ return NULL;
+}
+
isl_ctx *isl_schedule_get_ctx(__isl_keep isl_schedule *schedule)
{
- return schedule ? isl_space_get_ctx(schedule->dim) : NULL;
+ return schedule ? schedule->leaf.ctx : NULL;
+}
+
+/* Return a pointer to the leaf of "schedule".
+ *
+ * Even though these leaves are not reference counted, we still
+ * indicate that this function does not return a copy.
+ */
+__isl_keep isl_schedule_tree *isl_schedule_peek_leaf(
+ __isl_keep isl_schedule *schedule)
+{
+ return schedule ? &schedule->leaf : NULL;
+}
+
+/* Return the (parameter) space of the schedule, i.e., the space
+ * of the root domain.
+ */
+__isl_give isl_space *isl_schedule_get_space(
+ __isl_keep isl_schedule *schedule)
+{
+ enum isl_schedule_node_type type;
+ isl_space *space;
+ isl_union_set *domain;
+
+ if (!schedule)
+ return NULL;
+ if (!schedule->root)
+ isl_die(isl_schedule_get_ctx(schedule), isl_error_invalid,
+ "schedule tree representation not available",
+ return NULL);
+ type = isl_schedule_tree_get_type(schedule->root);
+ if (type != isl_schedule_node_domain)
+ isl_die(isl_schedule_get_ctx(schedule), isl_error_internal,
+ "root node not a domain node", return NULL);
+
+ domain = isl_schedule_tree_domain_get_domain(schedule->root);
+ space = isl_union_set_get_space(domain);
+ isl_union_set_free(domain);
+
+ return space;
+}
+
+/* Return a pointer to the root of "schedule".
+ */
+__isl_give isl_schedule_node *isl_schedule_get_root(
+ __isl_keep isl_schedule *schedule)
+{
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+ isl_schedule_tree_list *ancestors;
+
+ if (!schedule)
+ return NULL;
+
+ if (!schedule->root)
+ isl_die(isl_schedule_get_ctx(schedule), isl_error_invalid,
+ "schedule tree representation not available",
+ return NULL);
+
+ ctx = isl_schedule_get_ctx(schedule);
+ tree = isl_schedule_tree_copy(schedule->root);
+ schedule = isl_schedule_copy(schedule);
+ ancestors = isl_schedule_tree_list_alloc(ctx, 0);
+ return isl_schedule_node_alloc(schedule, tree, ancestors, NULL);
}
/* Set max_out to the maximal number of output dimensions over
@@ -114,473 +299,382 @@ static __isl_give isl_union_map *pad_sch
return data.res;
}
-/* Return an isl_union_map of the schedule. If we have already constructed
- * a band forest, then this band forest may have been modified so we need
- * to extract the isl_union_map from the forest rather than from
- * the originally computed schedule. This reconstructed schedule map
+/* Return the domain of the root domain node of "schedule".
+ */
+__isl_give isl_union_set *isl_schedule_get_domain(
+ __isl_keep isl_schedule *schedule)
+{
+ if (!schedule)
+ return NULL;
+ if (!schedule->root)
+ isl_die(isl_schedule_get_ctx(schedule), isl_error_invalid,
+ "schedule tree representation not available",
+ return NULL);
+ return isl_schedule_tree_domain_get_domain(schedule->root);
+}
+
+/* Traverse all nodes of "sched" in depth first preorder.
+ *
+ * If "fn" returns -1 on any of the nodes, then the traversal is aborted.
+ * If "fn" returns 0 on any of the nodes, then the subtree rooted
+ * at that node is skipped.
+ *
+ * Return 0 on success and -1 on failure.
+ */
+int isl_schedule_foreach_schedule_node(__isl_keep isl_schedule *sched,
+ int (*fn)(__isl_keep isl_schedule_node *node, void *user), void *user)
+{
+ isl_schedule_node *node;
+ int r;
+
+ if (!sched)
+ return -1;
+
+ node = isl_schedule_get_root(sched);
+ r = isl_schedule_node_foreach_descendant(node, fn, user);
+ isl_schedule_node_free(node);
+
+ return r;
+}
+
+/* Traverse the node of "sched" in depth first postorder,
+ * allowing the user to modify the visited node.
+ * The traversal continues from the node returned by the callback function.
+ * It is the responsibility of the user to ensure that this does not
+ * lead to an infinite loop. It is safest to always return a pointer
+ * to the same position (same ancestors and child positions) as the input node.
+ */
+__isl_give isl_schedule *isl_schedule_map_schedule_node(
+ __isl_take isl_schedule *schedule,
+ __isl_give isl_schedule_node *(*fn)(
+ __isl_take isl_schedule_node *node, void *user), void *user)
+{
+ isl_schedule_node *node;
+
+ node = isl_schedule_get_root(schedule);
+ isl_schedule_free(schedule);
+
+ node = isl_schedule_node_map_descendant(node, fn, user);
+ schedule = isl_schedule_node_get_schedule(node);
+ isl_schedule_node_free(node);
+
+ return schedule;
+}
+
+/* Return an isl_union_map representation of the schedule.
+ * If we still have access to the schedule tree, then we return
+ * an isl_union_map corresponding to the subtree schedule of the child
+ * of the root domain node. That is, we do not intersect the domain
+ * of the returned isl_union_map with the domain constraints.
+ * Otherwise, we must have removed it because we created a band forest.
+ * If so, we extract the isl_union_map from the forest.
+ * This reconstructed schedule map
* then needs to be padded with zeros to unify the schedule space
* since the result of isl_band_list_get_suffix_schedule may not have
* a unified schedule space.
*/
__isl_give isl_union_map *isl_schedule_get_map(__isl_keep isl_schedule *sched)
{
- int i;
+ enum isl_schedule_node_type type;
+ isl_schedule_node *node;
isl_union_map *umap;
if (!sched)
return NULL;
- if (sched->band_forest) {
- umap = isl_band_list_get_suffix_schedule(sched->band_forest);
- return pad_schedule_map(umap);
- }
-
- umap = isl_union_map_empty(isl_space_copy(sched->dim));
- for (i = 0; i < sched->n; ++i) {
- isl_multi_aff *ma;
+ if (sched->root) {
+ type = isl_schedule_tree_get_type(sched->root);
+ if (type != isl_schedule_node_domain)
+ isl_die(isl_schedule_get_ctx(sched), isl_error_internal,
+ "root node not a domain node", return NULL);
+
+ node = isl_schedule_get_root(sched);
+ node = isl_schedule_node_child(node, 0);
+ umap = isl_schedule_node_get_subtree_schedule_union_map(node);
+ isl_schedule_node_free(node);
- ma = isl_multi_aff_copy(sched->node[i].sched);
- umap = isl_union_map_add_map(umap, isl_map_from_multi_aff(ma));
+ return umap;
}
- return umap;
+ umap = isl_band_list_get_suffix_schedule(sched->band_forest);
+ return pad_schedule_map(umap);
}
static __isl_give isl_band_list *construct_band_list(
- __isl_keep isl_schedule *schedule, __isl_keep isl_band *parent,
- int band_nr, int *parent_active, int n_active);
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *domain,
+ __isl_keep isl_band *parent);
-/* Construct an isl_band structure for the band in the given schedule
- * with sequence number band_nr for the n_active nodes marked by active.
- * If the nodes don't have a band with the given sequence number,
- * then a band without members is created.
- *
- * Because of the way the schedule is constructed, we know that
- * the position of the band inside the schedule of a node is the same
- * for all active nodes.
- *
- * The partial schedule for the band is created before the children
- * are created to that construct_band_list can refer to the partial
- * schedule of the parent.
- */
-static __isl_give isl_band *construct_band(__isl_keep isl_schedule *schedule,
- __isl_keep isl_band *parent,
- int band_nr, int *active, int n_active)
+/* Construct an isl_band structure from the given schedule tree node,
+ * which may be either a band node or a leaf node.
+ * In the latter case, construct a zero-dimensional band.
+ * "domain" is the universe set of the domain elements that reach "node".
+ * "parent" is the parent isl_band of the isl_band constructed
+ * by this function.
+ *
+ * In case of a band node, we copy the properties (except tilability,
+ * which is implicit in an isl_band) to the isl_band.
+ * We assume that the band node is not zero-dimensional.
+ * If the child of the band node is not a leaf node,
+ * then we extract the children of the isl_band from this child.
+ */
+static __isl_give isl_band *construct_band(__isl_take isl_schedule_node *node,
+ __isl_take isl_union_set *domain, __isl_keep isl_band *parent)
{
- int i, j;
- isl_ctx *ctx = isl_schedule_get_ctx(schedule);
- isl_band *band;
- unsigned start, end;
+ int i;
+ isl_ctx *ctx;
+ isl_band *band = NULL;
+ isl_multi_union_pw_aff *mupa;
+
+ if (!node || !domain)
+ goto error;
+ ctx = isl_schedule_node_get_ctx(node);
band = isl_band_alloc(ctx);
if (!band)
- return NULL;
+ goto error;
- band->schedule = schedule;
+ band->schedule = node->schedule;
band->parent = parent;
- for (i = 0; i < schedule->n; ++i)
- if (active[i])
- break;
-
- if (i >= schedule->n)
- isl_die(ctx, isl_error_internal,
- "band without active statements", goto error);
-
- start = band_nr ? schedule->node[i].band_end[band_nr - 1] : 0;
- end = band_nr < schedule->node[i].n_band ?
- schedule->node[i].band_end[band_nr] : start;
- band->n = end - start;
+ if (isl_schedule_node_get_type(node) == isl_schedule_node_leaf) {
+ band->n = 0;
+ band->pma = isl_union_pw_multi_aff_from_domain(domain);
+ isl_schedule_node_free(node);
+ return band;
+ }
+ band->n = isl_schedule_node_band_n_member(node);
+ if (band->n == 0)
+ isl_die(ctx, isl_error_unsupported,
+ "zero-dimensional band nodes not supported",
+ goto error);
band->coincident = isl_alloc_array(ctx, int, band->n);
if (band->n && !band->coincident)
goto error;
-
- for (j = 0; j < band->n; ++j)
- band->coincident[j] = schedule->node[i].coincident[start + j];
-
- band->pma = isl_union_pw_multi_aff_empty(isl_space_copy(schedule->dim));
- for (i = 0; i < schedule->n; ++i) {
- isl_multi_aff *ma;
- isl_pw_multi_aff *pma;
- unsigned n_out;
-
- if (!active[i])
- continue;
-
- ma = isl_multi_aff_copy(schedule->node[i].sched);
- n_out = isl_multi_aff_dim(ma, isl_dim_out);
- ma = isl_multi_aff_drop_dims(ma, isl_dim_out, end, n_out - end);
- ma = isl_multi_aff_drop_dims(ma, isl_dim_out, 0, start);
- pma = isl_pw_multi_aff_from_multi_aff(ma);
- band->pma = isl_union_pw_multi_aff_add_pw_multi_aff(band->pma,
- pma);
- }
+ for (i = 0; i < band->n; ++i)
+ band->coincident[i] =
+ isl_schedule_node_band_member_get_coincident(node, i);
+ mupa = isl_schedule_node_band_get_partial_schedule(node);
+ band->pma = isl_union_pw_multi_aff_from_multi_union_pw_aff(mupa);
if (!band->pma)
goto error;
- for (i = 0; i < schedule->n; ++i)
- if (active[i] && schedule->node[i].n_band > band_nr + 1)
- break;
-
- if (i < schedule->n) {
- band->children = construct_band_list(schedule, band,
- band_nr + 1, active, n_active);
- if (!band->children)
- goto error;
+ node = isl_schedule_node_child(node, 0);
+ if (isl_schedule_node_get_type(node) == isl_schedule_node_leaf) {
+ isl_schedule_node_free(node);
+ isl_union_set_free(domain);
+ return band;
}
+ band->children = construct_band_list(node, domain, band);
+ if (!band->children)
+ return isl_band_free(band);
+
return band;
error:
+ isl_union_set_free(domain);
+ isl_schedule_node_free(node);
isl_band_free(band);
return NULL;
}
-/* Internal data structure used inside cmp_band and pw_multi_aff_extract_int.
- *
- * r is set to a negative value if anything goes wrong.
- *
- * c1 stores the result of extract_int.
- * c2 is a temporary value used inside cmp_band_in_ancestor.
- * t is a temporary value used inside extract_int.
- *
- * first and equal are used inside extract_int.
- * first is set if we are looking at the first isl_multi_aff inside
- * the isl_union_pw_multi_aff.
- * equal is set if all the isl_multi_affs have been equal so far.
+/* Construct a list of isl_band structures from the children of "node".
+ * "node" itself is a sequence or set node, so that each of the child nodes
+ * is a filter node and the list returned by node_construct_band_list
+ * consists of a single element.
+ * "domain" is the universe set of the domain elements that reach "node".
+ * "parent" is the parent isl_band of the isl_band structures constructed
+ * by this function.
*/
-struct isl_cmp_band_data {
- int r;
-
- int first;
- int equal;
-
- isl_int t;
- isl_int c1;
- isl_int c2;
-};
-
-/* Check if "ma" assigns a constant value.
- * Note that this function is only called on isl_multi_affs
- * with a single output dimension.
- *
- * If "ma" assigns a constant value then we compare it to data->c1
- * or assign it to data->c1 if this is the first isl_multi_aff we consider.
- * If "ma" does not assign a constant value or if it assigns a value
- * that is different from data->c1, then we set data->equal to zero
- * and terminate the check.
- */
-static int multi_aff_extract_int(__isl_take isl_set *set,
- __isl_take isl_multi_aff *ma, void *user)
-{
- isl_aff *aff;
- struct isl_cmp_band_data *data = user;
-
- aff = isl_multi_aff_get_aff(ma, 0);
- data->r = isl_aff_is_cst(aff);
- if (data->r >= 0 && data->r) {
- isl_aff_get_constant(aff, &data->t);
- if (data->first) {
- isl_int_set(data->c1, data->t);
- data->first = 0;
- } else if (!isl_int_eq(data->c1, data->t))
- data->equal = 0;
- } else if (data->r >= 0 && !data->r)
- data->equal = 0;
-
- isl_aff_free(aff);
- isl_set_free(set);
- isl_multi_aff_free(ma);
-
- if (data->r < 0)
- return -1;
- if (!data->equal)
- return -1;
- return 0;
-}
-
-/* This function is called for each isl_pw_multi_aff in
- * the isl_union_pw_multi_aff checked by extract_int.
- * Check all the isl_multi_affs inside "pma".
- */
-static int pw_multi_aff_extract_int(__isl_take isl_pw_multi_aff *pma,
- void *user)
+static __isl_give isl_band_list *construct_band_list_from_children(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *domain,
+ __isl_keep isl_band *parent)
{
- int r;
-
- r = isl_pw_multi_aff_foreach_piece(pma, &multi_aff_extract_int, user);
- isl_pw_multi_aff_free(pma);
-
- return r;
-}
-
-/* Check if "upma" assigns a single constant value to its domain.
- * If so, return 1 and store the result in data->c1.
- * If not, return 0.
- *
- * A negative return value from isl_union_pw_multi_aff_foreach_pw_multi_aff
- * means that either an error occurred or that we have broken off the check
- * because we already know the result is going to be negative.
- * In the latter case, data->equal is set to zero.
- */
-static int extract_int(__isl_keep isl_union_pw_multi_aff *upma,
- struct isl_cmp_band_data *data)
-{
- data->first = 1;
- data->equal = 1;
-
- if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
- &pw_multi_aff_extract_int, data) < 0) {
- if (!data->equal)
- return 0;
- return -1;
- }
-
- return !data->first && data->equal;
-}
+ int i, n;
+ isl_ctx *ctx;
+ isl_band_list *list;
-/* Compare "b1" and "b2" based on the parent schedule of their ancestor
- * "ancestor".
- *
- * If the parent of "ancestor" also has a single member, then we
- * first try to compare the two band based on the partial schedule
- * of this parent.
- *
- * Otherwise, or if the result is inconclusive, we look at the partial schedule
- * of "ancestor" itself.
- * In particular, we specialize the parent schedule based
- * on the domains of the child schedules, check if both assign
- * a single constant value and, if so, compare the two constant values.
- * If the specialized parent schedules do not assign a constant value,
- * then they cannot be used to order the two bands and so in this case
- * we return 0.
- */
-static int cmp_band_in_ancestor(__isl_keep isl_band *b1,
- __isl_keep isl_band *b2, struct isl_cmp_band_data *data,
- __isl_keep isl_band *ancestor)
-{
- isl_union_pw_multi_aff *upma;
- isl_union_set *domain;
- int r;
+ n = isl_schedule_node_n_children(node);
- if (data->r < 0)
- return 0;
+ ctx = isl_schedule_node_get_ctx(node);
+ list = isl_band_list_alloc(ctx, 0);
+ for (i = 0; i < n; ++i) {
+ isl_schedule_node *child;
+ isl_band_list *list_i;
- if (ancestor->parent && ancestor->parent->n == 1) {
- r = cmp_band_in_ancestor(b1, b2, data, ancestor->parent);
- if (data->r < 0)
- return 0;
- if (r)
- return r;
+ child = isl_schedule_node_get_child(node, i);
+ list_i = construct_band_list(child, isl_union_set_copy(domain),
+ parent);
+ list = isl_band_list_concat(list, list_i);
}
- upma = isl_union_pw_multi_aff_copy(b1->pma);
- domain = isl_union_pw_multi_aff_domain(upma);
- upma = isl_union_pw_multi_aff_copy(ancestor->pma);
- upma = isl_union_pw_multi_aff_intersect_domain(upma, domain);
- r = extract_int(upma, data);
- isl_union_pw_multi_aff_free(upma);
-
- if (r < 0)
- data->r = -1;
- if (r < 0 || !r)
- return 0;
-
- isl_int_set(data->c2, data->c1);
-
- upma = isl_union_pw_multi_aff_copy(b2->pma);
- domain = isl_union_pw_multi_aff_domain(upma);
- upma = isl_union_pw_multi_aff_copy(ancestor->pma);
- upma = isl_union_pw_multi_aff_intersect_domain(upma, domain);
- r = extract_int(upma, data);
- isl_union_pw_multi_aff_free(upma);
-
- if (r < 0)
- data->r = -1;
- if (r < 0 || !r)
- return 0;
-
- return isl_int_cmp(data->c2, data->c1);
-}
-
-/* Compare "a" and "b" based on the parent schedule of their parent.
- */
-static int cmp_band(const void *a, const void *b, void *user)
-{
- isl_band *b1 = *(isl_band * const *) a;
- isl_band *b2 = *(isl_band * const *) b;
- struct isl_cmp_band_data *data = user;
-
- return cmp_band_in_ancestor(b1, b2, data, b1->parent);
-}
-
-/* Sort the elements in "list" based on the partial schedules of its parent
- * (and ancestors). In particular if the parent assigns constant values
- * to the domains of the bands in "list", then the elements are sorted
- * according to that order.
- * This order should be a more "natural" order for the user, but otherwise
- * shouldn't have any effect.
- * If we would be constructing an isl_band forest directly in
- * isl_schedule_constraints_compute_schedule then there wouldn't be any need
- * for a reordering, since the children would be added to the list
- * in their natural order automatically.
- *
- * If there is only one element in the list, then there is no need to sort
- * anything.
- * If the partial schedule of the parent has more than one member
- * (or if there is no parent), then it's
- * defnitely not assigning constant values to the different children in
- * the list and so we wouldn't be able to use it to sort the list.
- */
-static __isl_give isl_band_list *sort_band_list(__isl_take isl_band_list *list,
- __isl_keep isl_band *parent)
-{
- struct isl_cmp_band_data data;
-
- if (!list)
- return NULL;
- if (list->n <= 1)
- return list;
- if (!parent || parent->n != 1)
- return list;
-
- data.r = 0;
- isl_int_init(data.c1);
- isl_int_init(data.c2);
- isl_int_init(data.t);
- isl_sort(list->p, list->n, sizeof(list->p[0]), &cmp_band, &data);
- if (data.r < 0)
- list = isl_band_list_free(list);
- isl_int_clear(data.c1);
- isl_int_clear(data.c2);
- isl_int_clear(data.t);
+ isl_union_set_free(domain);
+ isl_schedule_node_free(node);
return list;
}
-/* Construct a list of bands that start at the same position (with
- * sequence number band_nr) in the schedules of the nodes that
- * were active in the parent band.
- *
- * A separate isl_band structure is created for each band_id
- * and for each node that does not have a band with sequence
- * number band_nr. In the latter case, a band without members
- * is created.
- * This ensures that if a band has any children, then each node
- * that was active in the band is active in exactly one of the children.
+/* Construct an isl_band structure from the given sequence node
+ * (or set node that is treated as a sequence node).
+ * A single-dimensional band is created with as schedule for each of
+ * filters of the children, the corresponding child position.
+ * "domain" is the universe set of the domain elements that reach "node".
+ * "parent" is the parent isl_band of the isl_band constructed
+ * by this function.
*/
-static __isl_give isl_band_list *construct_band_list(
- __isl_keep isl_schedule *schedule, __isl_keep isl_band *parent,
- int band_nr, int *parent_active, int n_active)
+static __isl_give isl_band_list *construct_band_list_sequence(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *domain,
+ __isl_keep isl_band *parent)
{
- int i, j;
- isl_ctx *ctx = isl_schedule_get_ctx(schedule);
- int *active;
- int n_band;
- isl_band_list *list;
-
- n_band = 0;
- for (i = 0; i < n_active; ++i) {
- for (j = 0; j < schedule->n; ++j) {
- if (!parent_active[j])
- continue;
- if (schedule->node[j].n_band <= band_nr)
- continue;
- if (schedule->node[j].band_id[band_nr] == i) {
- n_band++;
- break;
- }
- }
- }
- for (j = 0; j < schedule->n; ++j)
- if (schedule->node[j].n_band <= band_nr)
- n_band++;
-
- if (n_band == 1) {
- isl_band *band;
- list = isl_band_list_alloc(ctx, n_band);
- band = construct_band(schedule, parent, band_nr,
- parent_active, n_active);
- return isl_band_list_add(list, band);
- }
+ int i, n;
+ isl_ctx *ctx;
+ isl_band *band = NULL;
+ isl_space *space;
+ isl_union_pw_multi_aff *upma;
- active = isl_alloc_array(ctx, int, schedule->n);
- if (schedule->n && !active)
- return NULL;
+ if (!node || !domain)
+ goto error;
- list = isl_band_list_alloc(ctx, n_band);
+ ctx = isl_schedule_node_get_ctx(node);
+ band = isl_band_alloc(ctx);
+ if (!band)
+ goto error;
- for (i = 0; i < n_active; ++i) {
- int n = 0;
- isl_band *band;
+ band->schedule = node->schedule;
+ band->parent = parent;
+ band->n = 1;
+ band->coincident = isl_calloc_array(ctx, int, band->n);
+ if (!band->coincident)
+ goto error;
- for (j = 0; j < schedule->n; ++j) {
- active[j] = parent_active[j] &&
- schedule->node[j].n_band > band_nr &&
- schedule->node[j].band_id[band_nr] == i;
- if (active[j])
- n++;
- }
- if (n == 0)
- continue;
+ n = isl_schedule_node_n_children(node);
+ space = isl_union_set_get_space(domain);
+ upma = isl_union_pw_multi_aff_empty(isl_space_copy(space));
- band = construct_band(schedule, parent, band_nr, active, n);
+ space = isl_space_set_from_params(space);
+ space = isl_space_add_dims(space, isl_dim_set, 1);
- list = isl_band_list_add(list, band);
- }
- for (i = 0; i < schedule->n; ++i) {
- isl_band *band;
- if (!parent_active[i])
- continue;
- if (schedule->node[i].n_band > band_nr)
- continue;
- for (j = 0; j < schedule->n; ++j)
- active[j] = j == i;
- band = construct_band(schedule, parent, band_nr, active, 1);
- list = isl_band_list_add(list, band);
+ for (i = 0; i < n; ++i) {
+ isl_schedule_node *child;
+ isl_union_set *filter;
+ isl_val *v;
+ isl_val_list *vl;
+ isl_multi_val *mv;
+ isl_union_pw_multi_aff *upma_i;
+
+ child = isl_schedule_node_get_child(node, i);
+ filter = isl_schedule_node_filter_get_filter(child);
+ isl_schedule_node_free(child);
+ filter = isl_union_set_intersect(filter,
+ isl_union_set_copy(domain));
+ v = isl_val_int_from_si(ctx, i);
+ vl = isl_val_list_from_val(v);
+ mv = isl_multi_val_from_val_list(isl_space_copy(space), vl);
+ upma_i = isl_union_pw_multi_aff_multi_val_on_domain(filter, mv);
+ upma = isl_union_pw_multi_aff_union_add(upma, upma_i);
}
- free(active);
+ isl_space_free(space);
- list = sort_band_list(list, parent);
+ band->pma = upma;
+ if (!band->pma)
+ goto error;
- return list;
+ band->children = construct_band_list_from_children(node, domain, band);
+ if (!band->children)
+ band = isl_band_free(band);
+ return isl_band_list_from_band(band);
+error:
+ isl_union_set_free(domain);
+ isl_schedule_node_free(node);
+ isl_band_free(band);
+ return NULL;
}
-/* Construct a band forest representation of the schedule and
- * return the list of roots.
+/* Construct a list of isl_band structures from "node" depending
+ * on the type of "node".
+ * "domain" is the universe set of the domain elements that reach "node".
+ * "parent" is the parent isl_band of the isl_band structures constructed
+ * by this function.
+ *
+ * If schedule_separate_components is set then set nodes are treated
+ * as sequence nodes. Otherwise, we directly extract an (implicitly
+ * parallel) list of isl_band structures.
+ *
+ * If "node" is a filter, then "domain" is updated by the filter.
*/
-static __isl_give isl_band_list *construct_forest(
- __isl_keep isl_schedule *schedule)
+static __isl_give isl_band_list *construct_band_list(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *domain,
+ __isl_keep isl_band *parent)
{
- int i;
- isl_ctx *ctx = isl_schedule_get_ctx(schedule);
- isl_band_list *forest;
- int *active;
-
- active = isl_alloc_array(ctx, int, schedule->n);
- if (schedule->n && !active)
- return NULL;
-
- for (i = 0; i < schedule->n; ++i)
- active[i] = 1;
+ enum isl_schedule_node_type type;
+ isl_ctx *ctx;
+ isl_band *band;
+ isl_band_list *list;
+ isl_union_set *filter;
- forest = construct_band_list(schedule, NULL, 0, active, schedule->n);
+ if (!node || !domain)
+ goto error;
- free(active);
+ type = isl_schedule_node_get_type(node);
+ switch (type) {
+ case isl_schedule_node_error:
+ goto error;
+ case isl_schedule_node_domain:
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "internal domain nodes not allowed", goto error);
+ case isl_schedule_node_filter:
+ filter = isl_schedule_node_filter_get_filter(node);
+ domain = isl_union_set_intersect(domain, filter);
+ node = isl_schedule_node_child(node, 0);
+ return construct_band_list(node, domain, parent);
+ case isl_schedule_node_set:
+ ctx = isl_schedule_node_get_ctx(node);
+ if (isl_options_get_schedule_separate_components(ctx))
+ return construct_band_list_sequence(node, domain,
+ parent);
+ else
+ return construct_band_list_from_children(node, domain,
+ parent);
+ case isl_schedule_node_sequence:
+ return construct_band_list_sequence(node, domain, parent);
+ case isl_schedule_node_leaf:
+ case isl_schedule_node_band:
+ band = construct_band(node, domain, parent);
+ list = isl_band_list_from_band(band);
+ break;
+ }
- return forest;
+ return list;
+error:
+ isl_union_set_free(domain);
+ isl_schedule_node_free(node);
+ return NULL;
}
/* Return the roots of a band forest representation of the schedule.
+ * The band forest is constructed from the schedule tree,
+ * but once such a band forest is
+ * constructed, we forget about the original schedule tree since
+ * the user may modify the schedule through the band forest.
*/
__isl_give isl_band_list *isl_schedule_get_band_forest(
__isl_keep isl_schedule *schedule)
{
+ isl_schedule_node *node;
+ isl_union_set *domain;
+
if (!schedule)
return NULL;
- if (!schedule->band_forest)
- schedule->band_forest = construct_forest(schedule);
+ if (schedule->root) {
+ node = isl_schedule_get_root(schedule);
+ domain = isl_schedule_node_domain_get_domain(node);
+ domain = isl_union_set_universe(domain);
+ node = isl_schedule_node_child(node, 0);
+
+ schedule->band_forest = construct_band_list(node, domain, NULL);
+ schedule->root = isl_schedule_tree_free(schedule->root);
+ }
return isl_band_list_dup(schedule->band_forest);
}
@@ -644,11 +738,23 @@ static __isl_give isl_printer *print_ban
return p;
}
+/* Print "schedule" to "p".
+ *
+ * If "schedule" was created from a schedule tree, then we print
+ * the schedule tree representation. Otherwise, we print
+ * the band forest representation.
+ */
__isl_give isl_printer *isl_printer_print_schedule(__isl_take isl_printer *p,
__isl_keep isl_schedule *schedule)
{
isl_band_list *forest;
+ if (!schedule)
+ return isl_printer_free(p);
+
+ if (schedule->root)
+ return isl_printer_print_schedule_tree(p, schedule->root);
+
forest = isl_schedule_get_band_forest(schedule);
p = print_band_list(p, forest);
@@ -666,6 +772,7 @@ void isl_schedule_dump(__isl_keep isl_sc
return;
printer = isl_printer_to_file(isl_schedule_get_ctx(schedule), stderr);
+ printer = isl_printer_set_yaml_style(printer, ISL_YAML_STYLE_BLOCK);
printer = isl_printer_print_schedule(printer, schedule);
isl_printer_free(printer);
Added: polly/trunk/lib/External/isl/isl_schedule_band.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_schedule_band.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_schedule_band.c (added)
+++ polly/trunk/lib/External/isl/isl_schedule_band.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,417 @@
+/*
+ * Copyright 2013-2014 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl/schedule_node.h>
+#include <isl_schedule_band.h>
+#include <isl_schedule_private.h>
+
+isl_ctx *isl_schedule_band_get_ctx(__isl_keep isl_schedule_band *band)
+{
+ return band ? isl_multi_union_pw_aff_get_ctx(band->mupa) : NULL;
+}
+
+/* Return a new uninitialized isl_schedule_band.
+ */
+static __isl_give isl_schedule_band *isl_schedule_band_alloc(isl_ctx *ctx)
+{
+ isl_schedule_band *band;
+
+ band = isl_calloc_type(ctx, isl_schedule_band);
+ if (!band)
+ return NULL;
+
+ band->ref = 1;
+
+ return band;
+}
+
+/* Return a new isl_schedule_band with partial schedule "mupa".
+ * First replace "mupa" by its greatest integer part to ensure
+ * that the schedule is always integral.
+ * The band is not marked permutable and the dimensions are not
+ * marked coincident.
+ */
+__isl_give isl_schedule_band *isl_schedule_band_from_multi_union_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ isl_ctx *ctx;
+ isl_schedule_band *band;
+
+ mupa = isl_multi_union_pw_aff_floor(mupa);
+ if (!mupa)
+ return NULL;
+ ctx = isl_multi_union_pw_aff_get_ctx(mupa);
+ band = isl_schedule_band_alloc(ctx);
+ if (!band)
+ goto error;
+
+ band->n = isl_multi_union_pw_aff_dim(mupa, isl_dim_set);
+ band->coincident = isl_calloc_array(ctx, int, band->n);
+ band->mupa = mupa;
+
+ if (band->n && !band->coincident)
+ return isl_schedule_band_free(band);
+
+ return band;
+error:
+ isl_multi_union_pw_aff_free(mupa);
+ return NULL;
+}
+
+/* Create a duplicate of the given isl_schedule_band.
+ */
+__isl_give isl_schedule_band *isl_schedule_band_dup(
+ __isl_keep isl_schedule_band *band)
+{
+ int i;
+ isl_ctx *ctx;
+ isl_schedule_band *dup;
+
+ if (!band)
+ return NULL;
+
+ ctx = isl_schedule_band_get_ctx(band);
+ dup = isl_schedule_band_alloc(ctx);
+ if (!dup)
+ return NULL;
+
+ dup->n = band->n;
+ dup->coincident = isl_alloc_array(ctx, int, band->n);
+ if (band->n && !dup->coincident)
+ return isl_schedule_band_free(dup);
+
+ for (i = 0; i < band->n; ++i)
+ dup->coincident[i] = band->coincident[i];
+ dup->permutable = band->permutable;
+
+ dup->mupa = isl_multi_union_pw_aff_copy(band->mupa);
+ if (!dup->mupa)
+ return isl_schedule_band_free(dup);
+
+ return dup;
+}
+
+/* Return an isl_schedule_band that is equal to "band" and that has only
+ * a single reference.
+ */
+__isl_give isl_schedule_band *isl_schedule_band_cow(
+ __isl_take isl_schedule_band *band)
+{
+ if (!band)
+ return NULL;
+
+ if (band->ref == 1)
+ return band;
+ band->ref--;
+ return isl_schedule_band_dup(band);
+}
+
+/* Return a new reference to "band".
+ */
+__isl_give isl_schedule_band *isl_schedule_band_copy(
+ __isl_keep isl_schedule_band *band)
+{
+ if (!band)
+ return NULL;
+
+ band->ref++;
+ return band;
+}
+
+/* Free a reference to "band" and return NULL.
+ */
+__isl_null isl_schedule_band *isl_schedule_band_free(
+ __isl_take isl_schedule_band *band)
+{
+ if (!band)
+ return NULL;
+
+ if (--band->ref > 0)
+ return NULL;
+
+ isl_multi_union_pw_aff_free(band->mupa);
+ free(band->coincident);
+ free(band);
+
+ return NULL;
+}
+
+/* Return the number of scheduling dimensions in the band.
+ */
+int isl_schedule_band_n_member(__isl_keep isl_schedule_band *band)
+{
+ return band ? band->n : 0;
+}
+
+/* Is the given scheduling dimension coincident within the band and
+ * with respect to the coincidence constraints?
+ */
+int isl_schedule_band_member_get_coincident(__isl_keep isl_schedule_band *band,
+ int pos)
+{
+ if (!band)
+ return -1;
+
+ if (pos < 0 || pos >= band->n)
+ isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
+ "invalid member position", return -1);
+
+ return band->coincident[pos];
+}
+
+/* Mark the given scheduling dimension as being coincident or not
+ * according to "coincident".
+ */
+__isl_give isl_schedule_band *isl_schedule_band_member_set_coincident(
+ __isl_take isl_schedule_band *band, int pos, int coincident)
+{
+ if (!band)
+ return NULL;
+ if (isl_schedule_band_member_get_coincident(band, pos) == coincident)
+ return band;
+ band = isl_schedule_band_cow(band);
+ if (!band)
+ return NULL;
+
+ if (pos < 0 || pos >= band->n)
+ isl_die(isl_schedule_band_get_ctx(band), isl_error_invalid,
+ "invalid member position",
+ isl_schedule_band_free(band));
+
+ band->coincident[pos] = coincident;
+
+ return band;
+}
+
+/* Is the schedule band mark permutable?
+ */
+int isl_schedule_band_get_permutable(__isl_keep isl_schedule_band *band)
+{
+ if (!band)
+ return -1;
+ return band->permutable;
+}
+
+/* Mark the schedule band permutable or not according to "permutable"?
+ */
+__isl_give isl_schedule_band *isl_schedule_band_set_permutable(
+ __isl_take isl_schedule_band *band, int permutable)
+{
+ if (!band)
+ return NULL;
+ if (band->permutable == permutable)
+ return band;
+ band = isl_schedule_band_cow(band);
+ if (!band)
+ return NULL;
+
+ band->permutable = permutable;
+
+ return band;
+}
+
+/* Return the schedule space of the band.
+ */
+__isl_give isl_space *isl_schedule_band_get_space(
+ __isl_keep isl_schedule_band *band)
+{
+ if (!band)
+ return NULL;
+ return isl_multi_union_pw_aff_get_space(band->mupa);
+}
+
+/* Return the schedule of the band in isolation.
+ */
+__isl_give isl_multi_union_pw_aff *isl_schedule_band_get_partial_schedule(
+ __isl_keep isl_schedule_band *band)
+{
+ return band ? isl_multi_union_pw_aff_copy(band->mupa) : NULL;
+}
+
+/* Multiply the partial schedule of "band" with the factors in "mv".
+ * Replace the result by its greatest integer part to ensure
+ * that the schedule is always integral.
+ */
+__isl_give isl_schedule_band *isl_schedule_band_scale(
+ __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
+{
+ band = isl_schedule_band_cow(band);
+ if (!band || !mv)
+ goto error;
+ band->mupa = isl_multi_union_pw_aff_scale_multi_val(band->mupa, mv);
+ band->mupa = isl_multi_union_pw_aff_floor(band->mupa);
+ if (!band->mupa)
+ return isl_schedule_band_free(band);
+ return band;
+error:
+ isl_schedule_band_free(band);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Divide the partial schedule of "band" by the factors in "mv".
+ * Replace the result by its greatest integer part to ensure
+ * that the schedule is always integral.
+ */
+__isl_give isl_schedule_band *isl_schedule_band_scale_down(
+ __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv)
+{
+ band = isl_schedule_band_cow(band);
+ if (!band || !mv)
+ goto error;
+ band->mupa = isl_multi_union_pw_aff_scale_down_multi_val(band->mupa,
+ mv);
+ band->mupa = isl_multi_union_pw_aff_floor(band->mupa);
+ if (!band->mupa)
+ return isl_schedule_band_free(band);
+ return band;
+error:
+ isl_schedule_band_free(band);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Given the schedule of a band, construct the corresponding
+ * schedule for the tile loops based on the given tile sizes
+ * and return the result.
+ *
+ * If the scale tile loops options is set, then the tile loops
+ * are scaled by the tile sizes.
+ *
+ * That is replace each schedule dimension "i" by either
+ * "floor(i/s)" or "s * floor(i/s)".
+ */
+static isl_multi_union_pw_aff *isl_multi_union_pw_aff_tile(
+ __isl_take isl_multi_union_pw_aff *sched,
+ __isl_take isl_multi_val *sizes)
+{
+ isl_ctx *ctx;
+ int i, n;
+ isl_val *v;
+ int scale;
+
+ ctx = isl_multi_val_get_ctx(sizes);
+ scale = isl_options_get_tile_scale_tile_loops(ctx);
+
+ n = isl_multi_union_pw_aff_dim(sched, isl_dim_set);
+ for (i = 0; i < n; ++i) {
+ isl_union_pw_aff *upa;
+
+ upa = isl_multi_union_pw_aff_get_union_pw_aff(sched, i);
+ v = isl_multi_val_get_val(sizes, i);
+
+ upa = isl_union_pw_aff_scale_down_val(upa, isl_val_copy(v));
+ upa = isl_union_pw_aff_floor(upa);
+ if (scale)
+ upa = isl_union_pw_aff_scale_val(upa, isl_val_copy(v));
+ isl_val_free(v);
+
+ sched = isl_multi_union_pw_aff_set_union_pw_aff(sched, i, upa);
+ }
+
+ isl_multi_val_free(sizes);
+ return sched;
+}
+
+/* Replace "band" by a band corresponding to the tile loops of a tiling
+ * with the given tile sizes.
+ */
+__isl_give isl_schedule_band *isl_schedule_band_tile(
+ __isl_take isl_schedule_band *band, __isl_take isl_multi_val *sizes)
+{
+ band = isl_schedule_band_cow(band);
+ if (!band || !sizes)
+ goto error;
+ band->mupa = isl_multi_union_pw_aff_tile(band->mupa, sizes);
+ if (!band->mupa)
+ return isl_schedule_band_free(band);
+ return band;
+error:
+ isl_schedule_band_free(band);
+ isl_multi_val_free(sizes);
+ return NULL;
+}
+
+/* Replace "band" by a band corresponding to the point loops of a tiling
+ * with the given tile sizes.
+ * "tile" is the corresponding tile loop band.
+ *
+ * If the shift point loops option is set, then the point loops
+ * are shifted to start at zero. That is, each schedule dimension "i"
+ * is replaced by "i - s * floor(i/s)".
+ * The expression "floor(i/s)" (or "s * floor(i/s)") is extracted from
+ * the tile band.
+ *
+ * Otherwise, the band is left untouched.
+ */
+__isl_give isl_schedule_band *isl_schedule_band_point(
+ __isl_take isl_schedule_band *band, __isl_keep isl_schedule_band *tile,
+ __isl_take isl_multi_val *sizes)
+{
+ isl_ctx *ctx;
+ isl_multi_union_pw_aff *scaled;
+
+ if (!band || !sizes)
+ goto error;
+
+ ctx = isl_schedule_band_get_ctx(band);
+ if (!isl_options_get_tile_shift_point_loops(ctx)) {
+ isl_multi_val_free(sizes);
+ return band;
+ }
+ band = isl_schedule_band_cow(band);
+ if (!band)
+ goto error;
+
+ scaled = isl_schedule_band_get_partial_schedule(tile);
+ if (!isl_options_get_tile_scale_tile_loops(ctx))
+ scaled = isl_multi_union_pw_aff_scale_multi_val(scaled, sizes);
+ else
+ isl_multi_val_free(sizes);
+ band->mupa = isl_multi_union_pw_aff_sub(band->mupa, scaled);
+ if (!band->mupa)
+ return isl_schedule_band_free(band);
+ return band;
+error:
+ isl_schedule_band_free(band);
+ isl_multi_val_free(sizes);
+ return NULL;
+}
+
+/* Drop the "n" dimensions starting at "pos" from "band".
+ *
+ * We apply the transformation even if "n" is zero to ensure consistent
+ * behavior with respect to changes in the schedule space.
+ */
+__isl_give isl_schedule_band *isl_schedule_band_drop(
+ __isl_take isl_schedule_band *band, int pos, int n)
+{
+ int i;
+
+ if (pos < 0 || n < 0 || pos + n > band->n)
+ isl_die(isl_schedule_band_get_ctx(band), isl_error_internal,
+ "range out of bounds",
+ return isl_schedule_band_free(band));
+
+ band = isl_schedule_band_cow(band);
+ if (!band)
+ return NULL;
+
+ band->mupa = isl_multi_union_pw_aff_drop_dims(band->mupa,
+ isl_dim_set, pos, n);
+ if (!band->mupa)
+ return isl_schedule_band_free(band);
+
+ for (i = pos + n; i < band->n; ++i)
+ band->coincident[i - n] = band->coincident[i];
+
+ band->n -= n;
+
+ return band;
+}
Added: polly/trunk/lib/External/isl/isl_schedule_band.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_schedule_band.h?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_schedule_band.h (added)
+++ polly/trunk/lib/External/isl/isl_schedule_band.h Mon Feb 16 13:33:40 2015
@@ -0,0 +1,63 @@
+#ifndef ISL_SCHEDULE_BAND_H
+#define ISL_SCHEDULE_BAND_H
+
+#include <isl/aff.h>
+#include <isl/union_map.h>
+
+/* Information about a band within a schedule.
+ *
+ * n is the number of scheduling dimensions within the band.
+ * coincident is an array of length n, indicating whether a scheduling dimension
+ * satisfies the coincidence constraints in the sense that
+ * the corresponding dependence distances are zero.
+ * permutable is set if the band is permutable.
+ * mupa is the partial schedule corresponding to this band. The dimension
+ * of mupa is equal to n.
+ */
+struct isl_schedule_band {
+ int ref;
+
+ int n;
+ int *coincident;
+ int permutable;
+
+ isl_multi_union_pw_aff *mupa;
+};
+typedef struct isl_schedule_band isl_schedule_band;
+
+__isl_give isl_schedule_band *isl_schedule_band_from_multi_union_pw_aff(
+ __isl_take isl_multi_union_pw_aff *mupa);
+__isl_give isl_schedule_band *isl_schedule_band_copy(
+ __isl_keep isl_schedule_band *band);
+__isl_null isl_schedule_band *isl_schedule_band_free(
+ __isl_take isl_schedule_band *band);
+
+isl_ctx *isl_schedule_band_get_ctx(__isl_keep isl_schedule_band *band);
+
+__isl_give isl_space *isl_schedule_band_get_space(
+ __isl_keep isl_schedule_band *band);
+__isl_give isl_multi_union_pw_aff *isl_schedule_band_get_partial_schedule(
+ __isl_keep isl_schedule_band *band);
+
+int isl_schedule_band_n_member(__isl_keep isl_schedule_band *band);
+int isl_schedule_band_member_get_coincident(
+ __isl_keep isl_schedule_band *band, int pos);
+__isl_give isl_schedule_band *isl_schedule_band_member_set_coincident(
+ __isl_take isl_schedule_band *band, int pos, int coincident);
+int isl_schedule_band_get_permutable(__isl_keep isl_schedule_band *band);
+__isl_give isl_schedule_band *isl_schedule_band_set_permutable(
+ __isl_take isl_schedule_band *band, int permutable);
+
+__isl_give isl_schedule_band *isl_schedule_band_scale(
+ __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv);
+__isl_give isl_schedule_band *isl_schedule_band_scale_down(
+ __isl_take isl_schedule_band *band, __isl_take isl_multi_val *mv);
+__isl_give isl_schedule_band *isl_schedule_band_tile(
+ __isl_take isl_schedule_band *band, __isl_take isl_multi_val *sizes);
+__isl_give isl_schedule_band *isl_schedule_band_point(
+ __isl_take isl_schedule_band *band, __isl_keep isl_schedule_band *tile,
+ __isl_take isl_multi_val *sizes);
+__isl_give isl_schedule_band *isl_schedule_band_drop(
+ __isl_take isl_schedule_band *band, int pos, int n);
+
+#endif
Added: polly/trunk/lib/External/isl/isl_schedule_node.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_schedule_node.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_schedule_node.c (added)
+++ polly/trunk/lib/External/isl/isl_schedule_node.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,1535 @@
+/*
+ * Copyright 2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl/set.h>
+#include <isl_schedule_band.h>
+#include <isl_schedule_private.h>
+#include <isl_schedule_node_private.h>
+
+/* Create a new schedule node in the given schedule, point at the given
+ * tree with given ancestors and child positions.
+ * "child_pos" may be NULL if there are no ancestors.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_alloc(
+ __isl_take isl_schedule *schedule, __isl_take isl_schedule_tree *tree,
+ __isl_take isl_schedule_tree_list *ancestors, int *child_pos)
+{
+ isl_ctx *ctx;
+ isl_schedule_node *node;
+ int i, n;
+
+ if (!schedule || !tree || !ancestors)
+ goto error;
+ n = isl_schedule_tree_list_n_schedule_tree(ancestors);
+ if (n > 0 && !child_pos)
+ goto error;
+ ctx = isl_schedule_get_ctx(schedule);
+ node = isl_calloc_type(ctx, isl_schedule_node);
+ if (!node)
+ goto error;
+ node->ref = 1;
+ node->schedule = schedule;
+ node->tree = tree;
+ node->ancestors = ancestors;
+ node->child_pos = isl_alloc_array(ctx, int, n);
+ if (n && !node->child_pos)
+ return isl_schedule_node_free(node);
+ for (i = 0; i < n; ++i)
+ node->child_pos[i] = child_pos[i];
+
+ return node;
+error:
+ isl_schedule_free(schedule);
+ isl_schedule_tree_free(tree);
+ isl_schedule_tree_list_free(ancestors);
+ return NULL;
+}
+
+/* Return a pointer to the root of a schedule tree with as single
+ * node a domain node with the given domain.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_from_domain(
+ __isl_take isl_union_set *domain)
+{
+ isl_schedule *schedule;
+ isl_schedule_node *node;
+
+ schedule = isl_schedule_from_domain(domain);
+ node = isl_schedule_get_root(schedule);
+ isl_schedule_free(schedule);
+
+ return node;
+}
+
+/* Return the isl_ctx to which "node" belongs.
+ */
+isl_ctx *isl_schedule_node_get_ctx(__isl_keep isl_schedule_node *node)
+{
+ return node ? isl_schedule_get_ctx(node->schedule) : NULL;
+}
+
+/* Return a pointer to the leaf of the schedule into which "node" points.
+ *
+ * Even though these leaves are not reference counted, we still
+ * indicate that this function does not return a copy.
+ */
+__isl_keep isl_schedule_tree *isl_schedule_node_peek_leaf(
+ __isl_keep isl_schedule_node *node)
+{
+ return node ? isl_schedule_peek_leaf(node->schedule) : NULL;
+}
+
+/* Return a pointer to the leaf of the schedule into which "node" points.
+ *
+ * Even though these leaves are not reference counted, we still
+ * return a "copy" of the leaf here such that it can still be "freed"
+ * by the user.
+ */
+__isl_give isl_schedule_tree *isl_schedule_node_get_leaf(
+ __isl_keep isl_schedule_node *node)
+{
+ return isl_schedule_tree_copy(isl_schedule_node_peek_leaf(node));
+}
+
+/* Return the type of the node or isl_schedule_node_error on error.
+ */
+enum isl_schedule_node_type isl_schedule_node_get_type(
+ __isl_keep isl_schedule_node *node)
+{
+ return node ? isl_schedule_tree_get_type(node->tree)
+ : isl_schedule_node_error;
+}
+
+/* Return the type of the parent of "node" or isl_schedule_node_error on error.
+ */
+enum isl_schedule_node_type isl_schedule_node_get_parent_type(
+ __isl_keep isl_schedule_node *node)
+{
+ int pos;
+ int has_parent;
+ isl_schedule_tree *parent;
+ enum isl_schedule_node_type type;
+
+ if (!node)
+ return isl_schedule_node_error;
+ has_parent = isl_schedule_node_has_parent(node);
+ if (has_parent < 0)
+ return isl_schedule_node_error;
+ if (!has_parent)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "node has no parent", return isl_schedule_node_error);
+
+ pos = isl_schedule_tree_list_n_schedule_tree(node->ancestors) - 1;
+ parent = isl_schedule_tree_list_get_schedule_tree(node->ancestors, pos);
+ type = isl_schedule_tree_get_type(parent);
+ isl_schedule_tree_free(parent);
+
+ return type;
+}
+
+/* Return a copy of the subtree that this node points to.
+ */
+__isl_give isl_schedule_tree *isl_schedule_node_get_tree(
+ __isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return NULL;
+
+ return isl_schedule_tree_copy(node->tree);
+}
+
+/* Return a copy of the schedule into which "node" points.
+ */
+__isl_give isl_schedule *isl_schedule_node_get_schedule(
+ __isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return NULL;
+ return isl_schedule_copy(node->schedule);
+}
+
+/* Return a fresh copy of "node".
+ */
+__isl_take isl_schedule_node *isl_schedule_node_dup(
+ __isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return NULL;
+
+ return isl_schedule_node_alloc(isl_schedule_copy(node->schedule),
+ isl_schedule_tree_copy(node->tree),
+ isl_schedule_tree_list_copy(node->ancestors),
+ node->child_pos);
+}
+
+/* Return an isl_schedule_node that is equal to "node" and that has only
+ * a single reference.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_cow(
+ __isl_take isl_schedule_node *node)
+{
+ if (!node)
+ return NULL;
+
+ if (node->ref == 1)
+ return node;
+ node->ref--;
+ return isl_schedule_node_dup(node);
+}
+
+/* Return a new reference to "node".
+ */
+__isl_give isl_schedule_node *isl_schedule_node_copy(
+ __isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return NULL;
+
+ node->ref++;
+ return node;
+}
+
+/* Free "node" and return NULL.
+ *
+ * Since the node may point to a leaf of its schedule, which
+ * point to a field inside the schedule, we need to make sure
+ * we free the tree before freeing the schedule.
+ */
+__isl_null isl_schedule_node *isl_schedule_node_free(
+ __isl_take isl_schedule_node *node)
+{
+ if (!node)
+ return NULL;
+ if (--node->ref > 0)
+ return NULL;
+
+ isl_schedule_tree_list_free(node->ancestors);
+ free(node->child_pos);
+ isl_schedule_tree_free(node->tree);
+ isl_schedule_free(node->schedule);
+ free(node);
+
+ return NULL;
+}
+
+/* Internal data structure for
+ * isl_schedule_node_get_prefix_schedule_union_pw_multi_aff
+ *
+ * "initialized" is set if the filter field has been initialized.
+ * "universe_filter" is set if we are only collecting the universes of filters
+ * "collect_prefix" is set if we are collecting prefixes.
+ * "filter" collects all outer filters and is NULL until "initialized" is set.
+ * "prefix" collects all outer band partial schedules (if "collect_prefix"
+ * is set). If it is used, then it is initialized by the caller
+ * of collect_filter_prefix to a zero-dimensional function.
+ */
+struct isl_schedule_node_get_filter_prefix_data {
+ int initialized;
+ int universe_filter;
+ int collect_prefix;
+ isl_union_set *filter;
+ isl_multi_union_pw_aff *prefix;
+};
+
+/* Update "data" based on the tree node "tree" in case "data" has
+ * not been initialized yet.
+ *
+ * Return 0 on success and -1 on error.
+ *
+ * If "tree" is a filter, then we set data->filter to this filter
+ * (or its universe).
+ * If "tree" is a domain, then this means we have reached the root
+ * of the schedule tree without being able to extract any information.
+ * We therefore initialize data->filter to the universe of the domain.
+ * If "tree" is a band with at least one member, then we set data->filter
+ * to the universe of the schedule domain and replace the zero-dimensional
+ * data->prefix by the band schedule (if data->collect_prefix is set).
+ */
+static int collect_filter_prefix_init(__isl_keep isl_schedule_tree *tree,
+ struct isl_schedule_node_get_filter_prefix_data *data)
+{
+ enum isl_schedule_node_type type;
+ isl_multi_union_pw_aff *mupa;
+ isl_union_set *filter;
+
+ type = isl_schedule_tree_get_type(tree);
+ switch (type) {
+ case isl_schedule_node_error:
+ return -1;
+ case isl_schedule_node_leaf:
+ case isl_schedule_node_sequence:
+ case isl_schedule_node_set:
+ return 0;
+ case isl_schedule_node_domain:
+ filter = isl_schedule_tree_domain_get_domain(tree);
+ filter = isl_union_set_universe(filter);
+ data->filter = filter;
+ break;
+ case isl_schedule_node_band:
+ if (isl_schedule_tree_band_n_member(tree) == 0)
+ return 0;
+ mupa = isl_schedule_tree_band_get_partial_schedule(tree);
+ if (data->collect_prefix) {
+ isl_multi_union_pw_aff_free(data->prefix);
+ mupa = isl_multi_union_pw_aff_reset_tuple_id(mupa,
+ isl_dim_set);
+ data->prefix = isl_multi_union_pw_aff_copy(mupa);
+ }
+ filter = isl_multi_union_pw_aff_domain(mupa);
+ filter = isl_union_set_universe(filter);
+ data->filter = filter;
+ break;
+ case isl_schedule_node_filter:
+ filter = isl_schedule_tree_filter_get_filter(tree);
+ if (data->universe_filter)
+ filter = isl_union_set_universe(filter);
+ data->filter = filter;
+ break;
+ }
+
+ if ((data->collect_prefix && !data->prefix) || !data->filter)
+ return -1;
+
+ data->initialized = 1;
+
+ return 0;
+}
+
+/* Update "data" based on the tree node "tree" in case "data" has
+ * already been initialized.
+ *
+ * Return 0 on success and -1 on error.
+ *
+ * If "tree" is a filter, then we intersect data->filter with this filter
+ * (or its universe).
+ * If "tree" is a band with at least one member and data->collect_prefix
+ * is set, then we extend data->prefix with the band schedule.
+ */
+static int collect_filter_prefix_update(__isl_keep isl_schedule_tree *tree,
+ struct isl_schedule_node_get_filter_prefix_data *data)
+{
+ enum isl_schedule_node_type type;
+ isl_multi_union_pw_aff *mupa;
+ isl_union_set *filter;
+
+ type = isl_schedule_tree_get_type(tree);
+ switch (type) {
+ case isl_schedule_node_error:
+ return -1;
+ case isl_schedule_node_domain:
+ case isl_schedule_node_leaf:
+ case isl_schedule_node_sequence:
+ case isl_schedule_node_set:
+ break;
+ case isl_schedule_node_band:
+ if (isl_schedule_tree_band_n_member(tree) == 0)
+ break;
+ if (!data->collect_prefix)
+ break;
+ mupa = isl_schedule_tree_band_get_partial_schedule(tree);
+ data->prefix = isl_multi_union_pw_aff_flat_range_product(mupa,
+ data->prefix);
+ if (!data->prefix)
+ return -1;
+ break;
+ case isl_schedule_node_filter:
+ filter = isl_schedule_tree_filter_get_filter(tree);
+ if (data->universe_filter)
+ filter = isl_union_set_universe(filter);
+ data->filter = isl_union_set_intersect(data->filter, filter);
+ if (!data->filter)
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
+/* Collect filter and/or prefix information from the elements
+ * in "list" (which represent the ancestors of a node).
+ * Store the results in "data".
+ *
+ * Return 0 on success and -1 on error.
+ *
+ * We traverse the list from innermost ancestor (last element)
+ * to outermost ancestor (first element), calling collect_filter_prefix_init
+ * on each node as long as we have not been able to extract any information
+ * yet and collect_filter_prefix_update afterwards.
+ * On successful return, data->initialized will be set since the outermost
+ * ancestor is a domain node, which always results in an initialization.
+ */
+static int collect_filter_prefix(__isl_keep isl_schedule_tree_list *list,
+ struct isl_schedule_node_get_filter_prefix_data *data)
+{
+ int i, n;
+
+ data->initialized = 0;
+ data->filter = NULL;
+
+ if (!list)
+ return -1;
+
+ n = isl_schedule_tree_list_n_schedule_tree(list);
+ for (i = n - 1; i >= 0; --i) {
+ isl_schedule_tree *tree;
+ int r;
+
+ tree = isl_schedule_tree_list_get_schedule_tree(list, i);
+ if (!tree)
+ return -1;
+ if (!data->initialized)
+ r = collect_filter_prefix_init(tree, data);
+ else
+ r = collect_filter_prefix_update(tree, data);
+ isl_schedule_tree_free(tree);
+ if (r < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Return the concatenation of the partial schedules of all outer band
+ * nodes of "node" interesected with all outer filters
+ * as an isl_union_pw_multi_aff.
+ *
+ * If "node" is pointing at the root of the schedule tree, then
+ * there are no domain elements reaching the current node, so
+ * we return an empty result.
+ *
+ * We collect all the filters and partial schedules in collect_filter_prefix.
+ * The partial schedules are collected as an isl_multi_union_pw_aff.
+ * If this isl_multi_union_pw_aff is zero-dimensional, then it does not
+ * contain any domain information, so we construct the isl_union_pw_multi_aff
+ * result as a zero-dimensional function on the collected filter.
+ * Otherwise, we convert the isl_multi_union_pw_aff to
+ * an isl_multi_union_pw_aff and intersect the domain with the filter.
+ */
+__isl_give isl_union_pw_multi_aff *
+isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(
+ __isl_keep isl_schedule_node *node)
+{
+ isl_space *space;
+ isl_union_pw_multi_aff *prefix;
+ struct isl_schedule_node_get_filter_prefix_data data;
+
+ if (!node)
+ return NULL;
+
+ space = isl_schedule_get_space(node->schedule);
+ if (node->tree == node->schedule->root)
+ return isl_union_pw_multi_aff_empty(space);
+
+ space = isl_space_set_from_params(space);
+ data.universe_filter = 0;
+ data.collect_prefix = 1;
+ data.prefix = isl_multi_union_pw_aff_zero(space);
+
+ if (collect_filter_prefix(node->ancestors, &data) < 0)
+ data.prefix = isl_multi_union_pw_aff_free(data.prefix);
+
+ if (data.prefix &&
+ isl_multi_union_pw_aff_dim(data.prefix, isl_dim_set) == 0) {
+ isl_multi_union_pw_aff_free(data.prefix);
+ prefix = isl_union_pw_multi_aff_from_domain(data.filter);
+ } else {
+ prefix =
+ isl_union_pw_multi_aff_from_multi_union_pw_aff(data.prefix);
+ prefix = isl_union_pw_multi_aff_intersect_domain(prefix,
+ data.filter);
+ }
+
+ return prefix;
+}
+
+/* Return the concatenation of the partial schedules of all outer band
+ * nodes of "node" interesected with all outer filters
+ * as an isl_union_map.
+ */
+__isl_give isl_union_map *isl_schedule_node_get_prefix_schedule_union_map(
+ __isl_keep isl_schedule_node *node)
+{
+ isl_union_pw_multi_aff *upma;
+
+ upma = isl_schedule_node_get_prefix_schedule_union_pw_multi_aff(node);
+ return isl_union_map_from_union_pw_multi_aff(upma);
+}
+
+/* Return the union of universe sets of the domain elements that reach "node".
+ *
+ * If "node" is pointing at the root of the schedule tree, then
+ * there are no domain elements reaching the current node, so
+ * we return an empty result.
+ *
+ * Otherwise, we collect the universes of all filters reaching the node
+ * in collect_filter_prefix.
+ */
+__isl_give isl_union_set *isl_schedule_node_get_universe_domain(
+ __isl_keep isl_schedule_node *node)
+{
+ struct isl_schedule_node_get_filter_prefix_data data;
+
+ if (!node)
+ return NULL;
+
+ if (node->tree == node->schedule->root) {
+ isl_space *space;
+
+ space = isl_schedule_get_space(node->schedule);
+ return isl_union_set_empty(space);
+ }
+
+ data.universe_filter = 1;
+ data.collect_prefix = 0;
+ data.prefix = NULL;
+
+ if (collect_filter_prefix(node->ancestors, &data) < 0)
+ data.filter = isl_union_set_free(data.filter);
+
+ return data.filter;
+}
+
+/* Return the subtree schedule of "node".
+ *
+ * Since isl_schedule_tree_get_subtree_schedule_union_map does not handle
+ * trees that do not contain any schedule information, we first
+ * move down to the first relevant descendant and handle leaves ourselves.
+ */
+__isl_give isl_union_map *isl_schedule_node_get_subtree_schedule_union_map(
+ __isl_keep isl_schedule_node *node)
+{
+ isl_schedule_tree *tree, *leaf;
+ isl_union_map *umap;
+
+ tree = isl_schedule_node_get_tree(node);
+ leaf = isl_schedule_node_peek_leaf(node);
+ tree = isl_schedule_tree_first_schedule_descendant(tree, leaf);
+ if (!tree)
+ return NULL;
+ if (tree == leaf) {
+ isl_union_set *domain;
+ domain = isl_schedule_node_get_universe_domain(node);
+ isl_schedule_tree_free(tree);
+ return isl_union_map_from_domain(domain);
+ }
+
+ umap = isl_schedule_tree_get_subtree_schedule_union_map(tree);
+ isl_schedule_tree_free(tree);
+ return umap;
+}
+
+/* Return the number of ancestors of "node" in its schedule tree.
+ */
+int isl_schedule_node_get_tree_depth(__isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return -1;
+ return isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+}
+
+/* Does "node" have a parent?
+ *
+ * That is, does it point to any node of the schedule other than the root?
+ */
+int isl_schedule_node_has_parent(__isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return -1;
+ if (!node->ancestors)
+ return -1;
+
+ return isl_schedule_tree_list_n_schedule_tree(node->ancestors) != 0;
+}
+
+/* Return the position of "node" among the children of its parent.
+ */
+int isl_schedule_node_get_child_position(__isl_keep isl_schedule_node *node)
+{
+ int n;
+ int has_parent;
+
+ if (!node)
+ return -1;
+ has_parent = isl_schedule_node_has_parent(node);
+ if (has_parent < 0)
+ return -1;
+ if (!has_parent)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "node has no parent", return -1);
+
+ n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+ return node->child_pos[n - 1];
+}
+
+/* Does the parent (if any) of "node" have any children with a smaller child
+ * position than this one?
+ */
+int isl_schedule_node_has_previous_sibling(__isl_keep isl_schedule_node *node)
+{
+ int n;
+ int has_parent;
+
+ if (!node)
+ return -1;
+ has_parent = isl_schedule_node_has_parent(node);
+ if (has_parent < 0 || !has_parent)
+ return has_parent;
+
+ n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+
+ return node->child_pos[n - 1] > 0;
+}
+
+/* Does the parent (if any) of "node" have any children with a greater child
+ * position than this one?
+ */
+int isl_schedule_node_has_next_sibling(__isl_keep isl_schedule_node *node)
+{
+ int n, n_child;
+ int has_parent;
+ isl_schedule_tree *tree;
+
+ if (!node)
+ return -1;
+ has_parent = isl_schedule_node_has_parent(node);
+ if (has_parent < 0 || !has_parent)
+ return has_parent;
+
+ n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+ tree = isl_schedule_tree_list_get_schedule_tree(node->ancestors, n - 1);
+ if (!tree)
+ return -1;
+ n_child = isl_schedule_tree_list_n_schedule_tree(tree->children);
+ isl_schedule_tree_free(tree);
+
+ return node->child_pos[n - 1] + 1 < n_child;
+}
+
+/* Does "node" have any children?
+ *
+ * Any node other than the leaf nodes is considered to have at least
+ * one child, even if the corresponding isl_schedule_tree does not
+ * have any children.
+ */
+int isl_schedule_node_has_children(__isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return -1;
+ return !isl_schedule_tree_is_leaf(node->tree);
+}
+
+/* Return the number of children of "node"?
+ *
+ * Any node other than the leaf nodes is considered to have at least
+ * one child, even if the corresponding isl_schedule_tree does not
+ * have any children. That is, the number of children of "node" is
+ * only zero if its tree is the explicit empty tree. Otherwise,
+ * if the isl_schedule_tree has any children, then it is equal
+ * to the number of children of "node". If it has zero children,
+ * then "node" still has a leaf node as child.
+ */
+int isl_schedule_node_n_children(__isl_keep isl_schedule_node *node)
+{
+ int n;
+
+ if (!node)
+ return -1;
+
+ if (isl_schedule_tree_is_leaf(node->tree))
+ return 0;
+
+ n = isl_schedule_tree_n_children(node->tree);
+ if (n == 0)
+ return 1;
+
+ return n;
+}
+
+/* Move the "node" pointer to the parent of the node it currently points to.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_parent(
+ __isl_take isl_schedule_node *node)
+{
+ int n;
+ isl_schedule_tree *tree;
+
+ node = isl_schedule_node_cow(node);
+ if (!node)
+ return NULL;
+ if (!isl_schedule_node_has_parent(node))
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "node has no parent",
+ return isl_schedule_node_free(node));
+ n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+ tree = isl_schedule_tree_list_get_schedule_tree(node->ancestors, n - 1);
+ isl_schedule_tree_free(node->tree);
+ node->tree = tree;
+ node->ancestors = isl_schedule_tree_list_drop(node->ancestors,
+ n - 1, 1);
+ if (!node->ancestors || !node->tree)
+ return isl_schedule_node_free(node);
+
+ return node;
+}
+
+/* Move the "node" pointer to the child at position "pos" of the node
+ * it currently points to.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_child(
+ __isl_take isl_schedule_node *node, int pos)
+{
+ int n;
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+ int *child_pos;
+
+ node = isl_schedule_node_cow(node);
+ if (!node)
+ return NULL;
+ if (!isl_schedule_node_has_children(node))
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "node has no children",
+ return isl_schedule_node_free(node));
+
+ ctx = isl_schedule_node_get_ctx(node);
+ n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+ child_pos = isl_realloc_array(ctx, node->child_pos, int, n + 1);
+ if (!child_pos)
+ return isl_schedule_node_free(node);
+ node->child_pos = child_pos;
+ node->child_pos[n] = pos;
+
+ node->ancestors = isl_schedule_tree_list_add(node->ancestors,
+ isl_schedule_tree_copy(node->tree));
+ tree = node->tree;
+ if (isl_schedule_tree_has_children(tree))
+ tree = isl_schedule_tree_get_child(tree, pos);
+ else
+ tree = isl_schedule_node_get_leaf(node);
+ isl_schedule_tree_free(node->tree);
+ node->tree = tree;
+
+ if (!node->tree || !node->ancestors)
+ return isl_schedule_node_free(node);
+
+ return node;
+}
+
+/* Move the "node" pointer to the first child of the node
+ * it currently points to.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_first_child(
+ __isl_take isl_schedule_node *node)
+{
+ return isl_schedule_node_child(node, 0);
+}
+
+/* Move the "node" pointer to the child of this node's parent in
+ * the previous child position.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_previous_sibling(
+ __isl_take isl_schedule_node *node)
+{
+ int n;
+ isl_schedule_tree *parent, *tree;
+
+ node = isl_schedule_node_cow(node);
+ if (!node)
+ return NULL;
+ if (!isl_schedule_node_has_previous_sibling(node))
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "node has no previous sibling",
+ return isl_schedule_node_free(node));
+
+ n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+ parent = isl_schedule_tree_list_get_schedule_tree(node->ancestors,
+ n - 1);
+ if (!parent)
+ return isl_schedule_node_free(node);
+ node->child_pos[n - 1]--;
+ tree = isl_schedule_tree_list_get_schedule_tree(parent->children,
+ node->child_pos[n - 1]);
+ isl_schedule_tree_free(parent);
+ if (!tree)
+ return isl_schedule_node_free(node);
+ isl_schedule_tree_free(node->tree);
+ node->tree = tree;
+
+ return node;
+}
+
+/* Move the "node" pointer to the child of this node's parent in
+ * the next child position.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_next_sibling(
+ __isl_take isl_schedule_node *node)
+{
+ int n;
+ isl_schedule_tree *parent, *tree;
+
+ node = isl_schedule_node_cow(node);
+ if (!node)
+ return NULL;
+ if (!isl_schedule_node_has_next_sibling(node))
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "node has no next sibling",
+ return isl_schedule_node_free(node));
+
+ n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+ parent = isl_schedule_tree_list_get_schedule_tree(node->ancestors,
+ n - 1);
+ if (!parent)
+ return isl_schedule_node_free(node);
+ node->child_pos[n - 1]++;
+ tree = isl_schedule_tree_list_get_schedule_tree(parent->children,
+ node->child_pos[n - 1]);
+ isl_schedule_tree_free(parent);
+ if (!tree)
+ return isl_schedule_node_free(node);
+ isl_schedule_tree_free(node->tree);
+ node->tree = tree;
+
+ return node;
+}
+
+/* Return a copy to the child at position "pos" of "node".
+ */
+__isl_give isl_schedule_node *isl_schedule_node_get_child(
+ __isl_keep isl_schedule_node *node, int pos)
+{
+ return isl_schedule_node_child(isl_schedule_node_copy(node), pos);
+}
+
+/* Traverse the descendant of "node" in depth-first order, including
+ * "node" itself. Call "enter" whenever a node is entered and "leave"
+ * whenever a node is left. The callback "enter" is responsible
+ * for moving to the deepest initial subtree of its argument that
+ * should be traversed.
+ */
+static __isl_give isl_schedule_node *traverse(
+ __isl_take isl_schedule_node *node,
+ __isl_give isl_schedule_node *(*enter)(
+ __isl_take isl_schedule_node *node, void *user),
+ __isl_give isl_schedule_node *(*leave)(
+ __isl_take isl_schedule_node *node, void *user),
+ void *user)
+{
+ int depth;
+
+ if (!node)
+ return NULL;
+
+ depth = isl_schedule_node_get_tree_depth(node);
+ do {
+ node = enter(node, user);
+ node = leave(node, user);
+ while (node && isl_schedule_node_get_tree_depth(node) > depth &&
+ !isl_schedule_node_has_next_sibling(node)) {
+ node = isl_schedule_node_parent(node);
+ node = leave(node, user);
+ }
+ if (node && isl_schedule_node_get_tree_depth(node) > depth)
+ node = isl_schedule_node_next_sibling(node);
+ } while (node && isl_schedule_node_get_tree_depth(node) > depth);
+
+ return node;
+}
+
+/* Internal data structure for isl_schedule_node_foreach_descendant.
+ *
+ * "fn" is the user-specified callback function.
+ * "user" is the user-specified argument for the callback.
+ */
+struct isl_schedule_node_preorder_data {
+ int (*fn)(__isl_keep isl_schedule_node *node, void *user);
+ void *user;
+};
+
+/* Callback for "traverse" to enter a node and to move
+ * to the deepest initial subtree that should be traversed
+ * for use in a preorder visit.
+ *
+ * If the user callback returns a negative value, then we abort
+ * the traversal. If this callback returns zero, then we skip
+ * the subtree rooted at the current node. Otherwise, we move
+ * down to the first child and repeat the process until a leaf
+ * is reached.
+ */
+static __isl_give isl_schedule_node *preorder_enter(
+ __isl_take isl_schedule_node *node, void *user)
+{
+ struct isl_schedule_node_preorder_data *data = user;
+
+ if (!node)
+ return NULL;
+
+ do {
+ int r;
+
+ r = data->fn(node, data->user);
+ if (r < 0)
+ return isl_schedule_node_free(node);
+ if (r == 0)
+ return node;
+ } while (isl_schedule_node_has_children(node) &&
+ (node = isl_schedule_node_first_child(node)) != NULL);
+
+ return node;
+}
+
+/* Callback for "traverse" to leave a node
+ * for use in a preorder visit.
+ * Since we already visited the node when we entered it,
+ * we do not need to do anything here.
+ */
+static __isl_give isl_schedule_node *preorder_leave(
+ __isl_take isl_schedule_node *node, void *user)
+{
+ return node;
+}
+
+/* Traverse the descendants of "node" (including the node itself)
+ * in depth first preorder.
+ *
+ * If "fn" returns -1 on any of the nodes, then the traversal is aborted.
+ * If "fn" returns 0 on any of the nodes, then the subtree rooted
+ * at that node is skipped.
+ *
+ * Return 0 on success and -1 on failure.
+ */
+int isl_schedule_node_foreach_descendant(__isl_keep isl_schedule_node *node,
+ int (*fn)(__isl_keep isl_schedule_node *node, void *user), void *user)
+{
+ struct isl_schedule_node_preorder_data data = { fn, user };
+
+ node = isl_schedule_node_copy(node);
+ node = traverse(node, &preorder_enter, &preorder_leave, &data);
+ isl_schedule_node_free(node);
+
+ return node ? 0 : -1;
+}
+
+/* Internal data structure for isl_schedule_node_map_descendant.
+ *
+ * "fn" is the user-specified callback function.
+ * "user" is the user-specified argument for the callback.
+ */
+struct isl_schedule_node_postorder_data {
+ __isl_give isl_schedule_node *(*fn)(__isl_take isl_schedule_node *node,
+ void *user);
+ void *user;
+};
+
+/* Callback for "traverse" to enter a node and to move
+ * to the deepest initial subtree that should be traversed
+ * for use in a postorder visit.
+ *
+ * Since we are performing a postorder visit, we only need
+ * to move to the deepest initial leaf here.
+ */
+static __isl_give isl_schedule_node *postorder_enter(
+ __isl_take isl_schedule_node *node, void *user)
+{
+ while (node && isl_schedule_node_has_children(node))
+ node = isl_schedule_node_first_child(node);
+
+ return node;
+}
+
+/* Callback for "traverse" to leave a node
+ * for use in a postorder visit.
+ *
+ * Since we are performing a postorder visit, we need
+ * to call the user callback here.
+ */
+static __isl_give isl_schedule_node *postorder_leave(
+ __isl_take isl_schedule_node *node, void *user)
+{
+ struct isl_schedule_node_postorder_data *data = user;
+
+ return data->fn(node, data->user);
+}
+
+/* Traverse the descendants of "node" (including the node itself)
+ * in depth first postorder, allowing the user to modify the visited node.
+ * The traversal continues from the node returned by the callback function.
+ * It is the responsibility of the user to ensure that this does not
+ * lead to an infinite loop. It is safest to always return a pointer
+ * to the same position (same ancestors and child positions) as the input node.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_map_descendant(
+ __isl_take isl_schedule_node *node,
+ __isl_give isl_schedule_node *(*fn)(__isl_take isl_schedule_node *node,
+ void *user), void *user)
+{
+ struct isl_schedule_node_postorder_data data = { fn, user };
+
+ return traverse(node, &postorder_enter, &postorder_leave, &data);
+}
+
+/* Return the number of members in the given band node.
+ */
+unsigned isl_schedule_node_band_n_member(__isl_keep isl_schedule_node *node)
+{
+ return node ? isl_schedule_tree_band_n_member(node->tree) : 0;
+}
+
+/* Is the band member at position "pos" of the band node "node"
+ * marked coincident?
+ */
+int isl_schedule_node_band_member_get_coincident(
+ __isl_keep isl_schedule_node *node, int pos)
+{
+ if (!node)
+ return -1;
+ return isl_schedule_tree_band_member_get_coincident(node->tree, pos);
+}
+
+/* Mark the band member at position "pos" the band node "node"
+ * as being coincident or not according to "coincident".
+ */
+__isl_give isl_schedule_node *isl_schedule_node_band_member_set_coincident(
+ __isl_take isl_schedule_node *node, int pos, int coincident)
+{
+ int c;
+ isl_schedule_tree *tree;
+
+ if (!node)
+ return NULL;
+ c = isl_schedule_node_band_member_get_coincident(node, pos);
+ if (c == coincident)
+ return node;
+
+ tree = isl_schedule_tree_copy(node->tree);
+ tree = isl_schedule_tree_band_member_set_coincident(tree, pos,
+ coincident);
+ node = isl_schedule_node_graft_tree(node, tree);
+
+ return node;
+}
+
+/* Is the band node "node" marked permutable?
+ */
+int isl_schedule_node_band_get_permutable(__isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return -1;
+
+ return isl_schedule_tree_band_get_permutable(node->tree);
+}
+
+/* Mark the band node "node" permutable or not according to "permutable"?
+ */
+__isl_give isl_schedule_node *isl_schedule_node_band_set_permutable(
+ __isl_take isl_schedule_node *node, int permutable)
+{
+ isl_schedule_tree *tree;
+
+ if (!node)
+ return NULL;
+ if (isl_schedule_node_band_get_permutable(node) == permutable)
+ return node;
+
+ tree = isl_schedule_tree_copy(node->tree);
+ tree = isl_schedule_tree_band_set_permutable(tree, permutable);
+ node = isl_schedule_node_graft_tree(node, tree);
+
+ return node;
+}
+
+/* Return the schedule space of the band node.
+ */
+__isl_give isl_space *isl_schedule_node_band_get_space(
+ __isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return NULL;
+
+ return isl_schedule_tree_band_get_space(node->tree);
+}
+
+/* Return the schedule of the band node in isolation.
+ */
+__isl_give isl_multi_union_pw_aff *isl_schedule_node_band_get_partial_schedule(
+ __isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return NULL;
+
+ return isl_schedule_tree_band_get_partial_schedule(node->tree);
+}
+
+/* Return the schedule of the band node in isolation in the form of
+ * an isl_union_map.
+ *
+ * If the band does not have any members, then we construct a universe map
+ * with the universe of the domain elements reaching the node as domain.
+ * Otherwise, we extract an isl_multi_union_pw_aff representation and
+ * convert that to an isl_union_map.
+ */
+__isl_give isl_union_map *isl_schedule_node_band_get_partial_schedule_union_map(
+ __isl_keep isl_schedule_node *node)
+{
+ isl_multi_union_pw_aff *mupa;
+
+ if (!node)
+ return NULL;
+
+ if (isl_schedule_node_get_type(node) != isl_schedule_node_band)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "not a band node", return NULL);
+ if (isl_schedule_node_band_n_member(node) == 0) {
+ isl_union_set *domain;
+
+ domain = isl_schedule_node_get_universe_domain(node);
+ return isl_union_map_from_domain(domain);
+ }
+
+ mupa = isl_schedule_node_band_get_partial_schedule(node);
+ return isl_union_map_from_multi_union_pw_aff(mupa);
+}
+
+/* Make sure that that spaces of "node" and "mv" are the same.
+ * Return -1 on error, reporting the error to the user.
+ */
+static int check_space_multi_val(__isl_keep isl_schedule_node *node,
+ __isl_keep isl_multi_val *mv)
+{
+ isl_space *node_space, *mv_space;
+ int equal;
+
+ node_space = isl_schedule_node_band_get_space(node);
+ mv_space = isl_multi_val_get_space(mv);
+ equal = isl_space_tuple_is_equal(node_space, isl_dim_set,
+ mv_space, isl_dim_set);
+ isl_space_free(mv_space);
+ isl_space_free(node_space);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "spaces don't match", return -1);
+
+ return 0;
+}
+
+/* Multiply the partial schedule of the band node "node"
+ * with the factors in "mv".
+ */
+__isl_give isl_schedule_node *isl_schedule_node_band_scale(
+ __isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv)
+{
+ isl_schedule_tree *tree;
+
+ if (!node || !mv)
+ goto error;
+ if (check_space_multi_val(node, mv) < 0)
+ goto error;
+
+ tree = isl_schedule_node_get_tree(node);
+ tree = isl_schedule_tree_band_scale(tree, mv);
+ return isl_schedule_node_graft_tree(node, tree);
+error:
+ isl_multi_val_free(mv);
+ isl_schedule_node_free(node);
+ return NULL;
+}
+
+/* Divide the partial schedule of the band node "node"
+ * by the factors in "mv".
+ */
+__isl_give isl_schedule_node *isl_schedule_node_band_scale_down(
+ __isl_take isl_schedule_node *node, __isl_take isl_multi_val *mv)
+{
+ isl_schedule_tree *tree;
+
+ if (!node || !mv)
+ goto error;
+ if (check_space_multi_val(node, mv) < 0)
+ goto error;
+
+ tree = isl_schedule_node_get_tree(node);
+ tree = isl_schedule_tree_band_scale_down(tree, mv);
+ return isl_schedule_node_graft_tree(node, tree);
+error:
+ isl_multi_val_free(mv);
+ isl_schedule_node_free(node);
+ return NULL;
+}
+
+/* Tile "node" with tile sizes "sizes".
+ *
+ * The current node is replaced by two nested nodes corresponding
+ * to the tile dimensions and the point dimensions.
+ *
+ * Return a pointer to the outer (tile) node.
+ *
+ * If the scale tile loops option is set, then the tile loops
+ * are scaled by the tile sizes. If the shift point loops option is set,
+ * then the point loops are shifted to start at zero.
+ * In particular, these options affect the tile and point loop schedules
+ * as follows
+ *
+ * scale shift original tile point
+ *
+ * 0 0 i floor(i/s) i
+ * 1 0 i s * floor(i/s) i
+ * 0 1 i floor(i/s) i - s * floor(i/s)
+ * 1 1 i s * floor(i/s) i - s * floor(i/s)
+ */
+__isl_give isl_schedule_node *isl_schedule_node_band_tile(
+ __isl_take isl_schedule_node *node, __isl_take isl_multi_val *sizes)
+{
+ isl_schedule_tree *tree;
+
+ if (!node || !sizes)
+ goto error;
+
+ if (check_space_multi_val(node, sizes) < 0)
+ goto error;
+
+ tree = isl_schedule_node_get_tree(node);
+ tree = isl_schedule_tree_band_tile(tree, sizes);
+ return isl_schedule_node_graft_tree(node, tree);
+error:
+ isl_multi_val_free(sizes);
+ isl_schedule_node_free(node);
+ return NULL;
+}
+
+/* Move the band node "node" down to all the leaves in the subtree
+ * rooted at "node".
+ * Return a pointer to the node in the resulting tree that is in the same
+ * position as the node pointed to by "node" in the original tree.
+ *
+ * If the node only has a leaf child, then nothing needs to be done.
+ * Otherwise, the child of the node is removed and the result is
+ * appended to all the leaves in the subtree rooted at the original child.
+ * The original node is then replaced by the result of this operation.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_band_sink(
+ __isl_take isl_schedule_node *node)
+{
+ enum isl_schedule_node_type type;
+ isl_schedule_tree *tree, *child;
+
+ if (!node)
+ return NULL;
+
+ type = isl_schedule_node_get_type(node);
+ if (type != isl_schedule_node_band)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "not a band node", isl_schedule_node_free(node));
+ if (isl_schedule_tree_n_children(node->tree) == 0)
+ return node;
+
+ tree = isl_schedule_node_get_tree(node);
+ child = isl_schedule_tree_get_child(tree, 0);
+ tree = isl_schedule_tree_reset_children(tree);
+ tree = isl_schedule_tree_append_to_leaves(child, tree);
+
+ return isl_schedule_node_graft_tree(node, tree);
+}
+
+/* Split "node" into two nested band nodes, one with the first "pos"
+ * dimensions and one with the remaining dimensions.
+ * The schedules of the two band nodes live in anonymous spaces.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_band_split(
+ __isl_take isl_schedule_node *node, int pos)
+{
+ isl_schedule_tree *tree;
+
+ tree = isl_schedule_node_get_tree(node);
+ tree = isl_schedule_tree_band_split(tree, pos);
+ return isl_schedule_node_graft_tree(node, tree);
+}
+
+/* Return the domain of the domain node "node".
+ */
+__isl_give isl_union_set *isl_schedule_node_domain_get_domain(
+ __isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return NULL;
+
+ return isl_schedule_tree_domain_get_domain(node->tree);
+}
+
+/* Return the filter of the filter node "node".
+ */
+__isl_give isl_union_set *isl_schedule_node_filter_get_filter(
+ __isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return NULL;
+
+ return isl_schedule_tree_filter_get_filter(node->tree);
+}
+
+/* Replace the filter of filter node "node" by "filter".
+ */
+__isl_give isl_schedule_node *isl_schedule_node_filter_set_filter(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *filter)
+{
+ isl_schedule_tree *tree;
+
+ if (!node || !filter)
+ goto error;
+
+ tree = isl_schedule_tree_copy(node->tree);
+ tree = isl_schedule_tree_filter_set_filter(tree, filter);
+ return isl_schedule_node_graft_tree(node, tree);
+error:
+ isl_schedule_node_free(node);
+ isl_union_set_free(filter);
+ return NULL;
+}
+
+/* Update the ancestors of "node" to point to the tree that "node"
+ * now points to.
+ * That is, replace the child in the original parent that corresponds
+ * to the current tree position by node->tree and continue updating
+ * the ancestors in the same way until the root is reached.
+ *
+ * If "node" originally points to a leaf of the schedule tree, then make sure
+ * that in the end it points to a leaf in the updated schedule tree.
+ */
+static __isl_give isl_schedule_node *update_ancestors(
+ __isl_take isl_schedule_node *node)
+{
+ int i, n;
+ int is_leaf;
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+
+ node = isl_schedule_node_cow(node);
+ if (!node)
+ return NULL;
+
+ ctx = isl_schedule_node_get_ctx(node);
+ n = isl_schedule_tree_list_n_schedule_tree(node->ancestors);
+ tree = isl_schedule_tree_copy(node->tree);
+
+ for (i = n - 1; i >= 0; --i) {
+ isl_schedule_tree *parent;
+
+ parent = isl_schedule_tree_list_get_schedule_tree(
+ node->ancestors, i);
+ parent = isl_schedule_tree_replace_child(parent,
+ node->child_pos[i], tree);
+ node->ancestors = isl_schedule_tree_list_set_schedule_tree(
+ node->ancestors, i, isl_schedule_tree_copy(parent));
+
+ tree = parent;
+ }
+
+ is_leaf = isl_schedule_tree_is_leaf(node->tree);
+ node->schedule = isl_schedule_set_root(node->schedule, tree);
+ if (is_leaf) {
+ isl_schedule_tree_free(node->tree);
+ node->tree = isl_schedule_node_get_leaf(node);
+ }
+
+ if (!node->schedule || !node->ancestors)
+ return isl_schedule_node_free(node);
+
+ return node;
+}
+
+/* Replace the subtree that "pos" points to by "tree", updating
+ * the ancestors to maintain a consistent state.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_graft_tree(
+ __isl_take isl_schedule_node *pos, __isl_take isl_schedule_tree *tree)
+{
+ if (!tree || !pos)
+ goto error;
+ if (pos->tree == tree) {
+ isl_schedule_tree_free(tree);
+ return pos;
+ }
+
+ pos = isl_schedule_node_cow(pos);
+ if (!pos)
+ goto error;
+
+ isl_schedule_tree_free(pos->tree);
+ pos->tree = tree;
+
+ return update_ancestors(pos);
+error:
+ isl_schedule_node_free(pos);
+ isl_schedule_tree_free(tree);
+ return NULL;
+}
+
+/* Make sure we can insert a node between "node" and its parent.
+ * Return -1 on error, reporting the reason why we cannot insert a node.
+ */
+static int check_insert(__isl_keep isl_schedule_node *node)
+{
+ int has_parent;
+ enum isl_schedule_node_type type;
+
+ has_parent = isl_schedule_node_has_parent(node);
+ if (has_parent < 0)
+ return -1;
+ if (!has_parent)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "cannot insert node outside of root", return -1);
+
+ type = isl_schedule_node_get_parent_type(node);
+ if (type == isl_schedule_node_error)
+ return -1;
+ if (type == isl_schedule_node_set || type == isl_schedule_node_sequence)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_invalid,
+ "cannot insert node between set or sequence node "
+ "and its filter children", return -1);
+
+ return 0;
+}
+
+/* Insert a band node with partial schedule "mupa" between "node" and
+ * its parent.
+ * Return a pointer to the new band node.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_insert_partial_schedule(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ isl_schedule_band *band;
+ isl_schedule_tree *tree;
+
+ if (check_insert(node) < 0)
+ node = isl_schedule_node_free(node);
+
+ tree = isl_schedule_node_get_tree(node);
+ band = isl_schedule_band_from_multi_union_pw_aff(mupa);
+ tree = isl_schedule_tree_insert_band(tree, band);
+ node = isl_schedule_node_graft_tree(node, tree);
+
+ return node;
+}
+
+/* Insert a filter node with filter "filter" between "node" and its parent.
+ * Return a pointer to the new filter node.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_insert_filter(
+ __isl_take isl_schedule_node *node, __isl_take isl_union_set *filter)
+{
+ isl_schedule_tree *tree;
+
+ if (check_insert(node) < 0)
+ node = isl_schedule_node_free(node);
+
+ tree = isl_schedule_node_get_tree(node);
+ tree = isl_schedule_tree_insert_filter(tree, filter);
+ node = isl_schedule_node_graft_tree(node, tree);
+
+ return node;
+}
+
+/* Attach the current subtree of "node" to a sequence of filter tree nodes
+ * with filters described by "filters", attach this sequence
+ * of filter tree nodes as children to a new tree of type "type" and
+ * replace the original subtree of "node" by this new tree.
+ */
+static __isl_give isl_schedule_node *isl_schedule_node_insert_children(
+ __isl_take isl_schedule_node *node,
+ enum isl_schedule_node_type type,
+ __isl_take isl_union_set_list *filters)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+ isl_schedule_tree_list *list;
+
+ if (check_insert(node) < 0)
+ node = isl_schedule_node_free(node);
+
+ if (!node || !filters)
+ goto error;
+
+ ctx = isl_schedule_node_get_ctx(node);
+ n = isl_union_set_list_n_union_set(filters);
+ list = isl_schedule_tree_list_alloc(ctx, n);
+ for (i = 0; i < n; ++i) {
+ isl_schedule_tree *tree;
+ isl_union_set *filter;
+
+ tree = isl_schedule_node_get_tree(node);
+ filter = isl_union_set_list_get_union_set(filters, i);
+ tree = isl_schedule_tree_insert_filter(tree, filter);
+ list = isl_schedule_tree_list_add(list, tree);
+ }
+ tree = isl_schedule_tree_from_children(type, list);
+ node = isl_schedule_node_graft_tree(node, tree);
+
+ isl_union_set_list_free(filters);
+ return node;
+error:
+ isl_union_set_list_free(filters);
+ isl_schedule_node_free(node);
+ return NULL;
+}
+
+/* Insert a sequence node with child filters "filters" between "node" and
+ * its parent. That is, the tree that "node" points to is attached
+ * to each of the child nodes of the filter nodes.
+ * Return a pointer to the new sequence node.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_insert_sequence(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_union_set_list *filters)
+{
+ return isl_schedule_node_insert_children(node,
+ isl_schedule_node_sequence, filters);
+}
+
+/* Insert a set node with child filters "filters" between "node" and
+ * its parent. That is, the tree that "node" points to is attached
+ * to each of the child nodes of the filter nodes.
+ * Return a pointer to the new set node.
+ */
+__isl_give isl_schedule_node *isl_schedule_node_insert_set(
+ __isl_take isl_schedule_node *node,
+ __isl_take isl_union_set_list *filters)
+{
+ return isl_schedule_node_insert_children(node,
+ isl_schedule_node_set, filters);
+}
+
+/* Print "node" to "p".
+ */
+__isl_give isl_printer *isl_printer_print_schedule_node(
+ __isl_take isl_printer *p, __isl_keep isl_schedule_node *node)
+{
+ if (!node)
+ return isl_printer_free(p);
+ return isl_printer_print_schedule_tree_mark(p, node->schedule->root,
+ isl_schedule_tree_list_n_schedule_tree(node->ancestors),
+ node->child_pos);
+}
+
+void isl_schedule_node_dump(__isl_keep isl_schedule_node *node)
+{
+ isl_ctx *ctx;
+ isl_printer *printer;
+
+ if (!node)
+ return;
+
+ ctx = isl_schedule_node_get_ctx(node);
+ printer = isl_printer_to_file(ctx, stderr);
+ printer = isl_printer_set_yaml_style(printer, ISL_YAML_STYLE_BLOCK);
+ printer = isl_printer_print_schedule_node(printer, node);
+
+ isl_printer_free(printer);
+}
Added: polly/trunk/lib/External/isl/isl_schedule_node_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_schedule_node_private.h?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_schedule_node_private.h (added)
+++ polly/trunk/lib/External/isl/isl_schedule_node_private.h Mon Feb 16 13:33:40 2015
@@ -0,0 +1,41 @@
+#ifndef ISL_SCHEDLUE_NODE_PRIVATE_H
+#define ISL_SCHEDLUE_NODE_PRIVATE_H
+
+#include <isl/schedule_node.h>
+#include <isl_schedule_band.h>
+
+/* An isl_schedule_node points to a particular location in a schedule tree.
+ *
+ * "schedule" is the schedule that the node is pointing to.
+ * "ancestors" is a list of the n ancestors of the node
+ * that is being pointed to.
+ * The first ancestor is the root of "schedule", while the last ancestor
+ * is the parent of the specified location.
+ * "child_pos" is an array of child positions of the same length as "ancestors",
+ * where ancestor i (i > 0) appears in child_pos[i - 1] of ancestor i - 1 and
+ * "tree" appears in child_pos[n - 1] of ancestor n - 1.
+ * "tree" is the subtree at the specified location.
+ *
+ * Note that the same isl_schedule_tree object may appear several times
+ * in a schedule tree and therefore does not uniquely identify a position
+ * in the schedule tree.
+ */
+struct isl_schedule_node {
+ int ref;
+
+ isl_schedule *schedule;
+ isl_schedule_tree_list *ancestors;
+ int *child_pos;
+ isl_schedule_tree *tree;
+};
+
+__isl_give isl_schedule_node *isl_schedule_node_alloc(
+ __isl_take isl_schedule *schedule, __isl_take isl_schedule_tree *tree,
+ __isl_take isl_schedule_tree_list *ancestors, int *child_pos);
+__isl_give isl_schedule_node *isl_schedule_node_graft_tree(
+ __isl_take isl_schedule_node *pos, __isl_take isl_schedule_tree *tree);
+
+__isl_give isl_schedule_tree *isl_schedule_node_get_tree(
+ __isl_keep isl_schedule_node *node);
+
+#endif
Modified: polly/trunk/lib/External/isl/isl_schedule_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_schedule_private.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_schedule_private.h (original)
+++ polly/trunk/lib/External/isl/isl_schedule_private.h Mon Feb 16 13:33:40 2015
@@ -3,42 +3,39 @@
#include <isl/aff.h>
#include <isl/schedule.h>
+#include <isl_schedule_tree.h>
-/* The schedule for an individual domain, plus information about the bands
- * and scheduling dimensions.
- * In particular, we keep track of the number of bands and for each
- * band, the starting position of the next band. The first band starts at
- * position 0.
- * For each scheduling dimension, we keep track of whether it satisfies
- * the coincidence constraints (within its band).
- */
-struct isl_schedule_node {
- isl_multi_aff *sched;
- int n_band;
- int *band_end;
- int *band_id;
- int *coincident;
-};
-
-/* Information about the computed schedule.
- * n is the number of nodes/domains/statements.
- * n_band is the maximal number of bands.
- * n_total_row is the number of coordinates of the schedule.
- * dim contains a description of the parameters.
+/* A complete schedule tree.
+ *
* band_forest points to a band forest representation of the schedule
* and may be NULL if the forest hasn't been created yet.
+ *
+ * "root" is the root of the schedule tree and may be NULL if we
+ * have created a band forest corresponding to the schedule.
+ *
+ * A pointer to "leaf" may be used to represent a leaf of the schedule.
+ * It should not appear as a child to any other isl_schedule_tree objects,
+ * but an isl_schedule_node may point to "leaf" if it refers to
+ * a leaf of this schedule tree.
*/
struct isl_schedule {
int ref;
- int n;
- int n_band;
- int n_total_row;
- isl_space *dim;
-
isl_band_list *band_forest;
+ isl_schedule_tree *root;
- struct isl_schedule_node node[1];
+ struct isl_schedule_tree leaf;
};
+__isl_give isl_schedule *isl_schedule_from_schedule_tree(isl_ctx *ctx,
+ __isl_take isl_schedule_tree *tree);
+__isl_give isl_schedule *isl_schedule_set_root(
+ __isl_take isl_schedule *schedule, __isl_take isl_schedule_tree *tree);
+__isl_give isl_space *isl_schedule_get_space(
+ __isl_keep isl_schedule *schedule);
+__isl_give isl_union_set *isl_schedule_get_domain(
+ __isl_keep isl_schedule *schedule);
+__isl_keep isl_schedule_tree *isl_schedule_peek_leaf(
+ __isl_keep isl_schedule *schedule);
+
#endif
Added: polly/trunk/lib/External/isl/isl_schedule_read.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_schedule_read.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_schedule_read.c (added)
+++ polly/trunk/lib/External/isl/isl_schedule_read.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,488 @@
+#include <string.h>
+
+#include <isl/schedule.h>
+#include <isl/stream.h>
+#include <isl_schedule_private.h>
+#include <isl_schedule_tree.h>
+
+/* An enumeration of the various keys that may appear in a YAML mapping
+ * of a schedule.
+ */
+enum isl_schedule_key {
+ isl_schedule_key_error = -1,
+ isl_schedule_key_child,
+ isl_schedule_key_coincident,
+ isl_schedule_key_domain,
+ isl_schedule_key_filter,
+ isl_schedule_key_leaf,
+ isl_schedule_key_permutable,
+ isl_schedule_key_schedule,
+ isl_schedule_key_sequence,
+ isl_schedule_key_set
+};
+
+/* Extract a mapping key from the token "tok".
+ * Return isl_schedule_key_error on error, i.e., if "tok" does not
+ * correspond to any known key.
+ */
+static enum isl_schedule_key extract_key(__isl_keep isl_stream *s,
+ struct isl_token *tok)
+{
+ int type;
+ char *name;
+ enum isl_schedule_key key;
+ isl_ctx *ctx;
+
+ ctx = isl_stream_get_ctx(s);
+ type = isl_token_get_type(tok);
+ if (type != ISL_TOKEN_IDENT && type != ISL_TOKEN_STRING) {
+ isl_stream_error(s, tok, "expecting key");
+ return isl_schedule_key_error;
+ }
+ name = isl_token_get_str(ctx, tok);
+ if (!strcmp(name, "child"))
+ key = isl_schedule_key_child;
+ else if (!strcmp(name, "coincident"))
+ key = isl_schedule_key_coincident;
+ else if (!strcmp(name, "domain"))
+ key = isl_schedule_key_domain;
+ else if (!strcmp(name, "filter"))
+ key = isl_schedule_key_filter;
+ else if (!strcmp(name, "leaf"))
+ key = isl_schedule_key_leaf;
+ else if (!strcmp(name, "schedule"))
+ key = isl_schedule_key_schedule;
+ else if (!strcmp(name, "sequence"))
+ key = isl_schedule_key_sequence;
+ else if (!strcmp(name, "set"))
+ key = isl_schedule_key_set;
+ else if (!strcmp(name, "permutable"))
+ key = isl_schedule_key_permutable;
+ else
+ isl_die(ctx, isl_error_invalid, "unknown key",
+ key = isl_schedule_key_error);
+ free(name);
+ return key;
+}
+
+/* Read a key from "s" and return the corresponding enum.
+ * Return isl_schedule_key_error on error, i.e., if the first token
+ * on the stream does not correspond to any known key.
+ */
+static enum isl_schedule_key get_key(__isl_keep isl_stream *s)
+{
+ struct isl_token *tok;
+ enum isl_schedule_key key;
+
+ tok = isl_stream_next_token(s);
+ key = extract_key(s, tok);
+ isl_token_free(tok);
+
+ return key;
+}
+
+static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
+ __isl_keep isl_stream *s);
+
+/* Read a subtree with domain root node from "s".
+ */
+static __isl_give isl_schedule_tree *read_domain(__isl_keep isl_stream *s)
+{
+ isl_union_set *domain = NULL;
+ isl_schedule_tree *tree;
+ isl_ctx *ctx;
+ struct isl_token *tok;
+ enum isl_schedule_key key;
+ char *str;
+ int more;
+
+ ctx = isl_stream_get_ctx(s);
+
+ key = get_key(s);
+
+ if (isl_stream_yaml_next(s) < 0)
+ return NULL;
+
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return NULL;
+ }
+ str = isl_token_get_str(ctx, tok);
+ domain = isl_union_set_read_from_str(ctx, str);
+ free(str);
+ isl_token_free(tok);
+
+ more = isl_stream_yaml_next(s);
+ if (more < 0)
+ goto error;
+ if (!more) {
+ tree = isl_schedule_tree_from_domain(domain);
+ } else {
+ key = get_key(s);
+ if (key != isl_schedule_key_child)
+ isl_die(ctx, isl_error_invalid, "expecting child",
+ goto error);
+ if (isl_stream_yaml_next(s) < 0)
+ goto error;
+ tree = isl_stream_read_schedule_tree(s);
+ tree = isl_schedule_tree_insert_domain(tree, domain);
+ }
+
+ return tree;
+error:
+ isl_union_set_free(domain);
+ return NULL;
+}
+
+/* Read a subtree with filter root node from "s".
+ */
+static __isl_give isl_schedule_tree *read_filter(__isl_keep isl_stream *s)
+{
+ isl_union_set *filter = NULL;
+ isl_schedule_tree *tree;
+ isl_ctx *ctx;
+ struct isl_token *tok;
+ enum isl_schedule_key key;
+ char *str;
+ int more;
+
+ ctx = isl_stream_get_ctx(s);
+
+ key = get_key(s);
+
+ if (isl_stream_yaml_next(s) < 0)
+ return NULL;
+
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return NULL;
+ }
+ str = isl_token_get_str(ctx, tok);
+ filter = isl_union_set_read_from_str(ctx, str);
+ free(str);
+ isl_token_free(tok);
+
+ more = isl_stream_yaml_next(s);
+ if (more < 0)
+ goto error;
+ if (!more) {
+ tree = isl_schedule_tree_from_filter(filter);
+ } else {
+ key = get_key(s);
+ if (key != isl_schedule_key_child)
+ isl_die(ctx, isl_error_invalid, "expecting child",
+ goto error);
+ if (isl_stream_yaml_next(s) < 0)
+ goto error;
+ tree = isl_stream_read_schedule_tree(s);
+ tree = isl_schedule_tree_insert_filter(tree, filter);
+ }
+
+ return tree;
+error:
+ isl_union_set_free(filter);
+ return NULL;
+}
+
+/* Read a sequence of integers from "s" (representing the coincident
+ * property of a band node).
+ */
+static __isl_give isl_val_list *read_coincident(__isl_keep isl_stream *s)
+{
+ isl_ctx *ctx;
+ isl_val_list *list;
+ int more;
+
+ ctx = isl_stream_get_ctx(s);
+
+ if (isl_stream_yaml_read_start_sequence(s) < 0)
+ return NULL;
+
+ list = isl_val_list_alloc(ctx, 0);
+ while ((more = isl_stream_yaml_next(s)) > 0) {
+ isl_val *val;
+
+ val = isl_stream_read_val(s);
+ list = isl_val_list_add(list, val);
+ }
+
+ if (more < 0 || isl_stream_yaml_read_end_sequence(s))
+ list = isl_val_list_free(list);
+
+ return list;
+}
+
+/* Set the (initial) coincident properties of "band" according to
+ * the (initial) elements of "coincident".
+ */
+static __isl_give isl_schedule_band *set_coincident(
+ __isl_take isl_schedule_band *band, __isl_take isl_val_list *coincident)
+{
+ int i;
+ int n, m;
+
+ n = isl_schedule_band_n_member(band);
+ m = isl_val_list_n_val(coincident);
+
+ for (i = 0; i < n && i < m; ++i) {
+ isl_val *v;
+
+ v = isl_val_list_get_val(coincident, i);
+ if (!v)
+ band = isl_schedule_band_free(band);
+ band = isl_schedule_band_member_set_coincident(band, i,
+ !isl_val_is_zero(v));
+ isl_val_free(v);
+ }
+ isl_val_list_free(coincident);
+ return band;
+}
+
+/* Read a subtree with band root node from "s".
+ */
+static __isl_give isl_schedule_tree *read_band(isl_stream *s)
+{
+ isl_multi_union_pw_aff *schedule = NULL;
+ isl_schedule_tree *tree = NULL;
+ isl_val_list *coincident = NULL;
+ isl_ctx *ctx;
+ isl_schedule_band *band;
+ int permutable = 0;
+ int more;
+
+ ctx = isl_stream_get_ctx(s);
+
+ do {
+ struct isl_token *tok;
+ enum isl_schedule_key key;
+ char *str;
+ isl_val *v;
+
+ key = get_key(s);
+ if (isl_stream_yaml_next(s) < 0)
+ goto error;
+
+ switch (key) {
+ case isl_schedule_key_schedule:
+ isl_multi_union_pw_aff_free(schedule);
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ isl_stream_error(s, NULL, "unexpected EOF");
+ goto error;
+ }
+ str = isl_token_get_str(ctx, tok);
+ schedule = isl_multi_union_pw_aff_read_from_str(ctx,
+ str);
+ free(str);
+ isl_token_free(tok);
+ if (!schedule)
+ goto error;
+ break;
+ case isl_schedule_key_coincident:
+ coincident = read_coincident(s);
+ if (!coincident)
+ goto error;
+ break;
+ case isl_schedule_key_permutable:
+ v = isl_stream_read_val(s);
+ permutable = !isl_val_is_zero(v);
+ isl_val_free(v);
+ break;
+ case isl_schedule_key_child:
+ isl_schedule_tree_free(tree);
+ tree = isl_stream_read_schedule_tree(s);
+ if (!tree)
+ goto error;
+ break;
+ default:
+ isl_die(ctx, isl_error_invalid, "unexpected key",
+ goto error);
+ }
+ } while ((more = isl_stream_yaml_next(s)) > 0);
+
+ if (more < 0)
+ goto error;
+
+ if (!schedule)
+ isl_die(ctx, isl_error_invalid, "missing schedule", goto error);
+
+ band = isl_schedule_band_from_multi_union_pw_aff(schedule);
+ band = isl_schedule_band_set_permutable(band, permutable);
+ if (coincident)
+ band = set_coincident(band, coincident);
+ if (tree)
+ tree = isl_schedule_tree_insert_band(tree, band);
+ else
+ tree = isl_schedule_tree_from_band(band);
+
+ return tree;
+error:
+ isl_val_list_free(coincident);
+ isl_schedule_tree_free(tree);
+ isl_multi_union_pw_aff_free(schedule);
+ return NULL;
+}
+
+/* Read a subtree with root node of type "type" from "s".
+ * The node is represented by a sequence of children.
+ */
+static __isl_give isl_schedule_tree *read_children(isl_stream *s,
+ enum isl_schedule_node_type type)
+{
+ isl_ctx *ctx;
+ isl_schedule_tree_list *list;
+ int more;
+
+ ctx = isl_stream_get_ctx(s);
+
+ isl_token_free(isl_stream_next_token(s));
+
+ if (isl_stream_yaml_next(s) < 0)
+ return NULL;
+
+ if (isl_stream_yaml_read_start_sequence(s))
+ return NULL;
+
+ list = isl_schedule_tree_list_alloc(ctx, 0);
+ while ((more = isl_stream_yaml_next(s)) > 0) {
+ isl_schedule_tree *tree;
+
+ tree = isl_stream_read_schedule_tree(s);
+ list = isl_schedule_tree_list_add(list, tree);
+ }
+
+ if (more < 0 || isl_stream_yaml_read_end_sequence(s))
+ list = isl_schedule_tree_list_free(list);
+
+ return isl_schedule_tree_from_children(type, list);
+}
+
+/* Read a subtree with sequence root node from "s".
+ */
+static __isl_give isl_schedule_tree *read_sequence(isl_stream *s)
+{
+ return read_children(s, isl_schedule_node_sequence);
+}
+
+/* Read a subtree with set root node from "s".
+ */
+static __isl_give isl_schedule_tree *read_set(isl_stream *s)
+{
+ return read_children(s, isl_schedule_node_set);
+}
+
+/* Read a schedule (sub)tree from "s".
+ *
+ * We first determine the type of the root node based on the first
+ * mapping key and then hand over to a function tailored to reading
+ * nodes of this type.
+ */
+static __isl_give isl_schedule_tree *isl_stream_read_schedule_tree(
+ struct isl_stream *s)
+{
+ enum isl_schedule_key key;
+ struct isl_token *tok;
+ isl_schedule_tree *tree = NULL;
+ int more;
+
+ if (isl_stream_yaml_read_start_mapping(s))
+ return NULL;
+ more = isl_stream_yaml_next(s);
+ if (more < 0)
+ return NULL;
+ if (!more) {
+ isl_stream_error(s, NULL, "missing key");
+ return NULL;
+ }
+
+ tok = isl_stream_next_token(s);
+ key = extract_key(s, tok);
+ isl_stream_push_token(s, tok);
+ if (key < 0)
+ return NULL;
+ switch (key) {
+ case isl_schedule_key_domain:
+ tree = read_domain(s);
+ break;
+ case isl_schedule_key_filter:
+ tree = read_filter(s);
+ break;
+ case isl_schedule_key_leaf:
+ isl_token_free(isl_stream_next_token(s));
+ tree = isl_schedule_tree_leaf(isl_stream_get_ctx(s));
+ break;
+ case isl_schedule_key_sequence:
+ tree = read_sequence(s);
+ break;
+ case isl_schedule_key_set:
+ tree = read_set(s);
+ break;
+ case isl_schedule_key_schedule:
+ case isl_schedule_key_coincident:
+ case isl_schedule_key_permutable:
+ tree = read_band(s);
+ break;
+ case isl_schedule_key_child:
+ isl_die(isl_stream_get_ctx(s), isl_error_unsupported,
+ "cannot identity node type", return NULL);
+ case isl_schedule_key_error:
+ return NULL;
+ }
+
+ if (isl_stream_yaml_read_end_mapping(s) < 0) {
+ isl_stream_error(s, NULL, "unexpected extra elements");
+ return isl_schedule_tree_free(tree);
+ }
+
+ return tree;
+}
+
+/* Read an isl_schedule from "s".
+ */
+__isl_give isl_schedule *isl_stream_read_schedule(isl_stream *s)
+{
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+
+ if (!s)
+ return NULL;
+
+ ctx = isl_stream_get_ctx(s);
+ tree = isl_stream_read_schedule_tree(s);
+ return isl_schedule_from_schedule_tree(ctx, tree);
+}
+
+/* Read an isl_schedule from "input".
+ */
+__isl_give isl_schedule *isl_schedule_read_from_file(isl_ctx *ctx, FILE *input)
+{
+ struct isl_stream *s;
+ isl_schedule *schedule;
+
+ s = isl_stream_new_file(ctx, input);
+ if (!s)
+ return NULL;
+ schedule = isl_stream_read_schedule(s);
+ isl_stream_free(s);
+
+ return schedule;
+}
+
+/* Read an isl_schedule from "str".
+ */
+__isl_give isl_schedule *isl_schedule_read_from_str(isl_ctx *ctx,
+ const char *str)
+{
+ struct isl_stream *s;
+ isl_schedule *schedule;
+
+ s = isl_stream_new_str(ctx, str);
+ if (!s)
+ return NULL;
+ schedule = isl_stream_read_schedule(s);
+ isl_stream_free(s);
+
+ return schedule;
+}
Added: polly/trunk/lib/External/isl/isl_schedule_tree.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_schedule_tree.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_schedule_tree.c (added)
+++ polly/trunk/lib/External/isl/isl_schedule_tree.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,1423 @@
+/*
+ * Copyright 2013 Ecole Normale Superieure
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege,
+ * Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ */
+
+#include <isl/map.h>
+#include <isl_schedule_band.h>
+#include <isl_schedule_private.h>
+
+#undef EL
+#define EL isl_schedule_tree
+
+#include <isl_list_templ.h>
+
+#undef BASE
+#define BASE schedule_tree
+
+#include <isl_list_templ.c>
+
+/* Is "tree" the leaf of a schedule tree?
+ */
+int isl_schedule_tree_is_leaf(__isl_keep isl_schedule_tree *tree)
+{
+ return isl_schedule_tree_get_type(tree) == isl_schedule_node_leaf;
+}
+
+/* Create a new schedule tree of type "type".
+ * The caller is responsible for filling in the type specific fields and
+ * the children.
+ */
+static __isl_give isl_schedule_tree *isl_schedule_tree_alloc(isl_ctx *ctx,
+ enum isl_schedule_node_type type)
+{
+ isl_schedule_tree *tree;
+
+ if (type == isl_schedule_node_error)
+ return NULL;
+
+ tree = isl_calloc_type(ctx, isl_schedule_tree);
+ if (!tree)
+ return NULL;
+
+ tree->ref = 1;
+ tree->ctx = ctx;
+ isl_ctx_ref(ctx);
+ tree->type = type;
+
+ return tree;
+}
+
+/* Return a fresh copy of "tree".
+ */
+__isl_take isl_schedule_tree *isl_schedule_tree_dup(
+ __isl_keep isl_schedule_tree *tree)
+{
+ isl_ctx *ctx;
+ isl_schedule_tree *dup;
+
+ if (!tree)
+ return NULL;
+
+ ctx = isl_schedule_tree_get_ctx(tree);
+ dup = isl_schedule_tree_alloc(ctx, tree->type);
+ if (!dup)
+ return NULL;
+
+ switch (tree->type) {
+ case isl_schedule_node_error:
+ isl_die(ctx, isl_error_internal,
+ "allocation should have failed",
+ isl_schedule_tree_free(dup));
+ case isl_schedule_node_band:
+ dup->band = isl_schedule_band_copy(tree->band);
+ if (!dup->band)
+ return isl_schedule_tree_free(dup);
+ break;
+ case isl_schedule_node_domain:
+ dup->domain = isl_union_set_copy(tree->domain);
+ if (!dup->domain)
+ return isl_schedule_tree_free(dup);
+ break;
+ case isl_schedule_node_filter:
+ dup->filter = isl_union_set_copy(tree->filter);
+ if (!dup->filter)
+ return isl_schedule_tree_free(dup);
+ break;
+ case isl_schedule_node_leaf:
+ case isl_schedule_node_sequence:
+ case isl_schedule_node_set:
+ break;
+ }
+
+ if (tree->children) {
+ dup->children = isl_schedule_tree_list_copy(tree->children);
+ if (!dup->children)
+ return isl_schedule_tree_free(dup);
+ }
+
+ return dup;
+}
+
+/* Return an isl_schedule_tree that is equal to "tree" and that has only
+ * a single reference.
+ *
+ * This function is called before a tree is modified.
+ * A static tree (with negative reference count) should never be modified,
+ * so it is not allowed to call this function on a static tree.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_cow(
+ __isl_take isl_schedule_tree *tree)
+{
+ if (!tree)
+ return NULL;
+
+ if (tree->ref < 0)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
+ "static trees cannot be modified",
+ return isl_schedule_tree_free(tree));
+
+ if (tree->ref == 1)
+ return tree;
+ tree->ref--;
+ return isl_schedule_tree_dup(tree);
+}
+
+/* Return a new reference to "tree".
+ *
+ * A static tree (with negative reference count) does not keep track
+ * of the number of references and should not be modified.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_copy(
+ __isl_keep isl_schedule_tree *tree)
+{
+ if (!tree)
+ return NULL;
+
+ if (tree->ref < 0)
+ return tree;
+
+ tree->ref++;
+ return tree;
+}
+
+/* Free "tree" and return NULL.
+ */
+__isl_null isl_schedule_tree *isl_schedule_tree_free(
+ __isl_take isl_schedule_tree *tree)
+{
+ if (!tree)
+ return NULL;
+ if (tree->ref < 0)
+ return NULL;
+ if (--tree->ref > 0)
+ return NULL;
+
+ switch (tree->type) {
+ case isl_schedule_node_band:
+ isl_schedule_band_free(tree->band);
+ break;
+ case isl_schedule_node_domain:
+ isl_union_set_free(tree->domain);
+ break;
+ case isl_schedule_node_filter:
+ isl_union_set_free(tree->filter);
+ break;
+ case isl_schedule_node_sequence:
+ case isl_schedule_node_set:
+ case isl_schedule_node_error:
+ case isl_schedule_node_leaf:
+ break;
+ }
+ isl_schedule_tree_list_free(tree->children);
+ isl_ctx_deref(tree->ctx);
+ free(tree);
+
+ return NULL;
+}
+
+/* Create and return a new leaf schedule tree.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_leaf(isl_ctx *ctx)
+{
+ return isl_schedule_tree_alloc(ctx, isl_schedule_node_leaf);
+}
+
+/* Create a new band schedule tree referring to "band"
+ * with no children.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_from_band(
+ __isl_take isl_schedule_band *band)
+{
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+
+ if (!band)
+ return NULL;
+
+ ctx = isl_schedule_band_get_ctx(band);
+ tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_band);
+ if (!tree)
+ goto error;
+
+ tree->band = band;
+
+ return tree;
+error:
+ isl_schedule_band_free(band);
+ return NULL;
+}
+
+/* Create a new domain schedule tree with the given domain and no children.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_from_domain(
+ __isl_take isl_union_set *domain)
+{
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+
+ if (!domain)
+ return NULL;
+
+ ctx = isl_union_set_get_ctx(domain);
+ tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_domain);
+ if (!tree)
+ goto error;
+
+ tree->domain = domain;
+
+ return tree;
+error:
+ isl_union_set_free(domain);
+ return NULL;
+}
+
+/* Create a new filter schedule tree with the given filter and no children.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_from_filter(
+ __isl_take isl_union_set *filter)
+{
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+
+ if (!filter)
+ return NULL;
+
+ ctx = isl_union_set_get_ctx(filter);
+ tree = isl_schedule_tree_alloc(ctx, isl_schedule_node_filter);
+ if (!tree)
+ goto error;
+
+ tree->filter = filter;
+
+ return tree;
+error:
+ isl_union_set_free(filter);
+ return NULL;
+}
+
+/* Create a new tree of the given type (isl_schedule_node_sequence or
+ * isl_schedule_node_set) with the given children.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_from_children(
+ enum isl_schedule_node_type type,
+ __isl_take isl_schedule_tree_list *list)
+{
+ isl_ctx *ctx;
+ isl_schedule_tree *tree;
+
+ if (!list)
+ return NULL;
+
+ ctx = isl_schedule_tree_list_get_ctx(list);
+ tree = isl_schedule_tree_alloc(ctx, type);
+ if (!tree)
+ goto error;
+
+ tree->children = list;
+
+ return tree;
+error:
+ isl_schedule_tree_list_free(list);
+ return NULL;
+}
+
+/* Return the isl_ctx to which "tree" belongs.
+ */
+isl_ctx *isl_schedule_tree_get_ctx(__isl_keep isl_schedule_tree *tree)
+{
+ return tree ? tree->ctx : NULL;
+}
+
+/* Return the type of the root of the tree or isl_schedule_node_error
+ * on error.
+ */
+enum isl_schedule_node_type isl_schedule_tree_get_type(
+ __isl_keep isl_schedule_tree *tree)
+{
+ return tree ? tree->type : isl_schedule_node_error;
+}
+
+/* Does "tree" have any children, other than an implicit leaf.
+ */
+int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree *tree)
+{
+ if (!tree)
+ return -1;
+
+ return tree->children != NULL;
+}
+
+/* Return the number of children of "tree", excluding implicit leaves.
+ */
+int isl_schedule_tree_n_children(__isl_keep isl_schedule_tree *tree)
+{
+ if (!tree)
+ return -1;
+
+ return isl_schedule_tree_list_n_schedule_tree(tree->children);
+}
+
+/* Return a copy of the (explicit) child at position "pos" of "tree".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_get_child(
+ __isl_keep isl_schedule_tree *tree, int pos)
+{
+ if (!tree)
+ return NULL;
+ if (!tree->children)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
+ "schedule tree has no explicit children", return NULL);
+ return isl_schedule_tree_list_get_schedule_tree(tree->children, pos);
+}
+
+/* Return a copy of the (explicit) child at position "pos" of "tree" and
+ * free "tree".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_child(
+ __isl_take isl_schedule_tree *tree, int pos)
+{
+ isl_schedule_tree *child;
+
+ child = isl_schedule_tree_get_child(tree, pos);
+ isl_schedule_tree_free(tree);
+ return child;
+}
+
+/* Remove all (explicit) children from "tree".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_reset_children(
+ __isl_take isl_schedule_tree *tree)
+{
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree)
+ return NULL;
+ tree->children = isl_schedule_tree_list_free(tree->children);
+ return tree;
+}
+
+/* Replace the child at position "pos" of "tree" by "child".
+ *
+ * If the new child is a leaf, then it is not explicitly
+ * recorded in the list of children. Instead, the list of children
+ * (which is assumed to have only one element) is removed.
+ * Note that the children of set and sequence nodes are always
+ * filters, so they cannot be replaced by empty trees.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_replace_child(
+ __isl_take isl_schedule_tree *tree, int pos,
+ __isl_take isl_schedule_tree *child)
+{
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree || !child)
+ goto error;
+
+ if (isl_schedule_tree_is_leaf(child)) {
+ isl_schedule_tree_free(child);
+ if (!tree->children && pos == 0)
+ return tree;
+ if (isl_schedule_tree_n_children(tree) != 1)
+ isl_die(isl_schedule_tree_get_ctx(tree),
+ isl_error_internal,
+ "can only replace single child by leaf",
+ goto error);
+ return isl_schedule_tree_reset_children(tree);
+ }
+
+ if (!tree->children && pos == 0)
+ tree->children =
+ isl_schedule_tree_list_from_schedule_tree(child);
+ else
+ tree->children = isl_schedule_tree_list_set_schedule_tree(
+ tree->children, pos, child);
+
+ if (!tree->children)
+ return isl_schedule_tree_free(tree);
+
+ return tree;
+error:
+ isl_schedule_tree_free(tree);
+ isl_schedule_tree_free(child);
+ return NULL;
+}
+
+/* Replace the (explicit) children of "tree" by "children"?
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_set_children(
+ __isl_take isl_schedule_tree *tree,
+ __isl_take isl_schedule_tree_list *children)
+{
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree || !children)
+ goto error;
+ isl_schedule_tree_list_free(tree->children);
+ tree->children = children;
+ return tree;
+error:
+ isl_schedule_tree_free(tree);
+ isl_schedule_tree_list_free(children);
+ return NULL;
+}
+
+/* Create a new band schedule tree referring to "band"
+ * with "tree" as single child.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_insert_band(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_schedule_band *band)
+{
+ isl_schedule_tree *res;
+
+ res = isl_schedule_tree_from_band(band);
+ return isl_schedule_tree_replace_child(res, 0, tree);
+}
+
+/* Create a new domain schedule tree with the given domain and
+ * with "tree" as single child.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_insert_domain(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain)
+{
+ isl_schedule_tree *res;
+
+ res = isl_schedule_tree_from_domain(domain);
+ return isl_schedule_tree_replace_child(res, 0, tree);
+}
+
+/* Create a new filter schedule tree with the given filter and single child.
+ *
+ * If the root of "tree" is itself a filter node, then the two
+ * filter nodes are merged into one node.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_insert_filter(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
+{
+ isl_schedule_tree *res;
+
+ if (isl_schedule_tree_get_type(tree) == isl_schedule_node_filter) {
+ isl_union_set *tree_filter;
+
+ tree_filter = isl_schedule_tree_filter_get_filter(tree);
+ tree_filter = isl_union_set_intersect(tree_filter, filter);
+ tree = isl_schedule_tree_filter_set_filter(tree, tree_filter);
+ return tree;
+ }
+
+ res = isl_schedule_tree_from_filter(filter);
+ return isl_schedule_tree_replace_child(res, 0, tree);
+}
+
+/* Return the number of members in the band tree root.
+ */
+unsigned isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree *tree)
+{
+ if (!tree)
+ return 0;
+
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", return 0);
+
+ return isl_schedule_band_n_member(tree->band);
+}
+
+/* Is the band member at position "pos" of the band tree root
+ * marked coincident?
+ */
+int isl_schedule_tree_band_member_get_coincident(
+ __isl_keep isl_schedule_tree *tree, int pos)
+{
+ if (!tree)
+ return -1;
+
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", return -1);
+
+ return isl_schedule_band_member_get_coincident(tree->band, pos);
+}
+
+/* Mark the given band member as being coincident or not
+ * according to "coincident".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_band_member_set_coincident(
+ __isl_take isl_schedule_tree *tree, int pos, int coincident)
+{
+ if (!tree)
+ return NULL;
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", return isl_schedule_tree_free(tree));
+ if (isl_schedule_tree_band_member_get_coincident(tree, pos) ==
+ coincident)
+ return tree;
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree)
+ return NULL;
+
+ tree->band = isl_schedule_band_member_set_coincident(tree->band, pos,
+ coincident);
+ if (!tree->band)
+ return isl_schedule_tree_free(tree);
+ return tree;
+}
+
+/* Is the band tree root marked permutable?
+ */
+int isl_schedule_tree_band_get_permutable(__isl_keep isl_schedule_tree *tree)
+{
+ if (!tree)
+ return -1;
+
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", return -1);
+
+ return isl_schedule_band_get_permutable(tree->band);
+}
+
+/* Mark the band tree root permutable or not according to "permutable"?
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_band_set_permutable(
+ __isl_take isl_schedule_tree *tree, int permutable)
+{
+ if (!tree)
+ return NULL;
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", return isl_schedule_tree_free(tree));
+ if (isl_schedule_tree_band_get_permutable(tree) == permutable)
+ return tree;
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree)
+ return NULL;
+
+ tree->band = isl_schedule_band_set_permutable(tree->band, permutable);
+ if (!tree->band)
+ return isl_schedule_tree_free(tree);
+ return tree;
+}
+
+/* Return the schedule space of the band tree root.
+ */
+__isl_give isl_space *isl_schedule_tree_band_get_space(
+ __isl_keep isl_schedule_tree *tree)
+{
+ if (!tree)
+ return NULL;
+
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", return NULL);
+
+ return isl_schedule_band_get_space(tree->band);
+}
+
+/* Return the schedule of the band tree root in isolation.
+ */
+__isl_give isl_multi_union_pw_aff *isl_schedule_tree_band_get_partial_schedule(
+ __isl_keep isl_schedule_tree *tree)
+{
+ if (!tree)
+ return NULL;
+
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", return NULL);
+
+ return isl_schedule_band_get_partial_schedule(tree->band);
+}
+
+/* Return the domain of the domain tree root.
+ */
+__isl_give isl_union_set *isl_schedule_tree_domain_get_domain(
+ __isl_keep isl_schedule_tree *tree)
+{
+ if (!tree)
+ return NULL;
+
+ if (tree->type != isl_schedule_node_domain)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a domain node", return NULL);
+
+ return isl_union_set_copy(tree->domain);
+}
+
+/* Replace the domain of domain tree root "tree" by "domain".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_domain_set_domain(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain)
+{
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree || !domain)
+ goto error;
+
+ if (tree->type != isl_schedule_node_domain)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a domain node", goto error);
+
+ isl_union_set_free(tree->domain);
+ tree->domain = domain;
+
+ return tree;
+error:
+ isl_schedule_tree_free(tree);
+ isl_union_set_free(domain);
+ return NULL;
+}
+
+/* Return the filter of the filter tree root.
+ */
+__isl_give isl_union_set *isl_schedule_tree_filter_get_filter(
+ __isl_keep isl_schedule_tree *tree)
+{
+ if (!tree)
+ return NULL;
+
+ if (tree->type != isl_schedule_node_filter)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a filter node", return NULL);
+
+ return isl_union_set_copy(tree->filter);
+}
+
+/* Replace the filter of the filter tree root by "filter".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_filter_set_filter(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter)
+{
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree || !filter)
+ goto error;
+
+ if (tree->type != isl_schedule_node_filter)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a filter node", return NULL);
+
+ isl_union_set_free(tree->filter);
+ tree->filter = filter;
+
+ return tree;
+error:
+ isl_schedule_tree_free(tree);
+ isl_union_set_free(filter);
+ return NULL;
+}
+
+/* Set dim to the range dimension of "map" and abort the search.
+ */
+static int set_range_dim(__isl_take isl_map *map, void *user)
+{
+ int *dim = user;
+
+ *dim = isl_map_dim(map, isl_dim_out);
+ isl_map_free(map);
+
+ return -1;
+}
+
+/* Return the dimension of the range of "umap".
+ * "umap" is assumed not to be empty and
+ * all maps inside "umap" are assumed to have the same range.
+ *
+ * We extract the range dimension from the first map in "umap".
+ */
+static int range_dim(__isl_keep isl_union_map *umap)
+{
+ int dim = -1;
+
+ if (!umap)
+ return -1;
+ if (isl_union_map_n_map(umap) == 0)
+ isl_die(isl_union_map_get_ctx(umap), isl_error_internal,
+ "unexpected empty input", return -1);
+
+ isl_union_map_foreach_map(umap, &set_range_dim, &dim);
+
+ return dim;
+}
+
+/* Append an "extra" number of zeros to the range of "umap" and
+ * return the result.
+ */
+static __isl_give isl_union_map *append_range(__isl_take isl_union_map *umap,
+ int extra)
+{
+ isl_union_set *dom;
+ isl_space *space;
+ isl_multi_val *mv;
+ isl_union_pw_multi_aff *suffix;
+ isl_union_map *universe;
+ isl_union_map *suffix_umap;
+
+ universe = isl_union_map_universe(isl_union_map_copy(umap));
+ dom = isl_union_map_domain(universe);
+ space = isl_union_set_get_space(dom);
+ space = isl_space_set_from_params(space);
+ space = isl_space_add_dims(space, isl_dim_set, extra);
+ mv = isl_multi_val_zero(space);
+
+ suffix = isl_union_pw_multi_aff_multi_val_on_domain(dom, mv);
+ suffix_umap = isl_union_map_from_union_pw_multi_aff(suffix);
+ umap = isl_union_map_flat_range_product(umap, suffix_umap);
+
+ return umap;
+}
+
+/* Move down to the first descendant of "tree" that contains any schedule
+ * information or return "leaf" if there is no such descendant.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_first_schedule_descendant(
+ __isl_take isl_schedule_tree *tree, __isl_keep isl_schedule_tree *leaf)
+{
+ while (isl_schedule_tree_get_type(tree) == isl_schedule_node_band &&
+ isl_schedule_tree_band_n_member(tree) == 0) {
+ if (!isl_schedule_tree_has_children(tree)) {
+ isl_schedule_tree_free(tree);
+ return isl_schedule_tree_copy(leaf);
+ }
+ tree = isl_schedule_tree_child(tree, 0);
+ }
+
+ return tree;
+}
+
+static __isl_give isl_union_map *subtree_schedule_extend(
+ __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer);
+
+/* Extend the schedule map "outer" with the subtree schedule
+ * of the (single) child of "tree", if any.
+ *
+ * If "tree" does not have any descendants (apart from those that
+ * do not carry any schedule information), then we simply return "outer".
+ * Otherwise, we extend the schedule map "outer" with the subtree schedule
+ * of the single child.
+ */
+static __isl_give isl_union_map *subtree_schedule_extend_child(
+ __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
+{
+ isl_schedule_tree *child;
+ isl_union_map *res;
+
+ if (!tree)
+ return isl_union_map_free(outer);
+ if (!isl_schedule_tree_has_children(tree))
+ return outer;
+ child = isl_schedule_tree_get_child(tree, 0);
+ if (!child)
+ return isl_union_map_free(outer);
+ res = subtree_schedule_extend(child, outer);
+ isl_schedule_tree_free(child);
+ return res;
+}
+
+/* Extract the parameter space from one of the children of "tree",
+ * which are assumed to be filters.
+ */
+static __isl_give isl_space *extract_space_from_filter_child(
+ __isl_keep isl_schedule_tree *tree)
+{
+ isl_space *space;
+ isl_union_set *dom;
+ isl_schedule_tree *child;
+
+ child = isl_schedule_tree_list_get_schedule_tree(tree->children, 0);
+ dom = isl_schedule_tree_filter_get_filter(child);
+ space = isl_union_set_get_space(dom);
+ isl_union_set_free(dom);
+ isl_schedule_tree_free(child);
+
+ return space;
+}
+
+/* Extend the schedule map "outer" with the subtree schedule
+ * of a set or sequence node.
+ *
+ * The schedule for the set or sequence node itself is composed of
+ * pieces of the form
+ *
+ * filter -> []
+ *
+ * or
+ *
+ * filter -> [index]
+ *
+ * The first form is used if there is only a single child or
+ * if the current node is a set node and the schedule_separate_components
+ * option is not set.
+ *
+ * Each of the pieces above is extended with the subtree schedule of
+ * the child of the corresponding filter, if any, padded with zeros
+ * to ensure that all pieces have the same range dimension.
+ */
+static __isl_give isl_union_map *subtree_schedule_extend_from_children(
+ __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
+{
+ int i, n;
+ int dim;
+ int separate;
+ isl_ctx *ctx;
+ isl_val *v = NULL;
+ isl_multi_val *mv;
+ isl_space *space;
+ isl_union_map *umap;
+
+ if (!tree)
+ return NULL;
+
+ ctx = isl_schedule_tree_get_ctx(tree);
+ if (!tree->children)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
+ "missing children", return NULL);
+ n = isl_schedule_tree_list_n_schedule_tree(tree->children);
+ if (n == 0)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
+ "missing children", return NULL);
+
+ separate = n > 1 && (tree->type == isl_schedule_node_sequence ||
+ isl_options_get_schedule_separate_components(ctx));
+
+ space = extract_space_from_filter_child(tree);
+
+ umap = isl_union_map_empty(isl_space_copy(space));
+ space = isl_space_set_from_params(space);
+ if (separate) {
+ space = isl_space_add_dims(space, isl_dim_set, 1);
+ v = isl_val_zero(ctx);
+ }
+ mv = isl_multi_val_zero(space);
+
+ dim = isl_multi_val_dim(mv, isl_dim_set);
+ for (i = 0; i < n; ++i) {
+ isl_union_pw_multi_aff *upma;
+ isl_union_map *umap_i;
+ isl_union_set *dom;
+ isl_schedule_tree *child;
+ int dim_i;
+ int empty;
+
+ child = isl_schedule_tree_list_get_schedule_tree(
+ tree->children, i);
+ dom = isl_schedule_tree_filter_get_filter(child);
+
+ if (separate) {
+ mv = isl_multi_val_set_val(mv, 0, isl_val_copy(v));
+ v = isl_val_add_ui(v, 1);
+ }
+ upma = isl_union_pw_multi_aff_multi_val_on_domain(dom,
+ isl_multi_val_copy(mv));
+ umap_i = isl_union_map_from_union_pw_multi_aff(upma);
+ umap_i = isl_union_map_flat_range_product(
+ isl_union_map_copy(outer), umap_i);
+ umap_i = subtree_schedule_extend_child(child, umap_i);
+ isl_schedule_tree_free(child);
+
+ empty = isl_union_map_is_empty(umap_i);
+ if (empty < 0)
+ umap_i = isl_union_map_free(umap_i);
+ else if (empty) {
+ isl_union_map_free(umap_i);
+ continue;
+ }
+
+ dim_i = range_dim(umap_i);
+ if (dim_i < 0) {
+ umap = isl_union_map_free(umap);
+ } else if (dim < dim_i) {
+ umap = append_range(umap, dim_i - dim);
+ dim = dim_i;
+ } else if (dim_i < dim) {
+ umap_i = append_range(umap_i, dim - dim_i);
+ }
+ umap = isl_union_map_union(umap, umap_i);
+ }
+
+ isl_val_free(v);
+ isl_multi_val_free(mv);
+ isl_union_map_free(outer);
+
+ return umap;
+}
+
+/* Extend the schedule map "outer" with the subtree schedule of "tree".
+ *
+ * If the root of the tree is a set or a sequence, then we extend
+ * the schedule map in subtree_schedule_extend_from_children.
+ * Otherwise, we extend the schedule map with the partial schedule
+ * corresponding to the root of the tree and then continue with
+ * the single child of this root.
+ */
+static __isl_give isl_union_map *subtree_schedule_extend(
+ __isl_keep isl_schedule_tree *tree, __isl_take isl_union_map *outer)
+{
+ isl_multi_union_pw_aff *mupa;
+ isl_union_map *umap;
+ isl_union_set *domain;
+
+ if (!tree)
+ return NULL;
+
+ switch (tree->type) {
+ case isl_schedule_node_error:
+ return isl_union_map_free(outer);
+ case isl_schedule_node_band:
+ if (isl_schedule_tree_band_n_member(tree) == 0)
+ return subtree_schedule_extend_child(tree, outer);
+ mupa = isl_schedule_band_get_partial_schedule(tree->band);
+ umap = isl_union_map_from_multi_union_pw_aff(mupa);
+ outer = isl_union_map_flat_range_product(outer, umap);
+ umap = subtree_schedule_extend_child(tree, outer);
+ break;
+ case isl_schedule_node_domain:
+ domain = isl_schedule_tree_domain_get_domain(tree);
+ umap = isl_union_map_from_domain(domain);
+ outer = isl_union_map_flat_range_product(outer, umap);
+ umap = subtree_schedule_extend_child(tree, outer);
+ break;
+ case isl_schedule_node_filter:
+ domain = isl_schedule_tree_filter_get_filter(tree);
+ umap = isl_union_map_from_domain(domain);
+ outer = isl_union_map_flat_range_product(outer, umap);
+ umap = subtree_schedule_extend_child(tree, outer);
+ break;
+ case isl_schedule_node_leaf:
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
+ "leaf node should be handled by caller", return NULL);
+ case isl_schedule_node_set:
+ case isl_schedule_node_sequence:
+ umap = subtree_schedule_extend_from_children(tree, outer);
+ break;
+ }
+
+ return umap;
+}
+
+static __isl_give isl_union_set *initial_domain(
+ __isl_keep isl_schedule_tree *tree);
+
+/* Extract a universe domain from the children of the tree root "tree",
+ * which is a set or sequence, meaning that its children are filters.
+ * In particular, return the union of the universes of the filters.
+ */
+static __isl_give isl_union_set *initial_domain_from_children(
+ __isl_keep isl_schedule_tree *tree)
+{
+ int i, n;
+ isl_space *space;
+ isl_union_set *domain;
+
+ if (!tree->children)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
+ "missing children", return NULL);
+ n = isl_schedule_tree_list_n_schedule_tree(tree->children);
+ if (n == 0)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
+ "missing children", return NULL);
+
+ space = extract_space_from_filter_child(tree);
+ domain = isl_union_set_empty(space);
+
+ for (i = 0; i < n; ++i) {
+ isl_schedule_tree *child;
+ isl_union_set *domain_i;
+
+ child = isl_schedule_tree_get_child(tree, i);
+ domain_i = initial_domain(child);
+ domain = isl_union_set_union(domain, domain_i);
+ isl_schedule_tree_free(child);
+ }
+
+ return domain;
+}
+
+/* Extract a universe domain from the tree root "tree".
+ * The caller is responsible for making sure that this node
+ * would not be skipped by isl_schedule_tree_first_schedule_descendant
+ * and that it is not a leaf node.
+ */
+static __isl_give isl_union_set *initial_domain(
+ __isl_keep isl_schedule_tree *tree)
+{
+ isl_multi_union_pw_aff *mupa;
+ isl_union_set *domain;
+
+ if (!tree)
+ return NULL;
+
+ switch (tree->type) {
+ case isl_schedule_node_error:
+ return NULL;
+ case isl_schedule_node_band:
+ if (isl_schedule_tree_band_n_member(tree) == 0)
+ isl_die(isl_schedule_tree_get_ctx(tree),
+ isl_error_internal,
+ "0D band should be handled by caller",
+ return NULL);
+ mupa = isl_schedule_band_get_partial_schedule(tree->band);
+ domain = isl_multi_union_pw_aff_domain(mupa);
+ domain = isl_union_set_universe(domain);
+ break;
+ case isl_schedule_node_domain:
+ domain = isl_schedule_tree_domain_get_domain(tree);
+ domain = isl_union_set_universe(domain);
+ break;
+ case isl_schedule_node_filter:
+ domain = isl_schedule_tree_filter_get_filter(tree);
+ domain = isl_union_set_universe(domain);
+ break;
+ case isl_schedule_node_leaf:
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_internal,
+ "leaf node should be handled by caller", return NULL);
+ case isl_schedule_node_set:
+ case isl_schedule_node_sequence:
+ domain = initial_domain_from_children(tree);
+ break;
+ }
+
+ return domain;
+}
+
+/* Return the subtree schedule of a node that contains some schedule
+ * information, i.e., a node that would not be skipped by
+ * isl_schedule_tree_first_schedule_descendant and that is not a leaf.
+ *
+ * We start with an initial zero-dimensional subtree schedule based
+ * on the domain information in the root node and then extend it
+ * based on the schedule information in the root node and its descendants.
+ */
+__isl_give isl_union_map *isl_schedule_tree_get_subtree_schedule_union_map(
+ __isl_keep isl_schedule_tree *tree)
+{
+ isl_union_set *domain;
+ isl_union_map *umap;
+
+ domain = initial_domain(tree);
+ umap = isl_union_map_from_domain(domain);
+ return subtree_schedule_extend(tree, umap);
+}
+
+/* Multiply the partial schedule of the band root node of "tree"
+ * with the factors in "mv".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_band_scale(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
+{
+ if (!tree || !mv)
+ goto error;
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", goto error);
+
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree)
+ goto error;
+
+ tree->band = isl_schedule_band_scale(tree->band, mv);
+ if (!tree->band)
+ return isl_schedule_tree_free(tree);
+
+ return tree;
+error:
+ isl_schedule_tree_free(tree);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Divide the partial schedule of the band root node of "tree"
+ * by the factors in "mv".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_band_scale_down(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv)
+{
+ if (!tree || !mv)
+ goto error;
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", goto error);
+
+ tree = isl_schedule_tree_cow(tree);
+ if (!tree)
+ goto error;
+
+ tree->band = isl_schedule_band_scale_down(tree->band, mv);
+ if (!tree->band)
+ return isl_schedule_tree_free(tree);
+
+ return tree;
+error:
+ isl_schedule_tree_free(tree);
+ isl_multi_val_free(mv);
+ return NULL;
+}
+
+/* Tile the band root node of "tree" with tile sizes "sizes".
+ *
+ * We duplicate the band node, change the schedule of one of them
+ * to the tile schedule and the other to the point schedule and then
+ * attach the point band as a child to the tile band.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_band_tile(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *sizes)
+{
+ isl_schedule_tree *child = NULL;
+
+ if (!tree || !sizes)
+ goto error;
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", goto error);
+
+ child = isl_schedule_tree_copy(tree);
+ tree = isl_schedule_tree_cow(tree);
+ child = isl_schedule_tree_cow(child);
+ if (!tree || !child)
+ goto error;
+
+ tree->band = isl_schedule_band_tile(tree->band,
+ isl_multi_val_copy(sizes));
+ if (!tree->band)
+ goto error;
+ child->band = isl_schedule_band_point(child->band, tree->band, sizes);
+ if (!child->band)
+ child = isl_schedule_tree_free(child);
+
+ tree = isl_schedule_tree_replace_child(tree, 0, child);
+
+ return tree;
+error:
+ isl_schedule_tree_free(child);
+ isl_schedule_tree_free(tree);
+ isl_multi_val_free(sizes);
+ return NULL;
+}
+
+/* Split the band root node of "tree" into two nested band nodes,
+ * one with the first "pos" dimensions and
+ * one with the remaining dimensions.
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_band_split(
+ __isl_take isl_schedule_tree *tree, int pos)
+{
+ int n;
+ isl_schedule_tree *child;
+
+ if (!tree)
+ return NULL;
+ if (tree->type != isl_schedule_node_band)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "not a band node", return isl_schedule_tree_free(tree));
+
+ n = isl_schedule_tree_band_n_member(tree);
+ if (pos < 0 || pos > n)
+ isl_die(isl_schedule_tree_get_ctx(tree), isl_error_invalid,
+ "position out of bounds",
+ return isl_schedule_tree_free(tree));
+
+ child = isl_schedule_tree_copy(tree);
+ tree = isl_schedule_tree_cow(tree);
+ child = isl_schedule_tree_cow(child);
+ if (!tree || !child)
+ goto error;
+
+ child->band = isl_schedule_band_drop(child->band, 0, pos);
+ tree->band = isl_schedule_band_drop(tree->band, pos, n - pos);
+ if (!child->band || !tree->band)
+ goto error;
+
+ tree = isl_schedule_tree_replace_child(tree, 0, child);
+
+ return tree;
+error:
+ isl_schedule_tree_free(child);
+ isl_schedule_tree_free(tree);
+ return NULL;
+}
+
+/* Attach "tree2" at each of the leaves of "tree1".
+ *
+ * If "tree1" does not have any explicit children, then make "tree2"
+ * its single child. Otherwise, attach "tree2" to the leaves of
+ * each of the children of "tree1".
+ */
+__isl_give isl_schedule_tree *isl_schedule_tree_append_to_leaves(
+ __isl_take isl_schedule_tree *tree1,
+ __isl_take isl_schedule_tree *tree2)
+{
+ int i, n;
+
+ if (!tree1 || !tree2)
+ goto error;
+ n = isl_schedule_tree_n_children(tree1);
+ if (n == 0) {
+ isl_schedule_tree_list *list;
+ list = isl_schedule_tree_list_from_schedule_tree(tree2);
+ tree1 = isl_schedule_tree_set_children(tree1, list);
+ return tree1;
+ }
+ for (i = 0; i < n; ++i) {
+ isl_schedule_tree *child;
+
+ child = isl_schedule_tree_get_child(tree1, i);
+ child = isl_schedule_tree_append_to_leaves(child,
+ isl_schedule_tree_copy(tree2));
+ tree1 = isl_schedule_tree_replace_child(tree1, i, child);
+ }
+
+ isl_schedule_tree_free(tree2);
+ return tree1;
+error:
+ isl_schedule_tree_free(tree1);
+ isl_schedule_tree_free(tree2);
+ return NULL;
+}
+
+/* Are any members in "band" marked coincident?
+ */
+static int any_coincident(__isl_keep isl_schedule_band *band)
+{
+ int i, n;
+
+ n = isl_schedule_band_n_member(band);
+ for (i = 0; i < n; ++i)
+ if (isl_schedule_band_member_get_coincident(band, i))
+ return 1;
+
+ return 0;
+}
+
+/* Print the band node "band" to "p".
+ *
+ * The permutable and coincident properties are only printed if they
+ * are different from the defaults.
+ * The coincident property is always printed in YAML flow style.
+ */
+static __isl_give isl_printer *print_tree_band(__isl_take isl_printer *p,
+ __isl_keep isl_schedule_band *band)
+{
+ p = isl_printer_print_str(p, "schedule");
+ p = isl_printer_yaml_next(p);
+ p = isl_printer_print_str(p, "\"");
+ p = isl_printer_print_multi_union_pw_aff(p, band->mupa);
+ p = isl_printer_print_str(p, "\"");
+ if (isl_schedule_band_get_permutable(band)) {
+ p = isl_printer_yaml_next(p);
+ p = isl_printer_print_str(p, "permutable");
+ p = isl_printer_yaml_next(p);
+ p = isl_printer_print_int(p, 1);
+ }
+ if (any_coincident(band)) {
+ int i, n;
+ int style;
+
+ p = isl_printer_yaml_next(p);
+ p = isl_printer_print_str(p, "coincident");
+ p = isl_printer_yaml_next(p);
+ style = isl_printer_get_yaml_style(p);
+ p = isl_printer_set_yaml_style(p, ISL_YAML_STYLE_FLOW);
+ p = isl_printer_yaml_start_sequence(p);
+ n = isl_schedule_band_n_member(band);
+ for (i = 0; i < n; ++i) {
+ p = isl_printer_print_int(p,
+ isl_schedule_band_member_get_coincident(band, i));
+ p = isl_printer_yaml_next(p);
+ }
+ p = isl_printer_yaml_end_sequence(p);
+ p = isl_printer_set_yaml_style(p, style);
+ }
+
+ return p;
+}
+
+/* Print "tree" to "p".
+ *
+ * If "n_ancestor" is non-negative, then "child_pos" contains the child
+ * positions of a descendant of the current node that should be marked
+ * (by the comment "YOU ARE HERE"). In particular, if "n_ancestor"
+ * is zero, then the current node should be marked.
+ * The marking is only printed in YAML block format.
+ *
+ * Implicit leaf nodes are not printed, except if they correspond
+ * to the node that should be marked.
+ */
+__isl_give isl_printer *isl_printer_print_schedule_tree_mark(
+ __isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree,
+ int n_ancestor, int *child_pos)
+{
+ int i, n;
+ int sequence = 0;
+ int block;
+
+ block = isl_printer_get_yaml_style(p) == ISL_YAML_STYLE_BLOCK;
+
+ p = isl_printer_yaml_start_mapping(p);
+ if (n_ancestor == 0 && block) {
+ p = isl_printer_print_str(p, "# YOU ARE HERE");
+ p = isl_printer_end_line(p);
+ p = isl_printer_start_line(p);
+ }
+ switch (tree->type) {
+ case isl_schedule_node_error:
+ p = isl_printer_print_str(p, "ERROR");
+ break;
+ case isl_schedule_node_leaf:
+ p = isl_printer_print_str(p, "leaf");
+ break;
+ case isl_schedule_node_sequence:
+ p = isl_printer_print_str(p, "sequence");
+ sequence = 1;
+ break;
+ case isl_schedule_node_set:
+ p = isl_printer_print_str(p, "set");
+ sequence = 1;
+ break;
+ case isl_schedule_node_domain:
+ p = isl_printer_print_str(p, "domain");
+ p = isl_printer_yaml_next(p);
+ p = isl_printer_print_str(p, "\"");
+ p = isl_printer_print_union_set(p, tree->domain);
+ p = isl_printer_print_str(p, "\"");
+ break;
+ case isl_schedule_node_filter:
+ p = isl_printer_print_str(p, "filter");
+ p = isl_printer_yaml_next(p);
+ p = isl_printer_print_str(p, "\"");
+ p = isl_printer_print_union_set(p, tree->filter);
+ p = isl_printer_print_str(p, "\"");
+ break;
+ case isl_schedule_node_band:
+ p = print_tree_band(p, tree->band);
+ break;
+ }
+ p = isl_printer_yaml_next(p);
+
+ if (!tree->children) {
+ if (n_ancestor > 0 && block) {
+ isl_schedule_tree *leaf;
+
+ p = isl_printer_print_str(p, "child");
+ p = isl_printer_yaml_next(p);
+ leaf = isl_schedule_tree_leaf(isl_printer_get_ctx(p));
+ p = isl_printer_print_schedule_tree_mark(p,
+ leaf, 0, NULL);
+ isl_schedule_tree_free(leaf);
+ p = isl_printer_yaml_next(p);
+ }
+ return isl_printer_yaml_end_mapping(p);
+ }
+
+ if (sequence) {
+ p = isl_printer_yaml_start_sequence(p);
+ } else {
+ p = isl_printer_print_str(p, "child");
+ p = isl_printer_yaml_next(p);
+ }
+
+ n = isl_schedule_tree_list_n_schedule_tree(tree->children);
+ for (i = 0; i < n; ++i) {
+ isl_schedule_tree *t;
+
+ t = isl_schedule_tree_get_child(tree, i);
+ if (n_ancestor > 0 && child_pos[0] == i)
+ p = isl_printer_print_schedule_tree_mark(p, t,
+ n_ancestor - 1, child_pos + 1);
+ else
+ p = isl_printer_print_schedule_tree_mark(p, t,
+ -1, NULL);
+ isl_schedule_tree_free(t);
+
+ p = isl_printer_yaml_next(p);
+ }
+
+ if (sequence)
+ p = isl_printer_yaml_end_sequence(p);
+ p = isl_printer_yaml_end_mapping(p);
+
+ return p;
+}
+
+/* Print "tree" to "p".
+ */
+__isl_give isl_printer *isl_printer_print_schedule_tree(
+ __isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree)
+{
+ return isl_printer_print_schedule_tree_mark(p, tree, -1, NULL);
+}
+
+void isl_schedule_tree_dump(__isl_keep isl_schedule_tree *tree)
+{
+ isl_ctx *ctx;
+ isl_printer *printer;
+
+ if (!tree)
+ return;
+
+ ctx = isl_schedule_tree_get_ctx(tree);
+ printer = isl_printer_to_file(ctx, stderr);
+ printer = isl_printer_set_yaml_style(printer, ISL_YAML_STYLE_BLOCK);
+ printer = isl_printer_print_schedule_tree(printer, tree);
+
+ isl_printer_free(printer);
+}
Added: polly/trunk/lib/External/isl/isl_schedule_tree.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_schedule_tree.h?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_schedule_tree.h (added)
+++ polly/trunk/lib/External/isl/isl_schedule_tree.h Mon Feb 16 13:33:40 2015
@@ -0,0 +1,134 @@
+#ifndef ISL_SCHEDLUE_TREE_H
+#define ISL_SCHEDLUE_TREE_H
+
+#include <isl_schedule_band.h>
+#include <isl/schedule.h>
+#include <isl/set.h>
+#include <isl/union_set.h>
+
+struct isl_schedule_tree;
+typedef struct isl_schedule_tree isl_schedule_tree;
+
+ISL_DECLARE_LIST(schedule_tree)
+
+/* A schedule (sub)tree.
+ *
+ * The leaves of a tree are not explicitly represented inside
+ * the isl_schedule_tree. If a tree consists of only a leaf,
+ * then it is equal to the static object isl_schedule_tree_empty.
+ *
+ * ctx may be NULL if type is isl_schedule_node_leaf.
+ * In this case, ref has a negative value.
+ *
+ * The "band" field is valid when type is isl_schedule_node_band.
+ * The "domain" field is valid when type is isl_schedule_node_domain
+ * and introduces the statement instances scheduled by the tree.
+ * The "filter" field is valid when type is isl_schedule_node_filter
+ * and represents the statement instances selected by the node.
+ *
+ * The "children" field is valid for all types except
+ * isl_schedule_node_leaf. This field is NULL if there are
+ * no children (except for the implicit leaves).
+ */
+struct isl_schedule_tree {
+ int ref;
+ isl_ctx *ctx;
+ enum isl_schedule_node_type type;
+ union {
+ isl_schedule_band *band;
+ isl_union_set *domain;
+ isl_union_set *filter;
+ };
+ isl_schedule_tree_list *children;
+};
+
+isl_ctx *isl_schedule_tree_get_ctx(__isl_keep isl_schedule_tree *tree);
+enum isl_schedule_node_type isl_schedule_tree_get_type(
+ __isl_keep isl_schedule_tree *tree);
+
+__isl_give isl_schedule_tree *isl_schedule_tree_leaf(isl_ctx *ctx);
+int isl_schedule_tree_is_leaf(__isl_keep isl_schedule_tree *tree);
+
+__isl_give isl_schedule_tree *isl_schedule_tree_copy(
+ __isl_keep isl_schedule_tree *tree);
+__isl_null isl_schedule_tree *isl_schedule_tree_free(
+ __isl_take isl_schedule_tree *tree);
+
+__isl_give isl_schedule_tree *isl_schedule_tree_from_band(
+ __isl_take isl_schedule_band *band);
+__isl_give isl_schedule_tree *isl_schedule_tree_from_domain(
+ __isl_take isl_union_set *domain);
+__isl_give isl_schedule_tree *isl_schedule_tree_from_filter(
+ __isl_take isl_union_set *filter);
+__isl_give isl_schedule_tree *isl_schedule_tree_from_children(
+ enum isl_schedule_node_type type,
+ __isl_take isl_schedule_tree_list *list);
+
+__isl_give isl_space *isl_schedule_tree_band_get_space(
+ __isl_keep isl_schedule_tree *tree);
+__isl_give isl_multi_union_pw_aff *isl_schedule_tree_band_get_partial_schedule(
+ __isl_keep isl_schedule_tree *tree);
+__isl_give isl_union_set *isl_schedule_tree_domain_get_domain(
+ __isl_keep isl_schedule_tree *tree);
+__isl_give isl_schedule_tree *isl_schedule_tree_domain_set_domain(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain);
+__isl_give isl_union_set *isl_schedule_tree_filter_get_filter(
+ __isl_keep isl_schedule_tree *tree);
+__isl_give isl_schedule_tree *isl_schedule_tree_filter_set_filter(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter);
+
+__isl_give isl_schedule_tree *isl_schedule_tree_first_schedule_descendant(
+ __isl_take isl_schedule_tree *tree, __isl_keep isl_schedule_tree *leaf);
+__isl_give isl_union_map *isl_schedule_tree_get_subtree_schedule_union_map(
+ __isl_keep isl_schedule_tree *tree);
+
+unsigned isl_schedule_tree_band_n_member(__isl_keep isl_schedule_tree *tree);
+
+int isl_schedule_tree_band_member_get_coincident(
+ __isl_keep isl_schedule_tree *tree, int pos);
+__isl_give isl_schedule_tree *isl_schedule_tree_band_member_set_coincident(
+ __isl_take isl_schedule_tree *tree, int pos, int coincident);
+int isl_schedule_tree_band_get_permutable(__isl_keep isl_schedule_tree *tree);
+__isl_give isl_schedule_tree *isl_schedule_tree_band_set_permutable(
+ __isl_take isl_schedule_tree *tree, int permutable);
+
+int isl_schedule_tree_has_children(__isl_keep isl_schedule_tree *tree);
+int isl_schedule_tree_n_children(__isl_keep isl_schedule_tree *tree);
+__isl_give isl_schedule_tree *isl_schedule_tree_get_child(
+ __isl_keep isl_schedule_tree *tree, int pos);
+
+__isl_give isl_schedule_tree *isl_schedule_tree_insert_band(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_schedule_band *band);
+__isl_give isl_schedule_tree *isl_schedule_tree_insert_domain(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *domain);
+__isl_give isl_schedule_tree *isl_schedule_tree_insert_filter(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_union_set *filter);
+
+__isl_give isl_schedule_tree *isl_schedule_tree_append_to_leaves(
+ __isl_take isl_schedule_tree *tree1,
+ __isl_take isl_schedule_tree *tree2);
+
+__isl_give isl_schedule_tree *isl_schedule_tree_band_scale(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv);
+__isl_give isl_schedule_tree *isl_schedule_tree_band_scale_down(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *mv);
+__isl_give isl_schedule_tree *isl_schedule_tree_band_tile(
+ __isl_take isl_schedule_tree *tree, __isl_take isl_multi_val *sizes);
+__isl_give isl_schedule_tree *isl_schedule_tree_band_split(
+ __isl_take isl_schedule_tree *tree, int pos);
+
+__isl_give isl_schedule_tree *isl_schedule_tree_child(
+ __isl_take isl_schedule_tree *tree, int pos);
+__isl_give isl_schedule_tree *isl_schedule_tree_reset_children(
+ __isl_take isl_schedule_tree *tree);
+__isl_give isl_schedule_tree *isl_schedule_tree_replace_child(
+ __isl_take isl_schedule_tree *tree, int pos,
+ __isl_take isl_schedule_tree *new_child);
+
+__isl_give isl_printer *isl_printer_print_schedule_tree(
+ __isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree);
+__isl_give isl_printer *isl_printer_print_schedule_tree_mark(
+ __isl_take isl_printer *p, __isl_keep isl_schedule_tree *tree,
+ int n_ancestor, int *child_pos);
+
+#endif
Modified: polly/trunk/lib/External/isl/isl_scheduler.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_scheduler.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_scheduler.c (original)
+++ polly/trunk/lib/External/isl/isl_scheduler.c Mon Feb 16 13:33:40 2015
@@ -17,6 +17,7 @@
#include <isl/hash.h>
#include <isl/constraint.h>
#include <isl/schedule.h>
+#include <isl/schedule_node.h>
#include <isl_mat_private.h>
#include <isl_vec_private.h>
#include <isl/set.h>
@@ -25,7 +26,6 @@
#include <isl_dim_map.h>
#include <isl/map_to_basic_set.h>
#include <isl_sort.h>
-#include <isl_schedule_private.h>
#include <isl_options_private.h>
#include <isl_tarjan.h>
#include <isl_morph.h>
@@ -48,6 +48,8 @@ enum isl_edge_type {
/* The constraints that need to be satisfied by a schedule on "domain".
*
+ * "context" specifies extra constraints on the parameters.
+ *
* "validity" constraints map domain elements i to domain elements
* that should be scheduled after i. (Hard constraint)
* "proximity" constraints map domain elements i to domains elements
@@ -67,6 +69,7 @@ enum isl_edge_type {
*/
struct isl_schedule_constraints {
isl_union_set *domain;
+ isl_set *context;
isl_union_map *constraint[isl_edge_last + 1];
};
@@ -84,7 +87,8 @@ struct isl_schedule_constraints {
return NULL;
sc_copy->domain = isl_union_set_copy(sc->domain);
- if (!sc_copy->domain)
+ sc_copy->context = isl_set_copy(sc->context);
+ if (!sc_copy->domain || !sc_copy->context)
return isl_schedule_constraints_free(sc_copy);
for (i = isl_edge_first; i <= isl_edge_last; ++i) {
@@ -119,6 +123,7 @@ __isl_give isl_schedule_constraints *isl
space = isl_union_set_get_space(domain);
sc->domain = domain;
+ sc->context = isl_set_universe(isl_space_copy(space));
empty = isl_union_map_empty(space);
for (i = isl_edge_first; i <= isl_edge_last; ++i) {
sc->constraint[i] = isl_union_map_copy(empty);
@@ -127,7 +132,7 @@ __isl_give isl_schedule_constraints *isl
}
isl_union_map_free(empty);
- if (!sc->domain)
+ if (!sc->domain || !sc->context)
return isl_schedule_constraints_free(sc);
return sc;
@@ -136,6 +141,24 @@ error:
return NULL;
}
+/* Replace the context of "sc" by "context".
+ */
+__isl_give isl_schedule_constraints *isl_schedule_constraints_set_context(
+ __isl_take isl_schedule_constraints *sc, __isl_take isl_set *context)
+{
+ if (!sc || !context)
+ goto error;
+
+ isl_set_free(sc->context);
+ sc->context = context;
+
+ return sc;
+error:
+ isl_schedule_constraints_free(sc);
+ isl_set_free(context);
+ return NULL;
+}
+
/* Replace the validity constraints of "sc" by "validity".
*/
__isl_give isl_schedule_constraints *isl_schedule_constraints_set_validity(
@@ -227,6 +250,7 @@ __isl_null isl_schedule_constraints *isl
return NULL;
isl_union_set_free(sc->domain);
+ isl_set_free(sc->context);
for (i = isl_edge_first; i <= isl_edge_last; ++i)
isl_union_map_free(sc->constraint[i]);
@@ -248,6 +272,8 @@ void isl_schedule_constraints_dump(__isl
fprintf(stderr, "domain: ");
isl_union_set_dump(sc->domain);
+ fprintf(stderr, "context: ");
+ isl_set_dump(sc->context);
fprintf(stderr, "validity: ");
isl_union_map_dump(sc->constraint[isl_edge_validity]);
fprintf(stderr, "proximity: ");
@@ -272,6 +298,7 @@ isl_schedule_constraints_align_params(__
return NULL;
space = isl_union_set_get_space(sc->domain);
+ space = isl_space_align_params(space, isl_set_get_space(sc->context));
for (i = isl_edge_first; i <= isl_edge_last; ++i)
space = isl_space_align_params(space,
isl_union_map_get_space(sc->constraint[i]));
@@ -282,8 +309,9 @@ isl_schedule_constraints_align_params(__
if (!sc->constraint[i])
space = isl_space_free(space);
}
+ sc->context = isl_set_align_params(sc->context, isl_space_copy(space));
sc->domain = isl_union_set_align_params(sc->domain, space);
- if (!sc->domain)
+ if (!sc->context || !sc->domain)
return isl_schedule_constraints_free(sc);
return sc;
@@ -331,10 +359,6 @@ static __isl_give int isl_schedule_const
*
* scc is the index of SCC (or WCC) this node belongs to
*
- * band contains the band index for each of the rows of the schedule.
- * band_id is used to differentiate between separate bands at the same
- * level within the same parent band, i.e., bands that are separated
- * by the parent band or bands that are independent of each other.
* coincident contains a boolean for each of the rows of the schedule,
* indicating whether the corresponding scheduling dimension satisfies
* the coincidence constraints in the sense that the corresponding
@@ -357,8 +381,6 @@ struct isl_sched_node {
int scc;
- int *band;
- int *band_id;
int *coincident;
};
@@ -370,6 +392,21 @@ static int node_has_space(const void *en
return isl_space_is_equal(node->space, dim);
}
+static int node_scc_exactly(struct isl_sched_node *node, int scc)
+{
+ return node->scc == scc;
+}
+
+static int node_scc_at_most(struct isl_sched_node *node, int scc)
+{
+ return node->scc <= scc;
+}
+
+static int node_scc_at_least(struct isl_sched_node *node, int scc)
+{
+ return node->scc >= scc;
+}
+
/* An edge in the dependence graph. An edge may be used to
* ensure validity of the generated schedule, to minimize the dependence
* distance or both
@@ -434,7 +471,6 @@ struct isl_sched_edge {
* n_row is the current (maximal) number of linearly independent
* rows in the node schedules
* n_total_row is the current number of rows in the node schedules
- * n_band is the current number of completed bands
* band_start is the starting row in the node schedules of the current band
* root is set if this graph is the original dependence graph,
* without any splitting
@@ -462,6 +498,7 @@ struct isl_sched_edge {
* conflicting constraints
*
* scc represents the number of components
+ * weak is set if the components are weakly connected
*/
struct isl_sched_graph {
isl_map_to_basic_set *intra_hmap;
@@ -475,7 +512,6 @@ struct isl_sched_graph {
int *sorted;
- int n_band;
int n_total_row;
int band_start;
@@ -495,6 +531,7 @@ struct isl_sched_graph {
int dst_scc;
int scc;
+ int weak;
};
/* Initialize node_table based on the list of nodes.
@@ -775,11 +812,8 @@ static void graph_free(isl_ctx *ctx, str
isl_map_free(graph->node[i].sched_map);
isl_mat_free(graph->node[i].cmap);
isl_mat_free(graph->node[i].cinv);
- if (graph->root) {
- free(graph->node[i].band);
- free(graph->node[i].band_id);
+ if (graph->root)
free(graph->node[i].coincident);
- }
}
free(graph->node);
free(graph->sorted);
@@ -827,15 +861,10 @@ static int add_n_basic_map(__isl_take is
}
/* Compute the number of rows that should be allocated for the schedule.
- * The graph can be split at most "n - 1" times, there can be at most
- * one row for each dimension in the iteration domains plus two rows
- * for each basic map in the dependences (in particular,
- * we usually have one row, but it may be split by split_scaled),
- * and there can be one extra row for ordering the statements.
- * Note that if we have actually split "n - 1" times, then no ordering
- * is needed, so in principle we could use "graph->n + 2 * graph->maxvar - 1".
- * It is also practically impossible to exhaust both the number of dependences
- * and the number of variables.
+ * In particular, we need one row for each variable or one row
+ * for each basic map in the dependences.
+ * Note that it is practically impossible to exhaust both
+ * the number of dependences and the number of variables.
*/
static int compute_max_row(struct isl_sched_graph *graph,
__isl_keep isl_schedule_constraints *sc)
@@ -852,7 +881,7 @@ static int compute_max_row(struct isl_sc
if (isl_union_map_foreach_map(sc->constraint[i],
&add_n_basic_map, &n_edge) < 0)
return -1;
- graph->max_row = graph->n + 2 * n_edge + graph->maxvar;
+ graph->max_row = n_edge + graph->maxvar;
return 0;
}
@@ -898,7 +927,7 @@ static int add_node(struct isl_sched_gra
int nparam;
isl_ctx *ctx;
isl_mat *sched;
- int *band, *band_id, *coincident;
+ int *coincident;
if (!space)
return -1;
@@ -913,10 +942,6 @@ static int add_node(struct isl_sched_gra
graph->node[graph->n].nparam = nparam;
graph->node[graph->n].sched = sched;
graph->node[graph->n].sched_map = NULL;
- band = isl_alloc_array(ctx, int, graph->max_row);
- graph->node[graph->n].band = band;
- band_id = isl_calloc_array(ctx, int, graph->max_row);
- graph->node[graph->n].band_id = band_id;
coincident = isl_calloc_array(ctx, int, graph->max_row);
graph->node[graph->n].coincident = coincident;
graph->node[graph->n].compressed = compressed;
@@ -925,8 +950,7 @@ static int add_node(struct isl_sched_gra
graph->node[graph->n].decompress = decompress;
graph->n++;
- if (!space || !sched ||
- (graph->max_row && (!band || !band_id || !coincident)))
+ if (!space || !sched || (graph->max_row && !coincident))
return -1;
if (compressed && (!hull || !compress || !decompress))
return -1;
@@ -1247,6 +1271,7 @@ static int detect_ccs(isl_ctx *ctx, stru
if (!g)
return -1;
+ graph->weak = weak;
graph->scc = 0;
i = 0;
n = graph->n;
@@ -2281,7 +2306,6 @@ static int update_schedule(struct isl_sc
for (j = 0; j < node->nvar; ++j)
node->sched = isl_mat_set_element(node->sched,
row, 1 + node->nparam + j, csol->el[j]);
- node->band[graph->n_total_row] = graph->n_band;
node->coincident[graph->n_total_row] = coincident;
}
isl_vec_free(sol);
@@ -2326,12 +2350,13 @@ static __isl_give isl_aff *extract_sched
return aff;
}
-/* Convert node->sched into a multi_aff and return this multi_aff.
+/* Convert the "n" rows starting at "first" of node->sched into a multi_aff
+ * and return this multi_aff.
*
* The result is defined over the uncompressed node domain.
*/
-static __isl_give isl_multi_aff *node_extract_schedule_multi_aff(
- struct isl_sched_node *node)
+static __isl_give isl_multi_aff *node_extract_partial_schedule_multi_aff(
+ struct isl_sched_node *node, int first, int n)
{
int i;
isl_space *space;
@@ -2348,12 +2373,12 @@ static __isl_give isl_multi_aff *node_ex
space = isl_space_copy(node->space);
ls = isl_local_space_from_space(isl_space_copy(space));
space = isl_space_from_domain(space);
- space = isl_space_add_dims(space, isl_dim_out, nrow);
+ space = isl_space_add_dims(space, isl_dim_out, n);
ma = isl_multi_aff_zero(space);
- for (i = 0; i < nrow; ++i) {
+ for (i = first; i < first + n; ++i) {
aff = extract_schedule_row(isl_local_space_copy(ls), node, i);
- ma = isl_multi_aff_set_aff(ma, i, aff);
+ ma = isl_multi_aff_set_aff(ma, i - first, aff);
}
isl_local_space_free(ls);
@@ -2365,6 +2390,19 @@ static __isl_give isl_multi_aff *node_ex
return ma;
}
+/* Convert node->sched into a multi_aff and return this multi_aff.
+ *
+ * The result is defined over the uncompressed node domain.
+ */
+static __isl_give isl_multi_aff *node_extract_schedule_multi_aff(
+ struct isl_sched_node *node)
+{
+ int nrow;
+
+ nrow = isl_mat_rows(node->sched);
+ return node_extract_partial_schedule_multi_aff(node, 0, nrow);
+}
+
/* Convert node->sched into a map and return this map.
*
* The result is cached in node->sched_map, which needs to be released
@@ -2472,126 +2510,115 @@ static int update_edges(isl_ctx *ctx, st
static void next_band(struct isl_sched_graph *graph)
{
graph->band_start = graph->n_total_row;
- graph->n_band++;
}
-/* Topologically sort statements mapped to the same schedule iteration
- * and add a row to the schedule corresponding to this order.
+/* Return the union of the universe domains of the nodes in "graph"
+ * that satisfy "pred".
*/
-static int sort_statements(isl_ctx *ctx, struct isl_sched_graph *graph)
+static __isl_give isl_union_set *isl_sched_graph_domain(isl_ctx *ctx,
+ struct isl_sched_graph *graph,
+ int (*pred)(struct isl_sched_node *node, int data), int data)
{
- int i, j;
+ int i;
+ isl_set *set;
+ isl_union_set *dom;
- if (graph->n <= 1)
- return 0;
+ for (i = 0; i < graph->n; ++i)
+ if (pred(&graph->node[i], data))
+ break;
- if (update_edges(ctx, graph) < 0)
- return -1;
+ if (i >= graph->n)
+ isl_die(ctx, isl_error_internal,
+ "empty component", return NULL);
- if (graph->n_edge == 0)
- return 0;
+ set = isl_set_universe(isl_space_copy(graph->node[i].space));
+ dom = isl_union_set_from_set(set);
- if (detect_sccs(ctx, graph) < 0)
- return -1;
+ for (i = i + 1; i < graph->n; ++i) {
+ if (!pred(&graph->node[i], data))
+ continue;
+ set = isl_set_universe(isl_space_copy(graph->node[i].space));
+ dom = isl_union_set_union(dom, isl_union_set_from_set(set));
+ }
- if (graph->n_total_row >= graph->max_row)
- isl_die(ctx, isl_error_internal,
- "too many schedule rows", return -1);
+ return dom;
+}
- for (i = 0; i < graph->n; ++i) {
- struct isl_sched_node *node = &graph->node[i];
- int row = isl_mat_rows(node->sched);
- int cols = isl_mat_cols(node->sched);
+/* Return a list of unions of universe domains, where each element
+ * in the list corresponds to an SCC (or WCC) indexed by node->scc.
+ */
+static __isl_give isl_union_set_list *extract_sccs(isl_ctx *ctx,
+ struct isl_sched_graph *graph)
+{
+ int i;
+ isl_union_set_list *filters;
- isl_map_free(node->sched_map);
- node->sched_map = NULL;
- node->sched = isl_mat_add_rows(node->sched, 1);
- if (!node->sched)
- return -1;
- node->sched = isl_mat_set_element_si(node->sched, row, 0,
- node->scc);
- for (j = 1; j < cols; ++j)
- node->sched = isl_mat_set_element_si(node->sched,
- row, j, 0);
- node->band[graph->n_total_row] = graph->n_band;
+ filters = isl_union_set_list_alloc(ctx, graph->scc);
+ for (i = 0; i < graph->scc; ++i) {
+ isl_union_set *dom;
+
+ dom = isl_sched_graph_domain(ctx, graph, &node_scc_exactly, i);
+ filters = isl_union_set_list_add(filters, dom);
}
- graph->n_total_row++;
- next_band(graph);
+ return filters;
+}
- return 0;
+/* Return a list of two unions of universe domains, one for the SCCs up
+ * to and including graph->src_scc and another for the other SCCS.
+ */
+static __isl_give isl_union_set_list *extract_split(isl_ctx *ctx,
+ struct isl_sched_graph *graph)
+{
+ isl_union_set *dom;
+ isl_union_set_list *filters;
+
+ filters = isl_union_set_list_alloc(ctx, 2);
+ dom = isl_sched_graph_domain(ctx, graph,
+ &node_scc_at_most, graph->src_scc);
+ filters = isl_union_set_list_add(filters, dom);
+ dom = isl_sched_graph_domain(ctx, graph,
+ &node_scc_at_least, graph->src_scc + 1);
+ filters = isl_union_set_list_add(filters, dom);
+
+ return filters;
}
-/* Construct an isl_schedule based on the computed schedule stored
- * in graph and with parameters specified by dim.
+/* Topologically sort statements mapped to the same schedule iteration
+ * and add insert a sequence node in front of "node"
+ * corresponding to this order.
*/
-static __isl_give isl_schedule *extract_schedule(struct isl_sched_graph *graph,
- __isl_take isl_space *dim)
+static __isl_give isl_schedule_node *sort_statements(
+ __isl_take isl_schedule_node *node, struct isl_sched_graph *graph)
{
- int i;
isl_ctx *ctx;
- isl_schedule *sched = NULL;
+ isl_union_set_list *filters;
- if (!dim)
+ if (!node)
return NULL;
- ctx = isl_space_get_ctx(dim);
- sched = isl_calloc(ctx, struct isl_schedule,
- sizeof(struct isl_schedule) +
- (graph->n - 1) * sizeof(struct isl_schedule_node));
- if (!sched)
- goto error;
+ ctx = isl_schedule_node_get_ctx(node);
+ if (graph->n < 1)
+ isl_die(ctx, isl_error_internal,
+ "graph should have at least one node",
+ return isl_schedule_node_free(node));
- sched->ref = 1;
- sched->n = graph->n;
- sched->n_band = graph->n_band;
- sched->n_total_row = graph->n_total_row;
-
- for (i = 0; i < sched->n; ++i) {
- int r, b;
- int *band_end, *band_id, *coincident;
-
- sched->node[i].sched =
- node_extract_schedule_multi_aff(&graph->node[i]);
- if (!sched->node[i].sched)
- goto error;
+ if (graph->n == 1)
+ return node;
- sched->node[i].n_band = graph->n_band;
- if (graph->n_band == 0)
- continue;
+ if (update_edges(ctx, graph) < 0)
+ return isl_schedule_node_free(node);
- band_end = isl_alloc_array(ctx, int, graph->n_band);
- band_id = isl_alloc_array(ctx, int, graph->n_band);
- coincident = isl_alloc_array(ctx, int, graph->n_total_row);
- sched->node[i].band_end = band_end;
- sched->node[i].band_id = band_id;
- sched->node[i].coincident = coincident;
- if (!band_end || !band_id || !coincident)
- goto error;
+ if (graph->n_edge == 0)
+ return node;
- for (r = 0; r < graph->n_total_row; ++r)
- coincident[r] = graph->node[i].coincident[r];
- for (r = b = 0; r < graph->n_total_row; ++r) {
- if (graph->node[i].band[r] == b)
- continue;
- band_end[b++] = r;
- if (graph->node[i].band[r] == -1)
- break;
- }
- if (r == graph->n_total_row)
- band_end[b++] = r;
- sched->node[i].n_band = b;
- for (--b; b >= 0; --b)
- band_id[b] = graph->node[i].band_id[b];
- }
+ if (detect_sccs(ctx, graph) < 0)
+ return isl_schedule_node_free(node);
- sched->dim = dim;
+ filters = extract_sccs(ctx, graph);
+ node = isl_schedule_node_insert_sequence(node, filters);
- return sched;
-error:
- isl_space_free(dim);
- isl_schedule_free(sched);
- return NULL;
+ return node;
}
/* Copy nodes that satisfy node_pred from the src dependence graph
@@ -2621,8 +2648,6 @@ static int copy_nodes(struct isl_sched_g
dst->node[j].nparam = src->node[i].nparam;
dst->node[j].sched = isl_mat_copy(src->node[i].sched);
dst->node[j].sched_map = isl_map_copy(src->node[i].sched_map);
- dst->node[j].band = src->node[i].band;
- dst->node[j].band_id = src->node[i].band_id;
dst->node[j].coincident = src->node[i].coincident;
dst->n++;
@@ -2709,35 +2734,6 @@ static int copy_edges(isl_ctx *ctx, stru
return 0;
}
-/* Given a "src" dependence graph that contains the nodes from "dst"
- * that satisfy node_pred, copy the schedule computed in "src"
- * for those nodes back to "dst".
- */
-static int copy_schedule(struct isl_sched_graph *dst,
- struct isl_sched_graph *src,
- int (*node_pred)(struct isl_sched_node *node, int data), int data)
-{
- int i;
-
- src->n = 0;
- for (i = 0; i < dst->n; ++i) {
- if (!node_pred(&dst->node[i], data))
- continue;
- isl_mat_free(dst->node[i].sched);
- isl_map_free(dst->node[i].sched_map);
- dst->node[i].sched = isl_mat_copy(src->node[src->n].sched);
- dst->node[i].sched_map =
- isl_map_copy(src->node[src->n].sched_map);
- src->n++;
- }
-
- dst->max_row = src->max_row;
- dst->n_total_row = src->n_total_row;
- dst->n_band = src->n_band;
-
- return 0;
-}
-
/* Compute the maximal number of variables over all nodes.
* This is the maximal number of linearly independent schedule
* rows that we need to compute.
@@ -2764,8 +2760,10 @@ static int compute_maxvar(struct isl_sch
return 0;
}
-static int compute_schedule(isl_ctx *ctx, struct isl_sched_graph *graph);
-static int compute_schedule_wcc(isl_ctx *ctx, struct isl_sched_graph *graph);
+static __isl_give isl_schedule_node *compute_schedule(isl_schedule_node *node,
+ struct isl_sched_graph *graph);
+static __isl_give isl_schedule_node *compute_schedule_wcc(
+ isl_schedule_node *node, struct isl_sched_graph *graph);
/* Compute a schedule for a subgraph of "graph". In particular, for
* the graph composed of nodes that satisfy node_pred and edges that
@@ -2776,8 +2774,12 @@ static int compute_schedule_wcc(isl_ctx
* be set and then we call compute_schedule_wcc on the constructed subgraph.
* Otherwise, we call compute_schedule, which will check whether the subgraph
* is connected.
+ *
+ * The schedule is inserted at "node" and the updated schedule node
+ * is returned.
*/
-static int compute_sub_schedule(isl_ctx *ctx,
+static __isl_give isl_schedule_node *compute_sub_schedule(
+ __isl_take isl_schedule_node *node, isl_ctx *ctx,
struct isl_sched_graph *graph, int n, int n_edge,
int (*node_pred)(struct isl_sched_node *node, int data),
int (*edge_pred)(struct isl_sched_edge *edge, int data),
@@ -2801,36 +2803,18 @@ static int compute_sub_schedule(isl_ctx
split.n_row = graph->n_row;
split.max_row = graph->max_row;
split.n_total_row = graph->n_total_row;
- split.n_band = graph->n_band;
split.band_start = graph->band_start;
- if (wcc && compute_schedule_wcc(ctx, &split) < 0)
- goto error;
- if (!wcc && compute_schedule(ctx, &split) < 0)
- goto error;
-
- copy_schedule(graph, &split, node_pred, data);
+ if (wcc)
+ node = compute_schedule_wcc(node, &split);
+ else
+ node = compute_schedule(node, &split);
graph_free(ctx, &split);
- return 0;
+ return node;
error:
graph_free(ctx, &split);
- return -1;
-}
-
-static int node_scc_exactly(struct isl_sched_node *node, int scc)
-{
- return node->scc == scc;
-}
-
-static int node_scc_at_most(struct isl_sched_node *node, int scc)
-{
- return node->scc <= scc;
-}
-
-static int node_scc_at_least(struct isl_sched_node *node, int scc)
-{
- return node->scc >= scc;
+ return isl_schedule_node_free(node);
}
static int edge_scc_exactly(struct isl_sched_edge *edge, int scc)
@@ -2848,32 +2832,6 @@ static int edge_src_scc_at_least(struct
return edge->src->scc >= scc;
}
-/* Pad the schedules of all nodes with zero rows such that in the end
- * they all have graph->n_total_row rows.
- * The extra rows don't belong to any band, so they get assigned band number -1.
- */
-static int pad_schedule(struct isl_sched_graph *graph)
-{
- int i, j;
-
- for (i = 0; i < graph->n; ++i) {
- struct isl_sched_node *node = &graph->node[i];
- int row = isl_mat_rows(node->sched);
- if (graph->n_total_row > row) {
- isl_map_free(node->sched_map);
- node->sched_map = NULL;
- }
- node->sched = isl_mat_add_zero_rows(node->sched,
- graph->n_total_row - row);
- if (!node->sched)
- return -1;
- for (j = row; j < graph->n_total_row; ++j)
- node->band[j] = -1;
- }
-
- return 0;
-}
-
/* Reset the current band by dropping all its schedule rows.
*/
static int reset_band(struct isl_sched_graph *graph)
@@ -2904,58 +2862,35 @@ static int reset_band(struct isl_sched_g
/* Split the current graph into two parts and compute a schedule for each
* part individually. In particular, one part consists of all SCCs up
* to and including graph->src_scc, while the other part contains the other
- * SCCS.
+ * SCCS. The split is enforced by a sequence node inserted at position "node"
+ * in the schedule tree. Return the updated schedule node.
*
- * The split is enforced in the schedule by constant rows with two different
- * values (0 and 1). These constant rows replace the previously computed rows
- * in the current band.
- * It would be possible to reuse them as the first rows in the next
+ * The current band is reset. It would be possible to reuse
+ * the previously computed rows as the first rows in the next
* band, but recomputing them may result in better rows as we are looking
* at a smaller part of the dependence graph.
- *
- * Since we do not enforce coincidence, we conservatively mark the
- * splitting row as not coincident.
- *
- * The band_id of the second group is set to n, where n is the number
- * of nodes in the first group. This ensures that the band_ids over
- * the two groups remain disjoint, even if either or both of the two
- * groups contain independent components.
- */
-static int compute_split_schedule(isl_ctx *ctx, struct isl_sched_graph *graph)
-{
- int i, j, n, e1, e2;
- int n_total_row, orig_total_row;
- int n_band, orig_band;
+ */
+static __isl_give isl_schedule_node *compute_split_schedule(
+ __isl_take isl_schedule_node *node, struct isl_sched_graph *graph)
+{
+ int i, n, e1, e2;
+ int orig_total_row;
+ isl_ctx *ctx;
+ isl_union_set_list *filters;
- if (graph->n_total_row >= graph->max_row)
- isl_die(ctx, isl_error_internal,
- "too many schedule rows", return -1);
+ if (!node)
+ return NULL;
if (reset_band(graph) < 0)
- return -1;
+ return isl_schedule_node_free(node);
n = 0;
for (i = 0; i < graph->n; ++i) {
struct isl_sched_node *node = &graph->node[i];
- int row = isl_mat_rows(node->sched);
- int cols = isl_mat_cols(node->sched);
int before = node->scc <= graph->src_scc;
if (before)
n++;
-
- isl_map_free(node->sched_map);
- node->sched_map = NULL;
- node->sched = isl_mat_add_rows(node->sched, 1);
- if (!node->sched)
- return -1;
- node->sched = isl_mat_set_element_si(node->sched, row, 0,
- !before);
- for (j = 1; j < cols; ++j)
- node->sched = isl_mat_set_element_si(node->sched,
- row, j, 0);
- node->band[graph->n_total_row] = graph->n_band;
- node->coincident[graph->n_total_row] = 0;
}
e1 = e2 = 0;
@@ -2966,47 +2901,108 @@ static int compute_split_schedule(isl_ct
e2++;
}
- graph->n_total_row++;
next_band(graph);
- for (i = 0; i < graph->n; ++i) {
- struct isl_sched_node *node = &graph->node[i];
- if (node->scc > graph->src_scc)
- node->band_id[graph->n_band] = n;
- }
+ ctx = isl_schedule_node_get_ctx(node);
+ filters = extract_split(ctx, graph);
+ node = isl_schedule_node_insert_sequence(node, filters);
+ node = isl_schedule_node_child(node, 0);
+ node = isl_schedule_node_child(node, 0);
orig_total_row = graph->n_total_row;
- orig_band = graph->n_band;
- if (compute_sub_schedule(ctx, graph, n, e1,
+ node = compute_sub_schedule(node, ctx, graph, n, e1,
&node_scc_at_most, &edge_dst_scc_at_most,
- graph->src_scc, 0) < 0)
- return -1;
- n_total_row = graph->n_total_row;
+ graph->src_scc, 0);
+ node = isl_schedule_node_parent(node);
+ node = isl_schedule_node_next_sibling(node);
+ node = isl_schedule_node_child(node, 0);
graph->n_total_row = orig_total_row;
- n_band = graph->n_band;
- graph->n_band = orig_band;
- if (compute_sub_schedule(ctx, graph, graph->n - n, e2,
+ node = compute_sub_schedule(node, ctx, graph, graph->n - n, e2,
&node_scc_at_least, &edge_src_scc_at_least,
- graph->src_scc + 1, 0) < 0)
- return -1;
- if (n_total_row > graph->n_total_row)
- graph->n_total_row = n_total_row;
- if (n_band > graph->n_band)
- graph->n_band = n_band;
+ graph->src_scc + 1, 0);
+ node = isl_schedule_node_parent(node);
+ node = isl_schedule_node_parent(node);
+
+ return node;
+}
+
+/* Insert a band node at position "node" in the schedule tree corresponding
+ * to the current band in "graph". Mark the band node permutable
+ * if "permutable" is set.
+ * The partial schedules and the coincidence property are extracted
+ * from the graph nodes.
+ * Return the updated schedule node.
+ */
+static __isl_give isl_schedule_node *insert_current_band(
+ __isl_take isl_schedule_node *node, struct isl_sched_graph *graph,
+ int permutable)
+{
+ int i;
+ int start, end, n;
+ isl_multi_aff *ma;
+ isl_multi_pw_aff *mpa;
+ isl_multi_union_pw_aff *mupa;
- return pad_schedule(graph);
-}
+ if (!node)
+ return NULL;
-/* Compute the next band of the schedule after updating the dependence
- * relations based on the the current schedule.
- */
-static int compute_next_band(isl_ctx *ctx, struct isl_sched_graph *graph)
+ if (graph->n < 1)
+ isl_die(isl_schedule_node_get_ctx(node), isl_error_internal,
+ "graph should have at least one node",
+ return isl_schedule_node_free(node));
+
+ start = graph->band_start;
+ end = graph->n_total_row;
+ n = end - start;
+
+ ma = node_extract_partial_schedule_multi_aff(&graph->node[0], start, n);
+ mpa = isl_multi_pw_aff_from_multi_aff(ma);
+ mupa = isl_multi_union_pw_aff_from_multi_pw_aff(mpa);
+
+ for (i = 1; i < graph->n; ++i) {
+ isl_multi_union_pw_aff *mupa_i;
+
+ ma = node_extract_partial_schedule_multi_aff(&graph->node[i],
+ start, n);
+ mpa = isl_multi_pw_aff_from_multi_aff(ma);
+ mupa_i = isl_multi_union_pw_aff_from_multi_pw_aff(mpa);
+ mupa = isl_multi_union_pw_aff_union_add(mupa, mupa_i);
+ }
+ node = isl_schedule_node_insert_partial_schedule(node, mupa);
+
+ for (i = 0; i < n; ++i)
+ node = isl_schedule_node_band_member_set_coincident(node, i,
+ graph->node[0].coincident[start + i]);
+ node = isl_schedule_node_band_set_permutable(node, permutable);
+
+ return node;
+}
+
+/* Update the dependence relations based on the current schedule,
+ * add the current band to "node" and the continue with the computation
+ * of the next band.
+ * Return the updated schedule node.
+ */
+static __isl_give isl_schedule_node *compute_next_band(
+ __isl_take isl_schedule_node *node,
+ struct isl_sched_graph *graph, int permutable)
{
+ isl_ctx *ctx;
+
+ if (!node)
+ return NULL;
+
+ ctx = isl_schedule_node_get_ctx(node);
if (update_edges(ctx, graph) < 0)
- return -1;
+ return isl_schedule_node_free(node);
+ node = insert_current_band(node, graph, permutable);
next_band(graph);
- return compute_schedule(ctx, graph);
+ node = isl_schedule_node_child(node, 0);
+ node = compute_schedule(node, graph);
+ node = isl_schedule_node_parent(node);
+
+ return node;
}
/* Add constraints to graph->lp that force the dependence "map" (which
@@ -3302,27 +3298,56 @@ static int setup_carry_lp(isl_ctx *ctx,
return 0;
}
+static __isl_give isl_schedule_node *compute_component_schedule(
+ __isl_take isl_schedule_node *node, struct isl_sched_graph *graph,
+ int wcc);
+
+/* Comparison function for sorting the statements based on
+ * the corresponding value in "r".
+ */
+static int smaller_value(const void *a, const void *b, void *data)
+{
+ isl_vec *r = data;
+ const int *i1 = a;
+ const int *i2 = b;
+
+ return isl_int_cmp(r->el[*i1], r->el[*i2]);
+}
+
/* If the schedule_split_scaled option is set and if the linear
* parts of the scheduling rows for all nodes in the graphs have
- * non-trivial common divisor, then split off the constant term
- * from the linear part.
- * The constant term is then placed in a separate band and
- * the linear part is reduced.
+ * a non-trivial common divisor, then split off the remainder of the
+ * constant term modulo this common divisor from the linear part.
+ * Otherwise, insert a band node directly and continue with
+ * the construction of the schedule.
+ *
+ * If a non-trivial common divisor is found, then
+ * the linear part is reduced and the remainder is enforced
+ * by a sequence node with the children placed in the order
+ * of this remainder.
+ * In particular, we assign an scc index based on the remainder and
+ * then rely on compute_component_schedule to insert the sequence and
+ * to continue the schedule construction on each part.
*/
-static int split_scaled(isl_ctx *ctx, struct isl_sched_graph *graph)
+static __isl_give isl_schedule_node *split_scaled(
+ __isl_take isl_schedule_node *node, struct isl_sched_graph *graph)
{
int i;
int row;
+ int scc;
+ isl_ctx *ctx;
isl_int gcd, gcd_i;
+ isl_vec *r;
+ int *order;
+
+ if (!node)
+ return NULL;
+ ctx = isl_schedule_node_get_ctx(node);
if (!ctx->opt->schedule_split_scaled)
- return 0;
+ return compute_next_band(node, graph, 0);
if (graph->n <= 1)
- return 0;
-
- if (graph->n_total_row >= graph->max_row)
- isl_die(ctx, isl_error_internal,
- "too many schedule rows", return -1);
+ return compute_next_band(node, graph, 0);
isl_int_init(gcd);
isl_int_init(gcd_i);
@@ -3343,21 +3368,19 @@ static int split_scaled(isl_ctx *ctx, st
if (isl_int_cmp_si(gcd, 1) <= 0) {
isl_int_clear(gcd);
- return 0;
+ return compute_next_band(node, graph, 0);
}
- next_band(graph);
+ r = isl_vec_alloc(ctx, graph->n);
+ order = isl_calloc_array(ctx, int, graph->n);
+ if (!r || !order)
+ goto error;
for (i = 0; i < graph->n; ++i) {
struct isl_sched_node *node = &graph->node[i];
- isl_map_free(node->sched_map);
- node->sched_map = NULL;
- node->sched = isl_mat_add_zero_rows(node->sched, 1);
- if (!node->sched)
- goto error;
- isl_int_fdiv_r(node->sched->row[row + 1][0],
- node->sched->row[row][0], gcd);
+ order[i] = i;
+ isl_int_fdiv_r(r->el[i], node->sched->row[row][0], gcd);
isl_int_fdiv_q(node->sched->row[row][0],
node->sched->row[row][0], gcd);
isl_int_mul(node->sched->row[row][0],
@@ -3365,21 +3388,41 @@ static int split_scaled(isl_ctx *ctx, st
node->sched = isl_mat_scale_down_row(node->sched, row, gcd);
if (!node->sched)
goto error;
- node->band[graph->n_total_row] = graph->n_band;
}
- graph->n_total_row++;
+ if (isl_sort(order, graph->n, sizeof(order[0]), &smaller_value, r) < 0)
+ goto error;
+
+ scc = 0;
+ for (i = 0; i < graph->n; ++i) {
+ if (i > 0 && isl_int_ne(r->el[order[i - 1]], r->el[order[i]]))
+ ++scc;
+ graph->node[order[i]].scc = scc;
+ }
+ graph->scc = ++scc;
+ graph->weak = 0;
isl_int_clear(gcd);
- return 0;
+ isl_vec_free(r);
+ free(order);
+
+ if (update_edges(ctx, graph) < 0)
+ return isl_schedule_node_free(node);
+ node = insert_current_band(node, graph, 0);
+ next_band(graph);
+
+ node = isl_schedule_node_child(node, 0);
+ node = compute_component_schedule(node, graph, 0);
+ node = isl_schedule_node_parent(node);
+
+ return node;
error:
+ isl_vec_free(r);
+ free(order);
isl_int_clear(gcd);
- return -1;
+ return isl_schedule_node_free(node);
}
-static int compute_component_schedule(isl_ctx *ctx,
- struct isl_sched_graph *graph);
-
/* Is the schedule row "sol" trivial on node "node"?
* That is, is the solution zero on the dimensions orthogonal to
* the previously found solutions?
@@ -3469,38 +3512,51 @@ static int is_any_trivial(struct isl_sch
* graph->maxvar is computed based on these ranks. The test for
* whether more schedule rows are required in compute_schedule_wcc
* is therefore not affected.
+ *
+ * Insert a band corresponding to the schedule row at position "node"
+ * of the schedule tree and continue with the construction of the schedule.
+ * This insertion and the continued construction is performed by split_scaled
+ * after optionally checking for non-trivial common divisors.
*/
-static int carry_dependences(isl_ctx *ctx, struct isl_sched_graph *graph)
+static __isl_give isl_schedule_node *carry_dependences(
+ __isl_take isl_schedule_node *node, struct isl_sched_graph *graph)
{
int i;
int n_edge;
int trivial;
+ isl_ctx *ctx;
isl_vec *sol;
isl_basic_set *lp;
+ if (!node)
+ return NULL;
+
n_edge = 0;
for (i = 0; i < graph->n_edge; ++i)
n_edge += graph->edge[i].map->n;
+ ctx = isl_schedule_node_get_ctx(node);
if (setup_carry_lp(ctx, graph) < 0)
- return -1;
+ return isl_schedule_node_free(node);
lp = isl_basic_set_copy(graph->lp);
sol = isl_tab_basic_set_non_neg_lexmin(lp);
if (!sol)
- return -1;
+ return isl_schedule_node_free(node);
if (sol->size == 0) {
isl_vec_free(sol);
isl_die(ctx, isl_error_internal,
- "error in schedule construction", return -1);
+ "error in schedule construction",
+ return isl_schedule_node_free(node));
}
isl_int_divexact(sol->el[1], sol->el[1], sol->el[0]);
if (isl_int_cmp_si(sol->el[1], n_edge) >= 0) {
isl_vec_free(sol);
isl_die(ctx, isl_error_unknown,
- "unable to carry dependences", return -1);
+ "unable to carry dependences",
+ return isl_schedule_node_free(node));
}
trivial = is_any_trivial(graph, sol);
@@ -3508,18 +3564,15 @@ static int carry_dependences(isl_ctx *ct
sol = isl_vec_free(sol);
} else if (trivial && graph->scc > 1) {
isl_vec_free(sol);
- return compute_component_schedule(ctx, graph);
+ return compute_component_schedule(node, graph, 1);
}
if (update_schedule(graph, sol, 0, 0) < 0)
- return -1;
+ return isl_schedule_node_free(node);
if (trivial)
graph->n_row--;
- if (split_scaled(ctx, graph) < 0)
- return -1;
-
- return compute_next_band(ctx, graph);
+ return split_scaled(node, graph);
}
/* Are there any (non-empty) (conditional) validity edges in the graph?
@@ -3557,7 +3610,8 @@ static int need_feautrier_step(isl_ctx *
}
/* Compute a schedule for a connected dependence graph using Feautrier's
- * multi-dimensional scheduling algorithm.
+ * multi-dimensional scheduling algorithm and return the updated schedule node.
+ *
* The original algorithm is described in [1].
* The main idea is to minimize the number of scheduling dimensions, by
* trying to satisfy as many dependences as possible per scheduling dimension.
@@ -3566,10 +3620,10 @@ static int need_feautrier_step(isl_ctx *
* Problem, Part II: Multi-Dimensional Time.
* In Intl. Journal of Parallel Programming, 1992.
*/
-static int compute_schedule_wcc_feautrier(isl_ctx *ctx,
- struct isl_sched_graph *graph)
+static __isl_give isl_schedule_node *compute_schedule_wcc_feautrier(
+ isl_schedule_node *node, struct isl_sched_graph *graph)
{
- return carry_dependences(ctx, graph);
+ return carry_dependences(node, graph);
}
/* Turn off the "local" bit on all (condition) edges.
@@ -3827,7 +3881,9 @@ error:
return -1;
}
-/* Compute a schedule for a connected dependence graph.
+/* Compute a schedule for a connected dependence graph and return
+ * the updated schedule node.
+ *
* We try to find a sequence of as many schedule rows as possible that result
* in non-negative dependence distances (independent of the previous rows
* in the sequence, i.e., such that the sequence is tilable), with as
@@ -3839,12 +3895,15 @@ error:
* one row)
* - try to carry as many dependences as possible and continue with the next
* band
+ * In each case, we first insert a band node in the schedule tree
+ * if any rows have been computed.
*
* If Feautrier's algorithm is selected, we first recursively try to satisfy
* as many validity dependences as possible. When all validity dependences
* are satisfied we extend the schedule to a full-dimensional schedule.
*
- * If we manage to complete the schedule, we finish off by topologically
+ * If we manage to complete the schedule, we insert a band node
+ * (if any schedule rows were computed) and we finish off by topologically
* sorting the statements based on the remaining dependences.
*
* If ctx->opt->schedule_outer_coincidence is set, then we force the
@@ -3868,23 +3927,29 @@ error:
* Since there are only a finite number of dependences,
* there will only be a finite number of iterations.
*/
-static int compute_schedule_wcc(isl_ctx *ctx, struct isl_sched_graph *graph)
+static __isl_give isl_schedule_node *compute_schedule_wcc(
+ __isl_take isl_schedule_node *node, struct isl_sched_graph *graph)
{
int has_coincidence;
int use_coincidence;
int force_coincidence = 0;
int check_conditional;
+ isl_ctx *ctx;
+
+ if (!node)
+ return NULL;
+ ctx = isl_schedule_node_get_ctx(node);
if (detect_sccs(ctx, graph) < 0)
- return -1;
+ return isl_schedule_node_free(node);
if (sort_sccs(graph) < 0)
- return -1;
+ return isl_schedule_node_free(node);
if (compute_maxvar(graph) < 0)
- return -1;
+ return isl_schedule_node_free(node);
if (need_feautrier_step(ctx, graph))
- return compute_schedule_wcc_feautrier(ctx, graph);
+ return compute_schedule_wcc_feautrier(node, graph);
clear_local_edges(graph);
check_conditional = need_condition_check(graph);
@@ -3903,10 +3968,10 @@ static int compute_schedule_wcc(isl_ctx
graph->dst_scc = -1;
if (setup_lp(ctx, graph, use_coincidence) < 0)
- return -1;
+ return isl_schedule_node_free(node);
sol = solve_lp(graph);
if (!sol)
- return -1;
+ return isl_schedule_node_free(node);
if (sol->size == 0) {
int empty = graph->n_total_row == graph->band_start;
@@ -3916,123 +3981,98 @@ static int compute_schedule_wcc(isl_ctx
continue;
}
if (!ctx->opt->schedule_maximize_band_depth && !empty)
- return compute_next_band(ctx, graph);
+ return compute_next_band(node, graph, 1);
if (graph->src_scc >= 0)
- return compute_split_schedule(ctx, graph);
+ return compute_split_schedule(node, graph);
if (!empty)
- return compute_next_band(ctx, graph);
- return carry_dependences(ctx, graph);
+ return compute_next_band(node, graph, 1);
+ return carry_dependences(node, graph);
}
coincident = !has_coincidence || use_coincidence;
if (update_schedule(graph, sol, 1, coincident) < 0)
- return -1;
+ return isl_schedule_node_free(node);
if (!check_conditional)
continue;
violated = has_violated_conditional_constraint(ctx, graph);
if (violated < 0)
- return -1;
+ return isl_schedule_node_free(node);
if (!violated)
continue;
if (reset_band(graph) < 0)
- return -1;
+ return isl_schedule_node_free(node);
use_coincidence = has_coincidence;
}
- if (graph->n_total_row > graph->band_start)
- next_band(graph);
- return sort_statements(ctx, graph);
-}
-
-/* Add a row to the schedules that separates the SCCs and move
- * to the next band.
- */
-static int split_on_scc(isl_ctx *ctx, struct isl_sched_graph *graph)
-{
- int i;
-
- if (graph->n_total_row >= graph->max_row)
- isl_die(ctx, isl_error_internal,
- "too many schedule rows", return -1);
-
- for (i = 0; i < graph->n; ++i) {
- struct isl_sched_node *node = &graph->node[i];
- int row = isl_mat_rows(node->sched);
-
- isl_map_free(node->sched_map);
- node->sched_map = NULL;
- node->sched = isl_mat_add_zero_rows(node->sched, 1);
- node->sched = isl_mat_set_element_si(node->sched, row, 0,
- node->scc);
- if (!node->sched)
- return -1;
- node->band[graph->n_total_row] = graph->n_band;
+ if (graph->n_total_row > graph->band_start) {
+ node = insert_current_band(node, graph, 1);
+ node = isl_schedule_node_child(node, 0);
}
+ node = sort_statements(node, graph);
+ if (graph->n_total_row > graph->band_start)
+ node = isl_schedule_node_parent(node);
- graph->n_total_row++;
- next_band(graph);
-
- return 0;
+ return node;
}
-/* Compute a schedule for each component (identified by node->scc)
- * of the dependence graph separately and then combine the results.
- * Depending on the setting of schedule_fuse, a component may be
- * either weakly or strongly connected.
- *
- * The band_id is adjusted such that each component has a separate id.
- * Note that the band_id may have already been set to a value different
- * from zero by compute_split_schedule.
+/* Compute a schedule for each group of nodes identified by node->scc
+ * separately and then combine them in a sequence node (or as set node
+ * if graph->weak is set) inserted at position "node" of the schedule tree.
+ * Return the updated schedule node.
+ *
+ * If "wcc" is set then each of the groups belongs to a single
+ * weakly connected component in the dependence graph so that
+ * there is no need for compute_sub_schedule to look for weakly
+ * connected components.
*/
-static int compute_component_schedule(isl_ctx *ctx,
- struct isl_sched_graph *graph)
+static __isl_give isl_schedule_node *compute_component_schedule(
+ __isl_take isl_schedule_node *node, struct isl_sched_graph *graph,
+ int wcc)
{
- int wcc, i;
+ int component, i;
int n, n_edge;
- int n_total_row, orig_total_row;
- int n_band, orig_band;
+ int orig_total_row;
+ isl_ctx *ctx;
+ isl_union_set_list *filters;
- if (ctx->opt->schedule_fuse == ISL_SCHEDULE_FUSE_MIN ||
- ctx->opt->schedule_separate_components)
- if (split_on_scc(ctx, graph) < 0)
- return -1;
+ if (!node)
+ return NULL;
+ ctx = isl_schedule_node_get_ctx(node);
+
+ filters = extract_sccs(ctx, graph);
+ if (graph->weak)
+ node = isl_schedule_node_insert_set(node, filters);
+ else
+ node = isl_schedule_node_insert_sequence(node, filters);
- n_total_row = 0;
orig_total_row = graph->n_total_row;
- n_band = 0;
- orig_band = graph->n_band;
- for (i = 0; i < graph->n; ++i)
- graph->node[i].band_id[graph->n_band] += graph->node[i].scc;
- for (wcc = 0; wcc < graph->scc; ++wcc) {
+ for (component = 0; component < graph->scc; ++component) {
n = 0;
for (i = 0; i < graph->n; ++i)
- if (graph->node[i].scc == wcc)
+ if (graph->node[i].scc == component)
n++;
n_edge = 0;
for (i = 0; i < graph->n_edge; ++i)
- if (graph->edge[i].src->scc == wcc &&
- graph->edge[i].dst->scc == wcc)
+ if (graph->edge[i].src->scc == component &&
+ graph->edge[i].dst->scc == component)
n_edge++;
- if (compute_sub_schedule(ctx, graph, n, n_edge,
+ node = isl_schedule_node_child(node, component);
+ node = isl_schedule_node_child(node, 0);
+ node = compute_sub_schedule(node, ctx, graph, n, n_edge,
&node_scc_exactly,
- &edge_scc_exactly, wcc, 1) < 0)
- return -1;
- if (graph->n_total_row > n_total_row)
- n_total_row = graph->n_total_row;
+ &edge_scc_exactly, component, wcc);
+ node = isl_schedule_node_parent(node);
+ node = isl_schedule_node_parent(node);
graph->n_total_row = orig_total_row;
- if (graph->n_band > n_band)
- n_band = graph->n_band;
- graph->n_band = orig_band;
}
- graph->n_total_row = n_total_row;
- graph->n_band = n_band;
-
- return pad_schedule(graph);
+ return node;
}
-/* Compute a schedule for the given dependence graph.
+/* Compute a schedule for the given dependence graph and insert it at "node".
+ * Return the updated schedule node.
+ *
* We first check if the graph is connected (through validity and conditional
* validity dependences) and, if not, compute a schedule
* for each component separately.
@@ -4040,20 +4080,27 @@ static int compute_component_schedule(is
* connected components instead and compute a separate schedule for
* each such strongly connected component.
*/
-static int compute_schedule(isl_ctx *ctx, struct isl_sched_graph *graph)
+static __isl_give isl_schedule_node *compute_schedule(isl_schedule_node *node,
+ struct isl_sched_graph *graph)
{
+ isl_ctx *ctx;
+
+ if (!node)
+ return NULL;
+
+ ctx = isl_schedule_node_get_ctx(node);
if (ctx->opt->schedule_fuse == ISL_SCHEDULE_FUSE_MIN) {
if (detect_sccs(ctx, graph) < 0)
- return -1;
+ return isl_schedule_node_free(node);
} else {
if (detect_wccs(ctx, graph) < 0)
- return -1;
+ return isl_schedule_node_free(node);
}
if (graph->scc > 1)
- return compute_component_schedule(ctx, graph);
+ return compute_component_schedule(node, graph, 1);
- return compute_schedule_wcc(ctx, graph);
+ return compute_schedule_wcc(node, graph);
}
/* Compute a schedule on sc->domain that respects the given schedule
@@ -4070,6 +4117,12 @@ static int compute_schedule(isl_ctx *ctx
* then the conditional validity dependences may be violated inside
* a tilable band, provided they have no adjacent non-local
* condition dependences.
+ *
+ * The context is included in the domain before the nodes of
+ * the graphs are extracted in order to be able to exploit
+ * any possible additional equalities.
+ * However, the returned schedule contains the original domain
+ * (before this intersection).
*/
__isl_give isl_schedule *isl_schedule_constraints_compute_schedule(
__isl_take isl_schedule_constraints *sc)
@@ -4077,16 +4130,22 @@ __isl_give isl_schedule *isl_schedule_co
isl_ctx *ctx = isl_schedule_constraints_get_ctx(sc);
struct isl_sched_graph graph = { 0 };
isl_schedule *sched;
+ isl_schedule_node *node;
+ isl_union_set *domain;
struct isl_extract_edge_data data;
enum isl_edge_type i;
+ int r;
sc = isl_schedule_constraints_align_params(sc);
if (!sc)
return NULL;
graph.n = isl_union_set_n_set(sc->domain);
- if (graph.n == 0)
- goto empty;
+ if (graph.n == 0) {
+ isl_union_set *domain = isl_union_set_copy(sc->domain);
+ sched = isl_schedule_from_domain(domain);
+ goto done;
+ }
if (graph_alloc(ctx, &graph, graph.n,
isl_schedule_constraints_n_map(sc)) < 0)
goto error;
@@ -4094,7 +4153,12 @@ __isl_give isl_schedule *isl_schedule_co
goto error;
graph.root = 1;
graph.n = 0;
- if (isl_union_set_foreach_set(sc->domain, &extract_node, &graph) < 0)
+ domain = isl_union_set_copy(sc->domain);
+ domain = isl_union_set_intersect_params(domain,
+ isl_set_copy(sc->context));
+ r = isl_union_set_foreach_set(domain, &extract_node, &graph);
+ isl_union_set_free(domain);
+ if (r < 0)
goto error;
if (graph_init_table(ctx, &graph) < 0)
goto error;
@@ -4111,12 +4175,13 @@ __isl_give isl_schedule *isl_schedule_co
goto error;
}
- if (compute_schedule(ctx, &graph) < 0)
- goto error;
-
-empty:
- sched = extract_schedule(&graph, isl_union_set_get_space(sc->domain));
+ node = isl_schedule_node_from_domain(isl_union_set_copy(sc->domain));
+ node = isl_schedule_node_child(node, 0);
+ node = compute_schedule(node, &graph);
+ sched = isl_schedule_node_get_schedule(node);
+ isl_schedule_node_free(node);
+done:
graph_free(ctx, &graph);
isl_schedule_constraints_free(sc);
Modified: polly/trunk/lib/External/isl/isl_set_list.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_set_list.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_set_list.c (original)
+++ polly/trunk/lib/External/isl/isl_set_list.c Mon Feb 16 13:33:40 2015
@@ -10,6 +10,11 @@
#include <isl_list_templ.h>
+#undef EL
+#define EL isl_union_set
+
+#include <isl_list_templ.h>
+
#undef BASE
#define BASE basic_set
@@ -19,3 +24,8 @@
#define BASE set
#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE union_set
+
+#include <isl_list_templ.c>
Modified: polly/trunk/lib/External/isl/isl_stream.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_stream.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_stream.c (original)
+++ polly/trunk/lib/External/isl/isl_stream.c Mon Feb 16 13:33:40 2015
@@ -28,7 +28,7 @@ static int same_name(const void *entry,
return !strcmp(keyword->name, val);
}
-enum isl_token_type isl_stream_register_keyword(struct isl_stream *s,
+enum isl_token_type isl_stream_register_keyword(__isl_keep isl_stream *s,
const char *name)
{
struct isl_hash_table_entry *entry;
@@ -101,14 +101,15 @@ __isl_give isl_val *isl_token_get_val(is
return isl_val_int_from_isl_int(ctx, tok->u.v);
}
-/* Given a token of type ISL_TOKEN_STRING, return the string it represents.
+/* Given a token with a string representation, return a copy of this string.
*/
__isl_give char *isl_token_get_str(isl_ctx *ctx, struct isl_token *tok)
{
if (!tok)
return NULL;
- if (tok->type != ISL_TOKEN_STRING)
- isl_die(ctx, isl_error_invalid, "not a string token",
+ if (!tok->u.s)
+ isl_die(ctx, isl_error_invalid,
+ "token does not have a string representation",
return NULL);
return strdup(tok->u.s);
@@ -129,7 +130,8 @@ void isl_token_free(struct isl_token *to
free(tok);
}
-void isl_stream_error(struct isl_stream *s, struct isl_token *tok, char *msg)
+void isl_stream_error(__isl_keep isl_stream *s, struct isl_token *tok,
+ char *msg)
{
int line = tok ? tok->line : s->line;
int col = tok ? tok->col : s->col;
@@ -166,10 +168,10 @@ void isl_stream_error(struct isl_stream
}
}
-static struct isl_stream* isl_stream_new(struct isl_ctx *ctx)
+static __isl_give isl_stream* isl_stream_new(struct isl_ctx *ctx)
{
int i;
- struct isl_stream *s = isl_alloc_type(ctx, struct isl_stream);
+ isl_stream *s = isl_calloc_type(ctx, struct isl_stream);
if (!s)
return NULL;
s->ctx = ctx;
@@ -178,8 +180,9 @@ static struct isl_stream* isl_stream_new
s->str = NULL;
s->len = 0;
s->line = 1;
- s->col = 0;
+ s->col = 1;
s->eof = 0;
+ s->last_line = 0;
s->c = -1;
s->n_un = 0;
for (i = 0; i < 5; ++i)
@@ -196,18 +199,18 @@ error:
return NULL;
}
-struct isl_stream* isl_stream_new_file(struct isl_ctx *ctx, FILE *file)
+__isl_give isl_stream* isl_stream_new_file(struct isl_ctx *ctx, FILE *file)
{
- struct isl_stream *s = isl_stream_new(ctx);
+ isl_stream *s = isl_stream_new(ctx);
if (!s)
return NULL;
s->file = file;
return s;
}
-struct isl_stream* isl_stream_new_str(struct isl_ctx *ctx, const char *str)
+__isl_give isl_stream* isl_stream_new_str(struct isl_ctx *ctx, const char *str)
{
- struct isl_stream *s;
+ isl_stream *s;
if (!str)
return NULL;
s = isl_stream_new(ctx);
@@ -217,7 +220,10 @@ struct isl_stream* isl_stream_new_str(st
return s;
}
-static int stream_getc(struct isl_stream *s)
+/* Read a character from the stream and advance s->line and s->col
+ * to point to the next character.
+ */
+static int stream_getc(__isl_keep isl_stream *s)
{
int c;
if (s->eof)
@@ -233,29 +239,33 @@ static int stream_getc(struct isl_stream
}
if (c == -1)
s->eof = 1;
- if (!s->eof) {
- if (s->c == '\n') {
- s->line++;
- s->col = 0;
- } else
- s->col++;
- }
+ else if (c == '\n') {
+ s->line++;
+ s->col = 1;
+ } else
+ s->col++;
s->c = c;
return c;
}
-static void isl_stream_ungetc(struct isl_stream *s, int c)
+static void isl_stream_ungetc(__isl_keep isl_stream *s, int c)
{
isl_assert(s->ctx, s->n_un < 5, return);
s->un[s->n_un++] = c;
s->c = -1;
}
-static int isl_stream_getc(struct isl_stream *s)
+/* Read a character from the stream, skipping pairs of '\\' and '\n'.
+ * Set s->start_line and s->start_col to the line and column
+ * of the returned character.
+ */
+static int isl_stream_getc(__isl_keep isl_stream *s)
{
int c;
do {
+ s->start_line = s->line;
+ s->start_col = s->col;
c = stream_getc(s);
if (c != '\\')
return c;
@@ -267,7 +277,7 @@ static int isl_stream_getc(struct isl_st
return '\\';
}
-static int isl_stream_push_char(struct isl_stream *s, int c)
+static int isl_stream_push_char(__isl_keep isl_stream *s, int c)
{
if (s->len >= s->size) {
char *buffer;
@@ -281,13 +291,13 @@ static int isl_stream_push_char(struct i
return 0;
}
-void isl_stream_push_token(struct isl_stream *s, struct isl_token *tok)
+void isl_stream_push_token(__isl_keep isl_stream *s, struct isl_token *tok)
{
isl_assert(s->ctx, s->n_token < 5, return);
s->tokens[s->n_token++] = tok;
}
-static enum isl_token_type check_keywords(struct isl_stream *s)
+static enum isl_token_type check_keywords(__isl_keep isl_stream *s)
{
struct isl_hash_table_entry *entry;
struct isl_keyword *keyword;
@@ -344,7 +354,7 @@ static enum isl_token_type check_keyword
return ISL_TOKEN_IDENT;
}
-int isl_stream_skip_line(struct isl_stream *s)
+int isl_stream_skip_line(__isl_keep isl_stream *s)
{
int c;
@@ -355,12 +365,12 @@ int isl_stream_skip_line(struct isl_stre
return c == -1 ? -1 : 0;
}
-static struct isl_token *next_token(struct isl_stream *s, int same_line)
+static struct isl_token *next_token(__isl_keep isl_stream *s, int same_line)
{
int c;
struct isl_token *tok = NULL;
int line, col;
- int old_line = s->line;
+ int old_line = s->last_line;
if (s->n_token) {
if (same_line && s->tokens[s->n_token - 1]->on_new_line)
@@ -385,11 +395,13 @@ static struct isl_token *next_token(stru
break;
}
- line = s->line;
- col = s->col;
+ line = s->start_line;
+ col = s->start_col;
if (c == -1 || (same_line && c == '\n'))
return NULL;
+ s->last_line = line;
+
if (c == '(' ||
c == ')' ||
c == '+' ||
@@ -655,17 +667,17 @@ error:
return NULL;
}
-struct isl_token *isl_stream_next_token(struct isl_stream *s)
+struct isl_token *isl_stream_next_token(__isl_keep isl_stream *s)
{
return next_token(s, 0);
}
-struct isl_token *isl_stream_next_token_on_same_line(struct isl_stream *s)
+struct isl_token *isl_stream_next_token_on_same_line(__isl_keep isl_stream *s)
{
return next_token(s, 1);
}
-int isl_stream_eat_if_available(struct isl_stream *s, int type)
+int isl_stream_eat_if_available(__isl_keep isl_stream *s, int type)
{
struct isl_token *tok;
@@ -680,7 +692,7 @@ int isl_stream_eat_if_available(struct i
return 0;
}
-int isl_stream_next_token_is(struct isl_stream *s, int type)
+int isl_stream_next_token_is(__isl_keep isl_stream *s, int type)
{
struct isl_token *tok;
int r;
@@ -693,7 +705,7 @@ int isl_stream_next_token_is(struct isl_
return r;
}
-char *isl_stream_read_ident_if_available(struct isl_stream *s)
+char *isl_stream_read_ident_if_available(__isl_keep isl_stream *s)
{
struct isl_token *tok;
@@ -709,7 +721,7 @@ char *isl_stream_read_ident_if_available
return NULL;
}
-int isl_stream_eat(struct isl_stream *s, int type)
+int isl_stream_eat(__isl_keep isl_stream *s, int type)
{
struct isl_token *tok;
@@ -725,7 +737,7 @@ int isl_stream_eat(struct isl_stream *s,
return -1;
}
-int isl_stream_is_empty(struct isl_stream *s)
+int isl_stream_is_empty(__isl_keep isl_stream *s)
{
struct isl_token *tok;
@@ -748,7 +760,7 @@ static int free_keyword(void **p, void *
return 0;
}
-void isl_stream_flush_tokens(struct isl_stream *s)
+void isl_stream_flush_tokens(__isl_keep isl_stream *s)
{
int i;
@@ -759,7 +771,12 @@ void isl_stream_flush_tokens(struct isl_
s->n_token = 0;
}
-void isl_stream_free(struct isl_stream *s)
+isl_ctx *isl_stream_get_ctx(__isl_keep isl_stream *s)
+{
+ return s ? s->ctx : NULL;
+}
+
+void isl_stream_free(__isl_take isl_stream *s)
{
if (!s)
return;
@@ -773,6 +790,382 @@ void isl_stream_free(struct isl_stream *
isl_hash_table_foreach(s->ctx, s->keywords, &free_keyword, NULL);
isl_hash_table_free(s->ctx, s->keywords);
}
+ free(s->yaml_state);
+ free(s->yaml_indent);
isl_ctx_deref(s->ctx);
free(s);
}
+
+/* Push "state" onto the stack of currently active YAML elements.
+ * The caller is responsible for setting the corresponding indentation.
+ * Return 0 on success and -1 on failure.
+ */
+static int push_state(__isl_keep isl_stream *s, enum isl_yaml_state state)
+{
+ if (s->yaml_size < s->yaml_depth + 1) {
+ int *indent;
+ enum isl_yaml_state *state;
+
+ state = isl_realloc_array(s->ctx, s->yaml_state,
+ enum isl_yaml_state, s->yaml_depth + 1);
+ if (!state)
+ return -1;
+ s->yaml_state = state;
+
+ indent = isl_realloc_array(s->ctx, s->yaml_indent,
+ int, s->yaml_depth + 1);
+ if (!indent)
+ return -1;
+ s->yaml_indent = indent;
+
+ s->yaml_size = s->yaml_depth + 1;
+ }
+
+ s->yaml_state[s->yaml_depth] = state;
+ s->yaml_depth++;
+
+ return 0;
+}
+
+/* Remove the innermost active YAML element from the stack.
+ * Return 0 on success and -1 on failure.
+ */
+static int pop_state(__isl_keep isl_stream *s)
+{
+ if (!s)
+ return -1;
+ if (s->yaml_depth < 1)
+ isl_die(isl_stream_get_ctx(s), isl_error_invalid,
+ "not in YAML construct", return -1);
+
+ s->yaml_depth--;
+
+ return 0;
+}
+
+/* Set the state of the innermost active YAML element to "state".
+ * Return 0 on success and -1 on failure.
+ */
+static int update_state(__isl_keep isl_stream *s, enum isl_yaml_state state)
+{
+ if (!s)
+ return -1;
+ if (s->yaml_depth < 1)
+ isl_die(isl_stream_get_ctx(s), isl_error_invalid,
+ "not in YAML construct", return -1);
+
+ s->yaml_state[s->yaml_depth - 1] = state;
+
+ return 0;
+}
+
+/* Return the state of the innermost active YAML element.
+ * Return isl_yaml_none if we are not inside any YAML element.
+ */
+static enum isl_yaml_state current_state(__isl_keep isl_stream *s)
+{
+ if (!s)
+ return isl_yaml_none;
+ if (s->yaml_depth < 1)
+ return isl_yaml_none;
+ return s->yaml_state[s->yaml_depth - 1];
+}
+
+/* Set the indentation of the innermost active YAML element to "indent".
+ * If "indent" is equal to ISL_YAML_INDENT_FLOW, then this means
+ * that the current elemient is in flow format.
+ */
+static int set_yaml_indent(__isl_keep isl_stream *s, int indent)
+{
+ if (s->yaml_depth < 1)
+ isl_die(s->ctx, isl_error_internal,
+ "not in YAML element", return -1);
+
+ s->yaml_indent[s->yaml_depth - 1] = indent;
+
+ return 0;
+}
+
+/* Return the indentation of the innermost active YAML element
+ * of -1 on error.
+ */
+static int get_yaml_indent(__isl_keep isl_stream *s)
+{
+ if (s->yaml_depth < 1)
+ isl_die(s->ctx, isl_error_internal,
+ "not in YAML element", return -1);
+
+ return s->yaml_indent[s->yaml_depth - 1];
+}
+
+/* Move to the next state at the innermost level.
+ * Return 1 if successful.
+ * Return 0 if we are at the end of the innermost level.
+ * Return -1 on error.
+ *
+ * If we are in state isl_yaml_mapping_key_start, then we have just
+ * started a mapping and we are expecting a key. If the mapping started
+ * with a '{', then we check if the next token is a '}'. If so,
+ * then the mapping is empty and there is no next state at this level.
+ * Otherwise, we assume that there is at least one key (the one from
+ * which we derived the indentation in isl_stream_yaml_read_start_mapping.
+ *
+ * If we are in state isl_yaml_mapping_key, then the we expect a colon
+ * followed by a value, so there is always a next state unless
+ * some error occurs.
+ *
+ * If we are in state isl_yaml_mapping_val, then there may or may
+ * not be a subsequent key in the same mapping.
+ * In flow format, the next key is preceded by a comma.
+ * In block format, the next key has the same indentation as the first key.
+ * If the first token has a smaller indentation, then we have reached
+ * the end of the current mapping.
+ *
+ * If we are in state isl_yaml_sequence_start, then we have just
+ * started a sequence. If the sequence started with a '[',
+ * then we check if the next token is a ']'. If so, then the sequence
+ * is empty and there is no next state at this level.
+ * Otherwise, we assume that there is at least one element in the sequence
+ * (the one from which we derived the indentation in
+ * isl_stream_yaml_read_start_sequence.
+ *
+ * If we are in state isl_yaml_sequence, then there may or may
+ * not be a subsequent element in the same sequence.
+ * In flow format, the next element is preceded by a comma.
+ * In block format, the next element is introduced by a dash with
+ * the same indentation as that of the first element.
+ * If the first token is not a dash or if it has a smaller indentation,
+ * then we have reached the end of the current sequence.
+ */
+int isl_stream_yaml_next(__isl_keep isl_stream *s)
+{
+ struct isl_token *tok;
+ enum isl_yaml_state state;
+ int indent;
+
+ state = current_state(s);
+ if (state == isl_yaml_none)
+ isl_die(s->ctx, isl_error_invalid,
+ "not in YAML element", return -1);
+ switch (state) {
+ case isl_yaml_mapping_key_start:
+ if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW &&
+ isl_stream_next_token_is(s, '}'))
+ return 0;
+ if (update_state(s, isl_yaml_mapping_key) < 0)
+ return -1;
+ return 1;
+ case isl_yaml_mapping_key:
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ if (s->eof)
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return -1;
+ }
+ if (tok->type == ':') {
+ isl_token_free(tok);
+ if (update_state(s, isl_yaml_mapping_val) < 0)
+ return -1;
+ return 1;
+ }
+ isl_stream_error(s, tok, "expecting ':'");
+ isl_stream_push_token(s, tok);
+ return -1;
+ case isl_yaml_mapping_val:
+ if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW) {
+ if (!isl_stream_eat_if_available(s, ','))
+ return 0;
+ if (update_state(s, isl_yaml_mapping_key) < 0)
+ return -1;
+ return 1;
+ }
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ indent = tok->col - 1;
+ isl_stream_push_token(s, tok);
+ if (indent < get_yaml_indent(s))
+ return 0;
+ if (update_state(s, isl_yaml_mapping_key) < 0)
+ return -1;
+ return 1;
+ case isl_yaml_sequence_start:
+ if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW) {
+ if (isl_stream_next_token_is(s, ']'))
+ return 0;
+ if (update_state(s, isl_yaml_sequence) < 0)
+ return -1;
+ return 1;
+ }
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ if (s->eof)
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return -1;
+ }
+ if (tok->type == '-') {
+ isl_token_free(tok);
+ if (update_state(s, isl_yaml_sequence) < 0)
+ return -1;
+ return 1;
+ }
+ isl_stream_error(s, tok, "expecting '-'");
+ isl_stream_push_token(s, tok);
+ return 0;
+ case isl_yaml_sequence:
+ if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW)
+ return isl_stream_eat_if_available(s, ',');
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return 0;
+ indent = tok->col - 1;
+ if (indent < get_yaml_indent(s) || tok->type != '-') {
+ isl_stream_push_token(s, tok);
+ return 0;
+ }
+ isl_token_free(tok);
+ return 1;
+ default:
+ isl_die(s->ctx, isl_error_internal,
+ "unexpected state", return 0);
+ }
+}
+
+/* Start reading a YAML mapping.
+ * Return 0 on success and -1 on error.
+ *
+ * If the first token on the stream is a '{' then we remove this token
+ * from the stream and keep track of the fact that the mapping
+ * is given in flow format.
+ * Otherwise, we assume the first token is the first key of the mapping and
+ * keep track of its indentation, but keep the token on the stream.
+ * In both cases, the next token we expect is the first key of the mapping.
+ */
+int isl_stream_yaml_read_start_mapping(__isl_keep isl_stream *s)
+{
+ struct isl_token *tok;
+ int indent;
+
+ if (push_state(s, isl_yaml_mapping_key_start) < 0)
+ return -1;
+
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ if (s->eof)
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return -1;
+ }
+ if (isl_token_get_type(tok) == '{') {
+ isl_token_free(tok);
+ return set_yaml_indent(s, ISL_YAML_INDENT_FLOW);
+ }
+ indent = tok->col - 1;
+ isl_stream_push_token(s, tok);
+
+ return set_yaml_indent(s, indent);
+}
+
+/* Finish reading a YAML mapping.
+ * Return 0 on success and -1 on error.
+ *
+ * If the mapping started with a '{', then we expect a '}' to close
+ * the mapping.
+ * Otherwise, we double-check that the next token (if any)
+ * has a smaller indentation than that of the current mapping.
+ */
+int isl_stream_yaml_read_end_mapping(__isl_keep isl_stream *s)
+{
+ struct isl_token *tok;
+ int indent;
+
+ if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW) {
+ if (isl_stream_eat(s, '}') < 0)
+ return -1;
+ return pop_state(s);
+ }
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return pop_state(s);
+
+ indent = tok->col - 1;
+ isl_stream_push_token(s, tok);
+
+ if (indent >= get_yaml_indent(s))
+ isl_die(isl_stream_get_ctx(s), isl_error_invalid,
+ "mapping not finished", return -1);
+
+ return pop_state(s);
+}
+
+/* Start reading a YAML sequence.
+ * Return 0 on success and -1 on error.
+ *
+ * If the first token on the stream is a '[' then we remove this token
+ * from the stream and keep track of the fact that the sequence
+ * is given in flow format.
+ * Otherwise, we assume the first token is the dash that introduces
+ * the first element of the sequence and keep track of its indentation,
+ * but keep the token on the stream.
+ * In both cases, the next token we expect is the first element
+ * of the sequence.
+ */
+int isl_stream_yaml_read_start_sequence(__isl_keep isl_stream *s)
+{
+ struct isl_token *tok;
+ int indent;
+
+ if (push_state(s, isl_yaml_sequence_start) < 0)
+ return -1;
+
+ tok = isl_stream_next_token(s);
+ if (!tok) {
+ if (s->eof)
+ isl_stream_error(s, NULL, "unexpected EOF");
+ return -1;
+ }
+ if (isl_token_get_type(tok) == '[') {
+ isl_token_free(tok);
+ return set_yaml_indent(s, ISL_YAML_INDENT_FLOW);
+ }
+ indent = tok->col - 1;
+ isl_stream_push_token(s, tok);
+
+ return set_yaml_indent(s, indent);
+}
+
+/* Finish reading a YAML sequence.
+ * Return 0 on success and -1 on error.
+ *
+ * If the sequence started with a '[', then we expect a ']' to close
+ * the sequence.
+ * Otherwise, we double-check that the next token (if any)
+ * is not a dash or that it has a smaller indentation than
+ * that of the current sequence.
+ */
+int isl_stream_yaml_read_end_sequence(__isl_keep isl_stream *s)
+{
+ struct isl_token *tok;
+ int indent;
+ int dash;
+
+ if (get_yaml_indent(s) == ISL_YAML_INDENT_FLOW) {
+ if (isl_stream_eat(s, ']') < 0)
+ return -1;
+ return pop_state(s);
+ }
+
+ tok = isl_stream_next_token(s);
+ if (!tok)
+ return pop_state(s);
+
+ indent = tok->col - 1;
+ dash = tok->type == '-';
+ isl_stream_push_token(s, tok);
+
+ if (indent >= get_yaml_indent(s) && dash)
+ isl_die(isl_stream_get_ctx(s), isl_error_invalid,
+ "sequence not finished", return -1);
+
+ return pop_state(s);
+}
Modified: polly/trunk/lib/External/isl/isl_stream_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_stream_private.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_stream_private.h (original)
+++ polly/trunk/lib/External/isl/isl_stream_private.h Mon Feb 16 13:33:40 2015
@@ -1,5 +1,6 @@
#include <isl_int.h>
#include <isl/stream.h>
+#include <isl_yaml.h>
struct isl_token {
int type;
@@ -19,3 +20,50 @@ struct isl_token {
struct isl_token *isl_token_new(isl_ctx *ctx,
int line, int col, unsigned on_new_line);
+
+/* An input stream that may be either a file or a string.
+ *
+ * line and col are the line and column number of the next character (1-based).
+ * start_line and start_col are set by isl_stream_getc to point
+ * to the position of the returned character.
+ * last_line is the line number of the previous token.
+ *
+ * yaml_state and yaml_indent keep track of the currently active YAML
+ * elements. yaml_size is the size of these arrays, while yaml_depth
+ * is the number of elements currently in use.
+ * yaml_state and yaml_indent may be NULL if no YAML parsing is being
+ * performed.
+ * yaml_state keeps track of what is expected next at each level.
+ * yaml_indent keeps track of the indentation at each level, with
+ * ISL_YAML_INDENT_FLOW meaning that the element is in flow format
+ * (such that the indentation is not relevant).
+ */
+struct isl_stream {
+ struct isl_ctx *ctx;
+ FILE *file;
+ const char *str;
+ int line;
+ int col;
+ int start_line;
+ int start_col;
+ int last_line;
+ int eof;
+
+ char *buffer;
+ size_t size;
+ size_t len;
+ int c;
+ int un[5];
+ int n_un;
+
+ struct isl_token *tokens[5];
+ int n_token;
+
+ struct isl_hash_table *keywords;
+ enum isl_token_type next_type;
+
+ int yaml_depth;
+ int yaml_size;
+ enum isl_yaml_state *yaml_state;
+ int *yaml_indent;
+};
Modified: polly/trunk/lib/External/isl/isl_tab.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_tab.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_tab.c (original)
+++ polly/trunk/lib/External/isl/isl_tab.c Mon Feb 16 13:33:40 2015
@@ -1,12 +1,15 @@
/*
* Copyright 2008-2009 Katholieke Universiteit Leuven
* Copyright 2013 Ecole Normale Superieure
+ * Copyright 2014 INRIA Rocquencourt
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege, K.U.Leuven, Departement
* Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
* and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
+ * and Inria Paris - Rocquencourt, Domaine de Voluceau - Rocquencourt,
+ * B.P. 105 - 78153 Le Chesnay, France
*/
#include <isl_ctx_private.h>
@@ -957,6 +960,22 @@ int isl_tab_mark_redundant(struct isl_ta
}
}
+/* Mark "tab" as a rational tableau.
+ * If it wasn't marked as a rational tableau already and if we may
+ * need to undo changes, then arrange for the marking to be undone
+ * during the undo.
+ */
+int isl_tab_mark_rational(struct isl_tab *tab)
+{
+ if (!tab)
+ return -1;
+ if (!tab->rational && tab->need_undo)
+ if (isl_tab_push(tab, isl_tab_undo_rational) < 0)
+ return -1;
+ tab->rational = 1;
+ return 0;
+}
+
int isl_tab_mark_empty(struct isl_tab *tab)
{
if (!tab)
@@ -1409,7 +1428,8 @@ static int row_at_most_neg_one(struct is
/* Return 1 if "var" can attain values <= -1.
* Return 0 otherwise.
*
- * The sample value of "var" is assumed to be non-negative when the
+ * If the variable "var" is supposed to be non-negative (is_nonneg is set),
+ * then the sample value of "var" is assumed to be non-negative when the
* the function is called. If 1 is returned then the constraint
* is not redundant and the sample value is made non-negative again before
* the function returns.
@@ -1447,7 +1467,7 @@ int isl_tab_min_at_most_neg_one(struct i
do {
find_pivot(tab, var, var, -1, &row, &col);
if (row == var->index) {
- if (restore_row(tab, var) < -1)
+ if (var->is_nonneg && restore_row(tab, var) < -1)
return -1;
return 1;
}
@@ -1643,19 +1663,75 @@ int isl_tab_allocate_con(struct isl_tab
return r;
}
-/* Add a variable to the tableau and allocate a column for it.
- * Return the index into the variable array "var".
+/* Move the entries in tab->var up one position, starting at "first",
+ * creating room for an extra entry at position "first".
+ * Since some of the entries of tab->row_var and tab->col_var contain
+ * indices into this array, they have to be updated accordingly.
+ */
+static int var_insert_entry(struct isl_tab *tab, int first)
+{
+ int i;
+
+ if (tab->n_var >= tab->max_var)
+ isl_die(isl_tab_get_ctx(tab), isl_error_internal,
+ "not enough room for new variable", return -1);
+ if (first > tab->n_var)
+ isl_die(isl_tab_get_ctx(tab), isl_error_internal,
+ "invalid initial position", return -1);
+
+ for (i = tab->n_var - 1; i >= first; --i) {
+ tab->var[i + 1] = tab->var[i];
+ if (tab->var[i + 1].is_row)
+ tab->row_var[tab->var[i + 1].index]++;
+ else
+ tab->col_var[tab->var[i + 1].index]++;
+ }
+
+ tab->n_var++;
+
+ return 0;
+}
+
+/* Drop the entry at position "first" in tab->var, moving all
+ * subsequent entries down.
+ * Since some of the entries of tab->row_var and tab->col_var contain
+ * indices into this array, they have to be updated accordingly.
*/
-int isl_tab_allocate_var(struct isl_tab *tab)
+static int var_drop_entry(struct isl_tab *tab, int first)
+{
+ int i;
+
+ if (first >= tab->n_var)
+ isl_die(isl_tab_get_ctx(tab), isl_error_internal,
+ "invalid initial position", return -1);
+
+ tab->n_var--;
+
+ for (i = first; i < tab->n_var; ++i) {
+ tab->var[i] = tab->var[i + 1];
+ if (tab->var[i + 1].is_row)
+ tab->row_var[tab->var[i].index]--;
+ else
+ tab->col_var[tab->var[i].index]--;
+ }
+
+ return 0;
+}
+
+/* Add a variable to the tableau at position "r" and allocate a column for it.
+ * Return the index into the variable array "var", i.e., "r",
+ * or -1 on error.
+ */
+int isl_tab_insert_var(struct isl_tab *tab, int r)
{
- int r;
int i;
unsigned off = 2 + tab->M;
isl_assert(tab->mat->ctx, tab->n_col < tab->mat->n_col, return -1);
- isl_assert(tab->mat->ctx, tab->n_var < tab->max_var, return -1);
- r = tab->n_var;
+ if (var_insert_entry(tab, r) < 0)
+ return -1;
+
tab->var[r].index = tab->n_col;
tab->var[r].is_row = 0;
tab->var[r].is_nonneg = 0;
@@ -1668,7 +1744,6 @@ int isl_tab_allocate_var(struct isl_tab
for (i = 0; i < tab->n_row; ++i)
isl_int_set_si(tab->mat->row[i][off + tab->n_col], 0);
- tab->n_var++;
tab->n_col++;
if (isl_tab_push_var(tab, isl_tab_undo_allocate, &tab->var[r]) < 0)
return -1;
@@ -1676,6 +1751,17 @@ int isl_tab_allocate_var(struct isl_tab
return r;
}
+/* Add a variable to the tableau and allocate a column for it.
+ * Return the index into the variable array "var".
+ */
+int isl_tab_allocate_var(struct isl_tab *tab)
+{
+ if (!tab)
+ return -1;
+
+ return isl_tab_insert_var(tab, tab->n_var);
+}
+
/* Add a row to the tableau. The row is given as an affine combination
* of the original variables and needs to be expressed in terms of the
* column variables.
@@ -1753,13 +1839,22 @@ static int drop_row(struct isl_tab *tab,
return 0;
}
+/* Drop the variable in column "col" along with the column.
+ * The column is removed first because it may need to be moved
+ * into the last position and this process requires
+ * the contents of the col_var array in a state
+ * before the removal of the variable.
+ */
static int drop_col(struct isl_tab *tab, int col)
{
- isl_assert(tab->mat->ctx, tab->col_var[col] == tab->n_var - 1, return -1);
+ int var;
+
+ var = tab->col_var[col];
if (col != tab->n_col - 1)
swap_cols(tab, col, tab->n_col - 1);
tab->n_col--;
- tab->n_var--;
+ if (var_drop_entry(tab, var) < 0)
+ return -1;
return 0;
}
@@ -1982,12 +2077,9 @@ int isl_tab_add_eq(struct isl_tab *tab,
var = &tab->con[r];
row = var->index;
if (row_is_manifestly_zero(tab, row)) {
- if (snap) {
- if (isl_tab_rollback(tab, snap) < 0)
- return -1;
- } else
- drop_row(tab, row);
- return 0;
+ if (snap)
+ return isl_tab_rollback(tab, snap);
+ return drop_row(tab, row);
}
if (tab->bmap) {
@@ -2545,37 +2637,37 @@ static int cut_to_hyperplane(struct isl_
* even after the relaxation, so we need to restore it.
* We therefore prefer to pivot a column up to a row, if possible.
*/
-struct isl_tab *isl_tab_relax(struct isl_tab *tab, int con)
+int isl_tab_relax(struct isl_tab *tab, int con)
{
struct isl_tab_var *var;
- unsigned off = 2 + tab->M;
if (!tab)
- return NULL;
+ return -1;
var = &tab->con[con];
if (var->is_row && (var->index < 0 || var->index < tab->n_redundant))
isl_die(tab->mat->ctx, isl_error_invalid,
- "cannot relax redundant constraint", goto error);
+ "cannot relax redundant constraint", return -1);
if (!var->is_row && (var->index < 0 || var->index < tab->n_dead))
isl_die(tab->mat->ctx, isl_error_invalid,
- "cannot relax dead constraint", goto error);
+ "cannot relax dead constraint", return -1);
if (!var->is_row && !max_is_manifestly_unbounded(tab, var))
if (to_row(tab, var, 1) < 0)
- goto error;
+ return -1;
if (!var->is_row && !min_is_manifestly_unbounded(tab, var))
if (to_row(tab, var, -1) < 0)
- goto error;
+ return -1;
if (var->is_row) {
isl_int_add(tab->mat->row[var->index][1],
tab->mat->row[var->index][1], tab->mat->row[var->index][0]);
if (restore_row(tab, var) < 0)
- goto error;
+ return -1;
} else {
int i;
+ unsigned off = 2 + tab->M;
for (i = 0; i < tab->n_row; ++i) {
if (isl_int_is_zero(tab->mat->row[i][off + var->index]))
@@ -2587,12 +2679,67 @@ struct isl_tab *isl_tab_relax(struct isl
}
if (isl_tab_push_var(tab, isl_tab_undo_relax, var) < 0)
- goto error;
+ return -1;
- return tab;
-error:
- isl_tab_free(tab);
- return NULL;
+ return 0;
+}
+
+/* Replace the variable v at position "pos" in the tableau "tab"
+ * by v' = v + shift.
+ *
+ * If the variable is in a column, then we first check if we can
+ * simply plug in v = v' - shift. The effect on a row with
+ * coefficient f/d for variable v is that the constant term c/d
+ * is replaced by (c - f * shift)/d. If shift is positive and
+ * f is negative for each row that needs to remain non-negative,
+ * then this is clearly safe. In other words, if the minimum of v
+ * is manifestly unbounded, then we can keep v in a column position.
+ * Otherwise, we can pivot it down to a row.
+ * Similarly, if shift is negative, we need to check if the maximum
+ * of is manifestly unbounded.
+ *
+ * If the variable is in a row (from the start or after pivoting),
+ * then the constant term c/d is replaced by (c + d * shift)/d.
+ */
+int isl_tab_shift_var(struct isl_tab *tab, int pos, isl_int shift)
+{
+ struct isl_tab_var *var;
+
+ if (!tab)
+ return -1;
+ if (isl_int_is_zero(shift))
+ return 0;
+
+ var = &tab->var[pos];
+ if (!var->is_row) {
+ if (isl_int_is_neg(shift)) {
+ if (!max_is_manifestly_unbounded(tab, var))
+ if (to_row(tab, var, 1) < 0)
+ return -1;
+ } else {
+ if (!min_is_manifestly_unbounded(tab, var))
+ if (to_row(tab, var, -1) < 0)
+ return -1;
+ }
+ }
+
+ if (var->is_row) {
+ isl_int_addmul(tab->mat->row[var->index][1],
+ shift, tab->mat->row[var->index][0]);
+ } else {
+ int i;
+ unsigned off = 2 + tab->M;
+
+ for (i = 0; i < tab->n_row; ++i) {
+ if (isl_int_is_zero(tab->mat->row[i][off + var->index]))
+ continue;
+ isl_int_submul(tab->mat->row[i][1],
+ shift, tab->mat->row[i][off + var->index]);
+ }
+
+ }
+
+ return 0;
}
/* Remove the sign constraint from constraint "con".
@@ -3014,10 +3161,21 @@ enum isl_lp_result isl_tab_min(struct is
return res;
}
+/* Is the constraint at position "con" marked as being redundant?
+ * If it is marked as representing an equality, then it is not
+ * considered to be redundant.
+ * Note that isl_tab_mark_redundant marks both the isl_tab_var as
+ * redundant and moves the corresponding row into the first
+ * tab->n_redundant positions (or removes the row, assigning it index -1),
+ * so the final test is actually redundant itself.
+ */
int isl_tab_is_redundant(struct isl_tab *tab, int con)
{
if (!tab)
return -1;
+ if (con < 0 || con >= tab->n_con)
+ isl_die(isl_tab_get_ctx(tab), isl_error_invalid,
+ "position out of bounds", return -1);
if (tab->con[con].is_zero)
return 0;
if (tab->con[con].is_redundant)
@@ -3108,8 +3266,7 @@ static int perform_undo_var(struct isl_t
case isl_tab_undo_allocate:
if (undo->u.var_index >= 0) {
isl_assert(tab->mat->ctx, !var->is_row, return -1);
- drop_col(tab, var->index);
- break;
+ return drop_col(tab, var->index);
}
if (!var->is_row) {
if (!max_is_manifestly_unbounded(tab, var)) {
@@ -3122,8 +3279,7 @@ static int perform_undo_var(struct isl_t
if (to_row(tab, var, 0) < 0)
return -1;
}
- drop_row(tab, var->index);
- break;
+ return drop_row(tab, var->index);
case isl_tab_undo_relax:
return unrelax(tab, var);
case isl_tab_undo_unrestrict:
@@ -3219,6 +3375,9 @@ static int perform_undo(struct isl_tab *
static int perform_undo(struct isl_tab *tab, struct isl_tab_undo *undo)
{
switch (undo->type) {
+ case isl_tab_undo_rational:
+ tab->rational = 0;
+ break;
case isl_tab_undo_empty:
tab->empty = 0;
break;
Modified: polly/trunk/lib/External/isl/isl_tab.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_tab.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_tab.h (original)
+++ polly/trunk/lib/External/isl/isl_tab.h Mon Feb 16 13:33:40 2015
@@ -29,6 +29,7 @@ struct isl_tab_var {
enum isl_tab_undo_type {
isl_tab_undo_bottom,
+ isl_tab_undo_rational,
isl_tab_undo_empty,
isl_tab_undo_nonneg,
isl_tab_undo_redundant,
@@ -235,7 +236,7 @@ enum isl_ineq_type isl_tab_ineq_type(str
struct isl_tab_undo *isl_tab_snap(struct isl_tab *tab);
int isl_tab_rollback(struct isl_tab *tab, struct isl_tab_undo *snap) WARN_UNUSED;
-struct isl_tab *isl_tab_relax(struct isl_tab *tab, int con) WARN_UNUSED;
+int isl_tab_relax(struct isl_tab *tab, int con) WARN_UNUSED;
int isl_tab_select_facet(struct isl_tab *tab, int con) WARN_UNUSED;
int isl_tab_unrestrict(struct isl_tab *tab, int con) WARN_UNUSED;
@@ -267,6 +268,7 @@ __isl_give isl_vec *isl_tab_basic_set_no
struct isl_tab_var *isl_tab_var_from_row(struct isl_tab *tab, int i);
int isl_tab_mark_redundant(struct isl_tab *tab, int row) WARN_UNUSED;
+int isl_tab_mark_rational(struct isl_tab *tab) WARN_UNUSED;
int isl_tab_mark_empty(struct isl_tab *tab) WARN_UNUSED;
struct isl_tab *isl_tab_dup(struct isl_tab *tab);
struct isl_tab *isl_tab_product(struct isl_tab *tab1, struct isl_tab *tab2);
@@ -274,6 +276,7 @@ int isl_tab_extend_cons(struct isl_tab *
int isl_tab_allocate_con(struct isl_tab *tab) WARN_UNUSED;
int isl_tab_extend_vars(struct isl_tab *tab, unsigned n_new) WARN_UNUSED;
int isl_tab_allocate_var(struct isl_tab *tab) WARN_UNUSED;
+int isl_tab_insert_var(struct isl_tab *tab, int pos) WARN_UNUSED;
int isl_tab_pivot(struct isl_tab *tab, int row, int col) WARN_UNUSED;
int isl_tab_add_row(struct isl_tab *tab, isl_int *line) WARN_UNUSED;
int isl_tab_row_is_redundant(struct isl_tab *tab, int row);
@@ -301,4 +304,6 @@ int isl_tab_push_callback(struct isl_tab
int isl_tab_add_div(struct isl_tab *tab, __isl_keep isl_vec *div,
int (*add_ineq)(void *user, isl_int *), void *user);
+int isl_tab_shift_var(struct isl_tab *tab, int pos, isl_int shift) WARN_UNUSED;
+
#endif
Modified: polly/trunk/lib/External/isl/isl_test.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_test.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_test.c (original)
+++ polly/trunk/lib/External/isl/isl_test.c Mon Feb 16 13:33:40 2015
@@ -28,6 +28,7 @@
#include <isl/union_map.h>
#include <isl_factorization.h>
#include <isl/schedule.h>
+#include <isl/schedule_node.h>
#include <isl_options_private.h>
#include <isl/vertices.h>
#include <isl/ast_build.h>
@@ -104,11 +105,30 @@ static void test_parse_pwaff(isl_ctx *ct
isl_pw_aff_free(pwaff);
}
+/* Check that we can read an isl_multi_val from "str" without errors.
+ */
+static int test_parse_multi_val(isl_ctx *ctx, const char *str)
+{
+ isl_multi_val *mv;
+
+ mv = isl_multi_val_read_from_str(ctx, str);
+ isl_multi_val_free(mv);
+
+ return mv ? 0 : -1;
+}
+
int test_parse(struct isl_ctx *ctx)
{
isl_map *map, *map2;
const char *str, *str2;
+ if (test_parse_multi_val(ctx, "{ A[B[2] -> C[5, 7]] }") < 0)
+ return -1;
+ if (test_parse_multi_val(ctx, "[n] -> { [2] }") < 0)
+ return -1;
+ if (test_parse_multi_val(ctx, "{ A[4, infty, NaN, -1/2, 2/3] }") < 0)
+ return -1;
+
str = "{ [i] -> [-i] }";
map = isl_map_read_from_str(ctx, str);
assert(map);
@@ -1167,6 +1187,12 @@ struct {
{ "{ : 1 = 0 }", "{ : 1 = 0 }", "{ : }" },
{ "[M] -> { [x] : exists (e0 = floor((-2 + x)/3): 3e0 = -2 + x) }",
"[M] -> { [3M] }" , "[M] -> { [x] : 1 = 0 }" },
+ { "{ [m, n, a, b] : a <= 2147 + n }",
+ "{ [m, n, a, b] : (m >= 1 and n >= 1 and a <= 2148 - m and "
+ "b <= 2148 - n and b >= 0 and b >= 2149 - n - a) or "
+ "(n >= 1 and a >= 0 and b <= 2148 - n - a and "
+ "b >= 0) }",
+ "{ [m, n, ku, kl] }" },
};
static int test_gist(struct isl_ctx *ctx)
@@ -1179,20 +1205,20 @@ static int test_gist(struct isl_ctx *ctx
for (i = 0; i < ARRAY_SIZE(gist_tests); ++i) {
int equal_input;
- isl_basic_set *copy;
+ isl_set *set1, *set2, *copy;
- bset1 = isl_basic_set_read_from_str(ctx, gist_tests[i].set);
- bset2 = isl_basic_set_read_from_str(ctx, gist_tests[i].context);
- copy = isl_basic_set_copy(bset1);
- bset1 = isl_basic_set_gist(bset1, bset2);
- bset2 = isl_basic_set_read_from_str(ctx, gist_tests[i].gist);
- equal = isl_basic_set_is_equal(bset1, bset2);
- isl_basic_set_free(bset1);
- isl_basic_set_free(bset2);
- bset1 = isl_basic_set_read_from_str(ctx, gist_tests[i].set);
- equal_input = isl_basic_set_is_equal(bset1, copy);
- isl_basic_set_free(bset1);
- isl_basic_set_free(copy);
+ set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
+ set2 = isl_set_read_from_str(ctx, gist_tests[i].context);
+ copy = isl_set_copy(set1);
+ set1 = isl_set_gist(set1, set2);
+ set2 = isl_set_read_from_str(ctx, gist_tests[i].gist);
+ equal = isl_set_is_equal(set1, set2);
+ isl_set_free(set1);
+ isl_set_free(set2);
+ set1 = isl_set_read_from_str(ctx, gist_tests[i].set);
+ equal_input = isl_set_is_equal(set1, copy);
+ isl_set_free(set1);
+ isl_set_free(copy);
if (equal < 0 || equal_input < 0)
return -1;
if (!equal)
@@ -1281,31 +1307,45 @@ int test_coalesce_set(isl_ctx *ctx, cons
return 0;
}
+/* Inputs for coalescing tests with unbounded wrapping.
+ * "str" is a string representation of the input set.
+ * "single_disjunct" is set if we expect the result to consist of
+ * a single disjunct.
+ */
+struct {
+ int single_disjunct;
+ const char *str;
+} coalesce_unbounded_tests[] = {
+ { 1, "{ [x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "
+ "-x - y + 1 >= 0 and -3 <= z <= 3;"
+ "[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "
+ "x-z + 20 >= 0 and x+z + 20 >= 0 and "
+ "-10 <= y <= 0}" },
+ { 1, "{ [x,y] : 0 <= x,y <= 10; [5,y]: 4 <= y <= 11 }" },
+ { 1, "{ [x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }" },
+ { 1, "{ [x,y] : 0 <= x <= 10 and 0 >= y >= -1 and x+y >= 0; [0,1] }" },
+ { 1, "{ [x,y] : (0 <= x,y <= 4) or (2 <= x,y <= 5 and x + y <= 9) }" },
+};
+
+/* Test the functionality of isl_set_coalesce with the bounded wrapping
+ * option turned off.
+ */
int test_coalesce_unbounded_wrapping(isl_ctx *ctx)
{
+ int i;
int r = 0;
int bounded;
bounded = isl_options_get_coalesce_bounded_wrapping(ctx);
isl_options_set_coalesce_bounded_wrapping(ctx, 0);
- if (test_coalesce_set(ctx,
- "{[x,y,z] : y + 2 >= 0 and x - y + 1 >= 0 and "
- "-x - y + 1 >= 0 and -3 <= z <= 3;"
- "[x,y,z] : -x+z + 20 >= 0 and -x-z + 20 >= 0 and "
- "x-z + 20 >= 0 and x+z + 20 >= 0 and "
- "-10 <= y <= 0}", 1) < 0)
- goto error;
- if (test_coalesce_set(ctx,
- "{[x,y] : 0 <= x,y <= 10; [5,y]: 4 <=y <= 11}", 1) < 0)
- goto error;
- if (test_coalesce_set(ctx,
- "{[x,0,0] : -5 <= x <= 5; [0,y,1] : -5 <= y <= 5 }", 1) < 0)
- goto error;
-
- if (0) {
-error:
+ for (i = 0; i < ARRAY_SIZE(coalesce_unbounded_tests); ++i) {
+ const char *str = coalesce_unbounded_tests[i].str;
+ int check_one = coalesce_unbounded_tests[i].single_disjunct;
+ if (test_coalesce_set(ctx, str, check_one) >= 0)
+ continue;
r = -1;
+ break;
}
isl_options_set_coalesce_bounded_wrapping(ctx, bounded);
@@ -1431,11 +1471,106 @@ struct {
"[x,0] : 3 <= x <= 5 }" },
{ 0, "{ [x,y] : 0 <= x <= 2 and y >= 0 and x + y <= 4; "
"[x,0] : 3 <= x <= 4 }" },
- { 1 , "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "
+ { 1, "{ [i0, i1] : i0 <= 122 and i0 >= 1 and 128i1 >= -249 + i0 and "
"i1 <= 0; "
"[i0, 0] : i0 >= 123 and i0 <= 124 }" },
+ { 1, "{ [0,0]; [1,1] }" },
+ { 1, "[n] -> { [k] : 16k <= -1 + n and k >= 1; [0] : n >= 2 }" },
+ { 1, "{ [k, ii, k - ii] : ii >= -6 + k and ii <= 6 and ii >= 1 and "
+ "ii <= k;"
+ "[k, 0, k] : k <= 6 and k >= 1 }" },
+ { 1, "{ [i,j] : i = 4 j and 0 <= i <= 100;"
+ "[i,j] : 1 <= i <= 100 and i >= 4j + 1 and i <= 4j + 2 }" },
+ { 1, "{ [x,y] : x % 2 = 0 and y % 2 = 0; [x,x] : x % 2 = 0 }" },
+ { 1, "[n] -> { [1] : n >= 0;"
+ "[x] : exists (e0 = floor((x)/2): x >= 2 and "
+ "2e0 >= -1 + x and 2e0 <= x and 2e0 <= n) }" },
+ { 1, "[n] -> { [x, y] : exists (e0 = floor((x)/2), e1 = floor((y)/3): "
+ "3e1 = y and x >= 2 and 2e0 >= -1 + x and "
+ "2e0 <= x and 2e0 <= n);"
+ "[1, y] : exists (e0 = floor((y)/3): 3e0 = y and "
+ "n >= 0) }" },
+ { 1, "[t1] -> { [i0] : (exists (e0 = floor((63t1)/64): "
+ "128e0 >= -134 + 127t1 and t1 >= 2 and "
+ "64e0 <= 63t1 and 64e0 >= -63 + 63t1)) or "
+ "t1 = 1 }" },
+ { 1, "{ [i, i] : exists (e0 = floor((1 + 2i)/3): 3e0 <= 2i and "
+ "3e0 >= -1 + 2i and i <= 9 and i >= 1);"
+ "[0, 0] }" },
+ { 1, "{ [t1] : exists (e0 = floor((-11 + t1)/2): 2e0 = -11 + t1 and "
+ "t1 >= 13 and t1 <= 16);"
+ "[t1] : t1 <= 15 and t1 >= 12 }" },
+ { 1, "{ [x,y] : x = 3y and 0 <= y <= 2; [-3,-1] }" },
+ { 1, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-2] }" },
+ { 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-2,-2] }" },
+ { 0, "{ [x,y] : 2x = 3y and 0 <= y <= 4; [-3,-1] }" },
+ { 1, "{ [i] : exists j : i = 4 j and 0 <= i <= 100;"
+ "[i] : exists j : 1 <= i <= 100 and i >= 4j + 1 and "
+ "i <= 4j + 2 }" },
+ { 1, "{ [c0] : (exists (e0 : c0 - 1 <= 3e0 <= c0)) or "
+ "(exists (e0 : 3e0 = -2 + c0)) }" },
+ { 0, "[n, b0, t0] -> "
+ "{ [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12] : "
+ "(exists (e0 = floor((-32b0 + i4)/1048576), "
+ "e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
+ "n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
+ "32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 >= 8 + n and "
+ "3i4 <= -96 + 3t0 + i0 and 3i4 >= -95 - n + 3t0 + i0 and "
+ "i8 >= -157 + i0 - 4i4 and i8 >= 0 and "
+ "i8 <= -33 + i0 - 4i4 and 3i8 <= -91 + 4n - i0)) or "
+ "(exists (e0 = floor((-32b0 + i4)/1048576), "
+ "e1 = floor((i8)/32): 1048576e0 = -32b0 + i4 and 32e1 = i8 and "
+ "n <= 2147483647 and b0 <= 32767 and b0 >= 0 and "
+ "32b0 <= -2 + n and t0 <= 31 and t0 >= 0 and i0 <= 7 + n and "
+ "4i4 <= -3 + i0 and 3i4 <= -96 + 3t0 + i0 and "
+ "3i4 >= -95 - n + 3t0 + i0 and i8 >= -157 + i0 - 4i4 and "
+ "i8 >= 0 and i8 <= -4 + i0 - 3i4 and i8 <= -41 + i0));"
+ "[i0, i1, i2, i3, 0, i5, i6, i7, i8, i9, i10, i11, i12] : "
+ "(exists (e0 = floor((i8)/32): b0 = 0 and 32e0 = i8 and "
+ "n <= 2147483647 and t0 <= 31 and t0 >= 0 and i0 >= 11 and "
+ "i0 >= 96 - 3t0 and i0 <= 95 + n - 3t0 and i0 <= 7 + n and "
+ "i8 >= -40 + i0 and i8 <= -10 + i0)) }" },
};
+/* A specialized coalescing test case that would result
+ * in a segmentation fault or a failed assertion in earlier versions of isl.
+ */
+static int test_coalesce_special(struct isl_ctx *ctx)
+{
+ const char *str;
+ isl_map *map1, *map2;
+
+ str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
+ "[[S_L309_IN[] -> T11[]] -> ce_imag2[1, o1]] : "
+ "(y = 201 and o1 <= 239 and o1 >= 212) or "
+ "(exists (e0 = [(y)/3]: 3e0 = y and y <= 198 and y >= 3 and "
+ "o1 <= 239 and o1 >= 212)) or "
+ "(exists (e0 = [(y)/3]: 3e0 = y and y <= 201 and y >= 3 and "
+ "o1 <= 241 and o1 >= 240));"
+ "[S_L220_OUT[] -> T7[]] -> "
+ "[[S_L309_IN[] -> T11[]] -> ce_imag2[0, o1]] : "
+ "(y = 2 and o1 <= 241 and o1 >= 212) or "
+ "(exists (e0 = [(-2 + y)/3]: 3e0 = -2 + y and y <= 200 and "
+ "y >= 5 and o1 <= 241 and o1 >= 212)) }";
+ map1 = isl_map_read_from_str(ctx, str);
+ map1 = isl_map_align_divs(map1);
+ map1 = isl_map_coalesce(map1);
+ str = "[y] -> { [S_L220_OUT[] -> T7[]] -> "
+ "[[S_L309_IN[] -> T11[]] -> ce_imag2[o0, o1]] : "
+ "exists (e0 = [(-1 - y + o0)/3]: 3e0 = -1 - y + o0 and "
+ "y <= 201 and o0 <= 2 and o1 >= 212 and o1 <= 241 and "
+ "o0 >= 3 - y and o0 <= -2 + y and o0 >= 0) }";
+ map2 = isl_map_read_from_str(ctx, str);
+ map2 = isl_map_union(map2, map1);
+ map2 = isl_map_align_divs(map2);
+ map2 = isl_map_coalesce(map2);
+ isl_map_free(map2);
+ if (!map2)
+ return -1;
+
+ return 0;
+}
+
/* Test the functionality of isl_set_coalesce.
* That is, check that the output is always equal to the input
* and in some cases that the result consists of a single disjunct.
@@ -1453,6 +1588,8 @@ static int test_coalesce(struct isl_ctx
if (test_coalesce_unbounded_wrapping(ctx) < 0)
return -1;
+ if (test_coalesce_special(ctx) < 0)
+ return -1;
return 0;
}
@@ -2461,6 +2598,7 @@ static int test_subtract(isl_ctx *ctx)
{
int i;
isl_union_map *umap1, *umap2;
+ isl_union_pw_multi_aff *upma1, *upma2;
isl_union_set *uset;
int equal;
@@ -2482,6 +2620,24 @@ static int test_subtract(isl_ctx *ctx)
"incorrect subtract domain result", return -1);
}
+ for (i = 0; i < ARRAY_SIZE(subtract_domain_tests); ++i) {
+ upma1 = isl_union_pw_multi_aff_read_from_str(ctx,
+ subtract_domain_tests[i].minuend);
+ uset = isl_union_set_read_from_str(ctx,
+ subtract_domain_tests[i].subtrahend);
+ upma2 = isl_union_pw_multi_aff_read_from_str(ctx,
+ subtract_domain_tests[i].difference);
+ upma1 = isl_union_pw_multi_aff_subtract_domain(upma1, uset);
+ equal = isl_union_pw_multi_aff_plain_is_equal(upma1, upma2);
+ isl_union_pw_multi_aff_free(upma1);
+ isl_union_pw_multi_aff_free(upma2);
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "incorrect subtract domain result", return -1);
+ }
+
return 0;
}
@@ -2857,7 +3013,7 @@ struct {
};
/* Test schedule construction based on conditional constraints.
- * In particular, check the number of members in the outer band
+ * In particular, check the number of members in the outer band node
* as an indication of whether tiling is possible or not.
*/
static int test_conditional_schedule_constraints(isl_ctx *ctx)
@@ -2869,8 +3025,7 @@ static int test_conditional_schedule_con
isl_union_map *validity;
isl_schedule_constraints *sc;
isl_schedule *schedule;
- isl_band_list *list;
- isl_band *band;
+ isl_schedule_node *node;
int n_member;
for (i = 0; i < ARRAY_SIZE(live_range_tests); ++i) {
@@ -2889,11 +3044,12 @@ static int test_conditional_schedule_con
sc = isl_schedule_constraints_set_conditional_validity(sc,
condition, validity);
schedule = isl_schedule_constraints_compute_schedule(sc);
- list = isl_schedule_get_band_forest(schedule);
- band = isl_band_list_get_band(list, 0);
- n_member = isl_band_n_member(band);
- isl_band_free(band);
- isl_band_list_free(list);
+ node = isl_schedule_get_root(schedule);
+ while (node &&
+ isl_schedule_node_get_type(node) != isl_schedule_node_band)
+ node = isl_schedule_node_first_child(node);
+ n_member = isl_schedule_node_band_n_member(node);
+ isl_schedule_node_free(node);
isl_schedule_free(schedule);
if (!schedule)
@@ -5085,6 +5241,112 @@ static int test_dual(isl_ctx *ctx)
}
struct {
+ int scale_tile;
+ int shift_point;
+ const char *domain;
+ const char *schedule;
+ const char *sizes;
+ const char *tile;
+ const char *point;
+} tile_tests[] = {
+ { 0, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
+ "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
+ "{ [32,32] }",
+ "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
+ "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
+ },
+ { 1, 0, "[n] -> { S[i,j] : 0 <= i,j < n }",
+ "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
+ "{ [32,32] }",
+ "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
+ "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
+ },
+ { 0, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
+ "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
+ "{ [32,32] }",
+ "[{ S[i,j] -> [floor(i/32)] }, { S[i,j] -> [floor(j/32)] }]",
+ "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
+ },
+ { 1, 1, "[n] -> { S[i,j] : 0 <= i,j < n }",
+ "[{ S[i,j] -> [i] }, { S[i,j] -> [j] }]",
+ "{ [32,32] }",
+ "[{ S[i,j] -> [32*floor(i/32)] }, { S[i,j] -> [32*floor(j/32)] }]",
+ "[{ S[i,j] -> [i%32] }, { S[i,j] -> [j%32] }]",
+ },
+};
+
+/* Basic tiling tests. Create a schedule tree with a domain and a band node,
+ * tile the band and then check if the tile and point bands have the
+ * expected partial schedule.
+ */
+static int test_tile(isl_ctx *ctx)
+{
+ int i;
+ int scale;
+ int shift;
+
+ scale = isl_options_get_tile_scale_tile_loops(ctx);
+ shift = isl_options_get_tile_shift_point_loops(ctx);
+
+ for (i = 0; i < ARRAY_SIZE(tile_tests); ++i) {
+ int opt;
+ int equal;
+ const char *str;
+ isl_union_set *domain;
+ isl_multi_union_pw_aff *mupa, *mupa2;
+ isl_schedule_node *node;
+ isl_multi_val *sizes;
+
+ opt = tile_tests[i].scale_tile;
+ isl_options_set_tile_scale_tile_loops(ctx, opt);
+ opt = tile_tests[i].shift_point;
+ isl_options_set_tile_shift_point_loops(ctx, opt);
+
+ str = tile_tests[i].domain;
+ domain = isl_union_set_read_from_str(ctx, str);
+ node = isl_schedule_node_from_domain(domain);
+ node = isl_schedule_node_child(node, 0);
+ str = tile_tests[i].schedule;
+ mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
+ node = isl_schedule_node_insert_partial_schedule(node, mupa);
+ str = tile_tests[i].sizes;
+ sizes = isl_multi_val_read_from_str(ctx, str);
+ node = isl_schedule_node_band_tile(node, sizes);
+
+ str = tile_tests[i].tile;
+ mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
+ mupa2 = isl_schedule_node_band_get_partial_schedule(node);
+ equal = isl_multi_union_pw_aff_plain_is_equal(mupa, mupa2);
+ isl_multi_union_pw_aff_free(mupa);
+ isl_multi_union_pw_aff_free(mupa2);
+
+ node = isl_schedule_node_child(node, 0);
+
+ str = tile_tests[i].point;
+ mupa = isl_multi_union_pw_aff_read_from_str(ctx, str);
+ mupa2 = isl_schedule_node_band_get_partial_schedule(node);
+ if (equal >= 0 && equal)
+ equal = isl_multi_union_pw_aff_plain_is_equal(mupa,
+ mupa2);
+ isl_multi_union_pw_aff_free(mupa);
+ isl_multi_union_pw_aff_free(mupa2);
+
+ isl_schedule_node_free(node);
+
+ if (equal < 0)
+ return -1;
+ if (!equal)
+ isl_die(ctx, isl_error_unknown,
+ "unexpected result", return -1);
+ }
+
+ isl_options_set_tile_scale_tile_loops(ctx, scale);
+ isl_options_set_tile_shift_point_loops(ctx, shift);
+
+ return 0;
+}
+
+struct {
const char *name;
int (*fn)(isl_ctx *ctx);
} tests [] = {
@@ -5121,6 +5383,7 @@ struct {
{ "affine", &test_aff },
{ "injective", &test_injective },
{ "schedule", &test_schedule },
+ { "tile", &test_tile },
{ "union_pw", &test_union_pw },
{ "parse", &test_parse },
{ "single-valued", &test_sv },
Modified: polly/trunk/lib/External/isl/isl_union_map.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_union_map.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_union_map.c (original)
+++ polly/trunk/lib/External/isl/isl_union_map.c Mon Feb 16 13:33:40 2015
@@ -14,13 +14,13 @@
#define ISL_DIM_H
#include <isl_map_private.h>
+#include <isl_union_map_private.h>
#include <isl/ctx.h>
#include <isl/hash.h>
#include <isl/aff.h>
#include <isl/map.h>
#include <isl/set.h>
#include <isl_space_private.h>
-#include <isl_union_map_private.h>
#include <isl/union_set.h>
#include <isl/deprecated/union_map_int.h>
@@ -705,10 +705,28 @@ error:
return NULL;
}
+/* Intersect "umap" with the parameter domain "set".
+ *
+ * If "set" does not have any constraints, then we can return immediately.
+ */
__isl_give isl_union_map *isl_union_map_intersect_params(
__isl_take isl_union_map *umap, __isl_take isl_set *set)
{
+ int is_universe;
+
+ is_universe = isl_set_plain_is_universe(set);
+ if (is_universe < 0)
+ goto error;
+ if (is_universe) {
+ isl_set_free(set);
+ return umap;
+ }
+
return gen_bin_set_op(umap, set, &intersect_params_entry);
+error:
+ isl_union_map_free(umap);
+ isl_set_free(set);
+ return NULL;
}
__isl_give isl_union_set *isl_union_set_intersect_params(
@@ -1421,6 +1439,34 @@ __isl_give isl_union_map *isl_union_map_
return bin_op(umap1, umap2, &range_product_entry);
}
+/* If data->map A -> B and "map2" C -> D have the same range space,
+ * then add (A, C) -> (B * D) to data->res.
+ */
+static int flat_domain_product_entry(void **entry, void *user)
+{
+ struct isl_union_map_bin_data *data = user;
+ isl_map *map2 = *entry;
+
+ if (!isl_space_tuple_is_equal(data->map->dim, isl_dim_out,
+ map2->dim, isl_dim_out))
+ return 0;
+
+ map2 = isl_map_flat_domain_product(isl_map_copy(data->map),
+ isl_map_copy(map2));
+
+ data->res = isl_union_map_add_map(data->res, map2);
+
+ return 0;
+}
+
+/* Given two maps A -> B and C -> D, construct a map (A, C) -> (B * D).
+ */
+__isl_give isl_union_map *isl_union_map_flat_domain_product(
+ __isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2)
+{
+ return bin_op(umap1, umap2, &flat_domain_product_entry);
+}
+
static int flat_range_product_entry(void **entry, void *user)
{
struct isl_union_map_bin_data *data = user;
@@ -1606,6 +1652,24 @@ error:
return NULL;
}
+/* Remove redundant constraints in each of the basic maps of "umap".
+ * Since removing redundant constraints does not change the meaning
+ * or the space, the operation can be performed in-place.
+ */
+__isl_give isl_union_map *isl_union_map_remove_redundancies(
+ __isl_take isl_union_map *umap)
+{
+ return inplace(umap, &isl_map_remove_redundancies);
+}
+
+/* Remove redundant constraints in each of the basic sets of "uset".
+ */
+__isl_give isl_union_set *isl_union_set_remove_redundancies(
+ __isl_take isl_union_set *uset)
+{
+ return isl_union_map_remove_redundancies(uset);
+}
+
__isl_give isl_union_map *isl_union_map_coalesce(
__isl_take isl_union_map *umap)
{
@@ -1805,6 +1869,39 @@ __isl_give isl_union_map *isl_union_map_
return cond_un_op(umap, &domain_map_entry);
}
+/* Construct an isl_pw_multi_aff that maps "map" to its domain and
+ * add the result to "res".
+ */
+static int domain_map_upma(__isl_take isl_map *map, void *user)
+{
+ isl_union_pw_multi_aff **res = user;
+ isl_multi_aff *ma;
+ isl_pw_multi_aff *pma;
+
+ ma = isl_multi_aff_domain_map(isl_map_get_space(map));
+ pma = isl_pw_multi_aff_alloc(isl_map_wrap(map), ma);
+ *res = isl_union_pw_multi_aff_add_pw_multi_aff(*res, pma);
+
+ return *res ? 0 : -1;
+
+}
+
+/* Return an isl_union_pw_multi_aff that maps a wrapped copy of "umap"
+ * to its domain.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_map_domain_map_union_pw_multi_aff(
+ __isl_take isl_union_map *umap)
+{
+ isl_union_pw_multi_aff *res;
+
+ res = isl_union_pw_multi_aff_empty(isl_union_map_get_space(umap));
+ if (isl_union_map_foreach_map(umap, &domain_map_upma, &res) < 0)
+ res = isl_union_pw_multi_aff_free(res);
+
+ isl_union_map_free(umap);
+ return res;
+}
+
static int range_map_entry(void **entry, void *user)
{
isl_map *map = *entry;
@@ -1907,6 +2004,38 @@ __isl_give isl_union_map *isl_union_set_
return cond_un_op(uset, &identity_entry);
}
+/* Construct an identity isl_pw_multi_aff on "set" and add it to *res.
+ */
+static int identity_upma(__isl_take isl_set *set, void *user)
+{
+ isl_union_pw_multi_aff **res = user;
+ isl_space *space;
+ isl_pw_multi_aff *pma;
+
+ space = isl_space_map_from_set(isl_set_get_space(set));
+ pma = isl_pw_multi_aff_identity(space);
+ pma = isl_pw_multi_aff_intersect_domain(pma, set);
+ *res = isl_union_pw_multi_aff_add_pw_multi_aff(*res, pma);
+
+ return *res ? 0 : -1;
+}
+
+/* Return an identity function on "uset" in the form
+ * of an isl_union_pw_multi_aff.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_set_identity_union_pw_multi_aff(
+ __isl_take isl_union_set *uset)
+{
+ isl_union_pw_multi_aff *res;
+
+ res = isl_union_pw_multi_aff_empty(isl_union_set_get_space(uset));
+ if (isl_union_set_foreach_set(uset, &identity_upma, &res) < 0)
+ res = isl_union_pw_multi_aff_free(res);
+
+ isl_union_set_free(uset);
+ return res;
+}
+
/* If "map" is of the form [A -> B] -> C, then add A -> C to "res".
*/
static int domain_factor_domain_entry(void **entry, void *user)
@@ -2174,6 +2303,80 @@ int isl_union_set_is_strict_subset(__isl
return isl_union_map_is_strict_subset(uset1, uset2);
}
+/* Internal data structure for isl_union_map_is_disjoint.
+ * umap2 is the union map with which we are comparing.
+ * is_disjoint is initialized to 1 and is set to 0 as soon
+ * as the union maps turn out not to be disjoint.
+ */
+struct isl_union_map_is_disjoint_data {
+ isl_union_map *umap2;
+ int is_disjoint;
+};
+
+/* Check if "map" is disjoint from data->umap2 and abort
+ * the search if it is not.
+ */
+static int is_disjoint_entry(void **entry, void *user)
+{
+ struct isl_union_map_is_disjoint_data *data = user;
+ uint32_t hash;
+ struct isl_hash_table_entry *entry2;
+ isl_map *map = *entry;
+
+ hash = isl_space_get_hash(map->dim);
+ entry2 = isl_hash_table_find(data->umap2->dim->ctx, &data->umap2->table,
+ hash, &has_dim, map->dim, 0);
+ if (!entry2)
+ return 0;
+
+ data->is_disjoint = isl_map_is_disjoint(map, entry2->data);
+ if (data->is_disjoint < 0 || !data->is_disjoint)
+ return -1;
+
+ return 0;
+}
+
+/* Are "umap1" and "umap2" disjoint?
+ */
+int isl_union_map_is_disjoint(__isl_keep isl_union_map *umap1,
+ __isl_keep isl_union_map *umap2)
+{
+ struct isl_union_map_is_disjoint_data data = { NULL, 1 };
+
+ umap1 = isl_union_map_copy(umap1);
+ umap2 = isl_union_map_copy(umap2);
+ umap1 = isl_union_map_align_params(umap1,
+ isl_union_map_get_space(umap2));
+ umap2 = isl_union_map_align_params(umap2,
+ isl_union_map_get_space(umap1));
+
+ if (!umap1 || !umap2)
+ goto error;
+
+ data.umap2 = umap2;
+ if (isl_hash_table_foreach(umap1->dim->ctx, &umap1->table,
+ &is_disjoint_entry, &data) < 0 &&
+ data.is_disjoint)
+ goto error;
+
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+
+ return data.is_disjoint;
+error:
+ isl_union_map_free(umap1);
+ isl_union_map_free(umap2);
+ return -1;
+}
+
+/* Are "uset1" and "uset2" disjoint?
+ */
+int isl_union_set_is_disjoint(__isl_keep isl_union_set *uset1,
+ __isl_keep isl_union_set *uset2)
+{
+ return isl_union_map_is_disjoint(uset1, uset2);
+}
+
static int sample_entry(void **entry, void *user)
{
isl_basic_map **sample = (isl_basic_map **)user;
@@ -3324,6 +3527,18 @@ __isl_give isl_union_map *isl_union_map_
return data.res;
}
+/* Turn the "n" dimensions of type "type", starting at "first"
+ * into existentially quantified variables.
+ * Since the space of an isl_union_set only contains parameters,
+ * "type" is required to be equal to isl_dim_param.
+ */
+__isl_give isl_union_set *isl_union_set_project_out(
+ __isl_take isl_union_set *uset,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ return isl_union_map_project_out(uset, type, first, n);
+}
+
/* Internal data structure for isl_union_map_involves_dims.
* "first" and "n" are the arguments for the isl_map_involves_dims calls.
*/
@@ -3371,3 +3586,176 @@ int isl_union_map_involves_dims(__isl_ke
return !excludes;
}
+
+/* Internal data structure for isl_union_map_reset_range_space.
+ * "range" is the space from which to set the range space.
+ * "res" collects the results.
+ */
+struct isl_union_map_reset_range_space_data {
+ isl_space *range;
+ isl_union_map *res;
+};
+
+/* Replace the range space of "map" by the range space of data->range and
+ * add the result to data->res.
+ */
+static int reset_range_space(__isl_take isl_map *map, void *user)
+{
+ struct isl_union_map_reset_range_space_data *data = user;
+ isl_space *space;
+
+ space = isl_map_get_space(map);
+ space = isl_space_domain(space);
+ space = isl_space_extend_domain_with_range(space,
+ isl_space_copy(data->range));
+ map = isl_map_reset_space(map, space);
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return data->res ? 0 : -1;
+}
+
+/* Replace the range space of all the maps in "umap" by
+ * the range space of "space".
+ *
+ * This assumes that all maps have the same output dimension.
+ * This function should therefore not be made publicly available.
+ *
+ * Since the spaces of the maps change, so do their hash value.
+ * We therefore need to create a new isl_union_map.
+ */
+__isl_give isl_union_map *isl_union_map_reset_range_space(
+ __isl_take isl_union_map *umap, __isl_take isl_space *space)
+{
+ struct isl_union_map_reset_range_space_data data = { space };
+
+ data.res = isl_union_map_empty(isl_union_map_get_space(umap));
+ if (isl_union_map_foreach_map(umap, &reset_range_space, &data) < 0)
+ data.res = isl_union_map_free(data.res);
+
+ isl_space_free(space);
+ isl_union_map_free(umap);
+ return data.res;
+}
+
+/* Internal data structure for isl_union_map_order_at_multi_union_pw_aff.
+ * "mupa" is the function from which the isl_multi_pw_affs are extracted.
+ * "order" is applied to the extracted isl_multi_pw_affs that correspond
+ * to the domain and the range of each map.
+ * "res" collects the results.
+ */
+struct isl_union_order_at_data {
+ isl_multi_union_pw_aff *mupa;
+ __isl_give isl_map *(*order)(__isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2);
+ isl_union_map *res;
+};
+
+/* Intersect "map" with the result of applying data->order to
+ * the functions in data->mupa that apply to the domain and the range
+ * of "map" and add the result to data->res.
+ */
+static int order_at(__isl_take isl_map *map, void *user)
+{
+ struct isl_union_order_at_data *data = user;
+ isl_space *space;
+ isl_multi_pw_aff *mpa1, *mpa2;
+ isl_map *order;
+
+ space = isl_space_domain(isl_map_get_space(map));
+ mpa1 = isl_multi_union_pw_aff_extract_multi_pw_aff(data->mupa, space);
+ space = isl_space_range(isl_map_get_space(map));
+ mpa2 = isl_multi_union_pw_aff_extract_multi_pw_aff(data->mupa, space);
+ order = data->order(mpa1, mpa2);
+ map = isl_map_intersect(map, order);
+ data->res = isl_union_map_add_map(data->res, map);
+
+ return data->res ? 0 : -1;
+}
+
+/* Intersect each map in "umap" with the result of calling "order"
+ * on the functions is "mupa" that apply to the domain and the range
+ * of the map.
+ */
+static __isl_give isl_union_map *isl_union_map_order_at_multi_union_pw_aff(
+ __isl_take isl_union_map *umap, __isl_take isl_multi_union_pw_aff *mupa,
+ __isl_give isl_map *(*order)(__isl_take isl_multi_pw_aff *mpa1,
+ __isl_take isl_multi_pw_aff *mpa2))
+{
+ struct isl_union_order_at_data data;
+
+ umap = isl_union_map_align_params(umap,
+ isl_multi_union_pw_aff_get_space(mupa));
+ mupa = isl_multi_union_pw_aff_align_params(mupa,
+ isl_union_map_get_space(umap));
+ data.mupa = mupa;
+ data.order = order;
+ data.res = isl_union_map_empty(isl_union_map_get_space(umap));
+ if (isl_union_map_foreach_map(umap, &order_at, &data) < 0)
+ data.res = isl_union_map_free(data.res);
+
+ isl_multi_union_pw_aff_free(mupa);
+ isl_union_map_free(umap);
+ return data.res;
+}
+
+/* Return the subset of "umap" where the domain and the range
+ * have equal "mupa" values.
+ */
+__isl_give isl_union_map *isl_union_map_eq_at_multi_union_pw_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ return isl_union_map_order_at_multi_union_pw_aff(umap, mupa,
+ &isl_multi_pw_aff_eq_map);
+}
+
+/* Return the subset of "umap" where the domain has a lexicographically
+ * smaller "mupa" value than the range.
+ */
+__isl_give isl_union_map *isl_union_map_lex_lt_at_multi_union_pw_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ return isl_union_map_order_at_multi_union_pw_aff(umap, mupa,
+ &isl_multi_pw_aff_lex_lt_map);
+}
+
+/* Return the subset of "umap" where the domain has a lexicographically
+ * greater "mupa" value than the range.
+ */
+__isl_give isl_union_map *isl_union_map_lex_gt_at_multi_union_pw_aff(
+ __isl_take isl_union_map *umap,
+ __isl_take isl_multi_union_pw_aff *mupa)
+{
+ return isl_union_map_order_at_multi_union_pw_aff(umap, mupa,
+ &isl_multi_pw_aff_lex_gt_map);
+}
+
+/* Return the union of the elements in the list "list".
+ */
+__isl_give isl_union_set *isl_union_set_list_union(
+ __isl_take isl_union_set_list *list)
+{
+ int i, n;
+ isl_ctx *ctx;
+ isl_space *space;
+ isl_union_set *res;
+
+ if (!list)
+ return NULL;
+
+ ctx = isl_union_set_list_get_ctx(list);
+ space = isl_space_params_alloc(ctx, 0);
+ res = isl_union_set_empty(space);
+
+ n = isl_union_set_list_n_union_set(list);
+ for (i = 0; i < n; ++i) {
+ isl_union_set *uset_i;
+
+ uset_i = isl_union_set_list_get_union_set(list, i);
+ res = isl_union_set_union(res, uset_i);
+ }
+
+ isl_union_set_list_free(list);
+ return res;
+}
Modified: polly/trunk/lib/External/isl/isl_union_map_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_union_map_private.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_union_map_private.h (original)
+++ polly/trunk/lib/External/isl/isl_union_map_private.h Mon Feb 16 13:33:40 2015
@@ -1,3 +1,4 @@
+#define isl_union_set_list isl_union_map_list
#define isl_union_set isl_union_map
#include <isl/union_map.h>
#include <isl/union_set.h>
@@ -8,3 +9,6 @@ struct isl_union_map {
struct isl_hash_table table;
};
+
+__isl_give isl_union_map *isl_union_map_reset_range_space(
+ __isl_take isl_union_map *umap, __isl_take isl_space *space);
Modified: polly/trunk/lib/External/isl/isl_union_templ.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_union_templ.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_union_templ.c (original)
+++ polly/trunk/lib/External/isl/isl_union_templ.c Mon Feb 16 13:33:40 2015
@@ -1,11 +1,13 @@
/*
* Copyright 2010 INRIA Saclay
+ * Copyright 2013 Ecole Normale Superieure
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege, INRIA Saclay - Ile-de-France,
* Parc Club Orsay Universite, ZAC des vignes, 4 rue Jacques Monod,
* 91893 Orsay, France
+ * and Ecole Normale Superieure, 45 rue d'Ulm, 75230 Paris, France
*/
#define xFN(TYPE,NAME) TYPE ## _ ## NAME
@@ -116,13 +118,20 @@ __isl_give UNION *FN(UNION,copy)(__isl_k
return u;
}
+/* Return the number of base expressions in "u".
+ */
+int FN(FN(UNION,n),PARTS)(__isl_keep UNION *u)
+{
+ return u ? u->table.n : 0;
+}
+
S(UNION,foreach_data)
{
int (*fn)(__isl_take PART *part, void *user);
void *user;
};
-static int call_on_copy(void **entry, void *user)
+static int FN(UNION,call_on_copy)(void **entry, void *user)
{
PART *part = *entry;
S(UNION,foreach_data) *data = (S(UNION,foreach_data) *)user;
@@ -139,12 +148,12 @@ int FN(FN(UNION,foreach),PARTS)(__isl_ke
return -1;
return isl_hash_table_foreach(u->space->ctx, &u->table,
- &call_on_copy, &data);
+ &FN(UNION,call_on_copy), &data);
}
/* Is the space of "entry" equal to "space"?
*/
-static int has_space(const void *entry, const void *val)
+static int FN(UNION,has_space)(const void *entry, const void *val)
{
PART *part = (PART *)entry;
isl_space *space = (isl_space *) val;
@@ -154,12 +163,12 @@ static int has_space(const void *entry,
/* This function is not currently used by isl_aff.c.
*/
-static int has_domain_space(const void *entry, const void *val)
+static int FN(UNION,has_domain_space)(const void *entry, const void *val)
__attribute__ ((unused));
/* Is the domain space of "entry" equal to "space"?
*/
-static int has_domain_space(const void *entry, const void *val)
+static int FN(UNION,has_domain_space)(const void *entry, const void *val)
{
PART *part = (PART *)entry;
isl_space *space = (isl_space *) val;
@@ -173,7 +182,7 @@ static int has_domain_space(const void *
/* Is the domain space of "entry" equal to the domain of "space"?
*/
-static int has_same_domain_space(const void *entry, const void *val)
+static int FN(UNION,has_same_domain_space)(const void *entry, const void *val)
{
PART *part = (PART *)entry;
isl_space *space = (isl_space *) val;
@@ -209,7 +218,7 @@ __isl_give PART *FN(FN(UNION,extract),PA
hash = isl_space_get_hash(space);
entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
- &has_space, space, 0);
+ &FN(UNION,has_space), space, 0);
if (!entry)
#ifdef HAS_TYPE
return FN(PART,ZERO)(space, u->type);
@@ -257,7 +266,8 @@ static __isl_give UNION *FN(UNION,add_pa
hash = isl_space_get_hash(part->dim);
entry = isl_hash_table_find(u->space->ctx, &u->table, hash,
- &has_same_domain_space, part->dim, 1);
+ &FN(UNION,has_same_domain_space),
+ part->dim, 1);
if (!entry)
goto error;
@@ -304,7 +314,7 @@ __isl_give UNION *FN(FN(UNION,add),PARTS
return FN(UNION,add_part_generic)(u, part, 1);
}
-static int add_part(__isl_take PART *part, void *user)
+static int FN(UNION,add_part)(__isl_take PART *part, void *user)
{
UNION **u = (UNION **)user;
@@ -325,7 +335,7 @@ __isl_give UNION *FN(UNION,dup)(__isl_ke
#else
dup = FN(UNION,ZERO)(isl_space_copy(u->space));
#endif
- if (FN(FN(UNION,foreach),PARTS)(u, &add_part, &dup) < 0)
+ if (FN(FN(UNION,foreach),PARTS)(u, &FN(UNION,add_part), &dup) < 0)
goto error;
return dup;
error:
@@ -344,7 +354,7 @@ __isl_give UNION *FN(UNION,cow)(__isl_ta
return FN(UNION,dup)(u);
}
-static int free_u_entry(void **entry, void *user)
+static int FN(UNION,free_u_entry)(void **entry, void *user)
{
PART *part = *entry;
FN(PART,free)(part);
@@ -359,7 +369,8 @@ __isl_null UNION *FN(UNION,free)(__isl_t
if (--u->ref > 0)
return NULL;
- isl_hash_table_foreach(u->space->ctx, &u->table, &free_u_entry, NULL);
+ isl_hash_table_foreach(u->space->ctx, &u->table,
+ &FN(UNION,free_u_entry), NULL);
isl_hash_table_clear(&u->table);
isl_space_free(u->space);
free(u);
@@ -371,8 +382,7 @@ S(UNION,align) {
UNION *res;
};
-#ifdef ALIGN_DOMAIN
-static int align_entry(__isl_take PART *part, void *user)
+static int FN(UNION,align_entry)(__isl_take PART *part, void *user)
{
isl_reordering *exp;
S(UNION,align) *data = user;
@@ -385,26 +395,41 @@ static int align_entry(__isl_take PART *
return 0;
}
-#else
-static int align_entry(__isl_take PART *part, void *user)
+
+/* Reorder the parameters of "u" according to the given reordering.
+ */
+static __isl_give UNION *FN(UNION,realign_domain)(__isl_take UNION *u,
+ __isl_take isl_reordering *r)
{
- isl_reordering *exp;
- S(UNION,align) *data = user;
+ S(UNION,align) data = { NULL, NULL };
- exp = isl_reordering_extend_space(isl_reordering_copy(data->exp),
- FN(PART,get_space)(part));
+ if (!u || !r)
+ goto error;
- data->res = FN(FN(UNION,add),PARTS)(data->res,
- FN(PART,realign)(part, exp));
+#ifdef HAS_TYPE
+ data.res = FN(UNION,alloc)(isl_space_copy(r->dim), u->type, u->table.n);
+#else
+ data.res = FN(UNION,alloc)(isl_space_copy(r->dim), u->table.n);
+#endif
+ data.exp = r;
+ if (FN(FN(UNION,foreach),PARTS)(u, &FN(UNION,align_entry), &data) < 0)
+ data.res = FN(UNION,free)(data.res);
- return 0;
+ isl_reordering_free(data.exp);
+ FN(UNION,free)(u);
+ return data.res;
+error:
+ FN(UNION,free)(u);
+ isl_reordering_free(r);
+ return NULL;
}
-#endif
+/* Align the parameters of "u" to those of "model".
+ */
__isl_give UNION *FN(UNION,align_params)(__isl_take UNION *u,
__isl_take isl_space *model)
{
- S(UNION,align) data = { NULL, NULL };
+ isl_reordering *r;
if (!u || !model)
goto error;
@@ -415,35 +440,20 @@ __isl_give UNION *FN(UNION,align_params)
}
model = isl_space_params(model);
- data.exp = isl_parameter_alignment_reordering(u->space, model);
- if (!data.exp)
- goto error;
-
-#ifdef HAS_TYPE
- data.res = FN(UNION,alloc)(isl_space_copy(data.exp->dim),
- u->type, u->table.n);
-#else
- data.res = FN(UNION,alloc)(isl_space_copy(data.exp->dim), u->table.n);
-#endif
- if (FN(FN(UNION,foreach),PARTS)(u, &align_entry, &data) < 0)
- goto error;
-
- isl_reordering_free(data.exp);
- FN(UNION,free)(u);
+ r = isl_parameter_alignment_reordering(u->space, model);
isl_space_free(model);
- return data.res;
+
+ return FN(UNION,realign_domain)(u, r);
error:
- isl_reordering_free(data.exp);
- FN(UNION,free)(u);
- FN(UNION,free)(data.res);
isl_space_free(model);
+ FN(UNION,free)(u);
return NULL;
}
/* Add "part" to *u, taking the union sum if "u" already has
* a part defined on the same space as "part".
*/
-static int union_add_part(__isl_take PART *part, void *user)
+static int FN(UNION,union_add_part)(__isl_take PART *part, void *user)
{
UNION **u = (UNION **)user;
@@ -473,7 +483,7 @@ static __isl_give UNION *FN(UNION,union_
if (!u1 || !u2)
goto error;
- if (FN(FN(UNION,foreach),PARTS)(u2, &union_add_part, &u1) < 0)
+ if (FN(FN(UNION,foreach),PARTS)(u2, &FN(UNION,union_add_part), &u1) < 0)
goto error;
FN(UNION,free)(u2);
@@ -516,7 +526,7 @@ S(UNION,match_bin_data) {
* If so, call data->fn on the two elements and add the result to
* data->res.
*/
-static int match_bin_entry(void **entry, void *user)
+static int FN(UNION,match_bin_entry)(void **entry, void *user)
{
S(UNION,match_bin_data) *data = user;
uint32_t hash;
@@ -528,7 +538,8 @@ static int match_bin_entry(void **entry,
space = FN(PART,get_space)(part);
hash = isl_space_get_hash(space);
entry2 = isl_hash_table_find(data->u2->space->ctx, &data->u2->table,
- hash, &has_same_domain_space, space, 0);
+ hash, &FN(UNION,has_same_domain_space),
+ space, 0);
isl_space_free(space);
if (!entry2)
return 0;
@@ -553,14 +564,14 @@ static int match_bin_entry(void **entry,
/* This function is currently only used from isl_polynomial.c
* and not from isl_fold.c.
*/
-static __isl_give UNION *match_bin_op(__isl_take UNION *u1,
+static __isl_give UNION *FN(UNION,match_bin_op)(__isl_take UNION *u1,
__isl_take UNION *u2,
__isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *))
__attribute__ ((unused));
/* For each pair of elements in "u1" and "u2" living in the same space,
* call "fn" and collect the results.
*/
-static __isl_give UNION *match_bin_op(__isl_take UNION *u1,
+static __isl_give UNION *FN(UNION,match_bin_op)(__isl_take UNION *u1,
__isl_take UNION *u2,
__isl_give PART *(*fn)(__isl_take PART *, __isl_take PART *))
{
@@ -580,7 +591,7 @@ static __isl_give UNION *match_bin_op(__
data.res = FN(UNION,alloc)(isl_space_copy(u1->space), u1->table.n);
#endif
if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
- &match_bin_entry, &data) < 0)
+ &FN(UNION,match_bin_entry), &data) < 0)
goto error;
FN(UNION,free)(u1);
@@ -604,7 +615,7 @@ __isl_give UNION *FN(UNION,add)(__isl_ta
#if DEFAULT_IS_ZERO
return FN(UNION,union_add_)(u1, u2);
#else
- return match_bin_op(u1, u2, &FN(PART,add));
+ return FN(UNION,match_bin_op)(u1, u2, &FN(PART,add));
#endif
}
@@ -613,7 +624,7 @@ __isl_give UNION *FN(UNION,add)(__isl_ta
*/
__isl_give UNION *FN(UNION,sub)(__isl_take UNION *u1, __isl_take UNION *u2)
{
- return match_bin_op(u1, u2, &FN(PART,sub));
+ return FN(UNION,match_bin_op)(u1, u2, &FN(PART,sub));
}
#endif
@@ -623,7 +634,7 @@ S(UNION,any_set_data) {
__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
};
-static int any_set_entry(void **entry, void *user)
+static int FN(UNION,any_set_entry)(void **entry, void *user)
{
S(UNION,any_set_data) *data = user;
PW *pw = *entry;
@@ -640,7 +651,7 @@ static int any_set_entry(void **entry, v
/* Update each element of "u" by calling "fn" on the element and "set".
*/
-static __isl_give UNION *any_set_op(__isl_take UNION *u,
+static __isl_give UNION *FN(UNION,any_set_op)(__isl_take UNION *u,
__isl_take isl_set *set,
__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
{
@@ -660,7 +671,7 @@ static __isl_give UNION *any_set_op(__is
data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->table.n);
#endif
if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &any_set_entry, &data) < 0)
+ &FN(UNION,any_set_entry), &data) < 0)
goto error;
FN(UNION,free)(u);
@@ -678,7 +689,7 @@ error:
__isl_give UNION *FN(UNION,intersect_params)(__isl_take UNION *u,
__isl_take isl_set *set)
{
- return any_set_op(u, set, &FN(PW,intersect_params));
+ return FN(UNION,any_set_op)(u, set, &FN(PW,intersect_params));
}
/* Compute the gist of the domain of "u" with respect to
@@ -687,7 +698,7 @@ __isl_give UNION *FN(UNION,intersect_par
__isl_give UNION *FN(UNION,gist_params)(__isl_take UNION *u,
__isl_take isl_set *set)
{
- return any_set_op(u, set, &FN(PW,gist_params));
+ return FN(UNION,any_set_op)(u, set, &FN(PW,gist_params));
}
S(UNION,match_domain_data) {
@@ -696,7 +707,7 @@ S(UNION,match_domain_data) {
__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*);
};
-static int set_has_dim(const void *entry, const void *val)
+static int FN(UNION,set_has_dim)(const void *entry, const void *val)
{
isl_set *set = (isl_set *)entry;
isl_space *dim = (isl_space *)val;
@@ -708,7 +719,7 @@ static int set_has_dim(const void *entry
* of *entry, apply data->fn to *entry and this set (if any), and add
* the result to data->res.
*/
-static int match_domain_entry(void **entry, void *user)
+static int FN(UNION,match_domain_entry)(void **entry, void *user)
{
S(UNION,match_domain_data) *data = user;
uint32_t hash;
@@ -719,7 +730,7 @@ static int match_domain_entry(void **ent
space = FN(PW,get_domain_space)(pw);
hash = isl_space_get_hash(space);
entry2 = isl_hash_table_find(data->uset->dim->ctx, &data->uset->table,
- hash, &set_has_dim, space, 0);
+ hash, &FN(UNION,set_has_dim), space, 0);
isl_space_free(space);
if (!entry2)
return 0;
@@ -738,7 +749,7 @@ static int match_domain_entry(void **ent
* the set lives in the same space as the domain of PW
* and collect the results.
*/
-static __isl_give UNION *match_domain_op(__isl_take UNION *u,
+static __isl_give UNION *FN(UNION,match_domain_op)(__isl_take UNION *u,
__isl_take isl_union_set *uset,
__isl_give PW *(*fn)(__isl_take PW*, __isl_take isl_set*))
{
@@ -758,7 +769,7 @@ static __isl_give UNION *match_domain_op
data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->table.n);
#endif
if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &match_domain_entry, &data) < 0)
+ &FN(UNION,match_domain_entry), &data) < 0)
goto error;
FN(UNION,free)(u);
@@ -781,7 +792,64 @@ __isl_give UNION *FN(UNION,intersect_dom
if (isl_union_set_is_params(uset))
return FN(UNION,intersect_params)(u,
isl_set_from_union_set(uset));
- return match_domain_op(u, uset, &FN(PW,intersect_domain));
+ return FN(UNION,match_domain_op)(u, uset, &FN(PW,intersect_domain));
+}
+
+/* Internal data structure for isl_union_*_subtract_domain.
+ * uset is the set that needs to be removed from the domain.
+ * res collects the results.
+ */
+S(UNION,subtract_domain_data) {
+ isl_union_set *uset;
+ UNION *res;
+};
+
+/* Take the set (which may be empty) in data->uset that lives
+ * in the same space as the domain of "pw", subtract it from the domain
+ * of "pw" and add the result to data->res.
+ */
+static int FN(UNION,subtract_domain_entry)(__isl_take PW *pw, void *user)
+{
+ S(UNION,subtract_domain_data) *data = user;
+ isl_space *space;
+ isl_set *set;
+
+ space = FN(PW,get_domain_space)(pw);
+ set = isl_union_set_extract_set(data->uset, space);
+ pw = FN(PW,subtract_domain)(pw, set);
+ data->res = FN(FN(UNION,add),PARTS)(data->res, pw);
+
+ return 0;
+}
+
+/* Subtract "uset' from the domain of "u".
+ */
+__isl_give UNION *FN(UNION,subtract_domain)(__isl_take UNION *u,
+ __isl_take isl_union_set *uset)
+{
+ S(UNION,subtract_domain_data) data;
+
+ if (!u || !uset)
+ goto error;
+
+ data.uset = uset;
+#ifdef HAS_TYPE
+ data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->type,
+ u->table.n);
+#else
+ data.res = FN(UNION,alloc)(isl_space_copy(u->space), u->table.n);
+#endif
+ if (FN(FN(UNION,foreach),PARTS)(u,
+ &FN(UNION,subtract_domain_entry), &data) < 0)
+ data.res = FN(UNION,free)(data.res);
+
+ FN(UNION,free)(u);
+ isl_union_set_free(uset);
+ return data.res;
+error:
+ FN(UNION,free)(u);
+ isl_union_set_free(uset);
+ return NULL;
}
__isl_give UNION *FN(UNION,gist)(__isl_take UNION *u,
@@ -789,7 +857,7 @@ __isl_give UNION *FN(UNION,gist)(__isl_t
{
if (isl_union_set_is_params(uset))
return FN(UNION,gist_params)(u, isl_set_from_union_set(uset));
- return match_domain_op(u, uset, &FN(PW,gist));
+ return FN(UNION,match_domain_op)(u, uset, &FN(PW,gist));
}
#ifndef NO_EVAL
@@ -809,7 +877,8 @@ __isl_give isl_val *FN(UNION,eval)(__isl
goto error;
hash = isl_space_get_hash(space);
entry = isl_hash_table_find(u->space->ctx, &u->table,
- hash, &has_domain_space, space, 0);
+ hash, &FN(UNION,has_domain_space),
+ space, 0);
isl_space_free(space);
if (!entry) {
v = isl_val_zero(isl_point_get_ctx(pnt));
@@ -826,7 +895,7 @@ error:
}
#endif
-static int coalesce_entry(void **entry, void *user)
+static int FN(UNION,coalesce_entry)(void **entry, void *user)
{
PW **pw = (PW **)entry;
@@ -843,7 +912,7 @@ __isl_give UNION *FN(UNION,coalesce)(__i
return NULL;
if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &coalesce_entry, NULL) < 0)
+ &FN(UNION,coalesce_entry), NULL) < 0)
goto error;
return u;
@@ -852,7 +921,7 @@ error:
return NULL;
}
-static int domain(__isl_take PART *part, void *user)
+static int FN(UNION,domain_entry)(__isl_take PART *part, void *user)
{
isl_union_set **uset = (isl_union_set **)user;
@@ -866,7 +935,7 @@ __isl_give isl_union_set *FN(UNION,domai
isl_union_set *uset;
uset = isl_union_set_empty(FN(UNION,get_space)(u));
- if (FN(FN(UNION,foreach),PARTS)(u, &domain, &uset) < 0)
+ if (FN(FN(UNION,foreach),PARTS)(u, &FN(UNION,domain_entry), &uset) < 0)
goto error;
FN(UNION,free)(u);
@@ -878,7 +947,7 @@ error:
return NULL;
}
-static int mul_isl_int(void **entry, void *user)
+static int FN(UNION,mul_isl_int_entry)(void **entry, void *user)
{
PW **pw = (PW **)entry;
isl_int *v = user;
@@ -916,7 +985,7 @@ __isl_give UNION *FN(UNION,mul_isl_int)(
u->type = isl_fold_type_negate(u->type);
#endif
if (isl_hash_table_foreach(u->space->ctx, &u->table,
- &mul_isl_int, &v) < 0)
+ &FN(UNION,mul_isl_int_entry), v) < 0)
goto error;
return u;
@@ -929,7 +998,7 @@ error:
*
* Return 0 on success and -1 on error.
*/
-static int scale_val(void **entry, void *user)
+static int FN(UNION,scale_val_entry)(void **entry, void *user)
{
PW **pw = (PW **)entry;
isl_val *v = user;
@@ -978,7 +1047,8 @@ __isl_give UNION *FN(UNION,scale_val)(__
if (isl_val_is_neg(v))
u->type = isl_fold_type_negate(u->type);
#endif
- if (isl_hash_table_foreach(u->space->ctx, &u->table, &scale_val, v) < 0)
+ if (isl_hash_table_foreach(u->space->ctx, &u->table,
+ &FN(UNION,scale_val_entry), v) < 0)
goto error;
isl_val_free(v);
@@ -1050,7 +1120,7 @@ S(UNION,plain_is_equal_data)
int is_equal;
};
-static int plain_is_equal_entry(void **entry, void *user)
+static int FN(UNION,plain_is_equal_entry)(void **entry, void *user)
{
S(UNION,plain_is_equal_data) *data = user;
uint32_t hash;
@@ -1059,7 +1129,8 @@ static int plain_is_equal_entry(void **e
hash = isl_space_get_hash(pw->dim);
entry2 = isl_hash_table_find(data->u2->space->ctx, &data->u2->table,
- hash, &has_same_domain_space, pw->dim, 0);
+ hash, &FN(UNION,has_same_domain_space),
+ pw->dim, 0);
if (!entry2) {
data->is_equal = 0;
return -1;
@@ -1092,7 +1163,7 @@ int FN(UNION,plain_is_equal)(__isl_keep
data.u2 = u2;
if (isl_hash_table_foreach(u1->space->ctx, &u1->table,
- &plain_is_equal_entry, &data) < 0 &&
+ &FN(UNION,plain_is_equal_entry), &data) < 0 &&
data.is_equal)
goto error;
@@ -1105,3 +1176,196 @@ error:
FN(UNION,free)(u2);
return -1;
}
+
+#ifndef NO_NEG
+/* Replace *entry by its opposite.
+ *
+ * Return 0 on success and -1 on error.
+ */
+static int FN(UNION,neg_entry)(void **entry, void *user)
+{
+ PW **pw = (PW **) entry;
+
+ *pw = FN(PW,neg)(*pw);
+
+ return *pw ? 0 : -1;
+}
+
+/* Return the opposite of "u".
+ */
+__isl_give UNION *FN(UNION,neg)(__isl_take UNION *u)
+{
+ u = FN(UNION,cow)(u);
+ if (!u)
+ return NULL;
+
+ if (isl_hash_table_foreach(u->space->ctx, &u->table,
+ &FN(UNION,neg_entry), NULL) < 0)
+ return FN(UNION,free)(u);
+
+ return u;
+}
+#endif
+
+/* Internal data structure for isl_union_*_drop_dims.
+ * type, first and n are passed to isl_*_drop_dims.
+ * res collects the results.
+ */
+S(UNION,drop_dims_data) {
+ enum isl_dim_type type;
+ unsigned first;
+ unsigned n;
+
+ UNION *res;
+};
+
+/* Drop the parameters specified by "data" from "part" and
+ * add the results to data->res.
+ */
+static int FN(UNION,drop_dims_entry)(__isl_take PART *part, void *user)
+{
+ S(UNION,drop_dims_data) *data = user;
+
+ part = FN(PART,drop_dims)(part, data->type, data->first, data->n);
+ data->res = FN(FN(UNION,add),PARTS)(data->res, part);
+ if (!data->res)
+ return -1;
+
+ return 0;
+}
+
+/* Drop the specified parameters from "u".
+ * That is, type is required to be isl_dim_param.
+ */
+__isl_give UNION *FN(UNION,drop_dims)( __isl_take UNION *u,
+ enum isl_dim_type type, unsigned first, unsigned n)
+{
+ isl_space *space;
+ S(UNION,drop_dims_data) data = { type, first, n };
+
+ if (!u)
+ return NULL;
+
+ if (type != isl_dim_param)
+ isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
+ "can only project out parameters",
+ return FN(UNION,free)(u));
+
+ space = FN(UNION,get_space)(u);
+ space = isl_space_drop_dims(space, type, first, n);
+#ifdef HAS_TYPE
+ data.res = FN(UNION,alloc)(space, u->type, u->table.n);
+#else
+ data.res = FN(UNION,alloc)(space, u->table.n);
+#endif
+ if (FN(FN(UNION,foreach),PARTS)(u,
+ &FN(UNION,drop_dims_entry), &data) < 0)
+ data.res = FN(UNION,free)(data.res);
+
+ FN(UNION,free)(u);
+
+ return data.res;
+}
+
+/* Internal data structure for isl_union_*_set_dim_name.
+ * pos is the position of the parameter that needs to be renamed.
+ * s is the new name.
+ * res collects the results.
+ */
+S(UNION,set_dim_name_data) {
+ unsigned pos;
+ const char *s;
+
+ UNION *res;
+};
+
+/* Change the name of the parameter at position data->pos of "part" to data->s
+ * and add the result to data->res.
+ */
+static int FN(UNION,set_dim_name_entry)(__isl_take PART *part, void *user)
+{
+ S(UNION,set_dim_name_data) *data = user;
+
+ part = FN(PART,set_dim_name)(part, isl_dim_param, data->pos, data->s);
+ data->res = FN(FN(UNION,add),PARTS)(data->res, part);
+ if (!data->res)
+ return -1;
+
+ return 0;
+}
+
+/* Change the name of the parameter at position "pos" to "s".
+ * That is, type is required to be isl_dim_param.
+ */
+__isl_give UNION *FN(UNION,set_dim_name)(__isl_take UNION *u,
+ enum isl_dim_type type, unsigned pos, const char *s)
+{
+ S(UNION,set_dim_name_data) data = { pos, s };
+ isl_space *space;
+
+ if (!u)
+ return NULL;
+
+ if (type != isl_dim_param)
+ isl_die(FN(UNION,get_ctx)(u), isl_error_invalid,
+ "can only set parameter names",
+ return FN(UNION,free)(u));
+
+ space = FN(UNION,get_space)(u);
+ space = isl_space_set_dim_name(space, type, pos, s);
+#ifdef HAS_TYPE
+ data.res = FN(UNION,alloc)(space, u->type, u->table.n);
+#else
+ data.res = FN(UNION,alloc)(space, u->table.n);
+#endif
+
+ if (FN(FN(UNION,foreach),PARTS)(u,
+ &FN(UNION,set_dim_name_entry), &data) < 0)
+ data.res = FN(UNION,free)(data.res);
+
+ FN(UNION,free)(u);
+
+ return data.res;
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the space of "part" and add the result to *res.
+ */
+static int FN(UNION,reset_user_entry)(__isl_take PART *part, void *user)
+{
+ UNION **res = user;
+
+ part = FN(PART,reset_user)(part);
+ *res = FN(FN(UNION,add),PARTS)(*res, part);
+ if (!*res)
+ return -1;
+
+ return 0;
+}
+
+/* Reset the user pointer on all identifiers of parameters and tuples
+ * of the spaces of "u".
+ */
+__isl_give UNION *FN(UNION,reset_user)(__isl_take UNION *u)
+{
+ isl_space *space;
+ UNION *res;
+
+ if (!u)
+ return NULL;
+
+ space = FN(UNION,get_space)(u);
+ space = isl_space_reset_user(space);
+#ifdef HAS_TYPE
+ res = FN(UNION,alloc)(space, u->type, u->table.n);
+#else
+ res = FN(UNION,alloc)(space, u->table.n);
+#endif
+ if (FN(FN(UNION,foreach),PARTS)(u,
+ &FN(UNION,reset_user_entry), &res) < 0)
+ res = FN(UNION,free)(res);
+
+ FN(UNION,free)(u);
+
+ return res;
+}
Modified: polly/trunk/lib/External/isl/isl_val.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_val.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_val.c (original)
+++ polly/trunk/lib/External/isl/isl_val.c Mon Feb 16 13:33:40 2015
@@ -936,6 +936,18 @@ error:
return NULL;
}
+/* Given two integer values "v1" and "v2", return the residue of "v1"
+ * modulo "v2".
+ *
+ * This is a private copy of isl_val_mod for use in the generic
+ * isl_multi_*_mod_multi_val instantiated for isl_val.
+ */
+__isl_give isl_val *isl_val_mod_val(__isl_take isl_val *v1,
+ __isl_take isl_val *v2)
+{
+ return isl_val_mod(v1, v2);
+}
+
/* Given two integer values, return their greatest common divisor.
*/
__isl_give isl_val *isl_val_gcd(__isl_take isl_val *v1, __isl_take isl_val *v2)
@@ -1566,8 +1578,6 @@ int isl_val_check_match_domain_space(__i
#define BASE val
#define NO_DOMAIN
-#define NO_INTERSECT_DOMAIN
-#define NO_GIST
#define NO_IDENTITY
#define NO_FROM_BASE
#define NO_MOVE_DIMS
Modified: polly/trunk/lib/External/isl/isl_val_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_val_private.h?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/isl_val_private.h (original)
+++ polly/trunk/lib/External/isl/isl_val_private.h Mon Feb 16 13:33:40 2015
@@ -55,6 +55,8 @@ __isl_give isl_val *isl_val_scale_val(__
__isl_take isl_val *v2);
__isl_give isl_val *isl_val_scale_down_val(__isl_take isl_val *v1,
__isl_take isl_val *v2);
+__isl_give isl_val *isl_val_mod_val(__isl_take isl_val *v1,
+ __isl_take isl_val *v2);
int isl_val_plain_is_equal(__isl_keep isl_val *val1, __isl_keep isl_val *val2);
Added: polly/trunk/lib/External/isl/isl_yaml.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_yaml.h?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_yaml.h (added)
+++ polly/trunk/lib/External/isl/isl_yaml.h Mon Feb 16 13:33:40 2015
@@ -0,0 +1,18 @@
+#ifndef ISL_YAML_H
+#define ISL_YAML_H
+
+#define ISL_YAML_INDENT_FLOW -1
+
+enum isl_yaml_state {
+ isl_yaml_none,
+ isl_yaml_mapping_first_key_start,
+ isl_yaml_mapping_key_start,
+ isl_yaml_mapping_key,
+ isl_yaml_mapping_val_start,
+ isl_yaml_mapping_val,
+ isl_yaml_sequence_first_start,
+ isl_yaml_sequence_start,
+ isl_yaml_sequence
+};
+
+#endif
Modified: polly/trunk/lib/External/isl/polyhedron_detect_equalities.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/polyhedron_detect_equalities.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/polyhedron_detect_equalities.c (original)
+++ polly/trunk/lib/External/isl/polyhedron_detect_equalities.c Mon Feb 16 13:33:40 2015
@@ -13,10 +13,16 @@ int main(int argc, char **argv)
{
struct isl_ctx *ctx = isl_ctx_alloc();
struct isl_basic_set *bset;
+ isl_printer *p;
bset = isl_basic_set_read_from_file(ctx, stdin);
bset = isl_basic_set_detect_equalities(bset);
- isl_basic_set_print(bset, stdout, 0, "", "", ISL_FORMAT_POLYLIB);
+
+ p = isl_printer_to_file(ctx, stdout);
+ p = isl_printer_set_output_format(p, ISL_FORMAT_POLYLIB);
+ p = isl_printer_print_basic_set(p, bset);
+ isl_printer_free(p);
+
isl_basic_set_free(bset);
isl_ctx_free(ctx);
Modified: polly/trunk/lib/External/isl/print.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/print.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/print.c (original)
+++ polly/trunk/lib/External/isl/print.c Mon Feb 16 13:33:40 2015
@@ -90,6 +90,12 @@
#define BASE multi_pw_aff
#include <print_templ.c>
#undef BASE
+#define BASE union_pw_aff
+#include <print_templ.c>
+#undef BASE
+#define BASE multi_union_pw_aff
+#include <print_templ.c>
+#undef BASE
#define BASE point
#include <print_templ.c>
#undef BASE
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/cholesky2.c Mon Feb 16 13:33:40 2015
@@ -6,14 +6,11 @@
}
for (int c0 = 1; c0 < 3 * M - 1; c0 += 3) {
S3((c0 + 2) / 3);
- if (3 * M >= c0 + 8) {
- for (int c1 = (c0 + 5) / 3; c1 <= M; c1 += 1) {
- S6((c0 + 2) / 3, c1);
- for (int c4 = (c0 + 5) / 3; c4 < c1; c4 += 1)
- S5(c4, c1, (c0 + 2) / 3);
- }
- } else if (c0 + 5 == 3 * M)
- S6(M - 1, M);
+ for (int c1 = (c0 + 5) / 3; c1 <= M; c1 += 1) {
+ S6((c0 + 2) / 3, c1);
+ for (int c4 = (c0 + 5) / 3; c4 < c1; c4 += 1)
+ S5(c4, c1, (c0 + 2) / 3);
+ }
for (int c1 = (c0 + 5) / 3; c1 <= M; c1 += 1)
S2(c1, (c0 + 2) / 3);
}
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/classen.c Mon Feb 16 13:33:40 2015
@@ -1,30 +1,20 @@
-{
- if (m == 1) {
- S1(0, 1, 1, 1);
- S8(0, 1);
- } else if (m >= 2) {
- S1(0, 1, 1, 1);
- S3(0, 1, 1, 2, 1, 1, 1, 2);
- S4(0, 1, 2, 2, 1, 1, 2, 2);
- S2(0, 1, 1, 1, 1, 1, 2, 1);
- S8(0, 1);
- }
- for (int c0 = 1; c0 < 2 * m - 3; c0 += 1) {
+for (int c0 = 0; c0 < 2 * m - 1; c0 += 1) {
+ if (2 * m >= c0 + 3 && c0 >= 1) {
if (c0 + 1 == m) {
S5(m - 2, 1, m - 1, 1, m - 1, 1, m, 1);
S1(m - 1, 1, m, 1);
S3(m - 1, 1, m, 2, m, 1, m, 2);
- } else if (m >= c0 + 2) {
+ } else if (c0 >= m) {
+ S5(c0 - 1, -m + c0 + 2, c0, -m + c0 + 2, m - 1, -m + c0 + 2, m, -m + c0 + 2);
+ S6(c0 - 1, -m + c0 + 1, c0, -m + c0 + 2, m, -m + c0 + 1, m, -m + c0 + 2);
+ S1(c0, -m + c0 + 2, m, -m + c0 + 2);
+ S3(c0, -m + c0 + 2, c0 + 1, -m + c0 + 3, m, -m + c0 + 2, m, -m + c0 + 3);
+ } else {
S5(c0 - 1, 1, c0, 1, c0, 1, c0 + 1, 1);
S1(c0, 1, c0 + 1, 1);
S3(c0, 1, c0 + 1, 2, c0 + 1, 1, c0 + 1, 2);
S4(c0, 1, c0 + 2, 2, c0 + 1, 1, c0 + 2, 2);
S2(c0, 1, c0 + 1, 1, c0 + 1, 1, c0 + 2, 1);
- } else {
- S5(c0 - 1, -m + c0 + 2, c0, -m + c0 + 2, m - 1, -m + c0 + 2, m, -m + c0 + 2);
- S6(c0 - 1, -m + c0 + 1, c0, -m + c0 + 2, m, -m + c0 + 1, m, -m + c0 + 2);
- S1(c0, -m + c0 + 2, m, -m + c0 + 2);
- S3(c0, -m + c0 + 2, c0 + 1, -m + c0 + 3, m, -m + c0 + 2, m, -m + c0 + 3);
}
for (int c2 = max(2, -m + c0 + 3); c2 <= min(m - 1, c0); c2 += 1) {
S5(c0 - 1, c2, c0, c2, c0 - c2 + 1, c2, c0 - c2 + 2, c2);
@@ -54,33 +44,17 @@
S4(c0, c0 + 1, c0 + 2, c0 + 2, 1, c0 + 1, 2, c0 + 2);
S2(c0, c0 + 1, c0 + 1, c0 + 1, 1, c0 + 1, 2, c0 + 1);
}
- for (int c8 = max(1, -m + c0 + 2); c8 <= min(m, c0 + 1); c8 += 1)
- S8(c0, c8);
- }
- if (m >= 2) {
- if (m >= 3) {
- S5(2 * m - 4, m - 1, 2 * m - 3, m - 1, m - 1, m - 1, m, m - 1);
- S6(2 * m - 4, m - 2, 2 * m - 3, m - 1, m, m - 2, m, m - 1);
- S1(2 * m - 3, m - 1, m, m - 1);
- S3(2 * m - 3, m - 1, 2 * m - 2, m, m, m - 1, m, m);
- S5(2 * m - 4, m, 2 * m - 3, m, m - 2, m, m - 1, m);
- S7(2 * m - 4, m - 1, 2 * m - 2, m, m - 1, m - 1, m, m);
- S6(2 * m - 4, m - 1, 2 * m - 3, m, m - 1, m - 1, m - 1, m);
- S1(2 * m - 3, m, m - 1, m);
- } else {
- S5(0, 1, 1, 1, 1, 1, 2, 1);
- S1(1, 1, 2, 1);
- S3(1, 1, 2, 2, 2, 1, 2, 2);
- S7(0, 1, 2, 2, 1, 1, 2, 2);
- S6(0, 1, 1, 2, 1, 1, 1, 2);
- S1(1, 2, 1, 2);
- }
- S2(2 * m - 3, m, 2 * m - 2, m, m - 1, m, m, m);
- for (int c8 = m - 1; c8 <= m; c8 += 1)
- S8(2 * m - 3, c8);
+ } else if (m >= 2 && c0 == 0) {
+ S1(0, 1, 1, 1);
+ S3(0, 1, 1, 2, 1, 1, 1, 2);
+ S4(0, 1, 2, 2, 1, 1, 2, 2);
+ S2(0, 1, 1, 1, 1, 1, 2, 1);
+ } else if (m >= 2) {
S5(2 * m - 3, m, 2 * m - 2, m, m - 1, m, m, m);
S6(2 * m - 3, m - 1, 2 * m - 2, m, m, m - 1, m, m);
S1(2 * m - 2, m, m, m);
- S8(2 * m - 2, m);
- }
+ } else
+ S1(0, 1, 1, 1);
+ for (int c8 = max(1, -m + c0 + 2); c8 <= min(m, c0 + 1); c8 += 1)
+ S8(c0, c8);
}
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/faber.c Mon Feb 16 13:33:40 2015
@@ -67,32 +67,25 @@
}
}
for (int c0 = 37; c0 <= 218; c0 += 1) {
- for (int c1 = (c0 + 5) / 14 - 8; c1 < min(0, c0 / 14 - 5); c1 += 1) {
- if (c0 <= 46 && c1 == -3)
- S7(c0, -3, 6);
- if (-77 * ((-3 * c1 + 1) / 5) + 447 >= 6 * c0)
- S6(c0, c1, -((-2 * c1 + 3) / 5) + 9);
- for (int c2 = c1 + 24; c2 <= -2 * c1 + 24; c2 += 1)
- S2(c0, c1, c2);
- for (int c2 = -2 * c1 + 30; c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
- S1(c0, c1, c2);
- }
- if (c0 <= 148)
- for (int c1 = max(0, (c0 + 5) / 14 - 8); c1 < c0 / 14 - 5; c1 += 1) {
- if (c1 == 0)
- S2(c0, 0, 24);
+ if (c0 <= 148) {
+ for (int c1 = (c0 + 5) / 14 - 8; c1 < c0 / 14 - 5; c1 += 1) {
+ if (c0 <= 46 && c1 == -3)
+ S7(c0, -3, 6);
+ if (77 * ((3 * c1 + 18) / 5) + 216 >= 6 * c0)
+ S6(c0, c1, -((-2 * c1 + 3) / 5) + 9);
+ for (int c2 = c1 + 24; c2 <= -2 * c1 + 24; c2 += 1)
+ S2(c0, c1, c2);
for (int c2 = max(c1 + 24, -2 * c1 + 30); c2 <= c1 - (3 * c0 + 17) / 14 + 56; c2 += 1)
S1(c0, c1, c2);
}
- if (c0 >= 79 && c0 % 14 >= 9) {
- for (int c2 = max((c0 - 70) / 14 + 24, (c0 - 70) / 14 - (3 * c0 + 14) / 14 + 49); c2 <= (c0 - 70) / 14 - (3 * c0 + 17) / 14 + 56; c2 += 1)
- S1(c0, c0 / 14 - 5, c2);
- } else if (c0 <= 69 && c0 % 14 >= 9) {
- if (c0 <= 41)
- S7(c0, -3, 6);
- S6(c0, c0 / 14 - 5, 8);
- for (int c2 = -((-c0 + 83) / 14) - (3 * c0 + 14) / 14 + 49; c2 <= -((-c0 + 83) / 14) - (3 * c0 + 17) / 14 + 56; c2 += 1)
- S1(c0, c0 / 14 - 5, c2);
+ if (c0 % 14 >= 9) {
+ if (c0 <= 41)
+ S7(c0, -3, 6);
+ if (c0 <= 69)
+ S6(c0, c0 / 14 - 5, 8);
+ for (int c2 = max((c0 - 28) / 14 + 21, (c0 - 28) / 14 - (3 * c0 + 14) / 14 + 46); c2 <= (c0 - 28) / 14 - (3 * c0 + 17) / 14 + 53; c2 += 1)
+ S1(c0, c0 / 14 - 5, c2);
+ }
}
for (int c1 = (c0 + 5) / 14 - 5; c1 < 0; c1 += 1) {
if (7 * c1 + 114 >= 2 * c0)
@@ -125,7 +118,7 @@
S1(c0, c1, c2);
}
for (int c1 = c0 / 14 - 2; c1 <= 18; c1 += 1) {
- for (int c2 = c1 + 6; c2 <= min((2 * c1 + 1) / 5 + 7, floord(2 * c0 - 7 * c1, 21) + 4); c2 += 1)
+ for (int c2 = c1 + 6; c2 <= min((2 * c1 + 1) / 5 + 7, (2 * c0 - 7 * c1 + 63) / 21 + 1); c2 += 1)
S7(c0, c1, c2);
for (int c2 = max(6, (c0 + 5) / 14 + 1); c2 <= min(min(c1, c0 / 14 + 3), -c1 + c1 / 2 + 18); c2 += 1)
S5(c0, c1, c2);
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/mxm-shared.c Mon Feb 16 13:33:40 2015
@@ -1,6 +1,3 @@
-if (g4 == 0 && N >= g0 + t1 + 1 && t1 <= 7) {
- for (int c0 = t0; c0 <= min(127, N - g1 - 1); c0 += 16)
- S1(g0 + t1, g1 + c0);
-} else if (g4 >= 4 && N >= g0 + t1 + 1 && t1 <= 7 && g4 % 4 == 0)
+if (N >= g0 + t1 + 1 && t1 <= 7 && g4 % 4 == 0)
for (int c0 = t0; c0 <= min(127, N - g1 - 1); c0 += 16)
S1(g0 + t1, g1 + c0);
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/nul_complex1.c Mon Feb 16 13:33:40 2015
@@ -1,3 +1,3 @@
for (int c0 = 0; c0 <= 5 * n; c0 += 1)
- for (int c1 = max(-((5 * n - c0 + 1) % 2) - n + c0 + 1, 2 * floord(c0 - 1, 3) + 2); c1 <= min(c0, n + c0 - (n + c0 + 2) / 3); c1 += 2)
+ for (int c1 = max(-((5 * n - c0 + 1) % 2) - n + c0 + 1, 2 * ((c0 + 2) / 3)); c1 <= min(c0, n + c0 - (n + c0 + 2) / 3); c1 += 2)
S1((3 * c1 / 2) - c0, c0 - c1);
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/vivien.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/vivien.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/vivien.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/vivien.c Mon Feb 16 13:33:40 2015
@@ -2,50 +2,50 @@
for (int c0 = -27 * n + 2; c0 <= 1; c0 += 1)
S1(c0 - 1);
for (int c0 = 2; c0 <= min(2 * n, n + 29); c0 += 1) {
- if (c0 >= 3) {
- if (2 * n >= c0 + 1) {
- S4(c0 - c0 / 2 - 1, c0 / 2 + 1);
- if (c0 + 2 >= 2 * n) {
- for (int c2 = 1; c2 < -n + c0; c2 += 1)
- S5(-n + c0, n, c2);
- } else if (c0 >= 5) {
- S4(c0 - c0 / 2 - 2, c0 / 2 + 2);
- for (int c2 = 1; c2 < c0 - c0 / 2 - 1; c2 += 1)
- S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
- }
+ if (c0 >= 3 && 2 * n >= c0 + 1) {
+ S4(c0 - c0 / 2 - 1, c0 / 2 + 1);
+ if (c0 >= 5 && 2 * n >= c0 + 3) {
+ S4(c0 - c0 / 2 - 2, c0 / 2 + 2);
+ for (int c2 = 1; c2 < c0 - c0 / 2 - 1; c2 += 1)
+ S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
}
- for (int c1 = -c0 + c0 / 2 + 3; c1 <= min(-1, n - c0); c1 += 1) {
- S4(-c1, c0 + c1);
- S6(-c1 + 2, c0 + c1 - 2);
- for (int c2 = 1; c2 <= -c1; c2 += 1)
- S5(-c1 + 1, c0 + c1 - 1, c2);
- }
- if (2 * n >= c0 + 3 && c0 >= n + 2) {
- S6(-n + c0 + 1, n - 1);
- for (int c2 = 1; c2 < -n + c0; c2 += 1)
- S5(-n + c0, n, c2);
- }
- if (c0 >= n + 3 && 2 * n >= c0 + 1) {
- S6(-n + c0, n);
- } else {
- if (c0 >= 5 && n + 1 >= c0) {
- S6(2, c0 - 2);
- S1(c0 - 1);
- } else if (n + 1 >= c0 && c0 <= 4)
- S1(c0 - 1);
- if (n + 1 >= c0) {
- S6(1, c0 - 1);
- } else if (n >= 3 && c0 == n + 2) {
- S6(2, n);
- S1(n + 1);
- }
- }
- if (c0 >= n + 3)
- S1(c0 - 1);
- if (n == 2 && c0 == 4)
- S1(3);
- } else
+ }
+ for (int c1 = -c0 + c0 / 2 + 3; c1 <= min(-1, n - c0); c1 += 1) {
+ S4(-c1, c0 + c1);
+ S6(-c1 + 2, c0 + c1 - 2);
+ for (int c2 = 1; c2 <= -c1; c2 += 1)
+ S5(-c1 + 1, c0 + c1 - 1, c2);
+ }
+ if (c0 >= 3 && n + 1 >= c0 && c0 <= 4) {
+ S1(c0 - 1);
+ } else if (c0 >= 5 && n + 1 >= c0) {
+ S6(2, c0 - 2);
+ S1(c0 - 1);
+ }
+ if (n >= 2 && c0 == n + 1) {
+ S6(1, n);
+ } else if (2 * n >= c0 + 3 && c0 >= n + 2) {
+ S6(-n + c0 + 1, n - 1);
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ }
+ if (2 * n >= c0 + 1 && c0 + 2 >= 2 * n)
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ if (c0 >= n + 3 && 2 * n >= c0 + 1) {
+ S6(-n + c0, n);
+ } else if (c0 >= 3 && n >= c0) {
+ S6(1, c0 - 1);
+ } else if (c0 == 2) {
S1(1);
+ } else if (n >= 3 && c0 == n + 2) {
+ S6(2, n);
+ S1(n + 1);
+ }
+ if (c0 >= n + 3)
+ S1(c0 - 1);
+ if (n == 2 && c0 == 4)
+ S1(3);
if (c0 % 2 == 0)
S3(c0 / 2);
for (int c1 = max(1, -n + c0); c1 < (c0 + 1) / 2; c1 += 1)
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/vivien2.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/vivien2.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/vivien2.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/vivien2.c Mon Feb 16 13:33:40 2015
@@ -9,37 +9,40 @@
for (int c2 = 1; c2 < c0 - c0 / 2 - 1; c2 += 1)
S5(c0 - c0 / 2 - 1, c0 / 2 + 1, c2);
}
- for (int c1 = -c0 + c0 / 2 + 3; c1 <= min(-1, n - c0); c1 += 1) {
- S4(-c1, c0 + c1);
- S6(-c1 + 2, c0 + c1 - 2);
- for (int c2 = 1; c2 <= -c1; c2 += 1)
- S5(-c1 + 1, c0 + c1 - 1, c2);
- }
- if (2 * n >= c0 + 3 && c0 >= n + 2) {
- S6(-n + c0 + 1, n - 1);
- for (int c2 = 1; c2 < -n + c0; c2 += 1)
- S5(-n + c0, n, c2);
- } else if (c0 + 2 >= 2 * n)
+ }
+ for (int c1 = -c0 + c0 / 2 + 3; c1 <= min(-1, n - c0); c1 += 1) {
+ S4(-c1, c0 + c1);
+ S6(-c1 + 2, c0 + c1 - 2);
+ for (int c2 = 1; c2 <= -c1; c2 += 1)
+ S5(-c1 + 1, c0 + c1 - 1, c2);
+ }
+ if (c0 >= 5 && n + 1 >= c0) {
+ S6(2, c0 - 2);
+ S1(c0 - 1);
+ if (c0 == n + 1)
+ S6(1, n);
+ } else if (c0 == 2) {
+ S1(1);
+ } else if (2 * n >= c0 + 3 && c0 >= n + 2) {
+ S6(-n + c0 + 1, n - 1);
+ for (int c2 = 1; c2 < -n + c0; c2 += 1)
+ S5(-n + c0, n, c2);
+ } else if (c0 <= 4)
+ S1(c0 - 1);
+ if (c0 >= 3 && n >= c0) {
+ S6(1, c0 - 1);
+ } else {
+ if (c0 + 2 >= 2 * n)
for (int c2 = 1; c2 < -n + c0; c2 += 1)
S5(-n + c0, n, c2);
if (c0 >= n + 3) {
S6(-n + c0, n);
S1(c0 - 1);
- } else {
- if (c0 >= 5 && n + 1 >= c0) {
- S6(2, c0 - 2);
- S1(c0 - 1);
- } else if (c0 <= 4)
- S1(c0 - 1);
- if (n + 1 >= c0) {
- S6(1, c0 - 1);
- } else {
- S6(2, n);
- S1(n + 1);
- }
+ } else if (c0 == n + 2) {
+ S6(2, n);
+ S1(n + 1);
}
- } else
- S1(1);
+ }
if (c0 % 2 == 0)
S3(c0 / 2);
for (int c1 = max(1, -n + c0); c1 < (c0 + 1) / 2; c1 += 1)
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/cloog/yosr.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/cloog/yosr.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/cloog/yosr.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/cloog/yosr.c Mon Feb 16 13:33:40 2015
@@ -1,12 +1,7 @@
-{
- for (int c0 = 1; c0 < n; c0 += 1) {
- for (int c2 = c0 + 1; c2 <= n; c2 += 1)
- S1(c0, c2);
- for (int c1 = 1; c1 < c0; c1 += 1)
- for (int c2 = c1 + 1; c2 <= n; c2 += 1)
- S2(c1, c2, c0);
- }
- for (int c1 = 1; c1 < n; c1 += 1)
+for (int c0 = 1; c0 <= n; c0 += 1) {
+ for (int c2 = c0 + 1; c2 <= n; c2 += 1)
+ S1(c0, c2);
+ for (int c1 = 1; c1 < c0; c1 += 1)
for (int c2 = c1 + 1; c2 <= n; c2 += 1)
- S2(c1, c2, n);
+ S2(c1, c2, c0);
}
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur00-0.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur00-0.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur00-0.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur00-0.c Mon Feb 16 13:33:40 2015
@@ -1,5 +1,5 @@
for (int c0 = 0; c0 <= 15; c0 += 1)
for (int c1 = max(2 * c0 - 15, c0 / 2); c1 <= min(15, c0 + 1); c1 += 1)
- for (int c2 = max(max(max(1, 67 * c0 - (c0 + 1) / 3), 67 * c1 - (c1 + 2) / 3), 133 * c0 - 67 * c1 + (c0 + c1 + 1) / 3 - 66); c2 <= min(min(1000, 100 * c0 + 99), 133 * c0 - 67 * c1 + floord(c0 + c1 - 1, 3) + 133); c2 += 1)
+ for (int c2 = max(max(max(1, 67 * c0 - (c0 + 1) / 3), 67 * c1 - (c1 + 2) / 3), 133 * c0 - 67 * c1 + (c0 + c1 + 1) / 3 - 66); c2 <= min(min(1000, 100 * c0 + 99), 133 * c0 - 67 * c1 + (c0 + c1 + 2) / 3 + 132); c2 += 1)
for (int c3 = max(max(c2, 200 * c0 - c2), 100 * c1 + (c2 + 1) / 2); c3 <= min(min(2 * c2 + 1, 200 * c0 - c2 + 199), 100 * c1 + (c2 + 1) / 2 + 99); c3 += 1)
s0(c0, c1, c2, c3);
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur01-0.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur01-0.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur01-0.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur01-0.c Mon Feb 16 13:33:40 2015
@@ -1,5 +1,5 @@
for (int c0 = 0; c0 <= 15; c0 += 1)
for (int c1 = max(2 * c0 - 15, c0 / 2); c1 <= min(15, c0 + 1); c1 += 1)
- for (int c2 = max(max(max(1, 67 * c0 - (c0 + 1) / 3), 67 * c1 - (c1 + 2) / 3), 133 * c0 - 67 * c1 + (c0 + c1 + 1) / 3 - 66); c2 <= min(min(1000, 100 * c0 + 99), 133 * c0 - 67 * c1 + floord(c0 + c1 - 1, 3) + 133); c2 += 1)
+ for (int c2 = max(max(max(1, 67 * c0 - (c0 + 1) / 3), 67 * c1 - (c1 + 2) / 3), 133 * c0 - 67 * c1 + (c0 + c1 + 1) / 3 - 66); c2 <= min(min(1000, 100 * c0 + 99), 133 * c0 - 67 * c1 + (c0 + c1 + 2) / 3 + 132); c2 += 1)
for (int c3 = max(max(c2, 200 * c0 - c2), 100 * c1 + (c2 + 1) / 2); c3 <= min(min(2 * c2 + 1, 200 * c0 - c2 + 199), 100 * c1 + (c2 + 1) / 2 + 99); c3 += 1)
s0(c0, c1, c2, c3);
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur01-1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur01-1.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur01-1.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/omega/lefur01-1.c Mon Feb 16 13:33:40 2015
@@ -1,5 +1,5 @@
for (int c0 = 0; c0 <= 15; c0 += 1)
for (int c1 = max(2 * c0 - 15, c0 / 2); c1 <= min(15, c0 + 1); c1 += 1)
- for (int c2 = max(max(max(1, 67 * c0 - (c0 + 1) / 3), 67 * c1 - (c1 + 2) / 3), 133 * c0 - 67 * c1 + (c0 + c1 + 1) / 3 - 66); c2 <= min(min(1000, 100 * c0 + 99), 133 * c0 - 67 * c1 + floord(c0 + c1 - 1, 3) + 133); c2 += 1)
+ for (int c2 = max(max(max(1, 67 * c0 - (c0 + 1) / 3), 67 * c1 - (c1 + 2) / 3), 133 * c0 - 67 * c1 + (c0 + c1 + 1) / 3 - 66); c2 <= min(min(1000, 100 * c0 + 99), 133 * c0 - 67 * c1 + (c0 + c1 + 2) / 3 + 132); c2 += 1)
for (int c3 = max(max(c2, 200 * c0 - c2), 100 * c1 + (c2 + 1) / 2); c3 <= min(min(2 * c2 + 1, 200 * c0 - c2 + 199), 100 * c1 + (c2 + 1) / 2 + 99); c3 += 1)
s0(c0, c1, c2, c3);
Modified: polly/trunk/lib/External/isl/test_inputs/codegen/omega/substitution-1.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/omega/substitution-1.c?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/omega/substitution-1.c (original)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/omega/substitution-1.c Mon Feb 16 13:33:40 2015
@@ -1,3 +1,3 @@
for (int c0 = 0; c0 <= 14; c0 += 1)
- for (int c1 = max(2 * c0 - 12, -c0 + 3 * floord(c0 - 1, 2) + 3); c1 <= min(2 * c0, c0 / 2 + 9); c1 += 3)
+ for (int c1 = max(2 * c0 - 12, -c0 + 3 * ((c0 + 1) / 2)); c1 <= min(2 * c0, c0 / 2 + 9); c1 += 3)
s0((2 * c0 - c1) / 3, (-c0 + 2 * c1) / 3);
Added: polly/trunk/lib/External/isl/test_inputs/codegen/unroll11.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/unroll11.c?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/unroll11.c (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/unroll11.c Mon Feb 16 13:33:40 2015
@@ -0,0 +1,8 @@
+{
+ if (t1 >= 126)
+ S(0, t1 - 384);
+ S(0, t1 - 256);
+ if (t1 >= 126)
+ S(1, t1 - 384);
+ S(1, t1 - 256);
+}
Added: polly/trunk/lib/External/isl/test_inputs/codegen/unroll11.in
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/test_inputs/codegen/unroll11.in?rev=229423&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/test_inputs/codegen/unroll11.in (added)
+++ polly/trunk/lib/External/isl/test_inputs/codegen/unroll11.in Mon Feb 16 13:33:40 2015
@@ -0,0 +1,10 @@
+# Check that the most appropriate lower bound is selected
+[t1,t2]->{ S[i,j] -> [i,j] : exists (alpha, beta :
+ 0 <= i <= 1 &&
+ t1 = j+128alpha &&
+ 0 <= j+2beta < 128 &&
+ 510 <= t2+2beta <= 514 &&
+ 0 <= 2beta - t2 <= 5
+)}
+[t1,t2] -> {: 125 <= t1 <= 127 and 254 <= t2 < 257}
+{[i,j] -> unroll[x]}
Modified: polly/trunk/test/Dependences/reduction_dependences_equal_non_reduction_dependences.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Dependences/reduction_dependences_equal_non_reduction_dependences.ll?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/test/Dependences/reduction_dependences_equal_non_reduction_dependences.ll (original)
+++ polly/trunk/test/Dependences/reduction_dependences_equal_non_reduction_dependences.ll Mon Feb 16 13:33:40 2015
@@ -8,7 +8,7 @@
; CHECK: WAR dependences:
; CHECK: { }
; CHECK: WAW dependences:
-; CHECK: { Stmt_for_body[i0] -> Stmt_for_body[1 + i0] : i0 >= 0 and i0 <= 1022 }
+; CHECK: { Stmt_for_body[i0] -> Stmt_for_body[1 + i0] : i0 <= 1022 and i0 >= 0 }
; CHECK: Reduction dependences:
; CHECK: { Stmt_for_body[i0] -> Stmt_for_body[1 + i0] : i0 <= 1022 and i0 >= 0 }
;
Modified: polly/trunk/test/Dependences/reduction_mixed_reduction_and_non_reduction_dependences.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Dependences/reduction_mixed_reduction_and_non_reduction_dependences.ll?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/test/Dependences/reduction_mixed_reduction_and_non_reduction_dependences.ll (original)
+++ polly/trunk/test/Dependences/reduction_mixed_reduction_and_non_reduction_dependences.ll Mon Feb 16 13:33:40 2015
@@ -1,8 +1,7 @@
; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
;
; CHECK: RAW dependences:
-; CHECK-DAG: Stmt_for_body3[i0, 1] -> Stmt_for_body3[1 + i0, o1] : i0 <= 1022 and i0 >= 0 and o1 <= 511 and o1 >= 1
-; CHECK-DAG: Stmt_for_body3[i0, 0] -> Stmt_for_body3[i0, o1] : i0 <= 1023 and i0 >= 0 and o1 <= 511 and o1 >= 1
+; CHECK-DAG: Stmt_for_body3[i0, i1] -> Stmt_for_body3[i0 + i1, o1] : i1 <= 1023 - i0 and i1 >= 0 and i1 <= 1 and i0 >= 0 and o1 <= 511 and o1 >= 1
; CHECK: WAR dependences:
; CHECK: { }
; CHECK: WAW dependences:
Modified: polly/trunk/test/Dependences/reduction_privatization_deps.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Dependences/reduction_privatization_deps.ll?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/test/Dependences/reduction_privatization_deps.ll (original)
+++ polly/trunk/test/Dependences/reduction_privatization_deps.ll Mon Feb 16 13:33:40 2015
@@ -2,13 +2,10 @@
;
; CHECK: RAW dependences:
; CHECK-DAG: Stmt_S0[i0] -> Stmt_S1[o0, i0 - o0] : i0 <= 1023 and o0 >= 0 and o0 <= i0
-; CHECK-DAG: Stmt_S1[i0, i1] -> Stmt_S2[-1 + i0 + i1] : i0 >= 0 and i1 >= 1 and i0 <= 1022 and i1 <= 1024 - i0 and i1 <= 1023
-; CHECK-DAG: Stmt_S1[1023, i1] -> Stmt_S2[1022 + i1] : i1 <= 1 and i1 >= 0
-; CHECK-DAG: Stmt_S1[i0, 0] -> Stmt_S2[-1 + i0] : i0 <= 1022 and i0 >= 1
+; CHECK-DAG: Stmt_S1[i0, i1] -> Stmt_S2[-1 + i0 + i1] : i1 <= 1023 and i1 >= 0 and i1 >= 1 - i0 and i0 >= 0 and i0 <= 1023 and i1 <= 1024 - i0
; CHECK: WAR dependences:
; CHECK-DAG: Stmt_S2[i0] -> Stmt_S2[1 + i0] : i0 <= 1022 and i0 >= 0
-; CHECK-DAG: Stmt_S1[i0, i1] -> Stmt_S2[i0 + i1] : i0 >= 0 and i1 <= 1023 - i0 and i1 >= 1
-; CHECK-DAG: Stmt_S1[i0, 0] -> Stmt_S2[i0] : i0 <= 1023 and i0 >= 1
+; CHECK-DAG: Stmt_S1[i0, i1] -> Stmt_S2[i0 + i1] : i1 <= 1023 - i0 and i1 >= 0 and i1 >= 1 - i0 and i0 >= 0 }
; CHECK: WAW dependences:
; CHECK-DAG: Stmt_S0[i0] -> Stmt_S1[o0, i0 - o0] : i0 <= 1023 and o0 >= 0 and o0 <= i0
; CHECK-DAG: Stmt_S1[0, 0] -> Stmt_S2[0]
Modified: polly/trunk/test/Dependences/reduction_privatization_deps_3.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Dependences/reduction_privatization_deps_3.ll?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/test/Dependences/reduction_privatization_deps_3.ll (original)
+++ polly/trunk/test/Dependences/reduction_privatization_deps_3.ll Mon Feb 16 13:33:40 2015
@@ -1,15 +1,13 @@
; RUN: opt %loadPolly -polly-dependences -analyze < %s | FileCheck %s
;
; CHECK: RAW dependences:
-; CHECK-DAG: Stmt_S2[0, 0] -> Stmt_S3[1]
-; CHECK-DAG: Stmt_S2[i0, 1 - i0] -> Stmt_S3[i0] : i0 <= 1 and i0 >= 0
+; CHECK-DAG: Stmt_S2[i0, i1] -> Stmt_S3[o0] : o0 <= 1 and i1 <= 1 - i0 and o0 <= 1 + i0 - i1 and o0 >= 1 - i1
; CHECK-DAG: Stmt_S3[i0] -> Stmt_S2[o0, 1 - i0] : i0 <= 1 and i0 >= 0 and o0 >= 1 + i0 and o0 <= 98
; CHECK-DAG: Stmt_S1[i0] -> Stmt_S3[2 + i0] : i0 >= 0 and i0 <= 96
; CHECK: WAR dependences:
; CHECK: { }
; CHECK: WAW dependences:
-; CHECK-DAG: Stmt_S2[0, 0] -> Stmt_S3[1]
-; CHECK-DAG: Stmt_S2[i0, 1 - i0] -> Stmt_S3[i0] : i0 <= 1 and i0 >= 0
+; CHECK-DAG: Stmt_S2[i0, i1] -> Stmt_S3[o0] : o0 <= 1 and i1 <= 1 - i0 and o0 <= 1 + i0 - i1 and o0 >= 1 - i1
; CHECK-DAG: Stmt_S3[i0] -> Stmt_S2[o0, 1 - i0] : i0 <= 1 and i0 >= 0 and o0 >= 1 + i0 and o0 <= 98
; CHECK-DAG: Stmt_S1[i0] -> Stmt_S3[2 + i0] : i0 >= 0 and i0 <= 96
; CHECK: Reduction dependences:
Modified: polly/trunk/test/Dependences/reduction_two_reductions_different_rloops.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Dependences/reduction_two_reductions_different_rloops.ll?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/test/Dependences/reduction_two_reductions_different_rloops.ll (original)
+++ polly/trunk/test/Dependences/reduction_two_reductions_different_rloops.ll Mon Feb 16 13:33:40 2015
@@ -7,8 +7,7 @@
; CHECK: WAW dependences:
; CHECK: { }
; CHECK: Reduction dependences:
-; CHECK-DAG: Stmt_for_body3[i0, i1] -> Stmt_for_body3[i0, 1 + i1] : i0 <= 1023 and i0 >= 0 and i1 <= 1022 and i1 >= 0
-; CHECK-DAG: Stmt_for_body3[i0, i1] -> Stmt_for_body3[1 + i0, i1] : i0 <= 1022 and i0 >= 0 and i1 <= 1023 and i1 >= 0
+; CHECK-DAG: Stmt_for_body3[i0, i1] -> Stmt_for_body3[o0, 1 + i0 + i1 - o0] : o0 <= 1 + i0 and o0 >= i0 and o0 <= 1023 and i0 >= 0 and i1 >= 0 and o0 >= -1022 + i0 + i1
;
; void f(int *restrict A, int *restrict B, int *restrict Values) {
; for (int i = 0; i < 1024; i++) {
Modified: polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions.ll?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions.ll (original)
+++ polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions.ll Mon Feb 16 13:33:40 2015
@@ -1,18 +1,11 @@
; RUN: opt %loadPolly -polly-import-jscop-dir=%S -polly-import-jscop -polly-ast -polly-ast-detect-parallel -analyze < %s | FileCheck %s
;
; CHECK: #pragma known-parallel
-; CHECK: for (int c0 = 0; c0 <= 1; c0 += 1) {
-; CHECK: if (c0 == 1) {
-; CHECK: for (int c1 = 1; c1 < 2 * n; c1 += 2)
-; CHECK: #pragma simd reduction
-; CHECK: for (int c3 = 0; c3 <= 1023; c3 += 1)
-; CHECK: Stmt_for_body3(c1, c3);
-; CHECK: } else
-; CHECK: for (int c1 = 0; c1 < 2 * n; c1 += 2)
-; CHECK: #pragma simd reduction
-; CHECK: for (int c3 = 0; c3 <= 1023; c3 += 1)
-; CHECK: Stmt_for_body3(c1, c3);
-; CHECK: }
+; CHECK: for (int c0 = 0; c0 <= 1; c0 += 1)
+; CHECK: for (int c1 = c0; c1 < 2 * n; c1 += 2)
+; CHECK: #pragma simd reduction
+; CHECK: for (int c3 = 0; c3 <= 1023; c3 += 1)
+; CHECK: Stmt_for_body3(c1, c3);
;
; void rmsmd(int *A, long n) {
; for (long i = 0; i < 2 * n; i++)
Modified: polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_2.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_2.ll?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_2.ll (original)
+++ polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_2.ll Mon Feb 16 13:33:40 2015
@@ -4,16 +4,10 @@
;
; CHECK-NOT:#pragma known-parallel reduction
; CHECK: #pragma known-parallel
-; CHECK: for (int c1 = 0; c1 < 2 * n; c1 += 1) {
-; CHECK: if (c1 % 2 == 0) {
-; CHECK: #pragma simd reduction
-; CHECK: for (int c3 = 0; c3 <= 1023; c3 += 1)
-; CHECK: Stmt_for_body3(c1, c3);
-; CHECK: } else
-; CHECK: #pragma simd reduction
-; CHECK: for (int c3 = 0; c3 <= 1023; c3 += 1)
-; CHECK: Stmt_for_body3(c1, c3);
-; CHECK: }
+; CHECK: for (int c1 = 0; c1 < 2 * n; c1 += 1)
+; CHECK: #pragma simd reduction
+; CHECK: for (int c3 = 0; c3 <= 1023; c3 += 1)
+; CHECK: Stmt_for_body3(c1, c3);
;
; void rmsmd2(int *A, long n) {
; for (long i = 0; i < 2 * n; i++)
Modified: polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_3.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_3.ll?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_3.ll (original)
+++ polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_3.ll Mon Feb 16 13:33:40 2015
@@ -6,12 +6,8 @@
; CHECK: #pragma known-parallel
; CHECK: for (int c1 = 0; c1 < 2 * n; c1 += 1)
; CHECK: #pragma simd reduction
-; CHECK: for (int c3 = 0; c3 <= 1023; c3 += 1) {
-; CHECK: if (c3 % 2 == 0) {
-; CHECK: Stmt_for_body3(c1, c3);
-; CHECK: } else
-; CHECK: Stmt_for_body3(c1, c3);
-; CHECK: }
+; CHECK: for (int c3 = 0; c3 <= 1023; c3 += 1)
+; CHECK: Stmt_for_body3(c1, c3);
;
; void rmsmd3(int *A, long n) {
; for (long i = 0; i < 2 * n; i++)
Modified: polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_4.ll
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_4.ll?rev=229423&r1=229422&r2=229423&view=diff
==============================================================================
--- polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_4.ll (original)
+++ polly/trunk/test/Isl/Ast/reduction_modulo_schedule_multiple_dimensions_4.ll Mon Feb 16 13:33:40 2015
@@ -6,7 +6,7 @@
; CHECK: #pragma known-parallel
; CHECK: for (int c1 = 0; c1 < 2 * n; c1 += 1)
; CHECK: #pragma simd reduction
-; CHECK: for (int c3 = -1023; c3 <= 1023; c3 += 1) {
+; CHECK: for (int c3 = -1022; c3 <= 1023; c3 += 1) {
; CHECK: if (c3 <= 0 && c3 % 2 == 0) {
; CHECK: Stmt_for_body3(c1, -c3);
; CHECK: } else if (c3 >= 1 && (c3 - 1) % 2 == 0)
More information about the llvm-commits
mailing list