[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