[polly] r228193 - Import isl(+imath) as an external library into Polly

Tobias Grosser tobias at grosser.es
Wed Feb 4 12:55:55 PST 2015


Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/aff.h (added)
+++ polly/trunk/lib/External/isl/include/isl/aff.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,663 @@
+#ifndef ISL_AFF_H
+#define ISL_AFF_H
+
+#include <isl/local_space.h>
+#include <isl/printer.h>
+#include <isl/set_type.h>
+#include <isl/aff_type.h>
+#include <isl/list.h>
+#include <isl/multi.h>
+#include <isl/union_set_type.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_aff *isl_aff_zero_on_domain(__isl_take isl_local_space *ls);
+__isl_give isl_aff *isl_aff_val_on_domain(__isl_take isl_local_space *ls,
+	__isl_take isl_val *val);
+__isl_give isl_aff *isl_aff_var_on_domain(__isl_take isl_local_space *ls,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_aff *isl_aff_nan_on_domain(__isl_take isl_local_space *ls);
+
+__isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff);
+__isl_null isl_aff *isl_aff_free(__isl_take isl_aff *aff);
+
+isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff);
+
+int isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type);
+int isl_aff_involves_dims(__isl_keep isl_aff *aff,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_space *isl_aff_get_domain_space(__isl_keep isl_aff *aff);
+__isl_give isl_space *isl_aff_get_space(__isl_keep isl_aff *aff);
+__isl_give isl_local_space *isl_aff_get_domain_local_space(
+	__isl_keep isl_aff *aff);
+__isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff);
+
+const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_val *isl_aff_get_constant_val(__isl_keep isl_aff *aff);
+__isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff,
+	enum isl_dim_type type, int pos);
+int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff,
+	enum isl_dim_type type, int pos);
+__isl_give isl_val *isl_aff_get_denominator_val(__isl_keep isl_aff *aff);
+__isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v);
+__isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff,
+	__isl_take isl_val *v);
+__isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, int v);
+__isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, __isl_take isl_val *v);
+__isl_give isl_aff *isl_aff_add_constant_si(__isl_take isl_aff *aff, int v);
+__isl_give isl_aff *isl_aff_add_constant_val(__isl_take isl_aff *aff,
+	__isl_take isl_val *v);
+__isl_give isl_aff *isl_aff_add_constant_num_si(__isl_take isl_aff *aff, int v);
+__isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, int v);
+__isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, __isl_take isl_val *v);
+
+int isl_aff_is_cst(__isl_keep isl_aff *aff);
+
+__isl_give isl_aff *isl_aff_set_tuple_id(__isl_take isl_aff *aff,
+	enum isl_dim_type type, __isl_take isl_id *id);
+__isl_give isl_aff *isl_aff_set_dim_name(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned pos, const char *s);
+__isl_give isl_aff *isl_aff_set_dim_id(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned pos, __isl_take 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_aff_plain_is_equal(__isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2);
+int isl_aff_plain_is_zero(__isl_keep isl_aff *aff);
+int isl_aff_is_nan(__isl_keep isl_aff *aff);
+
+__isl_give isl_aff *isl_aff_get_div(__isl_keep isl_aff *aff, int pos);
+
+__isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff);
+__isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff);
+__isl_give isl_aff *isl_aff_floor(__isl_take isl_aff *aff);
+__isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff,
+	__isl_take isl_val *mod);
+
+__isl_give isl_aff *isl_aff_mul(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2);
+__isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2);
+__isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2);
+__isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2);
+
+__isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff,
+	__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(__isl_take isl_aff *aff,
+	__isl_take isl_val *v);
+
+__isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned n);
+__isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_aff *isl_aff_project_domain_on_params(__isl_take isl_aff *aff);
+
+__isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff,
+	__isl_take isl_space *model);
+
+__isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff,
+	__isl_take isl_set *context);
+__isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff,
+	__isl_take isl_set *context);
+
+__isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2);
+__isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
+	__isl_take isl_multi_aff *ma);
+
+__isl_give isl_basic_set *isl_aff_zero_basic_set(__isl_take isl_aff *aff);
+__isl_give isl_basic_set *isl_aff_neg_basic_set(__isl_take isl_aff *aff);
+
+__isl_give isl_basic_set *isl_aff_le_basic_set(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2);
+__isl_give isl_basic_set *isl_aff_ge_basic_set(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2);
+
+__isl_give isl_aff *isl_aff_read_from_str(isl_ctx *ctx, const char *str);
+__isl_give isl_printer *isl_printer_print_aff(__isl_take isl_printer *p,
+	__isl_keep isl_aff *aff);
+void isl_aff_dump(__isl_keep isl_aff *aff);
+
+isl_ctx *isl_pw_aff_get_ctx(__isl_keep isl_pw_aff *pwaff);
+__isl_give isl_space *isl_pw_aff_get_domain_space(__isl_keep isl_pw_aff *pwaff);
+__isl_give isl_space *isl_pw_aff_get_space(__isl_keep isl_pw_aff *pwaff);
+
+__isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff);
+__isl_give isl_pw_aff *isl_pw_aff_empty(__isl_take isl_space *dim);
+__isl_give isl_pw_aff *isl_pw_aff_alloc(__isl_take isl_set *set,
+	__isl_take isl_aff *aff);
+__isl_give isl_pw_aff *isl_pw_aff_zero_on_domain(
+	__isl_take isl_local_space *ls);
+__isl_give isl_pw_aff *isl_pw_aff_var_on_domain(__isl_take isl_local_space *ls,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(__isl_take isl_local_space *ls);
+__isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
+	__isl_take isl_val *v);
+
+__isl_give isl_pw_aff *isl_set_indicator_function(__isl_take isl_set *set);
+
+const char *isl_pw_aff_get_dim_name(__isl_keep isl_pw_aff *pa,
+	enum isl_dim_type type, unsigned pos);
+int isl_pw_aff_has_dim_id(__isl_keep isl_pw_aff *pa,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_pw_aff_get_dim_id(__isl_keep isl_pw_aff *pa,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_pw_aff *isl_pw_aff_set_dim_id(__isl_take isl_pw_aff *pma,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+
+int isl_pw_aff_find_dim_by_name(__isl_keep isl_pw_aff *pa,
+	enum isl_dim_type type, const char *name);
+
+int isl_pw_aff_is_empty(__isl_keep isl_pw_aff *pwaff);
+int isl_pw_aff_involves_nan(__isl_keep isl_pw_aff *pa);
+int isl_pw_aff_plain_cmp(__isl_keep isl_pw_aff *pa1,
+	__isl_keep isl_pw_aff *pa2);
+int isl_pw_aff_plain_is_equal(__isl_keep isl_pw_aff *pwaff1,
+	__isl_keep isl_pw_aff *pwaff2);
+int isl_pw_aff_is_equal(__isl_keep isl_pw_aff *pa1, __isl_keep isl_pw_aff *pa2);
+
+__isl_give isl_pw_aff *isl_pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+
+__isl_give isl_pw_aff *isl_pw_aff_copy(__isl_keep isl_pw_aff *pwaff);
+__isl_null isl_pw_aff *isl_pw_aff_free(__isl_take isl_pw_aff *pwaff);
+
+unsigned isl_pw_aff_dim(__isl_keep isl_pw_aff *pwaff, enum isl_dim_type type);
+int isl_pw_aff_involves_dims(__isl_keep isl_pw_aff *pwaff,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+int isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff);
+
+__isl_give isl_pw_aff *isl_pw_aff_align_params(__isl_take isl_pw_aff *pwaff,
+	__isl_take isl_space *model);
+
+int isl_pw_aff_has_tuple_id(__isl_keep isl_pw_aff *pa, enum isl_dim_type type);
+__isl_give isl_id *isl_pw_aff_get_tuple_id(__isl_keep isl_pw_aff *pa,
+	enum isl_dim_type type);
+__isl_give isl_pw_aff *isl_pw_aff_set_tuple_id(__isl_take isl_pw_aff *pwaff,
+	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_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);
+__isl_give isl_pw_aff *isl_pw_aff_from_range(__isl_take isl_pw_aff *pwa);
+
+__isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1,
+	__isl_take isl_pw_aff *pa2);
+__isl_give isl_pw_aff *isl_pw_aff_add(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_pw_aff *isl_pw_aff_sub(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_pw_aff *isl_pw_aff_neg(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_pw_aff *isl_pw_aff_ceil(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_pw_aff *isl_pw_aff_floor(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_pw_aff *isl_pw_aff_mod_val(__isl_take isl_pw_aff *pa,
+	__isl_take isl_val *mod);
+__isl_give isl_pw_aff *isl_pw_aff_tdiv_q(__isl_take isl_pw_aff *pa1,
+	__isl_take isl_pw_aff *pa2);
+__isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1,
+	__isl_take isl_pw_aff *pa2);
+
+__isl_give isl_pw_aff *isl_pw_aff_intersect_params(__isl_take isl_pw_aff *pa,
+	__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_cond(__isl_take isl_pw_aff *cond,
+	__isl_take isl_pw_aff *pwaff_true, __isl_take isl_pw_aff *pwaff_false);
+
+__isl_give isl_pw_aff *isl_pw_aff_scale_val(__isl_take isl_pw_aff *pa,
+	__isl_take isl_val *v);
+__isl_give isl_pw_aff *isl_pw_aff_scale_down_val(__isl_take isl_pw_aff *pa,
+	__isl_take isl_val *f);
+
+__isl_give isl_pw_aff *isl_pw_aff_insert_dims(__isl_take isl_pw_aff *pwaff,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_pw_aff *isl_pw_aff_add_dims(__isl_take isl_pw_aff *pwaff,
+	enum isl_dim_type type, unsigned n);
+__isl_give isl_pw_aff *isl_pw_aff_move_dims(__isl_take isl_pw_aff *pa,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_pw_aff *isl_pw_aff_drop_dims(__isl_take isl_pw_aff *pwaff,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_pw_aff *isl_pw_aff_coalesce(__isl_take isl_pw_aff *pwqp);
+__isl_give isl_pw_aff *isl_pw_aff_gist(__isl_take isl_pw_aff *pwaff,
+	__isl_take isl_set *context);
+__isl_give isl_pw_aff *isl_pw_aff_gist_params(__isl_take isl_pw_aff *pwaff,
+	__isl_take isl_set *context);
+
+__isl_give isl_pw_aff *isl_pw_aff_pullback_multi_aff(
+	__isl_take isl_pw_aff *pa, __isl_take isl_multi_aff *ma);
+__isl_give isl_pw_aff *isl_pw_aff_pullback_pw_multi_aff(
+	__isl_take isl_pw_aff *pa, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff(
+	__isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa);
+
+int isl_pw_aff_n_piece(__isl_keep isl_pw_aff *pwaff);
+int isl_pw_aff_foreach_piece(__isl_keep isl_pw_aff *pwaff,
+	int (*fn)(__isl_take isl_set *set, __isl_take isl_aff *aff,
+		    void *user), void *user);
+
+__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_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_set *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_set *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_set *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+__isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2);
+
+__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);
+void isl_pw_aff_dump(__isl_keep isl_pw_aff *pwaff);
+
+__isl_give isl_pw_aff *isl_pw_aff_list_min(__isl_take isl_pw_aff_list *list);
+__isl_give isl_pw_aff *isl_pw_aff_list_max(__isl_take isl_pw_aff_list *list);
+
+__isl_give isl_set *isl_pw_aff_list_eq_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2);
+__isl_give isl_set *isl_pw_aff_list_ne_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2);
+__isl_give isl_set *isl_pw_aff_list_le_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2);
+__isl_give isl_set *isl_pw_aff_list_lt_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2);
+__isl_give isl_set *isl_pw_aff_list_ge_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2);
+__isl_give isl_set *isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2);
+
+ISL_DECLARE_MULTI(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);
+__isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space);
+__isl_give isl_multi_aff *isl_multi_aff_range_map(__isl_take isl_space *space);
+__isl_give isl_multi_aff *isl_multi_aff_project_out_map(
+	__isl_take isl_space *space, enum isl_dim_type type,
+	unsigned first, unsigned n);
+
+__isl_give isl_multi_aff *isl_multi_aff_multi_val_on_space(
+	__isl_take isl_space *space, __isl_take isl_multi_val *mv);
+
+__isl_give isl_multi_aff *isl_multi_aff_floor(__isl_take isl_multi_aff *ma);
+
+__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);
+
+__isl_give isl_multi_aff *isl_multi_aff_gist_params(
+	__isl_take isl_multi_aff *maff, __isl_take isl_set *context);
+__isl_give isl_multi_aff *isl_multi_aff_gist(__isl_take isl_multi_aff *maff,
+	__isl_take isl_set *context);
+
+__isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
+	__isl_give isl_local_space **ls);
+
+__isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
+	__isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2);
+
+__isl_give isl_multi_aff *isl_multi_aff_move_dims(__isl_take isl_multi_aff *ma,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+__isl_give isl_set *isl_multi_aff_lex_le_set(__isl_take isl_multi_aff *ma1,
+	__isl_take isl_multi_aff *ma2);
+__isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
+	__isl_take isl_multi_aff *ma2);
+
+__isl_give char *isl_multi_aff_to_str(__isl_keep isl_multi_aff *aff);
+__isl_give isl_printer *isl_printer_print_multi_aff(__isl_take isl_printer *p,
+	__isl_keep isl_multi_aff *maff);
+
+__isl_give isl_multi_aff *isl_multi_aff_read_from_str(isl_ctx *ctx,
+		const char *str);
+void isl_multi_aff_dump(__isl_keep isl_multi_aff *maff);
+
+ISL_DECLARE_MULTI(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_project_out_map(
+	__isl_take isl_space *space, enum isl_dim_type type,
+	unsigned first, unsigned n);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_aff(
+	__isl_take isl_multi_aff *ma);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_pw_aff(
+	__isl_take isl_pw_aff *pa);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_alloc(__isl_take isl_set *set,
+	__isl_take isl_multi_aff *maff);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_copy(
+	__isl_keep isl_pw_multi_aff *pma);
+__isl_null isl_pw_multi_aff *isl_pw_multi_aff_free(
+	__isl_take isl_pw_multi_aff *pma);
+
+unsigned isl_pw_multi_aff_dim(__isl_keep isl_pw_multi_aff *pma,
+	enum isl_dim_type type);
+__isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff(
+	__isl_keep isl_pw_multi_aff *pma, int pos);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff(
+	__isl_take isl_pw_multi_aff *pma, unsigned pos,
+	__isl_take isl_pw_aff *pa);
+
+isl_ctx *isl_pw_multi_aff_get_ctx(__isl_keep isl_pw_multi_aff *pma);
+__isl_give isl_space *isl_pw_multi_aff_get_domain_space(
+	__isl_keep isl_pw_multi_aff *pma);
+__isl_give isl_space *isl_pw_multi_aff_get_space(
+	__isl_keep isl_pw_multi_aff *pma);
+int isl_pw_multi_aff_has_tuple_name(__isl_keep isl_pw_multi_aff *pma,
+	enum isl_dim_type type);
+const char *isl_pw_multi_aff_get_tuple_name(__isl_keep isl_pw_multi_aff *pma,
+	enum isl_dim_type type);
+__isl_give isl_id *isl_pw_multi_aff_get_tuple_id(
+	__isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type);
+int isl_pw_multi_aff_has_tuple_id(__isl_keep isl_pw_multi_aff *pma,
+	enum isl_dim_type type);
+__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_pw_multi_aff *isl_pw_multi_aff_reset_tuple_id(
+	__isl_take isl_pw_multi_aff *pma, enum isl_dim_type type);
+
+int isl_pw_multi_aff_find_dim_by_name(__isl_keep isl_pw_multi_aff *pma,
+	enum isl_dim_type type, const char *name);
+
+__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_set *isl_pw_multi_aff_domain(__isl_take isl_pw_multi_aff *pma);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_empty(__isl_take isl_space *space);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain(
+	__isl_take isl_set *set);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_multi_val_on_domain(
+	__isl_take isl_set *domain, __isl_take isl_multi_val *mv);
+
+const char *isl_pw_multi_aff_get_dim_name(__isl_keep isl_pw_multi_aff *pma,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_pw_multi_aff_get_dim_id(
+	__isl_keep isl_pw_multi_aff *pma, enum isl_dim_type type,
+	unsigned pos);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_dim_id(
+	__isl_take isl_pw_multi_aff *pma,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+
+int isl_pw_multi_aff_plain_is_equal(__isl_keep isl_pw_multi_aff *pma1,
+	__isl_keep isl_pw_multi_aff *pma2);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_fix_si(
+	__isl_take isl_pw_multi_aff *pma, enum isl_dim_type type,
+	unsigned pos, int value);
+
+__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_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(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_val(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_val *v);
+__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_pw_multi_aff *isl_pw_multi_aff_scale_multi_val(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin(
+	__isl_take isl_pw_multi_aff *pma1,
+	__isl_take isl_pw_multi_aff *pma2);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax(
+	__isl_take isl_pw_multi_aff *pma1,
+	__isl_take isl_pw_multi_aff *pma2);
+
+__isl_give isl_multi_aff *isl_multi_aff_flatten_domain(
+	__isl_take isl_multi_aff *ma);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_product(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+__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_pw_multi_aff *isl_pw_multi_aff_intersect_params(
+	__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_project_domain_on_params(
+	__isl_take isl_pw_multi_aff *pma);
+
+__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_pw_multi_aff *isl_pw_multi_aff_coalesce(
+	__isl_take isl_pw_multi_aff *pma);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_gist_params(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_gist(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_set *set);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_pullback_multi_aff(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_aff *ma);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_pullback_pw_multi_aff(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+
+int isl_pw_multi_aff_foreach_piece(__isl_keep isl_pw_multi_aff *pma,
+	int (*fn)(__isl_take isl_set *set, __isl_take isl_multi_aff *maff,
+		    void *user), void *user);
+
+__isl_give isl_map *isl_map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma);
+__isl_give isl_set *isl_set_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma);
+
+__isl_give isl_printer *isl_printer_print_pw_multi_aff(__isl_take isl_printer *p,
+	__isl_keep isl_pw_multi_aff *pma);
+
+__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(__isl_take isl_map *map);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_read_from_str(isl_ctx *ctx,
+	const char *str);
+void isl_pw_multi_aff_dump(__isl_keep isl_pw_multi_aff *pma);
+
+
+__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_pw_multi_aff(
+	__isl_take isl_pw_multi_aff *pma);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain(
+	__isl_take isl_union_set *uset);
+__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);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_copy(
+	__isl_keep isl_union_pw_multi_aff *upma);
+__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_pw_multi_aff_add_pw_multi_aff(
+	__isl_take isl_union_pw_multi_aff *upma,
+	__isl_take isl_pw_multi_aff *pma);
+
+isl_ctx *isl_union_pw_multi_aff_get_ctx(
+	__isl_keep isl_union_pw_multi_aff *upma);
+__isl_give isl_space *isl_union_pw_multi_aff_get_space(
+	__isl_keep isl_union_pw_multi_aff *upma);
+
+unsigned isl_union_pw_multi_aff_dim(__isl_keep isl_union_pw_multi_aff *upma,
+	enum isl_dim_type type);
+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_coalesce(
+	__isl_take isl_union_pw_multi_aff *upma);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_gist_params(
+	__isl_take isl_union_pw_multi_aff *upma, __isl_take isl_set *context);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_gist(
+	__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_align_params(
+	__isl_take isl_union_pw_multi_aff *upma, __isl_take isl_space *model);
+
+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);
+__isl_give isl_pw_multi_aff *isl_union_pw_multi_aff_extract_pw_multi_aff(
+	__isl_keep isl_union_pw_multi_aff *upma, __isl_take isl_space *space);
+
+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);
+
+__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_add(
+	__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_union_add(
+	__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_sub(
+	__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_scale_val(
+	__isl_take isl_union_pw_multi_aff *upma, __isl_take isl_val *val);
+__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_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val(
+	__isl_take isl_union_pw_multi_aff *upma, __isl_take isl_multi_val *mv);
+
+__isl_give isl_union_pw_multi_aff *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_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_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_map *isl_union_map_from_union_pw_multi_aff(
+	__isl_take isl_union_pw_multi_aff *upma);
+
+__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_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_set(
+	__isl_take isl_union_set *uset);
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_map(
+	__isl_take isl_union_map *umap);
+
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_read_from_str(
+	isl_ctx *ctx, const char *str);
+void isl_union_pw_multi_aff_dump(__isl_keep isl_union_pw_multi_aff *upma);
+__isl_give char *isl_union_pw_multi_aff_to_str(
+	__isl_keep isl_union_pw_multi_aff *upma);
+
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_identity(
+	__isl_take isl_space *space);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
+	__isl_take isl_multi_aff *ma);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_aff(
+	__isl_take isl_pw_aff *pa);
+__isl_give isl_set *isl_multi_pw_aff_domain(__isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_intersect_params(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_set *set);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_intersect_domain(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_set *domain);
+
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_coalesce(
+	__isl_take isl_multi_pw_aff *mpa);
+__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_multi_pw_aff *isl_multi_pw_aff_gist_params(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_set *set);
+
+int isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff *mpa1,
+	__isl_keep isl_multi_pw_aff *mpa2);
+
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_pw_multi_aff(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_multi_pw_aff *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_multi_pw_aff *isl_multi_pw_aff_move_dims(
+	__isl_take isl_multi_pw_aff *pma,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+__isl_give isl_set *isl_set_from_multi_pw_aff(__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_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff(
+	__isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
+	__isl_take isl_pw_multi_aff *pma);
+
+__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);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/aff_type.h (added)
+++ polly/trunk/lib/External/isl/include/isl/aff_type.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,36 @@
+#ifndef ISL_AFF_TYPE_H
+#define ISL_AFF_TYPE_H
+
+#include <isl/list.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_aff;
+typedef struct isl_aff isl_aff;
+
+ISL_DECLARE_LIST(aff)
+
+struct isl_pw_aff;
+typedef struct isl_pw_aff isl_pw_aff;
+
+ISL_DECLARE_LIST(pw_aff)
+
+struct isl_multi_aff;
+typedef struct isl_multi_aff isl_multi_aff;
+
+struct isl_pw_multi_aff;
+typedef struct isl_pw_multi_aff isl_pw_multi_aff;
+
+struct isl_union_pw_multi_aff;
+typedef struct isl_union_pw_multi_aff isl_union_pw_multi_aff;
+
+struct isl_multi_pw_aff;
+typedef struct isl_multi_pw_aff isl_multi_pw_aff;
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/arg.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/arg.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/arg.h (added)
+++ polly/trunk/lib/External/isl/include/isl/arg.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_ARG_H
+#define ISL_ARG_H
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_arg_choice {
+	const char	*name;
+	unsigned	 value;
+};
+
+struct isl_arg_flags {
+	const char	*name;
+	unsigned	 mask;
+	unsigned	 value;
+};
+
+enum isl_arg_type {
+	isl_arg_end,
+	isl_arg_alias,
+	isl_arg_arg,
+	isl_arg_bool,
+	isl_arg_child,
+	isl_arg_choice,
+	isl_arg_flags,
+	isl_arg_footer,
+	isl_arg_int,
+	isl_arg_user,
+	isl_arg_long,
+	isl_arg_ulong,
+	isl_arg_str,
+	isl_arg_str_list,
+	isl_arg_version
+};
+
+struct isl_args;
+
+struct isl_arg {
+	enum isl_arg_type	 type;
+	char			 short_name;
+	const char		*long_name;
+	const char		*argument_name;
+	size_t			 offset;
+	const char		*help_msg;
+#define ISL_ARG_SINGLE_DASH	(1 << 0)
+#define ISL_ARG_BOOL_ARG	(1 << 1)
+#define ISL_ARG_HIDDEN		(1 << 2)
+	unsigned		 flags;
+	union {
+	struct {
+		struct isl_arg_choice	*choice;
+		unsigned	 	 default_value;
+		unsigned	 	 default_selected;
+		int (*set)(void *opt, unsigned val);
+	} choice;
+	struct {
+		struct isl_arg_flags	*flags;
+		unsigned	 	 default_value;
+	} flags;
+	struct {
+		unsigned		 default_value;
+		int (*set)(void *opt, unsigned val);
+	} b;
+	struct {
+		int			default_value;
+	} i;
+	struct {
+		long		 	default_value;
+		long		 	default_selected;
+		int (*set)(void *opt, long val);
+	} l;
+	struct {
+		unsigned long		default_value;
+	} ul;
+	struct {
+		const char		*default_value;
+	} str;
+	struct {
+		size_t			 offset_n;
+	} str_list;
+	struct {
+		struct isl_args		*child;
+	} child;
+	struct {
+		void (*print_version)(void);
+	} version;
+	struct {
+		int (*init)(void*);
+		void (*clear)(void*);
+	} user;
+	} u;
+};
+
+struct isl_args {
+	size_t			 options_size;
+	struct isl_arg		*args;
+};
+
+#define ISL_ARGS_START(s,name)						\
+	struct isl_arg name ## LIST[];					\
+	struct isl_args name = { sizeof(s), name ## LIST };		\
+	struct isl_arg name ## LIST[] = {
+#define ISL_ARGS_END							\
+	{ isl_arg_end } };
+
+#define ISL_ARG_ALIAS(l)	{					\
+	.type = isl_arg_alias,						\
+	.long_name = l,							\
+},
+#define ISL_ARG_ARG(st,f,a,d)	{					\
+	.type = isl_arg_arg,						\
+	.argument_name = a,						\
+	.offset = offsetof(st, f),					\
+	.u = { .str = { .default_value = d } }				\
+},
+#define ISL_ARG_FOOTER(h)	{					\
+	.type = isl_arg_footer,						\
+	.help_msg = h,							\
+},
+#define ISL_ARG_CHOICE(st,f,s,l,c,d,h)	{				\
+	.type = isl_arg_choice,						\
+	.short_name = s,						\
+	.long_name = l,							\
+	.offset = offsetof(st, f),					\
+	.help_msg = h,							\
+	.u = { .choice = { .choice = c, .default_value = d,		\
+			    .default_selected = d, .set = NULL } }	\
+},
+#define ISL_ARG_OPT_CHOICE(st,f,s,l,c,d,ds,h)	{			\
+	.type = isl_arg_choice,						\
+	.short_name = s,						\
+	.long_name = l,							\
+	.offset = offsetof(st, f),					\
+	.help_msg = h,							\
+	.u = { .choice = { .choice = c, .default_value = d,		\
+			    .default_selected = ds, .set = NULL } }	\
+},
+#define ISL_ARG_USER_OPT_CHOICE(st,f,s,l,c,setter,d,ds,h)	{	\
+	.type = isl_arg_choice,						\
+	.short_name = s,						\
+	.long_name = l,							\
+	.offset = offsetof(st, f),					\
+	.help_msg = h,							\
+	.u = { .choice = { .choice = c, .default_value = d,		\
+			    .default_selected = ds, .set = setter } }	\
+},
+#define _ISL_ARG_BOOL_F(o,s,l,setter,d,h,fl)	{			\
+	.type = isl_arg_bool,						\
+	.short_name = s,						\
+	.long_name = l,							\
+	.offset = o,							\
+	.help_msg = h,							\
+	.flags = fl,							\
+	.u = { .b = { .default_value = d, .set = setter } }		\
+},
+#define ISL_ARG_BOOL_F(st,f,s,l,d,h,fl)					\
+	_ISL_ARG_BOOL_F(offsetof(st, f),s,l,NULL,d,h,fl)
+#define ISL_ARG_BOOL(st,f,s,l,d,h)					\
+	ISL_ARG_BOOL_F(st,f,s,l,d,h,0)
+#define ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,fl)				\
+	_ISL_ARG_BOOL_F(-1,s,l,setter,0,h,fl)
+#define ISL_ARG_PHANTOM_BOOL(s,l,setter,h)				\
+	ISL_ARG_PHANTOM_BOOL_F(s,l,setter,h,0)
+#define ISL_ARG_INT_F(st,f,s,l,a,d,h,fl)	{			\
+	.type = isl_arg_int,						\
+	.short_name = s,						\
+	.long_name = l,							\
+	.argument_name = a,						\
+	.offset = offsetof(st, f),					\
+	.help_msg = h,							\
+	.flags = fl,							\
+	.u = { .ul = { .default_value = d } }				\
+},
+#define ISL_ARG_INT(st,f,s,l,a,d,h)					\
+	ISL_ARG_INT_F(st,f,s,l,a,d,h,0)
+#define ISL_ARG_LONG(st,f,s,lo,d,h)	{				\
+	.type = isl_arg_long,						\
+	.short_name = s,						\
+	.long_name = lo,						\
+	.offset = offsetof(st, f),					\
+	.help_msg = h,							\
+	.u = { .l = { .default_value = d, .default_selected = d,	\
+		      .set = NULL } }					\
+},
+#define ISL_ARG_USER_LONG(st,f,s,lo,setter,d,h)	{			\
+	.type = isl_arg_long,						\
+	.short_name = s,						\
+	.long_name = lo,						\
+	.offset = offsetof(st, f),					\
+	.help_msg = h,							\
+	.u = { .l = { .default_value = d, .default_selected = d,	\
+		      .set = setter } }					\
+},
+#define ISL_ARG_OPT_LONG(st,f,s,lo,d,ds,h)	{			\
+	.type = isl_arg_long,						\
+	.short_name = s,						\
+	.long_name = lo,						\
+	.offset = offsetof(st, f),					\
+	.help_msg = h,							\
+	.u = { .l = { .default_value = d, .default_selected = ds,	\
+		      .set = NULL } }					\
+},
+#define ISL_ARG_ULONG(st,f,s,l,d,h)	{				\
+	.type = isl_arg_ulong,						\
+	.short_name = s,						\
+	.long_name = l,							\
+	.offset = offsetof(st, f),					\
+	.help_msg = h,							\
+	.u = { .ul = { .default_value = d } }				\
+},
+#define ISL_ARG_STR_F(st,f,s,l,a,d,h,fl)	{			\
+	.type = isl_arg_str,						\
+	.short_name = s,						\
+	.long_name = l,							\
+	.argument_name = a,						\
+	.offset = offsetof(st, f),					\
+	.help_msg = h,							\
+	.flags = fl,							\
+	.u = { .str = { .default_value = d } }				\
+},
+#define ISL_ARG_STR(st,f,s,l,a,d,h)					\
+	ISL_ARG_STR_F(st,f,s,l,a,d,h,0)
+#define ISL_ARG_STR_LIST(st,f_n,f_l,s,l,a,h)	{			\
+	.type = isl_arg_str_list,					\
+	.short_name = s,						\
+	.long_name = l,							\
+	.argument_name = a,						\
+	.offset = offsetof(st, f_l),					\
+	.help_msg = h,							\
+	.u = { .str_list = { .offset_n = offsetof(st, f_n) } }		\
+},
+#define _ISL_ARG_CHILD(o,l,c,h,fl)	{				\
+	.type = isl_arg_child,						\
+	.long_name = l,							\
+	.offset = o,							\
+	.help_msg = h,							\
+	.flags = fl,							\
+	.u = { .child = { .child = c } }				\
+},
+#define ISL_ARG_CHILD(st,f,l,c,h)					\
+	_ISL_ARG_CHILD(offsetof(st, f),l,c,h,0)
+#define ISL_ARG_GROUP_F(l,c,h,fl)					\
+	_ISL_ARG_CHILD(-1,l,c,h,fl)
+#define ISL_ARG_GROUP(l,c,h)						\
+	ISL_ARG_GROUP_F(l,c,h,0)
+#define ISL_ARG_FLAGS(st,f,s,l,c,d,h)	{				\
+	.type = isl_arg_flags,						\
+	.short_name = s,						\
+	.long_name = l,							\
+	.offset = offsetof(st, f),					\
+	.help_msg = h,							\
+	.u = { .flags = { .flags = c, .default_value = d } }		\
+},
+#define ISL_ARG_USER(st,f,i,c) {					\
+	.type = isl_arg_user,						\
+	.offset = offsetof(st, f),					\
+	.u = { .user = { .init = i, .clear = c} }			\
+},
+#define ISL_ARG_VERSION(print) {					\
+	.type = isl_arg_version,					\
+	.u = { .version = { .print_version = print } }			\
+},
+
+#define ISL_ARG_ALL		(1 << 0)
+#define ISL_ARG_SKIP_HELP	(1 << 1)
+
+void isl_args_set_defaults(struct isl_args *args, void *opt);
+void isl_args_free(struct isl_args *args, void *opt);
+int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
+	unsigned flags);
+
+#define ISL_ARG_DECL(prefix,st,args)					\
+extern struct isl_args args;						\
+st *prefix ## _new_with_defaults(void);					\
+void prefix ## _free(st *opt);						\
+int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags);
+
+#define ISL_ARG_DEF(prefix,st,args)					\
+st *prefix ## _new_with_defaults()					\
+{									\
+	st *opt = (st *)calloc(1, sizeof(st));				\
+	if (opt)							\
+		isl_args_set_defaults(&(args), opt);			\
+	return opt;							\
+}									\
+									\
+void prefix ## _free(st *opt)						\
+{									\
+	isl_args_free(&(args), opt);					\
+}									\
+									\
+int prefix ## _parse(st *opt, int argc, char **argv, unsigned flags)	\
+{									\
+	return isl_args_parse(&(args), argc, argv, opt, flags);		\
+}
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/ast.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/ast.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/ast.h (added)
+++ polly/trunk/lib/External/isl/include/isl/ast.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,159 @@
+#ifndef ISL_AST_H
+#define ISL_AST_H
+
+#include <isl/ctx.h>
+#include <isl/ast_type.h>
+#include <isl/id.h>
+#include <isl/id_to_ast_expr.h>
+#include <isl/val.h>
+#include <isl/list.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_options_set_ast_iterator_type(isl_ctx *ctx, const char *val);
+const char *isl_options_get_ast_iterator_type(isl_ctx *ctx);
+
+int isl_options_set_ast_always_print_block(isl_ctx *ctx, int val);
+int isl_options_get_ast_always_print_block(isl_ctx *ctx);
+
+__isl_give isl_ast_expr *isl_ast_expr_from_val(__isl_take isl_val *v);
+__isl_give isl_ast_expr *isl_ast_expr_from_id(__isl_take isl_id *id);
+__isl_give isl_ast_expr *isl_ast_expr_neg(__isl_take isl_ast_expr *expr);
+__isl_give isl_ast_expr *isl_ast_expr_add(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_sub(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_mul(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_le(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_lt(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_ge(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_gt(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_eq(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2);
+__isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
+	__isl_take isl_ast_expr_list *indices);
+__isl_give isl_ast_expr *isl_ast_expr_address_of(__isl_take isl_ast_expr *expr);
+
+__isl_give isl_ast_expr *isl_ast_expr_copy(__isl_keep isl_ast_expr *expr);
+__isl_null isl_ast_expr *isl_ast_expr_free(__isl_take isl_ast_expr *expr);
+
+isl_ctx *isl_ast_expr_get_ctx(__isl_keep isl_ast_expr *expr);
+enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr);
+__isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr);
+__isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr);
+
+enum isl_ast_op_type isl_ast_expr_get_op_type(__isl_keep isl_ast_expr *expr);
+int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr);
+__isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
+	int pos);
+__isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,
+	int pos, __isl_take isl_ast_expr *arg);
+
+int isl_ast_expr_is_equal(__isl_keep isl_ast_expr *expr1,
+	__isl_keep isl_ast_expr *expr2);
+
+__isl_give isl_ast_expr *isl_ast_expr_substitute_ids(
+	__isl_take isl_ast_expr *expr, __isl_take isl_id_to_ast_expr *id2expr);
+
+__isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
+	__isl_keep isl_ast_expr *expr);
+void isl_ast_expr_dump(__isl_keep isl_ast_expr *expr);
+__isl_give char *isl_ast_expr_to_str(__isl_keep isl_ast_expr *expr);
+
+__isl_give isl_ast_node *isl_ast_node_alloc_user(__isl_take isl_ast_expr *expr);
+__isl_give isl_ast_node *isl_ast_node_copy(__isl_keep isl_ast_node *node);
+__isl_null isl_ast_node *isl_ast_node_free(__isl_take isl_ast_node *node);
+
+isl_ctx *isl_ast_node_get_ctx(__isl_keep isl_ast_node *node);
+enum isl_ast_node_type isl_ast_node_get_type(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_node *isl_ast_node_set_annotation(
+	__isl_take isl_ast_node *node, __isl_take isl_id *annotation);
+__isl_give isl_id *isl_ast_node_get_annotation(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
+	__isl_keep isl_ast_node *node);
+__isl_give isl_ast_expr *isl_ast_node_for_get_init(
+	__isl_keep isl_ast_node *node);
+__isl_give isl_ast_expr *isl_ast_node_for_get_cond(
+	__isl_keep isl_ast_node *node);
+__isl_give isl_ast_expr *isl_ast_node_for_get_inc(
+	__isl_keep isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_for_get_body(
+	__isl_keep isl_ast_node *node);
+int isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_expr *isl_ast_node_if_get_cond(
+	__isl_keep isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_if_get_then(
+	__isl_keep isl_ast_node *node);
+int isl_ast_node_if_has_else(__isl_keep isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_if_get_else(
+	__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_node_list *isl_ast_node_block_get_children(
+	__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_expr *isl_ast_node_user_get_expr(
+	__isl_keep isl_ast_node *node);
+
+__isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,
+	__isl_keep isl_ast_node *node);
+void isl_ast_node_dump(__isl_keep isl_ast_node *node);
+
+__isl_give isl_ast_print_options *isl_ast_print_options_alloc(isl_ctx *ctx);
+__isl_give isl_ast_print_options *isl_ast_print_options_copy(
+	__isl_keep isl_ast_print_options *options);
+__isl_null isl_ast_print_options *isl_ast_print_options_free(
+	__isl_take isl_ast_print_options *options);
+isl_ctx *isl_ast_print_options_get_ctx(
+	__isl_keep isl_ast_print_options *options);
+
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_user(
+	__isl_take isl_ast_print_options *options,
+	__isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
+		__isl_take isl_ast_print_options *options,
+		__isl_keep isl_ast_node *node, void *user),
+	void *user);
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_for(
+	__isl_take isl_ast_print_options *options,
+	__isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
+		__isl_take isl_ast_print_options *options,
+		__isl_keep isl_ast_node *node, void *user),
+	void *user);
+
+int isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
+	int (*fn)(enum isl_ast_op_type type, void *user), void *user);
+__isl_give isl_printer *isl_ast_op_type_print_macro(
+	enum isl_ast_op_type type, __isl_take isl_printer *p);
+__isl_give isl_printer *isl_ast_node_print_macros(
+	__isl_keep isl_ast_node *node, __isl_take isl_printer *p);
+__isl_give isl_printer *isl_ast_node_print(__isl_keep isl_ast_node *node,
+	__isl_take isl_printer *p,
+	__isl_take isl_ast_print_options *options);
+__isl_give isl_printer *isl_ast_node_for_print(__isl_keep isl_ast_node *node,
+	__isl_take isl_printer *p,
+	__isl_take isl_ast_print_options *options);
+__isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,
+	__isl_take isl_printer *p,
+	__isl_take isl_ast_print_options *options);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/ast_build.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/ast_build.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/ast_build.h (added)
+++ polly/trunk/lib/External/isl/include/isl/ast_build.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,100 @@
+#ifndef ISL_AST_CONTEXT_H
+#define ISL_AST_CONTEXT_H
+
+#include <isl/ctx.h>
+#include <isl/set.h>
+#include <isl/ast.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_ast_build;
+typedef struct isl_ast_build isl_ast_build;
+
+
+int isl_options_set_ast_build_atomic_upper_bound(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_atomic_upper_bound(isl_ctx *ctx);
+
+int isl_options_set_ast_build_prefer_pdiv(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_prefer_pdiv(isl_ctx *ctx);
+
+int isl_options_set_ast_build_exploit_nested_bounds(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_exploit_nested_bounds(isl_ctx *ctx);
+
+int isl_options_set_ast_build_group_coscheduled(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_group_coscheduled(isl_ctx *ctx);
+
+#define ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT		0
+#define ISL_AST_BUILD_SEPARATION_BOUNDS_IMPLICIT		1
+int isl_options_set_ast_build_separation_bounds(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_separation_bounds(isl_ctx *ctx);
+
+int isl_options_set_ast_build_scale_strides(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_scale_strides(isl_ctx *ctx);
+
+int isl_options_set_ast_build_allow_else(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_allow_else(isl_ctx *ctx);
+
+int isl_options_set_ast_build_allow_or(isl_ctx *ctx, int val);
+int isl_options_get_ast_build_allow_or(isl_ctx *ctx);
+
+isl_ctx *isl_ast_build_get_ctx(__isl_keep isl_ast_build *build);
+
+__isl_give isl_ast_build *isl_ast_build_from_context(__isl_take isl_set *set);
+
+__isl_give isl_space *isl_ast_build_get_schedule_space(
+	__isl_keep isl_ast_build *build);
+__isl_give isl_union_map *isl_ast_build_get_schedule(
+	__isl_keep isl_ast_build *build);
+
+__isl_give isl_ast_build *isl_ast_build_restrict(
+	__isl_take isl_ast_build *build, __isl_take isl_set *set);
+
+__isl_give isl_ast_build *isl_ast_build_copy(
+	__isl_keep isl_ast_build *build);
+__isl_null isl_ast_build *isl_ast_build_free(
+	__isl_take isl_ast_build *build);
+
+__isl_give isl_ast_build *isl_ast_build_set_options(
+	__isl_take isl_ast_build *build,
+	__isl_take isl_union_map *options);
+__isl_give isl_ast_build *isl_ast_build_set_iterators(
+	__isl_take isl_ast_build *build,
+	__isl_take isl_id_list *iterators);
+__isl_give isl_ast_build *isl_ast_build_set_at_each_domain(
+	__isl_take isl_ast_build *build,
+	__isl_give isl_ast_node *(*fn)(__isl_take isl_ast_node *node,
+		__isl_keep isl_ast_build *build, void *user), void *user);
+__isl_give isl_ast_build *isl_ast_build_set_before_each_for(
+	__isl_take isl_ast_build *build,
+	__isl_give isl_id *(*fn)(__isl_keep isl_ast_build *build,
+		void *user), void *user);
+__isl_give isl_ast_build *isl_ast_build_set_after_each_for(
+	__isl_take isl_ast_build *build,
+	__isl_give isl_ast_node *(*fn)(__isl_take isl_ast_node *node,
+		__isl_keep isl_ast_build *build, void *user), void *user);
+__isl_give isl_ast_build *isl_ast_build_set_create_leaf(
+	__isl_take isl_ast_build *build,
+	__isl_give isl_ast_node *(*fn)(__isl_take isl_ast_build *build,
+		void *user), void *user);
+
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa);
+__isl_give isl_ast_expr *isl_ast_build_access_from_pw_multi_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_ast_expr *isl_ast_build_access_from_multi_pw_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_ast_expr *isl_ast_build_call_from_multi_pw_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa);
+
+__isl_give isl_ast_node *isl_ast_build_ast_from_schedule(
+	__isl_keep isl_ast_build *build, __isl_take isl_union_map *schedule);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/ast_type.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/ast_type.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/ast_type.h (added)
+++ polly/trunk/lib/External/isl/include/isl/ast_type.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,71 @@
+#ifndef ISL_AST_TYPE_H
+#define ISL_AST_TYPE_H
+
+#include <isl/list.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_ast_expr;
+typedef struct isl_ast_expr isl_ast_expr;
+
+struct isl_ast_node;
+typedef struct isl_ast_node isl_ast_node;
+
+enum isl_ast_op_type {
+	isl_ast_op_error = -1,
+	isl_ast_op_and,
+	isl_ast_op_and_then,
+	isl_ast_op_or,
+	isl_ast_op_or_else,
+	isl_ast_op_max,
+	isl_ast_op_min,
+	isl_ast_op_minus,
+	isl_ast_op_add,
+	isl_ast_op_sub,
+	isl_ast_op_mul,
+	isl_ast_op_div,
+	isl_ast_op_fdiv_q,	/* Round towards -infty */
+	isl_ast_op_pdiv_q,	/* Dividend is non-negative */
+	isl_ast_op_pdiv_r,	/* Dividend is non-negative */
+	isl_ast_op_zdiv_r,	/* Result only compared against zero */
+	isl_ast_op_cond,
+	isl_ast_op_select,
+	isl_ast_op_eq,
+	isl_ast_op_le,
+	isl_ast_op_lt,
+	isl_ast_op_ge,
+	isl_ast_op_gt,
+	isl_ast_op_call,
+	isl_ast_op_access,
+	isl_ast_op_member,
+	isl_ast_op_address_of
+};
+
+enum isl_ast_expr_type {
+	isl_ast_expr_error = -1,
+	isl_ast_expr_op,
+	isl_ast_expr_id,
+	isl_ast_expr_int
+};
+
+enum isl_ast_node_type {
+	isl_ast_node_error = -1,
+	isl_ast_node_for = 1,
+	isl_ast_node_if,
+	isl_ast_node_block,
+	isl_ast_node_user
+};
+
+struct isl_ast_print_options;
+typedef struct isl_ast_print_options isl_ast_print_options;
+
+ISL_DECLARE_LIST(ast_expr)
+ISL_DECLARE_LIST(ast_node)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/band.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/band.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/band.h (added)
+++ polly/trunk/lib/External/isl/include/isl/band.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,56 @@
+#ifndef ISL_BAND_H
+#define ISL_BAND_H
+
+#include <isl/printer.h>
+#include <isl/list.h>
+#include <isl/union_map_type.h>
+#include <isl/vec.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_band;
+typedef struct isl_band isl_band;
+
+ISL_DECLARE_LIST(band)
+
+__isl_give isl_band *isl_band_copy(__isl_keep isl_band *band);
+__isl_null isl_band *isl_band_free(__isl_take isl_band *band);
+
+isl_ctx *isl_band_get_ctx(__isl_keep isl_band *band);
+
+int isl_band_has_children(__isl_keep isl_band *band);
+__isl_give isl_band_list *isl_band_get_children(
+	__isl_keep isl_band *band);
+
+__isl_give isl_union_map *isl_band_get_prefix_schedule(
+	__isl_keep isl_band *band);
+__isl_give isl_union_map *isl_band_get_partial_schedule(
+	__isl_keep isl_band *band);
+__isl_give isl_union_map *isl_band_get_suffix_schedule(
+	__isl_keep isl_band *band);
+
+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);
+
+int isl_band_tile(__isl_keep isl_band *band, __isl_take isl_vec *sizes);
+int isl_band_split(__isl_keep isl_band *band, int pos);
+
+int isl_band_n_member(__isl_keep isl_band *band);
+int isl_band_member_is_coincident(__isl_keep isl_band *band, int pos);
+
+int isl_band_list_foreach_band(__isl_keep isl_band_list *list,
+	int (*fn)(__isl_keep isl_band *band, void *user), void *user);
+
+__isl_give isl_printer *isl_printer_print_band(__isl_take isl_printer *p,
+	__isl_keep isl_band *band);
+void isl_band_dump(__isl_keep isl_band *band);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/constraint.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/constraint.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/constraint.h (added)
+++ polly/trunk/lib/External/isl/include/isl/constraint.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_CONSTRAINT_H
+#define ISL_CONSTRAINT_H
+
+#include <isl/local_space.h>
+#include <isl/space.h>
+#include <isl/aff_type.h>
+#include <isl/set_type.h>
+#include <isl/list.h>
+#include <isl/val.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_constraint;
+typedef struct isl_constraint isl_constraint;
+
+ISL_DECLARE_LIST(constraint)
+
+isl_ctx *isl_constraint_get_ctx(__isl_keep isl_constraint *c);
+
+__isl_give isl_constraint *isl_equality_alloc(__isl_take isl_local_space *ls);
+__isl_give isl_constraint *isl_inequality_alloc(__isl_take isl_local_space *ls);
+
+struct isl_constraint *isl_constraint_cow(struct isl_constraint *c);
+struct isl_constraint *isl_constraint_copy(struct isl_constraint *c);
+__isl_null isl_constraint *isl_constraint_free(__isl_take isl_constraint *c);
+
+int isl_basic_map_n_constraint(__isl_keep isl_basic_map *bmap);
+int isl_basic_set_n_constraint(__isl_keep isl_basic_set *bset);
+int isl_basic_map_foreach_constraint(__isl_keep isl_basic_map *bmap,
+	int (*fn)(__isl_take isl_constraint *c, void *user), void *user);
+int isl_basic_set_foreach_constraint(__isl_keep isl_basic_set *bset,
+	int (*fn)(__isl_take isl_constraint *c, void *user), void *user);
+__isl_give isl_constraint_list *isl_basic_map_get_constraint_list(
+	__isl_keep isl_basic_map *bmap);
+__isl_give isl_constraint_list *isl_basic_set_get_constraint_list(
+	__isl_keep isl_basic_set *bset);
+int isl_constraint_is_equal(struct isl_constraint *constraint1,
+			    struct isl_constraint *constraint2);
+
+int isl_basic_set_foreach_bound_pair(__isl_keep isl_basic_set *bset,
+	enum isl_dim_type type, unsigned pos,
+	int (*fn)(__isl_take isl_constraint *lower,
+		  __isl_take isl_constraint *upper,
+		  __isl_take isl_basic_set *bset, void *user), void *user);
+
+__isl_give isl_basic_map *isl_basic_map_add_constraint(
+	__isl_take isl_basic_map *bmap, __isl_take isl_constraint *constraint);
+__isl_give isl_basic_set *isl_basic_set_add_constraint(
+	__isl_take isl_basic_set *bset, __isl_take isl_constraint *constraint);
+__isl_give isl_map *isl_map_add_constraint(__isl_take isl_map *map,
+	__isl_take isl_constraint *constraint);
+__isl_give isl_set *isl_set_add_constraint(__isl_take isl_set *set,
+	__isl_take isl_constraint *constraint);
+
+int isl_basic_map_has_defining_equality(
+	__isl_keep isl_basic_map *bmap, enum isl_dim_type type, int pos,
+	__isl_give isl_constraint **c);
+int isl_basic_set_has_defining_equality(
+	struct isl_basic_set *bset, enum isl_dim_type type, int pos,
+	struct isl_constraint **constraint);
+int isl_basic_set_has_defining_inequalities(
+	struct isl_basic_set *bset, enum isl_dim_type type, int pos,
+	struct isl_constraint **lower,
+	struct isl_constraint **upper);
+
+__isl_give isl_space *isl_constraint_get_space(
+	__isl_keep isl_constraint *constraint);
+__isl_give isl_local_space *isl_constraint_get_local_space(
+	__isl_keep isl_constraint *constraint);
+int isl_constraint_dim(struct isl_constraint *constraint,
+	enum isl_dim_type type);
+
+int isl_constraint_involves_dims(__isl_keep isl_constraint *constraint,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+const char *isl_constraint_get_dim_name(__isl_keep isl_constraint *constraint,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_val *isl_constraint_get_constant_val(
+	__isl_keep isl_constraint *constraint);
+__isl_give isl_val *isl_constraint_get_coefficient_val(
+	__isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos);
+__isl_give isl_constraint *isl_constraint_set_constant_si(
+	__isl_take isl_constraint *constraint, int v);
+__isl_give isl_constraint *isl_constraint_set_constant_val(
+	__isl_take isl_constraint *constraint, __isl_take isl_val *v);
+__isl_give isl_constraint *isl_constraint_set_coefficient_si(
+	__isl_take isl_constraint *constraint,
+	enum isl_dim_type type, int pos, int v);
+__isl_give isl_constraint *isl_constraint_set_coefficient_val(
+	__isl_take isl_constraint *constraint,
+	enum isl_dim_type type, int pos, __isl_take isl_val *v);
+
+__isl_give isl_aff *isl_constraint_get_div(__isl_keep isl_constraint *constraint,
+	int pos);
+
+struct isl_constraint *isl_constraint_negate(struct isl_constraint *constraint);
+
+int isl_constraint_is_equality(__isl_keep isl_constraint *constraint);
+int isl_constraint_is_div_constraint(__isl_keep isl_constraint *constraint);
+
+int isl_constraint_is_lower_bound(__isl_keep isl_constraint *constraint,
+	enum isl_dim_type type, unsigned pos);
+int isl_constraint_is_upper_bound(__isl_keep isl_constraint *constraint,
+	enum isl_dim_type type, unsigned pos);
+
+__isl_give isl_basic_map *isl_basic_map_from_constraint(
+	__isl_take isl_constraint *constraint);
+struct isl_basic_set *isl_basic_set_from_constraint(
+	struct isl_constraint *constraint);
+
+__isl_give isl_aff *isl_constraint_get_bound(
+	__isl_keep isl_constraint *constraint, enum isl_dim_type type, int pos);
+__isl_give isl_aff *isl_constraint_get_aff(
+	__isl_keep isl_constraint *constraint);
+__isl_give isl_constraint *isl_equality_from_aff(__isl_take isl_aff *aff);
+__isl_give isl_constraint *isl_inequality_from_aff(__isl_take isl_aff *aff);
+
+__isl_give isl_basic_set *isl_basic_set_drop_constraint(
+	__isl_take isl_basic_set *bset, __isl_take isl_constraint *constraint);
+
+int isl_constraint_plain_cmp(__isl_keep isl_constraint *c1,
+	__isl_keep isl_constraint *c2);
+int isl_constraint_cmp_last_non_zero(__isl_keep isl_constraint *c1,
+	__isl_keep isl_constraint *c2);
+
+__isl_give isl_printer *isl_printer_print_constraint(__isl_take isl_printer *p,
+	__isl_keep isl_constraint *c);
+void isl_constraint_dump(__isl_keep isl_constraint *c);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/ctx.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/ctx.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/ctx.h (added)
+++ polly/trunk/lib/External/isl/include/isl/ctx.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_CTX_H
+#define ISL_CTX_H
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isl/arg.h>
+#include <isl/hash.h>
+
+#ifndef __isl_give
+#define __isl_give
+#endif
+#ifndef __isl_take
+#define __isl_take
+#endif
+#ifndef __isl_keep
+#define __isl_keep
+#endif
+#ifndef __isl_null
+#define __isl_null
+#endif
+#ifndef __isl_export
+#define __isl_export
+#endif
+#ifndef __isl_constructor
+#define __isl_constructor
+#endif
+#ifndef __isl_subclass
+#define __isl_subclass(super)
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Nearly all isa functions require a struct isl_ctx allocated using
+ * isl_ctx_alloc.  This ctx contains (or will contain) options that
+ * control the behavior of the library and some caches.
+ *
+ * An object allocated within a given ctx should never be used inside
+ * another ctx.  Functions for moving objects from one ctx to another
+ * will be added as the need arises.
+ *
+ * A given context should only be used inside a single thread.
+ * A global context for synchronization between different threads
+ * as well as functions for moving a context to a different thread
+ * will be added as the need arises.
+ *
+ * If anything goes wrong (out of memory, failed assertion), then
+ * the library will currently simply abort.  This will be made
+ * configurable in the future.
+ * Users of the library should expect functions that return
+ * a pointer to a structure, to return NULL, indicating failure.
+ * Any function accepting a pointer to a structure will treat
+ * a NULL argument as a failure, resulting in the function freeing
+ * the remaining structures (if any) and returning NULL itself
+ * (in case of pointer return type).
+ * The only exception is the isl_ctx argument, which should never be NULL.
+ */
+struct isl_stats {
+	long	gbr_solved_lps;
+};
+enum isl_error {
+	isl_error_none = 0,
+	isl_error_abort,
+	isl_error_alloc,
+	isl_error_unknown,
+	isl_error_internal,
+	isl_error_invalid,
+	isl_error_quota,
+	isl_error_unsupported
+};
+struct isl_ctx;
+typedef struct isl_ctx isl_ctx;
+
+/* Some helper macros */
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
+#define ISL_DEPRECATED	__attribute__((__deprecated__))
+#else
+#define ISL_DEPRECATED
+#endif
+
+#define ISL_FL_INIT(l, f)   (l) = (f)               /* Specific flags location. */
+#define ISL_FL_SET(l, f)    ((l) |= (f))
+#define ISL_FL_CLR(l, f)    ((l) &= ~(f))
+#define ISL_FL_ISSET(l, f)  (!!((l) & (f)))
+
+#define ISL_F_INIT(p, f)    ISL_FL_INIT((p)->flags, f)  /* Structure element flags. */
+#define ISL_F_SET(p, f)     ISL_FL_SET((p)->flags, f)
+#define ISL_F_CLR(p, f)     ISL_FL_CLR((p)->flags, f)
+#define ISL_F_ISSET(p, f)   ISL_FL_ISSET((p)->flags, f)
+
+void *isl_malloc_or_die(isl_ctx *ctx, size_t size);
+void *isl_calloc_or_die(isl_ctx *ctx, size_t nmemb, size_t size);
+void *isl_realloc_or_die(isl_ctx *ctx, void *ptr, size_t size);
+
+#define isl_alloc(ctx,type,size)	((type *)isl_malloc_or_die(ctx, size))
+#define isl_calloc(ctx,type,size)	((type *)isl_calloc_or_die(ctx,\
+								    1, size))
+#define isl_realloc(ctx,ptr,type,size)	((type *)isl_realloc_or_die(ctx,\
+								    ptr, size))
+#define isl_alloc_type(ctx,type)	isl_alloc(ctx,type,sizeof(type))
+#define isl_calloc_type(ctx,type)	isl_calloc(ctx,type,sizeof(type))
+#define isl_realloc_type(ctx,ptr,type)	isl_realloc(ctx,ptr,type,sizeof(type))
+#define isl_alloc_array(ctx,type,n)	isl_alloc(ctx,type,(n)*sizeof(type))
+#define isl_calloc_array(ctx,type,n)	((type *)isl_calloc_or_die(ctx,\
+							    n, sizeof(type)))
+#define isl_realloc_array(ctx,ptr,type,n) \
+				    isl_realloc(ctx,ptr,type,(n)*sizeof(type))
+
+#define isl_die(ctx,errno,msg,code)					\
+	do {								\
+		isl_handle_error(ctx, errno, msg, __FILE__, __LINE__);	\
+		code;							\
+	} while (0)
+
+void isl_handle_error(isl_ctx *ctx, enum isl_error error, const char *msg,
+	const char *file, int line);
+
+#define isl_assert4(ctx,test,code,errno)				\
+	do {								\
+		if (test)						\
+			break;						\
+		isl_die(ctx, errno, "Assertion \"" #test "\" failed", code);	\
+	} while (0)
+#define isl_assert(ctx,test,code)					\
+	isl_assert4(ctx,test,code,isl_error_unknown)
+
+#define isl_min(a,b)			((a < b) ? (a) : (b))
+
+/* struct isl_ctx functions */
+
+struct isl_options *isl_ctx_options(isl_ctx *ctx);
+
+isl_ctx *isl_ctx_alloc_with_options(struct isl_args *args,
+	__isl_take void *opt);
+isl_ctx *isl_ctx_alloc(void);
+void *isl_ctx_peek_options(isl_ctx *ctx, struct isl_args *args);
+int isl_ctx_parse_options(isl_ctx *ctx, int argc, char **argv, unsigned flags);
+void isl_ctx_ref(struct isl_ctx *ctx);
+void isl_ctx_deref(struct isl_ctx *ctx);
+void isl_ctx_free(isl_ctx *ctx);
+
+void isl_ctx_abort(isl_ctx *ctx);
+void isl_ctx_resume(isl_ctx *ctx);
+int isl_ctx_aborted(isl_ctx *ctx);
+
+void isl_ctx_set_max_operations(isl_ctx *ctx, unsigned long max_operations);
+unsigned long isl_ctx_get_max_operations(isl_ctx *ctx);
+void isl_ctx_reset_operations(isl_ctx *ctx);
+
+#define ISL_ARG_CTX_DECL(prefix,st,args)				\
+st *isl_ctx_peek_ ## prefix(isl_ctx *ctx);
+
+#define ISL_ARG_CTX_DEF(prefix,st,args)					\
+st *isl_ctx_peek_ ## prefix(isl_ctx *ctx)				\
+{									\
+	return (st *)isl_ctx_peek_options(ctx, &(args));		\
+}
+
+#define ISL_CTX_GET_INT_DEF(prefix,st,args,field)			\
+int prefix ## _get_ ## field(isl_ctx *ctx)				\
+{									\
+	st *options;							\
+	options = isl_ctx_peek_ ## prefix(ctx);				\
+	if (!options)							\
+		isl_die(ctx, isl_error_invalid,				\
+			"isl_ctx does not reference " #prefix,		\
+			return -1);					\
+	return options->field;						\
+}
+
+#define ISL_CTX_SET_INT_DEF(prefix,st,args,field)			\
+int prefix ## _set_ ## field(isl_ctx *ctx, int val)			\
+{									\
+	st *options;							\
+	options = isl_ctx_peek_ ## prefix(ctx);				\
+	if (!options)							\
+		isl_die(ctx, isl_error_invalid,				\
+			"isl_ctx does not reference " #prefix,		\
+			return -1);					\
+	options->field = val;						\
+	return 0;							\
+}
+
+#define ISL_CTX_GET_STR_DEF(prefix,st,args,field)			\
+const char *prefix ## _get_ ## field(isl_ctx *ctx)			\
+{									\
+	st *options;							\
+	options = isl_ctx_peek_ ## prefix(ctx);				\
+	if (!options)							\
+		isl_die(ctx, isl_error_invalid,				\
+			"isl_ctx does not reference " #prefix,		\
+			return NULL);					\
+	return options->field;						\
+}
+
+#define ISL_CTX_SET_STR_DEF(prefix,st,args,field)			\
+int prefix ## _set_ ## field(isl_ctx *ctx, const char *val)		\
+{									\
+	st *options;							\
+	options = isl_ctx_peek_ ## prefix(ctx);				\
+	if (!options)							\
+		isl_die(ctx, isl_error_invalid,				\
+			"isl_ctx does not reference " #prefix,		\
+			return -1);					\
+	if (!val)							\
+		return -1;						\
+	free(options->field);						\
+	options->field = strdup(val);					\
+	if (!options->field)						\
+		return -1;						\
+	return 0;							\
+}
+
+#define ISL_CTX_GET_BOOL_DEF(prefix,st,args,field)			\
+	ISL_CTX_GET_INT_DEF(prefix,st,args,field)
+
+#define ISL_CTX_SET_BOOL_DEF(prefix,st,args,field)			\
+	ISL_CTX_SET_INT_DEF(prefix,st,args,field)
+
+#define ISL_CTX_GET_CHOICE_DEF(prefix,st,args,field)			\
+	ISL_CTX_GET_INT_DEF(prefix,st,args,field)
+
+#define ISL_CTX_SET_CHOICE_DEF(prefix,st,args,field)			\
+	ISL_CTX_SET_INT_DEF(prefix,st,args,field)
+
+enum isl_error isl_ctx_last_error(isl_ctx *ctx);
+void isl_ctx_reset_error(isl_ctx *ctx);
+void isl_ctx_set_error(isl_ctx *ctx, enum isl_error error);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/aff_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/aff_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/aff_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/aff_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,45 @@
+#ifndef ISL_DEPRECATED_AFF_INT_H
+#define ISL_DEPRECATED_AFF_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/aff_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v);
+int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
+	enum isl_dim_type type, int pos, isl_int *v);
+int isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v);
+__isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v);
+__isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, isl_int v);
+__isl_give isl_aff *isl_aff_set_denominator(__isl_take isl_aff *aff, isl_int v);
+__isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v);
+__isl_give isl_aff *isl_aff_add_constant_num(__isl_take isl_aff *aff,
+	isl_int v);
+__isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, isl_int v);
+
+__isl_give isl_aff *isl_aff_mod(__isl_take isl_aff *aff, isl_int mod);
+
+__isl_give isl_aff *isl_aff_scale(__isl_take isl_aff *aff, isl_int f);
+__isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f);
+
+__isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff,
+	isl_int mod);
+
+__isl_give isl_pw_aff *isl_pw_aff_scale(__isl_take isl_pw_aff *pwaff,
+	isl_int f);
+__isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
+	isl_int f);
+
+__isl_give isl_multi_aff *isl_multi_aff_scale(__isl_take isl_multi_aff *maff,
+	isl_int f);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/ast_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/ast_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/ast_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/ast_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,17 @@
+#ifndef ISL_DEPRECATED_AST_INT_H
+#define ISL_DEPRECATED_AST_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/ast.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_ast_expr_get_int(__isl_keep isl_ast_expr *expr, isl_int *v);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/constraint_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/constraint_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/constraint_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/constraint_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,25 @@
+#ifndef ISL_DEPRECATED_CONSTRAINT_INT_H
+#define ISL_DEPRECATED_CONSTRAINT_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/constraint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+void isl_constraint_get_constant(__isl_keep isl_constraint *constraint,
+	isl_int *v);
+void isl_constraint_get_coefficient(__isl_keep isl_constraint *constraint,
+	enum isl_dim_type type, int pos, isl_int *v);
+__isl_give isl_constraint *isl_constraint_set_constant(
+	__isl_take isl_constraint *constraint, isl_int v);
+__isl_give isl_constraint *isl_constraint_set_coefficient(
+	__isl_take isl_constraint *constraint,
+	enum isl_dim_type type, int pos, isl_int v);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/ilp_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/ilp_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/ilp_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/ilp_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,23 @@
+#ifndef ISL_DEPRECATED_ILP_INT_H
+#define ISL_DEPRECATED_ILP_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/lp.h>
+#include <isl/ilp.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+enum isl_lp_result isl_basic_set_max(__isl_keep isl_basic_set *bset,
+	__isl_keep isl_aff *obj, isl_int *opt);
+enum isl_lp_result isl_set_min(__isl_keep isl_set *set,
+	__isl_keep isl_aff *obj, isl_int *opt);
+enum isl_lp_result isl_set_max(__isl_keep isl_set *set,
+	__isl_keep isl_aff *obj, isl_int *opt);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_DEPRECATED_INT_H
+#define ISL_DEPRECATED_INT_H
+
+#include <isl/hash.h>
+#include <string.h>
+#include <gmp.h>
+#if defined(__cplusplus)
+#include <iostream>
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef mp_get_memory_functions
+void mp_get_memory_functions(
+		void *(**alloc_func_ptr) (size_t),
+		void *(**realloc_func_ptr) (void *, size_t, size_t),
+		void (**free_func_ptr) (void *, size_t));
+#endif
+
+/* isl_int is the basic integer type.  It currently always corresponds
+ * to a gmp mpz_t, but in the future, different types such as long long
+ * or cln::cl_I will be supported.
+ */
+typedef mpz_t	isl_int;
+
+#define isl_int_init(i)		mpz_init(i)
+#define isl_int_clear(i)	mpz_clear(i)
+
+#define isl_int_set(r,i)	mpz_set(r,i)
+#define isl_int_set_gmp(r,i)	mpz_set(r,i)
+#define isl_int_set_si(r,i)	mpz_set_si(r,i)
+#define isl_int_set_ui(r,i)	mpz_set_ui(r,i)
+#define isl_int_get_gmp(i,g)	mpz_set(g,i)
+#define isl_int_get_si(r)	mpz_get_si(r)
+#define isl_int_get_ui(r)	mpz_get_ui(r)
+#define isl_int_get_d(r)	mpz_get_d(r)
+#define isl_int_get_str(r)	mpz_get_str(0, 10, r)
+typedef void (*isl_int_print_gmp_free_t)(void *, size_t);
+#define isl_int_free_str(s)					\
+	do {								\
+		isl_int_print_gmp_free_t gmp_free;			\
+		mp_get_memory_functions(NULL, NULL, &gmp_free);		\
+		(*gmp_free)(s, strlen(s) + 1);				\
+	} while (0)
+#define isl_int_abs(r,i)	mpz_abs(r,i)
+#define isl_int_neg(r,i)	mpz_neg(r,i)
+#define isl_int_swap(i,j)	mpz_swap(i,j)
+#define isl_int_swap_or_set(i,j)	mpz_swap(i,j)
+#define isl_int_add_ui(r,i,j)	mpz_add_ui(r,i,j)
+#define isl_int_sub_ui(r,i,j)	mpz_sub_ui(r,i,j)
+
+#define isl_int_add(r,i,j)	mpz_add(r,i,j)
+#define isl_int_sub(r,i,j)	mpz_sub(r,i,j)
+#define isl_int_mul(r,i,j)	mpz_mul(r,i,j)
+#define isl_int_mul_2exp(r,i,j)	mpz_mul_2exp(r,i,j)
+#define isl_int_mul_ui(r,i,j)	mpz_mul_ui(r,i,j)
+#define isl_int_pow_ui(r,i,j)	mpz_pow_ui(r,i,j)
+#define isl_int_addmul(r,i,j)	mpz_addmul(r,i,j)
+#define isl_int_submul(r,i,j)	mpz_submul(r,i,j)
+
+#define isl_int_gcd(r,i,j)	mpz_gcd(r,i,j)
+#define isl_int_lcm(r,i,j)	mpz_lcm(r,i,j)
+#define isl_int_divexact(r,i,j)	mpz_divexact(r,i,j)
+#define isl_int_divexact_ui(r,i,j)	mpz_divexact_ui(r,i,j)
+#define isl_int_tdiv_q(r,i,j)	mpz_tdiv_q(r,i,j)
+#define isl_int_cdiv_q(r,i,j)	mpz_cdiv_q(r,i,j)
+#define isl_int_fdiv_q(r,i,j)	mpz_fdiv_q(r,i,j)
+#define isl_int_fdiv_r(r,i,j)	mpz_fdiv_r(r,i,j)
+#define isl_int_fdiv_q_ui(r,i,j)	mpz_fdiv_q_ui(r,i,j)
+
+#define isl_int_read(r,s)	mpz_set_str(r,s,10)
+#define isl_int_print(out,i,width)					\
+	do {								\
+		char *s;						\
+		s = mpz_get_str(0, 10, i);				\
+		fprintf(out, "%*s", width, s);				\
+		isl_int_free_str(s);                                        \
+	} while (0)
+
+#define isl_int_sgn(i)		mpz_sgn(i)
+#define isl_int_cmp(i,j)	mpz_cmp(i,j)
+#define isl_int_cmp_si(i,si)	mpz_cmp_si(i,si)
+#define isl_int_eq(i,j)		(mpz_cmp(i,j) == 0)
+#define isl_int_ne(i,j)		(mpz_cmp(i,j) != 0)
+#define isl_int_lt(i,j)		(mpz_cmp(i,j) < 0)
+#define isl_int_le(i,j)		(mpz_cmp(i,j) <= 0)
+#define isl_int_gt(i,j)		(mpz_cmp(i,j) > 0)
+#define isl_int_ge(i,j)		(mpz_cmp(i,j) >= 0)
+#define isl_int_abs_eq(i,j)	(mpz_cmpabs(i,j) == 0)
+#define isl_int_abs_ne(i,j)	(mpz_cmpabs(i,j) != 0)
+#define isl_int_abs_lt(i,j)	(mpz_cmpabs(i,j) < 0)
+#define isl_int_abs_gt(i,j)	(mpz_cmpabs(i,j) > 0)
+#define isl_int_abs_ge(i,j)	(mpz_cmpabs(i,j) >= 0)
+
+
+#define isl_int_is_zero(i)	(isl_int_sgn(i) == 0)
+#define isl_int_is_one(i)	(isl_int_cmp_si(i,1) == 0)
+#define isl_int_is_negone(i)	(isl_int_cmp_si(i,-1) == 0)
+#define isl_int_is_pos(i)	(isl_int_sgn(i) > 0)
+#define isl_int_is_neg(i)	(isl_int_sgn(i) < 0)
+#define isl_int_is_nonpos(i)	(isl_int_sgn(i) <= 0)
+#define isl_int_is_nonneg(i)	(isl_int_sgn(i) >= 0)
+#define isl_int_is_divisible_by(i,j)	mpz_divisible_p(i,j)
+
+uint32_t isl_gmp_hash(mpz_t v, uint32_t hash);
+#define isl_int_hash(v,h)	isl_gmp_hash(v,h)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#if defined(__cplusplus)
+extern "C" { typedef void (*isl_gmp_free_t)(void *, size_t); }
+
+static inline std::ostream &operator<<(std::ostream &os, isl_int i)
+{
+	char *s;
+	s = mpz_get_str(0, 10, i);
+	os << s;
+	isl_int_free_str(s);
+	return os;
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/map_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/map_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/map_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/map_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,27 @@
+#ifndef ISL_DEPRECATED_MAP_INT_H
+#define ISL_DEPRECATED_MAP_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/map_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_basic_map_plain_is_fixed(__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned pos, isl_int *val);
+
+__isl_give isl_map *isl_map_fix(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned pos, isl_int value);
+int isl_map_plain_is_fixed(__isl_keep isl_map *map,
+	enum isl_dim_type type, unsigned pos, isl_int *val);
+int isl_map_fast_is_fixed(__isl_keep isl_map *map,
+	enum isl_dim_type type, unsigned pos, isl_int *val);
+
+__isl_give isl_map *isl_map_fixed_power(__isl_take isl_map *map, isl_int exp);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/mat_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/mat_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/mat_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/mat_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,19 @@
+#ifndef ISL_DEPRECATED_MAT_INT_H
+#define ISL_DEPRECATED_MAT_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/mat.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_mat_get_element(__isl_keep isl_mat *mat, int row, int col, isl_int *v);
+__isl_give isl_mat *isl_mat_set_element(__isl_take isl_mat *mat,
+	int row, int col, isl_int v);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/point_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/point_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/point_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/point_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,20 @@
+#ifndef ISL_DEPRECATED_POINT_INT_H
+#define ISL_DEPRECATED_POINT_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/point.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_point_get_coordinate(__isl_keep isl_point *pnt,
+	enum isl_dim_type type, int pos, isl_int *v);
+__isl_give isl_point *isl_point_set_coordinate(__isl_take isl_point *pnt,
+	enum isl_dim_type type, int pos, isl_int v);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/polynomial_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/polynomial_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/polynomial_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/polynomial_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,32 @@
+#ifndef ISL_DEPRECATED_POLYNOMIAL_INT_H
+#define ISL_DEPRECATED_POLYNOMIAL_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/polynomial.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_qpolynomial *isl_qpolynomial_rat_cst_on_domain(
+	__isl_take isl_space *space, const isl_int n, const isl_int d);
+int isl_qpolynomial_is_cst(__isl_keep isl_qpolynomial *qp,
+	isl_int *n, isl_int *d);
+__isl_give isl_qpolynomial *isl_qpolynomial_scale(
+	__isl_take isl_qpolynomial *qp, isl_int v);
+
+void isl_term_get_num(__isl_keep isl_term *term, isl_int *n);
+void isl_term_get_den(__isl_keep isl_term *term, isl_int *d);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale(
+	__isl_take isl_qpolynomial_fold *fold, isl_int v);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_fix_dim(
+	__isl_take isl_pw_qpolynomial_fold *pwf,
+	enum isl_dim_type type, unsigned n, isl_int v);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/set_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/set_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/set_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/set_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,27 @@
+#ifndef ISL_DEPRECATED_SET_INT_H
+#define ISL_DEPRECATED_SET_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/set_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_basic_set *isl_basic_set_fix(__isl_take isl_basic_set *bset,
+		enum isl_dim_type type, unsigned pos, isl_int value);
+__isl_give isl_set *isl_set_lower_bound(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned pos, isl_int value);
+__isl_give isl_set *isl_set_upper_bound(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned pos, isl_int value);
+__isl_give isl_set *isl_set_fix(__isl_take isl_set *set,
+		enum isl_dim_type type, unsigned pos, isl_int value);
+
+int isl_set_plain_is_fixed(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos, isl_int *val);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/union_map_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/union_map_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/union_map_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/union_map_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,18 @@
+#ifndef ISL_DEPRECATED_UNION_MAP_INT_H
+#define ISL_DEPRECATED_UNION_MAP_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/union_map_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_union_map *isl_union_map_fixed_power(
+	__isl_take isl_union_map *umap, isl_int exp);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/val_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/val_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/val_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/val_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,18 @@
+#ifndef ISL_DEPRECATED_VAL_INT_H
+#define ISL_DEPRECATED_VAL_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_val *isl_val_int_from_isl_int(isl_ctx *ctx, isl_int n);
+int isl_val_get_num_isl_int(__isl_keep isl_val *v, isl_int *n);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/deprecated/vec_int.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/deprecated/vec_int.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/deprecated/vec_int.h (added)
+++ polly/trunk/lib/External/isl/include/isl/deprecated/vec_int.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,22 @@
+#ifndef ISL_DEPRECATED_VEC_INT_H
+#define ISL_DEPRECATED_VEC_INT_H
+
+#include <isl/deprecated/int.h>
+#include <isl/vec.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int isl_vec_get_element(__isl_keep isl_vec *vec, int pos, isl_int *v);
+__isl_give isl_vec *isl_vec_set_element(__isl_take isl_vec *vec,
+	int pos, isl_int v);
+
+__isl_give isl_vec *isl_vec_set(__isl_take isl_vec *vec, isl_int v);
+__isl_give isl_vec *isl_vec_fdiv_r(__isl_take isl_vec *vec, isl_int m);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/dim.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/dim.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/dim.h (added)
+++ polly/trunk/lib/External/isl/include/isl/dim.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,174 @@
+#ifndef ISL_DIM_H
+#define ISL_DIM_H
+
+#include <isl/space.h>
+#include <isl/local_space.h>
+#include <isl/aff_type.h>
+#include <isl/constraint.h>
+#include <isl/map_type.h>
+#include <isl/set_type.h>
+#include <isl/point.h>
+#include <isl/union_map.h>
+#include <isl/union_set.h>
+#include <isl/polynomial_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define isl_dim isl_space
+
+ISL_DEPRECATED
+isl_ctx *isl_dim_get_ctx(__isl_keep isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_alloc(isl_ctx *ctx,
+			unsigned nparam, unsigned n_in, unsigned n_out);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_set_alloc(isl_ctx *ctx,
+			unsigned nparam, unsigned dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_copy(__isl_keep isl_space *dim);
+ISL_DEPRECATED
+void isl_dim_free(__isl_take isl_space *dim);
+
+ISL_DEPRECATED
+unsigned isl_dim_size(__isl_keep isl_space *dim, enum isl_dim_type type);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_set_dim_id(__isl_take isl_space *dim,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+ISL_DEPRECATED
+int isl_dim_has_dim_id(__isl_keep isl_space *dim,
+	enum isl_dim_type type, unsigned pos);
+ISL_DEPRECATED
+__isl_give isl_id *isl_dim_get_dim_id(__isl_keep isl_space *dim,
+	enum isl_dim_type type, unsigned pos);
+
+ISL_DEPRECATED
+int isl_dim_find_dim_by_id(__isl_keep isl_space *dim,
+	enum isl_dim_type type, __isl_keep isl_id *id);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_set_tuple_id(__isl_take isl_space *dim,
+	enum isl_dim_type type, __isl_take isl_id *id);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_reset_tuple_id(__isl_take isl_space *dim,
+	enum isl_dim_type type);
+ISL_DEPRECATED
+int isl_dim_has_tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type);
+ISL_DEPRECATED
+__isl_give isl_id *isl_dim_get_tuple_id(__isl_keep isl_space *dim,
+	enum isl_dim_type type);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_set_name(__isl_take isl_space *dim,
+	enum isl_dim_type type, unsigned pos, __isl_keep const char *name);
+ISL_DEPRECATED
+__isl_keep const char *isl_dim_get_name(__isl_keep isl_space *dim,
+	enum isl_dim_type type, unsigned pos);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_set_tuple_name(__isl_take isl_space *dim,
+	enum isl_dim_type type, const char *s);
+ISL_DEPRECATED
+const char *isl_dim_get_tuple_name(__isl_keep isl_space *dim,
+				 enum isl_dim_type type);
+
+ISL_DEPRECATED
+int isl_dim_is_wrapping(__isl_keep isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_wrap(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_unwrap(__isl_take isl_space *dim);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_domain(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_from_domain(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_range(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_from_range(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_reverse(__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_join(__isl_take isl_space *left,
+	__isl_take isl_space *right);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_align_params(__isl_take isl_space *dim1,
+	__isl_take isl_space *dim2);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_insert(__isl_take isl_space *dim,
+	enum isl_dim_type type, unsigned pos, unsigned n);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_add(__isl_take isl_space *dim,
+	enum isl_dim_type type, unsigned n);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_drop(__isl_take isl_space *dim,
+	enum isl_dim_type type, unsigned first, unsigned n);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_move(__isl_take isl_space *dim,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_map_from_set(
+	__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_dim_zip(__isl_take isl_space *dim);
+
+ISL_DEPRECATED
+__isl_give isl_local_space *isl_local_space_from_dim(
+	__isl_take isl_space *dim);
+ISL_DEPRECATED
+__isl_give isl_space *isl_local_space_get_dim(
+	__isl_keep isl_local_space *ls);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_aff_get_dim(__isl_keep isl_aff *aff);
+ISL_DEPRECATED
+__isl_give isl_space *isl_pw_aff_get_dim(__isl_keep isl_pw_aff *pwaff);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_constraint_get_dim(
+	__isl_keep isl_constraint *constraint);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_basic_map_get_dim(__isl_keep isl_basic_map *bmap);
+ISL_DEPRECATED
+__isl_give isl_space *isl_map_get_dim(__isl_keep isl_map *map);
+ISL_DEPRECATED
+__isl_give isl_space *isl_union_map_get_dim(__isl_keep isl_union_map *umap);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_basic_set_get_dim(__isl_keep isl_basic_set *bset);
+ISL_DEPRECATED
+__isl_give isl_space *isl_set_get_dim(__isl_keep isl_set *set);
+ISL_DEPRECATED
+__isl_give isl_space *isl_union_set_get_dim(__isl_keep isl_union_set *uset);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_point_get_dim(__isl_keep isl_point *pnt);
+
+ISL_DEPRECATED
+__isl_give isl_space *isl_qpolynomial_get_dim(__isl_keep isl_qpolynomial *qp);
+ISL_DEPRECATED
+__isl_give isl_space *isl_pw_qpolynomial_get_dim(
+	__isl_keep isl_pw_qpolynomial *pwqp);
+ISL_DEPRECATED
+__isl_give isl_space *isl_qpolynomial_fold_get_dim(
+	__isl_keep isl_qpolynomial_fold *fold);
+ISL_DEPRECATED
+__isl_give isl_space *isl_pw_qpolynomial_fold_get_dim(
+	__isl_keep isl_pw_qpolynomial_fold *pwf);
+ISL_DEPRECATED
+__isl_give isl_space *isl_union_pw_qpolynomial_get_dim(
+	__isl_keep isl_union_pw_qpolynomial *upwqp);
+ISL_DEPRECATED
+__isl_give isl_space *isl_union_pw_qpolynomial_fold_get_dim(
+	__isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/flow.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/flow.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/flow.h (added)
+++ polly/trunk/lib/External/isl/include/isl/flow.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,77 @@
+#ifndef ISL_FLOW_H
+#define ISL_FLOW_H
+
+#include <isl/set_type.h>
+#include <isl/map_type.h>
+#include <isl/union_set_type.h>
+#include <isl/union_map_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Let n (>= 0) be the number of iterators shared by first and second.
+ * If first precedes second textually return 2 * n + 1,
+ * otherwise return 2 * n.
+ */
+typedef int (*isl_access_level_before)(void *first, void *second);
+
+struct isl_restriction;
+typedef struct isl_restriction isl_restriction;
+
+__isl_null isl_restriction *isl_restriction_free(
+	__isl_take isl_restriction *restr);
+__isl_give isl_restriction *isl_restriction_empty(
+	__isl_take isl_map *source_map);
+__isl_give isl_restriction *isl_restriction_none(
+	__isl_take isl_map *source_map);
+__isl_give isl_restriction *isl_restriction_input(
+	__isl_take isl_set *source_restr, __isl_take isl_set *sink_restr);
+__isl_give isl_restriction *isl_restriction_output(
+	__isl_take isl_set *source_restr);
+
+isl_ctx *isl_restriction_get_ctx(__isl_keep isl_restriction *restr);
+
+typedef __isl_give isl_restriction *(*isl_access_restrict)(
+	__isl_keep isl_map *source_map, __isl_keep isl_set *sink,
+	void *source_user, void *user);
+
+struct isl_access_info;
+typedef struct isl_access_info isl_access_info;
+struct isl_flow;
+typedef struct isl_flow isl_flow;
+
+__isl_give isl_access_info *isl_access_info_alloc(__isl_take isl_map *sink,
+	void *sink_user, isl_access_level_before fn, int max_source);
+__isl_give isl_access_info *isl_access_info_set_restrict(
+	__isl_take isl_access_info *acc, isl_access_restrict fn, void *user);
+__isl_give isl_access_info *isl_access_info_add_source(
+	__isl_take isl_access_info *acc, __isl_take isl_map *source,
+	int must, void *source_user);
+__isl_null isl_access_info *isl_access_info_free(
+	__isl_take isl_access_info *acc);
+
+isl_ctx *isl_access_info_get_ctx(__isl_keep isl_access_info *acc);
+
+__isl_give isl_flow *isl_access_info_compute_flow(__isl_take isl_access_info *acc);
+int isl_flow_foreach(__isl_keep isl_flow *deps,
+	int (*fn)(__isl_take isl_map *dep, int must, void *dep_user, void *user),
+	void *user);
+__isl_give isl_map *isl_flow_get_no_source(__isl_keep isl_flow *deps, int must);
+void isl_flow_free(__isl_take isl_flow *deps);
+
+isl_ctx *isl_flow_get_ctx(__isl_keep isl_flow *deps);
+
+int isl_union_map_compute_flow(__isl_take isl_union_map *sink,
+	__isl_take isl_union_map *must_source,
+	__isl_take isl_union_map *may_source,
+	__isl_take isl_union_map *schedule,
+	__isl_give isl_union_map **must_dep, __isl_give isl_union_map **may_dep,
+	__isl_give isl_union_map **must_no_source,
+	__isl_give isl_union_map **may_no_source);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/hash.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/hash.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/hash.h (added)
+++ polly/trunk/lib/External/isl/include/isl/hash.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_HASH_H
+#define ISL_HASH_H
+
+#include <stdlib.h>
+
+// We do not generate isl/stdint.h in the Polly build. The configure logic has
+// not yet been implemented and it is unclear if it actually needed on the
+// platform LLVM is compiled for.
+
+#include <stdint.h>
+// #include <isl/stdint.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define isl_hash_init()		(2166136261u)
+#define isl_hash_byte(h,b)	do {					\
+					h *= 16777619;			\
+					h ^= b;				\
+				} while(0)
+#define isl_hash_hash(h,h2)						\
+	do {								\
+		isl_hash_byte(h, (h2) & 0xFF);				\
+		isl_hash_byte(h, ((h2) >> 8) & 0xFF);			\
+		isl_hash_byte(h, ((h2) >> 16) & 0xFF);			\
+		isl_hash_byte(h, ((h2) >> 24) & 0xFF);			\
+	} while(0)
+#define isl_hash_bits(h,bits)						\
+	((bits) == 32) ? (h) :						\
+	((bits) >= 16) ?						\
+	      ((h) >> (bits)) ^ ((h) & (((uint32_t)1 << (bits)) - 1)) :	\
+	      (((h) >> (bits)) ^ (h)) & (((uint32_t)1 << (bits)) - 1)
+
+uint32_t isl_hash_string(uint32_t hash, const char *s);
+uint32_t isl_hash_mem(uint32_t hash, const void *p, size_t len);
+
+#define isl_hash_builtin(h,l)	isl_hash_mem(h, &l, sizeof(l))
+
+struct isl_hash_table_entry
+{
+	uint32_t  hash;
+	void     *data;
+};
+
+struct isl_hash_table {
+	int    bits;
+	int    n;
+	struct isl_hash_table_entry *entries;
+};
+
+struct isl_ctx;
+
+struct isl_hash_table *isl_hash_table_alloc(struct isl_ctx *ctx, int min_size);
+void isl_hash_table_free(struct isl_ctx *ctx, struct isl_hash_table *table);
+
+int isl_hash_table_init(struct isl_ctx *ctx, struct isl_hash_table *table,
+			int min_size);
+void isl_hash_table_clear(struct isl_hash_table *table);
+struct isl_hash_table_entry *isl_hash_table_find(struct isl_ctx *ctx,
+				struct isl_hash_table *table,
+				uint32_t key_hash,
+				int (*eq)(const void *entry, const void *val),
+				const void *val, int reserve);
+int isl_hash_table_foreach(struct isl_ctx *ctx,
+			    struct isl_hash_table *table,
+			    int (*fn)(void **entry, void *user), void *user);
+void isl_hash_table_remove(struct isl_ctx *ctx,
+				struct isl_hash_table *table,
+				struct isl_hash_table_entry *entry);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/hmap.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/hmap.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/hmap.h (added)
+++ polly/trunk/lib/External/isl/include/isl/hmap.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,56 @@
+#include <isl/ctx.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define ISL_xCAT(A,B) A ## B
+#define ISL_CAT(A,B) ISL_xCAT(A,B)
+#define ISL_KEY ISL_CAT(isl_,ISL_KEY_BASE)
+#define ISL_VAL ISL_CAT(isl_,ISL_VAL_BASE)
+#define ISL_xFN(TYPE,NAME) TYPE ## _ ## NAME
+#define ISL_FN(TYPE,NAME) ISL_xFN(TYPE,NAME)
+#define ISL_xHMAP(KEY,VAL_BASE) KEY ## _to_ ## VAL_BASE
+#define ISL_yHMAP(KEY,VAL_BASE) ISL_xHMAP(KEY,VAL_BASE)
+#define ISL_HMAP ISL_yHMAP(ISL_KEY,ISL_VAL_BASE)
+#define ISL_HMAP_BASE ISL_yHMAP(ISL_KEY_BASE,ISL_VAL_BASE)
+
+struct ISL_HMAP;
+typedef struct ISL_HMAP	ISL_HMAP;
+
+__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,alloc)(isl_ctx *ctx, int min_size);
+__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,copy)(__isl_keep ISL_HMAP *hmap);
+__isl_null ISL_HMAP *ISL_FN(ISL_HMAP,free)(__isl_take ISL_HMAP *hmap);
+
+isl_ctx *ISL_FN(ISL_HMAP,get_ctx)(__isl_keep ISL_HMAP *hmap);
+
+int ISL_FN(ISL_HMAP,has)(__isl_keep ISL_HMAP *hmap, __isl_keep ISL_KEY *key);
+__isl_give ISL_VAL *ISL_FN(ISL_HMAP,get)(__isl_keep ISL_HMAP *hmap,
+	__isl_take ISL_KEY *key);
+__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,set)(__isl_take ISL_HMAP *hmap,
+	__isl_take ISL_KEY *key, __isl_take ISL_VAL *val);
+__isl_give ISL_HMAP *ISL_FN(ISL_HMAP,drop)(__isl_take ISL_HMAP *hmap,
+	__isl_take ISL_KEY *key);
+
+int ISL_FN(ISL_HMAP,foreach)(__isl_keep ISL_HMAP *hmap,
+	int (*fn)(__isl_take ISL_KEY *key, __isl_take ISL_VAL *val, void *user),
+	void *user);
+
+__isl_give isl_printer *ISL_FN(isl_printer_print,ISL_HMAP_BASE)(
+	__isl_take isl_printer *p, __isl_keep ISL_HMAP *hmap);
+void ISL_FN(ISL_HMAP,dump)(__isl_keep ISL_HMAP *hmap);
+
+#undef ISL_xCAT
+#undef ISL_CAT
+#undef ISL_KEY
+#undef ISL_VAL
+#undef ISL_xFN
+#undef ISL_FN
+#undef ISL_xHMAP
+#undef ISL_yHMAP
+#undef ISL_HMAP
+
+#if defined(__cplusplus)
+}
+#endif

Added: polly/trunk/lib/External/isl/include/isl/id.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/id.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/id.h (added)
+++ polly/trunk/lib/External/isl/include/isl/id.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,39 @@
+#ifndef ISL_ID_H
+#define ISL_ID_H
+
+#include <isl/ctx.h>
+#include <isl/list.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_id;
+typedef struct isl_id isl_id;
+
+ISL_DECLARE_LIST(id)
+
+isl_ctx *isl_id_get_ctx(__isl_keep isl_id *id);
+uint32_t isl_id_get_hash(__isl_keep isl_id *id);
+
+__isl_give isl_id *isl_id_alloc(isl_ctx *ctx,
+	__isl_keep const char *name, void *user);
+__isl_give isl_id *isl_id_copy(isl_id *id);
+__isl_null isl_id *isl_id_free(__isl_take isl_id *id);
+
+void *isl_id_get_user(__isl_keep isl_id *id);
+__isl_keep const char *isl_id_get_name(__isl_keep isl_id *id);
+
+__isl_give isl_id *isl_id_set_free_user(__isl_take isl_id *id,
+	__isl_give void (*free_user)(void *user));
+
+__isl_give isl_printer *isl_printer_print_id(__isl_take isl_printer *p,
+	__isl_keep isl_id *id);
+void isl_id_dump(__isl_keep isl_id *id);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/id_to_ast_expr.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/id_to_ast_expr.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/id_to_ast_expr.h (added)
+++ polly/trunk/lib/External/isl/include/isl/id_to_ast_expr.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,13 @@
+#ifndef ISL_ID_TO_AST_EXPR_H
+#define ISL_ID_TO_AST_EXPR_H
+
+#include <isl/id.h>
+#include <isl/ast_type.h>
+
+#define ISL_KEY_BASE	id
+#define ISL_VAL_BASE	ast_expr
+#include <isl/hmap.h>
+#undef ISL_KEY_BASE
+#undef ISL_VAL_BASE
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/id_to_pw_aff.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/id_to_pw_aff.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/id_to_pw_aff.h (added)
+++ polly/trunk/lib/External/isl/include/isl/id_to_pw_aff.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,13 @@
+#ifndef ISL_ID_TO_PW_AFF_H
+#define ISL_ID_TO_PW_AFF_H
+
+#include <isl/id.h>
+#include <isl/aff_type.h>
+
+#define ISL_KEY_BASE	id
+#define ISL_VAL_BASE	pw_aff
+#include <isl/hmap.h>
+#undef ISL_KEY_BASE
+#undef ISL_VAL_BASE
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/ilp.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/ilp.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/ilp.h (added)
+++ polly/trunk/lib/External/isl/include/isl/ilp.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_ILP_H
+#define ISL_ILP_H
+
+#include <isl/aff_type.h>
+#include <isl/set_type.h>
+#include <isl/val.h>
+#include <isl/vec.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_val *isl_basic_set_max_val(__isl_keep isl_basic_set *bset,
+	__isl_keep isl_aff *obj);
+__isl_give isl_val *isl_set_min_val(__isl_keep isl_set *set,
+	__isl_keep isl_aff *obj);
+__isl_give isl_val *isl_set_max_val(__isl_keep isl_set *set,
+	__isl_keep isl_aff *obj);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/list.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/list.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/list.h (added)
+++ polly/trunk/lib/External/isl/include/isl/list.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_LIST_H
+#define ISL_LIST_H
+
+#include <isl/ctx.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define ISL_DECLARE_LIST_TYPE(EL)					\
+struct isl_##EL;							\
+struct isl_##EL##_list;							\
+typedef struct isl_##EL##_list isl_##EL##_list;
+#define ISL_DECLARE_LIST_FN(EL)						\
+isl_ctx *isl_##EL##_list_get_ctx(__isl_keep isl_##EL##_list *list);	\
+__isl_give isl_##EL##_list *isl_##EL##_list_from_##EL(			\
+	__isl_take struct isl_##EL *el);				\
+__isl_give isl_##EL##_list *isl_##EL##_list_alloc(isl_ctx *ctx, int n);	\
+__isl_give isl_##EL##_list *isl_##EL##_list_copy(			\
+	__isl_keep isl_##EL##_list *list);				\
+__isl_null isl_##EL##_list *isl_##EL##_list_free(			\
+	__isl_take isl_##EL##_list *list);				\
+__isl_give isl_##EL##_list *isl_##EL##_list_add(			\
+	__isl_take isl_##EL##_list *list,				\
+	__isl_take struct isl_##EL *el);				\
+__isl_give isl_##EL##_list *isl_##EL##_list_insert(			\
+	__isl_take isl_##EL##_list *list, unsigned pos,			\
+	__isl_take struct isl_##EL *el);				\
+__isl_give isl_##EL##_list *isl_##EL##_list_drop(			\
+	__isl_take isl_##EL##_list *list, unsigned first, unsigned n);	\
+__isl_give isl_##EL##_list *isl_##EL##_list_concat(			\
+	__isl_take isl_##EL##_list *list1,				\
+	__isl_take isl_##EL##_list *list2);				\
+int isl_##EL##_list_n_##EL(__isl_keep isl_##EL##_list *list);		\
+__isl_give struct isl_##EL *isl_##EL##_list_get_##EL(			\
+	__isl_keep isl_##EL##_list *list, int index);			\
+__isl_give struct isl_##EL##_list *isl_##EL##_list_set_##EL(		\
+	__isl_take struct isl_##EL##_list *list, int index,		\
+	__isl_take struct isl_##EL *el);				\
+int isl_##EL##_list_foreach(__isl_keep isl_##EL##_list *list,		\
+	int (*fn)(__isl_take struct isl_##EL *el, void *user),		\
+	void *user);							\
+__isl_give isl_##EL##_list *isl_##EL##_list_sort(			\
+	__isl_take isl_##EL##_list *list,				\
+	int (*cmp)(__isl_keep struct isl_##EL *a,			\
+		__isl_keep struct isl_##EL *b,				\
+		void *user), void *user);				\
+int isl_##EL##_list_foreach_scc(__isl_keep isl_##EL##_list *list,	\
+	int (*follows)(__isl_keep struct isl_##EL *a,			\
+			__isl_keep struct isl_##EL *b, void *user),	\
+	void *follows_user,						\
+	int (*fn)(__isl_take isl_##EL##_list *scc, void *user),		\
+	void *fn_user);							\
+__isl_give isl_printer *isl_printer_print_##EL##_list(			\
+	__isl_take isl_printer *p, __isl_keep isl_##EL##_list *list);	\
+void isl_##EL##_list_dump(__isl_keep isl_##EL##_list *list);
+
+#define ISL_DECLARE_LIST(EL)						\
+	ISL_DECLARE_LIST_TYPE(EL)					\
+	ISL_DECLARE_LIST_FN(EL)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/local_space.h (added)
+++ polly/trunk/lib/External/isl/include/isl/local_space.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,92 @@
+#ifndef ISL_LOCAL_SPACE_H
+#define ISL_LOCAL_SPACE_H
+
+#include <isl/aff_type.h>
+#include <isl/space.h>
+#include <isl/printer.h>
+#include <isl/map_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_local_space;
+typedef struct isl_local_space isl_local_space;
+
+isl_ctx *isl_local_space_get_ctx(__isl_keep isl_local_space *ls);
+
+__isl_give isl_local_space *isl_local_space_from_space(__isl_take isl_space *dim);
+
+__isl_give isl_local_space *isl_local_space_copy(
+	__isl_keep isl_local_space *ls);
+__isl_null isl_local_space *isl_local_space_free(
+	__isl_take isl_local_space *ls);
+
+int isl_local_space_is_params(__isl_keep isl_local_space *ls);
+int isl_local_space_is_set(__isl_keep isl_local_space *ls);
+
+__isl_give isl_local_space *isl_local_space_set_tuple_id(
+	__isl_take isl_local_space *ls,
+	enum isl_dim_type type, __isl_take isl_id *id);
+
+int isl_local_space_dim(__isl_keep isl_local_space *ls,
+	enum isl_dim_type type);
+int isl_local_space_has_dim_name(__isl_keep isl_local_space *ls,
+	enum isl_dim_type type, unsigned pos);
+const char *isl_local_space_get_dim_name(__isl_keep isl_local_space *ls,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_local_space *isl_local_space_set_dim_name(
+	__isl_take isl_local_space *ls,
+	enum isl_dim_type type, unsigned pos, const char *s);
+int isl_local_space_has_dim_id(__isl_keep isl_local_space *ls,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_local_space_get_dim_id(__isl_keep isl_local_space *ls,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_local_space *isl_local_space_set_dim_id(
+	__isl_take isl_local_space *ls,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+__isl_give isl_space *isl_local_space_get_space(__isl_keep isl_local_space *ls);
+__isl_give isl_aff *isl_local_space_get_div(__isl_keep isl_local_space *ls,
+	int pos);
+
+int isl_local_space_find_dim_by_name(__isl_keep isl_local_space *ls,
+	enum isl_dim_type type, const char *name);
+
+__isl_give isl_local_space *isl_local_space_domain(
+	__isl_take isl_local_space *ls);
+__isl_give isl_local_space *isl_local_space_range(
+	__isl_take isl_local_space *ls);
+__isl_give isl_local_space *isl_local_space_from_domain(
+	__isl_take isl_local_space *ls);
+__isl_give isl_local_space *isl_local_space_add_dims(
+	__isl_take isl_local_space *ls, enum isl_dim_type type, unsigned n);
+__isl_give isl_local_space *isl_local_space_drop_dims(
+	__isl_take isl_local_space *ls,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_local_space *isl_local_space_insert_dims(
+	__isl_take isl_local_space *ls,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_local_space *isl_local_space_intersect(
+	__isl_take isl_local_space *ls1, __isl_take isl_local_space *ls2);
+
+int isl_local_space_is_equal(__isl_keep isl_local_space *ls1,
+	__isl_keep isl_local_space *ls2);
+
+__isl_give isl_basic_map *isl_local_space_lifting(
+	__isl_take isl_local_space *ls);
+
+__isl_give isl_local_space *isl_local_space_flatten_domain(
+	__isl_take isl_local_space *ls);
+__isl_give isl_local_space *isl_local_space_flatten_range(
+	__isl_take isl_local_space *ls);
+
+__isl_give isl_printer *isl_printer_print_local_space(__isl_take isl_printer *p,
+	__isl_keep isl_local_space *ls);
+void isl_local_space_dump(__isl_keep isl_local_space *ls);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/lp.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/lp.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/lp.h (added)
+++ polly/trunk/lib/External/isl/include/isl/lp.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_LP_H
+#define ISL_LP_H
+
+#include <isl/aff.h>
+#include <isl/val.h>
+#include <isl/set_type.h>
+
+enum isl_lp_result {
+	isl_lp_error = -1,
+	isl_lp_ok = 0,
+	isl_lp_unbounded,
+	isl_lp_empty
+};
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_val *isl_basic_set_min_lp_val(__isl_keep isl_basic_set *bset,
+	__isl_keep isl_aff *obj);
+__isl_give isl_val *isl_basic_set_max_lp_val(__isl_keep isl_basic_set *bset,
+	__isl_keep isl_aff *obj);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/map.h (added)
+++ polly/trunk/lib/External/isl/include/isl/map.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,697 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_MAP_H
+#define ISL_MAP_H
+
+#include <stdio.h>
+
+#include <isl/ctx.h>
+#include <isl/space.h>
+#include <isl/vec.h>
+#include <isl/mat.h>
+#include <isl/printer.h>
+#include <isl/local_space.h>
+#include <isl/aff_type.h>
+#include <isl/list.h>
+#include <isl/map_type.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* General notes:
+ *
+ * All structures are reference counted to allow reuse without duplication.
+ * A *_copy operation will increase the reference count, while a *_free
+ * operation will decrease the reference count and only actually release
+ * the structures when the reference count drops to zero.
+ *
+ * Functions that return an isa structure will in general _destroy_
+ * all argument isa structures (the obvious execption begin the _copy
+ * functions).  A pointer passed to such a function may therefore
+ * never be used after the function call.  If you want to keep a
+ * reference to the old structure(s), use the appropriate _copy function.
+ */
+
+unsigned isl_basic_map_n_in(const struct isl_basic_map *bmap);
+unsigned isl_basic_map_n_out(const struct isl_basic_map *bmap);
+unsigned isl_basic_map_n_param(const struct isl_basic_map *bmap);
+unsigned isl_basic_map_n_div(const struct isl_basic_map *bmap);
+unsigned isl_basic_map_total_dim(const struct isl_basic_map *bmap);
+unsigned isl_basic_map_dim(__isl_keep isl_basic_map *bmap,
+				enum isl_dim_type type);
+
+unsigned isl_map_n_in(const struct isl_map *map);
+unsigned isl_map_n_out(const struct isl_map *map);
+unsigned isl_map_n_param(const struct isl_map *map);
+unsigned isl_map_dim(__isl_keep isl_map *map, enum isl_dim_type type);
+
+isl_ctx *isl_basic_map_get_ctx(__isl_keep isl_basic_map *bmap);
+isl_ctx *isl_map_get_ctx(__isl_keep isl_map *map);
+__isl_give isl_space *isl_basic_map_get_space(__isl_keep isl_basic_map *bmap);
+__isl_give isl_space *isl_map_get_space(__isl_keep isl_map *map);
+
+__isl_give isl_aff *isl_basic_map_get_div(__isl_keep isl_basic_map *bmap,
+	int pos);
+
+__isl_give isl_local_space *isl_basic_map_get_local_space(
+	__isl_keep isl_basic_map *bmap);
+
+__isl_give isl_basic_map *isl_basic_map_set_tuple_name(
+	__isl_take isl_basic_map *bmap, enum isl_dim_type type, const char *s);
+const char *isl_basic_map_get_tuple_name(__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type);
+int isl_map_has_tuple_name(__isl_keep isl_map *map, enum isl_dim_type type);
+const char *isl_map_get_tuple_name(__isl_keep isl_map *map,
+	enum isl_dim_type type);
+__isl_give isl_map *isl_map_set_tuple_name(__isl_take isl_map *map,
+	enum isl_dim_type type, const char *s);
+const char *isl_basic_map_get_dim_name(__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned pos);
+int isl_map_has_dim_name(__isl_keep isl_map *map,
+	enum isl_dim_type type, unsigned pos);
+const char *isl_map_get_dim_name(__isl_keep isl_map *map,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_basic_map *isl_basic_map_set_dim_name(
+	__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned pos, const char *s);
+__isl_give isl_map *isl_map_set_dim_name(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned pos, const char *s);
+
+__isl_give isl_basic_map *isl_basic_map_set_tuple_id(
+	__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, __isl_take isl_id *id);
+__isl_give isl_map *isl_map_set_dim_id(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+int isl_basic_map_has_dim_id(__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned pos);
+int isl_map_has_dim_id(__isl_keep isl_map *map,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_map_get_dim_id(__isl_keep isl_map *map,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_map *isl_map_set_tuple_id(__isl_take isl_map *map,
+	enum isl_dim_type type, __isl_take isl_id *id);
+__isl_give isl_map *isl_map_reset_tuple_id(__isl_take isl_map *map,
+	enum isl_dim_type type);
+int isl_map_has_tuple_id(__isl_keep isl_map *map, enum isl_dim_type type);
+__isl_give isl_id *isl_map_get_tuple_id(__isl_keep isl_map *map,
+	enum isl_dim_type type);
+__isl_give isl_map *isl_map_reset_user(__isl_take isl_map *map);
+
+int isl_basic_map_find_dim_by_name(__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type, const char *name);
+int isl_map_find_dim_by_id(__isl_keep isl_map *map, enum isl_dim_type type,
+	__isl_keep isl_id *id);
+int isl_map_find_dim_by_name(__isl_keep isl_map *map, enum isl_dim_type type,
+	const char *name);
+
+int isl_basic_map_is_rational(__isl_keep isl_basic_map *bmap);
+
+struct isl_basic_map *isl_basic_map_alloc(struct isl_ctx *ctx,
+		unsigned nparam, unsigned in, unsigned out, unsigned extra,
+		unsigned n_eq, unsigned n_ineq);
+__isl_give isl_basic_map *isl_basic_map_identity(__isl_take isl_space *dim);
+struct isl_basic_map *isl_basic_map_identity_like(struct isl_basic_map *model);
+struct isl_basic_map *isl_basic_map_finalize(struct isl_basic_map *bmap);
+__isl_null isl_basic_map *isl_basic_map_free(__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_copy(__isl_keep isl_basic_map *bmap);
+struct isl_basic_map *isl_basic_map_extend(struct isl_basic_map *base,
+		unsigned nparam, unsigned n_in, unsigned n_out, unsigned extra,
+		unsigned n_eq, unsigned n_ineq);
+struct isl_basic_map *isl_basic_map_extend_constraints(
+		struct isl_basic_map *base, unsigned n_eq, unsigned n_ineq);
+__isl_give isl_basic_map *isl_basic_map_equal(
+	__isl_take isl_space *dim, unsigned n_equal);
+__isl_give isl_basic_map *isl_basic_map_less_at(__isl_take isl_space *dim,
+	unsigned pos);
+__isl_give isl_basic_map *isl_basic_map_more_at(__isl_take isl_space *dim,
+	unsigned pos);
+__isl_give isl_basic_map *isl_basic_map_empty(__isl_take isl_space *dim);
+struct isl_basic_map *isl_basic_map_empty_like(struct isl_basic_map *model);
+struct isl_basic_map *isl_basic_map_empty_like_map(struct isl_map *model);
+__isl_give isl_basic_map *isl_basic_map_universe(__isl_take isl_space *dim);
+__isl_give isl_basic_map *isl_basic_map_nat_universe(__isl_take isl_space *dim);
+__isl_give isl_basic_map *isl_basic_map_universe_like(
+		__isl_keep isl_basic_map *bmap);
+__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);
+__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_export
+__isl_give isl_basic_map *isl_basic_map_intersect_domain(
+		__isl_take isl_basic_map *bmap,
+		__isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_intersect_range(
+		__isl_take isl_basic_map *bmap,
+		__isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_intersect(
+		__isl_take isl_basic_map *bmap1,
+		__isl_take isl_basic_map *bmap2);
+__isl_export
+__isl_give isl_map *isl_basic_map_union(
+		__isl_take isl_basic_map *bmap1,
+		__isl_take isl_basic_map *bmap2);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_apply_domain(
+		__isl_take isl_basic_map *bmap1,
+		__isl_take isl_basic_map *bmap2);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_apply_range(
+		__isl_take isl_basic_map *bmap1,
+		__isl_take isl_basic_map *bmap2);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_affine_hull(
+		__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_preimage_domain_multi_aff(
+	__isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma);
+__isl_give isl_basic_map *isl_basic_map_preimage_range_multi_aff(
+	__isl_take isl_basic_map *bmap, __isl_take isl_multi_aff *ma);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_reverse(__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_set *isl_basic_map_domain(__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_set *isl_basic_map_range(__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_domain_map(
+	__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_range_map(
+	__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_remove_dims(
+	__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_eliminate(
+	__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_from_basic_set(
+	__isl_take isl_basic_set *bset, __isl_take isl_space *dim);
+struct isl_basic_set *isl_basic_set_from_basic_map(struct isl_basic_map *bmap);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_sample(__isl_take isl_basic_map *bmap);
+struct isl_basic_map *isl_basic_map_simplify(struct isl_basic_map *bmap);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_detect_equalities(
+						__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_map *isl_basic_map_read_from_file(isl_ctx *ctx,
+	FILE *input);
+__isl_constructor
+__isl_give isl_basic_map *isl_basic_map_read_from_str(isl_ctx *ctx,
+	const char *str);
+__isl_give isl_map *isl_map_read_from_file(isl_ctx *ctx, FILE *input);
+__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);
+__isl_give isl_printer *isl_printer_print_map(__isl_take isl_printer *printer,
+	__isl_keep isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_fix_si(__isl_take isl_basic_map *bmap,
+		enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_basic_map *isl_basic_map_fix_val(__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v);
+__isl_give isl_basic_map *isl_basic_map_lower_bound_si(
+		__isl_take isl_basic_map *bmap,
+		enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_basic_map *isl_basic_map_upper_bound_si(
+	__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned pos, int value);
+
+struct isl_basic_map *isl_basic_map_sum(
+		struct isl_basic_map *bmap1, struct isl_basic_map *bmap2);
+struct isl_basic_map *isl_basic_map_neg(struct isl_basic_map *bmap);
+
+struct isl_map *isl_map_sum(struct isl_map *map1, struct isl_map *map2);
+struct isl_map *isl_map_neg(struct isl_map *map);
+__isl_give isl_map *isl_map_floordiv_val(__isl_take isl_map *map,
+	__isl_take isl_val *d);
+
+__isl_export
+int isl_basic_map_is_equal(
+		__isl_keep isl_basic_map *bmap1,
+		__isl_keep isl_basic_map *bmap2);
+int isl_basic_map_is_disjoint(__isl_keep isl_basic_map *bmap1,
+	__isl_keep isl_basic_map *bmap2);
+
+__isl_give isl_map *isl_basic_map_partial_lexmax(
+		__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+		__isl_give isl_set **empty);
+__isl_give isl_map *isl_basic_map_partial_lexmin(
+		__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+		__isl_give isl_set **empty);
+__isl_give isl_map *isl_map_partial_lexmax(
+		__isl_take isl_map *map, __isl_take isl_set *dom,
+		__isl_give isl_set **empty);
+__isl_give isl_map *isl_map_partial_lexmin(
+		__isl_take isl_map *map, __isl_take isl_set *dom,
+		__isl_give isl_set **empty);
+__isl_export
+__isl_give isl_map *isl_basic_map_lexmin(__isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_map *isl_basic_map_lexmax(__isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_map *isl_map_lexmin(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_map *isl_map_lexmax(__isl_take isl_map *map);
+__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmin_pw_multi_aff(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty);
+__isl_give isl_pw_multi_aff *isl_basic_map_partial_lexmax_pw_multi_aff(
+	__isl_take isl_basic_map *bmap, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty);
+__isl_give isl_pw_multi_aff *isl_basic_map_lexmin_pw_multi_aff(
+	__isl_take isl_basic_map *bmap);
+__isl_give isl_pw_multi_aff *isl_map_lexmin_pw_multi_aff(
+	__isl_take isl_map *map);
+__isl_give isl_pw_multi_aff *isl_map_lexmax_pw_multi_aff(
+	__isl_take isl_map *map);
+
+void isl_basic_map_print_internal(__isl_keep isl_basic_map *bmap,
+	FILE *out, int indent);
+
+struct isl_basic_map *isl_map_copy_basic_map(struct isl_map *map);
+__isl_give isl_map *isl_map_drop_basic_map(__isl_take isl_map *map,
+						__isl_keep isl_basic_map *bmap);
+
+__isl_give isl_val *isl_basic_map_plain_get_val_if_fixed(
+	__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned pos);
+
+int isl_basic_map_image_is_bounded(__isl_keep isl_basic_map *bmap);
+int isl_basic_map_is_universe(__isl_keep isl_basic_map *bmap);
+int isl_basic_map_plain_is_empty(__isl_keep isl_basic_map *bmap);
+ISL_DEPRECATED
+int isl_basic_map_fast_is_empty(__isl_keep isl_basic_map *bmap);
+__isl_export
+int isl_basic_map_is_empty(__isl_keep isl_basic_map *bmap);
+__isl_export
+int isl_basic_map_is_subset(__isl_keep isl_basic_map *bmap1,
+		__isl_keep isl_basic_map *bmap2);
+int isl_basic_map_is_strict_subset(__isl_keep isl_basic_map *bmap1,
+		__isl_keep isl_basic_map *bmap2);
+
+struct isl_map *isl_map_alloc(struct isl_ctx *ctx,
+		unsigned nparam, unsigned in, unsigned out, int n,
+		unsigned flags);
+__isl_give isl_map *isl_map_universe(__isl_take isl_space *dim);
+__isl_give isl_map *isl_map_nat_universe(__isl_take isl_space *dim);
+__isl_give isl_map *isl_map_empty(__isl_take isl_space *dim);
+struct isl_map *isl_map_empty_like(struct isl_map *model);
+struct isl_map *isl_map_empty_like_basic_map(struct isl_basic_map *model);
+struct isl_map *isl_map_dup(struct isl_map *map);
+__isl_give isl_map *isl_map_add_basic_map(__isl_take isl_map *map,
+						__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_identity(__isl_take isl_space *dim);
+struct isl_map *isl_map_identity_like(struct isl_map *model);
+struct isl_map *isl_map_identity_like_basic_map(struct isl_basic_map *model);
+__isl_give isl_map *isl_map_lex_lt_first(__isl_take isl_space *dim, unsigned n);
+__isl_give isl_map *isl_map_lex_le_first(__isl_take isl_space *dim, unsigned n);
+__isl_give isl_map *isl_map_lex_lt(__isl_take isl_space *set_dim);
+__isl_give isl_map *isl_map_lex_le(__isl_take isl_space *set_dim);
+__isl_give isl_map *isl_map_lex_gt_first(__isl_take isl_space *dim, unsigned n);
+__isl_give isl_map *isl_map_lex_ge_first(__isl_take isl_space *dim, unsigned n);
+__isl_give isl_map *isl_map_lex_gt(__isl_take isl_space *set_dim);
+__isl_give isl_map *isl_map_lex_ge(__isl_take isl_space *set_dim);
+struct isl_map *isl_map_finalize(struct isl_map *map);
+__isl_null isl_map *isl_map_free(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_copy(__isl_keep isl_map *map);
+struct isl_map *isl_map_extend(struct isl_map *base,
+		unsigned nparam, unsigned n_in, unsigned n_out);
+__isl_export
+__isl_give isl_map *isl_map_reverse(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_map *isl_map_union(
+		__isl_take isl_map *map1,
+		__isl_take isl_map *map2);
+struct isl_map *isl_map_union_disjoint(
+			struct isl_map *map1, struct isl_map *map2);
+__isl_export
+__isl_give isl_map *isl_map_intersect_domain(
+		__isl_take isl_map *map,
+		__isl_take isl_set *set);
+__isl_export
+__isl_give isl_map *isl_map_intersect_range(
+		__isl_take isl_map *map,
+		__isl_take isl_set *set);
+__isl_export
+__isl_give isl_map *isl_map_apply_domain(
+		__isl_take isl_map *map1,
+		__isl_take isl_map *map2);
+__isl_export
+__isl_give isl_map *isl_map_apply_range(
+		__isl_take isl_map *map1,
+		__isl_take isl_map *map2);
+__isl_give isl_map *isl_map_preimage_domain_multi_aff(__isl_take isl_map *map,
+	__isl_take isl_multi_aff *ma);
+__isl_give isl_map *isl_map_preimage_range_multi_aff(__isl_take isl_map *map,
+	__isl_take isl_multi_aff *ma);
+__isl_give isl_map *isl_map_preimage_domain_pw_multi_aff(
+	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_map *isl_map_preimage_range_pw_multi_aff(
+	__isl_take isl_map *map, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_map *isl_map_preimage_domain_multi_pw_aff(
+	__isl_take isl_map *map, __isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_basic_map *isl_basic_map_product(
+	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2);
+__isl_give isl_map *isl_map_product(__isl_take isl_map *map1,
+	__isl_take isl_map *map2);
+__isl_give isl_basic_map *isl_basic_map_domain_product(
+	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2);
+__isl_give isl_basic_map *isl_basic_map_range_product(
+	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2);
+__isl_give isl_map *isl_map_domain_product(__isl_take isl_map *map1,
+	__isl_take isl_map *map2);
+__isl_give isl_map *isl_map_range_product(__isl_take isl_map *map1,
+	__isl_take isl_map *map2);
+__isl_give isl_basic_map *isl_basic_map_flat_product(
+	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2);
+__isl_give isl_map *isl_map_flat_product(__isl_take isl_map *map1,
+	__isl_take isl_map *map2);
+__isl_give isl_basic_map *isl_basic_map_flat_range_product(
+	__isl_take isl_basic_map *bmap1, __isl_take isl_basic_map *bmap2);
+__isl_give isl_map *isl_map_flat_domain_product(__isl_take isl_map *map1,
+	__isl_take isl_map *map2);
+__isl_give isl_map *isl_map_flat_range_product(__isl_take isl_map *map1,
+	__isl_take isl_map *map2);
+int isl_map_domain_is_wrapping(__isl_keep isl_map *map);
+int isl_map_range_is_wrapping(__isl_keep isl_map *map);
+__isl_give isl_map *isl_map_factor_domain(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_factor_range(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_domain_factor_domain(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_domain_factor_range(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_range_factor_domain(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_range_factor_range(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_map *isl_map_intersect(__isl_take isl_map *map1,
+				      __isl_take isl_map *map2);
+__isl_export
+__isl_give isl_map *isl_map_intersect_params(__isl_take isl_map *map,
+		__isl_take isl_set *params);
+__isl_export
+__isl_give isl_map *isl_map_subtract(
+		__isl_take isl_map *map1,
+		__isl_take isl_map *map2);
+__isl_give isl_map *isl_map_subtract_domain(__isl_take isl_map *map,
+	__isl_take isl_set *dom);
+__isl_give isl_map *isl_map_subtract_range(__isl_take isl_map *map,
+	__isl_take isl_set *dom);
+__isl_export
+__isl_give isl_map *isl_map_complement(__isl_take isl_map *map);
+struct isl_map *isl_map_fix_input_si(struct isl_map *map,
+		unsigned input, int value);
+__isl_give isl_map *isl_map_fix_si(__isl_take isl_map *map,
+		enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_map *isl_map_fix_val(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v);
+__isl_give isl_map *isl_map_lower_bound_si(__isl_take isl_map *map,
+		enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_map *isl_map_upper_bound_si(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned pos, int value);
+__isl_export
+__isl_give isl_basic_set *isl_basic_map_deltas(__isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_set *isl_map_deltas(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_deltas_map(
+	__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_deltas_map(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_map *isl_map_detect_equalities(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_basic_map *isl_map_affine_hull(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_map_convex_hull(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_basic_map *isl_map_polyhedral_hull(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_add(__isl_take isl_basic_map *bmap,
+		enum isl_dim_type type, unsigned n);
+__isl_give isl_map *isl_map_add_dims(__isl_take isl_map *map,
+		enum isl_dim_type type, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_insert_dims(
+	__isl_take isl_basic_map *bmap, enum isl_dim_type type,
+	unsigned pos, unsigned n);
+__isl_give isl_map *isl_map_insert_dims(__isl_take isl_map *map,
+		enum isl_dim_type type, unsigned pos, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_move_dims(
+	__isl_take isl_basic_map *bmap,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_map *isl_map_move_dims(__isl_take isl_map *map,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_project_out(
+		__isl_take isl_basic_map *bmap,
+		enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_map *isl_map_project_out(__isl_take isl_map *map,
+		enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_remove_divs(
+	__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_remove_unknown_divs(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_remove_divs(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_eliminate(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_map *isl_map_remove_dims(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_map *isl_basic_map_remove_divs_involving_dims(
+	__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_map *isl_map_remove_divs_involving_dims(__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned first, unsigned n);
+struct isl_map *isl_map_remove_inputs(struct isl_map *map,
+	unsigned first, unsigned n);
+
+__isl_give isl_basic_map *isl_basic_map_equate(__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_basic_map *isl_basic_map_order_ge(__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_order_ge(__isl_take isl_map *map,
+	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_order_le(__isl_take isl_map *map,
+	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_equate(__isl_take isl_map *map,
+	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_oppose(__isl_take isl_map *map,
+	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_order_lt(__isl_take isl_map *map,
+	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_basic_map *isl_basic_map_order_gt(__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+__isl_give isl_map *isl_map_order_gt(__isl_take isl_map *map,
+	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+
+__isl_export
+__isl_give isl_map *isl_set_identity(__isl_take isl_set *set);
+
+__isl_export
+int isl_basic_set_is_wrapping(__isl_keep isl_basic_set *bset);
+__isl_export
+int isl_set_is_wrapping(__isl_keep isl_set *set);
+__isl_give isl_basic_set *isl_basic_map_wrap(__isl_take isl_basic_map *bmap);
+__isl_give isl_set *isl_map_wrap(__isl_take isl_map *map);
+__isl_give isl_basic_map *isl_basic_set_unwrap(__isl_take isl_basic_set *bset);
+__isl_give isl_map *isl_set_unwrap(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_flatten(__isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_map *isl_map_flatten(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_flatten_domain(
+	__isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_flatten_range(
+	__isl_take isl_basic_map *bmap);
+__isl_export
+__isl_give isl_map *isl_map_flatten_domain(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_map *isl_map_flatten_range(__isl_take isl_map *map);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_flatten(__isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_set *isl_set_flatten(__isl_take isl_set *set);
+__isl_give isl_map *isl_set_flatten_map(__isl_take isl_set *set);
+__isl_give isl_set *isl_map_params(__isl_take isl_map *map);
+__isl_give isl_set *isl_map_domain(__isl_take isl_map *bmap);
+__isl_give isl_set *isl_map_range(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_domain_map(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_range_map(__isl_take isl_map *map);
+__isl_give isl_map *isl_set_wrapped_domain_map(__isl_take isl_set *set);
+__isl_constructor
+__isl_give isl_map *isl_map_from_basic_map(__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_from_domain(__isl_take isl_set *set);
+__isl_give isl_basic_map *isl_basic_map_from_domain(
+	__isl_take isl_basic_set *bset);
+__isl_give isl_basic_map *isl_basic_map_from_range(
+	__isl_take isl_basic_set *bset);
+__isl_give isl_map *isl_map_from_range(__isl_take isl_set *set);
+__isl_give isl_basic_map *isl_basic_map_from_domain_and_range(
+	__isl_take isl_basic_set *domain, __isl_take isl_basic_set *range);
+__isl_give isl_map *isl_map_from_domain_and_range(__isl_take isl_set *domain,
+	__isl_take isl_set *range);
+__isl_give isl_map *isl_map_from_set(__isl_take isl_set *set,
+	__isl_take isl_space *dim);
+struct isl_set *isl_set_from_map(struct isl_map *map);
+__isl_export
+__isl_give isl_basic_map *isl_map_sample(__isl_take isl_map *map);
+
+int isl_map_plain_is_empty(__isl_keep isl_map *map);
+ISL_DEPRECATED
+int isl_map_fast_is_empty(__isl_keep isl_map *map);
+int isl_map_plain_is_universe(__isl_keep isl_map *map);
+__isl_export
+int isl_map_is_empty(__isl_keep isl_map *map);
+__isl_export
+int isl_map_is_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+__isl_export
+int isl_map_is_strict_subset(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+__isl_export
+int isl_map_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+__isl_export
+int isl_map_is_disjoint(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+int isl_basic_map_is_single_valued(__isl_keep isl_basic_map *bmap);
+int isl_map_plain_is_single_valued(__isl_keep isl_map *map);
+__isl_export
+int isl_map_is_single_valued(__isl_keep isl_map *map);
+int isl_map_plain_is_injective(__isl_keep isl_map *map);
+__isl_export
+int isl_map_is_injective(__isl_keep isl_map *map);
+__isl_export
+int isl_map_is_bijective(__isl_keep isl_map *map);
+int isl_map_is_translation(__isl_keep isl_map *map);
+int isl_map_has_equal_space(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+
+int isl_basic_map_can_zip(__isl_keep isl_basic_map *bmap);
+int isl_map_can_zip(__isl_keep isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_zip(__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_zip(__isl_take isl_map *map);
+
+int isl_basic_map_can_curry(__isl_keep isl_basic_map *bmap);
+int isl_map_can_curry(__isl_keep isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_curry(__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_curry(__isl_take isl_map *map);
+
+int isl_basic_map_can_uncurry(__isl_keep isl_basic_map *bmap);
+int isl_map_can_uncurry(__isl_keep isl_map *map);
+__isl_give isl_basic_map *isl_basic_map_uncurry(__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_uncurry(__isl_take isl_map *map);
+
+__isl_give isl_map *isl_map_make_disjoint(__isl_take isl_map *map);
+__isl_give isl_map *isl_basic_map_compute_divs(__isl_take isl_basic_map *bmap);
+__isl_give isl_map *isl_map_compute_divs(__isl_take isl_map *map);
+__isl_give isl_map *isl_map_align_divs(__isl_take isl_map *map);
+
+__isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
+	__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_map *isl_map_drop_constraints_involving_dims(
+	__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+int isl_basic_map_involves_dims(__isl_keep isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned first, unsigned n);
+int isl_map_involves_dims(__isl_keep isl_map *map,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+void isl_map_print_internal(__isl_keep isl_map *map, FILE *out, int indent);
+
+__isl_give isl_val *isl_map_plain_get_val_if_fixed(__isl_keep isl_map *map,
+	enum isl_dim_type type, unsigned pos);
+
+__isl_export
+__isl_give isl_basic_map *isl_basic_map_gist(__isl_take isl_basic_map *bmap,
+	__isl_take isl_basic_map *context);
+__isl_export
+__isl_give isl_map *isl_map_gist(__isl_take isl_map *map,
+	__isl_take isl_map *context);
+__isl_export
+__isl_give isl_map *isl_map_gist_domain(__isl_take isl_map *map,
+	__isl_take isl_set *context);
+__isl_give isl_map *isl_map_gist_range(__isl_take isl_map *map,
+	__isl_take isl_set *context);
+__isl_give isl_map *isl_map_gist_params(__isl_take isl_map *map,
+	__isl_take isl_set *context);
+__isl_give isl_map *isl_map_gist_basic_map(__isl_take isl_map *map,
+	__isl_take isl_basic_map *context);
+
+__isl_export
+__isl_give isl_map *isl_map_coalesce(__isl_take isl_map *map);
+
+int isl_map_plain_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+ISL_DEPRECATED
+int isl_map_fast_is_equal(__isl_keep isl_map *map1, __isl_keep isl_map *map2);
+
+uint32_t isl_map_get_hash(__isl_keep isl_map *map);
+
+int isl_map_n_basic_map(__isl_keep isl_map *map);
+__isl_export
+int isl_map_foreach_basic_map(__isl_keep isl_map *map,
+	int (*fn)(__isl_take isl_basic_map *bmap, void *user), void *user);
+
+__isl_give isl_map *isl_set_lifting(__isl_take isl_set *set);
+
+__isl_give isl_map *isl_map_fixed_power_val(__isl_take isl_map *map,
+	__isl_take isl_val *exp);
+__isl_give isl_map *isl_map_power(__isl_take isl_map *map, int *exact);
+__isl_give isl_map *isl_map_reaching_path_lengths(__isl_take isl_map *map,
+	int *exact);
+__isl_give isl_map *isl_map_transitive_closure(__isl_take isl_map *map,
+	int *exact);
+
+__isl_give isl_map *isl_map_lex_le_map(__isl_take isl_map *map1,
+	__isl_take isl_map *map2);
+__isl_give isl_map *isl_map_lex_lt_map(__isl_take isl_map *map1,
+	__isl_take isl_map *map2);
+__isl_give isl_map *isl_map_lex_ge_map(__isl_take isl_map *map1,
+	__isl_take isl_map *map2);
+__isl_give isl_map *isl_map_lex_gt_map(__isl_take isl_map *map1,
+	__isl_take isl_map *map2);
+
+__isl_give isl_basic_map *isl_basic_map_align_params(
+	__isl_take isl_basic_map *bmap, __isl_take isl_space *model);
+__isl_give isl_map *isl_map_align_params(__isl_take isl_map *map,
+	__isl_take isl_space *model);
+
+__isl_give isl_mat *isl_basic_map_equalities_matrix(
+		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
+		enum isl_dim_type c2, enum isl_dim_type c3,
+		enum isl_dim_type c4, enum isl_dim_type c5);
+__isl_give isl_mat *isl_basic_map_inequalities_matrix(
+		__isl_keep isl_basic_map *bmap, enum isl_dim_type c1,
+		enum isl_dim_type c2, enum isl_dim_type c3,
+		enum isl_dim_type c4, enum isl_dim_type c5);
+__isl_give isl_basic_map *isl_basic_map_from_constraint_matrices(
+	__isl_take isl_space *dim,
+	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
+	enum isl_dim_type c2, enum isl_dim_type c3,
+	enum isl_dim_type c4, enum isl_dim_type c5);
+
+__isl_give isl_basic_map *isl_basic_map_from_aff(__isl_take isl_aff *aff);
+__isl_give isl_basic_map *isl_basic_map_from_multi_aff(
+	__isl_take isl_multi_aff *maff);
+__isl_give isl_basic_map *isl_basic_map_from_aff_list(
+	__isl_take isl_space *domain_dim, __isl_take isl_aff_list *list);
+
+__isl_give isl_map *isl_map_from_aff(__isl_take isl_aff *aff);
+__isl_give isl_map *isl_map_from_multi_aff(__isl_take isl_multi_aff *maff);
+
+__isl_give isl_pw_aff *isl_map_dim_max(__isl_take isl_map *map, int pos);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/map_to_basic_set.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/map_to_basic_set.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/map_to_basic_set.h (added)
+++ polly/trunk/lib/External/isl/include/isl/map_to_basic_set.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,13 @@
+#ifndef ISL_MAP_TO_BASIC_SET_H
+#define ISL_MAP_TO_BASIC_SET_H
+
+#include <isl/set_type.h>
+#include <isl/map_type.h>
+
+#define ISL_KEY_BASE	map
+#define ISL_VAL_BASE	basic_set
+#include <isl/hmap.h>
+#undef ISL_KEY_BASE
+#undef ISL_VAL_BASE
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/map_type.h (added)
+++ polly/trunk/lib/External/isl/include/isl/map_type.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,35 @@
+#ifndef ISL_MAP_TYPE_H
+#define ISL_MAP_TYPE_H
+
+#include <isl/ctx.h>
+#include <isl/list.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct __isl_subclass(isl_map) isl_basic_map;
+typedef struct isl_basic_map isl_basic_map;
+struct __isl_subclass(isl_union_map) isl_map;
+typedef struct isl_map isl_map;
+
+#ifndef isl_basic_set
+struct __isl_subclass(isl_set) isl_basic_set;
+typedef struct isl_basic_set isl_basic_set;
+ISL_DECLARE_LIST_TYPE(basic_set)
+#endif
+
+#ifndef isl_set
+struct __isl_subclass(isl_union_set) isl_set;
+typedef struct isl_set isl_set;
+ISL_DECLARE_LIST_TYPE(set)
+#endif
+
+ISL_DECLARE_LIST_FN(basic_set)
+ISL_DECLARE_LIST_FN(set)
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/mat.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/mat.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/mat.h (added)
+++ polly/trunk/lib/External/isl/include/isl/mat.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_MAT_H
+#define ISL_MAT_H
+
+#include <stdio.h>
+
+#include <isl/ctx.h>
+#include <isl/vec.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_mat;
+typedef struct isl_mat	isl_mat;
+
+isl_ctx *isl_mat_get_ctx(__isl_keep isl_mat *mat);
+
+__isl_give isl_mat *isl_mat_alloc(isl_ctx *ctx,
+	unsigned n_row, unsigned n_col);
+struct isl_mat *isl_mat_dup(struct isl_mat *mat);
+struct isl_mat *isl_mat_extend(struct isl_mat *mat,
+	unsigned n_row, unsigned n_col);
+struct isl_mat *isl_mat_identity(struct isl_ctx *ctx, unsigned n_row);
+__isl_give isl_mat *isl_mat_copy(__isl_keep isl_mat *mat);
+struct isl_mat *isl_mat_cow(struct isl_mat *mat);
+__isl_null isl_mat *isl_mat_free(__isl_take isl_mat *mat);
+
+int isl_mat_rows(__isl_keep isl_mat *mat);
+int isl_mat_cols(__isl_keep isl_mat *mat);
+__isl_give isl_val *isl_mat_get_element_val(__isl_keep isl_mat *mat,
+	int row, int col);
+__isl_give isl_mat *isl_mat_set_element_si(__isl_take isl_mat *mat,
+	int row, int col, int v);
+__isl_give isl_mat *isl_mat_set_element_val(__isl_take isl_mat *mat,
+	int row, int col, __isl_take isl_val *v);
+
+struct isl_mat *isl_mat_swap_cols(struct isl_mat *mat, unsigned i, unsigned j);
+struct isl_mat *isl_mat_swap_rows(struct isl_mat *mat, unsigned i, unsigned j);
+
+struct isl_vec *isl_mat_vec_product(struct isl_mat *mat, struct isl_vec *vec);
+struct isl_vec *isl_vec_mat_product(struct isl_vec *vec, struct isl_mat *mat);
+__isl_give isl_vec *isl_mat_vec_inverse_product(__isl_take isl_mat *mat,
+						__isl_take isl_vec *vec);
+struct isl_mat *isl_mat_aff_direct_sum(struct isl_mat *left,
+					struct isl_mat *right);
+__isl_give isl_mat *isl_mat_diagonal(__isl_take isl_mat *mat1,
+	__isl_take isl_mat *mat2);
+struct isl_mat *isl_mat_left_hermite(struct isl_mat *M,
+	int neg, struct isl_mat **U, struct isl_mat **Q);
+struct isl_mat *isl_mat_lin_to_aff(struct isl_mat *mat);
+struct isl_mat *isl_mat_inverse_product(struct isl_mat *left,
+	struct isl_mat *right);
+__isl_give isl_mat *isl_mat_product(__isl_take isl_mat *left,
+	__isl_take isl_mat *right);
+struct isl_mat *isl_mat_transpose(struct isl_mat *mat);
+__isl_give isl_mat *isl_mat_right_inverse(__isl_take isl_mat *mat);
+__isl_give isl_mat *isl_mat_right_kernel(__isl_take isl_mat *mat);
+
+__isl_give isl_mat *isl_mat_normalize(__isl_take isl_mat *mat);
+__isl_give isl_mat *isl_mat_normalize_row(__isl_take isl_mat *mat, int row);
+
+struct isl_mat *isl_mat_drop_cols(struct isl_mat *mat,
+				unsigned col, unsigned n);
+struct isl_mat *isl_mat_drop_rows(struct isl_mat *mat,
+				unsigned row, unsigned n);
+__isl_give isl_mat *isl_mat_insert_cols(__isl_take isl_mat *mat,
+				unsigned col, unsigned n);
+__isl_give isl_mat *isl_mat_insert_rows(__isl_take isl_mat *mat,
+				unsigned row, unsigned n);
+__isl_give isl_mat *isl_mat_move_cols(__isl_take isl_mat *mat,
+	unsigned dst_col, unsigned src_col, unsigned n);
+__isl_give isl_mat *isl_mat_add_rows(__isl_take isl_mat *mat, unsigned n);
+__isl_give isl_mat *isl_mat_insert_zero_cols(__isl_take isl_mat *mat,
+	unsigned first, unsigned n);
+__isl_give isl_mat *isl_mat_add_zero_cols(__isl_take isl_mat *mat, unsigned n);
+__isl_give isl_mat *isl_mat_insert_zero_rows(__isl_take isl_mat *mat,
+	unsigned row, unsigned n);
+__isl_give isl_mat *isl_mat_add_zero_rows(__isl_take isl_mat *mat, unsigned n);
+
+void isl_mat_col_add(__isl_keep isl_mat *mat, int dst_col, int src_col);
+
+struct isl_mat *isl_mat_unimodular_complete(struct isl_mat *M, int row);
+
+__isl_give isl_mat *isl_mat_from_row_vec(__isl_take isl_vec *vec);
+__isl_give isl_mat *isl_mat_concat(__isl_take isl_mat *top,
+	__isl_take isl_mat *bot);
+__isl_give isl_mat *isl_mat_vec_concat(__isl_take isl_mat *top,
+	__isl_take isl_vec *bot);
+
+int isl_mat_is_equal(__isl_keep isl_mat *mat1, __isl_keep isl_mat *mat2);
+
+int isl_mat_initial_non_zero_cols(__isl_keep isl_mat *mat);
+
+void isl_mat_print_internal(__isl_keep isl_mat *mat, FILE *out, int indent);
+void isl_mat_dump(__isl_keep isl_mat *mat);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/multi.h (added)
+++ polly/trunk/lib/External/isl/include/isl/multi.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,123 @@
+#ifndef ISL_MULTI_H
+#define ISL_MULTI_H
+
+#include <isl/space.h>
+#include <isl/list.h>
+#include <isl/set_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define ISL_DECLARE_MULTI(BASE)						\
+unsigned isl_multi_##BASE##_dim(__isl_keep isl_multi_##BASE *multi,	\
+	enum isl_dim_type type);					\
+isl_ctx *isl_multi_##BASE##_get_ctx(					\
+	__isl_keep isl_multi_##BASE *multi);				\
+__isl_give isl_space *isl_multi_##BASE##_get_space(			\
+	__isl_keep isl_multi_##BASE *multi);				\
+__isl_give isl_space *isl_multi_##BASE##_get_domain_space(		\
+	__isl_keep isl_multi_##BASE *multi);				\
+int isl_multi_##BASE##_find_dim_by_name(				\
+	__isl_keep isl_multi_##BASE *multi,				\
+	enum isl_dim_type type, const char *name);			\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_from_##BASE##_list(	\
+	__isl_take isl_space *space, __isl_take isl_##BASE##_list *list); \
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_zero(			\
+	__isl_take isl_space *space);					\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_copy(			\
+	__isl_keep isl_multi_##BASE *multi);				\
+__isl_null isl_multi_##BASE *isl_multi_##BASE##_free(			\
+	__isl_take isl_multi_##BASE *multi);				\
+int isl_multi_##BASE##_plain_is_equal(					\
+	__isl_keep isl_multi_##BASE *multi1,				\
+	__isl_keep isl_multi_##BASE *multi2);				\
+int isl_multi_##BASE##_find_dim_by_id(					\
+	__isl_keep isl_multi_##BASE *multi, enum isl_dim_type type,	\
+	__isl_keep isl_id *id);						\
+__isl_give isl_id *isl_multi_##BASE##_get_dim_id(			\
+	__isl_take isl_multi_##BASE *multi,				\
+	enum isl_dim_type type, unsigned pos);				\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_dim_name(		\
+	__isl_take isl_multi_##BASE *multi,				\
+	enum isl_dim_type type, unsigned pos, const char *s);		\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_dim_id(		\
+	__isl_take isl_multi_##BASE *multi,				\
+	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);	\
+const char *isl_multi_##BASE##_get_tuple_name(				\
+	__isl_keep isl_multi_##BASE *multi, enum isl_dim_type type);	\
+int isl_multi_##BASE##_has_tuple_id(__isl_keep isl_multi_##BASE *multi,	\
+	enum isl_dim_type type);					\
+__isl_give isl_id *isl_multi_##BASE##_get_tuple_id(			\
+	__isl_keep isl_multi_##BASE *multi, enum isl_dim_type type);	\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_tuple_name(		\
+	__isl_take isl_multi_##BASE *multi,				\
+	enum isl_dim_type type, const char *s);				\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_tuple_id(		\
+	__isl_take isl_multi_##BASE *multi,				\
+	enum isl_dim_type type, __isl_take isl_id *id);			\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_reset_tuple_id(		\
+	__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);					\
+__isl_give isl_##BASE *isl_multi_##BASE##_get_##BASE(			\
+	__isl_keep isl_multi_##BASE *multi, int pos);			\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_set_##BASE(		\
+	__isl_take isl_multi_##BASE *multi, int pos,			\
+	__isl_take isl_##BASE *el);					\
+__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(	\
+	__isl_take isl_multi_##BASE *multi1,				\
+	__isl_take isl_multi_##BASE *multi2);				\
+__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(	\
+	__isl_take isl_multi_##BASE *multi);				\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_range_factor_range(	\
+	__isl_take isl_multi_##BASE *multi);				\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_val(		\
+	__isl_take isl_multi_##BASE *multi, __isl_take isl_val *v);	\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_down_val(		\
+	__isl_take isl_multi_##BASE *multi, __isl_take isl_val *v);	\
+__isl_give isl_multi_##BASE *isl_multi_##BASE##_scale_multi_val(	\
+	__isl_take isl_multi_##BASE *multi,				\
+	__isl_take isl_multi_val *mv);					\
+__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##_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);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/obj.h (added)
+++ polly/trunk/lib/External/isl/include/isl/obj.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,55 @@
+#ifndef ISL_OBJ_H
+#define ISL_OBJ_H
+
+#include <isl/set_type.h>
+#include <isl/map_type.h>
+#include <isl/union_set_type.h>
+#include <isl/union_map_type.h>
+#include <isl/polynomial_type.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_obj_vtable {
+	void *(*copy)(void *v1);
+	void *(*add)(void *v1, void *v2);
+	__isl_give isl_printer *(*print)(__isl_take isl_printer *p, void *v);
+	void (*free)(void *v);
+};
+typedef struct isl_obj_vtable *isl_obj_type;
+extern struct isl_obj_vtable isl_obj_none_vtable;
+#define isl_obj_none		(&isl_obj_none_vtable)
+extern struct isl_obj_vtable isl_obj_int_vtable;
+#define isl_obj_int		(&isl_obj_int_vtable)
+extern struct isl_obj_vtable isl_obj_val_vtable;
+#define isl_obj_val		(&isl_obj_val_vtable)
+extern struct isl_obj_vtable isl_obj_set_vtable;
+#define isl_obj_set		(&isl_obj_set_vtable)
+extern struct isl_obj_vtable isl_obj_union_set_vtable;
+#define isl_obj_union_set	(&isl_obj_union_set_vtable)
+extern struct isl_obj_vtable isl_obj_map_vtable;
+#define isl_obj_map		(&isl_obj_map_vtable)
+extern struct isl_obj_vtable isl_obj_union_map_vtable;
+#define isl_obj_union_map	(&isl_obj_union_map_vtable)
+extern struct isl_obj_vtable isl_obj_pw_multi_aff_vtable;
+#define isl_obj_pw_multi_aff	(&isl_obj_pw_multi_aff_vtable)
+extern struct isl_obj_vtable isl_obj_pw_qpolynomial_vtable;
+#define isl_obj_pw_qpolynomial	(&isl_obj_pw_qpolynomial_vtable)
+extern struct isl_obj_vtable isl_obj_union_pw_qpolynomial_vtable;
+#define isl_obj_union_pw_qpolynomial	(&isl_obj_union_pw_qpolynomial_vtable)
+extern struct isl_obj_vtable isl_obj_pw_qpolynomial_fold_vtable;
+#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)
+struct isl_obj {
+	isl_obj_type	type;
+	void		*v;
+};
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/options.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/options.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/options.h (added)
+++ polly/trunk/lib/External/isl/include/isl/options.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_OPTIONS_H
+#define ISL_OPTIONS_H
+
+#include <isl/arg.h>
+#include <isl/ctx.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_options;
+
+ISL_ARG_DECL(isl_options, struct isl_options, isl_options_args)
+
+#define			ISL_BOUND_BERNSTEIN	0
+#define			ISL_BOUND_RANGE		1
+int isl_options_set_bound(isl_ctx *ctx, int val);
+int isl_options_get_bound(isl_ctx *ctx);
+
+#define			ISL_ON_ERROR_WARN	0
+#define			ISL_ON_ERROR_CONTINUE	1
+#define			ISL_ON_ERROR_ABORT	2
+int isl_options_set_on_error(isl_ctx *ctx, int val);
+int isl_options_get_on_error(isl_ctx *ctx);
+
+int isl_options_set_gbr_only_first(isl_ctx *ctx, int val);
+int isl_options_get_gbr_only_first(isl_ctx *ctx);
+
+#define		ISL_SCHEDULE_ALGORITHM_ISL		0
+#define		ISL_SCHEDULE_ALGORITHM_FEAUTRIER	1
+int isl_options_set_schedule_algorithm(isl_ctx *ctx, int val);
+int isl_options_get_schedule_algorithm(isl_ctx *ctx);
+
+int isl_options_set_coalesce_bounded_wrapping(isl_ctx *ctx, int val);
+int isl_options_get_coalesce_bounded_wrapping(isl_ctx *ctx);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/point.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/point.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/point.h (added)
+++ polly/trunk/lib/External/isl/include/isl/point.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,45 @@
+#ifndef ISL_POINT_H
+#define ISL_POINT_H
+
+#include <stdio.h>
+#include <isl/space.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_point;
+typedef struct isl_point isl_point;
+
+isl_ctx *isl_point_get_ctx(__isl_keep isl_point *pnt);
+__isl_give isl_space *isl_point_get_space(__isl_keep isl_point *pnt);
+
+__isl_give isl_point *isl_point_zero(__isl_take isl_space *dim);
+__isl_give isl_point *isl_point_copy(__isl_keep isl_point *pnt);
+void isl_point_free(__isl_take isl_point *pnt);
+
+__isl_give isl_val *isl_point_get_coordinate_val(__isl_keep isl_point *pnt,
+	enum isl_dim_type type, int pos);
+__isl_give isl_point *isl_point_set_coordinate_val(__isl_take isl_point *pnt,
+	enum isl_dim_type type, int pos, __isl_take isl_val *v);
+
+__isl_give isl_point *isl_point_add_ui(__isl_take isl_point *pnt,
+	enum isl_dim_type type, int pos, unsigned val);
+__isl_give isl_point *isl_point_sub_ui(__isl_take isl_point *pnt,
+	enum isl_dim_type type, int pos, unsigned val);
+
+__isl_give isl_point *isl_point_void(__isl_take isl_space *dim);
+int isl_point_is_void(__isl_keep isl_point *pnt);
+
+__isl_give isl_printer *isl_printer_print_point(
+	__isl_take isl_printer *printer, __isl_keep isl_point *pnt);
+void isl_point_dump(__isl_keep isl_point *pnt);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/polynomial.h (added)
+++ polly/trunk/lib/External/isl/include/isl/polynomial.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,623 @@
+#ifndef ISL_POLYNOMIAL_H
+#define ISL_POLYNOMIAL_H
+
+#include <isl/ctx.h>
+#include <isl/constraint.h>
+#include <isl/space.h>
+#include <isl/set_type.h>
+#include <isl/point.h>
+#include <isl/printer.h>
+#include <isl/union_set_type.h>
+#include <isl/aff_type.h>
+#include <isl/polynomial_type.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+isl_ctx *isl_qpolynomial_get_ctx(__isl_keep isl_qpolynomial *qp);
+__isl_give isl_space *isl_qpolynomial_get_domain_space(
+	__isl_keep isl_qpolynomial *qp);
+__isl_give isl_space *isl_qpolynomial_get_space(__isl_keep isl_qpolynomial *qp);
+unsigned isl_qpolynomial_dim(__isl_keep isl_qpolynomial *qp,
+	enum isl_dim_type type);
+int isl_qpolynomial_involves_dims(__isl_keep isl_qpolynomial *qp,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_val *isl_qpolynomial_get_constant_val(
+	__isl_keep isl_qpolynomial *qp);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_set_dim_name(
+	__isl_take isl_qpolynomial *qp,
+	enum isl_dim_type type, unsigned pos, const char *s);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_zero_on_domain(__isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_one_on_domain(__isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_infty_on_domain(__isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_neginfty_on_domain(__isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_nan_on_domain(__isl_take isl_space *dim);
+__isl_give isl_qpolynomial *isl_qpolynomial_val_on_domain(
+	__isl_take isl_space *space, __isl_take isl_val *val);
+__isl_give isl_qpolynomial *isl_qpolynomial_var_on_domain(__isl_take isl_space *dim,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_qpolynomial *isl_qpolynomial_copy(__isl_keep isl_qpolynomial *qp);
+__isl_null isl_qpolynomial *isl_qpolynomial_free(
+	__isl_take isl_qpolynomial *qp);
+
+int isl_qpolynomial_plain_is_equal(__isl_keep isl_qpolynomial *qp1,
+	__isl_keep isl_qpolynomial *qp2);
+int isl_qpolynomial_is_zero(__isl_keep isl_qpolynomial *qp);
+int isl_qpolynomial_is_nan(__isl_keep isl_qpolynomial *qp);
+int isl_qpolynomial_is_infty(__isl_keep isl_qpolynomial *qp);
+int isl_qpolynomial_is_neginfty(__isl_keep isl_qpolynomial *qp);
+int isl_qpolynomial_sgn(__isl_keep isl_qpolynomial *qp);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_neg(__isl_take isl_qpolynomial *qp);
+__isl_give isl_qpolynomial *isl_qpolynomial_add(__isl_take isl_qpolynomial *qp1,
+	__isl_take isl_qpolynomial *qp2);
+__isl_give isl_qpolynomial *isl_qpolynomial_sub(__isl_take isl_qpolynomial *qp1,
+	__isl_take isl_qpolynomial *qp2);
+__isl_give isl_qpolynomial *isl_qpolynomial_mul(__isl_take isl_qpolynomial *qp1,
+	__isl_take isl_qpolynomial *qp2);
+__isl_give isl_qpolynomial *isl_qpolynomial_pow(__isl_take isl_qpolynomial *qp,
+	unsigned power);
+__isl_give isl_qpolynomial *isl_qpolynomial_scale_val(
+	__isl_take isl_qpolynomial *qp, __isl_take isl_val *v);
+__isl_give isl_qpolynomial *isl_qpolynomial_scale_down_val(
+	__isl_take isl_qpolynomial *qp, __isl_take isl_val *v);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_insert_dims(
+	__isl_take isl_qpolynomial *qp, enum isl_dim_type type,
+	unsigned first, unsigned n);
+__isl_give isl_qpolynomial *isl_qpolynomial_add_dims(
+	__isl_take isl_qpolynomial *qp, enum isl_dim_type type, unsigned n);
+__isl_give isl_qpolynomial *isl_qpolynomial_move_dims(
+	__isl_take isl_qpolynomial *qp,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_qpolynomial *isl_qpolynomial_project_domain_on_params(
+	__isl_take isl_qpolynomial *qp);
+__isl_give isl_qpolynomial *isl_qpolynomial_drop_dims(
+	__isl_take isl_qpolynomial *qp,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_substitute(
+	__isl_take isl_qpolynomial *qp,
+	enum isl_dim_type type, unsigned first, unsigned n,
+	__isl_keep isl_qpolynomial **subs);
+
+int isl_qpolynomial_as_polynomial_on_domain(__isl_keep isl_qpolynomial *qp,
+	__isl_keep isl_basic_set *bset,
+	int (*fn)(__isl_take isl_basic_set *bset,
+		  __isl_take isl_qpolynomial *poly, void *user), void *user);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_homogenize(
+	__isl_take isl_qpolynomial *poly);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_align_params(
+	__isl_take isl_qpolynomial *qp, __isl_take isl_space *model);
+
+isl_ctx *isl_term_get_ctx(__isl_keep isl_term *term);
+
+__isl_give isl_term *isl_term_copy(__isl_keep isl_term *term);
+void isl_term_free(__isl_take isl_term *term);
+
+unsigned isl_term_dim(__isl_keep isl_term *term, enum isl_dim_type type);
+__isl_give isl_val *isl_term_get_coefficient_val(__isl_keep isl_term *term);
+int isl_term_get_exp(__isl_keep isl_term *term,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_aff *isl_term_get_div(__isl_keep isl_term *term, unsigned pos);
+
+int isl_qpolynomial_foreach_term(__isl_keep isl_qpolynomial *qp,
+	int (*fn)(__isl_take isl_term *term, void *user), void *user);
+
+__isl_give isl_val *isl_qpolynomial_eval(__isl_take isl_qpolynomial *qp,
+	__isl_take isl_point *pnt);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_gist_params(
+	__isl_take isl_qpolynomial *qp, __isl_take isl_set *context);
+__isl_give isl_qpolynomial *isl_qpolynomial_gist(
+	__isl_take isl_qpolynomial *qp, __isl_take isl_set *context);
+
+__isl_give isl_qpolynomial *isl_qpolynomial_from_constraint(
+	__isl_take isl_constraint *c, enum isl_dim_type type, unsigned pos);
+__isl_give isl_qpolynomial *isl_qpolynomial_from_term(__isl_take isl_term *term);
+__isl_give isl_qpolynomial *isl_qpolynomial_from_aff(__isl_take isl_aff *aff);
+__isl_give isl_basic_map *isl_basic_map_from_qpolynomial(
+	__isl_take isl_qpolynomial *qp);
+
+__isl_give isl_printer *isl_printer_print_qpolynomial(
+	__isl_take isl_printer *p, __isl_keep isl_qpolynomial *qp);
+void isl_qpolynomial_print(__isl_keep isl_qpolynomial *qp, FILE *out,
+	unsigned output_format);
+void isl_qpolynomial_dump(__isl_keep isl_qpolynomial *qp);
+
+isl_ctx *isl_pw_qpolynomial_get_ctx(__isl_keep isl_pw_qpolynomial *pwqp);
+
+int isl_pw_qpolynomial_plain_is_equal(__isl_keep isl_pw_qpolynomial *pwqp1,
+	__isl_keep isl_pw_qpolynomial *pwqp2);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_zero(__isl_take isl_space *dim);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_alloc(__isl_take isl_set *set,
+	__isl_take isl_qpolynomial *qp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_qpolynomial(
+	__isl_take isl_qpolynomial *qp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_copy(
+	__isl_keep isl_pw_qpolynomial *pwqp);
+__isl_null isl_pw_qpolynomial *isl_pw_qpolynomial_free(
+	__isl_take isl_pw_qpolynomial *pwqp);
+
+int isl_pw_qpolynomial_is_zero(__isl_keep isl_pw_qpolynomial *pwqp);
+
+__isl_give isl_space *isl_pw_qpolynomial_get_domain_space(
+	__isl_keep isl_pw_qpolynomial *pwqp);
+__isl_give isl_space *isl_pw_qpolynomial_get_space(
+	__isl_keep isl_pw_qpolynomial *pwqp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_reset_domain_space(
+	__isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_space *dim);
+unsigned isl_pw_qpolynomial_dim(__isl_keep isl_pw_qpolynomial *pwqp,
+	enum isl_dim_type type);
+int isl_pw_qpolynomial_involves_dims(__isl_keep isl_pw_qpolynomial *pwqp,
+	enum isl_dim_type type, unsigned first, unsigned n);
+int isl_pw_qpolynomial_has_equal_space(__isl_keep isl_pw_qpolynomial *pwqp1,
+	__isl_keep isl_pw_qpolynomial *pwqp2);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_set_dim_name(
+	__isl_take isl_pw_qpolynomial *pwqp,
+	enum isl_dim_type type, unsigned pos, const char *s);
+
+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_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_project_domain_on_params(
+	__isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_drop_dims(
+	__isl_take isl_pw_qpolynomial *pwqp,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_split_dims(
+	__isl_take isl_pw_qpolynomial *pwqp,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add(
+	__isl_take isl_pw_qpolynomial *pwqp1,
+	__isl_take isl_pw_qpolynomial *pwqp2);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_sub(
+	__isl_take isl_pw_qpolynomial *pwqp1,
+	__isl_take isl_pw_qpolynomial *pwqp2);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_disjoint(
+	__isl_take isl_pw_qpolynomial *pwqp1,
+	__isl_take isl_pw_qpolynomial *pwqp2);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_neg(
+	__isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_mul(
+	__isl_take isl_pw_qpolynomial *pwqp1,
+	__isl_take isl_pw_qpolynomial *pwqp2);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_scale_val(
+	__isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_val *v);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_scale_down_val(
+	__isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_val *v);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_pow(
+	__isl_take isl_pw_qpolynomial *pwqp, unsigned exponent);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_insert_dims(
+	__isl_take isl_pw_qpolynomial *pwqp, enum isl_dim_type type,
+	unsigned first, unsigned n);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_add_dims(
+	__isl_take isl_pw_qpolynomial *pwqp,
+	enum isl_dim_type type, unsigned n);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_move_dims(
+	__isl_take isl_pw_qpolynomial *pwqp,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_fix_val(
+	__isl_take isl_pw_qpolynomial *pwqp,
+	enum isl_dim_type type, unsigned n, __isl_take isl_val *v);
+
+__isl_give isl_val *isl_pw_qpolynomial_eval(
+	__isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_point *pnt);
+
+__isl_give isl_val *isl_pw_qpolynomial_max(__isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_val *isl_pw_qpolynomial_min(__isl_take isl_pw_qpolynomial *pwqp);
+
+int isl_pw_qpolynomial_foreach_piece(__isl_keep isl_pw_qpolynomial *pwqp,
+	int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp,
+		    void *user), void *user);
+int isl_pw_qpolynomial_foreach_lifted_piece(__isl_keep isl_pw_qpolynomial *pwqp,
+	int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial *qp,
+		    void *user), void *user);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_from_pw_aff(
+	__isl_take isl_pw_aff *pwaff);
+
+__isl_constructor
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_str(isl_ctx *ctx,
+		const char *str);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_read_from_file(isl_ctx *ctx,
+		FILE *input);
+__isl_give isl_printer *isl_printer_print_pw_qpolynomial(
+	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial *pwqp);
+void isl_pw_qpolynomial_print(__isl_keep isl_pw_qpolynomial *pwqp, FILE *out,
+	unsigned output_format);
+void isl_pw_qpolynomial_dump(__isl_keep isl_pw_qpolynomial *pwqp);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_coalesce(
+	__isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_gist(
+	__isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_set *context);
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_gist_params(
+	__isl_take isl_pw_qpolynomial *pwqp, __isl_take isl_set *context);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_split_periods(
+	__isl_take isl_pw_qpolynomial *pwqp, int max_periods);
+
+__isl_give isl_pw_qpolynomial *isl_basic_set_multiplicative_call(
+	__isl_take isl_basic_set *bset,
+	__isl_give isl_pw_qpolynomial *(*fn)(__isl_take isl_basic_set *bset));
+
+isl_ctx *isl_qpolynomial_fold_get_ctx(__isl_keep isl_qpolynomial_fold *fold);
+enum isl_fold isl_qpolynomial_fold_get_type(__isl_keep isl_qpolynomial_fold *fold);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_empty(enum isl_fold type,
+	__isl_take isl_space *dim);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_alloc(
+	enum isl_fold type, __isl_take isl_qpolynomial *qp);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_copy(
+	__isl_keep isl_qpolynomial_fold *fold);
+void isl_qpolynomial_fold_free(__isl_take isl_qpolynomial_fold *fold);
+
+int isl_qpolynomial_fold_is_empty(__isl_keep isl_qpolynomial_fold *fold);
+int isl_qpolynomial_fold_plain_is_equal(__isl_keep isl_qpolynomial_fold *fold1,
+	__isl_keep isl_qpolynomial_fold *fold2);
+
+__isl_give isl_space *isl_qpolynomial_fold_get_space(
+	__isl_keep isl_qpolynomial_fold *fold);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_fold(
+	__isl_take isl_qpolynomial_fold *fold1,
+	__isl_take isl_qpolynomial_fold *fold2);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale_val(
+	__isl_take isl_qpolynomial_fold *fold, __isl_take isl_val *v);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_scale_down_val(
+	__isl_take isl_qpolynomial_fold *fold, __isl_take isl_val *v);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_move_dims(
+	__isl_take isl_qpolynomial_fold *fold,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_substitute(
+	__isl_take isl_qpolynomial_fold *fold,
+	enum isl_dim_type type, unsigned first, unsigned n,
+	__isl_keep isl_qpolynomial **subs);
+
+__isl_give isl_val *isl_qpolynomial_fold_eval(
+	__isl_take isl_qpolynomial_fold *fold, __isl_take isl_point *pnt);
+
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist_params(
+	__isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *context);
+__isl_give isl_qpolynomial_fold *isl_qpolynomial_fold_gist(
+	__isl_take isl_qpolynomial_fold *fold, __isl_take isl_set *context);
+
+int isl_qpolynomial_fold_foreach_qpolynomial(
+	__isl_keep isl_qpolynomial_fold *fold,
+	int (*fn)(__isl_take isl_qpolynomial *qp, void *user), void *user);
+
+__isl_give isl_printer *isl_printer_print_qpolynomial_fold(
+	__isl_take isl_printer *p, __isl_keep isl_qpolynomial_fold *fold);
+void isl_qpolynomial_fold_print(__isl_keep isl_qpolynomial_fold *fold, FILE *out,
+	unsigned output_format);
+void isl_qpolynomial_fold_dump(__isl_keep isl_qpolynomial_fold *fold);
+
+isl_ctx *isl_pw_qpolynomial_fold_get_ctx(__isl_keep isl_pw_qpolynomial_fold *pwf);
+
+int isl_pw_qpolynomial_fold_plain_is_equal(
+	__isl_keep isl_pw_qpolynomial_fold *pwf1,
+	__isl_keep isl_pw_qpolynomial_fold *pwf2);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_from_pw_qpolynomial(
+	enum isl_fold type, __isl_take isl_pw_qpolynomial *pwqp);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_alloc(
+	enum isl_fold type,
+	__isl_take isl_set *set, __isl_take isl_qpolynomial_fold *fold);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_copy(
+	__isl_keep isl_pw_qpolynomial_fold *pwf);
+__isl_null isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_free(
+	__isl_take isl_pw_qpolynomial_fold *pwf);
+
+int isl_pw_qpolynomial_fold_is_zero(__isl_keep isl_pw_qpolynomial_fold *pwf);
+
+__isl_give isl_space *isl_pw_qpolynomial_fold_get_domain_space(
+	__isl_keep isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_space *isl_pw_qpolynomial_fold_get_space(
+	__isl_keep isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_reset_space(
+	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_space *dim);
+unsigned isl_pw_qpolynomial_fold_dim(__isl_keep isl_pw_qpolynomial_fold *pwf,
+	enum isl_dim_type type);
+int isl_pw_qpolynomial_fold_has_equal_space(
+	__isl_keep isl_pw_qpolynomial_fold *pwf1,
+	__isl_keep isl_pw_qpolynomial_fold *pwf2);
+
+size_t isl_pw_qpolynomial_fold_size(__isl_keep isl_pw_qpolynomial_fold *pwf);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_zero(
+	__isl_take isl_space *dim, enum isl_fold type);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_set_dim_name(
+	__isl_take isl_pw_qpolynomial_fold *pwf,
+	enum isl_dim_type type, unsigned pos, const char *s);
+
+int isl_pw_qpolynomial_fold_find_dim_by_name(
+	__isl_keep isl_pw_qpolynomial_fold *pwf,
+	enum isl_dim_type type, const char *name);
+
+__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_add(
+	__isl_take isl_pw_qpolynomial_fold *pwf1,
+	__isl_take isl_pw_qpolynomial_fold *pwf2);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_fold(
+	__isl_take isl_pw_qpolynomial_fold *pwf1,
+	__isl_take isl_pw_qpolynomial_fold *pwf2);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_add_disjoint(
+	__isl_take isl_pw_qpolynomial_fold *pwf1,
+	__isl_take isl_pw_qpolynomial_fold *pwf2);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_scale_val(
+	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_val *v);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_scale_down_val(
+	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_val *v);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_project_domain_on_params(
+	__isl_take isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_drop_dims(
+	__isl_take isl_pw_qpolynomial_fold *pwf,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_move_dims(
+	__isl_take isl_pw_qpolynomial_fold *pwf,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+
+__isl_give isl_val *isl_pw_qpolynomial_fold_eval(
+	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_point *pnt);
+
+int isl_pw_qpolynomial_fold_foreach_piece(
+	__isl_keep isl_pw_qpolynomial_fold *pwf,
+	int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial_fold *fold,
+		    void *user), void *user);
+int isl_pw_qpolynomial_fold_foreach_lifted_piece(
+	__isl_keep isl_pw_qpolynomial_fold *pwf,
+	int (*fn)(__isl_take isl_set *set, __isl_take isl_qpolynomial_fold *fold,
+		    void *user), void *user);
+
+__isl_give isl_printer *isl_printer_print_pw_qpolynomial_fold(
+	__isl_take isl_printer *p, __isl_keep isl_pw_qpolynomial_fold *pwf);
+void isl_pw_qpolynomial_fold_print(__isl_keep isl_pw_qpolynomial_fold *pwf,
+	FILE *out, unsigned output_format);
+void isl_pw_qpolynomial_fold_dump(__isl_keep isl_pw_qpolynomial_fold *pwf);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_coalesce(
+	__isl_take isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_gist(
+	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *context);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_gist_params(
+	__isl_take isl_pw_qpolynomial_fold *pwf, __isl_take isl_set *context);
+
+__isl_give isl_val *isl_pw_qpolynomial_fold_max(
+	__isl_take isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_val *isl_pw_qpolynomial_fold_min(
+	__isl_take isl_pw_qpolynomial_fold *pwf);
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_bound(
+	__isl_take isl_pw_qpolynomial *pwqp, enum isl_fold type, int *tight);
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_bound(
+	__isl_take isl_pw_qpolynomial_fold *pwf, int *tight);
+__isl_give isl_pw_qpolynomial_fold *isl_set_apply_pw_qpolynomial_fold(
+	__isl_take isl_set *set, __isl_take isl_pw_qpolynomial_fold *pwf,
+	int *tight);
+__isl_give isl_pw_qpolynomial_fold *isl_map_apply_pw_qpolynomial_fold(
+	__isl_take isl_map *map, __isl_take isl_pw_qpolynomial_fold *pwf,
+	int *tight);
+
+__isl_give isl_pw_qpolynomial *isl_pw_qpolynomial_to_polynomial(
+	__isl_take isl_pw_qpolynomial *pwqp, int sign);
+
+isl_ctx *isl_union_pw_qpolynomial_get_ctx(
+	__isl_keep isl_union_pw_qpolynomial *upwqp);
+
+unsigned isl_union_pw_qpolynomial_dim(
+	__isl_keep isl_union_pw_qpolynomial *upwqp, enum isl_dim_type type);
+
+int isl_union_pw_qpolynomial_plain_is_equal(
+	__isl_keep isl_union_pw_qpolynomial *upwqp1,
+	__isl_keep isl_union_pw_qpolynomial *upwqp2);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_from_pw_qpolynomial(__isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_zero(
+	__isl_take isl_space *dim);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_add_pw_qpolynomial(
+	__isl_take isl_union_pw_qpolynomial *upwqp,
+	__isl_take isl_pw_qpolynomial *pwqp);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_copy(
+	__isl_keep isl_union_pw_qpolynomial *upwqp);
+__isl_null isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_free(
+	__isl_take isl_union_pw_qpolynomial *upwqp);
+
+__isl_constructor
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_read_from_str(
+	isl_ctx *ctx, const char *str);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_neg(
+	__isl_take isl_union_pw_qpolynomial *upwqp);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_add(
+	__isl_take isl_union_pw_qpolynomial *upwqp1,
+	__isl_take isl_union_pw_qpolynomial *upwqp2);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_sub(
+	__isl_take isl_union_pw_qpolynomial *upwqp1,
+	__isl_take isl_union_pw_qpolynomial *upwqp2);
+__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);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_scale_val(
+	__isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_val *v);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_scale_down_val(
+	__isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_val *v);
+
+__isl_give isl_union_set *isl_union_pw_qpolynomial_domain(
+	__isl_take isl_union_pw_qpolynomial *upwqp);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_intersect_domain(
+	__isl_take isl_union_pw_qpolynomial *upwpq,
+	__isl_take isl_union_set *uset);
+__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_space *isl_union_pw_qpolynomial_get_space(
+	__isl_keep isl_union_pw_qpolynomial *upwqp);
+
+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_val *isl_union_pw_qpolynomial_eval(
+	__isl_take isl_union_pw_qpolynomial *upwqp, __isl_take isl_point *pnt);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_coalesce(
+	__isl_take isl_union_pw_qpolynomial *upwqp);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_gist(
+	__isl_take isl_union_pw_qpolynomial *upwqp,
+	__isl_take isl_union_set *context);
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_gist_params(
+	__isl_take isl_union_pw_qpolynomial *upwqp,
+	__isl_take isl_set *context);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_align_params(
+	__isl_take isl_union_pw_qpolynomial *upwqp,
+	__isl_take isl_space *model);
+
+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);
+__isl_give isl_pw_qpolynomial *isl_union_pw_qpolynomial_extract_pw_qpolynomial(
+	__isl_keep isl_union_pw_qpolynomial *upwqp, __isl_take isl_space *dim);
+
+__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial(
+	__isl_take isl_printer *p, __isl_keep isl_union_pw_qpolynomial *upwqp);
+
+isl_ctx *isl_union_pw_qpolynomial_fold_get_ctx(
+	__isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+unsigned isl_union_pw_qpolynomial_fold_dim(
+	__isl_keep isl_union_pw_qpolynomial_fold *upwf, enum isl_dim_type type);
+
+int isl_union_pw_qpolynomial_fold_plain_is_equal(
+	__isl_keep isl_union_pw_qpolynomial_fold *upwf1,
+	__isl_keep isl_union_pw_qpolynomial_fold *upwf2);
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_from_pw_qpolynomial_fold(__isl_take isl_pw_qpolynomial_fold *pwf);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_zero(
+	__isl_take isl_space *dim, enum isl_fold type);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
+	__isl_take isl_union_pw_qpolynomial_fold *upwqp,
+	__isl_take isl_pw_qpolynomial_fold *pwqp);
+__isl_null isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_free(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_copy(
+	__isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_fold(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf1,
+	__isl_take isl_union_pw_qpolynomial_fold *upwf2);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_add_union_pw_qpolynomial(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf,
+	__isl_take isl_union_pw_qpolynomial *upwqp);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_scale_val(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf, __isl_take isl_val *v);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_scale_down_val(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf, __isl_take isl_val *v);
+
+__isl_give isl_union_set *isl_union_pw_qpolynomial_fold_domain(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_intersect_domain(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf,
+	__isl_take isl_union_set *uset);
+__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);
+
+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);
+
+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_val *isl_union_pw_qpolynomial_fold_eval(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf,
+	__isl_take isl_point *pnt);
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_coalesce(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_gist(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf,
+	__isl_take isl_union_set *context);
+__isl_give isl_union_pw_qpolynomial_fold *
+isl_union_pw_qpolynomial_fold_gist_params(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf,
+	__isl_take isl_set *context);
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_align_params(
+	__isl_take isl_union_pw_qpolynomial_fold *upwf,
+	__isl_take isl_space *model);
+
+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,
+		    void *user), void *user);
+__isl_give isl_pw_qpolynomial_fold *isl_union_pw_qpolynomial_fold_extract_pw_qpolynomial_fold(
+	__isl_keep isl_union_pw_qpolynomial_fold *upwf, __isl_take isl_space *dim);
+
+__isl_give isl_printer *isl_printer_print_union_pw_qpolynomial_fold(
+	__isl_take isl_printer *p,
+	__isl_keep isl_union_pw_qpolynomial_fold *upwf);
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_bound(
+	__isl_take isl_union_pw_qpolynomial *upwqp,
+	enum isl_fold type, int *tight);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_set_apply_union_pw_qpolynomial_fold(
+	__isl_take isl_union_set *uset,
+	__isl_take isl_union_pw_qpolynomial_fold *upwf, int *tight);
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_map_apply_union_pw_qpolynomial_fold(
+	__isl_take isl_union_map *umap,
+	__isl_take isl_union_pw_qpolynomial_fold *upwf, int *tight);
+
+__isl_give isl_union_pw_qpolynomial *isl_union_pw_qpolynomial_to_polynomial(
+	__isl_take isl_union_pw_qpolynomial *upwqp, int sign);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/polynomial_type.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/polynomial_type.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/polynomial_type.h (added)
+++ polly/trunk/lib/External/isl/include/isl/polynomial_type.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,31 @@
+#ifndef ISL_POLYNOMIAL_TYPE_H
+#define ISL_POLYNOMIAL_TYPE_H
+
+struct isl_qpolynomial;
+typedef struct isl_qpolynomial isl_qpolynomial;
+
+struct isl_term;
+typedef struct isl_term isl_term;
+
+struct __isl_export isl_pw_qpolynomial;
+typedef struct isl_pw_qpolynomial isl_pw_qpolynomial;
+
+enum isl_fold {
+	isl_fold_min,
+	isl_fold_max,
+	isl_fold_list
+};
+
+struct isl_qpolynomial_fold;
+typedef struct isl_qpolynomial_fold isl_qpolynomial_fold;
+
+struct isl_pw_qpolynomial_fold;
+typedef struct isl_pw_qpolynomial_fold isl_pw_qpolynomial_fold;
+
+struct __isl_export isl_union_pw_qpolynomial;
+typedef struct isl_union_pw_qpolynomial isl_union_pw_qpolynomial;
+
+struct isl_union_pw_qpolynomial_fold;
+typedef struct isl_union_pw_qpolynomial_fold isl_union_pw_qpolynomial_fold;
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/printer.h (added)
+++ polly/trunk/lib/External/isl/include/isl/printer.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,62 @@
+#ifndef ISL_PRINTER_H
+#define ISL_PRINTER_H
+
+#include <stdio.h>
+#include <isl/ctx.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_printer;
+typedef struct isl_printer isl_printer;
+
+__isl_give isl_printer *isl_printer_to_file(isl_ctx *ctx, FILE *file);
+__isl_give isl_printer *isl_printer_to_str(isl_ctx *ctx);
+__isl_null isl_printer *isl_printer_free(__isl_take isl_printer *printer);
+
+isl_ctx *isl_printer_get_ctx(__isl_keep isl_printer *printer);
+FILE *isl_printer_get_file(__isl_keep isl_printer *printer);
+
+__isl_give char *isl_printer_get_str(__isl_keep isl_printer *printer);
+
+__isl_give isl_printer *isl_printer_set_indent(__isl_take isl_printer *p,
+	int indent);
+__isl_give isl_printer *isl_printer_indent(__isl_take isl_printer *p,
+	int indent);
+
+#define ISL_FORMAT_ISL			0
+#define ISL_FORMAT_POLYLIB		1
+#define ISL_FORMAT_POLYLIB_CONSTRAINTS	2
+#define ISL_FORMAT_OMEGA		3
+#define ISL_FORMAT_C			4
+#define ISL_FORMAT_LATEX		5
+#define ISL_FORMAT_EXT_POLYLIB		6
+__isl_give isl_printer *isl_printer_set_output_format(__isl_take isl_printer *p,
+	int output_format);
+int isl_printer_get_output_format(__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,
+	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_isl_int_width(__isl_take isl_printer *p,
+	int width);
+
+__isl_give isl_printer *isl_printer_start_line(__isl_take isl_printer *p);
+__isl_give isl_printer *isl_printer_end_line(__isl_take isl_printer *p);
+__isl_give isl_printer *isl_printer_print_double(__isl_take isl_printer *p,
+	double d);
+__isl_give isl_printer *isl_printer_print_int(__isl_take isl_printer *p, int i);
+__isl_give isl_printer *isl_printer_print_str(__isl_take isl_printer *p,
+	const char *s);
+
+__isl_give isl_printer *isl_printer_flush(__isl_take isl_printer *p);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/schedule.h (added)
+++ polly/trunk/lib/External/isl/include/isl/schedule.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,93 @@
+#ifndef ISL_SCHEDULE_H
+#define ISL_SCHEDULE_H
+
+#include <isl/union_set_type.h>
+#include <isl/union_map_type.h>
+#include <isl/band.h>
+#include <isl/list.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+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);
+
+int isl_options_set_schedule_max_constant_term(isl_ctx *ctx, int val);
+int isl_options_get_schedule_max_constant_term(isl_ctx *ctx);
+
+int isl_options_set_schedule_maximize_band_depth(isl_ctx *ctx, int val);
+int isl_options_get_schedule_maximize_band_depth(isl_ctx *ctx);
+
+int isl_options_set_schedule_outer_coincidence(isl_ctx *ctx, int val);
+int isl_options_get_schedule_outer_coincidence(isl_ctx *ctx);
+
+int isl_options_set_schedule_split_scaled(isl_ctx *ctx, int val);
+int isl_options_get_schedule_split_scaled(isl_ctx *ctx);
+
+int isl_options_set_schedule_separate_components(isl_ctx *ctx, int val);
+int isl_options_get_schedule_separate_components(isl_ctx *ctx);
+
+#define		ISL_SCHEDULE_FUSE_MAX			0
+#define		ISL_SCHEDULE_FUSE_MIN			1
+int isl_options_set_schedule_fuse(isl_ctx *ctx, int val);
+int isl_options_get_schedule_fuse(isl_ctx *ctx);
+
+__isl_give isl_schedule_constraints *isl_schedule_constraints_copy(
+	__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_validity(
+	__isl_take isl_schedule_constraints *sc,
+	__isl_take isl_union_map *validity);
+__isl_give isl_schedule_constraints *isl_schedule_constraints_set_coincidence(
+	__isl_take isl_schedule_constraints *sc,
+	__isl_take isl_union_map *coincidence);
+__isl_give isl_schedule_constraints *isl_schedule_constraints_set_proximity(
+	__isl_take isl_schedule_constraints *sc,
+	__isl_take isl_union_map *proximity);
+__isl_give isl_schedule_constraints *
+isl_schedule_constraints_set_conditional_validity(
+	__isl_take isl_schedule_constraints *sc,
+	__isl_take isl_union_map *condition,
+	__isl_take isl_union_map *validity);
+__isl_null isl_schedule_constraints *isl_schedule_constraints_free(
+	__isl_take isl_schedule_constraints *sc);
+
+isl_ctx *isl_schedule_constraints_get_ctx(
+	__isl_keep isl_schedule_constraints *sc);
+
+void isl_schedule_constraints_dump(__isl_keep isl_schedule_constraints *sc);
+
+__isl_give isl_schedule *isl_schedule_constraints_compute_schedule(
+	__isl_take isl_schedule_constraints *sc);
+
+__isl_give isl_schedule *isl_union_set_compute_schedule(
+	__isl_take isl_union_set *domain,
+	__isl_take isl_union_map *validity,
+	__isl_take isl_union_map *proximity);
+__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_band_list *isl_schedule_get_band_forest(
+	__isl_keep isl_schedule *schedule);
+
+__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);
+
+int isl_schedule_foreach_band(__isl_keep isl_schedule *sched,
+	int (*fn)(__isl_keep isl_band *band, void *user), void *user);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/set.h (added)
+++ polly/trunk/lib/External/isl/include/isl/set.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,540 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_SET_H
+#define ISL_SET_H
+
+#include <isl/map_type.h>
+#include <isl/aff_type.h>
+#include <isl/list.h>
+#include <isl/mat.h>
+#include <isl/point.h>
+#include <isl/local_space.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+unsigned isl_basic_set_n_dim(__isl_keep isl_basic_set *bset);
+unsigned isl_basic_set_n_param(__isl_keep isl_basic_set *bset);
+unsigned isl_basic_set_total_dim(const struct isl_basic_set *bset);
+unsigned isl_basic_set_dim(__isl_keep isl_basic_set *bset,
+				enum isl_dim_type type);
+
+unsigned isl_set_n_dim(__isl_keep isl_set *set);
+unsigned isl_set_n_param(__isl_keep isl_set *set);
+unsigned isl_set_dim(__isl_keep isl_set *set, enum isl_dim_type type);
+
+isl_ctx *isl_basic_set_get_ctx(__isl_keep isl_basic_set *bset);
+isl_ctx *isl_set_get_ctx(__isl_keep isl_set *set);
+__isl_give isl_space *isl_basic_set_get_space(__isl_keep isl_basic_set *bset);
+__isl_give isl_space *isl_set_get_space(__isl_keep isl_set *set);
+__isl_give isl_set *isl_set_reset_space(__isl_take isl_set *set,
+	__isl_take isl_space *dim);
+
+__isl_give isl_aff *isl_basic_set_get_div(__isl_keep isl_basic_set *bset,
+	int pos);
+
+__isl_give isl_local_space *isl_basic_set_get_local_space(
+	__isl_keep isl_basic_set *bset);
+
+const char *isl_basic_set_get_tuple_name(__isl_keep isl_basic_set *bset);
+int isl_set_has_tuple_name(__isl_keep isl_set *set);
+const char *isl_set_get_tuple_name(__isl_keep isl_set *set);
+__isl_give isl_basic_set *isl_basic_set_set_tuple_name(
+	__isl_take isl_basic_set *set, const char *s);
+__isl_give isl_set *isl_set_set_tuple_name(__isl_take isl_set *set,
+	const char *s);
+const char *isl_basic_set_get_dim_name(__isl_keep isl_basic_set *bset,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_basic_set *isl_basic_set_set_dim_name(
+	__isl_take isl_basic_set *bset,
+	enum isl_dim_type type, unsigned pos, const char *s);
+int isl_set_has_dim_name(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos);
+const char *isl_set_get_dim_name(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_set *isl_set_set_dim_name(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned pos, const char *s);
+
+__isl_give isl_id *isl_basic_set_get_dim_id(__isl_keep isl_basic_set *bset,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_basic_set *isl_basic_set_set_tuple_id(
+	__isl_take isl_basic_set *bset, __isl_take isl_id *id);
+__isl_give isl_set *isl_set_set_dim_id(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+int isl_set_has_dim_id(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_set_get_dim_id(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_set *isl_set_set_tuple_id(__isl_take isl_set *set,
+	__isl_take isl_id *id);
+__isl_give isl_set *isl_set_reset_tuple_id(__isl_take isl_set *set);
+int isl_set_has_tuple_id(__isl_keep isl_set *set);
+__isl_give isl_id *isl_set_get_tuple_id(__isl_keep isl_set *set);
+__isl_give isl_set *isl_set_reset_user(__isl_take isl_set *set);
+
+int isl_set_find_dim_by_id(__isl_keep isl_set *set, enum isl_dim_type type,
+	__isl_keep isl_id *id);
+int isl_set_find_dim_by_name(__isl_keep isl_set *set, enum isl_dim_type type,
+	const char *name);
+
+int isl_basic_set_is_rational(__isl_keep isl_basic_set *bset);
+
+struct isl_basic_set *isl_basic_set_alloc(struct isl_ctx *ctx,
+		unsigned nparam, unsigned dim, unsigned extra,
+		unsigned n_eq, unsigned n_ineq);
+struct isl_basic_set *isl_basic_set_extend(struct isl_basic_set *base,
+		unsigned nparam, unsigned dim, unsigned extra,
+		unsigned n_eq, unsigned n_ineq);
+struct isl_basic_set *isl_basic_set_extend_constraints(
+		struct isl_basic_set *base, unsigned n_eq, unsigned n_ineq);
+struct isl_basic_set *isl_basic_set_finalize(struct isl_basic_set *bset);
+__isl_null isl_basic_set *isl_basic_set_free(__isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_copy(__isl_keep isl_basic_set *bset);
+struct isl_basic_set *isl_basic_set_dup(struct isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_empty(__isl_take isl_space *dim);
+struct isl_basic_set *isl_basic_set_empty_like(struct isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_universe(__isl_take isl_space *dim);
+__isl_give isl_basic_set *isl_basic_set_nat_universe(__isl_take isl_space *dim);
+struct isl_basic_set *isl_basic_set_universe_like(struct isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_universe_like_set(
+	__isl_keep isl_set *model);
+__isl_give isl_basic_set *isl_basic_set_positive_orthant(
+	__isl_take isl_space *space);
+void isl_basic_set_print_internal(__isl_keep isl_basic_set *bset,
+				FILE *out, int indent);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_intersect(
+		__isl_take isl_basic_set *bset1,
+		__isl_take isl_basic_set *bset2);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_intersect_params(
+	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_apply(
+		__isl_take isl_basic_set *bset,
+		__isl_take isl_basic_map *bmap);
+__isl_give isl_basic_set *isl_basic_set_preimage_multi_aff(
+	__isl_take isl_basic_set *bset, __isl_take isl_multi_aff *ma);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_affine_hull(
+		__isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_remove_dims(
+	__isl_take isl_basic_set *bset,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_sample(__isl_take isl_basic_set *bset);
+struct isl_basic_set *isl_basic_set_simplify(struct isl_basic_set *bset);
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_detect_equalities(
+						__isl_take isl_basic_set *bset);
+__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);
+__isl_give isl_basic_set *isl_basic_set_list_intersect(
+	__isl_take struct isl_basic_set_list *list);
+__isl_give isl_basic_set *isl_basic_set_list_product(
+	__isl_take struct isl_basic_set_list *list);
+
+__isl_give isl_basic_set *isl_basic_set_read_from_file(isl_ctx *ctx,
+	FILE *input);
+__isl_constructor
+__isl_give isl_basic_set *isl_basic_set_read_from_str(isl_ctx *ctx,
+	const char *str);
+__isl_give isl_set *isl_set_read_from_file(isl_ctx *ctx, FILE *input);
+__isl_constructor
+__isl_give isl_set *isl_set_read_from_str(isl_ctx *ctx, const char *str);
+void isl_basic_set_dump(__isl_keep isl_basic_set *bset);
+void isl_set_dump(__isl_keep isl_set *set);
+__isl_give isl_printer *isl_printer_print_basic_set(
+	__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,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v);
+__isl_give isl_set *isl_set_fix_si(__isl_take isl_set *set,
+		enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_set *isl_set_lower_bound_si(__isl_take isl_set *set,
+		enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_set *isl_set_lower_bound_val(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value);
+__isl_give isl_set *isl_set_upper_bound_si(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned pos, int value);
+__isl_give isl_set *isl_set_upper_bound_val(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_val *value);
+
+__isl_give isl_set *isl_set_equate(__isl_take isl_set *set,
+	enum isl_dim_type type1, int pos1, enum isl_dim_type type2, int pos2);
+
+struct isl_basic_set *isl_basic_set_from_underlying_set(
+	struct isl_basic_set *bset, struct isl_basic_set *like);
+struct isl_set *isl_set_from_underlying_set(
+	struct isl_set *set, struct isl_basic_set *like);
+struct isl_set *isl_set_to_underlying_set(struct isl_set *set);
+
+__isl_export
+int isl_basic_set_is_equal(
+		struct isl_basic_set *bset1, struct isl_basic_set *bset2);
+int isl_basic_set_is_disjoint(__isl_keep isl_basic_set *bset1,
+	__isl_keep isl_basic_set *bset2);
+
+__isl_give isl_set *isl_basic_set_partial_lexmin(
+		__isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
+		__isl_give isl_set **empty);
+__isl_give isl_set *isl_basic_set_partial_lexmax(
+		__isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
+		__isl_give isl_set **empty);
+__isl_give isl_set *isl_set_partial_lexmin(
+		__isl_take isl_set *set, __isl_take isl_set *dom,
+		__isl_give isl_set **empty);
+__isl_give isl_set *isl_set_partial_lexmax(
+		__isl_take isl_set *set, __isl_take isl_set *dom,
+		__isl_give isl_set **empty);
+__isl_export
+__isl_give isl_set *isl_basic_set_lexmin(__isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_set *isl_basic_set_lexmax(__isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_set *isl_set_lexmin(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_set *isl_set_lexmax(__isl_take isl_set *set);
+__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmin_pw_multi_aff(
+	__isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty);
+__isl_give isl_pw_multi_aff *isl_basic_set_partial_lexmax_pw_multi_aff(
+	__isl_take isl_basic_set *bset, __isl_take isl_basic_set *dom,
+	__isl_give isl_set **empty);
+__isl_give isl_pw_multi_aff *isl_set_lexmin_pw_multi_aff(
+	__isl_take isl_set *set);
+__isl_give isl_pw_multi_aff *isl_set_lexmax_pw_multi_aff(
+	__isl_take isl_set *set);
+
+__isl_export
+__isl_give isl_set *isl_basic_set_union(
+		__isl_take isl_basic_set *bset1,
+		__isl_take isl_basic_set *bset2);
+
+int isl_basic_set_compare_at(struct isl_basic_set *bset1,
+	struct isl_basic_set *bset2, int pos);
+int isl_set_follows_at(__isl_keep isl_set *set1,
+	__isl_keep isl_set *set2, int pos);
+
+__isl_give isl_basic_set *isl_basic_set_params(__isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_from_params(
+	__isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_set_params(__isl_take isl_set *set);
+__isl_give isl_set *isl_set_from_params(__isl_take isl_set *set);
+
+int isl_basic_set_dims_get_sign(__isl_keep isl_basic_set *bset,
+	enum isl_dim_type type, unsigned pos, unsigned n, int *signs);
+
+int isl_basic_set_is_universe(__isl_keep isl_basic_set *bset);
+int isl_basic_set_plain_is_empty(__isl_keep isl_basic_set *bset);
+ISL_DEPRECATED
+int isl_basic_set_fast_is_empty(__isl_keep isl_basic_set *bset);
+__isl_export
+int isl_basic_set_is_empty(__isl_keep isl_basic_set *bset);
+int isl_basic_set_is_bounded(__isl_keep isl_basic_set *bset);
+__isl_export
+int isl_basic_set_is_subset(__isl_keep isl_basic_set *bset1,
+	__isl_keep isl_basic_set *bset2);
+int isl_basic_set_plain_is_equal(__isl_keep isl_basic_set *bset1,
+	__isl_keep isl_basic_set *bset2);
+
+struct isl_set *isl_set_alloc(struct isl_ctx *ctx,
+		unsigned nparam, unsigned dim, int n, unsigned flags);
+struct isl_set *isl_set_extend(struct isl_set *base,
+		unsigned nparam, unsigned dim);
+__isl_give isl_set *isl_set_empty(__isl_take isl_space *dim);
+struct isl_set *isl_set_empty_like(struct isl_set *set);
+__isl_give isl_set *isl_set_universe(__isl_take isl_space *dim);
+__isl_give isl_set *isl_set_nat_universe(__isl_take isl_space *dim);
+__isl_give isl_set *isl_set_universe_like(__isl_keep isl_set *model);
+__isl_give isl_set *isl_set_add_basic_set(__isl_take isl_set *set,
+						__isl_take isl_basic_set *bset);
+struct isl_set *isl_set_finalize(struct isl_set *set);
+__isl_give isl_set *isl_set_copy(__isl_keep isl_set *set);
+__isl_null isl_set *isl_set_free(__isl_take isl_set *set);
+struct isl_set *isl_set_dup(struct isl_set *set);
+__isl_constructor
+__isl_give isl_set *isl_set_from_basic_set(__isl_take isl_basic_set *bset);
+__isl_export
+__isl_give isl_basic_set *isl_set_sample(__isl_take isl_set *set);
+__isl_give isl_point *isl_basic_set_sample_point(__isl_take isl_basic_set *bset);
+__isl_give isl_point *isl_set_sample_point(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_set *isl_set_detect_equalities(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_basic_set *isl_set_affine_hull(__isl_take isl_set *set);
+__isl_give isl_basic_set *isl_set_convex_hull(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_basic_set *isl_set_polyhedral_hull(__isl_take isl_set *set);
+__isl_give isl_basic_set *isl_set_simple_hull(__isl_take isl_set *set);
+__isl_give isl_basic_set *isl_set_unshifted_simple_hull(
+	__isl_take isl_set *set);
+__isl_give isl_basic_set *isl_set_unshifted_simple_hull_from_set_list(
+	__isl_take isl_set *set, __isl_take isl_set_list *list);
+struct isl_basic_set *isl_set_bounded_simple_hull(struct isl_set *set);
+__isl_give isl_set *isl_set_recession_cone(__isl_take isl_set *set);
+
+struct isl_set *isl_set_union_disjoint(
+			struct isl_set *set1, struct isl_set *set2);
+__isl_export
+__isl_give isl_set *isl_set_union(
+		__isl_take isl_set *set1,
+		__isl_take isl_set *set2);
+__isl_give isl_set *isl_set_product(__isl_take isl_set *set1,
+	__isl_take isl_set *set2);
+__isl_give isl_basic_set *isl_basic_set_flat_product(
+	__isl_take isl_basic_set *bset1, __isl_take isl_basic_set *bset2);
+__isl_give isl_set *isl_set_flat_product(__isl_take isl_set *set1,
+	__isl_take isl_set *set2);
+__isl_export
+__isl_give isl_set *isl_set_intersect(
+		__isl_take isl_set *set1,
+		__isl_take isl_set *set2);
+__isl_export
+__isl_give isl_set *isl_set_intersect_params(__isl_take isl_set *set,
+		__isl_take isl_set *params);
+__isl_export
+__isl_give isl_set *isl_set_subtract(
+		__isl_take isl_set *set1,
+		__isl_take isl_set *set2);
+__isl_export
+__isl_give isl_set *isl_set_complement(__isl_take isl_set *set);
+__isl_export
+__isl_give isl_set *isl_set_apply(
+		__isl_take isl_set *set,
+		__isl_take isl_map *map);
+__isl_give isl_set *isl_set_preimage_multi_aff(__isl_take isl_set *set,
+	__isl_take isl_multi_aff *ma);
+__isl_give isl_set *isl_set_preimage_pw_multi_aff(__isl_take isl_set *set,
+	__isl_take isl_pw_multi_aff *pma);
+__isl_give isl_set *isl_set_preimage_multi_pw_aff(__isl_take isl_set *set,
+	__isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_set *isl_set_fix_val(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_val *v);
+struct isl_set *isl_set_fix_dim_si(struct isl_set *set,
+		unsigned dim, int value);
+__isl_give isl_basic_set *isl_basic_set_insert_dims(
+	__isl_take isl_basic_set *bset,
+	enum isl_dim_type type, unsigned pos, unsigned n);
+__isl_give isl_set *isl_set_insert_dims(__isl_take isl_set *set,
+		enum isl_dim_type type, unsigned pos, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_add_dims(__isl_take isl_basic_set *bset,
+		enum isl_dim_type type, unsigned n);
+/* deprecated */
+__isl_give isl_basic_set *isl_basic_set_add(__isl_take isl_basic_set *bset,
+	enum isl_dim_type type, unsigned n);
+__isl_give isl_set *isl_set_add_dims(__isl_take isl_set *set,
+		enum isl_dim_type type, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_move_dims(__isl_take isl_basic_set *bset,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_set *isl_set_move_dims(__isl_take isl_set *set,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_project_out(
+		__isl_take isl_basic_set *bset,
+		enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_set *isl_set_project_out(__isl_take isl_set *set,
+		enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_remove_divs(
+	__isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_basic_set_eliminate(
+	__isl_take isl_basic_set *bset,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_set *isl_set_eliminate(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned first, unsigned n);
+struct isl_set *isl_set_eliminate_dims(struct isl_set *set,
+		unsigned first, unsigned n);
+__isl_give isl_set *isl_set_remove_dims(__isl_take isl_set *bset,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_remove_divs_involving_dims(
+	__isl_take isl_basic_set *bset,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_set *isl_set_remove_divs_involving_dims(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_remove_unknown_divs(
+	__isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_set_remove_unknown_divs(__isl_take isl_set *set);
+__isl_give isl_set *isl_set_remove_divs(__isl_take isl_set *set);
+__isl_give isl_set *isl_set_split_dims(__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
+	__isl_take isl_basic_set *bset,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
+	__isl_take isl_basic_set *bset,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_set *isl_set_drop_constraints_involving_dims(
+	__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+int isl_basic_set_involves_dims(__isl_keep isl_basic_set *bset,
+	enum isl_dim_type type, unsigned first, unsigned n);
+int isl_set_involves_dims(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+void isl_set_print_internal(__isl_keep isl_set *set, FILE *out, int indent);
+int isl_set_plain_is_empty(__isl_keep isl_set *set);
+ISL_DEPRECATED
+int isl_set_fast_is_empty(__isl_keep isl_set *set);
+int isl_set_plain_is_universe(__isl_keep isl_set *set);
+ISL_DEPRECATED
+int isl_set_fast_is_universe(__isl_keep isl_set *set);
+int isl_set_is_params(__isl_keep isl_set *set);
+__isl_export
+int isl_set_is_empty(__isl_keep isl_set *set);
+int isl_set_is_bounded(__isl_keep isl_set *set);
+__isl_export
+int isl_set_is_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+__isl_export
+int isl_set_is_strict_subset(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+__isl_export
+int isl_set_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+__isl_export
+int isl_set_is_disjoint(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+int isl_set_is_singleton(__isl_keep isl_set *set);
+int isl_set_is_box(__isl_keep isl_set *set);
+int isl_set_has_equal_space(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+
+__isl_give isl_set *isl_set_sum(__isl_take isl_set *set1,
+	__isl_take isl_set *set2);
+__isl_give isl_basic_set *isl_basic_set_neg(__isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_set_neg(__isl_take isl_set *set);
+
+__isl_give isl_set *isl_set_make_disjoint(__isl_take isl_set *set);
+struct isl_set *isl_basic_set_compute_divs(struct isl_basic_set *bset);
+__isl_give isl_set *isl_set_compute_divs(__isl_take isl_set *set);
+__isl_give isl_set *isl_set_align_divs(__isl_take isl_set *set);
+
+struct isl_basic_set *isl_set_copy_basic_set(struct isl_set *set);
+struct isl_set *isl_set_drop_basic_set(struct isl_set *set,
+						struct isl_basic_set *bset);
+
+__isl_give isl_val *isl_set_plain_get_val_if_fixed(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos);
+int isl_set_dim_is_bounded(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos);
+int isl_set_dim_has_lower_bound(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos);
+int isl_set_dim_has_upper_bound(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos);
+int isl_set_dim_has_any_lower_bound(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos);
+int isl_set_dim_has_any_upper_bound(__isl_keep isl_set *set,
+	enum isl_dim_type type, unsigned pos);
+
+__isl_export
+__isl_give isl_basic_set *isl_basic_set_gist(__isl_take isl_basic_set *bset,
+					    __isl_take isl_basic_set *context);
+__isl_give isl_set *isl_set_gist_basic_set(__isl_take isl_set *set,
+	__isl_take isl_basic_set *context);
+__isl_export
+__isl_give isl_set *isl_set_gist(__isl_take isl_set *set,
+	__isl_take isl_set *context);
+__isl_give isl_set *isl_set_gist_params(__isl_take isl_set *set,
+	__isl_take isl_set *context);
+int isl_set_dim_residue_class_val(__isl_keep isl_set *set,
+	int pos, __isl_give isl_val **modulo, __isl_give isl_val **residue);
+
+__isl_export
+__isl_give isl_set *isl_set_coalesce(__isl_take isl_set *set);
+
+int isl_set_plain_cmp(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+int isl_set_plain_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+ISL_DEPRECATED
+int isl_set_fast_is_equal(__isl_keep isl_set *set1, __isl_keep isl_set *set2);
+int isl_set_plain_is_disjoint(__isl_keep isl_set *set1,
+	__isl_keep isl_set *set2);
+ISL_DEPRECATED
+int isl_set_fast_is_disjoint(__isl_keep isl_set *set1,
+	__isl_keep isl_set *set2);
+
+uint32_t isl_set_get_hash(struct isl_set *set);
+
+int isl_set_dim_is_unique(struct isl_set *set, unsigned dim);
+
+int isl_set_n_basic_set(__isl_keep isl_set *set);
+__isl_export
+int isl_set_foreach_basic_set(__isl_keep isl_set *set,
+	int (*fn)(__isl_take isl_basic_set *bset, void *user), void *user);
+
+int isl_set_foreach_point(__isl_keep isl_set *set,
+	int (*fn)(__isl_take isl_point *pnt, void *user), void *user);
+__isl_give isl_val *isl_set_count_val(__isl_keep isl_set *set);
+
+__isl_give isl_basic_set *isl_basic_set_from_point(__isl_take isl_point *pnt);
+__isl_give isl_set *isl_set_from_point(__isl_take isl_point *pnt);
+__isl_give isl_basic_set *isl_basic_set_box_from_points(
+	__isl_take isl_point *pnt1, __isl_take isl_point *pnt2);
+__isl_give isl_set *isl_set_box_from_points(__isl_take isl_point *pnt1,
+	__isl_take isl_point *pnt2);
+
+__isl_give isl_basic_set *isl_basic_set_lift(__isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_set_lift(__isl_take isl_set *set);
+
+__isl_give isl_map *isl_set_lex_le_set(__isl_take isl_set *set1,
+	__isl_take isl_set *set2);
+__isl_give isl_map *isl_set_lex_lt_set(__isl_take isl_set *set1,
+	__isl_take isl_set *set2);
+__isl_give isl_map *isl_set_lex_ge_set(__isl_take isl_set *set1,
+	__isl_take isl_set *set2);
+__isl_give isl_map *isl_set_lex_gt_set(__isl_take isl_set *set1,
+	__isl_take isl_set *set2);
+
+int isl_set_size(__isl_keep isl_set *set);
+
+__isl_give isl_basic_set *isl_basic_set_align_params(
+	__isl_take isl_basic_set *bset, __isl_take isl_space *model);
+__isl_give isl_set *isl_set_align_params(__isl_take isl_set *set,
+	__isl_take isl_space *model);
+
+__isl_give isl_mat *isl_basic_set_equalities_matrix(
+	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
+	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4);
+__isl_give isl_mat *isl_basic_set_inequalities_matrix(
+	__isl_keep isl_basic_set *bset, enum isl_dim_type c1,
+	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4);
+__isl_give isl_basic_set *isl_basic_set_from_constraint_matrices(
+	__isl_take isl_space *dim,
+	__isl_take isl_mat *eq, __isl_take isl_mat *ineq, enum isl_dim_type c1,
+	enum isl_dim_type c2, enum isl_dim_type c3, enum isl_dim_type c4);
+
+__isl_give isl_mat *isl_basic_set_reduced_basis(__isl_keep isl_basic_set *bset);
+
+__isl_give isl_basic_set *isl_basic_set_coefficients(
+	__isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_set_coefficients(__isl_take isl_set *set);
+__isl_give isl_basic_set *isl_basic_set_solutions(
+	__isl_take isl_basic_set *bset);
+__isl_give isl_basic_set *isl_set_solutions(__isl_take isl_set *set);
+
+__isl_give isl_pw_aff *isl_set_dim_max(__isl_take isl_set *set, int pos);
+__isl_give isl_pw_aff *isl_set_dim_min(__isl_take isl_set *set, int pos);
+
+__isl_give char *isl_set_to_str(__isl_keep isl_set *set);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/set_type.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/set_type.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/set_type.h (added)
+++ polly/trunk/lib/External/isl/include/isl/set_type.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6 @@
+#ifndef ISL_SET_TYPE_H
+#define ISL_SET_TYPE_H
+
+#include <isl/map_type.h>
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/space.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/space.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/space.h (added)
+++ polly/trunk/lib/External/isl/include/isl/space.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_SPACE_H
+#define ISL_SPACE_H
+
+#include <isl/ctx.h>
+#include <isl/id.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_space;
+typedef struct isl_space isl_space;
+
+enum isl_dim_type {
+	isl_dim_cst,
+	isl_dim_param,
+	isl_dim_in,
+	isl_dim_out,
+	isl_dim_set = isl_dim_out,
+	isl_dim_div,
+	isl_dim_all
+};
+
+isl_ctx *isl_space_get_ctx(__isl_keep isl_space *dim);
+__isl_give isl_space *isl_space_alloc(isl_ctx *ctx,
+			unsigned nparam, unsigned n_in, unsigned n_out);
+__isl_give isl_space *isl_space_set_alloc(isl_ctx *ctx,
+			unsigned nparam, unsigned dim);
+__isl_give isl_space *isl_space_params_alloc(isl_ctx *ctx, unsigned nparam);
+__isl_give isl_space *isl_space_copy(__isl_keep isl_space *dim);
+__isl_null isl_space *isl_space_free(__isl_take isl_space *space);
+
+int isl_space_is_params(__isl_keep isl_space *space);
+int isl_space_is_set(__isl_keep isl_space *space);
+int isl_space_is_map(__isl_keep isl_space *space);
+
+__isl_give isl_space *isl_space_set_tuple_name(__isl_take isl_space *dim,
+	enum isl_dim_type type, const char *s);
+int isl_space_has_tuple_name(__isl_keep isl_space *space,
+	enum isl_dim_type type);
+const char *isl_space_get_tuple_name(__isl_keep isl_space *dim,
+				 enum isl_dim_type type);
+__isl_give isl_space *isl_space_set_tuple_id(__isl_take isl_space *dim,
+	enum isl_dim_type type, __isl_take isl_id *id);
+__isl_give isl_space *isl_space_reset_tuple_id(__isl_take isl_space *dim,
+	enum isl_dim_type type);
+int isl_space_has_tuple_id(__isl_keep isl_space *dim, enum isl_dim_type type);
+__isl_give isl_id *isl_space_get_tuple_id(__isl_keep isl_space *dim,
+	enum isl_dim_type type);
+__isl_give isl_space *isl_space_reset_user(__isl_take isl_space *space);
+
+__isl_give isl_space *isl_space_set_dim_id(__isl_take isl_space *dim,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id);
+int isl_space_has_dim_id(__isl_keep isl_space *dim,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_id *isl_space_get_dim_id(__isl_keep isl_space *dim,
+	enum isl_dim_type type, unsigned pos);
+
+int isl_space_find_dim_by_id(__isl_keep isl_space *dim, enum isl_dim_type type,
+	__isl_keep isl_id *id);
+int isl_space_find_dim_by_name(__isl_keep isl_space *space,
+	enum isl_dim_type type, const char *name);
+
+int isl_space_has_dim_name(__isl_keep isl_space *space,
+	enum isl_dim_type type, unsigned pos);
+__isl_give isl_space *isl_space_set_dim_name(__isl_take isl_space *dim,
+				 enum isl_dim_type type, unsigned pos,
+				 __isl_keep const char *name);
+__isl_keep const char *isl_space_get_dim_name(__isl_keep isl_space *dim,
+				 enum isl_dim_type type, unsigned pos);
+
+__isl_give isl_space *isl_space_extend(__isl_take isl_space *dim,
+			unsigned nparam, unsigned n_in, unsigned n_out);
+__isl_give isl_space *isl_space_add_dims(__isl_take isl_space *dim, enum isl_dim_type type,
+		unsigned n);
+__isl_give isl_space *isl_space_move_dims(__isl_take isl_space *dim,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n);
+__isl_give isl_space *isl_space_insert_dims(__isl_take isl_space *dim,
+	enum isl_dim_type type, unsigned pos, unsigned n);
+__isl_give isl_space *isl_space_join(__isl_take isl_space *left,
+	__isl_take isl_space *right);
+__isl_give isl_space *isl_space_product(__isl_take isl_space *left,
+	__isl_take isl_space *right);
+__isl_give isl_space *isl_space_domain_product(__isl_take isl_space *left,
+	__isl_take isl_space *right);
+__isl_give isl_space *isl_space_range_product(__isl_take isl_space *left,
+	__isl_take isl_space *right);
+__isl_give isl_space *isl_space_factor_domain(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_factor_range(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_domain_factor_domain(
+	__isl_take isl_space *space);
+__isl_give isl_space *isl_space_domain_factor_range(
+	__isl_take isl_space *space);
+__isl_give isl_space *isl_space_range_factor_domain(
+	__isl_take isl_space *space);
+__isl_give isl_space *isl_space_range_factor_range(
+	__isl_take isl_space *space);
+__isl_give isl_space *isl_space_map_from_set(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_map_from_domain_and_range(
+	__isl_take isl_space *domain, __isl_take isl_space *range);
+__isl_give isl_space *isl_space_reverse(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_drop_dims(__isl_take isl_space *dim,
+	enum isl_dim_type type, unsigned first, unsigned num);
+__isl_give isl_space *isl_space_drop_inputs(__isl_take isl_space *dim,
+		unsigned first, unsigned n);
+__isl_give isl_space *isl_space_drop_outputs(__isl_take isl_space *dim,
+		unsigned first, unsigned n);
+__isl_give isl_space *isl_space_domain(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_from_domain(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_range(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_from_range(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_domain_map(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_range_map(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_params(__isl_take isl_space *space);
+__isl_give isl_space *isl_space_set_from_params(__isl_take isl_space *space);
+
+__isl_give isl_space *isl_space_align_params(__isl_take isl_space *dim1,
+	__isl_take isl_space *dim2);
+
+int isl_space_is_wrapping(__isl_keep isl_space *dim);
+int isl_space_domain_is_wrapping(__isl_keep isl_space *space);
+int isl_space_range_is_wrapping(__isl_keep isl_space *space);
+__isl_give isl_space *isl_space_wrap(__isl_take isl_space *dim);
+__isl_give isl_space *isl_space_unwrap(__isl_take isl_space *dim);
+
+int isl_space_can_zip(__isl_keep isl_space *dim);
+__isl_give isl_space *isl_space_zip(__isl_take isl_space *dim);
+
+int isl_space_can_curry(__isl_keep isl_space *space);
+__isl_give isl_space *isl_space_curry(__isl_take isl_space *space);
+
+int isl_space_can_uncurry(__isl_keep isl_space *space);
+__isl_give isl_space *isl_space_uncurry(__isl_take isl_space *space);
+
+int isl_space_is_domain(__isl_keep isl_space *space1,
+	__isl_keep isl_space *space2);
+int isl_space_is_range(__isl_keep isl_space *space1,
+	__isl_keep isl_space *space2);
+int isl_space_is_equal(__isl_keep isl_space *space1,
+	__isl_keep isl_space *space2);
+int isl_space_tuple_is_equal(__isl_keep isl_space *space1,
+	enum isl_dim_type type1, __isl_keep isl_space *space2,
+	enum isl_dim_type type2);
+int isl_space_match(__isl_keep isl_space *dim1, enum isl_dim_type dim1_type,
+	__isl_keep isl_space *dim2, enum isl_dim_type dim2_type);
+ISL_DEPRECATED
+int isl_space_tuple_match(__isl_keep isl_space *space1, enum isl_dim_type type1,
+	__isl_keep isl_space *space2, enum isl_dim_type type2);
+int isl_space_compatible(__isl_keep isl_space *dim1,
+	__isl_keep isl_space *dim2);
+unsigned isl_space_dim(__isl_keep isl_space *dim, enum isl_dim_type type);
+
+__isl_give char *isl_space_to_str(__isl_keep isl_space *space);
+__isl_give isl_printer *isl_printer_print_space(__isl_take isl_printer *p,
+	__isl_keep isl_space *dim);
+void isl_space_dump(__isl_keep isl_space *dim);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/stream.h (added)
+++ polly/trunk/lib/External/isl/include/isl/stream.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_STREAM_H
+#define ISL_STREAM_H
+
+#include <stdio.h>
+#include <isl/hash.h>
+#include <isl/aff_type.h>
+#include <isl/obj.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+enum isl_token_type { ISL_TOKEN_ERROR = -1,
+			ISL_TOKEN_UNKNOWN = 256, ISL_TOKEN_VALUE,
+			ISL_TOKEN_IDENT, ISL_TOKEN_GE,
+			ISL_TOKEN_LE, ISL_TOKEN_GT, ISL_TOKEN_LT,
+			ISL_TOKEN_NE, ISL_TOKEN_EQ_EQ,
+			ISL_TOKEN_LEX_GE, ISL_TOKEN_LEX_LE,
+			ISL_TOKEN_LEX_GT, ISL_TOKEN_LEX_LT,
+			ISL_TOKEN_TO, ISL_TOKEN_AND,
+			ISL_TOKEN_OR, ISL_TOKEN_EXISTS, ISL_TOKEN_NOT,
+			ISL_TOKEN_DEF, ISL_TOKEN_INFTY, ISL_TOKEN_NAN,
+			ISL_TOKEN_MIN, ISL_TOKEN_MAX, ISL_TOKEN_RAT,
+			ISL_TOKEN_TRUE, ISL_TOKEN_FALSE,
+			ISL_TOKEN_CEILD, ISL_TOKEN_FLOORD, ISL_TOKEN_MOD,
+			ISL_TOKEN_STRING,
+			ISL_TOKEN_MAP, ISL_TOKEN_AFF,
+			ISL_TOKEN_CEIL, ISL_TOKEN_FLOOR,
+			ISL_TOKEN_IMPLIES,
+			ISL_TOKEN_LAST };
+
+struct isl_token;
+
+__isl_give isl_val *isl_token_get_val(isl_ctx *ctx, struct isl_token *tok);
+__isl_give char *isl_token_get_str(isl_ctx *ctx, struct isl_token *tok);
+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);
+
+enum isl_token_type isl_stream_register_keyword(struct 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);
+__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);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/union_map.h (added)
+++ polly/trunk/lib/External/isl/include/isl/union_map.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,249 @@
+#ifndef ISL_UNION_MAP_H
+#define ISL_UNION_MAP_H
+
+#include <isl/space.h>
+#include <isl/map_type.h>
+#include <isl/union_map_type.h>
+#include <isl/printer.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+unsigned isl_union_map_dim(__isl_keep isl_union_map *umap,
+	enum isl_dim_type type);
+int isl_union_map_involves_dims(__isl_keep isl_union_map *umap,
+	enum isl_dim_type type, unsigned first, unsigned n);
+__isl_give isl_id *isl_union_map_get_dim_id(__isl_keep isl_union_map *umap,
+	enum isl_dim_type type, unsigned pos);
+
+__isl_constructor
+__isl_give isl_union_map *isl_union_map_from_basic_map(
+	__isl_take isl_basic_map *bmap);
+__isl_constructor
+__isl_give isl_union_map *isl_union_map_from_map(__isl_take isl_map *map);
+__isl_give isl_union_map *isl_union_map_empty(__isl_take isl_space *dim);
+__isl_give isl_union_map *isl_union_map_copy(__isl_keep isl_union_map *umap);
+__isl_null isl_union_map *isl_union_map_free(__isl_take isl_union_map *umap);
+
+isl_ctx *isl_union_map_get_ctx(__isl_keep isl_union_map *umap);
+__isl_give isl_space *isl_union_map_get_space(__isl_keep isl_union_map *umap);
+
+__isl_give isl_union_map *isl_union_map_reset_user(
+	__isl_take isl_union_map *umap);
+
+int isl_union_map_find_dim_by_name(__isl_keep isl_union_map *umap,
+	enum isl_dim_type type, const char *name);
+
+__isl_give isl_union_map *isl_union_map_universe(
+	__isl_take isl_union_map *umap);
+__isl_give isl_set *isl_union_map_params(__isl_take isl_union_map *umap);
+__isl_give isl_union_set *isl_union_map_domain(__isl_take isl_union_map *umap);
+__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_map *isl_union_map_range_map(
+	__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_set_wrapped_domain_map(
+	__isl_take isl_union_set *uset);
+__isl_give isl_union_map *isl_union_map_from_domain(
+	__isl_take isl_union_set *uset);
+__isl_give isl_union_map *isl_union_map_from_range(
+	__isl_take isl_union_set *uset);
+
+__isl_export
+__isl_give isl_union_map *isl_union_map_affine_hull(
+	__isl_take isl_union_map *umap);
+__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_simple_hull(
+	__isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_map_coalesce(
+	__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_compute_divs(
+	__isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_map_lexmin(__isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_map_lexmax(__isl_take isl_union_map *umap);
+
+__isl_give isl_union_map *isl_union_map_add_map(__isl_take isl_union_map *umap,
+	__isl_take isl_map *map);
+__isl_export
+__isl_give isl_union_map *isl_union_map_union(__isl_take isl_union_map *umap1,
+	__isl_take isl_union_map *umap2);
+__isl_export
+__isl_give isl_union_map *isl_union_map_subtract(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_export
+__isl_give isl_union_map *isl_union_map_intersect(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_export
+__isl_give isl_union_map *isl_union_map_intersect_params(
+	__isl_take isl_union_map *umap, __isl_take isl_set *set);
+__isl_give isl_union_map *isl_union_map_product(__isl_take isl_union_map *umap1,
+	__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_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(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_domain_factor_domain(
+	__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_domain_factor_range(
+	__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_range_factor_range(
+	__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_factor_domain(
+	__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_factor_range(
+	__isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_map_gist(__isl_take isl_union_map *umap,
+	__isl_take isl_union_map *context);
+__isl_export
+__isl_give isl_union_map *isl_union_map_gist_params(
+	__isl_take isl_union_map *umap, __isl_take isl_set *set);
+__isl_export
+__isl_give isl_union_map *isl_union_map_gist_domain(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_map *isl_union_map_gist_range(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *uset);
+
+__isl_export
+__isl_give isl_union_map *isl_union_map_intersect_domain(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_map *isl_union_map_intersect_range(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *uset);
+
+__isl_export
+__isl_give isl_union_map *isl_union_map_subtract_domain(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *dom);
+__isl_export
+__isl_give isl_union_map *isl_union_map_subtract_range(
+	__isl_take isl_union_map *umap, __isl_take isl_union_set *dom);
+
+__isl_export
+__isl_give isl_union_map *isl_union_map_apply_domain(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_export
+__isl_give isl_union_map *isl_union_map_apply_range(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_preimage_domain_multi_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma);
+__isl_give isl_union_map *isl_union_map_preimage_range_multi_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_multi_aff *ma);
+__isl_give isl_union_map *isl_union_map_preimage_domain_pw_multi_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_union_map *isl_union_map_preimage_range_pw_multi_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_union_map *isl_union_map_preimage_domain_multi_pw_aff(
+	__isl_take isl_union_map *umap, __isl_take isl_multi_pw_aff *mpa);
+__isl_give isl_union_map *isl_union_map_preimage_domain_union_pw_multi_aff(
+	__isl_take isl_union_map *umap,
+	__isl_take isl_union_pw_multi_aff *upma);
+__isl_give isl_union_map *isl_union_map_preimage_range_union_pw_multi_aff(
+	__isl_take isl_union_map *umap,
+	__isl_take isl_union_pw_multi_aff *upma);
+__isl_export
+__isl_give isl_union_map *isl_union_map_reverse(__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_from_domain_and_range(
+	__isl_take isl_union_set *domain, __isl_take isl_union_set *range);
+
+__isl_export
+__isl_give isl_union_map *isl_union_map_detect_equalities(
+	__isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_set *isl_union_map_deltas(__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_deltas_map(
+	__isl_take isl_union_map *umap);
+__isl_export
+__isl_give isl_union_map *isl_union_set_identity(__isl_take isl_union_set *uset);
+
+__isl_give isl_union_map *isl_union_map_project_out(
+	__isl_take isl_union_map *umap,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+__isl_export
+int isl_union_map_is_empty(__isl_keep isl_union_map *umap);
+__isl_export
+int isl_union_map_is_single_valued(__isl_keep isl_union_map *umap);
+int isl_union_map_plain_is_injective(__isl_keep isl_union_map *umap);
+__isl_export
+int isl_union_map_is_injective(__isl_keep isl_union_map *umap);
+__isl_export
+int isl_union_map_is_bijective(__isl_keep isl_union_map *umap);
+
+__isl_export
+int isl_union_map_is_subset(__isl_keep isl_union_map *umap1,
+	__isl_keep isl_union_map *umap2);
+__isl_export
+int isl_union_map_is_equal(__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);
+
+int isl_union_map_n_map(__isl_keep isl_union_map *umap);
+__isl_export
+int isl_union_map_foreach_map(__isl_keep isl_union_map *umap,
+	int (*fn)(__isl_take isl_map *map, void *user), void *user);
+__isl_give int isl_union_map_contains(__isl_keep isl_union_map *umap,
+	__isl_keep isl_space *dim);
+__isl_give isl_map *isl_union_map_extract_map(__isl_keep isl_union_map *umap,
+	__isl_take isl_space *dim);
+__isl_give isl_map *isl_map_from_union_map(__isl_take isl_union_map *umap);
+
+__isl_give isl_basic_map *isl_union_map_sample(__isl_take isl_union_map *umap);
+
+__isl_give isl_union_map *isl_union_map_fixed_power_val(
+	__isl_take isl_union_map *umap, __isl_take isl_val *exp);
+__isl_give isl_union_map *isl_union_map_power(__isl_take isl_union_map *umap,
+	int *exact);
+__isl_give isl_union_map *isl_union_map_transitive_closure(
+	__isl_take isl_union_map *umap, int *exact);
+
+__isl_give isl_union_map *isl_union_map_lex_lt_union_map(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_lex_le_union_map(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__isl_give isl_union_map *isl_union_map_lex_gt_union_map(
+	__isl_take isl_union_map *umap1, __isl_take isl_union_map *umap2);
+__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_read_from_file(isl_ctx *ctx,
+	FILE *input);
+__isl_constructor
+__isl_give isl_union_map *isl_union_map_read_from_str(isl_ctx *ctx,
+	const char *str);
+__isl_give char *isl_union_map_to_str(__isl_keep isl_union_map *umap);
+__isl_give isl_printer *isl_printer_print_union_map(__isl_take isl_printer *p,
+	__isl_keep isl_union_map *umap);
+void isl_union_map_dump(__isl_keep isl_union_map *umap);
+
+__isl_give isl_union_set *isl_union_map_wrap(__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_set_unwrap(__isl_take isl_union_set *uset);
+
+__isl_give isl_union_map *isl_union_map_zip(__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_curry(__isl_take isl_union_map *umap);
+__isl_give isl_union_map *isl_union_map_uncurry(__isl_take isl_union_map *umap);
+
+__isl_give isl_union_map *isl_union_map_align_params(
+	__isl_take isl_union_map *umap, __isl_take isl_space *model);
+__isl_give isl_union_set *isl_union_set_align_params(
+	__isl_take isl_union_set *uset, __isl_take isl_space *model);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/union_map_type.h (added)
+++ polly/trunk/lib/External/isl/include/isl/union_map_type.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,21 @@
+#ifndef ISL_UNION_MAP_TYPE_H
+#define ISL_UNION_MAP_TYPE_H
+
+#include <isl/ctx.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct __isl_export isl_union_map;
+typedef struct isl_union_map isl_union_map;
+#ifndef isl_union_set
+struct __isl_export isl_union_set;
+typedef struct isl_union_set isl_union_set;
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/union_set.h (added)
+++ polly/trunk/lib/External/isl/include/isl/union_set.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,147 @@
+#ifndef ISL_UNION_SET_H
+#define ISL_UNION_SET_H
+
+#include <isl/point.h>
+#include <isl/union_map.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+unsigned isl_union_set_dim(__isl_keep isl_union_set *uset,
+	enum isl_dim_type type);
+
+__isl_constructor
+__isl_give isl_union_set *isl_union_set_from_basic_set(
+	__isl_take isl_basic_set *bset);
+__isl_constructor
+__isl_give isl_union_set *isl_union_set_from_set(__isl_take isl_set *set);
+__isl_give isl_union_set *isl_union_set_empty(__isl_take isl_space *dim);
+__isl_give isl_union_set *isl_union_set_copy(__isl_keep isl_union_set *uset);
+__isl_null isl_union_set *isl_union_set_free(__isl_take isl_union_set *uset);
+
+isl_ctx *isl_union_set_get_ctx(__isl_keep isl_union_set *uset);
+__isl_give isl_space *isl_union_set_get_space(__isl_keep isl_union_set *uset);
+
+__isl_give isl_union_set *isl_union_set_reset_user(
+	__isl_take isl_union_set *uset);
+
+__isl_give isl_union_set *isl_union_set_universe(
+	__isl_take isl_union_set *uset);
+__isl_give isl_set *isl_union_set_params(__isl_take isl_union_set *uset);
+
+__isl_export
+__isl_give isl_union_set *isl_union_set_detect_equalities(
+	__isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_set *isl_union_set_affine_hull(
+	__isl_take isl_union_set *uset);
+__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_simple_hull(
+	__isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_set *isl_union_set_coalesce(
+	__isl_take isl_union_set *uset);
+__isl_give isl_union_set *isl_union_set_compute_divs(
+	__isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_set *isl_union_set_lexmin(__isl_take isl_union_set *uset);
+__isl_export
+__isl_give isl_union_set *isl_union_set_lexmax(__isl_take isl_union_set *uset);
+
+__isl_give isl_union_set *isl_union_set_add_set(__isl_take isl_union_set *uset,
+	__isl_take isl_set *set);
+__isl_give isl_union_set *isl_union_set_union(__isl_take isl_union_set *uset1,
+	__isl_take isl_union_set *uset2);
+__isl_export
+__isl_give isl_union_set *isl_union_set_subtract(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+__isl_export
+__isl_give isl_union_set *isl_union_set_intersect(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+__isl_export
+__isl_give isl_union_set *isl_union_set_intersect_params(
+	__isl_take isl_union_set *uset, __isl_take isl_set *set);
+__isl_give isl_union_set *isl_union_set_product(__isl_take isl_union_set *uset1,
+	__isl_take isl_union_set *uset2);
+__isl_export
+__isl_give isl_union_set *isl_union_set_gist(__isl_take isl_union_set *uset,
+	__isl_take isl_union_set *context);
+__isl_export
+__isl_give isl_union_set *isl_union_set_gist_params(
+	__isl_take isl_union_set *uset, __isl_take isl_set *set);
+
+__isl_export
+__isl_give isl_union_set *isl_union_set_apply(
+	__isl_take isl_union_set *uset, __isl_take isl_union_map *umap);
+__isl_give isl_union_set *isl_union_set_preimage_multi_aff(
+	__isl_take isl_union_set *uset, __isl_take isl_multi_aff *ma);
+__isl_give isl_union_set *isl_union_set_preimage_pw_multi_aff(
+	__isl_take isl_union_set *uset, __isl_take isl_pw_multi_aff *pma);
+__isl_give isl_union_set *isl_union_set_preimage_union_pw_multi_aff(
+	__isl_take isl_union_set *uset,
+	__isl_take isl_union_pw_multi_aff *upma);
+
+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);
+
+__isl_export
+int isl_union_set_is_subset(__isl_keep isl_union_set *uset1,
+	__isl_keep isl_union_set *uset2);
+__isl_export
+int isl_union_set_is_equal(__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);
+
+int isl_union_set_n_set(__isl_keep isl_union_set *uset);
+__isl_export
+int isl_union_set_foreach_set(__isl_keep isl_union_set *uset,
+	int (*fn)(__isl_take isl_set *set, void *user), void *user);
+__isl_give int isl_union_set_contains(__isl_keep isl_union_set *uset,
+	__isl_keep isl_space *dim);
+__isl_give isl_set *isl_union_set_extract_set(__isl_keep isl_union_set *uset,
+	__isl_take isl_space *dim);
+__isl_give isl_set *isl_set_from_union_set(__isl_take isl_union_set *uset);
+int isl_union_set_foreach_point(__isl_keep isl_union_set *uset,
+	int (*fn)(__isl_take isl_point *pnt, void *user), void *user);
+
+__isl_give isl_basic_set *isl_union_set_sample(__isl_take isl_union_set *uset);
+
+__isl_give isl_union_set *isl_union_set_lift(__isl_take isl_union_set *uset);
+
+__isl_give isl_union_map *isl_union_set_lex_lt_union_set(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+__isl_give isl_union_map *isl_union_set_lex_le_union_set(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+__isl_give isl_union_map *isl_union_set_lex_gt_union_set(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+__isl_give isl_union_map *isl_union_set_lex_ge_union_set(
+	__isl_take isl_union_set *uset1, __isl_take isl_union_set *uset2);
+
+__isl_give isl_union_set *isl_union_set_coefficients(
+	__isl_take isl_union_set *bset);
+__isl_give isl_union_set *isl_union_set_solutions(
+	__isl_take isl_union_set *bset);
+
+__isl_give isl_union_set *isl_union_set_read_from_file(isl_ctx *ctx,
+	FILE *input);
+__isl_constructor
+__isl_give isl_union_set *isl_union_set_read_from_str(isl_ctx *ctx,
+	const char *str);
+__isl_give char *isl_union_set_to_str(__isl_keep isl_union_set *uset);
+__isl_give isl_printer *isl_printer_print_union_set(__isl_take isl_printer *p,
+	__isl_keep isl_union_set *uset);
+void isl_union_set_dump(__isl_keep isl_union_set *uset);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#include <isl/dim.h>
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/union_set_type.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/union_set_type.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/union_set_type.h (added)
+++ polly/trunk/lib/External/isl/include/isl/union_set_type.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6 @@
+#ifndef ISL_UNION_SET_TYPE_H
+#define ISL_UNION_SET_TYPE_H
+
+#include <isl/union_map_type.h>
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/val.h (added)
+++ polly/trunk/lib/External/isl/include/isl/val.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,114 @@
+#ifndef ISL_VAL_H
+#define ISL_VAL_H
+
+#include <isl/ctx.h>
+#include <isl/list.h>
+#include <isl/multi.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_val;
+typedef struct isl_val isl_val;
+
+ISL_DECLARE_LIST(val)
+
+struct isl_multi_val;
+typedef struct isl_multi_val isl_multi_val;
+
+ISL_DECLARE_MULTI(val)
+
+__isl_give isl_val *isl_val_zero(isl_ctx *ctx);
+__isl_give isl_val *isl_val_one(isl_ctx *ctx);
+__isl_give isl_val *isl_val_negone(isl_ctx *ctx);
+__isl_give isl_val *isl_val_nan(isl_ctx *ctx);
+__isl_give isl_val *isl_val_infty(isl_ctx *ctx);
+__isl_give isl_val *isl_val_neginfty(isl_ctx *ctx);
+__isl_give isl_val *isl_val_int_from_si(isl_ctx *ctx, long i);
+__isl_give isl_val *isl_val_int_from_ui(isl_ctx *ctx, unsigned long u);
+__isl_give isl_val *isl_val_int_from_chunks(isl_ctx *ctx, size_t n,
+	size_t size, const void *chunks);
+
+__isl_give isl_val *isl_val_copy(__isl_keep isl_val *v);
+__isl_null isl_val *isl_val_free(__isl_take isl_val *v);
+
+isl_ctx *isl_val_get_ctx(__isl_keep isl_val *val);
+long isl_val_get_num_si(__isl_keep isl_val *v);
+long isl_val_get_den_si(__isl_keep isl_val *v);
+double isl_val_get_d(__isl_keep isl_val *v);
+size_t isl_val_n_abs_num_chunks(__isl_keep isl_val *v, size_t size);
+int isl_val_get_abs_num_chunks(__isl_keep isl_val *v, size_t size,
+	void *chunks);
+
+__isl_give isl_val *isl_val_set_si(__isl_take isl_val *v, long i);
+
+__isl_give isl_val *isl_val_abs(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_neg(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_inv(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_floor(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_ceil(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_trunc(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_2exp(__isl_take isl_val *v);
+__isl_give isl_val *isl_val_min(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_max(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_add(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_add_ui(__isl_take isl_val *v1, unsigned long v2);
+__isl_give isl_val *isl_val_sub(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_sub_ui(__isl_take isl_val *v1, unsigned long v2);
+__isl_give isl_val *isl_val_mul(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_mul_ui(__isl_take isl_val *v1, unsigned long v2);
+__isl_give isl_val *isl_val_div(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_mod(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_gcd(__isl_take isl_val *v1, __isl_take isl_val *v2);
+__isl_give isl_val *isl_val_gcdext(__isl_take isl_val *v1,
+	__isl_take isl_val *v2, __isl_give isl_val **x, __isl_give isl_val **y);
+
+int isl_val_sgn(__isl_keep isl_val *v);
+int isl_val_is_zero(__isl_keep isl_val *v);
+int isl_val_is_one(__isl_keep isl_val *v);
+int isl_val_is_negone(__isl_keep isl_val *v);
+int isl_val_is_nonneg(__isl_keep isl_val *v);
+int isl_val_is_nonpos(__isl_keep isl_val *v);
+int isl_val_is_pos(__isl_keep isl_val *v);
+int isl_val_is_neg(__isl_keep isl_val *v);
+int isl_val_is_int(__isl_keep isl_val *v);
+int isl_val_is_rat(__isl_keep isl_val *v);
+int isl_val_is_nan(__isl_keep isl_val *v);
+int isl_val_is_infty(__isl_keep isl_val *v);
+int isl_val_is_neginfty(__isl_keep isl_val *v);
+
+int isl_val_cmp_si(__isl_keep isl_val *v, long i);
+
+int isl_val_lt(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_le(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_gt(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_ge(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_ne(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+int isl_val_abs_eq(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+
+int isl_val_is_divisible_by(__isl_keep isl_val *v1, __isl_keep isl_val *v2);
+
+__isl_give isl_val *isl_val_read_from_str(isl_ctx *ctx, const char *str);
+__isl_give isl_printer *isl_printer_print_val(__isl_take isl_printer *p,
+	__isl_keep isl_val *v);
+void isl_val_dump(__isl_keep isl_val *v);
+__isl_give char *isl_val_to_str(__isl_keep isl_val *v);
+
+__isl_give isl_multi_val *isl_multi_val_add_val(__isl_take isl_multi_val *mv,
+	__isl_take isl_val *v);
+__isl_give isl_multi_val *isl_multi_val_mod_val(__isl_take isl_multi_val *mv,
+	__isl_take isl_val *v);
+
+__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);
+__isl_give char *isl_multi_val_to_str(__isl_keep isl_multi_val *mv);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/val_gmp.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/val_gmp.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/val_gmp.h (added)
+++ polly/trunk/lib/External/isl/include/isl/val_gmp.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,21 @@
+#ifndef ISL_VAL_GMP_H
+#define ISL_VAL_GMP_H
+
+#include <gmp.h>
+#include <isl/val.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+__isl_give isl_val *isl_val_int_from_gmp(isl_ctx *ctx, mpz_t z);
+__isl_give isl_val *isl_val_from_gmp(isl_ctx *ctx,
+	const mpz_t n, const mpz_t d);
+int isl_val_get_num_gmp(__isl_keep isl_val *v, mpz_t z);
+int isl_val_get_den_gmp(__isl_keep isl_val *v, mpz_t z);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/vec.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/vec.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/vec.h (added)
+++ polly/trunk/lib/External/isl/include/isl/vec.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_VEC_H
+#define ISL_VEC_H
+
+#include <stdio.h>
+
+#include <isl/ctx.h>
+#include <isl/val.h>
+#include <isl/printer.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_vec;
+typedef struct isl_vec isl_vec;
+
+__isl_give isl_vec *isl_vec_alloc(isl_ctx *ctx, unsigned size);
+__isl_give isl_vec *isl_vec_copy(__isl_keep isl_vec *vec);
+__isl_null isl_vec *isl_vec_free(__isl_take isl_vec *vec);
+
+isl_ctx *isl_vec_get_ctx(__isl_keep isl_vec *vec);
+
+int isl_vec_size(__isl_keep isl_vec *vec);
+__isl_give isl_val *isl_vec_get_element_val(__isl_keep isl_vec *vec, int pos);
+__isl_give isl_vec *isl_vec_set_element_si(__isl_take isl_vec *vec,
+	int pos, int v);
+__isl_give isl_vec *isl_vec_set_element_val(__isl_take isl_vec *vec,
+	int pos, __isl_take isl_val *v);
+
+int isl_vec_is_equal(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2);
+int isl_vec_cmp_element(__isl_keep isl_vec *vec1, __isl_keep isl_vec *vec2,
+	int pos);
+
+void isl_vec_dump(__isl_keep isl_vec *vec);
+__isl_give isl_printer *isl_printer_print_vec(__isl_take isl_printer *printer,
+	__isl_keep isl_vec *vec);
+
+struct isl_vec *isl_vec_ceil(struct isl_vec *vec);
+struct isl_vec *isl_vec_normalize(struct isl_vec *vec);
+__isl_give isl_vec *isl_vec_set_si(__isl_take isl_vec *vec, int v);
+__isl_give isl_vec *isl_vec_set_val(__isl_take isl_vec *vec,
+	__isl_take isl_val *v);
+__isl_give isl_vec *isl_vec_clr(__isl_take isl_vec *vec);
+__isl_give isl_vec *isl_vec_neg(__isl_take isl_vec *vec);
+__isl_give isl_vec *isl_vec_add(__isl_take isl_vec *vec1,
+	__isl_take isl_vec *vec2);
+__isl_give isl_vec *isl_vec_extend(__isl_take isl_vec *vec, unsigned size);
+__isl_give isl_vec *isl_vec_zero_extend(__isl_take isl_vec *vec, unsigned size);
+__isl_give isl_vec *isl_vec_concat(__isl_take isl_vec *vec1,
+	__isl_take isl_vec *vec2);
+
+__isl_give isl_vec *isl_vec_sort(__isl_take isl_vec *vec);
+
+__isl_give isl_vec *isl_vec_read_from_file(isl_ctx *ctx, FILE *input);
+
+__isl_give isl_vec *isl_vec_drop_els(__isl_take isl_vec *vec,
+	unsigned pos, unsigned n);
+__isl_give isl_vec *isl_vec_insert_els(__isl_take isl_vec *vec,
+	unsigned pos, unsigned n);
+__isl_give isl_vec *isl_vec_insert_zero_els(__isl_take isl_vec *vec,
+	unsigned pos, unsigned n);
+__isl_give isl_vec *isl_vec_move_els(__isl_take isl_vec *vec,
+	unsigned dst_col, unsigned src_col, unsigned n);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/version.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/version.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/version.h (added)
+++ polly/trunk/lib/External/isl/include/isl/version.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,14 @@
+#ifndef ISL_VERSION_H
+#define ISL_VERSION_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+const char *isl_version(void);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/include/isl/vertices.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/include/isl/vertices.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/include/isl/vertices.h (added)
+++ polly/trunk/lib/External/isl/include/isl/vertices.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,47 @@
+#ifndef ISL_VERTICES_H
+#define ISL_VERTICES_H
+
+#include <isl/aff_type.h>
+#include <isl/set_type.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_external_vertex;
+typedef struct isl_external_vertex	isl_vertex;
+
+struct isl_cell;
+typedef struct isl_cell		isl_cell;
+
+struct isl_vertices;
+typedef struct isl_vertices	isl_vertices;
+
+isl_ctx *isl_vertex_get_ctx(__isl_keep isl_vertex *vertex);
+int isl_vertex_get_id(__isl_keep isl_vertex *vertex);
+__isl_give isl_basic_set *isl_vertex_get_domain(__isl_keep isl_vertex *vertex);
+__isl_give isl_multi_aff *isl_vertex_get_expr(__isl_keep isl_vertex *vertex);
+void isl_vertex_free(__isl_take isl_vertex *vertex);
+
+__isl_give isl_vertices *isl_basic_set_compute_vertices(
+	__isl_keep isl_basic_set *bset);
+isl_ctx *isl_vertices_get_ctx(__isl_keep isl_vertices *vertices);
+int isl_vertices_get_n_vertices(__isl_keep isl_vertices *vertices);
+int isl_vertices_foreach_vertex(__isl_keep isl_vertices *vertices,
+	int (*fn)(__isl_take isl_vertex *vertex, void *user), void *user);
+void isl_vertices_free(__isl_take isl_vertices *vertices);
+
+isl_ctx *isl_cell_get_ctx(__isl_keep isl_cell *cell);
+__isl_give isl_basic_set *isl_cell_get_domain(__isl_keep isl_cell *cell);
+int isl_cell_foreach_vertex(__isl_keep isl_cell *cell,
+	int (*fn)(__isl_take isl_vertex *vertex, void *user), void *user);
+void isl_cell_free(__isl_take isl_cell *cell);
+
+int isl_vertices_foreach_cell(__isl_keep isl_vertices *vertices,
+	int (*fn)(__isl_take isl_cell *cell, void *user), void *user);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/interface/Makefile.am
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/interface/Makefile.am?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/interface/Makefile.am (added)
+++ polly/trunk/lib/External/isl/interface/Makefile.am Wed Feb  4 14:55:43 2015
@@ -0,0 +1,32 @@
+AUTOMAKE_OPTIONS = nostdinc
+
+noinst_PROGRAMS = extract_interface
+
+AM_CXXFLAGS = $(CLANG_CXXFLAGS)
+AM_LDFLAGS = $(CLANG_LDFLAGS)
+
+includes = -I$(top_builddir) -I$(top_srcdir) \
+	-I$(top_builddir)/include -I$(top_srcdir)/include
+
+extract_interface_CPPFLAGS = $(includes)
+extract_interface_SOURCES = \
+	python.h \
+	python.cc \
+	extract_interface.h \
+	extract_interface.cc
+extract_interface_LDADD = \
+	-lclangFrontend -lclangSerialization -lclangParse -lclangSema \
+	$(LIB_CLANG_EDIT) \
+	-lclangAnalysis -lclangAST -lclangLex -lclangBasic -lclangDriver \
+	$(CLANG_LIBS) $(CLANG_LDFLAGS)
+
+test: extract_interface
+	./extract_interface$(EXEEXT) $(includes) $(srcdir)/all.h
+
+isl.py: extract_interface isl.py.top
+	(cat $(srcdir)/isl.py.top; \
+		./extract_interface$(EXEEXT) $(includes) $(srcdir)/all.h) \
+			> isl.py
+
+dist-hook: isl.py
+	cp isl.py $(distdir)/

Added: polly/trunk/lib/External/isl/interface/all.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/interface/all.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/interface/all.h (added)
+++ polly/trunk/lib/External/isl/interface/all.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,4 @@
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/union_set.h>
+#include <isl/union_map.h>

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/interface/extract_interface.cc (added)
+++ polly/trunk/lib/External/isl/interface/extract_interface.cc Wed Feb  4 14:55:43 2015
@@ -0,0 +1,388 @@
+/*
+ * Copyright 2011 Sven Verdoolaege. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as
+ * representing official policies, either expressed or implied, of
+ * Sven Verdoolaege.
+ */ 
+
+#include "isl_config.h"
+
+#include <assert.h>
+#include <iostream>
+#ifdef HAVE_ADT_OWNINGPTR_H
+#include <llvm/ADT/OwningPtr.h>
+#else
+#include <memory>
+#endif
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/CommandLine.h>
+#include <llvm/Support/Host.h>
+#include <llvm/Support/ManagedStatic.h>
+#include <clang/AST/ASTContext.h>
+#include <clang/AST/ASTConsumer.h>
+#include <clang/Basic/FileSystemOptions.h>
+#include <clang/Basic/FileManager.h>
+#include <clang/Basic/TargetOptions.h>
+#include <clang/Basic/TargetInfo.h>
+#include <clang/Basic/Version.h>
+#include <clang/Driver/Compilation.h>
+#include <clang/Driver/Driver.h>
+#include <clang/Driver/Tool.h>
+#include <clang/Frontend/CompilerInstance.h>
+#include <clang/Frontend/CompilerInvocation.h>
+#ifdef HAVE_BASIC_DIAGNOSTICOPTIONS_H
+#include <clang/Basic/DiagnosticOptions.h>
+#else
+#include <clang/Frontend/DiagnosticOptions.h>
+#endif
+#include <clang/Frontend/TextDiagnosticPrinter.h>
+#include <clang/Frontend/Utils.h>
+#include <clang/Lex/HeaderSearch.h>
+#include <clang/Lex/Preprocessor.h>
+#include <clang/Parse/ParseAST.h>
+#include <clang/Sema/Sema.h>
+
+#include "extract_interface.h"
+#include "python.h"
+
+using namespace std;
+using namespace clang;
+using namespace clang::driver;
+
+#ifdef HAVE_ADT_OWNINGPTR_H
+#define unique_ptr	llvm::OwningPtr
+#endif
+
+static llvm::cl::opt<string> InputFilename(llvm::cl::Positional,
+			llvm::cl::Required, llvm::cl::desc("<input file>"));
+static llvm::cl::list<string> Includes("I",
+			llvm::cl::desc("Header search path"),
+			llvm::cl::value_desc("path"), llvm::cl::Prefix);
+
+static const char *ResourceDir =
+	CLANG_PREFIX "/lib/clang/" CLANG_VERSION_STRING;
+
+/* Does decl have an attribute of the following form?
+ *
+ *	__attribute__((annotate("name")))
+ */
+bool has_annotation(Decl *decl, const char *name)
+{
+	if (!decl->hasAttrs())
+		return false;
+
+	AttrVec attrs = decl->getAttrs();
+	for (AttrVec::const_iterator i = attrs.begin() ; i != attrs.end(); ++i) {
+		const AnnotateAttr *ann = dyn_cast<AnnotateAttr>(*i);
+		if (!ann)
+			continue;
+		if (ann->getAnnotation().str() == name)
+			return true;
+	}
+
+	return false;
+}
+
+/* Is decl marked as exported?
+ */
+static bool is_exported(Decl *decl)
+{
+	return has_annotation(decl, "isl_export");
+}
+
+/* Collect all types and functions that are annotated "isl_export"
+ * in "types" and "function".
+ *
+ * We currently only consider single declarations.
+ */
+struct MyASTConsumer : public ASTConsumer {
+	set<RecordDecl *> types;
+	set<FunctionDecl *> functions;
+
+	virtual HandleTopLevelDeclReturn HandleTopLevelDecl(DeclGroupRef D) {
+		Decl *decl;
+
+		if (!D.isSingleDecl())
+			return HandleTopLevelDeclContinue;
+		decl = D.getSingleDecl();
+		if (!is_exported(decl))
+			return HandleTopLevelDeclContinue;
+		switch (decl->getKind()) {
+		case Decl::Record:
+			types.insert(cast<RecordDecl>(decl));
+			break;
+		case Decl::Function:
+			functions.insert(cast<FunctionDecl>(decl));
+			break;
+		default:
+			break;
+		}
+		return HandleTopLevelDeclContinue;
+	}
+};
+
+#ifdef USE_ARRAYREF
+
+#ifdef HAVE_CXXISPRODUCTION
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
+			    "", false, false, Diags);
+}
+#elif defined(HAVE_ISPRODUCTION)
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
+			    "", false, Diags);
+}
+#elif defined(DRIVER_CTOR_TAKES_DEFAULTIMAGENAME)
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+	return new Driver(binary, llvm::sys::getDefaultTargetTriple(),
+			    "", Diags);
+}
+#else
+static Driver *construct_driver(const char *binary, DiagnosticsEngine &Diags)
+{
+	return new Driver(binary, llvm::sys::getDefaultTargetTriple(), Diags);
+}
+#endif
+
+/* 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
+ * paths on newer clangs and on some platforms.
+ */
+static CompilerInvocation *construct_invocation(const char *filename,
+	DiagnosticsEngine &Diags)
+{
+	const char *binary = CLANG_PREFIX"/bin/clang";
+	const unique_ptr<Driver> driver(construct_driver(binary, Diags));
+	std::vector<const char *> Argv;
+	Argv.push_back(binary);
+	Argv.push_back(filename);
+	const unique_ptr<Compilation> compilation(
+		driver->BuildCompilation(llvm::ArrayRef<const char *>(Argv)));
+	JobList &Jobs = compilation->getJobs();
+
+	Command *cmd = cast<Command>(*Jobs.begin());
+	if (strcmp(cmd->getCreator().getName(), "clang"))
+		return NULL;
+
+	const ArgStringList *args = &cmd->getArguments();
+
+	CompilerInvocation *invocation = new CompilerInvocation;
+	CompilerInvocation::CreateFromArgs(*invocation, args->data() + 1,
+						args->data() + args->size(),
+						Diags);
+	return invocation;
+}
+
+#else
+
+static CompilerInvocation *construct_invocation(const char *filename,
+	DiagnosticsEngine &Diags)
+{
+	return NULL;
+}
+
+#endif
+
+#ifdef HAVE_BASIC_DIAGNOSTICOPTIONS_H
+
+static TextDiagnosticPrinter *construct_printer(void)
+{
+	return new TextDiagnosticPrinter(llvm::errs(), new DiagnosticOptions());
+}
+
+#else
+
+static TextDiagnosticPrinter *construct_printer(void)
+{
+	DiagnosticOptions DO;
+	return new TextDiagnosticPrinter(llvm::errs(), DO);
+}
+
+#endif
+
+#ifdef CREATETARGETINFO_TAKES_SHARED_PTR
+
+static TargetInfo *create_target_info(CompilerInstance *Clang,
+	DiagnosticsEngine &Diags)
+{
+	shared_ptr<TargetOptions> TO = Clang->getInvocation().TargetOpts;
+	TO->Triple = llvm::sys::getDefaultTargetTriple();
+	return TargetInfo::CreateTargetInfo(Diags, TO);
+}
+
+#elif defined(CREATETARGETINFO_TAKES_POINTER)
+
+static TargetInfo *create_target_info(CompilerInstance *Clang,
+	DiagnosticsEngine &Diags)
+{
+	TargetOptions &TO = Clang->getTargetOpts();
+	TO.Triple = llvm::sys::getDefaultTargetTriple();
+	return TargetInfo::CreateTargetInfo(Diags, &TO);
+}
+
+#else
+
+static TargetInfo *create_target_info(CompilerInstance *Clang,
+	DiagnosticsEngine &Diags)
+{
+	TargetOptions &TO = Clang->getTargetOpts();
+	TO.Triple = llvm::sys::getDefaultTargetTriple();
+	return TargetInfo::CreateTargetInfo(Diags, TO);
+}
+
+#endif
+
+#ifdef CREATEDIAGNOSTICS_TAKES_ARG
+
+static void create_diagnostics(CompilerInstance *Clang)
+{
+	Clang->createDiagnostics(0, NULL, construct_printer());
+}
+
+#else
+
+static void create_diagnostics(CompilerInstance *Clang)
+{
+	Clang->createDiagnostics(construct_printer());
+}
+
+#endif
+
+#ifdef CREATEPREPROCESSOR_TAKES_TUKIND
+
+static void create_preprocessor(CompilerInstance *Clang)
+{
+	Clang->createPreprocessor(TU_Complete);
+}
+
+#else
+
+static void create_preprocessor(CompilerInstance *Clang)
+{
+	Clang->createPreprocessor();
+}
+
+#endif
+
+#ifdef ADDPATH_TAKES_4_ARGUMENTS
+
+void add_path(HeaderSearchOptions &HSO, string Path)
+{
+	HSO.AddPath(Path, frontend::Angled, false, false);
+}
+
+#else
+
+void add_path(HeaderSearchOptions &HSO, string Path)
+{
+	HSO.AddPath(Path, frontend::Angled, true, false, false);
+}
+
+#endif
+
+#ifdef HAVE_SETMAINFILEID
+
+static void create_main_file_id(SourceManager &SM, const FileEntry *file)
+{
+	SM.setMainFileID(SM.createFileID(file, SourceLocation(),
+					SrcMgr::C_User));
+}
+
+#else
+
+static void create_main_file_id(SourceManager &SM, const FileEntry *file)
+{
+	SM.createMainFileID(file);
+}
+
+#endif
+
+int main(int argc, char *argv[])
+{
+	llvm::cl::ParseCommandLineOptions(argc, argv);
+
+	CompilerInstance *Clang = new CompilerInstance();
+	create_diagnostics(Clang);
+	DiagnosticsEngine &Diags = Clang->getDiagnostics();
+	Diags.setSuppressSystemWarnings(true);
+	CompilerInvocation *invocation =
+		construct_invocation(InputFilename.c_str(), Diags);
+	if (invocation)
+		Clang->setInvocation(invocation);
+	Clang->createFileManager();
+	Clang->createSourceManager(Clang->getFileManager());
+	TargetInfo *target = create_target_info(Clang, Diags);
+	Clang->setTarget(target);
+	CompilerInvocation::setLangDefaults(Clang->getLangOpts(), IK_C,
+					    LangStandard::lang_unspecified);
+	HeaderSearchOptions &HSO = Clang->getHeaderSearchOpts();
+	LangOptions &LO = Clang->getLangOpts();
+	PreprocessorOptions &PO = Clang->getPreprocessorOpts();
+	HSO.ResourceDir = ResourceDir;
+
+	for (int i = 0; i < Includes.size(); ++i)
+		add_path(HSO, Includes[i]);
+
+	PO.addMacroDef("__isl_give=__attribute__((annotate(\"isl_give\")))");
+	PO.addMacroDef("__isl_keep=__attribute__((annotate(\"isl_keep\")))");
+	PO.addMacroDef("__isl_take=__attribute__((annotate(\"isl_take\")))");
+	PO.addMacroDef("__isl_export=__attribute__((annotate(\"isl_export\")))");
+	PO.addMacroDef("__isl_constructor=__attribute__((annotate(\"isl_constructor\"))) __attribute__((annotate(\"isl_export\")))");
+	PO.addMacroDef("__isl_subclass(super)=__attribute__((annotate(\"isl_subclass(\" #super \")\"))) __attribute__((annotate(\"isl_export\")))");
+
+	create_preprocessor(Clang);
+	Preprocessor &PP = Clang->getPreprocessor();
+
+	PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(), LO);
+
+	const FileEntry *file = Clang->getFileManager().getFile(InputFilename);
+	assert(file);
+	create_main_file_id(Clang->getSourceManager(), file);
+
+	Clang->createASTContext();
+	MyASTConsumer consumer;
+	Sema *sema = new Sema(PP, Clang->getASTContext(), consumer);
+
+	Diags.getClient()->BeginSourceFile(LO, &PP);
+	ParseAST(*sema);
+	Diags.getClient()->EndSourceFile();
+
+	generate_python(consumer.types, consumer.functions);
+
+	delete sema;
+	delete Clang;
+	llvm::llvm_shutdown();
+
+	return 0;
+}

Added: polly/trunk/lib/External/isl/interface/extract_interface.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/interface/extract_interface.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/interface/extract_interface.h (added)
+++ polly/trunk/lib/External/isl/interface/extract_interface.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3 @@
+#include <clang/AST/Decl.h>
+
+bool has_annotation(clang::Decl *decl, const char *name);

Added: polly/trunk/lib/External/isl/interface/isl.py.top
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/interface/isl.py.top?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/interface/isl.py.top (added)
+++ polly/trunk/lib/External/isl/interface/isl.py.top Wed Feb  4 14:55:43 2015
@@ -0,0 +1,29 @@
+from ctypes import *
+
+isl = cdll.LoadLibrary("libisl.so")
+libc = cdll.LoadLibrary("libc.so.6")
+
+class Error(Exception):
+    pass
+
+class Context:
+    defaultInstance = None
+
+    def __init__(self):
+        ptr = isl.isl_ctx_alloc()
+        self.ptr = ptr
+
+    def __del__(self):
+        isl.isl_ctx_free(self)
+
+    def from_param(self):
+        return self.ptr
+
+    @staticmethod
+    def getDefaultInstance():
+        if Context.defaultInstance == None:
+            Context.defaultInstance = Context()
+        return Context.defaultInstance
+
+isl.isl_ctx_alloc.restype = c_void_p
+isl.isl_ctx_free.argtypes = [Context]

Added: polly/trunk/lib/External/isl/interface/python.cc
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/interface/python.cc?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/interface/python.cc (added)
+++ polly/trunk/lib/External/isl/interface/python.cc Wed Feb  4 14:55:43 2015
@@ -0,0 +1,519 @@
+/*
+ * Copyright 2011 Sven Verdoolaege. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 
+ *    1. Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ * 
+ *    2. Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY SVEN VERDOOLAEGE ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SVEN VERDOOLAEGE OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ * The views and conclusions contained in the software and documentation
+ * are those of the authors and should not be interpreted as
+ * representing official policies, either expressed or implied, of
+ * Sven Verdoolaege.
+ */ 
+
+#include "isl_config.h"
+
+#include <stdio.h>
+#include <iostream>
+#include <map>
+#include <clang/AST/Attr.h>
+#include "extract_interface.h"
+#include "python.h"
+
+/* Is the given type declaration marked as being a subtype of some other
+ * type?  If so, return that other type in "super".
+ */
+static bool is_subclass(RecordDecl *decl, string &super)
+{
+	if (!decl->hasAttrs())
+		return false;
+
+	string sub = "isl_subclass";
+	size_t len = sub.length();
+	AttrVec attrs = decl->getAttrs();
+	for (AttrVec::const_iterator i = attrs.begin() ; i != attrs.end(); ++i) {
+		const AnnotateAttr *ann = dyn_cast<AnnotateAttr>(*i);
+		if (!ann)
+			continue;
+		string s = ann->getAnnotation().str();
+		if (s.substr(0, len) == sub) {
+			super = s.substr(len + 1, s.length() - len  - 2);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/* Is decl marked as a constructor?
+ */
+static bool is_constructor(Decl *decl)
+{
+	return has_annotation(decl, "isl_constructor");
+}
+
+/* Is decl marked as consuming a reference?
+ */
+static bool takes(Decl *decl)
+{
+	return has_annotation(decl, "isl_take");
+}
+
+/* isl_class collects all constructors and methods for an isl "class".
+ * "name" is the name of the class.
+ * "type" is the declaration that introduces the type.
+ */
+struct isl_class {
+	string name;
+	RecordDecl *type;
+	set<FunctionDecl *> constructors;
+	set<FunctionDecl *> methods;
+
+	void print(map<string, isl_class> &classes, set<string> &done);
+	void print_constructor(FunctionDecl *method);
+	void print_method(FunctionDecl *method, bool subclass, string super);
+};
+
+/* Return the class that has a name that matches the initial part
+ * of the namd of function "fd".
+ */
+static isl_class &method2class(map<string, isl_class> &classes,
+	FunctionDecl *fd)
+{
+	string best;
+	map<string, isl_class>::iterator ci;
+	string name = fd->getNameAsString();
+
+	for (ci = classes.begin(); ci != classes.end(); ++ci) {
+		if (name.substr(0, ci->first.length()) == ci->first)
+			best = ci->first;
+	}
+
+	return classes[best];
+}
+
+/* Is "type" the type "isl_ctx *"?
+ */
+static bool is_isl_ctx(QualType type)
+{
+	if (!type->isPointerType())
+		return 0;
+	type = type->getPointeeType();
+	if (type.getAsString() != "isl_ctx")
+		return false;
+
+	return true;
+}
+
+/* Is the first argument of "fd" of type "isl_ctx *"?
+ */
+static bool first_arg_is_isl_ctx(FunctionDecl *fd)
+{
+	ParmVarDecl *param;
+
+	if (fd->getNumParams() < 1)
+		return false;
+
+	param = fd->getParamDecl(0);
+	return is_isl_ctx(param->getOriginalType());
+}
+
+/* Is "type" that of a pointer to an isl_* structure?
+ */
+static bool is_isl_type(QualType type)
+{
+	if (type->isPointerType()) {
+		string s = type->getPointeeType().getAsString();
+		return s.substr(0, 4) == "isl_";
+	}
+
+	return false;
+}
+
+/* Is "type" that of a pointer to a function?
+ */
+static bool is_callback(QualType type)
+{
+	if (!type->isPointerType())
+		return false;
+	type = type->getPointeeType();
+	return type->isFunctionType();
+}
+
+/* Is "type" that of "char *" of "const char *"?
+ */
+static bool is_string(QualType type)
+{
+	if (type->isPointerType()) {
+		string s = type->getPointeeType().getAsString();
+		return s == "const char" || s == "char";
+	}
+
+	return false;
+}
+
+/* Return the name of the type that "type" points to.
+ * The input "type" is assumed to be a pointer type.
+ */
+static string extract_type(QualType type)
+{
+	if (type->isPointerType())
+		return type->getPointeeType().getAsString();
+	assert(0);
+}
+
+/* Drop the "isl_" initial part of the type name "name".
+ */
+static string type2python(string name)
+{
+	return name.substr(4);
+}
+
+/* Construct a wrapper for a callback argument (at position "arg").
+ * Assign the wrapper to "cb".  We assume here that a function call
+ * has at most one callback argument.
+ *
+ * The wrapper converts the arguments of the callback to python types.
+ * If any exception is thrown, the wrapper keeps track of it in exc_info[0]
+ * and returns -1.  Otherwise the wrapper returns 0.
+ */
+static void print_callback(QualType type, int arg)
+{
+	const FunctionProtoType *fn = type->getAs<FunctionProtoType>();
+	unsigned n_arg = fn->getNumArgs();
+
+	printf("        exc_info = [None]\n");
+	printf("        fn = CFUNCTYPE(c_int");
+	for (int i = 0; i < n_arg - 1; ++i) {
+		QualType arg_type = fn->getArgType(i);
+		assert(is_isl_type(arg_type));
+		printf(", c_void_p");
+	}
+	printf(", c_void_p)\n");
+	printf("        def cb_func(");
+	for (int i = 0; i < n_arg; ++i) {
+		if (i)
+			printf(", ");
+		printf("cb_arg%d", i);
+	}
+	printf("):\n");
+	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("            try:\n");
+	printf("                arg%d(", arg);
+	for (int i = 0; i < n_arg - 1; ++i) {
+		if (i)
+			printf(", ");
+		printf("cb_arg%d", i);
+	}
+	printf(")\n");
+	printf("            except:\n");
+	printf("                import sys\n");
+	printf("                exc_info[0] = sys.exc_info()\n");
+	printf("                return -1\n");
+	printf("            return 0\n");
+	printf("        cb = fn(cb_func)\n");
+}
+
+/* Print a python method corresponding to the C function "method".
+ * "subclass" is set if the method belongs to a class that is a subclass
+ * of some other class ("super").
+ *
+ * If the function has a callback argument, then it also has a "user"
+ * argument.  Since Python has closures, there is no need for such
+ * a user argument in the Python interface, so we simply drop it.
+ * We also create a wrapper ("cb") for the callback.
+ *
+ * For each argument of the function that refers to an isl structure,
+ * including the object on which the method is called,
+ * we check if the corresponding actual argument is of the right type.
+ * If not, we try to convert it to the right type.
+ * It that doesn't work and if subclass is set, we try to convert self
+ * to the type of the superclass and call the corresponding method.
+ *
+ * If the function consumes a reference, then we pass it a copy of
+ * the actual argument.
+ */
+void isl_class::print_method(FunctionDecl *method, bool subclass, string super)
+{
+	string fullname = method->getName();
+	string cname = fullname.substr(name.length() + 1);
+	int num_params = method->getNumParams();
+	int drop_user = 0;
+
+	for (int i = 1; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		QualType type = param->getOriginalType();
+		if (is_callback(type))
+			drop_user = 1;
+	}
+
+	printf("    def %s(arg0", cname.c_str());
+	for (int i = 1; i < num_params - drop_user; ++i)
+		printf(", arg%d", i);
+	printf("):\n");
+
+	for (int i = 0; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		string type;
+		if (!is_isl_type(param->getOriginalType()))
+			continue;
+		type = type2python(extract_type(param->getOriginalType()));
+		printf("        try:\n");
+		printf("            if not arg%d.__class__ is %s:\n",
+			i, type.c_str());
+		printf("                arg%d = %s(arg%d)\n",
+			i, type.c_str(), i);
+		printf("        except:\n");
+		if (i > 0 && subclass) {
+			printf("            return %s(arg0).%s(",
+				type2python(super).c_str(), cname.c_str());
+			for (int i = 1; i < num_params - drop_user; ++i) {
+				if (i != 1)
+					printf(", ");
+				printf("arg%d", i);
+			}
+			printf(")\n");
+		} else
+			printf("            raise\n");
+	}
+	for (int i = 1; i < num_params; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		QualType type = param->getOriginalType();
+		if (!is_callback(type))
+			continue;
+		print_callback(type->getPointeeType(), i);
+	}
+	printf("        res = isl.%s(", fullname.c_str());
+	if (takes(method->getParamDecl(0)))
+		printf("isl.%s_copy(arg0.ptr)", name.c_str());
+	else
+		printf("arg0.ptr");
+	for (int i = 1; i < num_params - drop_user; ++i) {
+		ParmVarDecl *param = method->getParamDecl(i);
+		QualType type = param->getOriginalType();
+		if (is_callback(type))
+			printf(", cb");
+		else if (takes(param)) {
+			string type_s = extract_type(type);
+			printf(", isl.%s_copy(arg%d.ptr)", type_s.c_str(), i);
+		} else
+			printf(", arg%d.ptr", i);
+	}
+	if (drop_user)
+		printf(", None");
+	printf(")\n");
+
+	if (is_isl_type(method->getReturnType())) {
+		string type;
+		type = type2python(extract_type(method->getReturnType()));
+		printf("        return %s(ctx=arg0.ctx, ptr=res)\n",
+			type.c_str());
+	} else {
+		if (drop_user) {
+			printf("        if exc_info[0] != None:\n");
+			printf("            raise exc_info[0][0], "
+				"exc_info[0][1], exc_info[0][2]\n");
+		}
+		printf("        return res\n");
+	}
+}
+
+/* Print part of the constructor for this isl_class.
+ *
+ * In particular, check if the actual arguments correspond to the
+ * formal arguments of "cons" and if so call "cons" and put the
+ * result in self.ptr and a reference to the default context in self.ctx.
+ *
+ * If the function consumes a reference, then we pass it a copy of
+ * the actual argument.
+ */
+void isl_class::print_constructor(FunctionDecl *cons)
+{
+	string fullname = cons->getName();
+	string cname = fullname.substr(name.length() + 1);
+	int num_params = cons->getNumParams();
+	int drop_ctx = first_arg_is_isl_ctx(cons);
+
+	printf("        if len(args) == %d", num_params - drop_ctx);
+	for (int i = drop_ctx; i < num_params; ++i) {
+		ParmVarDecl *param = cons->getParamDecl(i);
+		if (is_isl_type(param->getOriginalType())) {
+			string type;
+			type = extract_type(param->getOriginalType());
+			type = type2python(type);
+			printf(" and args[%d].__class__ is %s",
+				i - drop_ctx, type.c_str());
+		} else
+			printf(" and type(args[%d]) == str", i - drop_ctx);
+	}
+	printf(":\n");
+	printf("            self.ctx = Context.getDefaultInstance()\n");
+	printf("            self.ptr = isl.%s(", fullname.c_str());
+	if (drop_ctx)
+		printf("self.ctx");
+	for (int i = drop_ctx; i < num_params; ++i) {
+		ParmVarDecl *param = cons->getParamDecl(i);
+		if (i)
+			printf(", ");
+		if (is_isl_type(param->getOriginalType())) {
+			if (takes(param)) {
+				string type;
+				type = extract_type(param->getOriginalType());
+				printf("isl.%s_copy(args[%d].ptr)",
+					type.c_str(), i - drop_ctx);
+			} else
+				printf("args[%d].ptr", i - drop_ctx);
+		} else
+			printf("args[%d]", i - drop_ctx);
+	}
+	printf(")\n");
+	printf("            return\n");
+}
+
+/* Print out the definition of this isl_class.
+ *
+ * We first check if this isl_class is a subclass of some other class.
+ * If it is, we make sure the superclass is printed out first.
+ *
+ * Then we print a constructor with several cases, one for constructing
+ * a Python object from a return value and one for each function that
+ * was marked as a constructor.
+ *
+ * Next, we print out some common methods and the methods corresponding
+ * to functions that are not marked as constructors.
+ *
+ * Finally, we tell ctypes about the types of the arguments of the
+ * constructor functions and the return types of those function returning
+ * an isl object.
+ */
+void isl_class::print(map<string, isl_class> &classes, set<string> &done)
+{
+	string super;
+	string p_name = type2python(name);
+	set<FunctionDecl *>::iterator in;
+	bool subclass = is_subclass(type, super);
+
+	if (subclass && done.find(super) == done.end())
+		classes[super].print(classes, done);
+	done.insert(name);
+
+	printf("\n");
+	printf("class %s", p_name.c_str());
+	if (subclass)
+		printf("(%s)", type2python(super).c_str());
+	printf(":\n");
+	printf("    def __init__(self, *args, **keywords):\n");
+
+	printf("        if \"ptr\" in keywords:\n");
+	printf("            self.ctx = keywords[\"ctx\"]\n");
+	printf("            self.ptr = keywords[\"ptr\"]\n");
+	printf("            return\n");
+
+	for (in = constructors.begin(); in != constructors.end(); ++in)
+		print_constructor(*in);
+	printf("        raise Error\n");
+	printf("    def __del__(self):\n");
+	printf("        if hasattr(self, 'ptr'):\n");
+	printf("            isl.%s_free(self.ptr)\n", name.c_str());
+	printf("    def __str__(self):\n");
+	printf("        ptr = isl.%s_to_str(self.ptr)\n", name.c_str());
+	printf("        res = str(cast(ptr, c_char_p).value)\n");
+	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());
+
+	for (in = methods.begin(); in != methods.end(); ++in)
+		print_method(*in, subclass, super);
+
+	printf("\n");
+	for (in = constructors.begin(); in != constructors.end(); ++in) {
+		string fullname = (*in)->getName();
+		printf("isl.%s.restype = c_void_p\n", fullname.c_str());
+		printf("isl.%s.argtypes = [", fullname.c_str());
+		for (int i = 0; i < (*in)->getNumParams(); ++i) {
+			ParmVarDecl *param = (*in)->getParamDecl(i);
+			QualType type = param->getOriginalType();
+			if (i)
+				printf(", ");
+			if (is_isl_ctx(type))
+				printf("Context");
+			else if (is_isl_type(type))
+				printf("c_void_p");
+			else if (is_string(type))
+				printf("c_char_p");
+			else
+				printf("c_int");
+		}
+		printf("]\n");
+	}
+	for (in = methods.begin(); in != methods.end(); ++in) {
+		string fullname = (*in)->getName();
+		if (is_isl_type((*in)->getReturnType()))
+			printf("isl.%s.restype = c_void_p\n", fullname.c_str());
+	}
+	printf("isl.%s_free.argtypes = [c_void_p]\n", name.c_str());
+	printf("isl.%s_to_str.argtypes = [c_void_p]\n", name.c_str());
+	printf("isl.%s_to_str.restype = POINTER(c_char)\n", name.c_str());
+}
+
+/* Generate a python interface based on the extracted types and functions.
+ * We first collect all functions that belong to a certain type,
+ * separating constructors from regular methods.
+ *
+ * Then we print out each class in turn.  If one of these is a subclass
+ * of some other class, it will make sure the superclass is printed out first.
+ */
+void generate_python(set<RecordDecl *> &types, set<FunctionDecl *> functions)
+{
+	map<string, isl_class> classes;
+	map<string, isl_class>::iterator ci;
+	set<string> done;
+
+	set<RecordDecl *>::iterator it;
+	for (it = types.begin(); it != types.end(); ++it) {
+		RecordDecl *decl = *it;
+		string name = decl->getName();
+		classes[name].name = name;
+		classes[name].type = decl;
+	}
+
+	set<FunctionDecl *>::iterator in;
+	for (in = functions.begin(); in != functions.end(); ++in) {
+		isl_class &c = method2class(classes, *in);
+		if (is_constructor(*in))
+			c.constructors.insert(*in);
+		else
+			c.methods.insert(*in);
+	}
+
+	for (ci = classes.begin(); ci != classes.end(); ++ci) {
+		if (done.find(ci->first) == done.end())
+			ci->second.print(classes, done);
+	}
+}

Added: polly/trunk/lib/External/isl/interface/python.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/interface/python.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/interface/python.h (added)
+++ polly/trunk/lib/External/isl/interface/python.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,7 @@
+#include <set>
+#include <clang/AST/Decl.h>
+
+using namespace std;
+using namespace clang;
+
+void generate_python(set<RecordDecl *> &types, set<FunctionDecl *> functions);

Added: polly/trunk/lib/External/isl/isl.py
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl.py?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl.py (added)
+++ polly/trunk/lib/External/isl/isl.py Wed Feb  4 14:55:43 2015
@@ -0,0 +1,100 @@
+import gdb
+import re
+
+# GDB Pretty Printers for most isl objects
+class IslObjectPrinter:
+	"""Print an isl object"""
+	def __init__ (self, val, type):
+                self.val = val
+                self.type = type
+
+	def to_string (self):
+                # Cast val to a void pointer to stop gdb using this pretty
+                # printer for the pointer which would lead to an infinite loop.
+                void_ptr = gdb.lookup_type('void').pointer()
+                value = str(self.val.cast(void_ptr))
+                printer = gdb.parse_and_eval("isl_printer_to_str(isl_"
+                                             + str(self.type)
+					     + "_get_ctx(" + value + "))")
+                printer = gdb.parse_and_eval("isl_printer_print_"
+                                             + str(self.type) + "("
+                                             + str(printer) + ", "
+                                             + value + ")")
+                string = gdb.parse_and_eval("(char*)isl_printer_get_str("
+                                            + str(printer) + ")")
+                gdb.parse_and_eval("isl_printer_free(" + str(printer) + ")")
+                return string
+
+	def display_hint (self):
+                return 'string'
+
+class IslIntPrinter:
+	"""Print an isl_int """
+	def __init__ (self, val):
+                self.val = val
+
+	def to_string (self):
+                # Cast val to a void pointer to stop gdb using this pretty
+                # printer for the pointer which would lead to an infinite loop.
+                void_ptr = gdb.lookup_type('void').pointer()
+                value = str(self.val.cast(void_ptr))
+
+                context = gdb.parse_and_eval("isl_ctx_alloc()")
+                printer = gdb.parse_and_eval("isl_printer_to_str("
+                                             + str(context) + ")")
+                printer = gdb.parse_and_eval("isl_printer_print_isl_int("
+                                             + str(printer) + ", "
+                                             + value + ")")
+                string = gdb.parse_and_eval("(char*)isl_printer_get_str("
+                                            + str(printer) + ")")
+                gdb.parse_and_eval("isl_printer_free(" + str(printer) + ")")
+                gdb.parse_and_eval("isl_ctx_free(" + str(context) + ")")
+                return string
+
+	def display_hint (self):
+                return 'string'
+
+class IslPrintCommand (gdb.Command):
+        """Print an isl value."""
+        def __init__ (self):
+                super (IslPrintCommand, self).__init__ ("islprint",
+                                                        gdb.COMMAND_OBSCURE)
+        def invoke (self, arg, from_tty):
+                arg = gdb.parse_and_eval(arg);
+                printer = str_lookup_function(arg)
+
+                if printer == None:
+                        print "No isl printer for this type"
+                        return
+
+                print printer.to_string()
+
+IslPrintCommand()
+
+def str_lookup_function (val):
+	if val.type.code != gdb.TYPE_CODE_PTR:
+		if str(val.type) == "isl_int":
+			return IslIntPrinter(val)
+                else:
+                        return None
+
+	lookup_tag = val.type.target()
+	regex = re.compile ("^isl_(.*)$")
+
+	if lookup_tag == None:
+		return None
+
+	m = regex.match (str(lookup_tag))
+
+	if m:
+                # Those types of printers defined in isl.
+                if m.group(1) in ["basic_set", "set", "union_set", "basic_map",
+                                  "map", "union_map", "qpolynomial",
+                                  "pw_qpolynomial", "pw_qpolynomial_fold",
+                                  "union_pw_qpolynomial",
+                                  "union_pw_qpolynomial_fold"]:
+                        return IslObjectPrinter(val, m.group(1))
+        return None
+
+# Do not register the pretty printer.
+# gdb.current_objfile().pretty_printers.append(str_lookup_function)

Added: polly/trunk/lib/External/isl/isl_aff.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_aff.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_aff.c (added)
+++ polly/trunk/lib/External/isl/isl_aff.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,6809 @@
+/*
+ * Copyright 2011      INRIA Saclay
+ * Copyright 2011      Sven Verdoolaege
+ * Copyright 2012-2014 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
+ */
+
+#include <isl_ctx_private.h>
+#define ISL_DIM_H
+#include <isl_map_private.h>
+#include <isl_union_map_private.h>
+#include <isl_aff_private.h>
+#include <isl_space_private.h>
+#include <isl_local_space_private.h>
+#include <isl_vec_private.h>
+#include <isl_mat_private.h>
+#include <isl/constraint.h>
+#include <isl_seq.h>
+#include <isl/set.h>
+#include <isl_val_private.h>
+#include <isl/deprecated/aff_int.h>
+#include <isl_config.h>
+
+#undef BASE
+#define BASE aff
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE pw_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)
+{
+	isl_aff *aff;
+
+	if (!ls || !v)
+		goto error;
+
+	aff = isl_calloc_type(v->ctx, struct isl_aff);
+	if (!aff)
+		goto error;
+
+	aff->ref = 1;
+	aff->ls = ls;
+	aff->v = v;
+
+	return aff;
+error:
+	isl_local_space_free(ls);
+	isl_vec_free(v);
+	return NULL;
+}
+
+__isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls)
+{
+	isl_ctx *ctx;
+	isl_vec *v;
+	unsigned total;
+
+	if (!ls)
+		return NULL;
+
+	ctx = isl_local_space_get_ctx(ls);
+	if (!isl_local_space_divs_known(ls))
+		isl_die(ctx, isl_error_invalid, "local space has unknown divs",
+			goto error);
+	if (!isl_local_space_is_set(ls))
+		isl_die(ctx, isl_error_invalid,
+			"domain of affine expression should be a set",
+			goto error);
+
+	total = isl_local_space_dim(ls, isl_dim_all);
+	v = isl_vec_alloc(ctx, 1 + 1 + total);
+	return isl_aff_alloc_vec(ls, v);
+error:
+	isl_local_space_free(ls);
+	return NULL;
+}
+
+__isl_give isl_aff *isl_aff_zero_on_domain(__isl_take isl_local_space *ls)
+{
+	isl_aff *aff;
+
+	aff = isl_aff_alloc(ls);
+	if (!aff)
+		return NULL;
+
+	isl_int_set_si(aff->v->el[0], 1);
+	isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
+
+	return aff;
+}
+
+/* Return a piecewise affine expression defined on the specified domain
+ * that is equal to zero.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_zero_on_domain(__isl_take isl_local_space *ls)
+{
+	return isl_pw_aff_from_aff(isl_aff_zero_on_domain(ls));
+}
+
+/* Return an affine expression defined on the specified domain
+ * that represents NaN.
+ */
+__isl_give isl_aff *isl_aff_nan_on_domain(__isl_take isl_local_space *ls)
+{
+	isl_aff *aff;
+
+	aff = isl_aff_alloc(ls);
+	if (!aff)
+		return NULL;
+
+	isl_seq_clr(aff->v->el, aff->v->size);
+
+	return aff;
+}
+
+/* Return a piecewise affine expression defined on the specified domain
+ * that represents NaN.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_nan_on_domain(__isl_take isl_local_space *ls)
+{
+	return isl_pw_aff_from_aff(isl_aff_nan_on_domain(ls));
+}
+
+/* Return an affine expression that is equal to "val" on
+ * domain local space "ls".
+ */
+__isl_give isl_aff *isl_aff_val_on_domain(__isl_take isl_local_space *ls,
+	__isl_take isl_val *val)
+{
+	isl_aff *aff;
+
+	if (!ls || !val)
+		goto error;
+	if (!isl_val_is_rat(val))
+		isl_die(isl_val_get_ctx(val), isl_error_invalid,
+			"expecting rational value", goto error);
+
+	aff = isl_aff_alloc(isl_local_space_copy(ls));
+	if (!aff)
+		goto error;
+
+	isl_seq_clr(aff->v->el + 2, aff->v->size - 2);
+	isl_int_set(aff->v->el[1], val->n);
+	isl_int_set(aff->v->el[0], val->d);
+
+	isl_local_space_free(ls);
+	isl_val_free(val);
+	return aff;
+error:
+	isl_local_space_free(ls);
+	isl_val_free(val);
+	return NULL;
+}
+
+/* Return an affine expression that is equal to the specified dimension
+ * in "ls".
+ */
+__isl_give isl_aff *isl_aff_var_on_domain(__isl_take isl_local_space *ls,
+	enum isl_dim_type type, unsigned pos)
+{
+	isl_space *space;
+	isl_aff *aff;
+
+	if (!ls)
+		return NULL;
+
+	space = isl_local_space_get_space(ls);
+	if (!space)
+		goto error;
+	if (isl_space_is_map(space))
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"expecting (parameter) set space", goto error);
+	if (pos >= isl_local_space_dim(ls, type))
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"position out of bounds", goto error);
+
+	isl_space_free(space);
+	aff = isl_aff_alloc(ls);
+	if (!aff)
+		return NULL;
+
+	pos += isl_local_space_offset(aff->ls, type);
+
+	isl_int_set_si(aff->v->el[0], 1);
+	isl_seq_clr(aff->v->el + 1, aff->v->size - 1);
+	isl_int_set_si(aff->v->el[1 + pos], 1);
+
+	return aff;
+error:
+	isl_local_space_free(ls);
+	isl_space_free(space);
+	return NULL;
+}
+
+/* Return a piecewise affine expression that is equal to
+ * the specified dimension in "ls".
+ */
+__isl_give isl_pw_aff *isl_pw_aff_var_on_domain(__isl_take isl_local_space *ls,
+	enum isl_dim_type type, unsigned pos)
+{
+	return isl_pw_aff_from_aff(isl_aff_var_on_domain(ls, type, pos));
+}
+
+__isl_give isl_aff *isl_aff_copy(__isl_keep isl_aff *aff)
+{
+	if (!aff)
+		return NULL;
+
+	aff->ref++;
+	return aff;
+}
+
+__isl_give isl_aff *isl_aff_dup(__isl_keep isl_aff *aff)
+{
+	if (!aff)
+		return NULL;
+
+	return isl_aff_alloc_vec(isl_local_space_copy(aff->ls),
+				 isl_vec_copy(aff->v));
+}
+
+__isl_give isl_aff *isl_aff_cow(__isl_take isl_aff *aff)
+{
+	if (!aff)
+		return NULL;
+
+	if (aff->ref == 1)
+		return aff;
+	aff->ref--;
+	return isl_aff_dup(aff);
+}
+
+__isl_null isl_aff *isl_aff_free(__isl_take isl_aff *aff)
+{
+	if (!aff)
+		return NULL;
+
+	if (--aff->ref > 0)
+		return NULL;
+
+	isl_local_space_free(aff->ls);
+	isl_vec_free(aff->v);
+
+	free(aff);
+
+	return NULL;
+}
+
+isl_ctx *isl_aff_get_ctx(__isl_keep isl_aff *aff)
+{
+	return aff ? isl_local_space_get_ctx(aff->ls) : NULL;
+}
+
+/* Externally, an isl_aff has a map space, but internally, the
+ * ls field corresponds to the domain of that space.
+ */
+int isl_aff_dim(__isl_keep isl_aff *aff, enum isl_dim_type type)
+{
+	if (!aff)
+		return 0;
+	if (type == isl_dim_out)
+		return 1;
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+	return isl_local_space_dim(aff->ls, type);
+}
+
+/* Return the position of the dimension of the given type and name
+ * in "aff".
+ * Return -1 if no such dimension can be found.
+ */
+int isl_aff_find_dim_by_name(__isl_keep isl_aff *aff, enum isl_dim_type type,
+	const char *name)
+{
+	if (!aff)
+		return -1;
+	if (type == isl_dim_out)
+		return -1;
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+	return isl_local_space_find_dim_by_name(aff->ls, type, name);
+}
+
+__isl_give isl_space *isl_aff_get_domain_space(__isl_keep isl_aff *aff)
+{
+	return aff ? isl_local_space_get_space(aff->ls) : NULL;
+}
+
+__isl_give isl_space *isl_aff_get_space(__isl_keep isl_aff *aff)
+{
+	isl_space *space;
+	if (!aff)
+		return NULL;
+	space = isl_local_space_get_space(aff->ls);
+	space = isl_space_from_domain(space);
+	space = isl_space_add_dims(space, isl_dim_out, 1);
+	return space;
+}
+
+__isl_give isl_local_space *isl_aff_get_domain_local_space(
+	__isl_keep isl_aff *aff)
+{
+	return aff ? isl_local_space_copy(aff->ls) : NULL;
+}
+
+__isl_give isl_local_space *isl_aff_get_local_space(__isl_keep isl_aff *aff)
+{
+	isl_local_space *ls;
+	if (!aff)
+		return NULL;
+	ls = isl_local_space_copy(aff->ls);
+	ls = isl_local_space_from_domain(ls);
+	ls = isl_local_space_add_dims(ls, isl_dim_out, 1);
+	return ls;
+}
+
+/* Externally, an isl_aff has a map space, but internally, the
+ * ls field corresponds to the domain of that space.
+ */
+const char *isl_aff_get_dim_name(__isl_keep isl_aff *aff,
+	enum isl_dim_type type, unsigned pos)
+{
+	if (!aff)
+		return NULL;
+	if (type == isl_dim_out)
+		return NULL;
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+	return isl_local_space_get_dim_name(aff->ls, type, pos);
+}
+
+__isl_give isl_aff *isl_aff_reset_domain_space(__isl_take isl_aff *aff,
+	__isl_take isl_space *dim)
+{
+	aff = isl_aff_cow(aff);
+	if (!aff || !dim)
+		goto error;
+
+	aff->ls = isl_local_space_reset_space(aff->ls, dim);
+	if (!aff->ls)
+		return isl_aff_free(aff);
+
+	return aff;
+error:
+	isl_aff_free(aff);
+	isl_space_free(dim);
+	return NULL;
+}
+
+/* Reset the space of "aff".  This function is called from isl_pw_templ.c
+ * and doesn't know if the space of an element object is represented
+ * directly or through its domain.  It therefore passes along both.
+ */
+__isl_give isl_aff *isl_aff_reset_space_and_domain(__isl_take isl_aff *aff,
+	__isl_take isl_space *space, __isl_take isl_space *domain)
+{
+	isl_space_free(space);
+	return isl_aff_reset_domain_space(aff, domain);
+}
+
+/* Reorder the coefficients of the affine expression based
+ * on the given reodering.
+ * The reordering r is assumed to have been extended with the local
+ * variables.
+ */
+static __isl_give isl_vec *vec_reorder(__isl_take isl_vec *vec,
+	__isl_take isl_reordering *r, int n_div)
+{
+	isl_vec *res;
+	int i;
+
+	if (!vec || !r)
+		goto error;
+
+	res = isl_vec_alloc(vec->ctx,
+			    2 + isl_space_dim(r->dim, isl_dim_all) + n_div);
+	isl_seq_cpy(res->el, vec->el, 2);
+	isl_seq_clr(res->el + 2, res->size - 2);
+	for (i = 0; i < r->len; ++i)
+		isl_int_set(res->el[2 + r->pos[i]], vec->el[2 + i]);
+
+	isl_reordering_free(r);
+	isl_vec_free(vec);
+	return res;
+error:
+	isl_vec_free(vec);
+	isl_reordering_free(r);
+	return NULL;
+}
+
+/* Reorder the dimensions of the domain of "aff" according
+ * to the given reordering.
+ */
+__isl_give isl_aff *isl_aff_realign_domain(__isl_take isl_aff *aff,
+	__isl_take isl_reordering *r)
+{
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		goto error;
+
+	r = isl_reordering_extend(r, aff->ls->div->n_row);
+	aff->v = vec_reorder(aff->v, isl_reordering_copy(r),
+				aff->ls->div->n_row);
+	aff->ls = isl_local_space_realign(aff->ls, r);
+
+	if (!aff->v || !aff->ls)
+		return isl_aff_free(aff);
+
+	return aff;
+error:
+	isl_aff_free(aff);
+	isl_reordering_free(r);
+	return NULL;
+}
+
+__isl_give isl_aff *isl_aff_align_params(__isl_take isl_aff *aff,
+	__isl_take isl_space *model)
+{
+	if (!aff || !model)
+		goto error;
+
+	if (!isl_space_match(aff->ls->dim, isl_dim_param,
+			     model, isl_dim_param)) {
+		isl_reordering *exp;
+
+		model = isl_space_drop_dims(model, isl_dim_in,
+					0, isl_space_dim(model, isl_dim_in));
+		model = isl_space_drop_dims(model, isl_dim_out,
+					0, isl_space_dim(model, isl_dim_out));
+		exp = isl_parameter_alignment_reordering(aff->ls->dim, model);
+		exp = isl_reordering_extend_space(exp,
+					isl_aff_get_domain_space(aff));
+		aff = isl_aff_realign_domain(aff, exp);
+	}
+
+	isl_space_free(model);
+	return aff;
+error:
+	isl_space_free(model);
+	isl_aff_free(aff);
+	return NULL;
+}
+
+/* Is "aff" obviously equal to zero?
+ *
+ * If the denominator is zero, then "aff" is not equal to zero.
+ */
+int isl_aff_plain_is_zero(__isl_keep isl_aff *aff)
+{
+	if (!aff)
+		return -1;
+
+	if (isl_int_is_zero(aff->v->el[0]))
+		return 0;
+	return isl_seq_first_non_zero(aff->v->el + 1, aff->v->size - 1) < 0;
+}
+
+/* Does "aff" represent NaN?
+ */
+int isl_aff_is_nan(__isl_keep isl_aff *aff)
+{
+	if (!aff)
+		return -1;
+
+	return isl_seq_first_non_zero(aff->v->el, 2) < 0;
+}
+
+/* Does "pa" involve any NaNs?
+ */
+int isl_pw_aff_involves_nan(__isl_keep isl_pw_aff *pa)
+{
+	int i;
+
+	if (!pa)
+		return -1;
+	if (pa->n == 0)
+		return 0;
+
+	for (i = 0; i < pa->n; ++i) {
+		int is_nan = isl_aff_is_nan(pa->p[i].aff);
+		if (is_nan < 0 || is_nan)
+			return is_nan;
+	}
+
+	return 0;
+}
+
+/* Are "aff1" and "aff2" obviously equal?
+ *
+ * NaN is not equal to anything, not even to another NaN.
+ */
+int isl_aff_plain_is_equal(__isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2)
+{
+	int equal;
+
+	if (!aff1 || !aff2)
+		return -1;
+
+	if (isl_aff_is_nan(aff1) || isl_aff_is_nan(aff2))
+		return 0;
+
+	equal = isl_local_space_is_equal(aff1->ls, aff2->ls);
+	if (equal < 0 || !equal)
+		return equal;
+
+	return isl_vec_is_equal(aff1->v, aff2->v);
+}
+
+/* Return the common denominator of "aff" in "v".
+ *
+ * We cannot return anything meaningful in case of a NaN.
+ */
+int isl_aff_get_denominator(__isl_keep isl_aff *aff, isl_int *v)
+{
+	if (!aff)
+		return -1;
+	if (isl_aff_is_nan(aff))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"cannot get denominator of NaN", return -1);
+	isl_int_set(*v, aff->v->el[0]);
+	return 0;
+}
+
+/* Return the common denominator of "aff".
+ */
+__isl_give isl_val *isl_aff_get_denominator_val(__isl_keep isl_aff *aff)
+{
+	isl_ctx *ctx;
+
+	if (!aff)
+		return NULL;
+
+	ctx = isl_aff_get_ctx(aff);
+	if (isl_aff_is_nan(aff))
+		return isl_val_nan(ctx);
+	return isl_val_int_from_isl_int(ctx, aff->v->el[0]);
+}
+
+/* Return the constant term of "aff" in "v".
+ *
+ * We cannot return anything meaningful in case of a NaN.
+ */
+int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v)
+{
+	if (!aff)
+		return -1;
+	if (isl_aff_is_nan(aff))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"cannot get constant term of NaN", return -1);
+	isl_int_set(*v, aff->v->el[1]);
+	return 0;
+}
+
+/* Return the constant term of "aff".
+ */
+__isl_give isl_val *isl_aff_get_constant_val(__isl_keep isl_aff *aff)
+{
+	isl_ctx *ctx;
+	isl_val *v;
+
+	if (!aff)
+		return NULL;
+
+	ctx = isl_aff_get_ctx(aff);
+	if (isl_aff_is_nan(aff))
+		return isl_val_nan(ctx);
+	v = isl_val_rat_from_isl_int(ctx, aff->v->el[1], aff->v->el[0]);
+	return isl_val_normalize(v);
+}
+
+/* Return the coefficient of the variable of type "type" at position "pos"
+ * of "aff" in "v".
+ *
+ * We cannot return anything meaningful in case of a NaN.
+ */
+int isl_aff_get_coefficient(__isl_keep isl_aff *aff,
+	enum isl_dim_type type, int pos, isl_int *v)
+{
+	if (!aff)
+		return -1;
+
+	if (type == isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"output/set dimension does not have a coefficient",
+			return -1);
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+
+	if (pos >= isl_local_space_dim(aff->ls, type))
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"position out of bounds", return -1);
+
+	if (isl_aff_is_nan(aff))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"cannot get coefficient of NaN", return -1);
+	pos += isl_local_space_offset(aff->ls, type);
+	isl_int_set(*v, aff->v->el[1 + pos]);
+
+	return 0;
+}
+
+/* Return the coefficient of the variable of type "type" at position "pos"
+ * of "aff".
+ */
+__isl_give isl_val *isl_aff_get_coefficient_val(__isl_keep isl_aff *aff,
+	enum isl_dim_type type, int pos)
+{
+	isl_ctx *ctx;
+	isl_val *v;
+
+	if (!aff)
+		return NULL;
+
+	ctx = isl_aff_get_ctx(aff);
+	if (type == isl_dim_out)
+		isl_die(ctx, isl_error_invalid,
+			"output/set dimension does not have a coefficient",
+			return NULL);
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+
+	if (pos >= isl_local_space_dim(aff->ls, type))
+		isl_die(ctx, isl_error_invalid,
+			"position out of bounds", return NULL);
+
+	if (isl_aff_is_nan(aff))
+		return isl_val_nan(ctx);
+	pos += isl_local_space_offset(aff->ls, type);
+	v = isl_val_rat_from_isl_int(ctx, aff->v->el[1 + pos], aff->v->el[0]);
+	return isl_val_normalize(v);
+}
+
+/* Return the sign of the coefficient of the variable of type "type"
+ * at position "pos" of "aff".
+ */
+int isl_aff_coefficient_sgn(__isl_keep isl_aff *aff, enum isl_dim_type type,
+	int pos)
+{
+	isl_ctx *ctx;
+
+	if (!aff)
+		return 0;
+
+	ctx = isl_aff_get_ctx(aff);
+	if (type == isl_dim_out)
+		isl_die(ctx, isl_error_invalid,
+			"output/set dimension does not have a coefficient",
+			return 0);
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+
+	if (pos >= isl_local_space_dim(aff->ls, type))
+		isl_die(ctx, isl_error_invalid,
+			"position out of bounds", return 0);
+
+	pos += isl_local_space_offset(aff->ls, type);
+	return isl_int_sgn(aff->v->el[1 + pos]);
+}
+
+/* Replace the denominator of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_denominator(__isl_take isl_aff *aff, isl_int v)
+{
+	if (!aff)
+		return NULL;
+	if (isl_aff_is_nan(aff))
+		return aff;
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	isl_int_set(aff->v->el[0], v);
+
+	return aff;
+}
+
+/* Replace the numerator of the constant term of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v)
+{
+	if (!aff)
+		return NULL;
+	if (isl_aff_is_nan(aff))
+		return aff;
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	isl_int_set(aff->v->el[1], v);
+
+	return aff;
+}
+
+/* Replace the constant term of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_constant_val(__isl_take isl_aff *aff,
+	__isl_take isl_val *v)
+{
+	if (!aff || !v)
+		goto error;
+
+	if (isl_aff_is_nan(aff)) {
+		isl_val_free(v);
+		return aff;
+	}
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"expecting rational value", goto error);
+
+	if (isl_int_eq(aff->v->el[1], v->n) &&
+	    isl_int_eq(aff->v->el[0], v->d)) {
+		isl_val_free(v);
+		return aff;
+	}
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		goto error;
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		goto error;
+
+	if (isl_int_eq(aff->v->el[0], v->d)) {
+		isl_int_set(aff->v->el[1], v->n);
+	} else if (isl_int_is_one(v->d)) {
+		isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
+	} else {
+		isl_seq_scale(aff->v->el + 1,
+				aff->v->el + 1, v->d, aff->v->size - 1);
+		isl_int_mul(aff->v->el[1], aff->v->el[0], v->n);
+		isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+		aff->v = isl_vec_normalize(aff->v);
+		if (!aff->v)
+			goto error;
+	}
+
+	isl_val_free(v);
+	return aff;
+error:
+	isl_aff_free(aff);
+	isl_val_free(v);
+	return NULL;
+}
+
+/* Add "v" to the constant term of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v)
+{
+	if (isl_int_is_zero(v))
+		return aff;
+
+	if (!aff)
+		return NULL;
+	if (isl_aff_is_nan(aff))
+		return aff;
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	isl_int_addmul(aff->v->el[1], aff->v->el[0], v);
+
+	return aff;
+}
+
+/* Add "v" to the constant term of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_constant_val(__isl_take isl_aff *aff,
+	__isl_take isl_val *v)
+{
+	if (!aff || !v)
+		goto error;
+
+	if (isl_aff_is_nan(aff) || isl_val_is_zero(v)) {
+		isl_val_free(v);
+		return aff;
+	}
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"expecting rational value", goto error);
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		goto error;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		goto error;
+
+	if (isl_int_is_one(v->d)) {
+		isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
+	} else if (isl_int_eq(aff->v->el[0], v->d)) {
+		isl_int_add(aff->v->el[1], aff->v->el[1], v->n);
+		aff->v = isl_vec_normalize(aff->v);
+		if (!aff->v)
+			goto error;
+	} else {
+		isl_seq_scale(aff->v->el + 1,
+				aff->v->el + 1, v->d, aff->v->size - 1);
+		isl_int_addmul(aff->v->el[1], aff->v->el[0], v->n);
+		isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+		aff->v = isl_vec_normalize(aff->v);
+		if (!aff->v)
+			goto error;
+	}
+
+	isl_val_free(v);
+	return aff;
+error:
+	isl_aff_free(aff);
+	isl_val_free(v);
+	return NULL;
+}
+
+__isl_give isl_aff *isl_aff_add_constant_si(__isl_take isl_aff *aff, int v)
+{
+	isl_int t;
+
+	isl_int_init(t);
+	isl_int_set_si(t, v);
+	aff = isl_aff_add_constant(aff, t);
+	isl_int_clear(t);
+
+	return aff;
+}
+
+/* Add "v" to the numerator of the constant term of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_constant_num(__isl_take isl_aff *aff, isl_int v)
+{
+	if (isl_int_is_zero(v))
+		return aff;
+
+	if (!aff)
+		return NULL;
+	if (isl_aff_is_nan(aff))
+		return aff;
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	isl_int_add(aff->v->el[1], aff->v->el[1], v);
+
+	return aff;
+}
+
+/* Add "v" to the numerator of the constant term of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_constant_num_si(__isl_take isl_aff *aff, int v)
+{
+	isl_int t;
+
+	if (v == 0)
+		return aff;
+
+	isl_int_init(t);
+	isl_int_set_si(t, v);
+	aff = isl_aff_add_constant_num(aff, t);
+	isl_int_clear(t);
+
+	return aff;
+}
+
+/* Replace the numerator of the constant term of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_constant_si(__isl_take isl_aff *aff, int v)
+{
+	if (!aff)
+		return NULL;
+	if (isl_aff_is_nan(aff))
+		return aff;
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	isl_int_set_si(aff->v->el[1], v);
+
+	return aff;
+}
+
+/* Replace the numerator of the coefficient of the variable of type "type"
+ * at position "pos" of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, isl_int v)
+{
+	if (!aff)
+		return NULL;
+
+	if (type == isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"output/set dimension does not have a coefficient",
+			return isl_aff_free(aff));
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+
+	if (pos >= isl_local_space_dim(aff->ls, type))
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"position out of bounds", return isl_aff_free(aff));
+
+	if (isl_aff_is_nan(aff))
+		return aff;
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	pos += isl_local_space_offset(aff->ls, type);
+	isl_int_set(aff->v->el[1 + pos], v);
+
+	return aff;
+}
+
+/* Replace the numerator of the coefficient of the variable of type "type"
+ * at position "pos" of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_coefficient_si(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, int v)
+{
+	if (!aff)
+		return NULL;
+
+	if (type == isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"output/set dimension does not have a coefficient",
+			return isl_aff_free(aff));
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+
+	if (pos < 0 || pos >= isl_local_space_dim(aff->ls, type))
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"position out of bounds", return isl_aff_free(aff));
+
+	if (isl_aff_is_nan(aff))
+		return aff;
+	pos += isl_local_space_offset(aff->ls, type);
+	if (isl_int_cmp_si(aff->v->el[1 + pos], v) == 0)
+		return aff;
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	isl_int_set_si(aff->v->el[1 + pos], v);
+
+	return aff;
+}
+
+/* Replace the coefficient of the variable of type "type" at position "pos"
+ * of "aff" by "v".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_set_coefficient_val(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, __isl_take isl_val *v)
+{
+	if (!aff || !v)
+		goto error;
+
+	if (type == isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"output/set dimension does not have a coefficient",
+			goto error);
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+
+	if (pos >= isl_local_space_dim(aff->ls, type))
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"position out of bounds", goto error);
+
+	if (isl_aff_is_nan(aff)) {
+		isl_val_free(v);
+		return aff;
+	}
+	if (!isl_val_is_rat(v))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"expecting rational value", goto error);
+
+	pos += isl_local_space_offset(aff->ls, type);
+	if (isl_int_eq(aff->v->el[1 + pos], v->n) &&
+	    isl_int_eq(aff->v->el[0], v->d)) {
+		isl_val_free(v);
+		return aff;
+	}
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		goto error;
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		goto error;
+
+	if (isl_int_eq(aff->v->el[0], v->d)) {
+		isl_int_set(aff->v->el[1 + pos], v->n);
+	} else if (isl_int_is_one(v->d)) {
+		isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+	} else {
+		isl_seq_scale(aff->v->el + 1,
+				aff->v->el + 1, v->d, aff->v->size - 1);
+		isl_int_mul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+		isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+		aff->v = isl_vec_normalize(aff->v);
+		if (!aff->v)
+			goto error;
+	}
+
+	isl_val_free(v);
+	return aff;
+error:
+	isl_aff_free(aff);
+	isl_val_free(v);
+	return NULL;
+}
+
+/* Add "v" to the coefficient of the variable of type "type"
+ * at position "pos" of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_coefficient(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, isl_int v)
+{
+	if (!aff)
+		return NULL;
+
+	if (type == isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"output/set dimension does not have a coefficient",
+			return isl_aff_free(aff));
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+
+	if (pos >= isl_local_space_dim(aff->ls, type))
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"position out of bounds", return isl_aff_free(aff));
+
+	if (isl_aff_is_nan(aff))
+		return aff;
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	pos += isl_local_space_offset(aff->ls, type);
+	isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v);
+
+	return aff;
+}
+
+/* Add "v" to the coefficient of the variable of type "type"
+ * at position "pos" of "aff".
+ *
+ * A NaN is unaffected by this operation.
+ */
+__isl_give isl_aff *isl_aff_add_coefficient_val(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, __isl_take isl_val *v)
+{
+	if (!aff || !v)
+		goto error;
+
+	if (isl_val_is_zero(v)) {
+		isl_val_free(v);
+		return aff;
+	}
+
+	if (type == isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"output/set dimension does not have a coefficient",
+			goto error);
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+
+	if (pos >= isl_local_space_dim(aff->ls, type))
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"position out of bounds", goto error);
+
+	if (isl_aff_is_nan(aff)) {
+		isl_val_free(v);
+		return aff;
+	}
+	if (!isl_val_is_rat(v))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"expecting rational value", goto error);
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		goto error;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		goto error;
+
+	pos += isl_local_space_offset(aff->ls, type);
+	if (isl_int_is_one(v->d)) {
+		isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+	} else if (isl_int_eq(aff->v->el[0], v->d)) {
+		isl_int_add(aff->v->el[1 + pos], aff->v->el[1 + pos], v->n);
+		aff->v = isl_vec_normalize(aff->v);
+		if (!aff->v)
+			goto error;
+	} else {
+		isl_seq_scale(aff->v->el + 1,
+				aff->v->el + 1, v->d, aff->v->size - 1);
+		isl_int_addmul(aff->v->el[1 + pos], aff->v->el[0], v->n);
+		isl_int_mul(aff->v->el[0], aff->v->el[0], v->d);
+		aff->v = isl_vec_normalize(aff->v);
+		if (!aff->v)
+			goto error;
+	}
+
+	isl_val_free(v);
+	return aff;
+error:
+	isl_aff_free(aff);
+	isl_val_free(v);
+	return NULL;
+}
+
+__isl_give isl_aff *isl_aff_add_coefficient_si(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, int v)
+{
+	isl_int t;
+
+	isl_int_init(t);
+	isl_int_set_si(t, v);
+	aff = isl_aff_add_coefficient(aff, type, pos, t);
+	isl_int_clear(t);
+
+	return aff;
+}
+
+__isl_give isl_aff *isl_aff_get_div(__isl_keep isl_aff *aff, int pos)
+{
+	if (!aff)
+		return NULL;
+
+	return isl_local_space_get_div(aff->ls, pos);
+}
+
+/* Return the negation of "aff".
+ *
+ * As a special case, -NaN = NaN.
+ */
+__isl_give isl_aff *isl_aff_neg(__isl_take isl_aff *aff)
+{
+	if (!aff)
+		return NULL;
+	if (isl_aff_is_nan(aff))
+		return aff;
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	isl_seq_neg(aff->v->el + 1, aff->v->el + 1, aff->v->size - 1);
+
+	return aff;
+}
+
+/* Remove divs from the local space that do not appear in the affine
+ * expression.
+ * We currently only remove divs at the end.
+ * Some intermediate divs may also not appear directly in the affine
+ * expression, but we would also need to check that no other divs are
+ * defined in terms of them.
+ */
+__isl_give isl_aff *isl_aff_remove_unused_divs( __isl_take isl_aff *aff)
+{
+	int pos;
+	int off;
+	int n;
+
+	if (!aff)
+		return NULL;
+
+	n = isl_local_space_dim(aff->ls, isl_dim_div);
+	off = isl_local_space_offset(aff->ls, isl_dim_div);
+
+	pos = isl_seq_last_non_zero(aff->v->el + 1 + off, n) + 1;
+	if (pos == n)
+		return aff;
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->ls = isl_local_space_drop_dims(aff->ls, isl_dim_div, pos, n - pos);
+	aff->v = isl_vec_drop_els(aff->v, 1 + off + pos, n - pos);
+	if (!aff->ls || !aff->v)
+		return isl_aff_free(aff);
+
+	return aff;
+}
+
+/* Given two affine expressions "p" of length p_len (including the
+ * denominator and the constant term) and "subs" of length subs_len,
+ * plug in "subs" for the variable at position "pos".
+ * The variables of "subs" and "p" are assumed to match up to subs_len,
+ * but "p" may have additional variables.
+ * "v" is an initialized isl_int that can be used internally.
+ *
+ * In particular, if "p" represents the expression
+ *
+ *	(a i + g)/m
+ *
+ * with i the variable at position "pos" and "subs" represents the expression
+ *
+ *	f/d
+ *
+ * then the result represents the expression
+ *
+ *	(a f + d g)/(m d)
+ *
+ */
+void isl_seq_substitute(isl_int *p, int pos, isl_int *subs,
+	int p_len, int subs_len, isl_int v)
+{
+	isl_int_set(v, p[1 + pos]);
+	isl_int_set_si(p[1 + pos], 0);
+	isl_seq_combine(p + 1, subs[0], p + 1, v, subs + 1, subs_len - 1);
+	isl_seq_scale(p + subs_len, p + subs_len, subs[0], p_len - subs_len);
+	isl_int_mul(p[0], p[0], subs[0]);
+}
+
+/* Look for any divs in the aff->ls with a denominator equal to one
+ * and plug them into the affine expression and any subsequent divs
+ * that may reference the div.
+ */
+static __isl_give isl_aff *plug_in_integral_divs(__isl_take isl_aff *aff)
+{
+	int i, n;
+	int len;
+	isl_int v;
+	isl_vec *vec;
+	isl_local_space *ls;
+	unsigned pos;
+
+	if (!aff)
+		return NULL;
+
+	n = isl_local_space_dim(aff->ls, isl_dim_div);
+	len = aff->v->size;
+	for (i = 0; i < n; ++i) {
+		if (!isl_int_is_one(aff->ls->div->row[i][0]))
+			continue;
+		ls = isl_local_space_copy(aff->ls);
+		ls = isl_local_space_substitute_seq(ls, isl_dim_div, i,
+				aff->ls->div->row[i], len, i + 1, n - (i + 1));
+		vec = isl_vec_copy(aff->v);
+		vec = isl_vec_cow(vec);
+		if (!ls || !vec)
+			goto error;
+
+		isl_int_init(v);
+
+		pos = isl_local_space_offset(aff->ls, isl_dim_div) + i;
+		isl_seq_substitute(vec->el, pos, aff->ls->div->row[i],
+					len, len, v);
+
+		isl_int_clear(v);
+
+		isl_vec_free(aff->v);
+		aff->v = vec;
+		isl_local_space_free(aff->ls);
+		aff->ls = ls;
+	}
+
+	return aff;
+error:
+	isl_vec_free(vec);
+	isl_local_space_free(ls);
+	return isl_aff_free(aff);
+}
+
+/* Look for any divs j that appear with a unit coefficient inside
+ * the definitions of other divs i and plug them into the definitions
+ * of the divs i.
+ *
+ * In particular, an expression of the form
+ *
+ *	floor((f(..) + floor(g(..)/n))/m)
+ *
+ * is simplified to
+ *
+ *	floor((n * f(..) + g(..))/(n * m))
+ *
+ * This simplification is correct because we can move the expression
+ * f(..) into the inner floor in the original expression to obtain
+ *
+ *	floor(floor((n * f(..) + g(..))/n)/m)
+ *
+ * from which we can derive the simplified expression.
+ */
+static __isl_give isl_aff *plug_in_unit_divs(__isl_take isl_aff *aff)
+{
+	int i, j, n;
+	int off;
+
+	if (!aff)
+		return NULL;
+
+	n = isl_local_space_dim(aff->ls, isl_dim_div);
+	off = isl_local_space_offset(aff->ls, isl_dim_div);
+	for (i = 1; i < n; ++i) {
+		for (j = 0; j < i; ++j) {
+			if (!isl_int_is_one(aff->ls->div->row[i][1 + off + j]))
+				continue;
+			aff->ls = isl_local_space_substitute_seq(aff->ls,
+				isl_dim_div, j, aff->ls->div->row[j],
+				aff->v->size, i, 1);
+			if (!aff->ls)
+				return isl_aff_free(aff);
+		}
+	}
+
+	return aff;
+}
+
+/* Swap divs "a" and "b" in "aff", which is assumed to be non-NULL.
+ *
+ * Even though this function is only called on isl_affs with a single
+ * reference, we are careful to only change aff->v and aff->ls together.
+ */
+static __isl_give isl_aff *swap_div(__isl_take isl_aff *aff, int a, int b)
+{
+	unsigned off = isl_local_space_offset(aff->ls, isl_dim_div);
+	isl_local_space *ls;
+	isl_vec *v;
+
+	ls = isl_local_space_copy(aff->ls);
+	ls = isl_local_space_swap_div(ls, a, b);
+	v = isl_vec_copy(aff->v);
+	v = isl_vec_cow(v);
+	if (!ls || !v)
+		goto error;
+
+	isl_int_swap(v->el[1 + off + a], v->el[1 + off + b]);
+	isl_vec_free(aff->v);
+	aff->v = v;
+	isl_local_space_free(aff->ls);
+	aff->ls = ls;
+
+	return aff;
+error:
+	isl_vec_free(v);
+	isl_local_space_free(ls);
+	return isl_aff_free(aff);
+}
+
+/* Merge divs "a" and "b" in "aff", which is assumed to be non-NULL.
+ *
+ * We currently do not actually remove div "b", but simply add its
+ * coefficient to that of "a" and then zero it out.
+ */
+static __isl_give isl_aff *merge_divs(__isl_take isl_aff *aff, int a, int b)
+{
+	unsigned off = isl_local_space_offset(aff->ls, isl_dim_div);
+
+	if (isl_int_is_zero(aff->v->el[1 + off + b]))
+		return aff;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	isl_int_add(aff->v->el[1 + off + a],
+		    aff->v->el[1 + off + a], aff->v->el[1 + off + b]);
+	isl_int_set_si(aff->v->el[1 + off + b], 0);
+
+	return aff;
+}
+
+/* Sort the divs in the local space of "aff" according to
+ * the comparison function "cmp_row" in isl_local_space.c,
+ * combining the coefficients of identical divs.
+ *
+ * Reordering divs does not change the semantics of "aff",
+ * so there is no need to call isl_aff_cow.
+ * Moreover, this function is currently only called on isl_affs
+ * with a single reference.
+ */
+static __isl_give isl_aff *sort_divs(__isl_take isl_aff *aff)
+{
+	int i, j, n;
+	unsigned off;
+
+	if (!aff)
+		return NULL;
+
+	off = isl_local_space_offset(aff->ls, isl_dim_div);
+	n = isl_aff_dim(aff, isl_dim_div);
+	for (i = 1; i < n; ++i) {
+		for (j = i - 1; j >= 0; --j) {
+			int cmp = isl_mat_cmp_div(aff->ls->div, j, j + 1);
+			if (cmp < 0)
+				break;
+			if (cmp == 0)
+				aff = merge_divs(aff, j, j + 1);
+			else
+				aff = swap_div(aff, j, j + 1);
+			if (!aff)
+				return NULL;
+		}
+	}
+
+	return aff;
+}
+
+/* Normalize the representation of "aff".
+ *
+ * This function should only be called of "new" isl_affs, i.e.,
+ * with only a single reference.  We therefore do not need to
+ * worry about affecting other instances.
+ */
+__isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff)
+{
+	if (!aff)
+		return NULL;
+	aff->v = isl_vec_normalize(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+	aff = plug_in_integral_divs(aff);
+	aff = plug_in_unit_divs(aff);
+	aff = sort_divs(aff);
+	aff = isl_aff_remove_unused_divs(aff);
+	return aff;
+}
+
+/* Given f, return floor(f).
+ * If f is an integer expression, then just return f.
+ * If f is a constant, then return the constant floor(f).
+ * Otherwise, if f = g/m, write g = q m + r,
+ * create a new div d = [r/m] and return the expression q + d.
+ * The coefficients in r are taken to lie between -m/2 and m/2.
+ *
+ * As a special case, floor(NaN) = NaN.
+ */
+__isl_give isl_aff *isl_aff_floor(__isl_take isl_aff *aff)
+{
+	int i;
+	int size;
+	isl_ctx *ctx;
+	isl_vec *div;
+
+	if (!aff)
+		return NULL;
+
+	if (isl_aff_is_nan(aff))
+		return aff;
+	if (isl_int_is_one(aff->v->el[0]))
+		return aff;
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	if (isl_aff_is_cst(aff)) {
+		isl_int_fdiv_q(aff->v->el[1], aff->v->el[1], aff->v->el[0]);
+		isl_int_set_si(aff->v->el[0], 1);
+		return aff;
+	}
+
+	div = isl_vec_copy(aff->v);
+	div = isl_vec_cow(div);
+	if (!div)
+		return isl_aff_free(aff);
+
+	ctx = isl_aff_get_ctx(aff);
+	isl_int_fdiv_q(aff->v->el[0], aff->v->el[0], ctx->two);
+	for (i = 1; i < aff->v->size; ++i) {
+		isl_int_fdiv_r(div->el[i], div->el[i], div->el[0]);
+		isl_int_fdiv_q(aff->v->el[i], aff->v->el[i], div->el[0]);
+		if (isl_int_gt(div->el[i], aff->v->el[0])) {
+			isl_int_sub(div->el[i], div->el[i], div->el[0]);
+			isl_int_add_ui(aff->v->el[i], aff->v->el[i], 1);
+		}
+	}
+
+	aff->ls = isl_local_space_add_div(aff->ls, div);
+	if (!aff->ls)
+		return isl_aff_free(aff);
+
+	size = aff->v->size;
+	aff->v = isl_vec_extend(aff->v, size + 1);
+	if (!aff->v)
+		return isl_aff_free(aff);
+	isl_int_set_si(aff->v->el[0], 1);
+	isl_int_set_si(aff->v->el[size], 1);
+
+	aff = isl_aff_normalize(aff);
+
+	return aff;
+}
+
+/* Compute
+ *
+ *	aff mod m = aff - m * floor(aff/m)
+ */
+__isl_give isl_aff *isl_aff_mod(__isl_take isl_aff *aff, isl_int m)
+{
+	isl_aff *res;
+
+	res = isl_aff_copy(aff);
+	aff = isl_aff_scale_down(aff, m);
+	aff = isl_aff_floor(aff);
+	aff = isl_aff_scale(aff, m);
+	res = isl_aff_sub(res, aff);
+
+	return res;
+}
+
+/* Compute
+ *
+ *	aff mod m = aff - m * floor(aff/m)
+ *
+ * with m an integer value.
+ */
+__isl_give isl_aff *isl_aff_mod_val(__isl_take isl_aff *aff,
+	__isl_take isl_val *m)
+{
+	isl_aff *res;
+
+	if (!aff || !m)
+		goto error;
+
+	if (!isl_val_is_int(m))
+		isl_die(isl_val_get_ctx(m), isl_error_invalid,
+			"expecting integer modulo", goto error);
+
+	res = isl_aff_copy(aff);
+	aff = isl_aff_scale_down_val(aff, isl_val_copy(m));
+	aff = isl_aff_floor(aff);
+	aff = isl_aff_scale_val(aff, m);
+	res = isl_aff_sub(res, aff);
+
+	return res;
+error:
+	isl_aff_free(aff);
+	isl_val_free(m);
+	return NULL;
+}
+
+/* Compute
+ *
+ *	pwaff mod m = pwaff - m * floor(pwaff/m)
+ */
+__isl_give isl_pw_aff *isl_pw_aff_mod(__isl_take isl_pw_aff *pwaff, isl_int m)
+{
+	isl_pw_aff *res;
+
+	res = isl_pw_aff_copy(pwaff);
+	pwaff = isl_pw_aff_scale_down(pwaff, m);
+	pwaff = isl_pw_aff_floor(pwaff);
+	pwaff = isl_pw_aff_scale(pwaff, m);
+	res = isl_pw_aff_sub(res, pwaff);
+
+	return res;
+}
+
+/* Compute
+ *
+ *	pa mod m = pa - m * floor(pa/m)
+ *
+ * with m an integer value.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_mod_val(__isl_take isl_pw_aff *pa,
+	__isl_take isl_val *m)
+{
+	if (!pa || !m)
+		goto error;
+	if (!isl_val_is_int(m))
+		isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+			"expecting integer modulo", goto error);
+	pa = isl_pw_aff_mod(pa, m->n);
+	isl_val_free(m);
+	return pa;
+error:
+	isl_pw_aff_free(pa);
+	isl_val_free(m);
+	return NULL;
+}
+
+/* Given f, return ceil(f).
+ * If f is an integer expression, then just return f.
+ * Otherwise, let f be the expression
+ *
+ *	e/m
+ *
+ * then return
+ *
+ *	floor((e + m - 1)/m)
+ *
+ * As a special case, ceil(NaN) = NaN.
+ */
+__isl_give isl_aff *isl_aff_ceil(__isl_take isl_aff *aff)
+{
+	if (!aff)
+		return NULL;
+
+	if (isl_aff_is_nan(aff))
+		return aff;
+	if (isl_int_is_one(aff->v->el[0]))
+		return aff;
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	isl_int_add(aff->v->el[1], aff->v->el[1], aff->v->el[0]);
+	isl_int_sub_ui(aff->v->el[1], aff->v->el[1], 1);
+	aff = isl_aff_floor(aff);
+
+	return aff;
+}
+
+/* Apply the expansion computed by isl_merge_divs.
+ * The expansion itself is given by "exp" while the resulting
+ * list of divs is given by "div".
+ */
+__isl_give isl_aff *isl_aff_expand_divs( __isl_take isl_aff *aff,
+	__isl_take isl_mat *div, int *exp)
+{
+	int i, j;
+	int old_n_div;
+	int new_n_div;
+	int offset;
+
+	aff = isl_aff_cow(aff);
+	if (!aff || !div)
+		goto error;
+
+	old_n_div = isl_local_space_dim(aff->ls, isl_dim_div);
+	new_n_div = isl_mat_rows(div);
+	if (new_n_div < old_n_div)
+		isl_die(isl_mat_get_ctx(div), isl_error_invalid,
+			"not an expansion", goto error);
+
+	aff->v = isl_vec_extend(aff->v, aff->v->size + new_n_div - old_n_div);
+	if (!aff->v)
+		goto error;
+
+	offset = 1 + isl_local_space_offset(aff->ls, isl_dim_div);
+	j = old_n_div - 1;
+	for (i = new_n_div - 1; i >= 0; --i) {
+		if (j >= 0 && exp[j] == i) {
+			if (i != j)
+				isl_int_swap(aff->v->el[offset + i],
+					     aff->v->el[offset + j]);
+			j--;
+		} else
+			isl_int_set_si(aff->v->el[offset + i], 0);
+	}
+
+	aff->ls = isl_local_space_replace_divs(aff->ls, isl_mat_copy(div));
+	if (!aff->ls)
+		goto error;
+	isl_mat_free(div);
+	return aff;
+error:
+	isl_aff_free(aff);
+	isl_mat_free(div);
+	return NULL;
+}
+
+/* Add two affine expressions that live in the same local space.
+ */
+static __isl_give isl_aff *add_expanded(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2)
+{
+	isl_int gcd, f;
+
+	aff1 = isl_aff_cow(aff1);
+	if (!aff1 || !aff2)
+		goto error;
+
+	aff1->v = isl_vec_cow(aff1->v);
+	if (!aff1->v)
+		goto error;
+
+	isl_int_init(gcd);
+	isl_int_init(f);
+	isl_int_gcd(gcd, aff1->v->el[0], aff2->v->el[0]);
+	isl_int_divexact(f, aff2->v->el[0], gcd);
+	isl_seq_scale(aff1->v->el + 1, aff1->v->el + 1, f, aff1->v->size - 1);
+	isl_int_divexact(f, aff1->v->el[0], gcd);
+	isl_seq_addmul(aff1->v->el + 1, f, aff2->v->el + 1, aff1->v->size - 1);
+	isl_int_divexact(f, aff2->v->el[0], gcd);
+	isl_int_mul(aff1->v->el[0], aff1->v->el[0], f);
+	isl_int_clear(f);
+	isl_int_clear(gcd);
+
+	isl_aff_free(aff2);
+	return aff1;
+error:
+	isl_aff_free(aff1);
+	isl_aff_free(aff2);
+	return NULL;
+}
+
+/* Return the sum of "aff1" and "aff2".
+ *
+ * If either of the two is NaN, then the result is NaN.
+ */
+__isl_give isl_aff *isl_aff_add(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2)
+{
+	isl_ctx *ctx;
+	int *exp1 = NULL;
+	int *exp2 = NULL;
+	isl_mat *div;
+	int n_div1, n_div2;
+
+	if (!aff1 || !aff2)
+		goto error;
+
+	ctx = isl_aff_get_ctx(aff1);
+	if (!isl_space_is_equal(aff1->ls->dim, aff2->ls->dim))
+		isl_die(ctx, isl_error_invalid,
+			"spaces don't match", goto error);
+
+	if (isl_aff_is_nan(aff1)) {
+		isl_aff_free(aff2);
+		return aff1;
+	}
+	if (isl_aff_is_nan(aff2)) {
+		isl_aff_free(aff1);
+		return aff2;
+	}
+
+	n_div1 = isl_aff_dim(aff1, isl_dim_div);
+	n_div2 = isl_aff_dim(aff2, isl_dim_div);
+	if (n_div1 == 0 && n_div2 == 0)
+		return add_expanded(aff1, aff2);
+
+	exp1 = isl_alloc_array(ctx, int, n_div1);
+	exp2 = isl_alloc_array(ctx, int, n_div2);
+	if ((n_div1 && !exp1) || (n_div2 && !exp2))
+		goto error;
+
+	div = isl_merge_divs(aff1->ls->div, aff2->ls->div, exp1, exp2);
+	aff1 = isl_aff_expand_divs(aff1, isl_mat_copy(div), exp1);
+	aff2 = isl_aff_expand_divs(aff2, div, exp2);
+	free(exp1);
+	free(exp2);
+
+	return add_expanded(aff1, aff2);
+error:
+	free(exp1);
+	free(exp2);
+	isl_aff_free(aff1);
+	isl_aff_free(aff2);
+	return NULL;
+}
+
+__isl_give isl_aff *isl_aff_sub(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2)
+{
+	return isl_aff_add(aff1, isl_aff_neg(aff2));
+}
+
+/* Return the result of scaling "aff" by a factor of "f".
+ *
+ * As a special case, f * NaN = NaN.
+ */
+__isl_give isl_aff *isl_aff_scale(__isl_take isl_aff *aff, isl_int f)
+{
+	isl_int gcd;
+
+	if (!aff)
+		return NULL;
+	if (isl_aff_is_nan(aff))
+		return aff;
+
+	if (isl_int_is_one(f))
+		return aff;
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	if (isl_int_is_pos(f) && isl_int_is_divisible_by(aff->v->el[0], f)) {
+		isl_int_divexact(aff->v->el[0], aff->v->el[0], f);
+		return aff;
+	}
+
+	isl_int_init(gcd);
+	isl_int_gcd(gcd, aff->v->el[0], f);
+	isl_int_divexact(aff->v->el[0], aff->v->el[0], gcd);
+	isl_int_divexact(gcd, f, gcd);
+	isl_seq_scale(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1);
+	isl_int_clear(gcd);
+
+	return aff;
+}
+
+/* Multiple "aff" by "v".
+ */
+__isl_give isl_aff *isl_aff_scale_val(__isl_take isl_aff *aff,
+	__isl_take isl_val *v)
+{
+	if (!aff || !v)
+		goto error;
+
+	if (isl_val_is_one(v)) {
+		isl_val_free(v);
+		return aff;
+	}
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"expecting rational factor", goto error);
+
+	aff = isl_aff_scale(aff, v->n);
+	aff = isl_aff_scale_down(aff, v->d);
+
+	isl_val_free(v);
+	return aff;
+error:
+	isl_aff_free(aff);
+	isl_val_free(v);
+	return NULL;
+}
+
+/* Return the result of scaling "aff" down by a factor of "f".
+ *
+ * As a special case, NaN/f = NaN.
+ */
+__isl_give isl_aff *isl_aff_scale_down(__isl_take isl_aff *aff, isl_int f)
+{
+	isl_int gcd;
+
+	if (!aff)
+		return NULL;
+	if (isl_aff_is_nan(aff))
+		return aff;
+
+	if (isl_int_is_one(f))
+		return aff;
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	if (isl_int_is_zero(f))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"cannot scale down by zero", return isl_aff_free(aff));
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	isl_int_init(gcd);
+	isl_seq_gcd(aff->v->el + 1, aff->v->size - 1, &gcd);
+	isl_int_gcd(gcd, gcd, f);
+	isl_seq_scale_down(aff->v->el + 1, aff->v->el + 1, gcd, aff->v->size - 1);
+	isl_int_divexact(gcd, f, gcd);
+	isl_int_mul(aff->v->el[0], aff->v->el[0], gcd);
+	isl_int_clear(gcd);
+
+	return aff;
+}
+
+/* Divide "aff" by "v".
+ */
+__isl_give isl_aff *isl_aff_scale_down_val(__isl_take isl_aff *aff,
+	__isl_take isl_val *v)
+{
+	if (!aff || !v)
+		goto error;
+
+	if (isl_val_is_one(v)) {
+		isl_val_free(v);
+		return aff;
+	}
+
+	if (!isl_val_is_rat(v))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"expecting rational factor", goto error);
+	if (!isl_val_is_pos(v))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"factor needs to be positive", goto error);
+
+	aff = isl_aff_scale(aff, v->d);
+	aff = isl_aff_scale_down(aff, v->n);
+
+	isl_val_free(v);
+	return aff;
+error:
+	isl_aff_free(aff);
+	isl_val_free(v);
+	return NULL;
+}
+
+__isl_give isl_aff *isl_aff_scale_down_ui(__isl_take isl_aff *aff, unsigned f)
+{
+	isl_int v;
+
+	if (f == 1)
+		return aff;
+
+	isl_int_init(v);
+	isl_int_set_ui(v, f);
+	aff = isl_aff_scale_down(aff, v);
+	isl_int_clear(v);
+
+	return aff;
+}
+
+__isl_give isl_aff *isl_aff_set_dim_name(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned pos, const char *s)
+{
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+	if (type == isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"cannot set name of output/set dimension",
+			return isl_aff_free(aff));
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+	aff->ls = isl_local_space_set_dim_name(aff->ls, type, pos, s);
+	if (!aff->ls)
+		return isl_aff_free(aff);
+
+	return aff;
+}
+
+__isl_give isl_aff *isl_aff_set_dim_id(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned pos, __isl_take isl_id *id)
+{
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		goto error;
+	if (type == isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"cannot set name of output/set dimension",
+			goto error);
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+	aff->ls = isl_local_space_set_dim_id(aff->ls, type, pos, id);
+	if (!aff->ls)
+		return isl_aff_free(aff);
+
+	return aff;
+error:
+	isl_id_free(id);
+	isl_aff_free(aff);
+	return NULL;
+}
+
+/* Replace the identifier of the input tuple of "aff" by "id".
+ * type is currently required to be equal to isl_dim_in
+ */
+__isl_give isl_aff *isl_aff_set_tuple_id(__isl_take isl_aff *aff,
+	enum isl_dim_type type, __isl_take isl_id *id)
+{
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		goto error;
+	if (type != isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"cannot only set id of input tuple", goto error);
+	aff->ls = isl_local_space_set_tuple_id(aff->ls, isl_dim_set, id);
+	if (!aff->ls)
+		return isl_aff_free(aff);
+
+	return aff;
+error:
+	isl_id_free(id);
+	isl_aff_free(aff);
+	return NULL;
+}
+
+/* Exploit the equalities in "eq" to simplify the affine expression
+ * and the expressions of the integer divisions in the local space.
+ * The integer divisions in this local space are assumed to appear
+ * as regular dimensions in "eq".
+ */
+static __isl_give isl_aff *isl_aff_substitute_equalities_lifted(
+	__isl_take isl_aff *aff, __isl_take isl_basic_set *eq)
+{
+	int i, j;
+	unsigned total;
+	unsigned n_div;
+
+	if (!eq)
+		goto error;
+	if (eq->n_eq == 0) {
+		isl_basic_set_free(eq);
+		return aff;
+	}
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		goto error;
+
+	aff->ls = isl_local_space_substitute_equalities(aff->ls,
+							isl_basic_set_copy(eq));
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->ls || !aff->v)
+		goto error;
+
+	total = 1 + isl_space_dim(eq->dim, isl_dim_all);
+	n_div = eq->n_div;
+	for (i = 0; i < eq->n_eq; ++i) {
+		j = isl_seq_last_non_zero(eq->eq[i], total + n_div);
+		if (j < 0 || j == 0 || j >= total)
+			continue;
+
+		isl_seq_elim(aff->v->el + 1, eq->eq[i], j, total,
+				&aff->v->el[0]);
+	}
+
+	isl_basic_set_free(eq);
+	aff = isl_aff_normalize(aff);
+	return aff;
+error:
+	isl_basic_set_free(eq);
+	isl_aff_free(aff);
+	return NULL;
+}
+
+/* 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)
+{
+	int n_div;
+
+	if (!aff || !eq)
+		goto error;
+	n_div = isl_local_space_dim(aff->ls, isl_dim_div);
+	if (n_div > 0)
+		eq = isl_basic_set_add_dims(eq, isl_dim_set, n_div);
+	return isl_aff_substitute_equalities_lifted(aff, eq);
+error:
+	isl_basic_set_free(eq);
+	isl_aff_free(aff);
+	return NULL;
+}
+
+/* Look for equalities among the variables shared by context and aff
+ * and the integer divisions of aff, if any.
+ * The equalities are then used to eliminate coefficients and/or integer
+ * divisions from aff.
+ */
+__isl_give isl_aff *isl_aff_gist(__isl_take isl_aff *aff,
+	__isl_take isl_set *context)
+{
+	isl_basic_set *hull;
+	int n_div;
+
+	if (!aff)
+		goto error;
+	n_div = isl_local_space_dim(aff->ls, isl_dim_div);
+	if (n_div > 0) {
+		isl_basic_set *bset;
+		isl_local_space *ls;
+		context = isl_set_add_dims(context, isl_dim_set, n_div);
+		ls = isl_aff_get_domain_local_space(aff);
+		bset = isl_basic_set_from_local_space(ls);
+		bset = isl_basic_set_lift(bset);
+		bset = isl_basic_set_flatten(bset);
+		context = isl_set_intersect(context,
+					    isl_set_from_basic_set(bset));
+	}
+
+	hull = isl_set_affine_hull(context);
+	return isl_aff_substitute_equalities_lifted(aff, hull);
+error:
+	isl_aff_free(aff);
+	isl_set_free(context);
+	return NULL;
+}
+
+__isl_give isl_aff *isl_aff_gist_params(__isl_take isl_aff *aff,
+	__isl_take isl_set *context)
+{
+	isl_set *dom_context = isl_set_universe(isl_aff_get_domain_space(aff));
+	dom_context = isl_set_intersect_params(dom_context, context);
+	return isl_aff_gist(aff, dom_context);
+}
+
+/* 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.
+ *
+ * If "aff" is NaN, then it is not non-negative (it's not negative either).
+ */
+static __isl_give isl_basic_set *aff_nonneg_basic_set(
+	__isl_take isl_aff *aff, int rational)
+{
+	isl_constraint *ineq;
+	isl_basic_set *bset;
+
+	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);
+	}
+
+	ineq = isl_inequality_from_aff(aff);
+
+	bset = isl_basic_set_from_constraint(ineq);
+	if (rational)
+		bset = isl_basic_set_set_rational(bset);
+	bset = isl_basic_set_simplify(bset);
+	return bset;
+}
+
+/* Return a basic set containing those elements in the space
+ * of aff where it is non-negative.
+ */
+__isl_give isl_basic_set *isl_aff_nonneg_basic_set(__isl_take isl_aff *aff)
+{
+	return aff_nonneg_basic_set(aff, 0);
+}
+
+/* Return a basic set containing those elements in the domain space
+ * of aff where it is negative.
+ */
+__isl_give isl_basic_set *isl_aff_neg_basic_set(__isl_take isl_aff *aff)
+{
+	aff = isl_aff_neg(aff);
+	aff = isl_aff_add_constant_num_si(aff, -1);
+	return isl_aff_nonneg_basic_set(aff);
+}
+
+/* Return a basic set containing those elements in the space
+ * of aff where it is zero.
+ * If "rational" is set, then return a rational basic set.
+ *
+ * If "aff" is NaN, then it is not zero.
+ */
+static __isl_give isl_basic_set *aff_zero_basic_set(__isl_take isl_aff *aff,
+	int rational)
+{
+	isl_constraint *ineq;
+	isl_basic_set *bset;
+
+	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);
+	}
+
+	ineq = isl_equality_from_aff(aff);
+
+	bset = isl_basic_set_from_constraint(ineq);
+	if (rational)
+		bset = isl_basic_set_set_rational(bset);
+	bset = isl_basic_set_simplify(bset);
+	return bset;
+}
+
+/* Return a basic set containing those elements in the space
+ * of aff where it is zero.
+ */
+__isl_give isl_basic_set *isl_aff_zero_basic_set(__isl_take isl_aff *aff)
+{
+	return aff_zero_basic_set(aff, 0);
+}
+
+/* Return a basic set containing those elements in the shared space
+ * of aff1 and aff2 where aff1 is greater than or equal to aff2.
+ */
+__isl_give isl_basic_set *isl_aff_ge_basic_set(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2)
+{
+	aff1 = isl_aff_sub(aff1, aff2);
+
+	return isl_aff_nonneg_basic_set(aff1);
+}
+
+/* Return a basic set containing those elements in the shared space
+ * of aff1 and aff2 where aff1 is smaller than or equal to aff2.
+ */
+__isl_give isl_basic_set *isl_aff_le_basic_set(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2)
+{
+	return isl_aff_ge_basic_set(aff2, aff1);
+}
+
+__isl_give isl_aff *isl_aff_add_on_domain(__isl_keep isl_set *dom,
+	__isl_take isl_aff *aff1, __isl_take isl_aff *aff2)
+{
+	aff1 = isl_aff_add(aff1, aff2);
+	aff1 = isl_aff_gist(aff1, isl_set_copy(dom));
+	return aff1;
+}
+
+int isl_aff_is_empty(__isl_keep isl_aff *aff)
+{
+	if (!aff)
+		return -1;
+
+	return 0;
+}
+
+/* Check whether the given affine expression has non-zero coefficient
+ * 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 in the affine expression.
+ */
+int isl_aff_involves_dims(__isl_keep isl_aff *aff,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	int i;
+	isl_ctx *ctx;
+	int *active = NULL;
+	int involves = 0;
+
+	if (!aff)
+		return -1;
+	if (n == 0)
+		return 0;
+
+	ctx = isl_aff_get_ctx(aff);
+	if (first + n > isl_aff_dim(aff, type))
+		isl_die(ctx, isl_error_invalid,
+			"range out of bounds", return -1);
+
+	active = isl_local_space_get_active(aff->ls, aff->v->el + 2);
+	if (!active)
+		goto error;
+
+	first += isl_local_space_offset(aff->ls, type) - 1;
+	for (i = 0; i < n; ++i)
+		if (active[first + i]) {
+			involves = 1;
+			break;
+		}
+
+	free(active);
+
+	return involves;
+error:
+	free(active);
+	return -1;
+}
+
+__isl_give isl_aff *isl_aff_drop_dims(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	isl_ctx *ctx;
+
+	if (!aff)
+		return NULL;
+	if (type == isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"cannot drop output/set dimension",
+			return isl_aff_free(aff));
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+	if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type))
+		return aff;
+
+	ctx = isl_aff_get_ctx(aff);
+	if (first + n > isl_local_space_dim(aff->ls, type))
+		isl_die(ctx, isl_error_invalid, "range out of bounds",
+			return isl_aff_free(aff));
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->ls = isl_local_space_drop_dims(aff->ls, type, first, n);
+	if (!aff->ls)
+		return isl_aff_free(aff);
+
+	first += 1 + isl_local_space_offset(aff->ls, type);
+	aff->v = isl_vec_drop_els(aff->v, first, n);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	return aff;
+}
+
+/* Project the domain of the affine expression onto its parameter space.
+ * The affine expression may not involve any of the domain dimensions.
+ */
+__isl_give isl_aff *isl_aff_project_domain_on_params(__isl_take isl_aff *aff)
+{
+	isl_space *space;
+	unsigned n;
+	int involves;
+
+	n = isl_aff_dim(aff, isl_dim_in);
+	involves = isl_aff_involves_dims(aff, isl_dim_in, 0, n);
+	if (involves < 0)
+		return isl_aff_free(aff);
+	if (involves)
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+		    "affine expression involves some of the domain dimensions",
+		    return isl_aff_free(aff));
+	aff = isl_aff_drop_dims(aff, isl_dim_in, 0, n);
+	space = isl_aff_get_domain_space(aff);
+	space = isl_space_params(space);
+	aff = isl_aff_reset_domain_space(aff, space);
+	return aff;
+}
+
+__isl_give isl_aff *isl_aff_insert_dims(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	isl_ctx *ctx;
+
+	if (!aff)
+		return NULL;
+	if (type == isl_dim_out)
+		isl_die(aff->v->ctx, isl_error_invalid,
+			"cannot insert output/set dimensions",
+			return isl_aff_free(aff));
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+	if (n == 0 && !isl_local_space_is_named_or_nested(aff->ls, type))
+		return aff;
+
+	ctx = isl_aff_get_ctx(aff);
+	if (first > isl_local_space_dim(aff->ls, type))
+		isl_die(ctx, isl_error_invalid, "position out of bounds",
+			return isl_aff_free(aff));
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->ls = isl_local_space_insert_dims(aff->ls, type, first, n);
+	if (!aff->ls)
+		return isl_aff_free(aff);
+
+	first += 1 + isl_local_space_offset(aff->ls, type);
+	aff->v = isl_vec_insert_zero_els(aff->v, first, n);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	return aff;
+}
+
+__isl_give isl_aff *isl_aff_add_dims(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned n)
+{
+	unsigned pos;
+
+	pos = isl_aff_dim(aff, type);
+
+	return isl_aff_insert_dims(aff, type, pos, n);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_add_dims(__isl_take isl_pw_aff *pwaff,
+	enum isl_dim_type type, unsigned n)
+{
+	unsigned pos;
+
+	pos = isl_pw_aff_dim(pwaff, type);
+
+	return isl_pw_aff_insert_dims(pwaff, type, pos, n);
+}
+
+/* Move the "n" dimensions of "src_type" starting at "src_pos" of "aff"
+ * to dimensions of "dst_type" at "dst_pos".
+ *
+ * We only support moving input dimensions to parameters and vice versa.
+ */
+__isl_give isl_aff *isl_aff_move_dims(__isl_take isl_aff *aff,
+	enum isl_dim_type dst_type, unsigned dst_pos,
+	enum isl_dim_type src_type, unsigned src_pos, unsigned n)
+{
+	unsigned g_dst_pos;
+	unsigned g_src_pos;
+
+	if (!aff)
+		return NULL;
+	if (n == 0 &&
+	    !isl_local_space_is_named_or_nested(aff->ls, src_type) &&
+	    !isl_local_space_is_named_or_nested(aff->ls, dst_type))
+		return aff;
+
+	if (dst_type == isl_dim_out || src_type == isl_dim_out)
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"cannot move output/set dimension", isl_aff_free(aff));
+	if (dst_type == isl_dim_div || src_type == isl_dim_div)
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"cannot move divs", isl_aff_free(aff));
+	if (dst_type == isl_dim_in)
+		dst_type = isl_dim_set;
+	if (src_type == isl_dim_in)
+		src_type = isl_dim_set;
+
+	if (src_pos + n > isl_local_space_dim(aff->ls, src_type))
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"range out of bounds", isl_aff_free(aff));
+	if (dst_type == src_type)
+		isl_die(isl_aff_get_ctx(aff), isl_error_unsupported,
+			"moving dims within the same type not supported",
+			isl_aff_free(aff));
+
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	g_src_pos = 1 + isl_local_space_offset(aff->ls, src_type) + src_pos;
+	g_dst_pos = 1 + isl_local_space_offset(aff->ls, dst_type) + dst_pos;
+	if (dst_type > src_type)
+		g_dst_pos -= n;
+
+	aff->v = isl_vec_move_els(aff->v, g_dst_pos, g_src_pos, n);
+	aff->ls = isl_local_space_move_dims(aff->ls, dst_type, dst_pos,
+						src_type, src_pos, n);
+	if (!aff->v || !aff->ls)
+		return isl_aff_free(aff);
+
+	aff = sort_divs(aff);
+
+	return aff;
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_from_aff(__isl_take isl_aff *aff)
+{
+	isl_set *dom = isl_set_universe(isl_aff_get_domain_space(aff));
+	return isl_pw_aff_alloc(dom, aff);
+}
+
+#undef PW
+#define PW isl_pw_aff
+#undef EL
+#define EL isl_aff
+#undef EL_IS_ZERO
+#define EL_IS_ZERO is_empty
+#undef ZERO
+#define ZERO empty
+#undef IS_ZERO
+#define IS_ZERO is_empty
+#undef FIELD
+#define FIELD aff
+#undef DEFAULT_IS_ZERO
+#define DEFAULT_IS_ZERO 0
+
+#define NO_EVAL
+#define NO_OPT
+#define NO_LIFT
+#define NO_MORPH
+
+#include <isl_pw_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,
+				    __isl_take isl_pw_aff *pwaff2))
+{
+	if (!pwaff1 || !pwaff2)
+		goto error;
+	if (isl_space_match(pwaff1->dim, isl_dim_param,
+			  pwaff2->dim, isl_dim_param))
+		return fn(pwaff1, pwaff2);
+	if (!isl_space_has_named_params(pwaff1->dim) ||
+	    !isl_space_has_named_params(pwaff2->dim))
+		isl_die(isl_pw_aff_get_ctx(pwaff1), isl_error_invalid,
+			"unaligned unnamed parameters", goto error);
+	pwaff1 = isl_pw_aff_align_params(pwaff1, isl_pw_aff_get_space(pwaff2));
+	pwaff2 = isl_pw_aff_align_params(pwaff2, isl_pw_aff_get_space(pwaff1));
+	return fn(pwaff1, pwaff2);
+error:
+	isl_pw_aff_free(pwaff1);
+	isl_pw_aff_free(pwaff2);
+	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)
+ * of those of pwaff1 and pwaff2.  If only one of pwaff1 or pwaff2
+ * is defined on a given cell, then the associated expression
+ * is the defined one.
+ */
+static __isl_give isl_pw_aff *pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2,
+	__isl_give isl_basic_set *(*cmp)(__isl_take isl_aff *aff1,
+					__isl_take isl_aff *aff2))
+{
+	int i, j, n;
+	isl_pw_aff *res;
+	isl_ctx *ctx;
+	isl_set *set;
+
+	if (!pwaff1 || !pwaff2)
+		goto error;
+
+	ctx = isl_space_get_ctx(pwaff1->dim);
+	if (!isl_space_is_equal(pwaff1->dim, pwaff2->dim))
+		isl_die(ctx, isl_error_invalid,
+			"arguments should live in same space", goto error);
+
+	if (isl_pw_aff_is_empty(pwaff1)) {
+		isl_pw_aff_free(pwaff1);
+		return pwaff2;
+	}
+
+	if (isl_pw_aff_is_empty(pwaff2)) {
+		isl_pw_aff_free(pwaff2);
+		return pwaff1;
+	}
+
+	n = 2 * (pwaff1->n + 1) * (pwaff2->n + 1);
+	res = isl_pw_aff_alloc_size(isl_space_copy(pwaff1->dim), n);
+
+	for (i = 0; i < pwaff1->n; ++i) {
+		set = isl_set_copy(pwaff1->p[i].set);
+		for (j = 0; j < pwaff2->n; ++j) {
+			struct isl_set *common;
+			isl_set *better;
+
+			common = isl_set_intersect(
+					isl_set_copy(pwaff1->p[i].set),
+					isl_set_copy(pwaff2->p[j].set));
+			better = isl_set_from_basic_set(cmp(
+					isl_aff_copy(pwaff2->p[j].aff),
+					isl_aff_copy(pwaff1->p[i].aff)));
+			better = isl_set_intersect(common, better);
+			if (isl_set_plain_is_empty(better)) {
+				isl_set_free(better);
+				continue;
+			}
+			set = isl_set_subtract(set, isl_set_copy(better));
+
+			res = isl_pw_aff_add_piece(res, better,
+						isl_aff_copy(pwaff2->p[j].aff));
+		}
+		res = isl_pw_aff_add_piece(res, set,
+						isl_aff_copy(pwaff1->p[i].aff));
+	}
+
+	for (j = 0; j < pwaff2->n; ++j) {
+		set = isl_set_copy(pwaff2->p[j].set);
+		for (i = 0; i < pwaff1->n; ++i)
+			set = isl_set_subtract(set,
+					isl_set_copy(pwaff1->p[i].set));
+		res = isl_pw_aff_add_piece(res, set,
+						isl_aff_copy(pwaff2->p[j].aff));
+	}
+
+	isl_pw_aff_free(pwaff1);
+	isl_pw_aff_free(pwaff2);
+
+	return res;
+error:
+	isl_pw_aff_free(pwaff1);
+	isl_pw_aff_free(pwaff2);
+	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 maximum of those of pwaff1
+ * and pwaff2.  If only one of pwaff1 or pwaff2 is defined on a given
+ * cell, then the associated expression is the defined one.
+ */
+static __isl_give isl_pw_aff *pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return pw_aff_union_opt(pwaff1, pwaff2, &isl_aff_ge_basic_set);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_union_max(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2,
+							&pw_aff_union_max);
+}
+
+/* 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 minimum of those of pwaff1
+ * and pwaff2.  If only one of pwaff1 or pwaff2 is defined on a given
+ * cell, then the associated expression is the defined one.
+ */
+static __isl_give isl_pw_aff *pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return pw_aff_union_opt(pwaff1, pwaff2, &isl_aff_le_basic_set);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_union_min(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2,
+							&pw_aff_union_min);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2, int max)
+{
+	if (max)
+		return isl_pw_aff_union_max(pwaff1, pwaff2);
+	else
+		return isl_pw_aff_union_min(pwaff1, pwaff2);
+}
+
+/* Construct a map with as domain the domain of pwaff and
+ * one-dimensional range corresponding to the affine expressions.
+ */
+static __isl_give isl_map *map_from_pw_aff(__isl_take isl_pw_aff *pwaff)
+{
+	int i;
+	isl_space *dim;
+	isl_map *map;
+
+	if (!pwaff)
+		return NULL;
+
+	dim = isl_pw_aff_get_space(pwaff);
+	map = isl_map_empty(dim);
+
+	for (i = 0; i < pwaff->n; ++i) {
+		isl_basic_map *bmap;
+		isl_map *map_i;
+
+		bmap = isl_basic_map_from_aff(isl_aff_copy(pwaff->p[i].aff));
+		map_i = isl_map_from_basic_map(bmap);
+		map_i = isl_map_intersect_domain(map_i,
+						isl_set_copy(pwaff->p[i].set));
+		map = isl_map_union_disjoint(map, map_i);
+	}
+
+	isl_pw_aff_free(pwaff);
+
+	return map;
+}
+
+/* Construct a map with as domain the domain of pwaff and
+ * one-dimensional range corresponding to the affine expressions.
+ */
+__isl_give isl_map *isl_map_from_pw_aff(__isl_take isl_pw_aff *pwaff)
+{
+	if (!pwaff)
+		return NULL;
+	if (isl_space_is_set(pwaff->dim))
+		isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
+			"space of input is not a map", goto error);
+	return map_from_pw_aff(pwaff);
+error:
+	isl_pw_aff_free(pwaff);
+	return NULL;
+}
+
+/* Construct a one-dimensional set with as parameter domain
+ * the domain of pwaff and the single set dimension
+ * corresponding to the affine expressions.
+ */
+__isl_give isl_set *isl_set_from_pw_aff(__isl_take isl_pw_aff *pwaff)
+{
+	if (!pwaff)
+		return NULL;
+	if (!isl_space_is_set(pwaff->dim))
+		isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
+			"space of input is not a set", goto error);
+	return map_from_pw_aff(pwaff);
+error:
+	isl_pw_aff_free(pwaff);
+	return NULL;
+}
+
+/* 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).
+ *
+ * The pieces with a NaN never belong to the result since
+ * NaN is neither zero nor non-zero.
+ */
+static __isl_give isl_set *pw_aff_zero_set(__isl_take isl_pw_aff *pwaff,
+	int complement)
+{
+	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, *zero;
+		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);
+		set_i = isl_set_copy(pwaff->p[i].set);
+		if (complement)
+			set_i = isl_set_subtract(set_i, zero);
+		else
+			set_i = isl_set_intersect(set_i, zero);
+		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.
+ */
+__isl_give isl_set *isl_pw_aff_zero_set(__isl_take isl_pw_aff *pwaff)
+{
+	return pw_aff_zero_set(pwaff, 0);
+}
+
+/* Return a set containing those elements in the domain
+ * of pwaff where it is not zero.
+ */
+__isl_give isl_set *isl_pw_aff_non_zero_set(__isl_take isl_pw_aff *pwaff)
+{
+	return pw_aff_zero_set(pwaff, 1);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of pwaff1 and pwaff2 where pwaff1 is greater than (or equal) to pwaff2.
+ *
+ * We compute the difference on the shared domain and then construct
+ * the set of values where this difference is non-negative.
+ * If strict is set, we first subtract 1 from the difference.
+ * If equal is set, we only return the elements where pwaff1 and pwaff2
+ * are equal.
+ */
+static __isl_give isl_set *pw_aff_gte_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2, int strict, int equal)
+{
+	isl_set *set1, *set2;
+
+	set1 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff1));
+	set2 = isl_pw_aff_domain(isl_pw_aff_copy(pwaff2));
+	set1 = isl_set_intersect(set1, set2);
+	pwaff1 = isl_pw_aff_intersect_domain(pwaff1, isl_set_copy(set1));
+	pwaff2 = isl_pw_aff_intersect_domain(pwaff2, isl_set_copy(set1));
+	pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_neg(pwaff2));
+
+	if (strict) {
+		isl_space *dim = isl_set_get_space(set1);
+		isl_aff *aff;
+		aff = isl_aff_zero_on_domain(isl_local_space_from_space(dim));
+		aff = isl_aff_add_constant_si(aff, -1);
+		pwaff1 = isl_pw_aff_add(pwaff1, isl_pw_aff_alloc(set1, aff));
+	} else
+		isl_set_free(set1);
+
+	if (equal)
+		return isl_pw_aff_zero_set(pwaff1);
+	return isl_pw_aff_nonneg_set(pwaff1);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of pwaff1 and pwaff2 where pwaff1 is equal to pwaff2.
+ */
+static __isl_give isl_set *pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return pw_aff_gte_set(pwaff1, pwaff2, 0, 1);
+}
+
+__isl_give isl_set *isl_pw_aff_eq_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_eq_set);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of pwaff1 and pwaff2 where pwaff1 is greater than or equal to pwaff2.
+ */
+static __isl_give isl_set *pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return pw_aff_gte_set(pwaff1, pwaff2, 0, 0);
+}
+
+__isl_give isl_set *isl_pw_aff_ge_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ge_set);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of pwaff1 and pwaff2 where pwaff1 is strictly greater than pwaff2.
+ */
+static __isl_give isl_set *pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return pw_aff_gte_set(pwaff1, pwaff2, 1, 0);
+}
+
+__isl_give isl_set *isl_pw_aff_gt_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_gt_set);
+}
+
+__isl_give isl_set *isl_pw_aff_le_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_ge_set(pwaff2, pwaff1);
+}
+
+__isl_give isl_set *isl_pw_aff_lt_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_gt_set(pwaff2, pwaff1);
+}
+
+/* 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.
+ */
+static __isl_give isl_set *pw_aff_list_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2,
+	__isl_give isl_set *(*fn)(__isl_take isl_pw_aff *pwaff1,
+				    __isl_take isl_pw_aff *pwaff2))
+{
+	int i, j;
+	isl_ctx *ctx;
+	isl_set *set;
+
+	if (!list1 || !list2)
+		goto error;
+
+	ctx = isl_pw_aff_list_get_ctx(list1);
+	if (list1->n < 1 || list2->n < 1)
+		isl_die(ctx, isl_error_invalid,
+			"list should contain at least one element", goto error);
+
+	set = isl_set_universe(isl_pw_aff_get_domain_space(list1->p[0]));
+	for (i = 0; i < list1->n; ++i)
+		for (j = 0; j < list2->n; ++j) {
+			isl_set *set_ij;
+
+			set_ij = fn(isl_pw_aff_copy(list1->p[i]),
+				    isl_pw_aff_copy(list2->p[j]));
+			set = isl_set_intersect(set, set_ij);
+		}
+
+	isl_pw_aff_list_free(list1);
+	isl_pw_aff_list_free(list2);
+	return set;
+error:
+	isl_pw_aff_list_free(list1);
+	isl_pw_aff_list_free(list2);
+	return NULL;
+}
+
+/* Return a set containing those elements in the shared domain
+ * of the elements of list1 and list2 where each element in list1
+ * is equal to each element in list2.
+ */
+__isl_give isl_set *isl_pw_aff_list_eq_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2)
+{
+	return pw_aff_list_set(list1, list2, &isl_pw_aff_eq_set);
+}
+
+__isl_give isl_set *isl_pw_aff_list_ne_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2)
+{
+	return pw_aff_list_set(list1, list2, &isl_pw_aff_ne_set);
+}
+
+/* Return a set containing those elements in the shared domain
+ * of the elements of list1 and list2 where each element in list1
+ * is less than or equal to each element in list2.
+ */
+__isl_give isl_set *isl_pw_aff_list_le_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2)
+{
+	return pw_aff_list_set(list1, list2, &isl_pw_aff_le_set);
+}
+
+__isl_give isl_set *isl_pw_aff_list_lt_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2)
+{
+	return pw_aff_list_set(list1, list2, &isl_pw_aff_lt_set);
+}
+
+__isl_give isl_set *isl_pw_aff_list_ge_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2)
+{
+	return pw_aff_list_set(list1, list2, &isl_pw_aff_ge_set);
+}
+
+__isl_give isl_set *isl_pw_aff_list_gt_set(__isl_take isl_pw_aff_list *list1,
+	__isl_take isl_pw_aff_list *list2)
+{
+	return pw_aff_list_set(list1, list2, &isl_pw_aff_gt_set);
+}
+
+
+/* Return a set containing those elements in the shared domain
+ * of pwaff1 and pwaff2 where pwaff1 is not equal to pwaff2.
+ */
+static __isl_give isl_set *pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	isl_set *set_lt, *set_gt;
+
+	set_lt = isl_pw_aff_lt_set(isl_pw_aff_copy(pwaff1),
+				   isl_pw_aff_copy(pwaff2));
+	set_gt = isl_pw_aff_gt_set(pwaff1, pwaff2);
+	return isl_set_union_disjoint(set_lt, set_gt);
+}
+
+__isl_give isl_set *isl_pw_aff_ne_set(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return align_params_pw_pw_set_and(pwaff1, pwaff2, &pw_aff_ne_set);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
+	isl_int v)
+{
+	int i;
+
+	if (isl_int_is_one(v))
+		return pwaff;
+	if (!isl_int_is_pos(v))
+		isl_die(isl_pw_aff_get_ctx(pwaff), isl_error_invalid,
+			"factor needs to be positive",
+			return isl_pw_aff_free(pwaff));
+	pwaff = isl_pw_aff_cow(pwaff);
+	if (!pwaff)
+		return NULL;
+	if (pwaff->n == 0)
+		return pwaff;
+
+	for (i = 0; i < pwaff->n; ++i) {
+		pwaff->p[i].aff = isl_aff_scale_down(pwaff->p[i].aff, v);
+		if (!pwaff->p[i].aff)
+			return isl_pw_aff_free(pwaff);
+	}
+
+	return pwaff;
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_floor(__isl_take isl_pw_aff *pwaff)
+{
+	int i;
+
+	pwaff = isl_pw_aff_cow(pwaff);
+	if (!pwaff)
+		return NULL;
+	if (pwaff->n == 0)
+		return pwaff;
+
+	for (i = 0; i < pwaff->n; ++i) {
+		pwaff->p[i].aff = isl_aff_floor(pwaff->p[i].aff);
+		if (!pwaff->p[i].aff)
+			return isl_pw_aff_free(pwaff);
+	}
+
+	return pwaff;
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_ceil(__isl_take isl_pw_aff *pwaff)
+{
+	int i;
+
+	pwaff = isl_pw_aff_cow(pwaff);
+	if (!pwaff)
+		return NULL;
+	if (pwaff->n == 0)
+		return pwaff;
+
+	for (i = 0; i < pwaff->n; ++i) {
+		pwaff->p[i].aff = isl_aff_ceil(pwaff->p[i].aff);
+		if (!pwaff->p[i].aff)
+			return isl_pw_aff_free(pwaff);
+	}
+
+	return pwaff;
+}
+
+/* Assuming that "cond1" and "cond2" are disjoint,
+ * return an affine expression that is equal to pwaff1 on cond1
+ * and to pwaff2 on cond2.
+ */
+static __isl_give isl_pw_aff *isl_pw_aff_select(
+	__isl_take isl_set *cond1, __isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_set *cond2, __isl_take isl_pw_aff *pwaff2)
+{
+	pwaff1 = isl_pw_aff_intersect_domain(pwaff1, cond1);
+	pwaff2 = isl_pw_aff_intersect_domain(pwaff2, cond2);
+
+	return isl_pw_aff_add_disjoint(pwaff1, pwaff2);
+}
+
+/* Return an affine expression that is equal to pwaff_true for elements
+ * where "cond" is non-zero and to pwaff_false for elements where "cond"
+ * is zero.
+ * That is, return cond ? pwaff_true : pwaff_false;
+ *
+ * If "cond" involves and NaN, then we conservatively return a NaN
+ * on its entire domain.  In principle, we could consider the pieces
+ * where it is NaN separately from those where it is not.
+ */
+__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)
+{
+	isl_set *cond_true, *cond_false;
+
+	if (!cond)
+		goto error;
+	if (isl_pw_aff_involves_nan(cond)) {
+		isl_space *space = isl_pw_aff_get_domain_space(cond);
+		isl_local_space *ls = isl_local_space_from_space(space);
+		isl_pw_aff_free(cond);
+		isl_pw_aff_free(pwaff_true);
+		isl_pw_aff_free(pwaff_false);
+		return isl_pw_aff_nan_on_domain(ls);
+	}
+
+	cond_true = isl_pw_aff_non_zero_set(isl_pw_aff_copy(cond));
+	cond_false = isl_pw_aff_zero_set(cond);
+	return isl_pw_aff_select(cond_true, pwaff_true,
+				 cond_false, pwaff_false);
+error:
+	isl_pw_aff_free(cond);
+	isl_pw_aff_free(pwaff_true);
+	isl_pw_aff_free(pwaff_false);
+	return NULL;
+}
+
+int isl_aff_is_cst(__isl_keep isl_aff *aff)
+{
+	if (!aff)
+		return -1;
+
+	return isl_seq_first_non_zero(aff->v->el + 2, aff->v->size - 2) == -1;
+}
+
+/* Check whether pwaff is a piecewise constant.
+ */
+int isl_pw_aff_is_cst(__isl_keep isl_pw_aff *pwaff)
+{
+	int i;
+
+	if (!pwaff)
+		return -1;
+
+	for (i = 0; i < pwaff->n; ++i) {
+		int is_cst = isl_aff_is_cst(pwaff->p[i].aff);
+		if (is_cst < 0 || !is_cst)
+			return is_cst;
+	}
+
+	return 1;
+}
+
+/* Return the product of "aff1" and "aff2".
+ *
+ * If either of the two is NaN, then the result is NaN.
+ *
+ * Otherwise, at least one of "aff1" or "aff2" needs to be a constant.
+ */
+__isl_give isl_aff *isl_aff_mul(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2)
+{
+	if (!aff1 || !aff2)
+		goto error;
+
+	if (isl_aff_is_nan(aff1)) {
+		isl_aff_free(aff2);
+		return aff1;
+	}
+	if (isl_aff_is_nan(aff2)) {
+		isl_aff_free(aff1);
+		return aff2;
+	}
+
+	if (!isl_aff_is_cst(aff2) && isl_aff_is_cst(aff1))
+		return isl_aff_mul(aff2, aff1);
+
+	if (!isl_aff_is_cst(aff2))
+		isl_die(isl_aff_get_ctx(aff1), isl_error_invalid,
+			"at least one affine expression should be constant",
+			goto error);
+
+	aff1 = isl_aff_cow(aff1);
+	if (!aff1 || !aff2)
+		goto error;
+
+	aff1 = isl_aff_scale(aff1, aff2->v->el[1]);
+	aff1 = isl_aff_scale_down(aff1, aff2->v->el[0]);
+
+	isl_aff_free(aff2);
+	return aff1;
+error:
+	isl_aff_free(aff1);
+	isl_aff_free(aff2);
+	return NULL;
+}
+
+/* Divide "aff1" by "aff2", assuming "aff2" is a constant.
+ *
+ * If either of the two is NaN, then the result is NaN.
+ */
+__isl_give isl_aff *isl_aff_div(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2)
+{
+	int is_cst;
+	int neg;
+
+	if (!aff1 || !aff2)
+		goto error;
+
+	if (isl_aff_is_nan(aff1)) {
+		isl_aff_free(aff2);
+		return aff1;
+	}
+	if (isl_aff_is_nan(aff2)) {
+		isl_aff_free(aff1);
+		return aff2;
+	}
+
+	is_cst = isl_aff_is_cst(aff2);
+	if (is_cst < 0)
+		goto error;
+	if (!is_cst)
+		isl_die(isl_aff_get_ctx(aff2), isl_error_invalid,
+			"second argument should be a constant", goto error);
+
+	if (!aff2)
+		goto error;
+
+	neg = isl_int_is_neg(aff2->v->el[1]);
+	if (neg) {
+		isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
+		isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
+	}
+
+	aff1 = isl_aff_scale(aff1, aff2->v->el[0]);
+	aff1 = isl_aff_scale_down(aff1, aff2->v->el[1]);
+
+	if (neg) {
+		isl_int_neg(aff2->v->el[0], aff2->v->el[0]);
+		isl_int_neg(aff2->v->el[1], aff2->v->el[1]);
+	}
+
+	isl_aff_free(aff2);
+	return aff1;
+error:
+	isl_aff_free(aff1);
+	isl_aff_free(aff2);
+	return NULL;
+}
+
+static __isl_give isl_pw_aff *pw_aff_add(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_add);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_add(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_add);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_union_add(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_union_add_(pwaff1, pwaff2);
+}
+
+static __isl_give isl_pw_aff *pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_on_shared_domain(pwaff1, pwaff2, &isl_aff_mul);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_mul(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_mul);
+}
+
+static __isl_give isl_pw_aff *pw_aff_div(__isl_take isl_pw_aff *pa1,
+	__isl_take isl_pw_aff *pa2)
+{
+	return isl_pw_aff_on_shared_domain(pa1, pa2, &isl_aff_div);
+}
+
+/* Divide "pa1" by "pa2", assuming "pa2" is a piecewise constant.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_div(__isl_take isl_pw_aff *pa1,
+	__isl_take isl_pw_aff *pa2)
+{
+	int is_cst;
+
+	is_cst = isl_pw_aff_is_cst(pa2);
+	if (is_cst < 0)
+		goto error;
+	if (!is_cst)
+		isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
+			"second argument should be a piecewise constant",
+			goto error);
+	return isl_pw_aff_align_params_pw_pw_and(pa1, pa2, &pw_aff_div);
+error:
+	isl_pw_aff_free(pa1);
+	isl_pw_aff_free(pa2);
+	return NULL;
+}
+
+/* Compute the quotient of the integer division of "pa1" by "pa2"
+ * with rounding towards zero.
+ * "pa2" is assumed to be a piecewise constant.
+ *
+ * In particular, return
+ *
+ *	pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2)
+ *
+ */
+__isl_give isl_pw_aff *isl_pw_aff_tdiv_q(__isl_take isl_pw_aff *pa1,
+	__isl_take isl_pw_aff *pa2)
+{
+	int is_cst;
+	isl_set *cond;
+	isl_pw_aff *f, *c;
+
+	is_cst = isl_pw_aff_is_cst(pa2);
+	if (is_cst < 0)
+		goto error;
+	if (!is_cst)
+		isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
+			"second argument should be a piecewise constant",
+			goto error);
+
+	pa1 = isl_pw_aff_div(pa1, pa2);
+
+	cond = isl_pw_aff_nonneg_set(isl_pw_aff_copy(pa1));
+	f = isl_pw_aff_floor(isl_pw_aff_copy(pa1));
+	c = isl_pw_aff_ceil(pa1);
+	return isl_pw_aff_cond(isl_set_indicator_function(cond), f, c);
+error:
+	isl_pw_aff_free(pa1);
+	isl_pw_aff_free(pa2);
+	return NULL;
+}
+
+/* Compute the remainder of the integer division of "pa1" by "pa2"
+ * with rounding towards zero.
+ * "pa2" is assumed to be a piecewise constant.
+ *
+ * In particular, return
+ *
+ *	pa1 - pa2 * (pa1 >= 0 ? floor(pa1/pa2) : ceil(pa1/pa2))
+ *
+ */
+__isl_give isl_pw_aff *isl_pw_aff_tdiv_r(__isl_take isl_pw_aff *pa1,
+	__isl_take isl_pw_aff *pa2)
+{
+	int is_cst;
+	isl_pw_aff *res;
+
+	is_cst = isl_pw_aff_is_cst(pa2);
+	if (is_cst < 0)
+		goto error;
+	if (!is_cst)
+		isl_die(isl_pw_aff_get_ctx(pa2), isl_error_invalid,
+			"second argument should be a piecewise constant",
+			goto error);
+	res = isl_pw_aff_tdiv_q(isl_pw_aff_copy(pa1), isl_pw_aff_copy(pa2));
+	res = isl_pw_aff_mul(pa2, res);
+	res = isl_pw_aff_sub(pa1, res);
+	return res;
+error:
+	isl_pw_aff_free(pa1);
+	isl_pw_aff_free(pa2);
+	return NULL;
+}
+
+static __isl_give isl_pw_aff *pw_aff_min(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	isl_set *le;
+	isl_set *dom;
+
+	dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)),
+				isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)));
+	le = isl_pw_aff_le_set(isl_pw_aff_copy(pwaff1),
+				isl_pw_aff_copy(pwaff2));
+	dom = isl_set_subtract(dom, isl_set_copy(le));
+	return isl_pw_aff_select(le, pwaff1, dom, pwaff2);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_min(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_min);
+}
+
+static __isl_give isl_pw_aff *pw_aff_max(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	isl_set *ge;
+	isl_set *dom;
+
+	dom = isl_set_intersect(isl_pw_aff_domain(isl_pw_aff_copy(pwaff1)),
+				isl_pw_aff_domain(isl_pw_aff_copy(pwaff2)));
+	ge = isl_pw_aff_ge_set(isl_pw_aff_copy(pwaff1),
+				isl_pw_aff_copy(pwaff2));
+	dom = isl_set_subtract(dom, isl_set_copy(ge));
+	return isl_pw_aff_select(ge, pwaff1, dom, pwaff2);
+}
+
+__isl_give isl_pw_aff *isl_pw_aff_max(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2)
+{
+	return isl_pw_aff_align_params_pw_pw_and(pwaff1, pwaff2, &pw_aff_max);
+}
+
+static __isl_give isl_pw_aff *pw_aff_list_reduce(
+	__isl_take isl_pw_aff_list *list,
+	__isl_give isl_pw_aff *(*fn)(__isl_take isl_pw_aff *pwaff1,
+					__isl_take isl_pw_aff *pwaff2))
+{
+	int i;
+	isl_ctx *ctx;
+	isl_pw_aff *res;
+
+	if (!list)
+		return NULL;
+
+	ctx = isl_pw_aff_list_get_ctx(list);
+	if (list->n < 1)
+		isl_die(ctx, isl_error_invalid,
+			"list should contain at least one element", goto error);
+
+	res = isl_pw_aff_copy(list->p[0]);
+	for (i = 1; i < list->n; ++i)
+		res = fn(res, isl_pw_aff_copy(list->p[i]));
+
+	isl_pw_aff_list_free(list);
+	return res;
+error:
+	isl_pw_aff_list_free(list);
+	return NULL;
+}
+
+/* Return an isl_pw_aff that maps each element in the intersection of the
+ * domains of the elements of list to the minimal corresponding affine
+ * expression.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_list_min(__isl_take isl_pw_aff_list *list)
+{
+	return pw_aff_list_reduce(list, &isl_pw_aff_min);
+}
+
+/* Return an isl_pw_aff that maps each element in the intersection of the
+ * domains of the elements of list to the maximal corresponding affine
+ * expression.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_list_max(__isl_take isl_pw_aff_list *list)
+{
+	return pw_aff_list_reduce(list, &isl_pw_aff_max);
+}
+
+/* Mark the domains of "pwaff" as rational.
+ */
+__isl_give isl_pw_aff *isl_pw_aff_set_rational(__isl_take isl_pw_aff *pwaff)
+{
+	int i;
+
+	pwaff = isl_pw_aff_cow(pwaff);
+	if (!pwaff)
+		return NULL;
+	if (pwaff->n == 0)
+		return pwaff;
+
+	for (i = 0; i < pwaff->n; ++i) {
+		pwaff->p[i].set = isl_set_set_rational(pwaff->p[i].set);
+		if (!pwaff->p[i].set)
+			return isl_pw_aff_free(pwaff);
+	}
+
+	return pwaff;
+}
+
+/* Mark the domains of the elements of "list" as rational.
+ */
+__isl_give isl_pw_aff_list *isl_pw_aff_list_set_rational(
+	__isl_take isl_pw_aff_list *list)
+{
+	int i, n;
+
+	if (!list)
+		return NULL;
+	if (list->n == 0)
+		return list;
+
+	n = list->n;
+	for (i = 0; i < n; ++i) {
+		isl_pw_aff *pa;
+
+		pa = isl_pw_aff_list_get_pw_aff(list, i);
+		pa = isl_pw_aff_set_rational(pa);
+		list = isl_pw_aff_list_set_pw_aff(list, i, pa);
+	}
+
+	return list;
+}
+
+/* Do the parameters of "aff" match those of "space"?
+ */
+int isl_aff_matching_params(__isl_keep isl_aff *aff,
+	__isl_keep isl_space *space)
+{
+	isl_space *aff_space;
+	int match;
+
+	if (!aff || !space)
+		return -1;
+
+	aff_space = isl_aff_get_domain_space(aff);
+
+	match = isl_space_match(space, isl_dim_param, aff_space, isl_dim_param);
+
+	isl_space_free(aff_space);
+	return match;
+}
+
+/* Check that the domain space of "aff" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ */
+int isl_aff_check_match_domain_space(__isl_keep isl_aff *aff,
+	__isl_keep isl_space *space)
+{
+	isl_space *aff_space;
+	int match;
+
+	if (!aff || !space)
+		return -1;
+
+	aff_space = isl_aff_get_domain_space(aff);
+
+	match = isl_space_match(space, isl_dim_param, aff_space, isl_dim_param);
+	if (match < 0)
+		goto error;
+	if (!match)
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"parameters don't match", goto error);
+	match = isl_space_tuple_is_equal(space, isl_dim_in,
+					aff_space, isl_dim_set);
+	if (match < 0)
+		goto error;
+	if (!match)
+		isl_die(isl_aff_get_ctx(aff), isl_error_invalid,
+			"domains don't match", goto error);
+	isl_space_free(aff_space);
+	return 0;
+error:
+	isl_space_free(aff_space);
+	return -1;
+}
+
+#undef BASE
+#define BASE aff
+#define NO_INTERSECT_DOMAIN
+#define NO_DOMAIN
+
+#include <isl_multi_templ.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,
+ * then the name of the corresponding space is also removed.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_flatten_domain(
+	__isl_take isl_multi_aff *ma)
+{
+	isl_space *space;
+
+	if (!ma)
+		return NULL;
+
+	if (!ma->space->nested[0])
+		return ma;
+
+	space = isl_multi_aff_get_space(ma);
+	space = isl_space_flatten_domain(space);
+	ma = isl_multi_aff_reset_space(ma, space);
+
+	return ma;
+}
+
+/* Given a map space, return an isl_multi_aff that maps a wrapped copy
+ * of the space to its domain.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_domain_map(__isl_take isl_space *space)
+{
+	int i, n_in;
+	isl_local_space *ls;
+	isl_multi_aff *ma;
+
+	if (!space)
+		return NULL;
+	if (!isl_space_is_map(space))
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"not a map space", goto error);
+
+	n_in = isl_space_dim(space, isl_dim_in);
+	space = isl_space_domain_map(space);
+
+	ma = isl_multi_aff_alloc(isl_space_copy(space));
+	if (n_in == 0) {
+		isl_space_free(space);
+		return ma;
+	}
+
+	space = isl_space_domain(space);
+	ls = isl_local_space_from_space(space);
+	for (i = 0; i < n_in; ++i) {
+		isl_aff *aff;
+
+		aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
+						isl_dim_set, i);
+		ma = isl_multi_aff_set_aff(ma, i, aff);
+	}
+	isl_local_space_free(ls);
+	return ma;
+error:
+	isl_space_free(space);
+	return NULL;
+}
+
+/* Given a map space, return an isl_multi_aff that maps a wrapped copy
+ * of the space to its range.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_range_map(__isl_take isl_space *space)
+{
+	int i, n_in, n_out;
+	isl_local_space *ls;
+	isl_multi_aff *ma;
+
+	if (!space)
+		return NULL;
+	if (!isl_space_is_map(space))
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"not a map space", goto error);
+
+	n_in = isl_space_dim(space, isl_dim_in);
+	n_out = isl_space_dim(space, isl_dim_out);
+	space = isl_space_range_map(space);
+
+	ma = isl_multi_aff_alloc(isl_space_copy(space));
+	if (n_out == 0) {
+		isl_space_free(space);
+		return ma;
+	}
+
+	space = isl_space_domain(space);
+	ls = isl_local_space_from_space(space);
+	for (i = 0; i < n_out; ++i) {
+		isl_aff *aff;
+
+		aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
+						isl_dim_set, n_in + i);
+		ma = isl_multi_aff_set_aff(ma, i, aff);
+	}
+	isl_local_space_free(ls);
+	return ma;
+error:
+	isl_space_free(space);
+	return NULL;
+}
+
+/* Given the space of a set and a range of set dimensions,
+ * construct an isl_multi_aff that projects out those dimensions.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_project_out_map(
+	__isl_take isl_space *space, enum isl_dim_type type,
+	unsigned first, unsigned n)
+{
+	int i, dim;
+	isl_local_space *ls;
+	isl_multi_aff *ma;
+
+	if (!space)
+		return NULL;
+	if (!isl_space_is_set(space))
+		isl_die(isl_space_get_ctx(space), isl_error_unsupported,
+			"expecting set space", goto error);
+	if (type != isl_dim_set)
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"only set dimensions can be projected out", goto error);
+
+	dim = isl_space_dim(space, isl_dim_set);
+	if (first + n > dim)
+		isl_die(isl_space_get_ctx(space), isl_error_invalid,
+			"range out of bounds", goto error);
+
+	space = isl_space_from_domain(space);
+	space = isl_space_add_dims(space, isl_dim_out, dim - n);
+
+	if (dim == n)
+		return isl_multi_aff_alloc(space);
+
+	ma = isl_multi_aff_alloc(isl_space_copy(space));
+	space = isl_space_domain(space);
+	ls = isl_local_space_from_space(space);
+
+	for (i = 0; i < first; ++i) {
+		isl_aff *aff;
+
+		aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
+						isl_dim_set, i);
+		ma = isl_multi_aff_set_aff(ma, i, aff);
+	}
+
+	for (i = 0; i < dim - (first + n); ++i) {
+		isl_aff *aff;
+
+		aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
+						isl_dim_set, first + n + i);
+		ma = isl_multi_aff_set_aff(ma, first + i, aff);
+	}
+
+	isl_local_space_free(ls);
+	return ma;
+error:
+	isl_space_free(space);
+	return NULL;
+}
+
+/* Given the space of a set and a range of set dimensions,
+ * construct an isl_pw_multi_aff that projects out those dimensions.
+ */
+__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)
+{
+	isl_multi_aff *ma;
+
+	ma = isl_multi_aff_project_out_map(space, type, first, n);
+	return isl_pw_multi_aff_from_multi_aff(ma);
+}
+
+/* Create an isl_pw_multi_aff with the given isl_multi_aff on a universe
+ * domain.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_aff(
+	__isl_take isl_multi_aff *ma)
+{
+	isl_set *dom = isl_set_universe(isl_multi_aff_get_domain_space(ma));
+	return isl_pw_multi_aff_alloc(dom, ma);
+}
+
+/* Create a piecewise multi-affine expression in the given space that maps each
+ * input dimension to the corresponding output dimension.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_identity(
+	__isl_take isl_space *space)
+{
+	return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_identity(space));
+}
+
+/* Add "ma2" to "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_add_aligned(
+	__isl_take isl_multi_aff *maff1, __isl_take isl_multi_aff *maff2)
+{
+	return isl_multi_aff_bin_op(maff1, maff2, &isl_aff_add);
+}
+
+/* Add "ma2" to "ma1" and return the result.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_add(__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_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(
+	__isl_take isl_multi_aff *maff, __isl_take isl_basic_set *eq)
+{
+	int i;
+
+	maff = isl_multi_aff_cow(maff);
+	if (!maff || !eq)
+		goto error;
+
+	for (i = 0; i < maff->n; ++i) {
+		maff->p[i] = isl_aff_substitute_equalities(maff->p[i],
+						    isl_basic_set_copy(eq));
+		if (!maff->p[i])
+			goto error;
+	}
+
+	isl_basic_set_free(eq);
+	return maff;
+error:
+	isl_basic_set_free(eq);
+	isl_multi_aff_free(maff);
+	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)
+{
+	int i;
+
+	maff = isl_multi_aff_cow(maff);
+	if (!maff)
+		return NULL;
+
+	for (i = 0; i < maff->n; ++i) {
+		maff->p[i] = isl_aff_scale(maff->p[i], f);
+		if (!maff->p[i])
+			return isl_multi_aff_free(maff);
+	}
+
+	return maff;
+}
+
+__isl_give isl_multi_aff *isl_multi_aff_add_on_domain(__isl_keep isl_set *dom,
+	__isl_take isl_multi_aff *maff1, __isl_take isl_multi_aff *maff2)
+{
+	maff1 = isl_multi_aff_add(maff1, maff2);
+	maff1 = isl_multi_aff_gist(maff1, isl_set_copy(dom));
+	return maff1;
+}
+
+int isl_multi_aff_is_empty(__isl_keep isl_multi_aff *maff)
+{
+	if (!maff)
+		return -1;
+
+	return 0;
+}
+
+/* Return the set of domain elements where "ma1" is lexicographically
+ * smaller than or equal to "ma2".
+ */
+__isl_give isl_set *isl_multi_aff_lex_le_set(__isl_take isl_multi_aff *ma1,
+	__isl_take isl_multi_aff *ma2)
+{
+	return isl_multi_aff_lex_ge_set(ma2, ma1);
+}
+
+/* Return the set of domain elements where "ma1" is lexicographically
+ * greater than or equal to "ma2".
+ */
+__isl_give isl_set *isl_multi_aff_lex_ge_set(__isl_take isl_multi_aff *ma1,
+	__isl_take isl_multi_aff *ma2)
+{
+	isl_space *space;
+	isl_map *map1, *map2;
+	isl_map *map, *ge;
+
+	map1 = isl_map_from_multi_aff(ma1);
+	map2 = isl_map_from_multi_aff(ma2);
+	map = isl_map_range_product(map1, map2);
+	space = isl_space_range(isl_map_get_space(map));
+	space = isl_space_domain(isl_space_unwrap(space));
+	ge = isl_map_lex_ge(space);
+	map = isl_map_intersect_range(map, isl_map_wrap(ge));
+
+	return isl_map_domain(map);
+}
+
+#undef PW
+#define PW isl_pw_multi_aff
+#undef EL
+#define EL isl_multi_aff
+#undef EL_IS_ZERO
+#define EL_IS_ZERO is_empty
+#undef ZERO
+#define ZERO empty
+#undef IS_ZERO
+#define IS_ZERO is_empty
+#undef FIELD
+#define FIELD maff
+#undef DEFAULT_IS_ZERO
+#define DEFAULT_IS_ZERO 0
+
+#define NO_NEG
+#define NO_EVAL
+#define NO_OPT
+#define NO_INVOLVES_DIMS
+#define NO_INSERT_DIMS
+#define NO_LIFT
+#define NO_MORPH
+
+#include <isl_pw_templ.c>
+
+#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
+
+#include <isl_union_templ.c>
+
+/* Given a function "cmp" that returns the set of elements where
+ * "ma1" is "better" than "ma2", return the intersection of this
+ * set with "dom1" and "dom2".
+ */
+static __isl_give isl_set *shared_and_better(__isl_keep isl_set *dom1,
+	__isl_keep isl_set *dom2, __isl_keep isl_multi_aff *ma1,
+	__isl_keep isl_multi_aff *ma2,
+	__isl_give isl_set *(*cmp)(__isl_take isl_multi_aff *ma1,
+				    __isl_take isl_multi_aff *ma2))
+{
+	isl_set *common;
+	isl_set *better;
+	int is_empty;
+
+	common = isl_set_intersect(isl_set_copy(dom1), isl_set_copy(dom2));
+	is_empty = isl_set_plain_is_empty(common);
+	if (is_empty >= 0 && is_empty)
+		return common;
+	if (is_empty < 0)
+		return isl_set_free(common);
+	better = cmp(isl_multi_aff_copy(ma1), isl_multi_aff_copy(ma2));
+	better = isl_set_intersect(common, better);
+
+	return better;
+}
+
+/* Given a function "cmp" that returns the set of elements where
+ * "ma1" is "better" than "ma2", return a piecewise multi affine
+ * expression defined on the union of the definition domains
+ * of "pma1" and "pma2" that maps to the "best" of "pma1" and
+ * "pma2" on each cell.  If only one of the two input functions
+ * is defined on a given cell, then it is considered the best.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_union_opt(
+	__isl_take isl_pw_multi_aff *pma1,
+	__isl_take isl_pw_multi_aff *pma2,
+	__isl_give isl_set *(*cmp)(__isl_take isl_multi_aff *ma1,
+				    __isl_take isl_multi_aff *ma2))
+{
+	int i, j, n;
+	isl_pw_multi_aff *res = NULL;
+	isl_ctx *ctx;
+	isl_set *set = NULL;
+
+	if (!pma1 || !pma2)
+		goto error;
+
+	ctx = isl_space_get_ctx(pma1->dim);
+	if (!isl_space_is_equal(pma1->dim, pma2->dim))
+		isl_die(ctx, isl_error_invalid,
+			"arguments should live in the same space", goto error);
+
+	if (isl_pw_multi_aff_is_empty(pma1)) {
+		isl_pw_multi_aff_free(pma1);
+		return pma2;
+	}
+
+	if (isl_pw_multi_aff_is_empty(pma2)) {
+		isl_pw_multi_aff_free(pma2);
+		return pma1;
+	}
+
+	n = 2 * (pma1->n + 1) * (pma2->n + 1);
+	res = isl_pw_multi_aff_alloc_size(isl_space_copy(pma1->dim), n);
+
+	for (i = 0; i < pma1->n; ++i) {
+		set = isl_set_copy(pma1->p[i].set);
+		for (j = 0; j < pma2->n; ++j) {
+			isl_set *better;
+			int is_empty;
+
+			better = shared_and_better(pma2->p[j].set,
+					pma1->p[i].set, pma2->p[j].maff,
+					pma1->p[i].maff, cmp);
+			is_empty = isl_set_plain_is_empty(better);
+			if (is_empty < 0 || is_empty) {
+				isl_set_free(better);
+				if (is_empty < 0)
+					goto error;
+				continue;
+			}
+			set = isl_set_subtract(set, isl_set_copy(better));
+
+			res = isl_pw_multi_aff_add_piece(res, better,
+					isl_multi_aff_copy(pma2->p[j].maff));
+		}
+		res = isl_pw_multi_aff_add_piece(res, set,
+					isl_multi_aff_copy(pma1->p[i].maff));
+	}
+
+	for (j = 0; j < pma2->n; ++j) {
+		set = isl_set_copy(pma2->p[j].set);
+		for (i = 0; i < pma1->n; ++i)
+			set = isl_set_subtract(set,
+					isl_set_copy(pma1->p[i].set));
+		res = isl_pw_multi_aff_add_piece(res, set,
+					isl_multi_aff_copy(pma2->p[j].maff));
+	}
+
+	isl_pw_multi_aff_free(pma1);
+	isl_pw_multi_aff_free(pma2);
+
+	return res;
+error:
+	isl_pw_multi_aff_free(pma1);
+	isl_pw_multi_aff_free(pma2);
+	isl_set_free(set);
+	return isl_pw_multi_aff_free(res);
+}
+
+static __isl_give isl_pw_multi_aff *pw_multi_aff_union_lexmax(
+	__isl_take isl_pw_multi_aff *pma1,
+	__isl_take isl_pw_multi_aff *pma2)
+{
+	return pw_multi_aff_union_opt(pma1, pma2, &isl_multi_aff_lex_ge_set);
+}
+
+/* Given two piecewise multi affine expressions, return a piecewise
+ * multi-affine expression defined on the union of the definition domains
+ * of the inputs that is equal to the lexicographic maximum of the two
+ * inputs on each cell.  If only one of the two inputs is defined on
+ * a given cell, then it is considered to be the maximum.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmax(
+	__isl_take isl_pw_multi_aff *pma1,
+	__isl_take isl_pw_multi_aff *pma2)
+{
+	return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+						    &pw_multi_aff_union_lexmax);
+}
+
+static __isl_give isl_pw_multi_aff *pw_multi_aff_union_lexmin(
+	__isl_take isl_pw_multi_aff *pma1,
+	__isl_take isl_pw_multi_aff *pma2)
+{
+	return pw_multi_aff_union_opt(pma1, pma2, &isl_multi_aff_lex_le_set);
+}
+
+/* Given two piecewise multi affine expressions, return a piecewise
+ * multi-affine expression defined on the union of the definition domains
+ * of the inputs that is equal to the lexicographic minimum of the two
+ * inputs on each cell.  If only one of the two inputs is defined on
+ * a given cell, then it is considered to be the minimum.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_union_lexmin(
+	__isl_take isl_pw_multi_aff *pma1,
+	__isl_take isl_pw_multi_aff *pma2)
+{
+	return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+						    &pw_multi_aff_union_lexmin);
+}
+
+static __isl_give isl_pw_multi_aff *pw_multi_aff_add(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+	return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
+						&isl_multi_aff_add);
+}
+
+__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)
+{
+	return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+						&pw_multi_aff_add);
+}
+
+static __isl_give isl_pw_multi_aff *pw_multi_aff_sub(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+	return isl_pw_multi_aff_on_shared_domain(pma1, pma2,
+						&isl_multi_aff_sub);
+}
+
+/* Subtract "pma2" from "pma1" and return the result.
+ */
+__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)
+{
+	return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+						&pw_multi_aff_sub);
+}
+
+__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)
+{
+	return isl_pw_multi_aff_union_add_(pma1, pma2);
+}
+
+/* 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.
+ */
+__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)
+{
+	return isl_union_pw_multi_aff_union_add_(upma1, upma2);
+}
+
+/* Given two piecewise multi-affine expressions A -> B and C -> D,
+ * construct a piecewise multi-affine expression [A -> C] -> [B -> D].
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_product(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+	int i, j, n;
+	isl_space *space;
+	isl_pw_multi_aff *res;
+
+	if (!pma1 || !pma2)
+		goto error;
+
+	n = pma1->n * pma2->n;
+	space = isl_space_product(isl_space_copy(pma1->dim),
+				  isl_space_copy(pma2->dim));
+	res = isl_pw_multi_aff_alloc_size(space, n);
+
+	for (i = 0; i < pma1->n; ++i) {
+		for (j = 0; j < pma2->n; ++j) {
+			isl_set *domain;
+			isl_multi_aff *ma;
+
+			domain = isl_set_product(isl_set_copy(pma1->p[i].set),
+						 isl_set_copy(pma2->p[j].set));
+			ma = isl_multi_aff_product(
+					isl_multi_aff_copy(pma1->p[i].maff),
+					isl_multi_aff_copy(pma2->p[j].maff));
+			res = isl_pw_multi_aff_add_piece(res, domain, ma);
+		}
+	}
+
+	isl_pw_multi_aff_free(pma1);
+	isl_pw_multi_aff_free(pma2);
+	return res;
+error:
+	isl_pw_multi_aff_free(pma1);
+	isl_pw_multi_aff_free(pma2);
+	return NULL;
+}
+
+__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)
+{
+	return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+						&pw_multi_aff_product);
+}
+
+/* Construct a map mapping the domain of the piecewise multi-affine expression
+ * to its range, with each dimension in the range equated to the
+ * corresponding affine expression on its cell.
+ */
+__isl_give isl_map *isl_map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma)
+{
+	int i;
+	isl_map *map;
+
+	if (!pma)
+		return NULL;
+
+	map = isl_map_empty(isl_pw_multi_aff_get_space(pma));
+
+	for (i = 0; i < pma->n; ++i) {
+		isl_multi_aff *maff;
+		isl_basic_map *bmap;
+		isl_map *map_i;
+
+		maff = isl_multi_aff_copy(pma->p[i].maff);
+		bmap = isl_basic_map_from_multi_aff(maff);
+		map_i = isl_map_from_basic_map(bmap);
+		map_i = isl_map_intersect_domain(map_i,
+						isl_set_copy(pma->p[i].set));
+		map = isl_map_union_disjoint(map, map_i);
+	}
+
+	isl_pw_multi_aff_free(pma);
+	return map;
+}
+
+__isl_give isl_set *isl_set_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma)
+{
+	if (!pma)
+		return NULL;
+
+	if (!isl_space_is_set(pma->dim))
+		isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+			"isl_pw_multi_aff cannot be converted into an isl_set",
+			goto error);
+
+	return isl_map_from_pw_multi_aff(pma);
+error:
+	isl_pw_multi_aff_free(pma);
+	return NULL;
+}
+
+/* Given a basic map with a single output dimension that is defined
+ * in terms of the parameters and input dimensions using an equality,
+ * extract an isl_aff that expresses the output dimension in terms
+ * of the parameters and input dimensions.
+ * Note that this expression may involve integer divisions defined
+ * in terms of parameters and input dimensions.
+ *
+ * This function shares some similarities with
+ * isl_basic_map_has_defining_equality and isl_constraint_get_bound.
+ */
+static __isl_give isl_aff *extract_isl_aff_from_basic_map(
+	__isl_take isl_basic_map *bmap)
+{
+	int eq;
+	unsigned offset;
+	unsigned n_div;
+	isl_local_space *ls;
+	isl_aff *aff;
+
+	if (!bmap)
+		return NULL;
+	if (isl_basic_map_dim(bmap, isl_dim_out) != 1)
+		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+			"basic map should have a single output dimension",
+			goto error);
+	eq = isl_basic_map_output_defining_equality(bmap, 0);
+	if (eq >= bmap->n_eq)
+		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+			"unable to find suitable equality", goto error);
+	ls = isl_basic_map_get_local_space(bmap);
+	aff = isl_aff_alloc(isl_local_space_domain(ls));
+	if (!aff)
+		goto error;
+	offset = isl_basic_map_offset(bmap, isl_dim_out);
+	n_div = isl_basic_map_dim(bmap, isl_dim_div);
+	if (isl_int_is_neg(bmap->eq[eq][offset])) {
+		isl_seq_cpy(aff->v->el + 1, bmap->eq[eq], offset);
+		isl_seq_cpy(aff->v->el + 1 + offset, bmap->eq[eq] + offset + 1,
+			    n_div);
+	} else {
+		isl_seq_neg(aff->v->el + 1, bmap->eq[eq], offset);
+		isl_seq_neg(aff->v->el + 1 + offset, bmap->eq[eq] + offset + 1,
+			    n_div);
+	}
+	isl_int_abs(aff->v->el[0], bmap->eq[eq][offset]);
+	isl_basic_map_free(bmap);
+
+	aff = isl_aff_remove_unused_divs(aff);
+	return aff;
+error:
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+/* Given a basic map where each output dimension is defined
+ * in terms of the parameters and input dimensions using an equality,
+ * extract an isl_multi_aff that expresses the output dimensions in terms
+ * of the parameters and input dimensions.
+ */
+static __isl_give isl_multi_aff *extract_isl_multi_aff_from_basic_map(
+	__isl_take isl_basic_map *bmap)
+{
+	int i;
+	unsigned n_out;
+	isl_multi_aff *ma;
+
+	if (!bmap)
+		return NULL;
+
+	ma = isl_multi_aff_alloc(isl_basic_map_get_space(bmap));
+	n_out = isl_basic_map_dim(bmap, isl_dim_out);
+
+	for (i = 0; i < n_out; ++i) {
+		isl_basic_map *bmap_i;
+		isl_aff *aff;
+
+		bmap_i = isl_basic_map_copy(bmap);
+		bmap_i = isl_basic_map_project_out(bmap_i, isl_dim_out,
+							i + 1, n_out - (1 + i));
+		bmap_i = isl_basic_map_project_out(bmap_i, isl_dim_out, 0, i);
+		aff = extract_isl_aff_from_basic_map(bmap_i);
+		ma = isl_multi_aff_set_aff(ma, i, aff);
+	}
+
+	isl_basic_map_free(bmap);
+
+	return ma;
+}
+
+/* Given a basic set where each set dimension is defined
+ * in terms of the parameters using an equality,
+ * extract an isl_multi_aff that expresses the set dimensions in terms
+ * of the parameters.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_from_basic_set_equalities(
+	__isl_take isl_basic_set *bset)
+{
+	return extract_isl_multi_aff_from_basic_map(bset);
+}
+
+/* Create an isl_pw_multi_aff that is equivalent to
+ * isl_map_intersect_domain(isl_map_from_basic_map(bmap), domain).
+ * The given basic map is such that each output dimension is defined
+ * in terms of the parameters and input dimensions using an equality.
+ *
+ * Since some applications expect the result of isl_pw_multi_aff_from_map
+ * to only contain integer affine expressions, we compute the floor
+ * of the expression before returning.
+ */
+static __isl_give isl_pw_multi_aff *plain_pw_multi_aff_from_map(
+	__isl_take isl_set *domain, __isl_take isl_basic_map *bmap)
+{
+	isl_multi_aff *ma;
+
+	ma = extract_isl_multi_aff_from_basic_map(bmap);
+	ma = isl_multi_aff_floor(ma);
+	return isl_pw_multi_aff_alloc(domain, ma);
+}
+
+/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
+ * This obviously only works if the input "map" is single-valued.
+ * If so, we compute the lexicographic minimum of the image in the form
+ * of an isl_pw_multi_aff.  Since the image is unique, it is equal
+ * to its lexicographic minimum.
+ * If the input is not single-valued, we produce an error.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_base(
+	__isl_take isl_map *map)
+{
+	int i;
+	int sv;
+	isl_pw_multi_aff *pma;
+
+	sv = isl_map_is_single_valued(map);
+	if (sv < 0)
+		goto error;
+	if (!sv)
+		isl_die(isl_map_get_ctx(map), isl_error_invalid,
+			"map is not single-valued", goto error);
+	map = isl_map_make_disjoint(map);
+	if (!map)
+		return NULL;
+
+	pma = isl_pw_multi_aff_empty(isl_map_get_space(map));
+
+	for (i = 0; i < map->n; ++i) {
+		isl_pw_multi_aff *pma_i;
+		isl_basic_map *bmap;
+		bmap = isl_basic_map_copy(map->p[i]);
+		pma_i = isl_basic_map_lexmin_pw_multi_aff(bmap);
+		pma = isl_pw_multi_aff_add_disjoint(pma, pma_i);
+	}
+
+	isl_map_free(map);
+	return pma;
+error:
+	isl_map_free(map);
+	return NULL;
+}
+
+/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
+ * taking into account that the output dimension at position "d"
+ * can be represented as
+ *
+ *	x = floor((e(...) + c1) / m)
+ *
+ * given that constraint "i" is of the form
+ *
+ *	e(...) + c1 - m x >= 0
+ *
+ *
+ * Let "map" be of the form
+ *
+ *	A -> B
+ *
+ * We construct a mapping
+ *
+ *	A -> [A -> x = floor(...)]
+ *
+ * apply that to the map, obtaining
+ *
+ *	[A -> x = floor(...)] -> B
+ *
+ * and equate dimension "d" to x.
+ * We then compute a isl_pw_multi_aff representation of the resulting map
+ * and plug in the mapping above.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_div(
+	__isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i)
+{
+	isl_ctx *ctx;
+	isl_space *space;
+	isl_local_space *ls;
+	isl_multi_aff *ma;
+	isl_aff *aff;
+	isl_vec *v;
+	isl_map *insert;
+	int offset;
+	int n;
+	int n_in;
+	isl_pw_multi_aff *pma;
+	int is_set;
+
+	is_set = isl_map_is_set(map);
+
+	offset = isl_basic_map_offset(hull, isl_dim_out);
+	ctx = isl_map_get_ctx(map);
+	space = isl_space_domain(isl_map_get_space(map));
+	n_in = isl_space_dim(space, isl_dim_set);
+	n = isl_space_dim(space, isl_dim_all);
+
+	v = isl_vec_alloc(ctx, 1 + 1 + n);
+	if (v) {
+		isl_int_neg(v->el[0], hull->ineq[i][offset + d]);
+		isl_seq_cpy(v->el + 1, hull->ineq[i], 1 + n);
+	}
+	isl_basic_map_free(hull);
+
+	ls = isl_local_space_from_space(isl_space_copy(space));
+	aff = isl_aff_alloc_vec(ls, v);
+	aff = isl_aff_floor(aff);
+	if (is_set) {
+		isl_space_free(space);
+		ma = isl_multi_aff_from_aff(aff);
+	} else {
+		ma = isl_multi_aff_identity(isl_space_map_from_set(space));
+		ma = isl_multi_aff_range_product(ma,
+						isl_multi_aff_from_aff(aff));
+	}
+
+	insert = isl_map_from_multi_aff(isl_multi_aff_copy(ma));
+	map = isl_map_apply_domain(map, insert);
+	map = isl_map_equate(map, isl_dim_in, n_in, isl_dim_out, d);
+	pma = isl_pw_multi_aff_from_map(map);
+	pma = isl_pw_multi_aff_pullback_multi_aff(pma, ma);
+
+	return pma;
+}
+
+/* Is constraint "c" of the form
+ *
+ *	e(...) + c1 - m x >= 0
+ *
+ * or
+ *
+ *	-e(...) + c2 + m x >= 0
+ *
+ * where m > 1 and e only depends on parameters and input dimemnsions?
+ *
+ * "offset" is the offset of the output dimensions
+ * "pos" is the position of output dimension x.
+ */
+static int is_potential_div_constraint(isl_int *c, int offset, int d, int total)
+{
+	if (isl_int_is_zero(c[offset + d]))
+		return 0;
+	if (isl_int_is_one(c[offset + d]))
+		return 0;
+	if (isl_int_is_negone(c[offset + d]))
+		return 0;
+	if (isl_seq_first_non_zero(c + offset, d) != -1)
+		return 0;
+	if (isl_seq_first_non_zero(c + offset + d + 1,
+				    total - (offset + d + 1)) != -1)
+		return 0;
+	return 1;
+}
+
+/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
+ *
+ * As a special case, we first check if there is any pair of constraints,
+ * shared by all the basic maps in "map" that force a given dimension
+ * to be equal to the floor of some affine combination of the input dimensions.
+ *
+ * In particular, if we can find two constraints
+ *
+ *	e(...) + c1 - m x >= 0		i.e.,		m x <= e(...) + c1
+ *
+ * and
+ *
+ *	-e(...) + c2 + m x >= 0		i.e.,		m x >= e(...) - c2
+ *
+ * where m > 1 and e only depends on parameters and input dimemnsions,
+ * and such that
+ *
+ *	c1 + c2 < m			i.e.,		-c2 >= c1 - (m - 1)
+ *
+ * then we know that we can take
+ *
+ *	x = floor((e(...) + c1) / m)
+ *
+ * without having to perform any computation.
+ *
+ * Note that we know that
+ *
+ *	c1 + c2 >= 1
+ *
+ * If c1 + c2 were 0, then we would have detected an equality during
+ * simplification.  If c1 + c2 were negative, then we would have detected
+ * a contradiction.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_check_div(
+	__isl_take isl_map *map)
+{
+	int d, dim;
+	int i, j, n;
+	int offset, total;
+	isl_int sum;
+	isl_basic_map *hull;
+
+	hull = isl_map_unshifted_simple_hull(isl_map_copy(map));
+	if (!hull)
+		goto error;
+
+	isl_int_init(sum);
+	dim = isl_map_dim(map, isl_dim_out);
+	offset = isl_basic_map_offset(hull, isl_dim_out);
+	total = 1 + isl_basic_map_total_dim(hull);
+	n = hull->n_ineq;
+	for (d = 0; d < dim; ++d) {
+		for (i = 0; i < n; ++i) {
+			if (!is_potential_div_constraint(hull->ineq[i],
+							offset, d, total))
+				continue;
+			for (j = i + 1; j < n; ++j) {
+				if (!isl_seq_is_neg(hull->ineq[i] + 1,
+						hull->ineq[j] + 1, total - 1))
+					continue;
+				isl_int_add(sum, hull->ineq[i][0],
+						hull->ineq[j][0]);
+				if (isl_int_abs_lt(sum,
+						    hull->ineq[i][offset + d]))
+					break;
+
+			}
+			if (j >= n)
+				continue;
+			isl_int_clear(sum);
+			if (isl_int_is_pos(hull->ineq[j][offset + d]))
+				j = i;
+			return pw_multi_aff_from_map_div(map, hull, d, j);
+		}
+	}
+	isl_int_clear(sum);
+	isl_basic_map_free(hull);
+	return pw_multi_aff_from_map_base(map);
+error:
+	isl_map_free(map);
+	isl_basic_map_free(hull);
+	return NULL;
+}
+
+/* Given an affine expression
+ *
+ *	[A -> B] -> f(A,B)
+ *
+ * construct an isl_multi_aff
+ *
+ *	[A -> B] -> B'
+ *
+ * such that dimension "d" in B' is set to "aff" and the remaining
+ * dimensions are set equal to the corresponding dimensions in B.
+ * "n_in" is the dimension of the space A.
+ * "n_out" is the dimension of the space B.
+ *
+ * If "is_set" is set, then the affine expression is of the form
+ *
+ *	[B] -> f(B)
+ *
+ * and we construct an isl_multi_aff
+ *
+ *	B -> B'
+ */
+static __isl_give isl_multi_aff *range_map(__isl_take isl_aff *aff, int d,
+	unsigned n_in, unsigned n_out, int is_set)
+{
+	int i;
+	isl_multi_aff *ma;
+	isl_space *space, *space2;
+	isl_local_space *ls;
+
+	space = isl_aff_get_domain_space(aff);
+	ls = isl_local_space_from_space(isl_space_copy(space));
+	space2 = isl_space_copy(space);
+	if (!is_set)
+		space2 = isl_space_range(isl_space_unwrap(space2));
+	space = isl_space_map_from_domain_and_range(space, space2);
+	ma = isl_multi_aff_alloc(space);
+	ma = isl_multi_aff_set_aff(ma, d, aff);
+
+	for (i = 0; i < n_out; ++i) {
+		if (i == d)
+			continue;
+		aff = isl_aff_var_on_domain(isl_local_space_copy(ls),
+						isl_dim_set, n_in + i);
+		ma = isl_multi_aff_set_aff(ma, i, aff);
+	}
+
+	isl_local_space_free(ls);
+
+	return ma;
+}
+
+/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map,
+ * taking into account that the dimension at position "d" can be written as
+ *
+ *	x = m a + f(..)						(1)
+ *
+ * where m is equal to "gcd".
+ * "i" is the index of the equality in "hull" that defines f(..).
+ * In particular, the equality is of the form
+ *
+ *	f(..) - x + m g(existentials) = 0
+ *
+ * or
+ *
+ *	-f(..) + x + m g(existentials) = 0
+ *
+ * We basically plug (1) into "map", resulting in a map with "a"
+ * in the range instead of "x".  The corresponding isl_pw_multi_aff
+ * defining "a" is then plugged back into (1) to obtain a definition fro "x".
+ *
+ * Specifically, given the input map
+ *
+ *	A -> B
+ *
+ * We first wrap it into a set
+ *
+ *	[A -> B]
+ *
+ * and define (1) on top of the corresponding space, resulting in "aff".
+ * We use this to create an isl_multi_aff that maps the output position "d"
+ * from "a" to "x", leaving all other (intput and output) dimensions unchanged.
+ * We plug this into the wrapped map, unwrap the result and compute the
+ * corresponding isl_pw_multi_aff.
+ * The result is an expression
+ *
+ *	A -> T(A)
+ *
+ * We adjust that to
+ *
+ *	A -> [A -> T(A)]
+ *
+ * so that we can plug that into "aff", after extending the latter to
+ * a mapping
+ *
+ *	[A -> B] -> B'
+ *
+ *
+ * If "map" is actually a set, then there is no "A" space, meaning
+ * that we do not need to perform any wrapping, and that the result
+ * of the recursive call is of the form
+ *
+ *	[T]
+ *
+ * which is plugged into a mapping of the form
+ *
+ *	B -> B'
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_from_map_stride(
+	__isl_take isl_map *map, __isl_take isl_basic_map *hull, int d, int i,
+	isl_int gcd)
+{
+	isl_set *set;
+	isl_space *space;
+	isl_local_space *ls;
+	isl_aff *aff;
+	isl_multi_aff *ma;
+	isl_pw_multi_aff *pma, *id;
+	unsigned n_in;
+	unsigned o_out;
+	unsigned n_out;
+	int is_set;
+
+	is_set = isl_map_is_set(map);
+
+	n_in = isl_basic_map_dim(hull, isl_dim_in);
+	n_out = isl_basic_map_dim(hull, isl_dim_out);
+	o_out = isl_basic_map_offset(hull, isl_dim_out);
+
+	if (is_set)
+		set = map;
+	else
+		set = isl_map_wrap(map);
+	space = isl_space_map_from_set(isl_set_get_space(set));
+	ma = isl_multi_aff_identity(space);
+	ls = isl_local_space_from_space(isl_set_get_space(set));
+	aff = isl_aff_alloc(ls);
+	if (aff) {
+		isl_int_set_si(aff->v->el[0], 1);
+		if (isl_int_is_one(hull->eq[i][o_out + d]))
+			isl_seq_neg(aff->v->el + 1, hull->eq[i],
+				    aff->v->size - 1);
+		else
+			isl_seq_cpy(aff->v->el + 1, hull->eq[i],
+				    aff->v->size - 1);
+		isl_int_set(aff->v->el[1 + o_out + d], gcd);
+	}
+	ma = isl_multi_aff_set_aff(ma, n_in + d, isl_aff_copy(aff));
+	set = isl_set_preimage_multi_aff(set, ma);
+
+	ma = range_map(aff, d, n_in, n_out, is_set);
+
+	if (is_set)
+		map = set;
+	else
+		map = isl_set_unwrap(set);
+	pma = isl_pw_multi_aff_from_map(set);
+
+	if (!is_set) {
+		space = isl_pw_multi_aff_get_domain_space(pma);
+		space = isl_space_map_from_set(space);
+		id = isl_pw_multi_aff_identity(space);
+		pma = isl_pw_multi_aff_range_product(id, pma);
+	}
+	id = isl_pw_multi_aff_from_multi_aff(ma);
+	pma = isl_pw_multi_aff_pullback_pw_multi_aff(id, pma);
+
+	isl_basic_map_free(hull);
+	return pma;
+}
+
+/* Try and create an isl_pw_multi_aff that is equivalent to the given isl_map.
+ *
+ * As a special case, we first check if all output dimensions are uniquely
+ * defined in terms of the parameters and input dimensions over the entire
+ * domain.  If so, we extract the desired isl_pw_multi_aff directly
+ * from the affine hull of "map" and its domain.
+ *
+ * Otherwise, we check if any of the output dimensions is "strided".
+ * That is, we check if can be written as
+ *
+ *	x = m a + f(..)
+ *
+ * with m greater than 1, a some combination of existentiall quantified
+ * variables and f and expression in the parameters and input dimensions.
+ * If so, we remove the stride in pw_multi_aff_from_map_stride.
+ *
+ * Otherwise, we continue with pw_multi_aff_from_map_check_div for a further
+ * special case.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_map(__isl_take isl_map *map)
+{
+	int i, j;
+	int sv;
+	isl_basic_map *hull;
+	unsigned n_out;
+	unsigned o_out;
+	unsigned n_div;
+	unsigned o_div;
+	isl_int gcd;
+
+	if (!map)
+		return NULL;
+
+	hull = isl_map_affine_hull(isl_map_copy(map));
+	sv = isl_basic_map_plain_is_single_valued(hull);
+	if (sv >= 0 && sv)
+		return plain_pw_multi_aff_from_map(isl_map_domain(map), hull);
+	if (sv < 0)
+		hull = isl_basic_map_free(hull);
+	if (!hull)
+		goto error;
+
+	n_div = isl_basic_map_dim(hull, isl_dim_div);
+	o_div = isl_basic_map_offset(hull, isl_dim_div);
+
+	if (n_div == 0) {
+		isl_basic_map_free(hull);
+		return pw_multi_aff_from_map_check_div(map);
+	}
+
+	isl_int_init(gcd);
+
+	n_out = isl_basic_map_dim(hull, isl_dim_out);
+	o_out = isl_basic_map_offset(hull, isl_dim_out);
+
+	for (i = 0; i < n_out; ++i) {
+		for (j = 0; j < hull->n_eq; ++j) {
+			isl_int *eq = hull->eq[j];
+			isl_pw_multi_aff *res;
+
+			if (!isl_int_is_one(eq[o_out + i]) &&
+			    !isl_int_is_negone(eq[o_out + i]))
+				continue;
+			if (isl_seq_first_non_zero(eq + o_out, i) != -1)
+				continue;
+			if (isl_seq_first_non_zero(eq + o_out + i + 1,
+						    n_out - (i + 1)) != -1)
+				continue;
+			isl_seq_gcd(eq + o_div, n_div, &gcd);
+			if (isl_int_is_zero(gcd))
+				continue;
+			if (isl_int_is_one(gcd))
+				continue;
+
+			res = pw_multi_aff_from_map_stride(map, hull,
+								i, j, gcd);
+			isl_int_clear(gcd);
+			return res;
+		}
+	}
+
+	isl_int_clear(gcd);
+	isl_basic_map_free(hull);
+	return pw_multi_aff_from_map_check_div(map);
+error:
+	isl_map_free(map);
+	return NULL;
+}
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_set(__isl_take isl_set *set)
+{
+	return isl_pw_multi_aff_from_map(set);
+}
+
+/* Convert "map" into an isl_pw_multi_aff (if possible) and
+ * add it to *user.
+ */
+static int pw_multi_aff_from_map(__isl_take isl_map *map, void *user)
+{
+	isl_union_pw_multi_aff **upma = user;
+	isl_pw_multi_aff *pma;
+
+	pma = isl_pw_multi_aff_from_map(map);
+	*upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
+
+	return *upma ? 0 : -1;
+}
+
+/* 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.
+ * Otherwise, an error is produced.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_map(
+	__isl_take isl_union_map *umap)
+{
+	isl_space *space;
+	isl_union_pw_multi_aff *upma;
+
+	space = isl_union_map_get_space(umap);
+	upma = isl_union_pw_multi_aff_empty(space);
+	if (isl_union_map_foreach_map(umap, &pw_multi_aff_from_map, &upma) < 0)
+		upma = isl_union_pw_multi_aff_free(upma);
+	isl_union_map_free(umap);
+
+	return upma;
+}
+
+/* Try and create an isl_union_pw_multi_aff that is equivalent
+ * to the given isl_union_set.
+ * The isl_union_set is required to be a singleton in each space.
+ * Otherwise, an error is produced.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_union_set(
+	__isl_take isl_union_set *uset)
+{
+	return isl_union_pw_multi_aff_from_union_map(uset);
+}
+
+/* Return the piecewise affine expression "set ? 1 : 0".
+ */
+__isl_give isl_pw_aff *isl_set_indicator_function(__isl_take isl_set *set)
+{
+	isl_pw_aff *pa;
+	isl_space *space = isl_set_get_space(set);
+	isl_local_space *ls = isl_local_space_from_space(space);
+	isl_aff *zero = isl_aff_zero_on_domain(isl_local_space_copy(ls));
+	isl_aff *one = isl_aff_zero_on_domain(ls);
+
+	one = isl_aff_add_constant_si(one, 1);
+	pa = isl_pw_aff_alloc(isl_set_copy(set), one);
+	set = isl_set_complement(set);
+	pa = isl_pw_aff_add_disjoint(pa, isl_pw_aff_alloc(set, zero));
+
+	return pa;
+}
+
+/* Plug in "subs" for dimension "type", "pos" of "aff".
+ *
+ * Let i be the dimension to replace and let "subs" be of the form
+ *
+ *	f/d
+ *
+ * and "aff" of the form
+ *
+ *	(a i + g)/m
+ *
+ * The result is
+ *
+ *	(a f + d g')/(m d)
+ *
+ * where g' is the result of plugging in "subs" in each of the integer
+ * divisions in g.
+ */
+__isl_give isl_aff *isl_aff_substitute(__isl_take isl_aff *aff,
+	enum isl_dim_type type, unsigned pos, __isl_keep isl_aff *subs)
+{
+	isl_ctx *ctx;
+	isl_int v;
+
+	aff = isl_aff_cow(aff);
+	if (!aff || !subs)
+		return isl_aff_free(aff);
+
+	ctx = isl_aff_get_ctx(aff);
+	if (!isl_space_is_equal(aff->ls->dim, subs->ls->dim))
+		isl_die(ctx, isl_error_invalid,
+			"spaces don't match", return isl_aff_free(aff));
+	if (isl_local_space_dim(subs->ls, isl_dim_div) != 0)
+		isl_die(ctx, isl_error_unsupported,
+			"cannot handle divs yet", return isl_aff_free(aff));
+
+	aff->ls = isl_local_space_substitute(aff->ls, type, pos, subs);
+	if (!aff->ls)
+		return isl_aff_free(aff);
+
+	aff->v = isl_vec_cow(aff->v);
+	if (!aff->v)
+		return isl_aff_free(aff);
+
+	pos += isl_local_space_offset(aff->ls, type);
+
+	isl_int_init(v);
+	isl_seq_substitute(aff->v->el, pos, subs->v->el,
+			    aff->v->size, subs->v->size, v);
+	isl_int_clear(v);
+
+	return aff;
+}
+
+/* Plug in "subs" for dimension "type", "pos" in each of the affine
+ * expressions in "maff".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_substitute(
+	__isl_take isl_multi_aff *maff, enum isl_dim_type type, unsigned pos,
+	__isl_keep isl_aff *subs)
+{
+	int i;
+
+	maff = isl_multi_aff_cow(maff);
+	if (!maff || !subs)
+		return isl_multi_aff_free(maff);
+
+	if (type == isl_dim_in)
+		type = isl_dim_set;
+
+	for (i = 0; i < maff->n; ++i) {
+		maff->p[i] = isl_aff_substitute(maff->p[i], type, pos, subs);
+		if (!maff->p[i])
+			return isl_multi_aff_free(maff);
+	}
+
+	return maff;
+}
+
+/* Plug in "subs" for dimension "type", "pos" of "pma".
+ *
+ * pma is of the form
+ *
+ *	A_i(v) -> M_i(v)
+ *
+ * while subs is of the form
+ *
+ *	v' = B_j(v) -> S_j
+ *
+ * Each pair i,j such that C_ij = A_i \cap B_i is non-empty
+ * has a contribution in the result, in particular
+ *
+ *	C_ij(S_j) -> M_i(S_j)
+ *
+ * Note that plugging in S_j in C_ij may also result in an empty set
+ * and this contribution should simply be discarded.
+ */
+__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)
+{
+	int i, j, n;
+	isl_pw_multi_aff *res;
+
+	if (!pma || !subs)
+		return isl_pw_multi_aff_free(pma);
+
+	n = pma->n * subs->n;
+	res = isl_pw_multi_aff_alloc_size(isl_space_copy(pma->dim), n);
+
+	for (i = 0; i < pma->n; ++i) {
+		for (j = 0; j < subs->n; ++j) {
+			isl_set *common;
+			isl_multi_aff *res_ij;
+			int empty;
+
+			common = isl_set_intersect(
+					isl_set_copy(pma->p[i].set),
+					isl_set_copy(subs->p[j].set));
+			common = isl_set_substitute(common,
+					type, pos, subs->p[j].aff);
+			empty = isl_set_plain_is_empty(common);
+			if (empty < 0 || empty) {
+				isl_set_free(common);
+				if (empty < 0)
+					goto error;
+				continue;
+			}
+
+			res_ij = isl_multi_aff_substitute(
+					isl_multi_aff_copy(pma->p[i].maff),
+					type, pos, subs->p[j].aff);
+
+			res = isl_pw_multi_aff_add_piece(res, common, res_ij);
+		}
+	}
+
+	isl_pw_multi_aff_free(pma);
+	return res;
+error:
+	isl_pw_multi_aff_free(pma);
+	isl_pw_multi_aff_free(res);
+	return NULL;
+}
+
+/* Compute the preimage of a range of dimensions in the affine expression "src"
+ * under "ma" and put the result in "dst".  The number of dimensions in "src"
+ * that precede the range is given by "n_before".  The number of dimensions
+ * in the range is given by the number of output dimensions of "ma".
+ * The number of dimensions that follow the range is given by "n_after".
+ * If "has_denom" is set (to one),
+ * then "src" and "dst" have an extra initial denominator.
+ * "n_div_ma" is the number of existentials in "ma"
+ * "n_div_bset" is the number of existentials in "src"
+ * The resulting "dst" (which is assumed to have been allocated by
+ * the caller) contains coefficients for both sets of existentials,
+ * first those in "ma" and then those in "src".
+ * f, c1, c2 and g are temporary objects that have been initialized
+ * by the caller.
+ *
+ * Let src represent the expression
+ *
+ *	(a(p) + f_u u + b v + f_w w + c(divs))/d
+ *
+ * and let ma represent the expressions
+ *
+ *	v_i = (r_i(p) + s_i(y) + t_i(divs'))/m_i
+ *
+ * We start out with the following expression for dst:
+ *
+ *	(a(p) + f_u u + 0 y + f_w w + 0 divs' + c(divs) + f \sum_i b_i v_i)/d
+ *
+ * with the multiplication factor f initially equal to 1
+ * and f \sum_i b_i v_i kept separately.
+ * For each x_i that we substitute, we multiply the numerator
+ * (and denominator) of dst by c_1 = m_i and add the numerator
+ * of the x_i expression multiplied by c_2 = f b_i,
+ * after removing the common factors of c_1 and c_2.
+ * The multiplication factor f also needs to be multiplied by c_1
+ * for the next x_j, j > i.
+ */
+void isl_seq_preimage(isl_int *dst, isl_int *src,
+	__isl_keep isl_multi_aff *ma, int n_before, int n_after,
+	int n_div_ma, int n_div_bmap,
+	isl_int f, isl_int c1, isl_int c2, isl_int g, int has_denom)
+{
+	int i;
+	int n_param, n_in, n_out;
+	int o_dst, o_src;
+
+	n_param = isl_multi_aff_dim(ma, isl_dim_param);
+	n_in = isl_multi_aff_dim(ma, isl_dim_in);
+	n_out = isl_multi_aff_dim(ma, isl_dim_out);
+
+	isl_seq_cpy(dst, src, has_denom + 1 + n_param + n_before);
+	o_dst = o_src = has_denom + 1 + n_param + n_before;
+	isl_seq_clr(dst + o_dst, n_in);
+	o_dst += n_in;
+	o_src += n_out;
+	isl_seq_cpy(dst + o_dst, src + o_src, n_after);
+	o_dst += n_after;
+	o_src += n_after;
+	isl_seq_clr(dst + o_dst, n_div_ma);
+	o_dst += n_div_ma;
+	isl_seq_cpy(dst + o_dst, src + o_src, n_div_bmap);
+
+	isl_int_set_si(f, 1);
+
+	for (i = 0; i < n_out; ++i) {
+		int offset = has_denom + 1 + n_param + n_before + i;
+
+		if (isl_int_is_zero(src[offset]))
+			continue;
+		isl_int_set(c1, ma->p[i]->v->el[0]);
+		isl_int_mul(c2, f, src[offset]);
+		isl_int_gcd(g, c1, c2);
+		isl_int_divexact(c1, c1, g);
+		isl_int_divexact(c2, c2, g);
+
+		isl_int_mul(f, f, c1);
+		o_dst = has_denom;
+		o_src = 1;
+		isl_seq_combine(dst + o_dst, c1, dst + o_dst,
+				c2, ma->p[i]->v->el + o_src, 1 + n_param);
+		o_dst += 1 + n_param;
+		o_src += 1 + n_param;
+		isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_before);
+		o_dst += n_before;
+		isl_seq_combine(dst + o_dst, c1, dst + o_dst,
+				c2, ma->p[i]->v->el + o_src, n_in);
+		o_dst += n_in;
+		o_src += n_in;
+		isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_after);
+		o_dst += n_after;
+		isl_seq_combine(dst + o_dst, c1, dst + o_dst,
+				c2, ma->p[i]->v->el + o_src, n_div_ma);
+		o_dst += n_div_ma;
+		o_src += n_div_ma;
+		isl_seq_scale(dst + o_dst, dst + o_dst, c1, n_div_bmap);
+		if (has_denom)
+			isl_int_mul(dst[0], dst[0], c1);
+	}
+}
+
+/* Compute the pullback of "aff" by the function represented by "ma".
+ * In other words, plug in "ma" in "aff".  The result is an affine expression
+ * defined over the domain space of "ma".
+ *
+ * If "aff" is represented by
+ *
+ *	(a(p) + b x + c(divs))/d
+ *
+ * and ma is represented by
+ *
+ *	x = D(p) + F(y) + G(divs')
+ *
+ * then the result is
+ *
+ *	(a(p) + b D(p) + b F(y) + b G(divs') + c(divs))/d
+ *
+ * The divs in the local space of the input are similarly adjusted
+ * through a call to isl_local_space_preimage_multi_aff.
+ */
+__isl_give isl_aff *isl_aff_pullback_multi_aff(__isl_take isl_aff *aff,
+	__isl_take isl_multi_aff *ma)
+{
+	isl_aff *res = NULL;
+	isl_local_space *ls;
+	int n_div_aff, n_div_ma;
+	isl_int f, c1, c2, g;
+
+	ma = isl_multi_aff_align_divs(ma);
+	if (!aff || !ma)
+		goto error;
+
+	n_div_aff = isl_aff_dim(aff, isl_dim_div);
+	n_div_ma = ma->n ? isl_aff_dim(ma->p[0], isl_dim_div) : 0;
+
+	ls = isl_aff_get_domain_local_space(aff);
+	ls = isl_local_space_preimage_multi_aff(ls, isl_multi_aff_copy(ma));
+	res = isl_aff_alloc(ls);
+	if (!res)
+		goto error;
+
+	isl_int_init(f);
+	isl_int_init(c1);
+	isl_int_init(c2);
+	isl_int_init(g);
+
+	isl_seq_preimage(res->v->el, aff->v->el, ma, 0, 0, n_div_ma, n_div_aff,
+			f, c1, c2, g, 1);
+
+	isl_int_clear(f);
+	isl_int_clear(c1);
+	isl_int_clear(c2);
+	isl_int_clear(g);
+
+	isl_aff_free(aff);
+	isl_multi_aff_free(ma);
+	res = isl_aff_normalize(res);
+	return res;
+error:
+	isl_aff_free(aff);
+	isl_multi_aff_free(ma);
+	isl_aff_free(res);
+	return NULL;
+}
+
+/* Compute the pullback of "aff1" by the function represented by "aff2".
+ * In other words, plug in "aff2" in "aff1".  The result is an affine expression
+ * defined over the domain space of "aff1".
+ *
+ * The domain of "aff1" should match the range of "aff2", which means
+ * that it should be single-dimensional.
+ */
+__isl_give isl_aff *isl_aff_pullback_aff(__isl_take isl_aff *aff1,
+	__isl_take isl_aff *aff2)
+{
+	isl_multi_aff *ma;
+
+	ma = isl_multi_aff_from_aff(aff2);
+	return isl_aff_pullback_multi_aff(aff1, ma);
+}
+
+/* Compute the pullback of "ma1" by the function represented by "ma2".
+ * In other words, plug in "ma2" in "ma1".
+ *
+ * The parameters of "ma1" and "ma2" are assumed to have been aligned.
+ */
+static __isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff_aligned(
+	__isl_take isl_multi_aff *ma1, __isl_take isl_multi_aff *ma2)
+{
+	int i;
+	isl_space *space = NULL;
+
+	ma2 = isl_multi_aff_align_divs(ma2);
+	ma1 = isl_multi_aff_cow(ma1);
+	if (!ma1 || !ma2)
+		goto error;
+
+	space = isl_space_join(isl_multi_aff_get_space(ma2),
+				isl_multi_aff_get_space(ma1));
+
+	for (i = 0; i < ma1->n; ++i) {
+		ma1->p[i] = isl_aff_pullback_multi_aff(ma1->p[i],
+						    isl_multi_aff_copy(ma2));
+		if (!ma1->p[i])
+			goto error;
+	}
+
+	ma1 = isl_multi_aff_reset_space(ma1, space);
+	isl_multi_aff_free(ma2);
+	return ma1;
+error:
+	isl_space_free(space);
+	isl_multi_aff_free(ma2);
+	isl_multi_aff_free(ma1);
+	return NULL;
+}
+
+/* Compute the pullback of "ma1" by the function represented by "ma2".
+ * In other words, plug in "ma2" in "ma1".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_pullback_multi_aff(
+	__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_pullback_multi_aff_aligned);
+}
+
+/* Extend the local space of "dst" to include the divs
+ * in the local space of "src".
+ */
+__isl_give isl_aff *isl_aff_align_divs(__isl_take isl_aff *dst,
+	__isl_keep isl_aff *src)
+{
+	isl_ctx *ctx;
+	int *exp1 = NULL;
+	int *exp2 = NULL;
+	isl_mat *div;
+
+	if (!src || !dst)
+		return isl_aff_free(dst);
+
+	ctx = isl_aff_get_ctx(src);
+	if (!isl_space_is_equal(src->ls->dim, dst->ls->dim))
+		isl_die(ctx, isl_error_invalid,
+			"spaces don't match", goto error);
+
+	if (src->ls->div->n_row == 0)
+		return dst;
+
+	exp1 = isl_alloc_array(ctx, int, src->ls->div->n_row);
+	exp2 = isl_alloc_array(ctx, int, dst->ls->div->n_row);
+	if (!exp1 || (dst->ls->div->n_row && !exp2))
+		goto error;
+
+	div = isl_merge_divs(src->ls->div, dst->ls->div, exp1, exp2);
+	dst = isl_aff_expand_divs(dst, div, exp2);
+	free(exp1);
+	free(exp2);
+
+	return dst;
+error:
+	free(exp1);
+	free(exp2);
+	return isl_aff_free(dst);
+}
+
+/* Adjust the local spaces of the affine expressions in "maff"
+ * such that they all have the save divs.
+ */
+__isl_give isl_multi_aff *isl_multi_aff_align_divs(
+	__isl_take isl_multi_aff *maff)
+{
+	int i;
+
+	if (!maff)
+		return NULL;
+	if (maff->n == 0)
+		return maff;
+	maff = isl_multi_aff_cow(maff);
+	if (!maff)
+		return NULL;
+
+	for (i = 1; i < maff->n; ++i)
+		maff->p[0] = isl_aff_align_divs(maff->p[0], maff->p[i]);
+	for (i = 1; i < maff->n; ++i) {
+		maff->p[i] = isl_aff_align_divs(maff->p[i], maff->p[0]);
+		if (!maff->p[i])
+			return isl_multi_aff_free(maff);
+	}
+
+	return maff;
+}
+
+__isl_give isl_aff *isl_aff_lift(__isl_take isl_aff *aff)
+{
+	aff = isl_aff_cow(aff);
+	if (!aff)
+		return NULL;
+
+	aff->ls = isl_local_space_lift(aff->ls);
+	if (!aff->ls)
+		return isl_aff_free(aff);
+
+	return aff;
+}
+
+/* Lift "maff" to a space with extra dimensions such that the result
+ * has no more existentially quantified variables.
+ * If "ls" is not NULL, then *ls is assigned the local space that lies
+ * at the basis of the lifting applied to "maff".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_lift(__isl_take isl_multi_aff *maff,
+	__isl_give isl_local_space **ls)
+{
+	int i;
+	isl_space *space;
+	unsigned n_div;
+
+	if (ls)
+		*ls = NULL;
+
+	if (!maff)
+		return NULL;
+
+	if (maff->n == 0) {
+		if (ls) {
+			isl_space *space = isl_multi_aff_get_domain_space(maff);
+			*ls = isl_local_space_from_space(space);
+			if (!*ls)
+				return isl_multi_aff_free(maff);
+		}
+		return maff;
+	}
+
+	maff = isl_multi_aff_cow(maff);
+	maff = isl_multi_aff_align_divs(maff);
+	if (!maff)
+		return NULL;
+
+	n_div = isl_aff_dim(maff->p[0], isl_dim_div);
+	space = isl_multi_aff_get_space(maff);
+	space = isl_space_lift(isl_space_domain(space), n_div);
+	space = isl_space_extend_domain_with_range(space,
+						isl_multi_aff_get_space(maff));
+	if (!space)
+		return isl_multi_aff_free(maff);
+	isl_space_free(maff->space);
+	maff->space = space;
+
+	if (ls) {
+		*ls = isl_aff_get_domain_local_space(maff->p[0]);
+		if (!*ls)
+			return isl_multi_aff_free(maff);
+	}
+
+	for (i = 0; i < maff->n; ++i) {
+		maff->p[i] = isl_aff_lift(maff->p[i]);
+		if (!maff->p[i])
+			goto error;
+	}
+
+	return maff;
+error:
+	if (ls)
+		isl_local_space_free(*ls);
+	return isl_multi_aff_free(maff);
+}
+
+
+/* Extract an isl_pw_aff corresponding to output dimension "pos" of "pma".
+ */
+__isl_give isl_pw_aff *isl_pw_multi_aff_get_pw_aff(
+	__isl_keep isl_pw_multi_aff *pma, int pos)
+{
+	int i;
+	int n_out;
+	isl_space *space;
+	isl_pw_aff *pa;
+
+	if (!pma)
+		return NULL;
+
+	n_out = isl_pw_multi_aff_dim(pma, isl_dim_out);
+	if (pos < 0 || pos >= n_out)
+		isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+			"index out of bounds", return NULL);
+
+	space = isl_pw_multi_aff_get_space(pma);
+	space = isl_space_drop_dims(space, isl_dim_out,
+				    pos + 1, n_out - pos - 1);
+	space = isl_space_drop_dims(space, isl_dim_out, 0, pos);
+
+	pa = isl_pw_aff_alloc_size(space, pma->n);
+	for (i = 0; i < pma->n; ++i) {
+		isl_aff *aff;
+		aff = isl_multi_aff_get_aff(pma->p[i].maff, pos);
+		pa = isl_pw_aff_add_piece(pa, isl_set_copy(pma->p[i].set), aff);
+	}
+
+	return pa;
+}
+
+/* Return an isl_pw_multi_aff with the given "set" as domain and
+ * an unnamed zero-dimensional range.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_domain(
+	__isl_take isl_set *set)
+{
+	isl_multi_aff *ma;
+	isl_space *space;
+
+	space = isl_set_get_space(set);
+	space = isl_space_from_domain(space);
+	ma = isl_multi_aff_zero(space);
+	return isl_pw_multi_aff_alloc(set, ma);
+}
+
+/* Add an isl_pw_multi_aff with the given "set" as domain and
+ * an unnamed zero-dimensional range to *user.
+ */
+static int add_pw_multi_aff_from_domain(__isl_take isl_set *set, void *user)
+{
+	isl_union_pw_multi_aff **upma = user;
+	isl_pw_multi_aff *pma;
+
+	pma = isl_pw_multi_aff_from_domain(set);
+	*upma = isl_union_pw_multi_aff_add_pw_multi_aff(*upma, pma);
+
+	return 0;
+}
+
+/* Return an isl_union_pw_multi_aff with the given "uset" as domain and
+ * an unnamed zero-dimensional range.
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_from_domain(
+	__isl_take isl_union_set *uset)
+{
+	isl_space *space;
+	isl_union_pw_multi_aff *upma;
+
+	if (!uset)
+		return NULL;
+
+	space = isl_union_set_get_space(uset);
+	upma = isl_union_pw_multi_aff_empty(space);
+
+	if (isl_union_set_foreach_set(uset,
+				    &add_pw_multi_aff_from_domain, &upma) < 0)
+		goto error;
+
+	isl_union_set_free(uset);
+	return upma;
+error:
+	isl_union_set_free(uset);
+	isl_union_pw_multi_aff_free(upma);
+	return NULL;
+}
+
+/* Convert "pma" to an isl_map and add it to *umap.
+ */
+static int map_from_pw_multi_aff(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+	isl_union_map **umap = user;
+	isl_map *map;
+
+	map = isl_map_from_pw_multi_aff(pma);
+	*umap = isl_union_map_add_map(*umap, map);
+
+	return 0;
+}
+
+/* Construct a union map mapping the domain of the union
+ * piecewise multi-affine expression to its range, with each dimension
+ * in the range equated to the corresponding affine expression on its cell.
+ */
+__isl_give isl_union_map *isl_union_map_from_union_pw_multi_aff(
+	__isl_take isl_union_pw_multi_aff *upma)
+{
+	isl_space *space;
+	isl_union_map *umap;
+
+	if (!upma)
+		return NULL;
+
+	space = isl_union_pw_multi_aff_get_space(upma);
+	umap = isl_union_map_empty(space);
+
+	if (isl_union_pw_multi_aff_foreach_pw_multi_aff(upma,
+					&map_from_pw_multi_aff, &umap) < 0)
+		goto error;
+
+	isl_union_pw_multi_aff_free(upma);
+	return umap;
+error:
+	isl_union_pw_multi_aff_free(upma);
+	isl_union_map_free(umap);
+	return NULL;
+}
+
+/* Local data for bin_entry and the callback "fn".
+ */
+struct isl_union_pw_multi_aff_bin_data {
+	isl_union_pw_multi_aff *upma2;
+	isl_union_pw_multi_aff *res;
+	isl_pw_multi_aff *pma;
+	int (*fn)(void **entry, void *user);
+};
+
+/* Given an isl_pw_multi_aff from upma1, store it in data->pma
+ * and call data->fn for each isl_pw_multi_aff in data->upma2.
+ */
+static int bin_entry(void **entry, void *user)
+{
+	struct isl_union_pw_multi_aff_bin_data *data = user;
+	isl_pw_multi_aff *pma = *entry;
+
+	data->pma = pma;
+	if (isl_hash_table_foreach(data->upma2->space->ctx, &data->upma2->table,
+				   data->fn, data) < 0)
+		return -1;
+
+	return 0;
+}
+
+/* Call "fn" on each pair of isl_pw_multi_affs in "upma1" and "upma2".
+ * The isl_pw_multi_aff from upma1 is stored in data->pma (where data is
+ * passed as user field) and the isl_pw_multi_aff from upma2 is available
+ * as *entry.  The callback should adjust data->res if desired.
+ */
+static __isl_give isl_union_pw_multi_aff *bin_op(
+	__isl_take isl_union_pw_multi_aff *upma1,
+	__isl_take isl_union_pw_multi_aff *upma2,
+	int (*fn)(void **entry, void *user))
+{
+	isl_space *space;
+	struct isl_union_pw_multi_aff_bin_data data = { NULL, NULL, NULL, fn };
+
+	space = isl_union_pw_multi_aff_get_space(upma2);
+	upma1 = isl_union_pw_multi_aff_align_params(upma1, space);
+	space = isl_union_pw_multi_aff_get_space(upma1);
+	upma2 = isl_union_pw_multi_aff_align_params(upma2, space);
+
+	if (!upma1 || !upma2)
+		goto error;
+
+	data.upma2 = upma2;
+	data.res = isl_union_pw_multi_aff_alloc(isl_space_copy(upma1->space),
+				       upma1->table.n);
+	if (isl_hash_table_foreach(upma1->space->ctx, &upma1->table,
+				   &bin_entry, &data) < 0)
+		goto error;
+
+	isl_union_pw_multi_aff_free(upma1);
+	isl_union_pw_multi_aff_free(upma2);
+	return data.res;
+error:
+	isl_union_pw_multi_aff_free(upma1);
+	isl_union_pw_multi_aff_free(upma2);
+	isl_union_pw_multi_aff_free(data.res);
+	return NULL;
+}
+
+/* Given two aligned isl_pw_multi_affs A -> B and C -> D,
+ * construct an isl_pw_multi_aff (A * C) -> [B -> D].
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_range_product(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+	isl_space *space;
+
+	space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1),
+					isl_pw_multi_aff_get_space(pma2));
+	return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space,
+					    &isl_multi_aff_range_product);
+}
+
+/* Given two isl_pw_multi_affs A -> B and C -> D,
+ * construct an isl_pw_multi_aff (A * C) -> [B -> D].
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_range_product(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+	return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+					    &pw_multi_aff_range_product);
+}
+
+/* Given two aligned isl_pw_multi_affs A -> B and C -> D,
+ * construct an isl_pw_multi_aff (A * C) -> (B, D).
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_flat_range_product(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+	isl_space *space;
+
+	space = isl_space_range_product(isl_pw_multi_aff_get_space(pma1),
+					isl_pw_multi_aff_get_space(pma2));
+	space = isl_space_flatten_range(space);
+	return isl_pw_multi_aff_on_shared_domain_in(pma1, pma2, space,
+					    &isl_multi_aff_flat_range_product);
+}
+
+/* Given two isl_pw_multi_affs A -> B and C -> D,
+ * construct an isl_pw_multi_aff (A * C) -> (B, D).
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_flat_range_product(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2)
+{
+	return isl_pw_multi_aff_align_params_pw_pw_and(pma1, pma2,
+					    &pw_multi_aff_flat_range_product);
+}
+
+/* If data->pma and *entry have the same domain space, then compute
+ * their flat range product and the result to data->res.
+ */
+static int flat_range_product_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_in))
+		return 0;
+
+	pma2 = isl_pw_multi_aff_flat_range_product(
+					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);
+
+	return 0;
+}
+
+/* Given two isl_union_pw_multi_affs A -> B and C -> D,
+ * construct an isl_union_pw_multi_aff (A * C) -> (B, D).
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_flat_range_product(
+	__isl_take isl_union_pw_multi_aff *upma1,
+	__isl_take isl_union_pw_multi_aff *upma2)
+{
+	return bin_op(upma1, upma2, &flat_range_product_entry);
+}
+
+/* Replace the affine expressions at position "pos" in "pma" by "pa".
+ * The parameters are assumed to have been aligned.
+ *
+ * The implementation essentially performs an isl_pw_*_on_shared_domain,
+ * except that it works on two different isl_pw_* types.
+ */
+static __isl_give isl_pw_multi_aff *pw_multi_aff_set_pw_aff(
+	__isl_take isl_pw_multi_aff *pma, unsigned pos,
+	__isl_take isl_pw_aff *pa)
+{
+	int i, j, n;
+	isl_pw_multi_aff *res = NULL;
+
+	if (!pma || !pa)
+		goto error;
+
+	if (!isl_space_tuple_is_equal(pma->dim, isl_dim_in,
+					pa->dim, isl_dim_in))
+		isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+			"domains don't match", goto error);
+	if (pos >= isl_pw_multi_aff_dim(pma, isl_dim_out))
+		isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+			"index out of bounds", goto error);
+
+	n = pma->n * pa->n;
+	res = isl_pw_multi_aff_alloc_size(isl_pw_multi_aff_get_space(pma), n);
+
+	for (i = 0; i < pma->n; ++i) {
+		for (j = 0; j < pa->n; ++j) {
+			isl_set *common;
+			isl_multi_aff *res_ij;
+			int empty;
+
+			common = isl_set_intersect(isl_set_copy(pma->p[i].set),
+						   isl_set_copy(pa->p[j].set));
+			empty = isl_set_plain_is_empty(common);
+			if (empty < 0 || empty) {
+				isl_set_free(common);
+				if (empty < 0)
+					goto error;
+				continue;
+			}
+
+			res_ij = isl_multi_aff_set_aff(
+					isl_multi_aff_copy(pma->p[i].maff), pos,
+					isl_aff_copy(pa->p[j].aff));
+			res_ij = isl_multi_aff_gist(res_ij,
+					isl_set_copy(common));
+
+			res = isl_pw_multi_aff_add_piece(res, common, res_ij);
+		}
+	}
+
+	isl_pw_multi_aff_free(pma);
+	isl_pw_aff_free(pa);
+	return res;
+error:
+	isl_pw_multi_aff_free(pma);
+	isl_pw_aff_free(pa);
+	return isl_pw_multi_aff_free(res);
+}
+
+/* Replace the affine expressions at position "pos" in "pma" by "pa".
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_set_pw_aff(
+	__isl_take isl_pw_multi_aff *pma, unsigned pos,
+	__isl_take isl_pw_aff *pa)
+{
+	if (!pma || !pa)
+		goto error;
+	if (isl_space_match(pma->dim, isl_dim_param, pa->dim, isl_dim_param))
+		return pw_multi_aff_set_pw_aff(pma, pos, pa);
+	if (!isl_space_has_named_params(pma->dim) ||
+	    !isl_space_has_named_params(pa->dim))
+		isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+			"unaligned unnamed parameters", goto error);
+	pma = isl_pw_multi_aff_align_params(pma, isl_pw_aff_get_space(pa));
+	pa = isl_pw_aff_align_params(pa, isl_pw_multi_aff_get_space(pma));
+	return pw_multi_aff_set_pw_aff(pma, pos, pa);
+error:
+	isl_pw_multi_aff_free(pma);
+	isl_pw_aff_free(pa);
+	return NULL;
+}
+
+/* Do the parameters of "pa" match those of "space"?
+ */
+int isl_pw_aff_matching_params(__isl_keep isl_pw_aff *pa,
+	__isl_keep isl_space *space)
+{
+	isl_space *pa_space;
+	int match;
+
+	if (!pa || !space)
+		return -1;
+
+	pa_space = isl_pw_aff_get_space(pa);
+
+	match = isl_space_match(space, isl_dim_param, pa_space, isl_dim_param);
+
+	isl_space_free(pa_space);
+	return match;
+}
+
+/* Check that the domain space of "pa" matches "space".
+ *
+ * Return 0 on success and -1 on error.
+ */
+int isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
+	__isl_keep isl_space *space)
+{
+	isl_space *pa_space;
+	int match;
+
+	if (!pa || !space)
+		return -1;
+
+	pa_space = isl_pw_aff_get_space(pa);
+
+	match = isl_space_match(space, isl_dim_param, pa_space, isl_dim_param);
+	if (match < 0)
+		goto error;
+	if (!match)
+		isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+			"parameters don't match", goto error);
+	match = isl_space_tuple_is_equal(space, isl_dim_in,
+					pa_space, isl_dim_in);
+	if (match < 0)
+		goto error;
+	if (!match)
+		isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+			"domains don't match", goto error);
+	isl_space_free(pa_space);
+	return 0;
+error:
+	isl_space_free(pa_space);
+	return -1;
+}
+
+#undef BASE
+#define BASE pw_aff
+
+#include <isl_multi_templ.c>
+
+/* Scale the elements of "pma" by the corresponding elements of "mv".
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_scale_multi_val(
+	__isl_take isl_pw_multi_aff *pma, __isl_take isl_multi_val *mv)
+{
+	int i;
+
+	pma = isl_pw_multi_aff_cow(pma);
+	if (!pma || !mv)
+		goto error;
+	if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
+					mv->space, isl_dim_set))
+		isl_die(isl_pw_multi_aff_get_ctx(pma), isl_error_invalid,
+			"spaces don't match", goto error);
+	if (!isl_space_match(pma->dim, isl_dim_param,
+					mv->space, isl_dim_param)) {
+		pma = isl_pw_multi_aff_align_params(pma,
+					    isl_multi_val_get_space(mv));
+		mv = isl_multi_val_align_params(mv,
+					    isl_pw_multi_aff_get_space(pma));
+		if (!pma || !mv)
+			goto error;
+	}
+
+	for (i = 0; i < pma->n; ++i) {
+		pma->p[i].maff = isl_multi_aff_scale_multi_val(pma->p[i].maff,
+							isl_multi_val_copy(mv));
+		if (!pma->p[i].maff)
+			goto error;
+	}
+
+	isl_multi_val_free(mv);
+	return pma;
+error:
+	isl_multi_val_free(mv);
+	isl_pw_multi_aff_free(pma);
+	return NULL;
+}
+
+/* Internal data structure for isl_union_pw_multi_aff_scale_multi_val.
+ * mv contains the mv argument.
+ * res collects the results.
+ */
+struct isl_union_pw_multi_aff_scale_multi_val_data {
+	isl_multi_val *mv;
+	isl_union_pw_multi_aff *res;
+};
+
+/* This function is called for each entry of an isl_union_pw_multi_aff.
+ * If the space of the entry matches that of data->mv,
+ * then apply isl_pw_multi_aff_scale_multi_val and add the result
+ * to data->res.
+ */
+static int union_pw_multi_aff_scale_multi_val_entry(void **entry, void *user)
+{
+	struct isl_union_pw_multi_aff_scale_multi_val_data *data = user;
+	isl_pw_multi_aff *pma = *entry;
+
+	if (!pma)
+		return -1;
+	if (!isl_space_tuple_is_equal(pma->dim, isl_dim_out,
+				    data->mv->space, isl_dim_set))
+		return 0;
+
+	pma = isl_pw_multi_aff_copy(pma);
+	pma = isl_pw_multi_aff_scale_multi_val(pma,
+						isl_multi_val_copy(data->mv));
+	data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
+	if (!data->res)
+		return -1;
+
+	return 0;
+}
+
+/* Scale the elements of "upma" by the corresponding elements of "mv",
+ * for those entries that match the space of "mv".
+ */
+__isl_give isl_union_pw_multi_aff *isl_union_pw_multi_aff_scale_multi_val(
+	__isl_take isl_union_pw_multi_aff *upma, __isl_take isl_multi_val *mv)
+{
+	struct isl_union_pw_multi_aff_scale_multi_val_data data;
+
+	upma = isl_union_pw_multi_aff_align_params(upma,
+						isl_multi_val_get_space(mv));
+	mv = isl_multi_val_align_params(mv,
+					isl_union_pw_multi_aff_get_space(upma));
+	if (!upma || !mv)
+		goto error;
+
+	data.mv = mv;
+	data.res = isl_union_pw_multi_aff_alloc(isl_space_copy(upma->space),
+						upma->table.n);
+	if (isl_hash_table_foreach(upma->space->ctx, &upma->table,
+		       &union_pw_multi_aff_scale_multi_val_entry, &data) < 0)
+		goto error;
+
+	isl_multi_val_free(mv);
+	isl_union_pw_multi_aff_free(upma);
+	return data.res;
+error:
+	isl_multi_val_free(mv);
+	isl_union_pw_multi_aff_free(upma);
+	return NULL;
+}
+
+/* Construct and return a piecewise multi affine expression
+ * in the given space with value zero in each of the output dimensions and
+ * a universe domain.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_zero(__isl_take isl_space *space)
+{
+	return isl_pw_multi_aff_from_multi_aff(isl_multi_aff_zero(space));
+}
+
+/* Construct and return a piecewise multi affine expression
+ * that is equal to the given piecewise affine expression.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_pw_aff(
+	__isl_take isl_pw_aff *pa)
+{
+	int i;
+	isl_space *space;
+	isl_pw_multi_aff *pma;
+
+	if (!pa)
+		return NULL;
+
+	space = isl_pw_aff_get_space(pa);
+	pma = isl_pw_multi_aff_alloc_size(space, pa->n);
+
+	for (i = 0; i < pa->n; ++i) {
+		isl_set *set;
+		isl_multi_aff *ma;
+
+		set = isl_set_copy(pa->p[i].set);
+		ma = isl_multi_aff_from_aff(isl_aff_copy(pa->p[i].aff));
+		pma = isl_pw_multi_aff_add_piece(pma, set, ma);
+	}
+
+	isl_pw_aff_free(pa);
+	return pma;
+}
+
+/* Construct a set or map mapping the shared (parameter) domain
+ * of the piecewise affine expressions to the range of "mpa"
+ * with each dimension in the range equated to the
+ * corresponding piecewise affine expression.
+ */
+static __isl_give isl_map *map_from_multi_pw_aff(
+	__isl_take isl_multi_pw_aff *mpa)
+{
+	int i;
+	isl_space *space;
+	isl_map *map;
+
+	if (!mpa)
+		return NULL;
+
+	if (isl_space_dim(mpa->space, isl_dim_out) != mpa->n)
+		isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
+			"invalid space", goto error);
+
+	space = isl_multi_pw_aff_get_domain_space(mpa);
+	map = isl_map_universe(isl_space_from_domain(space));
+
+	for (i = 0; i < mpa->n; ++i) {
+		isl_pw_aff *pa;
+		isl_map *map_i;
+
+		pa = isl_pw_aff_copy(mpa->p[i]);
+		map_i = map_from_pw_aff(pa);
+
+		map = isl_map_flat_range_product(map, map_i);
+	}
+
+	map = isl_map_reset_space(map, isl_multi_pw_aff_get_space(mpa));
+
+	isl_multi_pw_aff_free(mpa);
+	return map;
+error:
+	isl_multi_pw_aff_free(mpa);
+	return NULL;
+}
+
+/* Construct a map mapping the shared domain
+ * of the piecewise affine expressions to the range of "mpa"
+ * with each dimension in the range equated to the
+ * corresponding piecewise affine expression.
+ */
+__isl_give isl_map *isl_map_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa)
+{
+	if (!mpa)
+		return NULL;
+	if (isl_space_is_set(mpa->space))
+		isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
+			"space of input is not a map", goto error);
+
+	return map_from_multi_pw_aff(mpa);
+error:
+	isl_multi_pw_aff_free(mpa);
+	return NULL;
+}
+
+/* Construct a set mapping the shared parameter domain
+ * of the piecewise affine expressions to the space of "mpa"
+ * with each dimension in the range equated to the
+ * corresponding piecewise affine expression.
+ */
+__isl_give isl_set *isl_set_from_multi_pw_aff(__isl_take isl_multi_pw_aff *mpa)
+{
+	if (!mpa)
+		return NULL;
+	if (!isl_space_is_set(mpa->space))
+		isl_die(isl_multi_pw_aff_get_ctx(mpa), isl_error_internal,
+			"space of input is not a set", goto error);
+
+	return map_from_multi_pw_aff(mpa);
+error:
+	isl_multi_pw_aff_free(mpa);
+	return NULL;
+}
+
+/* Construct and return a piecewise multi affine expression
+ * that is equal to the given multi piecewise affine expression
+ * on the shared domain of the piecewise affine expressions.
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_from_multi_pw_aff(
+	__isl_take isl_multi_pw_aff *mpa)
+{
+	int i;
+	isl_space *space;
+	isl_pw_aff *pa;
+	isl_pw_multi_aff *pma;
+
+	if (!mpa)
+		return NULL;
+
+	space = isl_multi_pw_aff_get_space(mpa);
+
+	if (mpa->n == 0) {
+		isl_multi_pw_aff_free(mpa);
+		return isl_pw_multi_aff_zero(space);
+	}
+
+	pa = isl_multi_pw_aff_get_pw_aff(mpa, 0);
+	pma = isl_pw_multi_aff_from_pw_aff(pa);
+
+	for (i = 1; i < mpa->n; ++i) {
+		isl_pw_multi_aff *pma_i;
+
+		pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
+		pma_i = isl_pw_multi_aff_from_pw_aff(pa);
+		pma = isl_pw_multi_aff_range_product(pma, pma_i);
+	}
+
+	pma = isl_pw_multi_aff_reset_space(pma, space);
+
+	isl_multi_pw_aff_free(mpa);
+	return pma;
+}
+
+/* Construct and return a multi piecewise affine expression
+ * that is equal to the given multi affine expression.
+ */
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_multi_aff(
+	__isl_take isl_multi_aff *ma)
+{
+	int i, n;
+	isl_multi_pw_aff *mpa;
+
+	if (!ma)
+		return NULL;
+
+	n = isl_multi_aff_dim(ma, isl_dim_out);
+	mpa = isl_multi_pw_aff_alloc(isl_multi_aff_get_space(ma));
+
+	for (i = 0; i < n; ++i) {
+		isl_pw_aff *pa;
+
+		pa = isl_pw_aff_from_aff(isl_multi_aff_get_aff(ma, i));
+		mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
+	}
+
+	isl_multi_aff_free(ma);
+	return mpa;
+}
+
+/* Construct and return a multi piecewise affine expression
+ * that is equal to the given piecewise multi affine expression.
+ */
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_from_pw_multi_aff(
+	__isl_take isl_pw_multi_aff *pma)
+{
+	int i, n;
+	isl_space *space;
+	isl_multi_pw_aff *mpa;
+
+	if (!pma)
+		return NULL;
+
+	n = isl_pw_multi_aff_dim(pma, isl_dim_out);
+	space = isl_pw_multi_aff_get_space(pma);
+	mpa = isl_multi_pw_aff_alloc(space);
+
+	for (i = 0; i < n; ++i) {
+		isl_pw_aff *pa;
+
+		pa = isl_pw_multi_aff_get_pw_aff(pma, i);
+		mpa = isl_multi_pw_aff_set_pw_aff(mpa, i, pa);
+	}
+
+	isl_pw_multi_aff_free(pma);
+	return mpa;
+}
+
+/* Do "pa1" and "pa2" represent the same function?
+ *
+ * We first check if they are obviously equal.
+ * If not, we convert them to maps and check if those are equal.
+ */
+int isl_pw_aff_is_equal(__isl_keep isl_pw_aff *pa1, __isl_keep isl_pw_aff *pa2)
+{
+	int equal;
+	isl_map *map1, *map2;
+
+	if (!pa1 || !pa2)
+		return -1;
+
+	equal = isl_pw_aff_plain_is_equal(pa1, pa2);
+	if (equal < 0 || equal)
+		return equal;
+
+	map1 = map_from_pw_aff(isl_pw_aff_copy(pa1));
+	map2 = map_from_pw_aff(isl_pw_aff_copy(pa2));
+	equal = isl_map_is_equal(map1, map2);
+	isl_map_free(map1);
+	isl_map_free(map2);
+
+	return equal;
+}
+
+/* Do "mpa1" and "mpa2" represent the same function?
+ *
+ * Note that we cannot convert the entire isl_multi_pw_aff
+ * to a map because the domains of the piecewise affine expressions
+ * may not be the same.
+ */
+int isl_multi_pw_aff_is_equal(__isl_keep isl_multi_pw_aff *mpa1,
+	__isl_keep isl_multi_pw_aff *mpa2)
+{
+	int i;
+	int equal;
+
+	if (!mpa1 || !mpa2)
+		return -1;
+
+	if (!isl_space_match(mpa1->space, isl_dim_param,
+			     mpa2->space, isl_dim_param)) {
+		if (!isl_space_has_named_params(mpa1->space))
+			return 0;
+		if (!isl_space_has_named_params(mpa2->space))
+			return 0;
+		mpa1 = isl_multi_pw_aff_copy(mpa1);
+		mpa2 = isl_multi_pw_aff_copy(mpa2);
+		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));
+		equal = isl_multi_pw_aff_is_equal(mpa1, mpa2);
+		isl_multi_pw_aff_free(mpa1);
+		isl_multi_pw_aff_free(mpa2);
+		return equal;
+	}
+
+	equal = isl_space_is_equal(mpa1->space, mpa2->space);
+	if (equal < 0 || !equal)
+		return equal;
+
+	for (i = 0; i < mpa1->n; ++i) {
+		equal = isl_pw_aff_is_equal(mpa1->p[i], mpa2->p[i]);
+		if (equal < 0 || !equal)
+			return equal;
+	}
+
+	return 1;
+}
+
+/* Coalesce the elements of "mpa".
+ *
+ * Note that such coalescing does not change the meaning of "mpa"
+ * so there is no need to cow.  We do need to be careful not to
+ * destroy any other copies of "mpa" in case of failure.
+ */
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_coalesce(
+	__isl_take isl_multi_pw_aff *mpa)
+{
+	int i;
+
+	if (!mpa)
+		return NULL;
+
+	for (i = 0; i < mpa->n; ++i) {
+		isl_pw_aff *pa = isl_pw_aff_copy(mpa->p[i]);
+		pa = isl_pw_aff_coalesce(pa);
+		if (!pa)
+			return isl_multi_pw_aff_free(mpa);
+		isl_pw_aff_free(mpa->p[i]);
+		mpa->p[i] = pa;
+	}
+
+	return mpa;
+}
+
+/* Compute the pullback of "mpa" by the function represented by "ma".
+ * In other words, plug in "ma" in "mpa".
+ *
+ * The parameters of "mpa" and "ma" are assumed to have been aligned.
+ */
+static __isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff_aligned(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma)
+{
+	int i;
+	isl_space *space = NULL;
+
+	mpa = isl_multi_pw_aff_cow(mpa);
+	if (!mpa || !ma)
+		goto error;
+
+	space = isl_space_join(isl_multi_aff_get_space(ma),
+				isl_multi_pw_aff_get_space(mpa));
+	if (!space)
+		goto error;
+
+	for (i = 0; i < mpa->n; ++i) {
+		mpa->p[i] = isl_pw_aff_pullback_multi_aff(mpa->p[i],
+						    isl_multi_aff_copy(ma));
+		if (!mpa->p[i])
+			goto error;
+	}
+
+	isl_multi_aff_free(ma);
+	isl_space_free(mpa->space);
+	mpa->space = space;
+	return mpa;
+error:
+	isl_space_free(space);
+	isl_multi_pw_aff_free(mpa);
+	isl_multi_aff_free(ma);
+	return NULL;
+}
+
+/* Compute the pullback of "mpa" by the function represented by "ma".
+ * In other words, plug in "ma" in "mpa".
+ */
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_aff(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_multi_aff *ma)
+{
+	if (!mpa || !ma)
+		goto error;
+	if (isl_space_match(mpa->space, isl_dim_param,
+			    ma->space, isl_dim_param))
+		return isl_multi_pw_aff_pullback_multi_aff_aligned(mpa, ma);
+	mpa = isl_multi_pw_aff_align_params(mpa, isl_multi_aff_get_space(ma));
+	ma = isl_multi_aff_align_params(ma, isl_multi_pw_aff_get_space(mpa));
+	return isl_multi_pw_aff_pullback_multi_aff_aligned(mpa, ma);
+error:
+	isl_multi_pw_aff_free(mpa);
+	isl_multi_aff_free(ma);
+	return NULL;
+}
+
+/* Compute the pullback of "mpa" by the function represented by "pma".
+ * In other words, plug in "pma" in "mpa".
+ *
+ * The parameters of "mpa" and "mpa" are assumed to have been aligned.
+ */
+static __isl_give isl_multi_pw_aff *
+isl_multi_pw_aff_pullback_pw_multi_aff_aligned(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma)
+{
+	int i;
+	isl_space *space = NULL;
+
+	mpa = isl_multi_pw_aff_cow(mpa);
+	if (!mpa || !pma)
+		goto error;
+
+	space = isl_space_join(isl_pw_multi_aff_get_space(pma),
+				isl_multi_pw_aff_get_space(mpa));
+
+	for (i = 0; i < mpa->n; ++i) {
+		mpa->p[i] = isl_pw_aff_pullback_pw_multi_aff_aligned(mpa->p[i],
+						    isl_pw_multi_aff_copy(pma));
+		if (!mpa->p[i])
+			goto error;
+	}
+
+	isl_pw_multi_aff_free(pma);
+	isl_space_free(mpa->space);
+	mpa->space = space;
+	return mpa;
+error:
+	isl_space_free(space);
+	isl_multi_pw_aff_free(mpa);
+	isl_pw_multi_aff_free(pma);
+	return NULL;
+}
+
+/* Compute the pullback of "mpa" by the function represented by "pma".
+ * In other words, plug in "pma" in "mpa".
+ */
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_pw_multi_aff(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_multi_aff *pma)
+{
+	if (!mpa || !pma)
+		goto error;
+	if (isl_space_match(mpa->space, isl_dim_param, pma->dim, isl_dim_param))
+		return isl_multi_pw_aff_pullback_pw_multi_aff_aligned(mpa, pma);
+	mpa = isl_multi_pw_aff_align_params(mpa,
+					    isl_pw_multi_aff_get_space(pma));
+	pma = isl_pw_multi_aff_align_params(pma,
+					    isl_multi_pw_aff_get_space(mpa));
+	return isl_multi_pw_aff_pullback_pw_multi_aff_aligned(mpa, pma);
+error:
+	isl_multi_pw_aff_free(mpa);
+	isl_pw_multi_aff_free(pma);
+	return NULL;
+}
+
+/* Apply "aff" to "mpa".  The range of "mpa" needs to be compatible
+ * with the domain of "aff".  The domain of the result is the same
+ * as that of "mpa".
+ * "mpa" and "aff" are assumed to have been aligned.
+ *
+ * We first extract the parametric constant from "aff", defined
+ * over the correct domain.
+ * Then we add the appropriate combinations of the members of "mpa".
+ * Finally, we add the integer divisions through recursive calls.
+ */
+static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff_aligned(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff)
+{
+	int i, n_param, n_in, n_div;
+	isl_space *space;
+	isl_val *v;
+	isl_pw_aff *pa;
+	isl_aff *tmp;
+
+	n_param = isl_aff_dim(aff, isl_dim_param);
+	n_in = isl_aff_dim(aff, isl_dim_in);
+	n_div = isl_aff_dim(aff, isl_dim_div);
+
+	space = isl_space_domain(isl_multi_pw_aff_get_space(mpa));
+	tmp = isl_aff_copy(aff);
+	tmp = isl_aff_drop_dims(tmp, isl_dim_div, 0, n_div);
+	tmp = isl_aff_drop_dims(tmp, isl_dim_in, 0, n_in);
+	tmp = isl_aff_add_dims(tmp, isl_dim_in,
+				isl_space_dim(space, isl_dim_set));
+	tmp = isl_aff_reset_domain_space(tmp, space);
+	pa = isl_pw_aff_from_aff(tmp);
+
+	for (i = 0; i < n_in; ++i) {
+		isl_pw_aff *pa_i;
+
+		if (!isl_aff_involves_dims(aff, isl_dim_in, i, 1))
+			continue;
+		v = isl_aff_get_coefficient_val(aff, isl_dim_in, i);
+		pa_i = isl_multi_pw_aff_get_pw_aff(mpa, i);
+		pa_i = isl_pw_aff_scale_val(pa_i, v);
+		pa = isl_pw_aff_add(pa, pa_i);
+	}
+
+	for (i = 0; i < n_div; ++i) {
+		isl_aff *div;
+		isl_pw_aff *pa_i;
+
+		if (!isl_aff_involves_dims(aff, isl_dim_div, i, 1))
+			continue;
+		div = isl_aff_get_div(aff, i);
+		pa_i = isl_multi_pw_aff_apply_aff_aligned(
+					    isl_multi_pw_aff_copy(mpa), div);
+		pa_i = isl_pw_aff_floor(pa_i);
+		v = isl_aff_get_coefficient_val(aff, isl_dim_div, i);
+		pa_i = isl_pw_aff_scale_val(pa_i, v);
+		pa = isl_pw_aff_add(pa, pa_i);
+	}
+
+	isl_multi_pw_aff_free(mpa);
+	isl_aff_free(aff);
+
+	return pa;
+}
+
+/* Apply "aff" to "mpa".  The range of "mpa" needs to be compatible
+ * with the domain of "aff".  The domain of the result is the same
+ * as that of "mpa".
+ */
+__isl_give isl_pw_aff *isl_multi_pw_aff_apply_aff(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_aff *aff)
+{
+	if (!aff || !mpa)
+		goto error;
+	if (isl_space_match(aff->ls->dim, isl_dim_param,
+				mpa->space, isl_dim_param))
+		return isl_multi_pw_aff_apply_aff_aligned(mpa, aff);
+
+	aff = isl_aff_align_params(aff, isl_multi_pw_aff_get_space(mpa));
+	mpa = isl_multi_pw_aff_align_params(mpa, isl_aff_get_space(aff));
+
+	return isl_multi_pw_aff_apply_aff_aligned(mpa, aff);
+error:
+	isl_aff_free(aff);
+	isl_multi_pw_aff_free(mpa);
+	return NULL;
+}
+
+/* Apply "pa" to "mpa".  The range of "mpa" needs to be compatible
+ * with the domain of "pa".  The domain of the result is the same
+ * as that of "mpa".
+ * "mpa" and "pa" are assumed to have been aligned.
+ *
+ * We consider each piece in turn.  Note that the domains of the
+ * pieces are assumed to be disjoint and they remain disjoint
+ * after taking the preimage (over the same function).
+ */
+static __isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff_aligned(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa)
+{
+	isl_space *space;
+	isl_pw_aff *res;
+	int i;
+
+	if (!mpa || !pa)
+		goto error;
+
+	space = isl_space_join(isl_multi_pw_aff_get_space(mpa),
+				isl_pw_aff_get_space(pa));
+	res = isl_pw_aff_empty(space);
+
+	for (i = 0; i < pa->n; ++i) {
+		isl_pw_aff *pa_i;
+		isl_set *domain;
+
+		pa_i = isl_multi_pw_aff_apply_aff_aligned(
+					isl_multi_pw_aff_copy(mpa),
+					isl_aff_copy(pa->p[i].aff));
+		domain = isl_set_copy(pa->p[i].set);
+		domain = isl_set_preimage_multi_pw_aff(domain,
+					isl_multi_pw_aff_copy(mpa));
+		pa_i = isl_pw_aff_intersect_domain(pa_i, domain);
+		res = isl_pw_aff_add_disjoint(res, pa_i);
+	}
+
+	isl_pw_aff_free(pa);
+	isl_multi_pw_aff_free(mpa);
+	return res;
+error:
+	isl_pw_aff_free(pa);
+	isl_multi_pw_aff_free(mpa);
+	return NULL;
+}
+
+/* Apply "pa" to "mpa".  The range of "mpa" needs to be compatible
+ * with the domain of "pa".  The domain of the result is the same
+ * as that of "mpa".
+ */
+__isl_give isl_pw_aff *isl_multi_pw_aff_apply_pw_aff(
+	__isl_take isl_multi_pw_aff *mpa, __isl_take isl_pw_aff *pa)
+{
+	if (!pa || !mpa)
+		goto error;
+	if (isl_space_match(pa->dim, isl_dim_param, mpa->space, isl_dim_param))
+		return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
+
+	pa = isl_pw_aff_align_params(pa, isl_multi_pw_aff_get_space(mpa));
+	mpa = isl_multi_pw_aff_align_params(mpa, isl_pw_aff_get_space(pa));
+
+	return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
+error:
+	isl_pw_aff_free(pa);
+	isl_multi_pw_aff_free(mpa);
+	return NULL;
+}
+
+/* Compute the pullback of "pa" by the function represented by "mpa".
+ * In other words, plug in "mpa" in "pa".
+ * "pa" and "mpa" are assumed to have been aligned.
+ *
+ * The pullback is computed by applying "pa" to "mpa".
+ */
+static __isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff_aligned(
+	__isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa)
+{
+	return isl_multi_pw_aff_apply_pw_aff_aligned(mpa, pa);
+}
+
+/* Compute the pullback of "pa" by the function represented by "mpa".
+ * In other words, plug in "mpa" in "pa".
+ *
+ * The pullback is computed by applying "pa" to "mpa".
+ */
+__isl_give isl_pw_aff *isl_pw_aff_pullback_multi_pw_aff(
+	__isl_take isl_pw_aff *pa, __isl_take isl_multi_pw_aff *mpa)
+{
+	return isl_multi_pw_aff_apply_pw_aff(mpa, pa);
+}
+
+/* Compute the pullback of "mpa1" by the function represented by "mpa2".
+ * In other words, plug in "mpa2" in "mpa1".
+ *
+ * The parameters of "mpa1" and "mpa2" are assumed to have been aligned.
+ *
+ * We pullback each member of "mpa1" in turn.
+ */
+static __isl_give isl_multi_pw_aff *
+isl_multi_pw_aff_pullback_multi_pw_aff_aligned(
+	__isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
+{
+	int i;
+	isl_space *space = NULL;
+
+	mpa1 = isl_multi_pw_aff_cow(mpa1);
+	if (!mpa1 || !mpa2)
+		goto error;
+
+	space = isl_space_join(isl_multi_pw_aff_get_space(mpa2),
+				isl_multi_pw_aff_get_space(mpa1));
+
+	for (i = 0; i < mpa1->n; ++i) {
+		mpa1->p[i] = isl_pw_aff_pullback_multi_pw_aff_aligned(
+				mpa1->p[i], isl_multi_pw_aff_copy(mpa2));
+		if (!mpa1->p[i])
+			goto error;
+	}
+
+	mpa1 = isl_multi_pw_aff_reset_space(mpa1, space);
+
+	isl_multi_pw_aff_free(mpa2);
+	return mpa1;
+error:
+	isl_space_free(space);
+	isl_multi_pw_aff_free(mpa1);
+	isl_multi_pw_aff_free(mpa2);
+	return NULL;
+}
+
+/* Compute the pullback of "mpa1" by the function represented by "mpa2".
+ * In other words, plug in "mpa2" in "mpa1".
+ */
+__isl_give isl_multi_pw_aff *isl_multi_pw_aff_pullback_multi_pw_aff(
+	__isl_take isl_multi_pw_aff *mpa1, __isl_take isl_multi_pw_aff *mpa2)
+{
+	return isl_multi_pw_aff_align_params_multi_multi_and(mpa1, mpa2,
+			&isl_multi_pw_aff_pullback_multi_pw_aff_aligned);
+}
+
+/* Compare two isl_affs.
+ *
+ * Return -1 if "aff1" is "smaller" than "aff2", 1 if "aff1" is "greater"
+ * than "aff2" and 0 if they are equal.
+ *
+ * The order is fairly arbitrary.  We do consider expressions that only involve
+ * earlier dimensions as "smaller".
+ */
+int isl_aff_plain_cmp(__isl_keep isl_aff *aff1, __isl_keep isl_aff *aff2)
+{
+	int cmp;
+	int last1, last2;
+
+	if (aff1 == aff2)
+		return 0;
+
+	if (!aff1)
+		return -1;
+	if (!aff2)
+		return 1;
+
+	cmp = isl_local_space_cmp(aff1->ls, aff2->ls);
+	if (cmp != 0)
+		return cmp;
+
+	last1 = isl_seq_last_non_zero(aff1->v->el + 1, aff1->v->size - 1);
+	last2 = isl_seq_last_non_zero(aff2->v->el + 1, aff1->v->size - 1);
+	if (last1 != last2)
+		return last1 - last2;
+
+	return isl_seq_cmp(aff1->v->el, aff2->v->el, aff1->v->size);
+}
+
+/* Compare two isl_pw_affs.
+ *
+ * Return -1 if "pa1" is "smaller" than "pa2", 1 if "pa1" is "greater"
+ * than "pa2" and 0 if they are equal.
+ *
+ * The order is fairly arbitrary.  We do consider expressions that only involve
+ * earlier dimensions as "smaller".
+ */
+int isl_pw_aff_plain_cmp(__isl_keep isl_pw_aff *pa1,
+	__isl_keep isl_pw_aff *pa2)
+{
+	int i;
+	int cmp;
+
+	if (pa1 == pa2)
+		return 0;
+
+	if (!pa1)
+		return -1;
+	if (!pa2)
+		return 1;
+
+	cmp = isl_space_cmp(pa1->dim, pa2->dim);
+	if (cmp != 0)
+		return cmp;
+
+	if (pa1->n != pa2->n)
+		return pa1->n - pa2->n;
+
+	for (i = 0; i < pa1->n; ++i) {
+		cmp = isl_set_plain_cmp(pa1->p[i].set, pa2->p[i].set);
+		if (cmp != 0)
+			return cmp;
+		cmp = isl_aff_plain_cmp(pa1->p[i].aff, pa2->p[i].aff);
+		if (cmp != 0)
+			return cmp;
+	}
+
+	return 0;
+}
+
+/* Return a piecewise affine expression that is equal to "v" on "domain".
+ */
+__isl_give isl_pw_aff *isl_pw_aff_val_on_domain(__isl_take isl_set *domain,
+	__isl_take isl_val *v)
+{
+	isl_space *space;
+	isl_local_space *ls;
+	isl_aff *aff;
+
+	space = isl_set_get_space(domain);
+	ls = isl_local_space_from_space(space);
+	aff = isl_aff_val_on_domain(ls, v);
+
+	return isl_pw_aff_alloc(domain, aff);
+}
+
+/* Return a multi affine expression that is equal to "mv" on domain
+ * space "space".
+ */
+__isl_give isl_multi_aff *isl_multi_aff_multi_val_on_space(
+	__isl_take isl_space *space, __isl_take isl_multi_val *mv)
+{
+	int i, n;
+	isl_space *space2;
+	isl_local_space *ls;
+	isl_multi_aff *ma;
+
+	if (!space || !mv)
+		goto error;
+
+	n = isl_multi_val_dim(mv, isl_dim_set);
+	space2 = isl_multi_val_get_space(mv);
+	space2 = isl_space_align_params(space2, isl_space_copy(space));
+	space = isl_space_align_params(space, isl_space_copy(space2));
+	space = isl_space_map_from_domain_and_range(space, space2);
+	ma = isl_multi_aff_alloc(isl_space_copy(space));
+	ls = isl_local_space_from_space(isl_space_domain(space));
+	for (i = 0; i < n; ++i) {
+		isl_val *v;
+		isl_aff *aff;
+
+		v = isl_multi_val_get_val(mv, i);
+		aff = isl_aff_val_on_domain(isl_local_space_copy(ls), v);
+		ma = isl_multi_aff_set_aff(ma, i, aff);
+	}
+	isl_local_space_free(ls);
+
+	isl_multi_val_free(mv);
+	return ma;
+error:
+	isl_space_free(space);
+	isl_multi_val_free(mv);
+	return NULL;
+}
+
+/* Return a piecewise multi-affine expression
+ * that is equal to "mv" on "domain".
+ */
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_multi_val_on_domain(
+	__isl_take isl_set *domain, __isl_take isl_multi_val *mv)
+{
+	isl_space *space;
+	isl_multi_aff *ma;
+
+	space = isl_set_get_space(domain);
+	ma = isl_multi_aff_multi_val_on_space(space, mv);
+
+	return isl_pw_multi_aff_alloc(domain, ma);
+}
+
+/* Internal data structure for isl_union_pw_multi_aff_multi_val_on_domain.
+ * mv is the value that should be attained on each domain set
+ * res collects the results
+ */
+struct isl_union_pw_multi_aff_multi_val_on_domain_data {
+	isl_multi_val *mv;
+	isl_union_pw_multi_aff *res;
+};
+
+/* Create an isl_pw_multi_aff equal to data->mv on "domain"
+ * and add it to data->res.
+ */
+static int pw_multi_aff_multi_val_on_domain(__isl_take isl_set *domain,
+	void *user)
+{
+	struct isl_union_pw_multi_aff_multi_val_on_domain_data *data = user;
+	isl_pw_multi_aff *pma;
+	isl_multi_val *mv;
+
+	mv = isl_multi_val_copy(data->mv);
+	pma = isl_pw_multi_aff_multi_val_on_domain(domain, mv);
+	data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
+
+	return data->res ? 0 : -1;
+}
+
+/* Return a union piecewise multi-affine expression
+ * that is equal to "mv" on "domain".
+ */
+__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)
+{
+	struct isl_union_pw_multi_aff_multi_val_on_domain_data data;
+	isl_space *space;
+
+	space = isl_union_set_get_space(domain);
+	data.res = isl_union_pw_multi_aff_empty(space);
+	data.mv = mv;
+	if (isl_union_set_foreach_set(domain,
+			&pw_multi_aff_multi_val_on_domain, &data) < 0)
+		data.res = isl_union_pw_multi_aff_free(data.res);
+	isl_union_set_free(domain);
+	isl_multi_val_free(mv);
+	return data.res;
+}

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_aff_private.h (added)
+++ polly/trunk/lib/External/isl/isl_aff_private.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,158 @@
+#ifndef ISL_AFF_PRIVATE_H
+#define ISL_AFF_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/vec.h>
+#include <isl/mat.h>
+#include <isl/local_space.h>
+#include <isl_int.h>
+#include <isl_reordering.h>
+
+/* ls represents the domain space.
+ *
+ * If the first two elements of "v" (the denominator and the constant term)
+ * are zero, then the isl_aff represents NaN.
+ */
+struct isl_aff {
+	int ref;
+
+	isl_local_space	*ls;
+	isl_vec		*v;
+};
+
+#undef EL
+#define EL isl_aff
+
+#include <isl_list_templ.h>
+
+struct isl_pw_aff_piece {
+	struct isl_set *set;
+	struct isl_aff *aff;
+};
+
+struct isl_pw_aff {
+	int ref;
+
+	isl_space *dim;
+
+	int n;
+
+	size_t size;
+	struct isl_pw_aff_piece p[1];
+};
+
+#undef EL
+#define EL isl_pw_aff
+
+#include <isl_list_templ.h>
+
+struct isl_pw_multi_aff_piece {
+	isl_set *set;
+	isl_multi_aff *maff;
+};
+
+struct isl_pw_multi_aff {
+	int ref;
+
+	isl_space *dim;
+
+	int n;
+
+	size_t size;
+	struct isl_pw_multi_aff_piece p[1];
+};
+
+__isl_give isl_aff *isl_aff_alloc_vec(__isl_take isl_local_space *ls,
+	__isl_take isl_vec *v);
+__isl_give isl_aff *isl_aff_alloc(__isl_take isl_local_space *ls);
+
+__isl_give isl_aff *isl_aff_reset_space_and_domain(__isl_take isl_aff *aff,
+	__isl_take isl_space *space, __isl_take isl_space *domain);
+__isl_give isl_aff *isl_aff_reset_domain_space(__isl_take isl_aff *aff,
+	__isl_take isl_space *dim);
+__isl_give isl_aff *isl_aff_realign_domain(__isl_take isl_aff *aff,
+	__isl_take isl_reordering *r);
+
+int isl_aff_get_constant(__isl_keep isl_aff *aff, isl_int *v);
+__isl_give isl_aff *isl_aff_set_constant(__isl_take isl_aff *aff, isl_int v);
+__isl_give isl_aff *isl_aff_set_coefficient(__isl_take isl_aff *aff,
+	enum isl_dim_type type, int pos, isl_int v);
+__isl_give isl_aff *isl_aff_add_constant(__isl_take isl_aff *aff, isl_int v);
+
+__isl_give isl_aff *isl_aff_normalize(__isl_take isl_aff *aff);
+
+__isl_give isl_aff *isl_aff_expand_divs( __isl_take isl_aff *aff,
+	__isl_take isl_mat *div, int *exp);
+
+__isl_give isl_pw_aff *isl_pw_aff_alloc_size(__isl_take isl_space *space,
+	int n);
+__isl_give isl_pw_aff *isl_pw_aff_reset_space(__isl_take isl_pw_aff *pwaff,
+	__isl_take isl_space *dim);
+__isl_give isl_pw_aff *isl_pw_aff_reset_domain_space(
+	__isl_take isl_pw_aff *pwaff, __isl_take isl_space *space);
+__isl_give isl_pw_aff *isl_pw_aff_add_disjoint(
+	__isl_take isl_pw_aff *pwaff1, __isl_take isl_pw_aff *pwaff2);
+
+__isl_give isl_pw_aff *isl_pw_aff_union_opt(__isl_take isl_pw_aff *pwaff1,
+	__isl_take isl_pw_aff *pwaff2, int max);
+
+__isl_give isl_pw_aff *isl_pw_aff_set_rational(__isl_take isl_pw_aff *pwaff);
+__isl_give isl_pw_aff_list *isl_pw_aff_list_set_rational(
+	__isl_take isl_pw_aff_list *list);
+
+__isl_give isl_pw_aff *isl_pw_aff_scale(__isl_take isl_pw_aff *pwaff,
+	isl_int f);
+__isl_give isl_pw_aff *isl_pw_aff_scale_down(__isl_take isl_pw_aff *pwaff,
+	isl_int f);
+
+int isl_aff_matching_params(__isl_keep isl_aff *aff,
+	__isl_keep isl_space *space);
+int isl_aff_check_match_domain_space(__isl_keep isl_aff *aff,
+	__isl_keep isl_space *space);
+
+#undef BASE
+#define BASE aff
+
+#include <isl_multi_templ.h>
+
+__isl_give isl_multi_aff *isl_multi_aff_dup(__isl_keep isl_multi_aff *multi);
+
+__isl_give isl_multi_aff *isl_multi_aff_align_divs(
+	__isl_take isl_multi_aff *maff);
+
+__isl_give isl_multi_aff *isl_multi_aff_from_basic_set_equalities(
+	__isl_take isl_basic_set *bset);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_reset_domain_space(
+	__isl_take isl_pw_multi_aff *pwmaff, __isl_take isl_space *space);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_reset_space(
+	__isl_take isl_pw_multi_aff *pwmaff, __isl_take isl_space *space);
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_add_disjoint(
+	__isl_take isl_pw_multi_aff *pma1, __isl_take isl_pw_multi_aff *pma2);
+
+__isl_give isl_pw_multi_aff *isl_pw_multi_aff_project_out(
+	__isl_take isl_pw_multi_aff *pma,
+	enum isl_dim_type type, unsigned first, unsigned n);
+
+void isl_seq_substitute(isl_int *p, int pos, isl_int *subs,
+	int p_len, int subs_len, isl_int v);
+void isl_seq_preimage(isl_int *dst, isl_int *src,
+	__isl_keep isl_multi_aff *ma, int n_before, int n_after,
+	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_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);
+
+int isl_pw_aff_matching_params(__isl_keep isl_pw_aff *pa,
+	__isl_keep isl_space *space);
+int isl_pw_aff_check_match_domain_space(__isl_keep isl_pw_aff *pa,
+	__isl_keep isl_space *space);
+
+#undef BASE
+#define BASE pw_aff
+
+#include <isl_multi_templ.h>
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_affine_hull.c (added)
+++ polly/trunk/lib/External/isl/isl_affine_hull.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,1405 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010      INRIA Saclay
+ * Copyright 2012      Ecole Normale Superieure
+ *
+ * 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 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
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_seq.h>
+#include <isl/set.h>
+#include <isl/lp.h>
+#include <isl/map.h>
+#include "isl_equalities.h"
+#include "isl_sample.h"
+#include "isl_tab.h"
+#include <isl_mat_private.h>
+#include <isl_vec_private.h>
+
+struct isl_basic_map *isl_basic_map_implicit_equalities(
+						struct isl_basic_map *bmap)
+{
+	struct isl_tab *tab;
+
+	if (!bmap)
+		return bmap;
+
+	bmap = isl_basic_map_gauss(bmap, NULL);
+	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
+		return bmap;
+	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_NO_IMPLICIT))
+		return bmap;
+	if (bmap->n_ineq <= 1)
+		return bmap;
+
+	tab = isl_tab_from_basic_map(bmap, 0);
+	if (isl_tab_detect_implicit_equalities(tab) < 0)
+		goto error;
+	bmap = isl_basic_map_update_from_tab(bmap, tab);
+	isl_tab_free(tab);
+	bmap = isl_basic_map_gauss(bmap, NULL);
+	ISL_F_SET(bmap, ISL_BASIC_MAP_NO_IMPLICIT);
+	return bmap;
+error:
+	isl_tab_free(tab);
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_implicit_equalities(
+						struct isl_basic_set *bset)
+{
+	return (struct isl_basic_set *)
+		isl_basic_map_implicit_equalities((struct isl_basic_map*)bset);
+}
+
+struct isl_map *isl_map_implicit_equalities(struct isl_map *map)
+{
+	int i;
+
+	if (!map)
+		return map;
+
+	for (i = 0; i < map->n; ++i) {
+		map->p[i] = isl_basic_map_implicit_equalities(map->p[i]);
+		if (!map->p[i])
+			goto error;
+	}
+
+	return map;
+error:
+	isl_map_free(map);
+	return NULL;
+}
+
+/* Make eq[row][col] of both bmaps equal so we can add the row
+ * add the column to the common matrix.
+ * Note that because of the echelon form, the columns of row row
+ * after column col are zero.
+ */
+static void set_common_multiple(
+	struct isl_basic_set *bset1, struct isl_basic_set *bset2,
+	unsigned row, unsigned col)
+{
+	isl_int m, c;
+
+	if (isl_int_eq(bset1->eq[row][col], bset2->eq[row][col]))
+		return;
+
+	isl_int_init(c);
+	isl_int_init(m);
+	isl_int_lcm(m, bset1->eq[row][col], bset2->eq[row][col]);
+	isl_int_divexact(c, m, bset1->eq[row][col]);
+	isl_seq_scale(bset1->eq[row], bset1->eq[row], c, col+1);
+	isl_int_divexact(c, m, bset2->eq[row][col]);
+	isl_seq_scale(bset2->eq[row], bset2->eq[row], c, col+1);
+	isl_int_clear(c);
+	isl_int_clear(m);
+}
+
+/* Delete a given equality, moving all the following equalities one up.
+ */
+static void delete_row(struct isl_basic_set *bset, unsigned row)
+{
+	isl_int *t;
+	int r;
+
+	t = bset->eq[row];
+	bset->n_eq--;
+	for (r = row; r < bset->n_eq; ++r)
+		bset->eq[r] = bset->eq[r+1];
+	bset->eq[bset->n_eq] = t;
+}
+
+/* Make first row entries in column col of bset1 identical to
+ * those of bset2, using the fact that entry bset1->eq[row][col]=a
+ * is non-zero.  Initially, these elements of bset1 are all zero.
+ * For each row i < row, we set
+ *		A[i] = a * A[i] + B[i][col] * A[row]
+ *		B[i] = a * B[i]
+ * so that
+ *		A[i][col] = B[i][col] = a * old(B[i][col])
+ */
+static void construct_column(
+	struct isl_basic_set *bset1, struct isl_basic_set *bset2,
+	unsigned row, unsigned col)
+{
+	int r;
+	isl_int a;
+	isl_int b;
+	unsigned total;
+
+	isl_int_init(a);
+	isl_int_init(b);
+	total = 1 + isl_basic_set_n_dim(bset1);
+	for (r = 0; r < row; ++r) {
+		if (isl_int_is_zero(bset2->eq[r][col]))
+			continue;
+		isl_int_gcd(b, bset2->eq[r][col], bset1->eq[row][col]);
+		isl_int_divexact(a, bset1->eq[row][col], b);
+		isl_int_divexact(b, bset2->eq[r][col], b);
+		isl_seq_combine(bset1->eq[r], a, bset1->eq[r],
+					      b, bset1->eq[row], total);
+		isl_seq_scale(bset2->eq[r], bset2->eq[r], a, total);
+	}
+	isl_int_clear(a);
+	isl_int_clear(b);
+	delete_row(bset1, row);
+}
+
+/* Make first row entries in column col of bset1 identical to
+ * those of bset2, using only these entries of the two matrices.
+ * Let t be the last row with different entries.
+ * For each row i < t, we set
+ *	A[i] = (A[t][col]-B[t][col]) * A[i] + (B[i][col]-A[i][col) * A[t]
+ *	B[i] = (A[t][col]-B[t][col]) * B[i] + (B[i][col]-A[i][col) * B[t]
+ * so that
+ *	A[i][col] = B[i][col] = old(A[t][col]*B[i][col]-A[i][col]*B[t][col])
+ */
+static int transform_column(
+	struct isl_basic_set *bset1, struct isl_basic_set *bset2,
+	unsigned row, unsigned col)
+{
+	int i, t;
+	isl_int a, b, g;
+	unsigned total;
+
+	for (t = row-1; t >= 0; --t)
+		if (isl_int_ne(bset1->eq[t][col], bset2->eq[t][col]))
+			break;
+	if (t < 0)
+		return 0;
+
+	total = 1 + isl_basic_set_n_dim(bset1);
+	isl_int_init(a);
+	isl_int_init(b);
+	isl_int_init(g);
+	isl_int_sub(b, bset1->eq[t][col], bset2->eq[t][col]);
+	for (i = 0; i < t; ++i) {
+		isl_int_sub(a, bset2->eq[i][col], bset1->eq[i][col]);
+		isl_int_gcd(g, a, b);
+		isl_int_divexact(a, a, g);
+		isl_int_divexact(g, b, g);
+		isl_seq_combine(bset1->eq[i], g, bset1->eq[i], a, bset1->eq[t],
+				total);
+		isl_seq_combine(bset2->eq[i], g, bset2->eq[i], a, bset2->eq[t],
+				total);
+	}
+	isl_int_clear(a);
+	isl_int_clear(b);
+	isl_int_clear(g);
+	delete_row(bset1, t);
+	delete_row(bset2, t);
+	return 1;
+}
+
+/* The implementation is based on Section 5.2 of Michael Karr,
+ * "Affine Relationships Among Variables of a Program",
+ * except that the echelon form we use starts from the last column
+ * and that we are dealing with integer coefficients.
+ */
+static struct isl_basic_set *affine_hull(
+	struct isl_basic_set *bset1, struct isl_basic_set *bset2)
+{
+	unsigned total;
+	int col;
+	int row;
+
+	if (!bset1 || !bset2)
+		goto error;
+
+	total = 1 + isl_basic_set_n_dim(bset1);
+
+	row = 0;
+	for (col = total-1; col >= 0; --col) {
+		int is_zero1 = row >= bset1->n_eq ||
+			isl_int_is_zero(bset1->eq[row][col]);
+		int is_zero2 = row >= bset2->n_eq ||
+			isl_int_is_zero(bset2->eq[row][col]);
+		if (!is_zero1 && !is_zero2) {
+			set_common_multiple(bset1, bset2, row, col);
+			++row;
+		} else if (!is_zero1 && is_zero2) {
+			construct_column(bset1, bset2, row, col);
+		} else if (is_zero1 && !is_zero2) {
+			construct_column(bset2, bset1, row, col);
+		} else {
+			if (transform_column(bset1, bset2, row, col))
+				--row;
+		}
+	}
+	isl_assert(bset1->ctx, row == bset1->n_eq, goto error);
+	isl_basic_set_free(bset2);
+	bset1 = isl_basic_set_normalize_constraints(bset1);
+	return bset1;
+error:
+	isl_basic_set_free(bset1);
+	isl_basic_set_free(bset2);
+	return NULL;
+}
+
+/* Find an integer point in the set represented by "tab"
+ * that lies outside of the equality "eq" e(x) = 0.
+ * If "up" is true, look for a point satisfying e(x) - 1 >= 0.
+ * Otherwise, look for a point satisfying -e(x) - 1 >= 0 (i.e., e(x) <= -1).
+ * The point, if found, is returned.
+ * If no point can be found, a zero-length vector is returned.
+ *
+ * Before solving an ILP problem, we first check if simply
+ * adding the normal of the constraint to one of the known
+ * integer points in the basic set represented by "tab"
+ * yields another point inside the basic set.
+ *
+ * The caller of this function ensures that the tableau is bounded or
+ * that tab->basis and tab->n_unbounded have been set appropriately.
+ */
+static struct isl_vec *outside_point(struct isl_tab *tab, isl_int *eq, int up)
+{
+	struct isl_ctx *ctx;
+	struct isl_vec *sample = NULL;
+	struct isl_tab_undo *snap;
+	unsigned dim;
+
+	if (!tab)
+		return NULL;
+	ctx = tab->mat->ctx;
+
+	dim = tab->n_var;
+	sample = isl_vec_alloc(ctx, 1 + dim);
+	if (!sample)
+		return NULL;
+	isl_int_set_si(sample->el[0], 1);
+	isl_seq_combine(sample->el + 1,
+		ctx->one, tab->bmap->sample->el + 1,
+		up ? ctx->one : ctx->negone, eq + 1, dim);
+	if (isl_basic_map_contains(tab->bmap, sample))
+		return sample;
+	isl_vec_free(sample);
+	sample = NULL;
+
+	snap = isl_tab_snap(tab);
+
+	if (!up)
+		isl_seq_neg(eq, eq, 1 + dim);
+	isl_int_sub_ui(eq[0], eq[0], 1);
+
+	if (isl_tab_extend_cons(tab, 1) < 0)
+		goto error;
+	if (isl_tab_add_ineq(tab, eq) < 0)
+		goto error;
+
+	sample = isl_tab_sample(tab);
+
+	isl_int_add_ui(eq[0], eq[0], 1);
+	if (!up)
+		isl_seq_neg(eq, eq, 1 + dim);
+
+	if (sample && isl_tab_rollback(tab, snap) < 0)
+		goto error;
+
+	return sample;
+error:
+	isl_vec_free(sample);
+	return NULL;
+}
+
+struct isl_basic_set *isl_basic_set_recession_cone(struct isl_basic_set *bset)
+{
+	int i;
+
+	bset = isl_basic_set_cow(bset);
+	if (!bset)
+		return NULL;
+	isl_assert(bset->ctx, bset->n_div == 0, goto error);
+
+	for (i = 0; i < bset->n_eq; ++i)
+		isl_int_set_si(bset->eq[i][0], 0);
+
+	for (i = 0; i < bset->n_ineq; ++i)
+		isl_int_set_si(bset->ineq[i][0], 0);
+
+	ISL_F_CLR(bset, ISL_BASIC_SET_NO_IMPLICIT);
+	return isl_basic_set_implicit_equalities(bset);
+error:
+	isl_basic_set_free(bset);
+	return NULL;
+}
+
+__isl_give isl_set *isl_set_recession_cone(__isl_take isl_set *set)
+{
+	int i;
+
+	if (!set)
+		return NULL;
+	if (set->n == 0)
+		return set;
+
+	set = isl_set_remove_divs(set);
+	set = isl_set_cow(set);
+	if (!set)
+		return NULL;
+
+	for (i = 0; i < set->n; ++i) {
+		set->p[i] = isl_basic_set_recession_cone(set->p[i]);
+		if (!set->p[i])
+			goto error;
+	}
+
+	return set;
+error:
+	isl_set_free(set);
+	return NULL;
+}
+
+/* Move "sample" to a point that is one up (or down) from the original
+ * point in dimension "pos".
+ */
+static void adjacent_point(__isl_keep isl_vec *sample, int pos, int up)
+{
+	if (up)
+		isl_int_add_ui(sample->el[1 + pos], sample->el[1 + pos], 1);
+	else
+		isl_int_sub_ui(sample->el[1 + pos], sample->el[1 + pos], 1);
+}
+
+/* Check if any points that are adjacent to "sample" also belong to "bset".
+ * If so, add them to "hull" and return the updated hull.
+ *
+ * Before checking whether and adjacent point belongs to "bset", we first
+ * check whether it already belongs to "hull" as this test is typically
+ * much cheaper.
+ */
+static __isl_give isl_basic_set *add_adjacent_points(
+	__isl_take isl_basic_set *hull, __isl_take isl_vec *sample,
+	__isl_keep isl_basic_set *bset)
+{
+	int i, up;
+	int dim;
+
+	if (!sample)
+		goto error;
+
+	dim = isl_basic_set_dim(hull, isl_dim_set);
+
+	for (i = 0; i < dim; ++i) {
+		for (up = 0; up <= 1; ++up) {
+			int contains;
+			isl_basic_set *point;
+
+			adjacent_point(sample, i, up);
+			contains = isl_basic_set_contains(hull, sample);
+			if (contains < 0)
+				goto error;
+			if (contains) {
+				adjacent_point(sample, i, !up);
+				continue;
+			}
+			contains = isl_basic_set_contains(bset, sample);
+			if (contains < 0)
+				goto error;
+			if (contains) {
+				point = isl_basic_set_from_vec(
+							isl_vec_copy(sample));
+				hull = affine_hull(hull, point);
+			}
+			adjacent_point(sample, i, !up);
+			if (contains)
+				break;
+		}
+	}
+
+	isl_vec_free(sample);
+
+	return hull;
+error:
+	isl_vec_free(sample);
+	isl_basic_set_free(hull);
+	return NULL;
+}
+
+/* Extend an initial (under-)approximation of the affine hull of basic
+ * set represented by the tableau "tab"
+ * by looking for points that do not satisfy one of the equalities
+ * in the current approximation and adding them to that approximation
+ * until no such points can be found any more.
+ *
+ * The caller of this function ensures that "tab" is bounded or
+ * that tab->basis and tab->n_unbounded have been set appropriately.
+ *
+ * "bset" may be either NULL or the basic set represented by "tab".
+ * If "bset" is not NULL, we check for any point we find if any
+ * of its adjacent points also belong to "bset".
+ */
+static __isl_give isl_basic_set *extend_affine_hull(struct isl_tab *tab,
+	__isl_take isl_basic_set *hull, __isl_keep isl_basic_set *bset)
+{
+	int i, j;
+	unsigned dim;
+
+	if (!tab || !hull)
+		goto error;
+
+	dim = tab->n_var;
+
+	if (isl_tab_extend_cons(tab, 2 * dim + 1) < 0)
+		goto error;
+
+	for (i = 0; i < dim; ++i) {
+		struct isl_vec *sample;
+		struct isl_basic_set *point;
+		for (j = 0; j < hull->n_eq; ++j) {
+			sample = outside_point(tab, hull->eq[j], 1);
+			if (!sample)
+				goto error;
+			if (sample->size > 0)
+				break;
+			isl_vec_free(sample);
+			sample = outside_point(tab, hull->eq[j], 0);
+			if (!sample)
+				goto error;
+			if (sample->size > 0)
+				break;
+			isl_vec_free(sample);
+
+			if (isl_tab_add_eq(tab, hull->eq[j]) < 0)
+				goto error;
+		}
+		if (j == hull->n_eq)
+			break;
+		if (tab->samples &&
+		    isl_tab_add_sample(tab, isl_vec_copy(sample)) < 0)
+			hull = isl_basic_set_free(hull);
+		if (bset)
+			hull = add_adjacent_points(hull, isl_vec_copy(sample),
+						    bset);
+		point = isl_basic_set_from_vec(sample);
+		hull = affine_hull(hull, point);
+		if (!hull)
+			return NULL;
+	}
+
+	return hull;
+error:
+	isl_basic_set_free(hull);
+	return NULL;
+}
+
+/* Drop all constraints in bmap that involve any of the dimensions
+ * first to first+n-1.
+ */
+static __isl_give isl_basic_map *isl_basic_map_drop_constraints_involving(
+	__isl_take isl_basic_map *bmap, unsigned first, unsigned n)
+{
+	int i;
+
+	if (n == 0)
+		return bmap;
+
+	bmap = isl_basic_map_cow(bmap);
+
+	if (!bmap)
+		return NULL;
+
+	for (i = bmap->n_eq - 1; i >= 0; --i) {
+		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) == -1)
+			continue;
+		isl_basic_map_drop_equality(bmap, i);
+	}
+
+	for (i = bmap->n_ineq - 1; i >= 0; --i) {
+		if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) == -1)
+			continue;
+		isl_basic_map_drop_inequality(bmap, i);
+	}
+
+	bmap = isl_basic_map_add_known_div_constraints(bmap);
+	return bmap;
+}
+
+/* Drop all constraints in bset that involve any of the dimensions
+ * first to first+n-1.
+ */
+__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving(
+	__isl_take isl_basic_set *bset, unsigned first, unsigned n)
+{
+	return isl_basic_map_drop_constraints_involving(bset, first, n);
+}
+
+/* Drop all constraints in bmap that do not involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__isl_give isl_basic_map *isl_basic_map_drop_constraints_not_involving_dims(
+	__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	int i;
+	unsigned dim;
+
+	if (n == 0) {
+		isl_space *space = isl_basic_map_get_space(bmap);
+		isl_basic_map_free(bmap);
+		return isl_basic_map_universe(space);
+	}
+	bmap = isl_basic_map_cow(bmap);
+	if (!bmap)
+		return NULL;
+
+	dim = isl_basic_map_dim(bmap, type);
+	if (first + n > dim || first + n < first)
+		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+			"index out of bounds", return isl_basic_map_free(bmap));
+
+	first += isl_basic_map_offset(bmap, type) - 1;
+
+	for (i = bmap->n_eq - 1; i >= 0; --i) {
+		if (isl_seq_first_non_zero(bmap->eq[i] + 1 + first, n) != -1)
+			continue;
+		isl_basic_map_drop_equality(bmap, i);
+	}
+
+	for (i = bmap->n_ineq - 1; i >= 0; --i) {
+		if (isl_seq_first_non_zero(bmap->ineq[i] + 1 + first, n) != -1)
+			continue;
+		isl_basic_map_drop_inequality(bmap, i);
+	}
+
+	bmap = isl_basic_map_add_known_div_constraints(bmap);
+	return bmap;
+}
+
+/* Drop all constraints in bset that do not involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__isl_give isl_basic_set *isl_basic_set_drop_constraints_not_involving_dims(
+	__isl_take isl_basic_set *bset,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	return isl_basic_map_drop_constraints_not_involving_dims(bset,
+							    type, first, n);
+}
+
+/* Drop all constraints in bmap that involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__isl_give isl_basic_map *isl_basic_map_drop_constraints_involving_dims(
+	__isl_take isl_basic_map *bmap,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	unsigned dim;
+
+	if (!bmap)
+		return NULL;
+	if (n == 0)
+		return bmap;
+
+	dim = isl_basic_map_dim(bmap, type);
+	if (first + n > dim || first + n < first)
+		isl_die(isl_basic_map_get_ctx(bmap), isl_error_invalid,
+			"index out of bounds", return isl_basic_map_free(bmap));
+
+	bmap = isl_basic_map_remove_divs_involving_dims(bmap, type, first, n);
+	first += isl_basic_map_offset(bmap, type) - 1;
+	return isl_basic_map_drop_constraints_involving(bmap, first, n);
+}
+
+/* Drop all constraints in bset that involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__isl_give isl_basic_set *isl_basic_set_drop_constraints_involving_dims(
+	__isl_take isl_basic_set *bset,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	return isl_basic_map_drop_constraints_involving_dims(bset,
+							    type, first, n);
+}
+
+/* Drop all constraints in map that involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__isl_give isl_map *isl_map_drop_constraints_involving_dims(
+	__isl_take isl_map *map,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	int i;
+	unsigned dim;
+
+	if (!map)
+		return NULL;
+	if (n == 0)
+		return map;
+
+	dim = isl_map_dim(map, type);
+	if (first + n > dim || first + n < first)
+		isl_die(isl_map_get_ctx(map), isl_error_invalid,
+			"index out of bounds", return isl_map_free(map));
+
+	map = isl_map_cow(map);
+	if (!map)
+		return NULL;
+
+	for (i = 0; i < map->n; ++i) {
+		map->p[i] = isl_basic_map_drop_constraints_involving_dims(
+						    map->p[i], type, first, n);
+		if (!map->p[i])
+			return isl_map_free(map);
+	}
+
+	return map;
+}
+
+/* Drop all constraints in set that involve any of the dimensions
+ * first to first + n - 1 of the given type.
+ */
+__isl_give isl_set *isl_set_drop_constraints_involving_dims(
+	__isl_take isl_set *set,
+	enum isl_dim_type type, unsigned first, unsigned n)
+{
+	return isl_map_drop_constraints_involving_dims(set, type, first, n);
+}
+
+/* Construct an initial underapproximatino of the hull of "bset"
+ * from "sample" and any of its adjacent points that also belong to "bset".
+ */
+static __isl_give isl_basic_set *initialize_hull(__isl_keep isl_basic_set *bset,
+	__isl_take isl_vec *sample)
+{
+	isl_basic_set *hull;
+
+	hull = isl_basic_set_from_vec(isl_vec_copy(sample));
+	hull = add_adjacent_points(hull, sample, bset);
+
+	return hull;
+}
+
+/* Look for all equalities satisfied by the integer points in bset,
+ * which is assumed to be bounded.
+ *
+ * The equalities are obtained by successively looking for
+ * a point that is affinely independent of the points found so far.
+ * In particular, for each equality satisfied by the points so far,
+ * we check if there is any point on a hyperplane parallel to the
+ * corresponding hyperplane shifted by at least one (in either direction).
+ */
+static struct isl_basic_set *uset_affine_hull_bounded(struct isl_basic_set *bset)
+{
+	struct isl_vec *sample = NULL;
+	struct isl_basic_set *hull;
+	struct isl_tab *tab = NULL;
+	unsigned dim;
+
+	if (isl_basic_set_plain_is_empty(bset))
+		return bset;
+
+	dim = isl_basic_set_n_dim(bset);
+
+	if (bset->sample && bset->sample->size == 1 + dim) {
+		int contains = isl_basic_set_contains(bset, bset->sample);
+		if (contains < 0)
+			goto error;
+		if (contains) {
+			if (dim == 0)
+				return bset;
+			sample = isl_vec_copy(bset->sample);
+		} else {
+			isl_vec_free(bset->sample);
+			bset->sample = NULL;
+		}
+	}
+
+	tab = isl_tab_from_basic_set(bset, 1);
+	if (!tab)
+		goto error;
+	if (tab->empty) {
+		isl_tab_free(tab);
+		isl_vec_free(sample);
+		return isl_basic_set_set_to_empty(bset);
+	}
+
+	if (!sample) {
+		struct isl_tab_undo *snap;
+		snap = isl_tab_snap(tab);
+		sample = isl_tab_sample(tab);
+		if (isl_tab_rollback(tab, snap) < 0)
+			goto error;
+		isl_vec_free(tab->bmap->sample);
+		tab->bmap->sample = isl_vec_copy(sample);
+	}
+
+	if (!sample)
+		goto error;
+	if (sample->size == 0) {
+		isl_tab_free(tab);
+		isl_vec_free(sample);
+		return isl_basic_set_set_to_empty(bset);
+	}
+
+	hull = initialize_hull(bset, sample);
+
+	hull = extend_affine_hull(tab, hull, bset);
+	isl_basic_set_free(bset);
+	isl_tab_free(tab);
+
+	return hull;
+error:
+	isl_vec_free(sample);
+	isl_tab_free(tab);
+	isl_basic_set_free(bset);
+	return NULL;
+}
+
+/* Given an unbounded tableau and an integer point satisfying the tableau,
+ * construct an initial affine hull containing the recession cone
+ * shifted to the given point.
+ *
+ * The unbounded directions are taken from the last rows of the basis,
+ * which is assumed to have been initialized appropriately.
+ */
+static __isl_give isl_basic_set *initial_hull(struct isl_tab *tab,
+	__isl_take isl_vec *vec)
+{
+	int i;
+	int k;
+	struct isl_basic_set *bset = NULL;
+	struct isl_ctx *ctx;
+	unsigned dim;
+
+	if (!vec || !tab)
+		return NULL;
+	ctx = vec->ctx;
+	isl_assert(ctx, vec->size != 0, goto error);
+
+	bset = isl_basic_set_alloc(ctx, 0, vec->size - 1, 0, vec->size - 1, 0);
+	if (!bset)
+		goto error;
+	dim = isl_basic_set_n_dim(bset) - tab->n_unbounded;
+	for (i = 0; i < dim; ++i) {
+		k = isl_basic_set_alloc_equality(bset);
+		if (k < 0)
+			goto error;
+		isl_seq_cpy(bset->eq[k] + 1, tab->basis->row[1 + i] + 1,
+			    vec->size - 1);
+		isl_seq_inner_product(bset->eq[k] + 1, vec->el +1,
+				      vec->size - 1, &bset->eq[k][0]);
+		isl_int_neg(bset->eq[k][0], bset->eq[k][0]);
+	}
+	bset->sample = vec;
+	bset = isl_basic_set_gauss(bset, NULL);
+
+	return bset;
+error:
+	isl_basic_set_free(bset);
+	isl_vec_free(vec);
+	return NULL;
+}
+
+/* Given a tableau of a set and a tableau of the corresponding
+ * recession cone, detect and add all equalities to the tableau.
+ * If the tableau is bounded, then we can simply keep the
+ * tableau in its state after the return from extend_affine_hull.
+ * However, if the tableau is unbounded, then
+ * isl_tab_set_initial_basis_with_cone will add some additional
+ * constraints to the tableau that have to be removed again.
+ * In this case, we therefore rollback to the state before
+ * any constraints were added and then add the equalities back in.
+ */
+struct isl_tab *isl_tab_detect_equalities(struct isl_tab *tab,
+	struct isl_tab *tab_cone)
+{
+	int j;
+	struct isl_vec *sample;
+	struct isl_basic_set *hull = NULL;
+	struct isl_tab_undo *snap;
+
+	if (!tab || !tab_cone)
+		goto error;
+
+	snap = isl_tab_snap(tab);
+
+	isl_mat_free(tab->basis);
+	tab->basis = NULL;
+
+	isl_assert(tab->mat->ctx, tab->bmap, goto error);
+	isl_assert(tab->mat->ctx, tab->samples, goto error);
+	isl_assert(tab->mat->ctx, tab->samples->n_col == 1 + tab->n_var, goto error);
+	isl_assert(tab->mat->ctx, tab->n_sample > tab->n_outside, goto error);
+
+	if (isl_tab_set_initial_basis_with_cone(tab, tab_cone) < 0)
+		goto error;
+
+	sample = isl_vec_alloc(tab->mat->ctx, 1 + tab->n_var);
+	if (!sample)
+		goto error;
+
+	isl_seq_cpy(sample->el, tab->samples->row[tab->n_outside], sample->size);
+
+	isl_vec_free(tab->bmap->sample);
+	tab->bmap->sample = isl_vec_copy(sample);
+
+	if (tab->n_unbounded == 0)
+		hull = isl_basic_set_from_vec(isl_vec_copy(sample));
+	else
+		hull = initial_hull(tab, isl_vec_copy(sample));
+
+	for (j = tab->n_outside + 1; j < tab->n_sample; ++j) {
+		isl_seq_cpy(sample->el, tab->samples->row[j], sample->size);
+		hull = affine_hull(hull,
+				isl_basic_set_from_vec(isl_vec_copy(sample)));
+	}
+
+	isl_vec_free(sample);
+
+	hull = extend_affine_hull(tab, hull, NULL);
+	if (!hull)
+		goto error;
+
+	if (tab->n_unbounded == 0) {
+		isl_basic_set_free(hull);
+		return tab;
+	}
+
+	if (isl_tab_rollback(tab, snap) < 0)
+		goto error;
+
+	if (hull->n_eq > tab->n_zero) {
+		for (j = 0; j < hull->n_eq; ++j) {
+			isl_seq_normalize(tab->mat->ctx, hull->eq[j], 1 + tab->n_var);
+			if (isl_tab_add_eq(tab, hull->eq[j]) < 0)
+				goto error;
+		}
+	}
+
+	isl_basic_set_free(hull);
+
+	return tab;
+error:
+	isl_basic_set_free(hull);
+	isl_tab_free(tab);
+	return NULL;
+}
+
+/* Compute the affine hull of "bset", where "cone" is the recession cone
+ * of "bset".
+ *
+ * We first compute a unimodular transformation that puts the unbounded
+ * directions in the last dimensions.  In particular, we take a transformation
+ * that maps all equalities to equalities (in HNF) on the first dimensions.
+ * Let x be the original dimensions and y the transformed, with y_1 bounded
+ * and y_2 unbounded.
+ *
+ *	       [ y_1 ]			[ y_1 ]   [ Q_1 ]
+ *	x = U  [ y_2 ]			[ y_2 ] = [ Q_2 ] x
+ *
+ * Let's call the input basic set S.  We compute S' = preimage(S, U)
+ * and drop the final dimensions including any constraints involving them.
+ * This results in set S''.
+ * Then we compute the affine hull A'' of S''.
+ * Let F y_1 >= g be the constraint system of A''.  In the transformed
+ * space the y_2 are unbounded, so we can add them back without any constraints,
+ * resulting in
+ *
+ *		        [ y_1 ]
+ *		[ F 0 ] [ y_2 ] >= g
+ * or
+ *		        [ Q_1 ]
+ *		[ F 0 ] [ Q_2 ] x >= g
+ * or
+ *		F Q_1 x >= g
+ *
+ * The affine hull in the original space is then obtained as
+ * A = preimage(A'', Q_1).
+ */
+static struct isl_basic_set *affine_hull_with_cone(struct isl_basic_set *bset,
+	struct isl_basic_set *cone)
+{
+	unsigned total;
+	unsigned cone_dim;
+	struct isl_basic_set *hull;
+	struct isl_mat *M, *U, *Q;
+
+	if (!bset || !cone)
+		goto error;
+
+	total = isl_basic_set_total_dim(cone);
+	cone_dim = total - cone->n_eq;
+
+	M = isl_mat_sub_alloc6(bset->ctx, cone->eq, 0, cone->n_eq, 1, total);
+	M = isl_mat_left_hermite(M, 0, &U, &Q);
+	if (!M)
+		goto error;
+	isl_mat_free(M);
+
+	U = isl_mat_lin_to_aff(U);
+	bset = isl_basic_set_preimage(bset, isl_mat_copy(U));
+
+	bset = isl_basic_set_drop_constraints_involving(bset, total - cone_dim,
+							cone_dim);
+	bset = isl_basic_set_drop_dims(bset, total - cone_dim, cone_dim);
+
+	Q = isl_mat_lin_to_aff(Q);
+	Q = isl_mat_drop_rows(Q, 1 + total - cone_dim, cone_dim);
+
+	if (bset && bset->sample && bset->sample->size == 1 + total)
+		bset->sample = isl_mat_vec_product(isl_mat_copy(Q), bset->sample);
+
+	hull = uset_affine_hull_bounded(bset);
+
+	if (!hull) {
+		isl_mat_free(Q);
+		isl_mat_free(U);
+	} else {
+		struct isl_vec *sample = isl_vec_copy(hull->sample);
+		U = isl_mat_drop_cols(U, 1 + total - cone_dim, cone_dim);
+		if (sample && sample->size > 0)
+			sample = isl_mat_vec_product(U, sample);
+		else
+			isl_mat_free(U);
+		hull = isl_basic_set_preimage(hull, Q);
+		if (hull) {
+			isl_vec_free(hull->sample);
+			hull->sample = sample;
+		} else
+			isl_vec_free(sample);
+	}
+
+	isl_basic_set_free(cone);
+
+	return hull;
+error:
+	isl_basic_set_free(bset);
+	isl_basic_set_free(cone);
+	return NULL;
+}
+
+/* Look for all equalities satisfied by the integer points in bset,
+ * which is assumed not to have any explicit equalities.
+ *
+ * The equalities are obtained by successively looking for
+ * a point that is affinely independent of the points found so far.
+ * In particular, for each equality satisfied by the points so far,
+ * we check if there is any point on a hyperplane parallel to the
+ * corresponding hyperplane shifted by at least one (in either direction).
+ *
+ * Before looking for any outside points, we first compute the recession
+ * cone.  The directions of this recession cone will always be part
+ * of the affine hull, so there is no need for looking for any points
+ * in these directions.
+ * In particular, if the recession cone is full-dimensional, then
+ * the affine hull is simply the whole universe.
+ */
+static struct isl_basic_set *uset_affine_hull(struct isl_basic_set *bset)
+{
+	struct isl_basic_set *cone;
+
+	if (isl_basic_set_plain_is_empty(bset))
+		return bset;
+
+	cone = isl_basic_set_recession_cone(isl_basic_set_copy(bset));
+	if (!cone)
+		goto error;
+	if (cone->n_eq == 0) {
+		struct isl_basic_set *hull;
+		isl_basic_set_free(cone);
+		hull = isl_basic_set_universe_like(bset);
+		isl_basic_set_free(bset);
+		return hull;
+	}
+
+	if (cone->n_eq < isl_basic_set_total_dim(cone))
+		return affine_hull_with_cone(bset, cone);
+
+	isl_basic_set_free(cone);
+	return uset_affine_hull_bounded(bset);
+error:
+	isl_basic_set_free(bset);
+	return NULL;
+}
+
+/* Look for all equalities satisfied by the integer points in bmap
+ * that are independent of the equalities already explicitly available
+ * in bmap.
+ *
+ * We first remove all equalities already explicitly available,
+ * then look for additional equalities in the reduced space
+ * and then transform the result to the original space.
+ * The original equalities are _not_ added to this set.  This is
+ * the responsibility of the calling function.
+ * The resulting basic set has all meaning about the dimensions removed.
+ * In particular, dimensions that correspond to existential variables
+ * in bmap and that are found to be fixed are not removed.
+ */
+static struct isl_basic_set *equalities_in_underlying_set(
+						struct isl_basic_map *bmap)
+{
+	struct isl_mat *T1 = NULL;
+	struct isl_mat *T2 = NULL;
+	struct isl_basic_set *bset = NULL;
+	struct isl_basic_set *hull = NULL;
+
+	bset = isl_basic_map_underlying_set(bmap);
+	if (!bset)
+		return NULL;
+	if (bset->n_eq)
+		bset = isl_basic_set_remove_equalities(bset, &T1, &T2);
+	if (!bset)
+		goto error;
+
+	hull = uset_affine_hull(bset);
+	if (!T2)
+		return hull;
+
+	if (!hull) {
+		isl_mat_free(T1);
+		isl_mat_free(T2);
+	} else {
+		struct isl_vec *sample = isl_vec_copy(hull->sample);
+		if (sample && sample->size > 0)
+			sample = isl_mat_vec_product(T1, sample);
+		else
+			isl_mat_free(T1);
+		hull = isl_basic_set_preimage(hull, T2);
+		if (hull) {
+			isl_vec_free(hull->sample);
+			hull->sample = sample;
+		} else
+			isl_vec_free(sample);
+	}
+
+	return hull;
+error:
+	isl_mat_free(T1);
+	isl_mat_free(T2);
+	isl_basic_set_free(bset);
+	isl_basic_set_free(hull);
+	return NULL;
+}
+
+/* Detect and make explicit all equalities satisfied by the (integer)
+ * points in bmap.
+ */
+struct isl_basic_map *isl_basic_map_detect_equalities(
+						struct isl_basic_map *bmap)
+{
+	int i, j;
+	struct isl_basic_set *hull = NULL;
+
+	if (!bmap)
+		return NULL;
+	if (bmap->n_ineq == 0)
+		return bmap;
+	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_EMPTY))
+		return bmap;
+	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_ALL_EQUALITIES))
+		return bmap;
+	if (ISL_F_ISSET(bmap, ISL_BASIC_MAP_RATIONAL))
+		return isl_basic_map_implicit_equalities(bmap);
+
+	hull = equalities_in_underlying_set(isl_basic_map_copy(bmap));
+	if (!hull)
+		goto error;
+	if (ISL_F_ISSET(hull, ISL_BASIC_SET_EMPTY)) {
+		isl_basic_set_free(hull);
+		return isl_basic_map_set_to_empty(bmap);
+	}
+	bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim), 0,
+					hull->n_eq, 0);
+	for (i = 0; i < hull->n_eq; ++i) {
+		j = isl_basic_map_alloc_equality(bmap);
+		if (j < 0)
+			goto error;
+		isl_seq_cpy(bmap->eq[j], hull->eq[i],
+				1 + isl_basic_set_total_dim(hull));
+	}
+	isl_vec_free(bmap->sample);
+	bmap->sample = isl_vec_copy(hull->sample);
+	isl_basic_set_free(hull);
+	ISL_F_SET(bmap, ISL_BASIC_MAP_NO_IMPLICIT | ISL_BASIC_MAP_ALL_EQUALITIES);
+	bmap = isl_basic_map_simplify(bmap);
+	return isl_basic_map_finalize(bmap);
+error:
+	isl_basic_set_free(hull);
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+__isl_give isl_basic_set *isl_basic_set_detect_equalities(
+						__isl_take isl_basic_set *bset)
+{
+	return (isl_basic_set *)
+		isl_basic_map_detect_equalities((isl_basic_map *)bset);
+}
+
+__isl_give isl_map *isl_map_detect_equalities(__isl_take isl_map *map)
+{
+	return isl_map_inline_foreach_basic_map(map,
+					    &isl_basic_map_detect_equalities);
+}
+
+__isl_give isl_set *isl_set_detect_equalities(__isl_take isl_set *set)
+{
+	return (isl_set *)isl_map_detect_equalities((isl_map *)set);
+}
+
+/* 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.
+ */
+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);
+	return bmap;
+}
+
+struct isl_basic_set *isl_basic_set_affine_hull(struct isl_basic_set *bset)
+{
+	return (struct isl_basic_set *)
+		isl_basic_map_affine_hull((struct isl_basic_map *)bset);
+}
+
+/* Given a rational affine matrix "M", add stride constraints to "bmap"
+ * that ensure that
+ *
+ *		M(x)
+ *
+ * is an integer vector.  The variables x include all the variables
+ * of "bmap" except the unknown divs.
+ *
+ * If d is the common denominator of M, then we need to impose that
+ *
+ *		d M(x) = 0 	mod d
+ *
+ * or
+ *
+ *		exists alpha : d M(x) = d alpha
+ *
+ * This function is similar to add_strides in isl_morph.c
+ */
+static __isl_give isl_basic_map *add_strides(__isl_take isl_basic_map *bmap,
+	__isl_keep isl_mat *M, int n_known)
+{
+	int i, div, k;
+	isl_int gcd;
+
+	if (isl_int_is_one(M->row[0][0]))
+		return bmap;
+
+	bmap = isl_basic_map_extend_space(bmap, isl_space_copy(bmap->dim),
+					M->n_row - 1, M->n_row - 1, 0);
+
+	isl_int_init(gcd);
+	for (i = 1; i < M->n_row; ++i) {
+		isl_seq_gcd(M->row[i], M->n_col, &gcd);
+		if (isl_int_is_divisible_by(gcd, M->row[0][0]))
+			continue;
+		div = isl_basic_map_alloc_div(bmap);
+		if (div < 0)
+			goto error;
+		isl_int_set_si(bmap->div[div][0], 0);
+		k = isl_basic_map_alloc_equality(bmap);
+		if (k < 0)
+			goto error;
+		isl_seq_cpy(bmap->eq[k], M->row[i], M->n_col);
+		isl_seq_clr(bmap->eq[k] + M->n_col, bmap->n_div - n_known);
+		isl_int_set(bmap->eq[k][M->n_col - n_known + div],
+			    M->row[0][0]);
+	}
+	isl_int_clear(gcd);
+
+	return bmap;
+error:
+	isl_int_clear(gcd);
+	isl_basic_map_free(bmap);
+	return NULL;
+}
+
+/* If there are any equalities that involve (multiple) unknown divs,
+ * then extract the stride information encoded by those equalities
+ * and make it explicitly available in "bmap".
+ *
+ * We first sort the divs so that the unknown divs appear last and
+ * then we count how many equalities involve these divs.
+ *
+ * Let these equalities be of the form
+ *
+ *		A(x) + B y = 0
+ *
+ * where y represents the unknown divs and x the remaining variables.
+ * Let [H 0] be the Hermite Normal Form of B, i.e.,
+ *
+ *		B = [H 0] Q
+ *
+ * Then x is a solution of the equalities iff
+ *
+ *		H^-1 A(x) (= - [I 0] Q y)
+ *
+ * is an integer vector.  Let d be the common denominator of H^-1.
+ * We impose
+ *
+ *		d H^-1 A(x) = d alpha
+ *
+ * in add_strides, with alpha fresh existentially quantified variables.
+ */
+static __isl_give isl_basic_map *isl_basic_map_make_strides_explicit(
+	__isl_take isl_basic_map *bmap)
+{
+	int known;
+	int n_known;
+	int n, n_col;
+	int total;
+	isl_ctx *ctx;
+	isl_mat *A, *B, *M;
+
+	known = isl_basic_map_divs_known(bmap);
+	if (known < 0)
+		return isl_basic_map_free(bmap);
+	if (known)
+		return bmap;
+	bmap = isl_basic_map_sort_divs(bmap);
+	bmap = isl_basic_map_gauss(bmap, NULL);
+	if (!bmap)
+		return NULL;
+
+	for (n_known = 0; n_known < bmap->n_div; ++n_known)
+		if (isl_int_is_zero(bmap->div[n_known][0]))
+			break;
+	ctx = isl_basic_map_get_ctx(bmap);
+	total = isl_space_dim(bmap->dim, isl_dim_all);
+	for (n = 0; n < bmap->n_eq; ++n)
+		if (isl_seq_first_non_zero(bmap->eq[n] + 1 + total + n_known,
+					    bmap->n_div - n_known) == -1)
+			break;
+	if (n == 0)
+		return bmap;
+	B = isl_mat_sub_alloc6(ctx, bmap->eq, 0, n, 0, 1 + total + n_known);
+	n_col = bmap->n_div - n_known;
+	A = isl_mat_sub_alloc6(ctx, bmap->eq, 0, n, 1 + total + n_known, n_col);
+	A = isl_mat_left_hermite(A, 0, NULL, NULL);
+	A = isl_mat_drop_cols(A, n, n_col - n);
+	A = isl_mat_lin_to_aff(A);
+	A = isl_mat_right_inverse(A);
+	B = isl_mat_insert_zero_rows(B, 0, 1);
+	B = isl_mat_set_element_si(B, 0, 0, 1);
+	M = isl_mat_product(A, B);
+	if (!M)
+		return isl_basic_map_free(bmap);
+	bmap = add_strides(bmap, M, n_known);
+	bmap = isl_basic_map_gauss(bmap, NULL);
+	isl_mat_free(M);
+
+	return bmap;
+}
+
+/* Compute the affine hull of each basic map in "map" separately
+ * and make all stride information explicit so that we can remove
+ * all unknown divs without losing this information.
+ * The result is also guaranteed to be gaussed.
+ *
+ * In simple cases where a div is determined by an equality,
+ * calling isl_basic_map_gauss is enough to make the stride information
+ * explicit, as it will derive an explicit representation for the div
+ * from the equality.  If, however, the stride information
+ * is encoded through multiple unknown divs then we need to make
+ * some extra effort in isl_basic_map_make_strides_explicit.
+ */
+static __isl_give isl_map *isl_map_local_affine_hull(__isl_take isl_map *map)
+{
+	int i;
+
+	map = isl_map_cow(map);
+	if (!map)
+		return NULL;
+
+	for (i = 0; i < map->n; ++i) {
+		map->p[i] = isl_basic_map_affine_hull(map->p[i]);
+		map->p[i] = isl_basic_map_gauss(map->p[i], NULL);
+		map->p[i] = isl_basic_map_make_strides_explicit(map->p[i]);
+		if (!map->p[i])
+			return isl_map_free(map);
+	}
+
+	return map;
+}
+
+static __isl_give isl_set *isl_set_local_affine_hull(__isl_take isl_set *set)
+{
+	return isl_map_local_affine_hull(set);
+}
+
+/* Compute the affine hull of "map".
+ *
+ * We first compute the affine hull of each basic map separately.
+ * Then we align the divs and recompute the affine hulls of the basic
+ * maps since some of them may now have extra divs.
+ * In order to avoid performing parametric integer programming to
+ * compute explicit expressions for the divs, possible leading to
+ * an explosion in the number of basic maps, we first drop all unknown
+ * divs before aligning the divs.  Note that isl_map_local_affine_hull tries
+ * to make sure that all stride information is explicitly available
+ * in terms of known divs.  This involves calling isl_basic_set_gauss,
+ * which is also needed because affine_hull assumes its input has been gaussed,
+ * while isl_map_affine_hull may be called on input that has not been gaussed,
+ * in particular from initial_facet_constraint.
+ * Similarly, align_divs may reorder some divs so that we need to
+ * gauss the result again.
+ * Finally, we combine the individual affine hulls into a single
+ * affine hull.
+ */
+__isl_give isl_basic_map *isl_map_affine_hull(__isl_take isl_map *map)
+{
+	struct isl_basic_map *model = NULL;
+	struct isl_basic_map *hull = NULL;
+	struct isl_set *set;
+	isl_basic_set *bset;
+
+	map = isl_map_detect_equalities(map);
+	map = isl_map_local_affine_hull(map);
+	map = isl_map_remove_empty_parts(map);
+	map = isl_map_remove_unknown_divs(map);
+	map = isl_map_align_divs(map);
+
+	if (!map)
+		return NULL;
+
+	if (map->n == 0) {
+		hull = isl_basic_map_empty_like_map(map);
+		isl_map_free(map);
+		return hull;
+	}
+
+	model = isl_basic_map_copy(map->p[0]);
+	set = isl_map_underlying_set(map);
+	set = isl_set_cow(set);
+	set = isl_set_local_affine_hull(set);
+	if (!set)
+		goto error;
+
+	while (set->n > 1)
+		set->p[0] = affine_hull(set->p[0], set->p[--set->n]);
+
+	bset = isl_basic_set_copy(set->p[0]);
+	hull = isl_basic_map_overlying_set(bset, model);
+	isl_set_free(set);
+	hull = isl_basic_map_simplify(hull);
+	return isl_basic_map_finalize(hull);
+error:
+	isl_basic_map_free(model);
+	isl_set_free(set);
+	return NULL;
+}
+
+struct isl_basic_set *isl_set_affine_hull(struct isl_set *set)
+{
+	return (struct isl_basic_set *)
+		isl_map_affine_hull((struct isl_map *)set);
+}

Added: polly/trunk/lib/External/isl/isl_arg.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_arg.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_arg.c (added)
+++ polly/trunk/lib/External/isl/isl_arg.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,1308 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isl/arg.h>
+#include <isl/ctx.h>
+
+static struct isl_arg help_arg[] = {
+ISL_ARG_PHANTOM_BOOL('h', "help", NULL, "print this help, then exit")
+};
+
+static void set_default_choice(struct isl_arg *arg, void *opt)
+{
+	*(unsigned *)(((char *)opt) + arg->offset) = arg->u.choice.default_value;
+}
+
+static void set_default_flags(struct isl_arg *arg, void *opt)
+{
+	*(unsigned *)(((char *)opt) + arg->offset) = arg->u.flags.default_value;
+}
+
+static void set_default_bool(struct isl_arg *arg, void *opt)
+{
+	if (arg->offset == (size_t) -1)
+		return;
+	*(unsigned *)(((char *)opt) + arg->offset) = arg->u.b.default_value;
+}
+
+static void set_default_child(struct isl_arg *arg, void *opt)
+{
+	void *child;
+
+	if (arg->offset == (size_t) -1)
+		child = opt;
+	else {
+		child = calloc(1, arg->u.child.child->options_size);
+		*(void **)(((char *)opt) + arg->offset) = child;
+	}
+
+	if (child)
+		isl_args_set_defaults(arg->u.child.child, child);
+}
+
+static void set_default_user(struct isl_arg *arg, void *opt)
+{
+	arg->u.user.init(((char *)opt) + arg->offset);
+}
+
+static void set_default_int(struct isl_arg *arg, void *opt)
+{
+	*(int *)(((char *)opt) + arg->offset) = arg->u.i.default_value;
+}
+
+static void set_default_long(struct isl_arg *arg, void *opt)
+{
+	*(long *)(((char *)opt) + arg->offset) = arg->u.l.default_value;
+}
+
+static void set_default_ulong(struct isl_arg *arg, void *opt)
+{
+	*(unsigned long *)(((char *)opt) + arg->offset) = arg->u.ul.default_value;
+}
+
+static void set_default_str(struct isl_arg *arg, void *opt)
+{
+	const char *str = NULL;
+	if (arg->u.str.default_value)
+		str = strdup(arg->u.str.default_value);
+	*(const char **)(((char *)opt) + arg->offset) = str;
+}
+
+static void set_default_str_list(struct isl_arg *arg, void *opt)
+{
+	*(const char ***)(((char *) opt) + arg->offset) = NULL;
+	*(int *)(((char *) opt) + arg->u.str_list.offset_n) = 0;
+}
+
+void isl_args_set_defaults(struct isl_args *args, void *opt)
+{
+	int i;
+
+	for (i = 0; args->args[i].type != isl_arg_end; ++i) {
+		switch (args->args[i].type) {
+		case isl_arg_choice:
+			set_default_choice(&args->args[i], opt);
+			break;
+		case isl_arg_flags:
+			set_default_flags(&args->args[i], opt);
+			break;
+		case isl_arg_bool:
+			set_default_bool(&args->args[i], opt);
+			break;
+		case isl_arg_child:
+			set_default_child(&args->args[i], opt);
+			break;
+		case isl_arg_user:
+			set_default_user(&args->args[i], opt);
+			break;
+		case isl_arg_int:
+			set_default_int(&args->args[i], opt);
+			break;
+		case isl_arg_long:
+			set_default_long(&args->args[i], opt);
+			break;
+		case isl_arg_ulong:
+			set_default_ulong(&args->args[i], opt);
+			break;
+		case isl_arg_arg:
+		case isl_arg_str:
+			set_default_str(&args->args[i], opt);
+			break;
+		case isl_arg_str_list:
+			set_default_str_list(&args->args[i], opt);
+			break;
+		case isl_arg_alias:
+		case isl_arg_footer:
+		case isl_arg_version:
+		case isl_arg_end:
+			break;
+		}
+	}
+}
+
+static void free_args(struct isl_arg *arg, void *opt);
+
+static void free_child(struct isl_arg *arg, void *opt)
+{
+	if (arg->offset == (size_t) -1)
+		free_args(arg->u.child.child->args, opt);
+	else
+		isl_args_free(arg->u.child.child,
+			    *(void **)(((char *)opt) + arg->offset));
+}
+
+static void free_str_list(struct isl_arg *arg, void *opt)
+{
+	int i;
+	int n = *(int *)(((char *) opt) + arg->u.str_list.offset_n);
+	char **list = *(char ***)(((char *) opt) + arg->offset);
+
+	for (i = 0; i < n; ++i)
+		free(list[i]);
+	free(list);
+}
+
+static void free_user(struct isl_arg *arg, void *opt)
+{
+	if (arg->u.user.clear)
+		arg->u.user.clear(((char *)opt) + arg->offset);
+}
+
+static void free_args(struct isl_arg *arg, void *opt)
+{
+	int i;
+
+	for (i = 0; arg[i].type != isl_arg_end; ++i) {
+		switch (arg[i].type) {
+		case isl_arg_child:
+			free_child(&arg[i], opt);
+			break;
+		case isl_arg_arg:
+		case isl_arg_str:
+			free(*(char **)(((char *)opt) + arg[i].offset));
+			break;
+		case isl_arg_str_list:
+			free_str_list(&arg[i], opt);
+			break;
+		case isl_arg_user:
+			free_user(&arg[i], opt);
+			break;
+		case isl_arg_alias:
+		case isl_arg_bool:
+		case isl_arg_choice:
+		case isl_arg_flags:
+		case isl_arg_int:
+		case isl_arg_long:
+		case isl_arg_ulong:
+		case isl_arg_version:
+		case isl_arg_footer:
+		case isl_arg_end:
+			break;
+		}
+	}
+}
+
+void isl_args_free(struct isl_args *args, void *opt)
+{
+	if (!opt)
+		return;
+
+	free_args(args->args, opt);
+
+	free(opt);
+}
+
+/* Data structure for collecting the prefixes of ancestor nodes.
+ *
+ * n is the number of prefixes.
+ * prefix[i] for i < n is a prefix of an ancestor.
+ * len[i] for i < n is the length of prefix[i].
+ */
+struct isl_prefixes {
+	int n;
+	const char *prefix[10];
+	size_t len[10];
+};
+
+/* Add "prefix" to the list of prefixes and return the updated
+ * number of prefixes.
+ */
+static int add_prefix(struct isl_prefixes *prefixes, const char *prefix)
+{
+	int n = prefixes->n;
+
+	if (!prefix)
+		return n;
+
+	if (prefixes->n >= 10) {
+		fprintf(stderr, "too many prefixes\n");
+		exit(EXIT_FAILURE);
+	}
+	prefixes->len[prefixes->n] = strlen(prefix);
+	prefixes->prefix[prefixes->n] = prefix;
+	prefixes->n++;
+
+	return n;
+}
+
+/* Drop all prefixes starting at "first".
+ */
+static void drop_prefix(struct isl_prefixes *prefixes, int first)
+{
+	prefixes->n = first;
+}
+
+/* Print the prefixes in "prefixes".
+ */
+static int print_prefixes(struct isl_prefixes *prefixes)
+{
+	int i;
+	int len = 0;
+
+	if (!prefixes)
+		return 0;
+
+	for (i = 0; i < prefixes->n; ++i) {
+		printf("%s-", prefixes->prefix[i]);
+		len += strlen(prefixes->prefix[i]) + 1;
+	}
+
+	return len;
+}
+
+/* Check if "name" starts with one or more of the prefixes in "prefixes",
+ * starting at *first.  If so, advance the pointer beyond the prefixes
+ * and return the updated pointer.  Additionally, update *first to
+ * the index after the last prefix found.
+ */
+static const char *skip_prefixes(const char *name,
+	struct isl_prefixes *prefixes, int *first)
+{
+	int i;
+
+	for (i = first ? *first : 0; i < prefixes->n; ++i) {
+		size_t len = prefixes->len[i];
+		const char *prefix = prefixes->prefix[i];
+		if (strncmp(name, prefix, len) == 0 && name[len] == '-') {
+			name += len + 1;
+			if (first)
+				*first = i + 1;
+		}
+	}
+
+	return name;
+}
+
+static int print_arg_help(struct isl_arg *decl, struct isl_prefixes *prefixes,
+	int no)
+{
+	int len = 0;
+
+	if (!decl->long_name) {
+		printf("  -%c", decl->short_name);
+		return 4;
+	}
+
+	if (decl->short_name) {
+		printf("  -%c, --", decl->short_name);
+		len += 8;
+	} else if (decl->flags & ISL_ARG_SINGLE_DASH) {
+		printf("  -");
+		len += 3;
+	} else {
+		printf("      --");
+		len += 8;
+	}
+
+	if (no) {
+		printf("no-");
+		len += 3;
+	}
+	len += print_prefixes(prefixes);
+	printf("%s", decl->long_name);
+	len += strlen(decl->long_name);
+
+	while ((++decl)->type == isl_arg_alias) {
+		printf(", --");
+		len += 4;
+		if (no) {
+			printf("no-");
+			len += 3;
+		}
+		printf("%s", decl->long_name);
+		len += strlen(decl->long_name);
+	}
+
+	return len;
+}
+
+const void *isl_memrchr(const void *s, int c, size_t n)
+{
+	const char *p = s;
+	while (n-- > 0)
+		if (p[n] == c)
+			return p + n;
+	return NULL;
+}
+
+static int wrap_msg(const char *s, int indent, int pos)
+{
+	int len;
+	int wrap_len = 75 - indent;
+
+	if (pos + 1 >= indent)
+		printf("\n%*s", indent, "");
+	else
+		printf("%*s", indent - pos, "");
+
+	len = strlen(s);
+	while (len > wrap_len) {
+		const char *space = isl_memrchr(s, ' ', wrap_len);
+		int l;
+
+		if (!space)
+			space = strchr(s + wrap_len, ' ');
+		if (!space)
+			break;
+		l = space - s;
+		printf("%.*s", l, s);
+		s = space + 1;
+		len -= l + 1;
+		printf("\n%*s", indent, "");
+	}
+
+	printf("%s", s);
+	return len;
+}
+
+static int print_help_msg(struct isl_arg *decl, int pos)
+{
+	if (!decl->help_msg)
+		return pos;
+
+	return wrap_msg(decl->help_msg, 30, pos);
+}
+
+static void print_default(struct isl_arg *decl, const char *def, int pos)
+{
+	const char *default_prefix = "[default: ";
+	const char *default_suffix = "]";
+	int len;
+
+	len = strlen(default_prefix) + strlen(def) + strlen(default_suffix);
+
+	if (!decl->help_msg) {
+		if (pos >= 29)
+			printf("\n%30s", "");
+		else
+			printf("%*s", 30 - pos, "");
+		pos = 0;
+	} else {
+		if (pos + len >= 48)
+			printf("\n%30s", "");
+		else
+			printf(" ");
+	}
+	printf("%s%s%s", default_prefix, def, default_suffix);
+}
+
+static void print_default_choice(struct isl_arg *decl, void *opt, int pos)
+{
+	int i;
+	const char *s = "none";
+	unsigned *p;
+
+	p = (unsigned *)(((char *) opt) + decl->offset);
+	for (i = 0; decl->u.choice.choice[i].name; ++i)
+		if (decl->u.choice.choice[i].value == *p) {
+			s = decl->u.choice.choice[i].name;
+			break;
+		}
+
+	print_default(decl, s, pos);
+}
+
+static void print_choice_help(struct isl_arg *decl,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int i;
+	int pos;
+
+	pos = print_arg_help(decl, prefixes, 0);
+	printf("=");
+	pos++;
+
+	for (i = 0; decl->u.choice.choice[i].name; ++i) {
+		if (i) {
+			printf("|");
+			pos++;
+		}
+		printf("%s", decl->u.choice.choice[i].name);
+		pos += strlen(decl->u.choice.choice[i].name);
+	}
+
+	pos = print_help_msg(decl, pos);
+	print_default_choice(decl, opt, pos);
+
+	printf("\n");
+}
+
+static void print_default_flags(struct isl_arg *decl, void *opt, int pos)
+{
+	int i, first;
+	const char *default_prefix = "[default: ";
+	const char *default_suffix = "]";
+	int len = strlen(default_prefix) + strlen(default_suffix);
+	unsigned *p;
+
+	p = (unsigned *)(((char *) opt) + decl->offset);
+	for (i = 0; decl->u.flags.flags[i].name; ++i)
+		if ((*p & decl->u.flags.flags[i].mask) ==
+		     decl->u.flags.flags[i].value)
+			len += strlen(decl->u.flags.flags[i].name);
+
+	if (!decl->help_msg) {
+		if (pos >= 29)
+			printf("\n%30s", "");
+		else
+			printf("%*s", 30 - pos, "");
+		pos = 0;
+	} else {
+		if (pos + len >= 48)
+			printf("\n%30s", "");
+		else
+			printf(" ");
+	}
+	printf("%s", default_prefix);
+
+	for (first = 1, i = 0; decl->u.flags.flags[i].name; ++i)
+		if ((*p & decl->u.flags.flags[i].mask) ==
+		     decl->u.flags.flags[i].value) {
+			if (!first)
+				printf(",");
+			printf("%s", decl->u.flags.flags[i].name);
+			first = 0;
+		}
+
+	printf("%s", default_suffix);
+}
+
+static void print_flags_help(struct isl_arg *decl,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int i, j;
+	int pos;
+
+	pos = print_arg_help(decl, prefixes, 0);
+	printf("=");
+	pos++;
+
+	for (i = 0; decl->u.flags.flags[i].name; ++i) {
+		if (i) {
+			printf(",");
+			pos++;
+		}
+		for (j = i;
+		     decl->u.flags.flags[j].mask == decl->u.flags.flags[i].mask;
+		     ++j) {
+			if (j != i) {
+				printf("|");
+				pos++;
+			}
+			printf("%s", decl->u.flags.flags[j].name);
+			pos += strlen(decl->u.flags.flags[j].name);
+		}
+		i = j - 1;
+	}
+
+	pos = print_help_msg(decl, pos);
+	print_default_flags(decl, opt, pos);
+
+	printf("\n");
+}
+
+static void print_bool_help(struct isl_arg *decl,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int pos;
+	unsigned *p = opt ? (unsigned *)(((char *) opt) + decl->offset) : NULL;
+	int no = p ? *p == 1 : 0;
+	pos = print_arg_help(decl, prefixes, no);
+	pos = print_help_msg(decl, pos);
+	if (decl->offset != (size_t) -1)
+		print_default(decl, no ? "yes" : "no", pos);
+	printf("\n");
+}
+
+static int print_argument_name(struct isl_arg *decl, const char *name, int pos)
+{
+	printf("%c<%s>", decl->long_name ? '=' : ' ', name);
+	return pos + 3 + strlen(name);
+}
+
+static void print_int_help(struct isl_arg *decl,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int pos;
+	char val[20];
+	int *p = (int *)(((char *) opt) + decl->offset);
+	pos = print_arg_help(decl, prefixes, 0);
+	pos = print_argument_name(decl, decl->argument_name, pos);
+	pos = print_help_msg(decl, pos);
+	snprintf(val, sizeof(val), "%d", *p);
+	print_default(decl, val, pos);
+	printf("\n");
+}
+
+static void print_long_help(struct isl_arg *decl,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int pos;
+	long *p = (long *)(((char *) opt) + decl->offset);
+	pos = print_arg_help(decl, prefixes, 0);
+	if (*p != decl->u.l.default_selected) {
+		printf("[");
+		pos++;
+	}
+	printf("=long");
+	pos += 5;
+	if (*p != decl->u.l.default_selected) {
+		printf("]");
+		pos++;
+	}
+	print_help_msg(decl, pos);
+	printf("\n");
+}
+
+static void print_ulong_help(struct isl_arg *decl,
+	struct isl_prefixes *prefixes)
+{
+	int pos;
+	pos = print_arg_help(decl, prefixes, 0);
+	printf("=ulong");
+	pos += 6;
+	print_help_msg(decl, pos);
+	printf("\n");
+}
+
+static void print_str_help(struct isl_arg *decl,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int pos;
+	const char *a = decl->argument_name ? decl->argument_name : "string";
+	const char **p = (const char **)(((char *) opt) + decl->offset);
+	pos = print_arg_help(decl, prefixes, 0);
+	pos = print_argument_name(decl, a, pos);
+	pos = print_help_msg(decl, pos);
+	if (*p)
+		print_default(decl, *p, pos);
+	printf("\n");
+}
+
+static void print_str_list_help(struct isl_arg *decl,
+	struct isl_prefixes *prefixes)
+{
+	int pos;
+	const char *a = decl->argument_name ? decl->argument_name : "string";
+	pos = print_arg_help(decl, prefixes, 0);
+	pos = print_argument_name(decl, a, pos);
+	pos = print_help_msg(decl, pos);
+	printf("\n");
+}
+
+static void print_help(struct isl_arg *arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int i;
+	int any = 0;
+
+	for (i = 0; arg[i].type != isl_arg_end; ++i) {
+		if (arg[i].flags & ISL_ARG_HIDDEN)
+			continue;
+		switch (arg[i].type) {
+		case isl_arg_flags:
+			print_flags_help(&arg[i], prefixes, opt);
+			any = 1;
+			break;
+		case isl_arg_choice:
+			print_choice_help(&arg[i], prefixes, opt);
+			any = 1;
+			break;
+		case isl_arg_bool:
+			print_bool_help(&arg[i], prefixes, opt);
+			any = 1;
+			break;
+		case isl_arg_int:
+			print_int_help(&arg[i], prefixes, opt);
+			any = 1;
+			break;
+		case isl_arg_long:
+			print_long_help(&arg[i], prefixes, opt);
+			any = 1;
+			break;
+		case isl_arg_ulong:
+			print_ulong_help(&arg[i], prefixes);
+			any = 1;
+			break;
+		case isl_arg_str:
+			print_str_help(&arg[i], prefixes, opt);
+			any = 1;
+			break;
+		case isl_arg_str_list:
+			print_str_list_help(&arg[i], prefixes);
+			any = 1;
+			break;
+		case isl_arg_alias:
+		case isl_arg_version:
+		case isl_arg_arg:
+		case isl_arg_footer:
+		case isl_arg_child:
+		case isl_arg_user:
+		case isl_arg_end:
+			break;
+		}
+	}
+
+	for (i = 0; arg[i].type != isl_arg_end; ++i) {
+		void *child;
+		int first;
+
+		if (arg[i].type != isl_arg_child)
+			continue;
+		if (arg[i].flags & ISL_ARG_HIDDEN)
+			continue;
+
+		if (any)
+			printf("\n");
+		if (arg[i].help_msg)
+			printf(" %s\n", arg[i].help_msg);
+		if (arg[i].offset == (size_t) -1)
+			child = opt;
+		else
+			child = *(void **)(((char *) opt) + arg[i].offset);
+		first = add_prefix(prefixes, arg[i].long_name);
+		print_help(arg[i].u.child.child->args, prefixes, child);
+		drop_prefix(prefixes, first);
+		any = 1;
+	}
+}
+
+static const char *prog_name(const char *prog)
+{
+	const char *slash;
+
+	slash = strrchr(prog, '/');
+	if (slash)
+		prog = slash + 1;
+	if (strncmp(prog, "lt-", 3) == 0)
+		prog += 3;
+
+	return prog;
+}
+
+static int any_version(struct isl_arg *decl)
+{
+	int i;
+
+	for (i = 0; decl[i].type != isl_arg_end; ++i) {
+		switch (decl[i].type) {
+		case isl_arg_version:
+			return 1;
+		case isl_arg_child:
+			if (any_version(decl[i].u.child.child->args))
+				return 1;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+static void print_help_and_exit(struct isl_arg *arg, const char *prog,
+	void *opt)
+{
+	int i;
+	struct isl_prefixes prefixes = { 0 };
+
+	printf("Usage: %s [OPTION...]", prog_name(prog));
+
+	for (i = 0; arg[i].type != isl_arg_end; ++i)
+		if (arg[i].type == isl_arg_arg)
+			printf(" %s", arg[i].argument_name);
+
+	printf("\n\n");
+
+	print_help(arg, &prefixes, opt);
+	printf("\n");
+	if (any_version(arg))
+		printf("  -V, --version\n");
+	print_bool_help(help_arg, NULL, NULL);
+
+	for (i = 0; arg[i].type != isl_arg_end; ++i) {
+		if (arg[i].type != isl_arg_footer)
+			continue;
+		wrap_msg(arg[i].help_msg, 0, 0);
+		printf("\n");
+	}
+
+	exit(0);
+}
+
+static int match_long_name(struct isl_arg *decl,
+	const char *start, const char *end)
+{
+	do {
+		if (end - start == strlen(decl->long_name) &&
+		    !strncmp(start, decl->long_name, end - start))
+			return 1;
+	} while ((++decl)->type == isl_arg_alias);
+
+	return 0;
+}
+
+static const char *skip_dash_dash(struct isl_arg *decl, const char *arg)
+{
+	if (!strncmp(arg, "--", 2))
+		return arg + 2;
+	if ((decl->flags & ISL_ARG_SINGLE_DASH) && arg[0] == '-')
+		return arg + 1;
+	return NULL;
+}
+
+static const char *skip_name(struct isl_arg *decl, const char *arg,
+	struct isl_prefixes *prefixes, int need_argument, int *has_argument)
+{
+	const char *equal;
+	const char *name;
+	const char *end;
+
+	if (arg[0] == '-' && arg[1] && arg[1] == decl->short_name) {
+		if (need_argument && !arg[2])
+			return NULL;
+		if (has_argument)
+			*has_argument = arg[2] != '\0';
+		return arg + 2;
+	}
+	if (!decl->long_name)
+		return NULL;
+
+	name = skip_dash_dash(decl, arg);
+	if (!name)
+		return NULL;
+
+	equal = strchr(name, '=');
+	if (need_argument && !equal)
+		return NULL;
+
+	if (has_argument)
+		*has_argument = !!equal;
+	end = equal ? equal : name + strlen(name);
+
+	name = skip_prefixes(name, prefixes, NULL);
+
+	if (!match_long_name(decl, name, end))
+		return NULL;
+
+	return equal ? equal + 1 : end;
+}
+
+static int parse_choice_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int i;
+	int has_argument;
+	const char *choice;
+
+	choice = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+	if (!choice)
+		return 0;
+
+	if (!has_argument && (!arg[1] || arg[1][0] == '-')) {
+		unsigned u = decl->u.choice.default_selected;
+		*(unsigned *)(((char *)opt) + decl->offset) = u;
+		if (decl->u.choice.set)
+			decl->u.choice.set(opt, u);
+
+		return 1;
+	}
+
+	if (!has_argument)
+		choice = arg[1];
+
+	for (i = 0; decl->u.choice.choice[i].name; ++i) {
+		unsigned u;
+
+		if (strcmp(choice, decl->u.choice.choice[i].name))
+			continue;
+
+		u = decl->u.choice.choice[i].value;
+		*(unsigned *)(((char *)opt) + decl->offset) = u;
+		if (decl->u.choice.set)
+			decl->u.choice.set(opt, u);
+
+		return has_argument ? 1 : 2;
+	}
+
+	return 0;
+}
+
+static int set_flag(struct isl_arg *decl, unsigned *val, const char *flag,
+	size_t len)
+{
+	int i;
+
+	for (i = 0; decl->u.flags.flags[i].name; ++i) {
+		if (strncmp(flag, decl->u.flags.flags[i].name, len))
+			continue;
+
+		*val &= ~decl->u.flags.flags[i].mask;
+		*val |= decl->u.flags.flags[i].value;
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static int parse_flags_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int has_argument;
+	const char *flags;
+	const char *comma;
+	unsigned val;
+
+	flags = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+	if (!flags)
+		return 0;
+
+	if (!has_argument && !arg[1])
+		return 0;
+
+	if (!has_argument)
+		flags = arg[1];
+
+	val = 0;
+
+	while ((comma = strchr(flags, ',')) != NULL) {
+		if (!set_flag(decl, &val, flags, comma - flags))
+			return 0;
+		flags = comma + 1;
+	}
+	if (!set_flag(decl, &val, flags, strlen(flags)))
+		return 0;
+
+	*(unsigned *)(((char *)opt) + decl->offset) = val;
+
+	return has_argument ? 1 : 2;
+}
+
+static int parse_bool_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	const char *name;
+	unsigned *p = (unsigned *)(((char *)opt) + decl->offset);
+	int next_prefix;
+
+	if (skip_name(decl, arg[0], prefixes, 0, NULL)) {
+		if ((decl->flags & ISL_ARG_BOOL_ARG) && arg[1]) {
+			char *endptr;
+			int val = strtol(arg[1], &endptr, 0);
+			if (*endptr == '\0' && (val == 0 || val == 1)) {
+				if (decl->offset != (size_t) -1)
+					*p = val;
+				if (decl->u.b.set)
+					decl->u.b.set(opt, val);
+				return 2;
+			}
+		}
+		if (decl->offset != (size_t) -1)
+			*p = 1;
+		if (decl->u.b.set)
+			decl->u.b.set(opt, 1);
+
+		return 1;
+	}
+
+	if (!decl->long_name)
+		return 0;
+
+	name = skip_dash_dash(decl, arg[0]);
+	if (!name)
+		return 0;
+
+	next_prefix = 0;
+	name = skip_prefixes(name, prefixes, &next_prefix);
+
+	if (strncmp(name, "no-", 3))
+		return 0;
+	name += 3;
+
+	name = skip_prefixes(name, prefixes, &next_prefix);
+
+	if (match_long_name(decl, name, name + strlen(name))) {
+		if (decl->offset != (size_t) -1)
+			*p = 0;
+		if (decl->u.b.set)
+			decl->u.b.set(opt, 0);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static int parse_str_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int has_argument;
+	const char *s;
+	char **p = (char **)(((char *)opt) + decl->offset);
+
+	s = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+	if (!s)
+		return 0;
+
+	if (has_argument) {
+		free(*p);
+		*p = strdup(s);
+		return 1;
+	}
+
+	if (arg[1]) {
+		free(*p);
+		*p = strdup(arg[1]);
+		return 2;
+	}
+
+	return 0;
+}
+
+static int isl_arg_str_list_append(struct isl_arg *decl, void *opt,
+	const char *s)
+{
+	int *n = (int *)(((char *) opt) + decl->u.str_list.offset_n);
+	char **list = *(char ***)(((char *) opt) + decl->offset);
+
+	list = realloc(list, (*n + 1) * sizeof(char *));
+	if (!list)
+		return -1;
+	*(char ***)(((char *) opt) + decl->offset) = list;
+	list[*n] = strdup(s);
+	(*n)++;
+	return 0;
+}
+
+static int parse_str_list_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int has_argument;
+	const char *s;
+
+	s = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+	if (!s)
+		return 0;
+
+	if (has_argument) {
+		isl_arg_str_list_append(decl, opt, s);
+		return 1;
+	}
+
+	if (arg[1]) {
+		isl_arg_str_list_append(decl, opt, arg[1]);
+		return 2;
+	}
+
+	return 0;
+}
+
+static int parse_int_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int has_argument;
+	const char *val;
+	char *endptr;
+	int *p = (int *)(((char *)opt) + decl->offset);
+
+	val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+	if (!val)
+		return 0;
+
+	if (has_argument) {
+		*p = atoi(val);
+		return 1;
+	}
+
+	if (arg[1]) {
+		int i = strtol(arg[1], &endptr, 0);
+		if (*endptr == '\0') {
+			*p = i;
+			return 2;
+		}
+	}
+
+	return 0;
+}
+
+static int parse_long_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int has_argument;
+	const char *val;
+	char *endptr;
+	long *p = (long *)(((char *)opt) + decl->offset);
+
+	val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+	if (!val)
+		return 0;
+
+	if (has_argument) {
+		long l = strtol(val, NULL, 0);
+		*p = l;
+		if (decl->u.l.set)
+			decl->u.l.set(opt, l);
+		return 1;
+	}
+
+	if (arg[1]) {
+		long l = strtol(arg[1], &endptr, 0);
+		if (*endptr == '\0') {
+			*p = l;
+			if (decl->u.l.set)
+				decl->u.l.set(opt, l);
+			return 2;
+		}
+	}
+
+	if (decl->u.l.default_value != decl->u.l.default_selected) {
+		*p = decl->u.l.default_selected;
+		if (decl->u.l.set)
+			decl->u.l.set(opt, decl->u.l.default_selected);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int parse_ulong_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int has_argument;
+	const char *val;
+	char *endptr;
+	unsigned long *p = (unsigned long *)(((char *)opt) + decl->offset);
+
+	val = skip_name(decl, arg[0], prefixes, 0, &has_argument);
+	if (!val)
+		return 0;
+
+	if (has_argument) {
+		*p = strtoul(val, NULL, 0);
+		return 1;
+	}
+
+	if (arg[1]) {
+		unsigned long ul = strtoul(arg[1], &endptr, 0);
+		if (*endptr == '\0') {
+			*p = ul;
+			return 2;
+		}
+	}
+
+	return 0;
+}
+
+static int parse_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt);
+
+static int parse_child_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	void *child;
+	int first, parsed;
+
+	if (decl->offset == (size_t) -1)
+		child = opt;
+	else
+		child = *(void **)(((char *)opt) + decl->offset);
+
+	first = add_prefix(prefixes, decl->long_name);
+	parsed = parse_option(decl->u.child.child->args, arg, prefixes, child);
+	drop_prefix(prefixes, first);
+
+	return parsed;
+}
+
+static int parse_option(struct isl_arg *decl, char **arg,
+	struct isl_prefixes *prefixes, void *opt)
+{
+	int i;
+
+	for (i = 0; decl[i].type != isl_arg_end; ++i) {
+		int parsed = 0;
+		switch (decl[i].type) {
+		case isl_arg_choice:
+			parsed = parse_choice_option(&decl[i], arg,
+							prefixes, opt);
+			break;
+		case isl_arg_flags:
+			parsed = parse_flags_option(&decl[i], arg,
+							prefixes, opt);
+			break;
+		case isl_arg_int:
+			parsed = parse_int_option(&decl[i], arg, prefixes, opt);
+			break;
+		case isl_arg_long:
+			parsed = parse_long_option(&decl[i], arg,
+							prefixes, opt);
+			break;
+		case isl_arg_ulong:
+			parsed = parse_ulong_option(&decl[i], arg,
+							prefixes, opt);
+			break;
+		case isl_arg_bool:
+			parsed = parse_bool_option(&decl[i], arg,
+							prefixes, opt);
+			break;
+		case isl_arg_str:
+			parsed = parse_str_option(&decl[i], arg, prefixes, opt);
+			break;
+		case isl_arg_str_list:
+			parsed = parse_str_list_option(&decl[i], arg, prefixes,
+							opt);
+			break;
+		case isl_arg_child:
+			parsed = parse_child_option(&decl[i], arg,
+							prefixes, opt);
+			break;
+		case isl_arg_alias:
+		case isl_arg_arg:
+		case isl_arg_footer:
+		case isl_arg_user:
+		case isl_arg_version:
+		case isl_arg_end:
+			break;
+		}
+		if (parsed)
+			return parsed;
+	}
+
+	return 0;
+}
+
+static void print_version(struct isl_arg *decl)
+{
+	int i;
+
+	for (i = 0; decl[i].type != isl_arg_end; ++i) {
+		switch (decl[i].type) {
+		case isl_arg_version:
+			decl[i].u.version.print_version();
+			break;
+		case isl_arg_child:
+			print_version(decl[i].u.child.child->args);
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+static void print_version_and_exit(struct isl_arg *decl)
+{
+	print_version(decl);
+
+	exit(0);
+}
+
+static int drop_argument(int argc, char **argv, int drop, int n)
+{
+	for (; drop + n < argc; ++drop)
+		argv[drop] = argv[drop + n];
+
+	return argc - n;
+}
+
+static int n_arg(struct isl_arg *arg)
+{
+	int i;
+	int n_arg = 0;
+
+	for (i = 0; arg[i].type != isl_arg_end; ++i)
+		if (arg[i].type == isl_arg_arg)
+			n_arg++;
+
+	return n_arg;
+}
+
+static int next_arg(struct isl_arg *arg, int a)
+{
+	for (++a; arg[a].type != isl_arg_end; ++a)
+		if (arg[a].type == isl_arg_arg)
+			return a;
+
+	return -1;
+}
+
+/* Unless ISL_ARG_SKIP_HELP is set, check if "arg" is
+ * equal to "--help" and if so call print_help_and_exit.
+ */
+static void check_help(struct isl_args *args, char *arg, char *prog, void *opt,
+	unsigned flags)
+{
+	if (ISL_FL_ISSET(flags, ISL_ARG_SKIP_HELP))
+		return;
+
+	if (strcmp(arg, "--help") == 0)
+		print_help_and_exit(args->args, prog, opt);
+}
+
+int isl_args_parse(struct isl_args *args, int argc, char **argv, void *opt,
+	unsigned flags)
+{
+	int a = -1;
+	int skip = 0;
+	int i;
+	int n;
+	struct isl_prefixes prefixes = { 0 };
+
+	n = n_arg(args->args);
+
+	for (i = 1; i < argc; ++i) {
+		if ((strcmp(argv[i], "--version") == 0 ||
+		     strcmp(argv[i], "-V") == 0) && any_version(args->args))
+			print_version_and_exit(args->args);
+	}
+
+	while (argc > 1 + skip) {
+		int parsed;
+		if (argv[1 + skip][0] != '-') {
+			a = next_arg(args->args, a);
+			if (a >= 0) {
+				char **p;
+				p = (char **)(((char *)opt)+args->args[a].offset);
+				free(*p);
+				*p = strdup(argv[1 + skip]);
+				argc = drop_argument(argc, argv, 1 + skip, 1);
+				--n;
+			} else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
+				fprintf(stderr, "%s: extra argument: %s\n",
+					    prog_name(argv[0]), argv[1 + skip]);
+				exit(-1);
+			} else
+				++skip;
+			continue;
+		}
+		check_help(args, argv[1 + skip], argv[0], opt, flags);
+		parsed = parse_option(args->args, &argv[1 + skip],
+					&prefixes, opt);
+		if (parsed)
+			argc = drop_argument(argc, argv, 1 + skip, parsed);
+		else if (ISL_FL_ISSET(flags, ISL_ARG_ALL)) {
+			fprintf(stderr, "%s: unrecognized option: %s\n",
+					prog_name(argv[0]), argv[1 + skip]);
+			exit(-1);
+		} else
+			++skip;
+	}
+
+	if (n > 0) {
+		fprintf(stderr, "%s: expecting %d more argument(s)\n",
+				prog_name(argv[0]), n);
+		exit(-1);
+	}
+
+	return argc;
+}

Added: polly/trunk/lib/External/isl/isl_ast.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_ast.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast.c (added)
+++ polly/trunk/lib/External/isl/isl_ast.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2069 @@
+/*
+ * 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_ast_private.h>
+
+#undef BASE
+#define BASE ast_expr
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE ast_node
+
+#include <isl_list_templ.c>
+
+isl_ctx *isl_ast_print_options_get_ctx(
+	__isl_keep isl_ast_print_options *options)
+{
+	return options ? options->ctx : NULL;
+}
+
+__isl_give isl_ast_print_options *isl_ast_print_options_alloc(isl_ctx *ctx)
+{
+	isl_ast_print_options *options;
+
+	options = isl_calloc_type(ctx, isl_ast_print_options);
+	if (!options)
+		return NULL;
+
+	options->ctx = ctx;
+	isl_ctx_ref(ctx);
+	options->ref = 1;
+
+	return options;
+}
+
+__isl_give isl_ast_print_options *isl_ast_print_options_dup(
+	__isl_keep isl_ast_print_options *options)
+{
+	isl_ctx *ctx;
+	isl_ast_print_options *dup;
+
+	if (!options)
+		return NULL;
+
+	ctx = isl_ast_print_options_get_ctx(options);
+	dup = isl_ast_print_options_alloc(ctx);
+	if (!dup)
+		return NULL;
+
+	dup->print_for = options->print_for;
+	dup->print_for_user = options->print_for_user;
+	dup->print_user = options->print_user;
+	dup->print_user_user = options->print_user_user;
+
+	return dup;
+}
+
+__isl_give isl_ast_print_options *isl_ast_print_options_cow(
+	__isl_take isl_ast_print_options *options)
+{
+	if (!options)
+		return NULL;
+
+	if (options->ref == 1)
+		return options;
+	options->ref--;
+	return isl_ast_print_options_dup(options);
+}
+
+__isl_give isl_ast_print_options *isl_ast_print_options_copy(
+	__isl_keep isl_ast_print_options *options)
+{
+	if (!options)
+		return NULL;
+
+	options->ref++;
+	return options;
+}
+
+__isl_null isl_ast_print_options *isl_ast_print_options_free(
+	__isl_take isl_ast_print_options *options)
+{
+	if (!options)
+		return NULL;
+
+	if (--options->ref > 0)
+		return NULL;
+
+	isl_ctx_deref(options->ctx);
+
+	free(options);
+	return NULL;
+}
+
+/* Set the print_user callback of "options" to "print_user".
+ *
+ * If this callback is set, then it used to print user nodes in the AST.
+ * Otherwise, the expression associated to the user node is printed.
+ */
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_user(
+	__isl_take isl_ast_print_options *options,
+	__isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
+		__isl_take isl_ast_print_options *options,
+		__isl_keep isl_ast_node *node, void *user),
+	void *user)
+{
+	options = isl_ast_print_options_cow(options);
+	if (!options)
+		return NULL;
+
+	options->print_user = print_user;
+	options->print_user_user = user;
+
+	return options;
+}
+
+/* Set the print_for callback of "options" to "print_for".
+ *
+ * If this callback is set, then it used to print for nodes in the AST.
+ */
+__isl_give isl_ast_print_options *isl_ast_print_options_set_print_for(
+	__isl_take isl_ast_print_options *options,
+	__isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
+		__isl_take isl_ast_print_options *options,
+		__isl_keep isl_ast_node *node, void *user),
+	void *user)
+{
+	options = isl_ast_print_options_cow(options);
+	if (!options)
+		return NULL;
+
+	options->print_for = print_for;
+	options->print_for_user = user;
+
+	return options;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_copy(__isl_keep isl_ast_expr *expr)
+{
+	if (!expr)
+		return NULL;
+
+	expr->ref++;
+	return expr;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_dup(__isl_keep isl_ast_expr *expr)
+{
+	int i;
+	isl_ctx *ctx;
+	isl_ast_expr *dup;
+
+	if (!expr)
+		return NULL;
+
+	ctx = isl_ast_expr_get_ctx(expr);
+	switch (expr->type) {
+	case isl_ast_expr_int:
+		dup = isl_ast_expr_from_val(isl_val_copy(expr->u.v));
+		break;
+	case isl_ast_expr_id:
+		dup = isl_ast_expr_from_id(isl_id_copy(expr->u.id));
+		break;
+	case isl_ast_expr_op:
+		dup = isl_ast_expr_alloc_op(ctx,
+					    expr->u.op.op, expr->u.op.n_arg);
+		if (!dup)
+			return NULL;
+		for (i = 0; i < expr->u.op.n_arg; ++i)
+			dup->u.op.args[i] =
+				isl_ast_expr_copy(expr->u.op.args[i]);
+		break;
+	case isl_ast_expr_error:
+		dup = NULL;
+	}
+
+	if (!dup)
+		return NULL;
+
+	return dup;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_cow(__isl_take isl_ast_expr *expr)
+{
+	if (!expr)
+		return NULL;
+
+	if (expr->ref == 1)
+		return expr;
+	expr->ref--;
+	return isl_ast_expr_dup(expr);
+}
+
+__isl_null isl_ast_expr *isl_ast_expr_free(__isl_take isl_ast_expr *expr)
+{
+	int i;
+
+	if (!expr)
+		return NULL;
+
+	if (--expr->ref > 0)
+		return NULL;
+
+	isl_ctx_deref(expr->ctx);
+
+	switch (expr->type) {
+	case isl_ast_expr_int:
+		isl_val_free(expr->u.v);
+		break;
+	case isl_ast_expr_id:
+		isl_id_free(expr->u.id);
+		break;
+	case isl_ast_expr_op:
+		if (expr->u.op.args)
+			for (i = 0; i < expr->u.op.n_arg; ++i)
+				isl_ast_expr_free(expr->u.op.args[i]);
+		free(expr->u.op.args);
+		break;
+	case isl_ast_expr_error:
+		break;
+	}
+
+	free(expr);
+	return NULL;
+}
+
+isl_ctx *isl_ast_expr_get_ctx(__isl_keep isl_ast_expr *expr)
+{
+	return expr ? expr->ctx : NULL;
+}
+
+enum isl_ast_expr_type isl_ast_expr_get_type(__isl_keep isl_ast_expr *expr)
+{
+	return expr ? expr->type : isl_ast_expr_error;
+}
+
+/* Return the integer value represented by "expr".
+ */
+__isl_give isl_val *isl_ast_expr_get_val(__isl_keep isl_ast_expr *expr)
+{
+	if (!expr)
+		return NULL;
+	if (expr->type != isl_ast_expr_int)
+		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+			"expression not an int", return NULL);
+	return isl_val_copy(expr->u.v);
+}
+
+__isl_give isl_id *isl_ast_expr_get_id(__isl_keep isl_ast_expr *expr)
+{
+	if (!expr)
+		return NULL;
+	if (expr->type != isl_ast_expr_id)
+		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+			"expression not an identifier", return NULL);
+
+	return isl_id_copy(expr->u.id);
+}
+
+enum isl_ast_op_type isl_ast_expr_get_op_type(__isl_keep isl_ast_expr *expr)
+{
+	if (!expr)
+		return isl_ast_op_error;
+	if (expr->type != isl_ast_expr_op)
+		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+			"expression not an operation", return isl_ast_op_error);
+	return expr->u.op.op;
+}
+
+int isl_ast_expr_get_op_n_arg(__isl_keep isl_ast_expr *expr)
+{
+	if (!expr)
+		return -1;
+	if (expr->type != isl_ast_expr_op)
+		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+			"expression not an operation", return -1);
+	return expr->u.op.n_arg;
+}
+
+__isl_give isl_ast_expr *isl_ast_expr_get_op_arg(__isl_keep isl_ast_expr *expr,
+	int pos)
+{
+	if (!expr)
+		return NULL;
+	if (expr->type != isl_ast_expr_op)
+		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+			"expression not an operation", return NULL);
+	if (pos < 0 || pos >= expr->u.op.n_arg)
+		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+			"index out of bounds", return NULL);
+
+	return isl_ast_expr_copy(expr->u.op.args[pos]);
+}
+
+/* Replace the argument at position "pos" of "expr" by "arg".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,
+	int pos, __isl_take isl_ast_expr *arg)
+{
+	expr = isl_ast_expr_cow(expr);
+	if (!expr || !arg)
+		goto error;
+	if (expr->type != isl_ast_expr_op)
+		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+			"expression not an operation", goto error);
+	if (pos < 0 || pos >= expr->u.op.n_arg)
+		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+			"index out of bounds", goto error);
+
+	isl_ast_expr_free(expr->u.op.args[pos]);
+	expr->u.op.args[pos] = arg;
+
+	return expr;
+error:
+	isl_ast_expr_free(arg);
+	return isl_ast_expr_free(expr);
+}
+
+/* Is "expr1" equal to "expr2"?
+ */
+int isl_ast_expr_is_equal(__isl_keep isl_ast_expr *expr1,
+	__isl_keep isl_ast_expr *expr2)
+{
+	int i;
+
+	if (!expr1 || !expr2)
+		return -1;
+
+	if (expr1 == expr2)
+		return 1;
+	if (expr1->type != expr2->type)
+		return 0;
+	switch (expr1->type) {
+	case isl_ast_expr_int:
+		return isl_val_eq(expr1->u.v, expr2->u.v);
+	case isl_ast_expr_id:
+		return expr1->u.id == expr2->u.id;
+	case isl_ast_expr_op:
+		if (expr1->u.op.op != expr2->u.op.op)
+			return 0;
+		if (expr1->u.op.n_arg != expr2->u.op.n_arg)
+			return 0;
+		for (i = 0; i < expr1->u.op.n_arg; ++i) {
+			int equal;
+			equal = isl_ast_expr_is_equal(expr1->u.op.args[i],
+							expr2->u.op.args[i]);
+				return 0;
+			if (equal < 0 || !equal)
+				return equal;
+		}
+		return 1;
+	case isl_ast_expr_error:
+		return -1;
+	}
+}
+
+/* Create a new operation expression of operation type "op",
+ * with "n_arg" as yet unspecified arguments.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_op(isl_ctx *ctx,
+	enum isl_ast_op_type op, int n_arg)
+{
+	isl_ast_expr *expr;
+
+	expr = isl_calloc_type(ctx, isl_ast_expr);
+	if (!expr)
+		return NULL;
+
+	expr->ctx = ctx;
+	isl_ctx_ref(ctx);
+	expr->ref = 1;
+	expr->type = isl_ast_expr_op;
+	expr->u.op.op = op;
+	expr->u.op.n_arg = n_arg;
+	expr->u.op.args = isl_calloc_array(ctx, isl_ast_expr *, n_arg);
+
+	if (n_arg && !expr->u.op.args)
+		return isl_ast_expr_free(expr);
+
+	return expr;
+}
+
+/* Create a new id expression representing "id".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_from_id(__isl_take isl_id *id)
+{
+	isl_ctx *ctx;
+	isl_ast_expr *expr;
+
+	if (!id)
+		return NULL;
+
+	ctx = isl_id_get_ctx(id);
+	expr = isl_calloc_type(ctx, isl_ast_expr);
+	if (!expr)
+		goto error;
+
+	expr->ctx = ctx;
+	isl_ctx_ref(ctx);
+	expr->ref = 1;
+	expr->type = isl_ast_expr_id;
+	expr->u.id = id;
+
+	return expr;
+error:
+	isl_id_free(id);
+	return NULL;
+}
+
+/* Create a new integer expression representing "i".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_int_si(isl_ctx *ctx, int i)
+{
+	isl_ast_expr *expr;
+
+	expr = isl_calloc_type(ctx, isl_ast_expr);
+	if (!expr)
+		return NULL;
+
+	expr->ctx = ctx;
+	isl_ctx_ref(ctx);
+	expr->ref = 1;
+	expr->type = isl_ast_expr_int;
+	expr->u.v = isl_val_int_from_si(ctx, i);
+	if (!expr->u.v)
+		return isl_ast_expr_free(expr);
+
+	return expr;
+}
+
+/* Create a new integer expression representing "v".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_from_val(__isl_take isl_val *v)
+{
+	isl_ctx *ctx;
+	isl_ast_expr *expr;
+
+	if (!v)
+		return NULL;
+	if (!isl_val_is_int(v))
+		isl_die(isl_val_get_ctx(v), isl_error_invalid,
+			"expecting integer value", goto error);
+
+	ctx = isl_val_get_ctx(v);
+	expr = isl_calloc_type(ctx, isl_ast_expr);
+	if (!expr)
+		goto error;
+
+	expr->ctx = ctx;
+	isl_ctx_ref(ctx);
+	expr->ref = 1;
+	expr->type = isl_ast_expr_int;
+	expr->u.v = v;
+
+	return expr;
+error:
+	isl_val_free(v);
+	return NULL;
+}
+
+/* Create an expression representing the unary operation "type" applied to
+ * "arg".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_unary(enum isl_ast_op_type type,
+	__isl_take isl_ast_expr *arg)
+{
+	isl_ctx *ctx;
+	isl_ast_expr *expr = NULL;
+
+	if (!arg)
+		return NULL;
+
+	ctx = isl_ast_expr_get_ctx(arg);
+	expr = isl_ast_expr_alloc_op(ctx, type, 1);
+	if (!expr)
+		goto error;
+
+	expr->u.op.args[0] = arg;
+
+	return expr;
+error:
+	isl_ast_expr_free(arg);
+	return NULL;
+}
+
+/* Create an expression representing the negation of "arg".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_neg(__isl_take isl_ast_expr *arg)
+{
+	return isl_ast_expr_alloc_unary(isl_ast_op_minus, arg);
+}
+
+/* Create an expression representing the address of "expr".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_address_of(__isl_take isl_ast_expr *expr)
+{
+	if (!expr)
+		return NULL;
+
+	if (isl_ast_expr_get_type(expr) != isl_ast_expr_op ||
+	    isl_ast_expr_get_op_type(expr) != isl_ast_op_access)
+		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+			"can only take address of access expressions",
+			return isl_ast_expr_free(expr));
+
+	return isl_ast_expr_alloc_unary(isl_ast_op_address_of, expr);
+}
+
+/* Create an expression representing the binary operation "type"
+ * applied to "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_alloc_binary(enum isl_ast_op_type type,
+	__isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2)
+{
+	isl_ctx *ctx;
+	isl_ast_expr *expr = NULL;
+
+	if (!expr1 || !expr2)
+		goto error;
+
+	ctx = isl_ast_expr_get_ctx(expr1);
+	expr = isl_ast_expr_alloc_op(ctx, type, 2);
+	if (!expr)
+		goto error;
+
+	expr->u.op.args[0] = expr1;
+	expr->u.op.args[1] = expr2;
+
+	return expr;
+error:
+	isl_ast_expr_free(expr1);
+	isl_ast_expr_free(expr2);
+	return NULL;
+}
+
+/* Create an expression representing the sum of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_add(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_add, expr1, expr2);
+}
+
+/* Create an expression representing the difference of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_sub(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_sub, expr1, expr2);
+}
+
+/* Create an expression representing the product of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_mul(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_mul, expr1, expr2);
+}
+
+/* Create an expression representing the quotient of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_div(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_div, expr1, expr2);
+}
+
+/* Create an expression representing the conjunction of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_and(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_and, expr1, expr2);
+}
+
+/* Create an expression representing the disjunction of "expr1" and "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_or(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_or, expr1, expr2);
+}
+
+/* Create an expression representing "expr1" less than or equal to "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_le(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_le, expr1, expr2);
+}
+
+/* Create an expression representing "expr1" less than "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_lt(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_lt, expr1, expr2);
+}
+
+/* Create an expression representing "expr1" greater than or equal to "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_ge(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_ge, expr1, expr2);
+}
+
+/* Create an expression representing "expr1" greater than "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_gt(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_gt, expr1, expr2);
+}
+
+/* Create an expression representing "expr1" equal to "expr2".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_eq(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	return isl_ast_expr_alloc_binary(isl_ast_op_eq, expr1, expr2);
+}
+
+/* Create an expression representing an access to "array" with index
+ * expressions "indices".
+ */
+__isl_give isl_ast_expr *isl_ast_expr_access(__isl_take isl_ast_expr *array,
+	__isl_take isl_ast_expr_list *indices)
+{
+	int i, n;
+	isl_ctx *ctx;
+	isl_ast_expr *access = NULL;
+
+	if (!array || !indices)
+		goto error;
+
+	ctx = isl_ast_expr_get_ctx(array);
+	n = isl_ast_expr_list_n_ast_expr(indices);
+	access = isl_ast_expr_alloc_op(ctx, isl_ast_op_access, 1 + n);
+	if (!access)
+		goto error;
+	for (i = 0; i < n; ++i) {
+		isl_ast_expr *index;
+		index = isl_ast_expr_list_get_ast_expr(indices, i);
+		access->u.op.args[1 + i] = index;
+		if (!index)
+			goto error;
+	}
+	access->u.op.args[0] = array;
+
+	isl_ast_expr_list_free(indices);
+	return access;
+error:
+	isl_ast_expr_free(array);
+	isl_ast_expr_list_free(indices);
+	isl_ast_expr_free(access);
+	return NULL;
+}
+
+/* For each subexpression of "expr" of type isl_ast_expr_id,
+ * if it appears in "id2expr", then replace it by the corresponding
+ * expression.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_substitute_ids(
+	__isl_take isl_ast_expr *expr, __isl_take isl_id_to_ast_expr *id2expr)
+{
+	int i;
+	isl_id *id;
+
+	if (!expr || !id2expr)
+		goto error;
+
+	switch (expr->type) {
+	case isl_ast_expr_int:
+		break;
+	case isl_ast_expr_id:
+		if (!isl_id_to_ast_expr_has(id2expr, expr->u.id))
+			break;
+		id = isl_id_copy(expr->u.id);
+		isl_ast_expr_free(expr);
+		expr = isl_id_to_ast_expr_get(id2expr, id);
+		break;
+	case isl_ast_expr_op:
+		for (i = 0; i < expr->u.op.n_arg; ++i) {
+			isl_ast_expr *arg;
+			arg = isl_ast_expr_copy(expr->u.op.args[i]);
+			arg = isl_ast_expr_substitute_ids(arg,
+					    isl_id_to_ast_expr_copy(id2expr));
+			if (arg == expr->u.op.args[i]) {
+				isl_ast_expr_free(arg);
+				continue;
+			}
+			if (!arg)
+				expr = isl_ast_expr_free(expr);
+			expr = isl_ast_expr_cow(expr);
+			if (!expr) {
+				isl_ast_expr_free(arg);
+				break;
+			}
+			isl_ast_expr_free(expr->u.op.args[i]);
+			expr->u.op.args[i] = arg;
+		}
+		break;
+	case isl_ast_expr_error:
+		expr = isl_ast_expr_free(expr);
+		break;
+	}
+
+	isl_id_to_ast_expr_free(id2expr);
+	return expr;
+error:
+	isl_ast_expr_free(expr);
+	isl_id_to_ast_expr_free(id2expr);
+	return NULL;
+}
+
+isl_ctx *isl_ast_node_get_ctx(__isl_keep isl_ast_node *node)
+{
+	return node ? node->ctx : NULL;
+}
+
+enum isl_ast_node_type isl_ast_node_get_type(__isl_keep isl_ast_node *node)
+{
+	return node ? node->type : isl_ast_node_error;
+}
+
+__isl_give isl_ast_node *isl_ast_node_alloc(isl_ctx *ctx,
+	enum isl_ast_node_type type)
+{
+	isl_ast_node *node;
+
+	node = isl_calloc_type(ctx, isl_ast_node);
+	if (!node)
+		return NULL;
+
+	node->ctx = ctx;
+	isl_ctx_ref(ctx);
+	node->ref = 1;
+	node->type = type;
+
+	return node;
+}
+
+/* Create an if node with the given guard.
+ *
+ * The then body needs to be filled in later.
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_if(__isl_take isl_ast_expr *guard)
+{
+	isl_ast_node *node;
+
+	if (!guard)
+		return NULL;
+
+	node = isl_ast_node_alloc(isl_ast_expr_get_ctx(guard), isl_ast_node_if);
+	if (!node)
+		goto error;
+	node->u.i.guard = guard;
+
+	return node;
+error:
+	isl_ast_expr_free(guard);
+	return NULL;
+}
+
+/* Create a for node with the given iterator.
+ *
+ * The remaining fields need to be filled in later.
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_for(__isl_take isl_id *id)
+{
+	isl_ast_node *node;
+	isl_ctx *ctx;
+
+	if (!id)
+		return NULL;
+
+	ctx = isl_id_get_ctx(id);
+	node = isl_ast_node_alloc(ctx, isl_ast_node_for);
+	if (!node)
+		goto error;
+
+	node->u.f.iterator = isl_ast_expr_from_id(id);
+	if (!node->u.f.iterator)
+		return isl_ast_node_free(node);
+
+	return node;
+error:
+	isl_id_free(id);
+	return NULL;
+}
+
+/* Create a user node evaluating "expr".
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_user(__isl_take isl_ast_expr *expr)
+{
+	isl_ctx *ctx;
+	isl_ast_node *node;
+
+	if (!expr)
+		return NULL;
+
+	ctx = isl_ast_expr_get_ctx(expr);
+	node = isl_ast_node_alloc(ctx, isl_ast_node_user);
+	if (!node)
+		goto error;
+
+	node->u.e.expr = expr;
+
+	return node;
+error:
+	isl_ast_expr_free(expr);
+	return NULL;
+}
+
+/* Create a block node with the given children.
+ */
+__isl_give isl_ast_node *isl_ast_node_alloc_block(
+	__isl_take isl_ast_node_list *list)
+{
+	isl_ast_node *node;
+	isl_ctx *ctx;
+
+	if (!list)
+		return NULL;
+
+	ctx = isl_ast_node_list_get_ctx(list);
+	node = isl_ast_node_alloc(ctx, isl_ast_node_block);
+	if (!node)
+		goto error;
+
+	node->u.b.children = list;
+
+	return node;
+error:
+	isl_ast_node_list_free(list);
+	return NULL;
+}
+
+/* Represent the given list of nodes as a single node, either by
+ * extract the node from a single element list or by creating
+ * a block node with the list of nodes as children.
+ */
+__isl_give isl_ast_node *isl_ast_node_from_ast_node_list(
+	__isl_take isl_ast_node_list *list)
+{
+	isl_ast_node *node;
+
+	if (isl_ast_node_list_n_ast_node(list) != 1)
+		return isl_ast_node_alloc_block(list);
+
+	node = isl_ast_node_list_get_ast_node(list, 0);
+	isl_ast_node_list_free(list);
+
+	return node;
+}
+
+__isl_give isl_ast_node *isl_ast_node_copy(__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+
+	node->ref++;
+	return node;
+}
+
+__isl_give isl_ast_node *isl_ast_node_dup(__isl_keep isl_ast_node *node)
+{
+	isl_ast_node *dup;
+
+	if (!node)
+		return NULL;
+
+	dup = isl_ast_node_alloc(isl_ast_node_get_ctx(node), node->type);
+	if (!dup)
+		return NULL;
+
+	switch (node->type) {
+	case isl_ast_node_if:
+		dup->u.i.guard = isl_ast_expr_copy(node->u.i.guard);
+		dup->u.i.then = isl_ast_node_copy(node->u.i.then);
+		dup->u.i.else_node = isl_ast_node_copy(node->u.i.else_node);
+		if (!dup->u.i.guard  || !dup->u.i.then ||
+		    (node->u.i.else_node && !dup->u.i.else_node))
+			return isl_ast_node_free(dup);
+		break;
+	case isl_ast_node_for:
+		dup->u.f.iterator = isl_ast_expr_copy(node->u.f.iterator);
+		dup->u.f.init = isl_ast_expr_copy(node->u.f.init);
+		dup->u.f.cond = isl_ast_expr_copy(node->u.f.cond);
+		dup->u.f.inc = isl_ast_expr_copy(node->u.f.inc);
+		dup->u.f.body = isl_ast_node_copy(node->u.f.body);
+		if (!dup->u.f.iterator || !dup->u.f.init || !dup->u.f.cond ||
+		    !dup->u.f.inc || !dup->u.f.body)
+			return isl_ast_node_free(dup);
+		break;
+	case isl_ast_node_block:
+		dup->u.b.children = isl_ast_node_list_copy(node->u.b.children);
+		if (!dup->u.b.children)
+			return isl_ast_node_free(dup);
+		break;
+	case isl_ast_node_user:
+		dup->u.e.expr = isl_ast_expr_copy(node->u.e.expr);
+		if (!dup->u.e.expr)
+			return isl_ast_node_free(dup);
+		break;
+	case isl_ast_node_error:
+		break;
+	}
+
+	return dup;
+}
+
+__isl_give isl_ast_node *isl_ast_node_cow(__isl_take isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+
+	if (node->ref == 1)
+		return node;
+	node->ref--;
+	return isl_ast_node_dup(node);
+}
+
+__isl_null isl_ast_node *isl_ast_node_free(__isl_take isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+
+	if (--node->ref > 0)
+		return NULL;
+
+	switch (node->type) {
+	case isl_ast_node_if:
+		isl_ast_expr_free(node->u.i.guard);
+		isl_ast_node_free(node->u.i.then);
+		isl_ast_node_free(node->u.i.else_node);
+		break;
+	case isl_ast_node_for:
+		isl_ast_expr_free(node->u.f.iterator);
+		isl_ast_expr_free(node->u.f.init);
+		isl_ast_expr_free(node->u.f.cond);
+		isl_ast_expr_free(node->u.f.inc);
+		isl_ast_node_free(node->u.f.body);
+		break;
+	case isl_ast_node_block:
+		isl_ast_node_list_free(node->u.b.children);
+		break;
+	case isl_ast_node_user:
+		isl_ast_expr_free(node->u.e.expr);
+		break;
+	case isl_ast_node_error:
+		break;
+	}
+
+	isl_id_free(node->annotation);
+	isl_ctx_deref(node->ctx);
+	free(node);
+
+	return NULL;
+}
+
+/* Replace the body of the for node "node" by "body".
+ */
+__isl_give isl_ast_node *isl_ast_node_for_set_body(
+	__isl_take isl_ast_node *node, __isl_take isl_ast_node *body)
+{
+	node = isl_ast_node_cow(node);
+	if (!node || !body)
+		goto error;
+	if (node->type != isl_ast_node_for)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a for node", goto error);
+
+	isl_ast_node_free(node->u.f.body);
+	node->u.f.body = body;
+
+	return node;
+error:
+	isl_ast_node_free(node);
+	isl_ast_node_free(body);
+	return NULL;
+}
+
+__isl_give isl_ast_node *isl_ast_node_for_get_body(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+	if (node->type != isl_ast_node_for)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a for node", return NULL);
+	return isl_ast_node_copy(node->u.f.body);
+}
+
+/* Mark the given for node as being degenerate.
+ */
+__isl_give isl_ast_node *isl_ast_node_for_mark_degenerate(
+	__isl_take isl_ast_node *node)
+{
+	node = isl_ast_node_cow(node);
+	if (!node)
+		return NULL;
+	node->u.f.degenerate = 1;
+	return node;
+}
+
+int isl_ast_node_for_is_degenerate(__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return -1;
+	if (node->type != isl_ast_node_for)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a for node", return -1);
+	return node->u.f.degenerate;
+}
+
+__isl_give isl_ast_expr *isl_ast_node_for_get_iterator(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+	if (node->type != isl_ast_node_for)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a for node", return NULL);
+	return isl_ast_expr_copy(node->u.f.iterator);
+}
+
+__isl_give isl_ast_expr *isl_ast_node_for_get_init(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+	if (node->type != isl_ast_node_for)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a for node", return NULL);
+	return isl_ast_expr_copy(node->u.f.init);
+}
+
+/* Return the condition expression of the given for node.
+ *
+ * If the for node is degenerate, then the condition is not explicitly
+ * stored in the node.  Instead, it is constructed as
+ *
+ *	iterator <= init
+ */
+__isl_give isl_ast_expr *isl_ast_node_for_get_cond(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+	if (node->type != isl_ast_node_for)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a for node", return NULL);
+	if (!node->u.f.degenerate)
+		return isl_ast_expr_copy(node->u.f.cond);
+
+	return isl_ast_expr_alloc_binary(isl_ast_op_le,
+				isl_ast_expr_copy(node->u.f.iterator),
+				isl_ast_expr_copy(node->u.f.init));
+}
+
+/* Return the increment of the given for node.
+ *
+ * If the for node is degenerate, then the increment is not explicitly
+ * stored in the node.  We simply return "1".
+ */
+__isl_give isl_ast_expr *isl_ast_node_for_get_inc(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+	if (node->type != isl_ast_node_for)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a for node", return NULL);
+	if (!node->u.f.degenerate)
+		return isl_ast_expr_copy(node->u.f.inc);
+	return isl_ast_expr_alloc_int_si(isl_ast_node_get_ctx(node), 1);
+}
+
+/* Replace the then branch of the if node "node" by "child".
+ */
+__isl_give isl_ast_node *isl_ast_node_if_set_then(
+	__isl_take isl_ast_node *node, __isl_take isl_ast_node *child)
+{
+	node = isl_ast_node_cow(node);
+	if (!node || !child)
+		goto error;
+	if (node->type != isl_ast_node_if)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not an if node", goto error);
+
+	isl_ast_node_free(node->u.i.then);
+	node->u.i.then = child;
+
+	return node;
+error:
+	isl_ast_node_free(node);
+	isl_ast_node_free(child);
+	return NULL;
+}
+
+__isl_give isl_ast_node *isl_ast_node_if_get_then(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+	if (node->type != isl_ast_node_if)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not an if node", return NULL);
+	return isl_ast_node_copy(node->u.i.then);
+}
+
+int isl_ast_node_if_has_else(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return -1;
+	if (node->type != isl_ast_node_if)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not an if node", return -1);
+	return node->u.i.else_node != NULL;
+}
+
+__isl_give isl_ast_node *isl_ast_node_if_get_else(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+	if (node->type != isl_ast_node_if)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not an if node", return NULL);
+	return isl_ast_node_copy(node->u.i.else_node);
+}
+
+__isl_give isl_ast_expr *isl_ast_node_if_get_cond(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+	if (node->type != isl_ast_node_if)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a guard node", return NULL);
+	return isl_ast_expr_copy(node->u.i.guard);
+}
+
+__isl_give isl_ast_node_list *isl_ast_node_block_get_children(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+	if (node->type != isl_ast_node_block)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a block node", return NULL);
+	return isl_ast_node_list_copy(node->u.b.children);
+}
+
+__isl_give isl_ast_expr *isl_ast_node_user_get_expr(
+	__isl_keep isl_ast_node *node)
+{
+	if (!node)
+		return NULL;
+	if (node->type != isl_ast_node_user)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a user node", return NULL);
+
+	return isl_ast_expr_copy(node->u.e.expr);
+}
+
+__isl_give isl_id *isl_ast_node_get_annotation(__isl_keep isl_ast_node *node)
+{
+	return node ? isl_id_copy(node->annotation) : NULL;
+}
+
+/* Replace node->annotation by "annotation".
+ */
+__isl_give isl_ast_node *isl_ast_node_set_annotation(
+	__isl_take isl_ast_node *node, __isl_take isl_id *annotation)
+{
+	node = isl_ast_node_cow(node);
+	if (!node || !annotation)
+		goto error;
+
+	isl_id_free(node->annotation);
+	node->annotation = annotation;
+
+	return node;
+error:
+	isl_id_free(annotation);
+	return isl_ast_node_free(node);
+}
+
+/* Textual C representation of the various operators.
+ */
+static char *op_str[] = {
+	[isl_ast_op_and] = "&&",
+	[isl_ast_op_and_then] = "&&",
+	[isl_ast_op_or] = "||",
+	[isl_ast_op_or_else] = "||",
+	[isl_ast_op_max] = "max",
+	[isl_ast_op_min] = "min",
+	[isl_ast_op_minus] = "-",
+	[isl_ast_op_add] = "+",
+	[isl_ast_op_sub] = "-",
+	[isl_ast_op_mul] = "*",
+	[isl_ast_op_pdiv_q] = "/",
+	[isl_ast_op_pdiv_r] = "%",
+	[isl_ast_op_zdiv_r] = "%",
+	[isl_ast_op_div] = "/",
+	[isl_ast_op_eq] = "==",
+	[isl_ast_op_le] = "<=",
+	[isl_ast_op_ge] = ">=",
+	[isl_ast_op_lt] = "<",
+	[isl_ast_op_gt] = ">",
+	[isl_ast_op_member] = ".",
+	[isl_ast_op_address_of] = "&"
+};
+
+/* Precedence in C of the various operators.
+ * Based on http://en.wikipedia.org/wiki/Operators_in_C_and_C++
+ * Lowest value means highest precedence.
+ */
+static int op_prec[] = {
+	[isl_ast_op_and] = 13,
+	[isl_ast_op_and_then] = 13,
+	[isl_ast_op_or] = 14,
+	[isl_ast_op_or_else] = 14,
+	[isl_ast_op_max] = 2,
+	[isl_ast_op_min] = 2,
+	[isl_ast_op_minus] = 3,
+	[isl_ast_op_add] = 6,
+	[isl_ast_op_sub] = 6,
+	[isl_ast_op_mul] = 5,
+	[isl_ast_op_div] = 5,
+	[isl_ast_op_fdiv_q] = 2,
+	[isl_ast_op_pdiv_q] = 5,
+	[isl_ast_op_pdiv_r] = 5,
+	[isl_ast_op_zdiv_r] = 5,
+	[isl_ast_op_cond] = 15,
+	[isl_ast_op_select] = 15,
+	[isl_ast_op_eq] = 9,
+	[isl_ast_op_le] = 8,
+	[isl_ast_op_ge] = 8,
+	[isl_ast_op_lt] = 8,
+	[isl_ast_op_gt] = 8,
+	[isl_ast_op_call] = 2,
+	[isl_ast_op_access] = 2,
+	[isl_ast_op_member] = 2,
+	[isl_ast_op_address_of] = 3
+};
+
+/* Is the operator left-to-right associative?
+ */
+static int op_left[] = {
+	[isl_ast_op_and] = 1,
+	[isl_ast_op_and_then] = 1,
+	[isl_ast_op_or] = 1,
+	[isl_ast_op_or_else] = 1,
+	[isl_ast_op_max] = 1,
+	[isl_ast_op_min] = 1,
+	[isl_ast_op_minus] = 0,
+	[isl_ast_op_add] = 1,
+	[isl_ast_op_sub] = 1,
+	[isl_ast_op_mul] = 1,
+	[isl_ast_op_div] = 1,
+	[isl_ast_op_fdiv_q] = 1,
+	[isl_ast_op_pdiv_q] = 1,
+	[isl_ast_op_pdiv_r] = 1,
+	[isl_ast_op_zdiv_r] = 1,
+	[isl_ast_op_cond] = 0,
+	[isl_ast_op_select] = 0,
+	[isl_ast_op_eq] = 1,
+	[isl_ast_op_le] = 1,
+	[isl_ast_op_ge] = 1,
+	[isl_ast_op_lt] = 1,
+	[isl_ast_op_gt] = 1,
+	[isl_ast_op_call] = 1,
+	[isl_ast_op_access] = 1,
+	[isl_ast_op_member] = 1,
+	[isl_ast_op_address_of] = 0
+};
+
+static int is_and(enum isl_ast_op_type op)
+{
+	return op == isl_ast_op_and || op == isl_ast_op_and_then;
+}
+
+static int is_or(enum isl_ast_op_type op)
+{
+	return op == isl_ast_op_or || op == isl_ast_op_or_else;
+}
+
+static int is_add_sub(enum isl_ast_op_type op)
+{
+	return op == isl_ast_op_add || op == isl_ast_op_sub;
+}
+
+static int is_div_mod(enum isl_ast_op_type op)
+{
+	return op == isl_ast_op_div ||
+	       op == isl_ast_op_pdiv_r ||
+	       op == isl_ast_op_zdiv_r;
+}
+
+/* Do we need/want parentheses around "expr" as a subexpression of
+ * an "op" operation?  If "left" is set, then "expr" is the left-most
+ * operand.
+ *
+ * We only need parentheses if "expr" represents an operation.
+ *
+ * If op has a higher precedence than expr->u.op.op, then we need
+ * parentheses.
+ * If op and expr->u.op.op have the same precedence, but the operations
+ * are performed in an order that is different from the associativity,
+ * then we need parentheses.
+ *
+ * An and inside an or technically does not require parentheses,
+ * but some compilers complain about that, so we add them anyway.
+ *
+ * Computations such as "a / b * c" and "a % b + c" can be somewhat
+ * difficult to read, so we add parentheses for those as well.
+ */
+static int sub_expr_need_parens(enum isl_ast_op_type op,
+	__isl_keep isl_ast_expr *expr, int left)
+{
+	if (expr->type != isl_ast_expr_op)
+		return 0;
+
+	if (op_prec[expr->u.op.op] > op_prec[op])
+		return 1;
+	if (op_prec[expr->u.op.op] == op_prec[op] && left != op_left[op])
+		return 1;
+
+	if (is_or(op) && is_and(expr->u.op.op))
+		return 1;
+	if (op == isl_ast_op_mul && expr->u.op.op != isl_ast_op_mul &&
+	    op_prec[expr->u.op.op] == op_prec[op])
+		return 1;
+	if (is_add_sub(op) && is_div_mod(expr->u.op.op))
+		return 1;
+
+	return 0;
+}
+
+/* Print "expr" as a subexpression of an "op" operation.
+ * If "left" is set, then "expr" is the left-most operand.
+ */
+static __isl_give isl_printer *print_sub_expr(__isl_take isl_printer *p,
+	enum isl_ast_op_type op, __isl_keep isl_ast_expr *expr, int left)
+{
+	int need_parens;
+
+	need_parens = sub_expr_need_parens(op, expr, left);
+
+	if (need_parens)
+		p = isl_printer_print_str(p, "(");
+	p = isl_printer_print_ast_expr(p, expr);
+	if (need_parens)
+		p = isl_printer_print_str(p, ")");
+	return p;
+}
+
+/* Print a min or max reduction "expr".
+ */
+static __isl_give isl_printer *print_min_max(__isl_take isl_printer *p,
+	__isl_keep isl_ast_expr *expr)
+{
+	int i = 0;
+
+	for (i = 1; i < expr->u.op.n_arg; ++i) {
+		p = isl_printer_print_str(p, op_str[expr->u.op.op]);
+		p = isl_printer_print_str(p, "(");
+	}
+	p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+	for (i = 1; i < expr->u.op.n_arg; ++i) {
+		p = isl_printer_print_str(p, ", ");
+		p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
+		p = isl_printer_print_str(p, ")");
+	}
+
+	return p;
+}
+
+/* Print a function call "expr".
+ *
+ * The first argument represents the function to be called.
+ */
+static __isl_give isl_printer *print_call(__isl_take isl_printer *p,
+	__isl_keep isl_ast_expr *expr)
+{
+	int i = 0;
+
+	p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+	p = isl_printer_print_str(p, "(");
+	for (i = 1; i < expr->u.op.n_arg; ++i) {
+		if (i != 1)
+			p = isl_printer_print_str(p, ", ");
+		p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
+	}
+	p = isl_printer_print_str(p, ")");
+
+	return p;
+}
+
+/* Print an array access "expr".
+ *
+ * The first argument represents the array being accessed.
+ */
+static __isl_give isl_printer *print_access(__isl_take isl_printer *p,
+	__isl_keep isl_ast_expr *expr)
+{
+	int i = 0;
+
+	p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+	for (i = 1; i < expr->u.op.n_arg; ++i) {
+		p = isl_printer_print_str(p, "[");
+		p = isl_printer_print_ast_expr(p, expr->u.op.args[i]);
+		p = isl_printer_print_str(p, "]");
+	}
+
+	return p;
+}
+
+/* Print "expr" to "p".
+ *
+ * If we are printing in isl format, then we also print an indication
+ * of the size of the expression (if it was computed).
+ */
+__isl_give isl_printer *isl_printer_print_ast_expr(__isl_take isl_printer *p,
+	__isl_keep isl_ast_expr *expr)
+{
+	if (!p)
+		return NULL;
+	if (!expr)
+		return isl_printer_free(p);
+
+	switch (expr->type) {
+	case isl_ast_expr_op:
+		if (expr->u.op.op == isl_ast_op_call) {
+			p = print_call(p, expr);
+			break;
+		}
+		if (expr->u.op.op == isl_ast_op_access) {
+			p = print_access(p, expr);
+			break;
+		}
+		if (expr->u.op.n_arg == 1) {
+			p = isl_printer_print_str(p, op_str[expr->u.op.op]);
+			p = print_sub_expr(p, expr->u.op.op,
+						expr->u.op.args[0], 0);
+			break;
+		}
+		if (expr->u.op.op == isl_ast_op_fdiv_q) {
+			p = isl_printer_print_str(p, "floord(");
+			p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+			p = isl_printer_print_str(p, ", ");
+			p = isl_printer_print_ast_expr(p, expr->u.op.args[1]);
+			p = isl_printer_print_str(p, ")");
+			break;
+		}
+		if (expr->u.op.op == isl_ast_op_max ||
+		    expr->u.op.op == isl_ast_op_min) {
+			p = print_min_max(p, expr);
+			break;
+		}
+		if (expr->u.op.op == isl_ast_op_cond ||
+		    expr->u.op.op == isl_ast_op_select) {
+			p = isl_printer_print_ast_expr(p, expr->u.op.args[0]);
+			p = isl_printer_print_str(p, " ? ");
+			p = isl_printer_print_ast_expr(p, expr->u.op.args[1]);
+			p = isl_printer_print_str(p, " : ");
+			p = isl_printer_print_ast_expr(p, expr->u.op.args[2]);
+			break;
+		}
+		if (expr->u.op.n_arg != 2)
+			isl_die(isl_printer_get_ctx(p), isl_error_internal,
+				"operation should have two arguments",
+				goto error);
+		p = print_sub_expr(p, expr->u.op.op, expr->u.op.args[0], 1);
+		if (expr->u.op.op != isl_ast_op_member)
+			p = isl_printer_print_str(p, " ");
+		p = isl_printer_print_str(p, op_str[expr->u.op.op]);
+		if (expr->u.op.op != isl_ast_op_member)
+			p = isl_printer_print_str(p, " ");
+		p = print_sub_expr(p, expr->u.op.op, expr->u.op.args[1], 0);
+		break;
+	case isl_ast_expr_id:
+		p = isl_printer_print_str(p, isl_id_get_name(expr->u.id));
+		break;
+	case isl_ast_expr_int:
+		p = isl_printer_print_val(p, expr->u.v);
+		break;
+	case isl_ast_expr_error:
+		break;
+	}
+
+	return p;
+error:
+	isl_printer_free(p);
+	return NULL;
+}
+
+/* Print "node" to "p" in "isl format".
+ */
+static __isl_give isl_printer *print_ast_node_isl(__isl_take isl_printer *p,
+	__isl_keep isl_ast_node *node)
+{
+	p = isl_printer_print_str(p, "(");
+	switch (node->type) {
+	case isl_ast_node_for:
+		if (node->u.f.degenerate) {
+			p = isl_printer_print_ast_expr(p, node->u.f.init);
+		} else {
+			p = isl_printer_print_str(p, "init: ");
+			p = isl_printer_print_ast_expr(p, node->u.f.init);
+			p = isl_printer_print_str(p, ", ");
+			p = isl_printer_print_str(p, "cond: ");
+			p = isl_printer_print_ast_expr(p, node->u.f.cond);
+			p = isl_printer_print_str(p, ", ");
+			p = isl_printer_print_str(p, "inc: ");
+			p = isl_printer_print_ast_expr(p, node->u.f.inc);
+		}
+		if (node->u.f.body) {
+			p = isl_printer_print_str(p, ", ");
+			p = isl_printer_print_str(p, "body: ");
+			p = isl_printer_print_ast_node(p, node->u.f.body);
+		}
+		break;
+	case isl_ast_node_user:
+		p = isl_printer_print_ast_expr(p, node->u.e.expr);
+		break;
+	case isl_ast_node_if:
+		p = isl_printer_print_str(p, "guard: ");
+		p = isl_printer_print_ast_expr(p, node->u.i.guard);
+		if (node->u.i.then) {
+			p = isl_printer_print_str(p, ", ");
+			p = isl_printer_print_str(p, "then: ");
+			p = isl_printer_print_ast_node(p, node->u.i.then);
+		}
+		if (node->u.i.else_node) {
+			p = isl_printer_print_str(p, ", ");
+			p = isl_printer_print_str(p, "else: ");
+			p = isl_printer_print_ast_node(p, node->u.i.else_node);
+		}
+		break;
+	case isl_ast_node_block:
+		p = isl_printer_print_ast_node_list(p, node->u.b.children);
+		break;
+	default:
+		break;
+	}
+	p = isl_printer_print_str(p, ")");
+	return p;
+}
+
+/* Do we need to print a block around the body "node" of a for or if node?
+ *
+ * If the node is a block, then we need to print a block.
+ * Also if the node is a degenerate for then we will print it as
+ * an assignment followed by the body of the for loop, so we need a block
+ * as well.
+ * If the node is an if node with an else, then we print a block
+ * to avoid spurious dangling else warnings emitted by some compilers.
+ * If the ast_always_print_block option has been set, then we print a block.
+ */
+static int need_block(__isl_keep isl_ast_node *node)
+{
+	isl_ctx *ctx;
+
+	if (node->type == isl_ast_node_block)
+		return 1;
+	if (node->type == isl_ast_node_for && node->u.f.degenerate)
+		return 1;
+	if (node->type == isl_ast_node_if && node->u.i.else_node)
+		return 1;
+
+	ctx = isl_ast_node_get_ctx(node);
+	return isl_options_get_ast_always_print_block(ctx);
+}
+
+static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,
+	__isl_keep isl_ast_node *node,
+	__isl_keep isl_ast_print_options *options, int in_block, int in_list);
+static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,
+	__isl_keep isl_ast_node *node,
+	__isl_keep isl_ast_print_options *options, int new_line);
+
+/* Print the body "node" of a for or if node.
+ * If "else_node" is set, then it is printed as well.
+ *
+ * We first check if we need to print out a block.
+ * We always print out a block if there is an else node to make
+ * sure that the else node is matched to the correct if node.
+ *
+ * If the else node is itself an if, then we print it as
+ *
+ *	} else if (..)
+ *
+ * Otherwise the else node is printed as
+ *
+ *	} else
+ *	  node
+ */
+static __isl_give isl_printer *print_body_c(__isl_take isl_printer *p,
+	__isl_keep isl_ast_node *node, __isl_keep isl_ast_node *else_node,
+	__isl_keep isl_ast_print_options *options)
+{
+	if (!node)
+		return isl_printer_free(p);
+
+	if (!else_node && !need_block(node)) {
+		p = isl_printer_end_line(p);
+		p = isl_printer_indent(p, 2);
+		p = isl_ast_node_print(node, p,
+					isl_ast_print_options_copy(options));
+		p = isl_printer_indent(p, -2);
+		return p;
+	}
+
+	p = isl_printer_print_str(p, " {");
+	p = isl_printer_end_line(p);
+	p = isl_printer_indent(p, 2);
+	p = print_ast_node_c(p, node, options, 1, 0);
+	p = isl_printer_indent(p, -2);
+	p = isl_printer_start_line(p);
+	p = isl_printer_print_str(p, "}");
+	if (else_node) {
+		if (else_node->type == isl_ast_node_if) {
+			p = isl_printer_print_str(p, " else ");
+			p = print_if_c(p, else_node, options, 0);
+		} else {
+			p = isl_printer_print_str(p, " else");
+			p = print_body_c(p, else_node, NULL, options);
+		}
+	} else
+		p = isl_printer_end_line(p);
+
+	return p;
+}
+
+/* Print the start of a compound statement.
+ */
+static __isl_give isl_printer *start_block(__isl_take isl_printer *p)
+{
+	p = isl_printer_start_line(p);
+	p = isl_printer_print_str(p, "{");
+	p = isl_printer_end_line(p);
+	p = isl_printer_indent(p, 2);
+
+	return p;
+}
+
+/* Print the end of a compound statement.
+ */
+static __isl_give isl_printer *end_block(__isl_take isl_printer *p)
+{
+	p = isl_printer_indent(p, -2);
+	p = isl_printer_start_line(p);
+	p = isl_printer_print_str(p, "}");
+	p = isl_printer_end_line(p);
+
+	return p;
+}
+
+/* Print the for node "node".
+ *
+ * If the for node is degenerate, it is printed as
+ *
+ *	type iterator = init;
+ *	body
+ *
+ * Otherwise, it is printed as
+ *
+ *	for (type iterator = init; cond; iterator += inc)
+ *		body
+ *
+ * "in_block" is set if we are currently inside a block.
+ * "in_list" is set if the current node is not alone in the block.
+ * If we are not in a block or if the current not is not alone in the block
+ * then we print a block around a degenerate for loop such that the variable
+ * declaration will not conflict with any potential other declaration
+ * of the same variable.
+ */
+static __isl_give isl_printer *print_for_c(__isl_take isl_printer *p,
+	__isl_keep isl_ast_node *node,
+	__isl_keep isl_ast_print_options *options, int in_block, int in_list)
+{
+	isl_id *id;
+	const char *name;
+	const char *type;
+
+	type = isl_options_get_ast_iterator_type(isl_printer_get_ctx(p));
+	if (!node->u.f.degenerate) {
+		id = isl_ast_expr_get_id(node->u.f.iterator);
+		name = isl_id_get_name(id);
+		isl_id_free(id);
+		p = isl_printer_start_line(p);
+		p = isl_printer_print_str(p, "for (");
+		p = isl_printer_print_str(p, type);
+		p = isl_printer_print_str(p, " ");
+		p = isl_printer_print_str(p, name);
+		p = isl_printer_print_str(p, " = ");
+		p = isl_printer_print_ast_expr(p, node->u.f.init);
+		p = isl_printer_print_str(p, "; ");
+		p = isl_printer_print_ast_expr(p, node->u.f.cond);
+		p = isl_printer_print_str(p, "; ");
+		p = isl_printer_print_str(p, name);
+		p = isl_printer_print_str(p, " += ");
+		p = isl_printer_print_ast_expr(p, node->u.f.inc);
+		p = isl_printer_print_str(p, ")");
+		p = print_body_c(p, node->u.f.body, NULL, options);
+	} else {
+		id = isl_ast_expr_get_id(node->u.f.iterator);
+		name = isl_id_get_name(id);
+		isl_id_free(id);
+		if (!in_block || in_list)
+			p = start_block(p);
+		p = isl_printer_start_line(p);
+		p = isl_printer_print_str(p, type);
+		p = isl_printer_print_str(p, " ");
+		p = isl_printer_print_str(p, name);
+		p = isl_printer_print_str(p, " = ");
+		p = isl_printer_print_ast_expr(p, node->u.f.init);
+		p = isl_printer_print_str(p, ";");
+		p = isl_printer_end_line(p);
+		p = print_ast_node_c(p, node->u.f.body, options, 1, 0);
+		if (!in_block || in_list)
+			p = end_block(p);
+	}
+
+	return p;
+}
+
+/* Print the if node "node".
+ * If "new_line" is set then the if node should be printed on a new line.
+ */
+static __isl_give isl_printer *print_if_c(__isl_take isl_printer *p,
+	__isl_keep isl_ast_node *node,
+	__isl_keep isl_ast_print_options *options, int new_line)
+{
+	if (new_line)
+		p = isl_printer_start_line(p);
+	p = isl_printer_print_str(p, "if (");
+	p = isl_printer_print_ast_expr(p, node->u.i.guard);
+	p = isl_printer_print_str(p, ")");
+	p = print_body_c(p, node->u.i.then, node->u.i.else_node, options);
+
+	return p;
+}
+
+/* Print the "node" to "p".
+ *
+ * "in_block" is set if we are currently inside a block.
+ * If so, we do not print a block around the children of a block node.
+ * We do this to avoid an extra block around the body of a degenerate
+ * for node.
+ *
+ * "in_list" is set if the current node is not alone in the block.
+ */
+static __isl_give isl_printer *print_ast_node_c(__isl_take isl_printer *p,
+	__isl_keep isl_ast_node *node,
+	__isl_keep isl_ast_print_options *options, int in_block, int in_list)
+{
+	switch (node->type) {
+	case isl_ast_node_for:
+		if (options->print_for)
+			return options->print_for(p,
+					isl_ast_print_options_copy(options),
+					node, options->print_for_user);
+		p = print_for_c(p, node, options, in_block, in_list);
+		break;
+	case isl_ast_node_if:
+		p = print_if_c(p, node, options, 1);
+		break;
+	case isl_ast_node_block:
+		if (!in_block)
+			p = start_block(p);
+		p = isl_ast_node_list_print(node->u.b.children, p, options);
+		if (!in_block)
+			p = end_block(p);
+		break;
+	case isl_ast_node_user:
+		if (options->print_user)
+			return options->print_user(p,
+					isl_ast_print_options_copy(options),
+					node, options->print_user_user);
+		p = isl_printer_start_line(p);
+		p = isl_printer_print_ast_expr(p, node->u.e.expr);
+		p = isl_printer_print_str(p, ";");
+		p = isl_printer_end_line(p);
+		break;
+	case isl_ast_node_error:
+		break;
+	}
+	return p;
+}
+
+/* Print the for node "node" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_for_print(__isl_keep isl_ast_node *node,
+	__isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
+{
+	if (!node || !options)
+		goto error;
+	if (node->type != isl_ast_node_for)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not a for node", goto error);
+	p = print_for_c(p, node, options, 0, 0);
+	isl_ast_print_options_free(options);
+	return p;
+error:
+	isl_ast_print_options_free(options);
+	isl_printer_free(p);
+	return NULL;
+}
+
+/* Print the if node "node" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_if_print(__isl_keep isl_ast_node *node,
+	__isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
+{
+	if (!node || !options)
+		goto error;
+	if (node->type != isl_ast_node_if)
+		isl_die(isl_ast_node_get_ctx(node), isl_error_invalid,
+			"not an if node", goto error);
+	p = print_if_c(p, node, options, 1);
+	isl_ast_print_options_free(options);
+	return p;
+error:
+	isl_ast_print_options_free(options);
+	isl_printer_free(p);
+	return NULL;
+}
+
+/* Print "node" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_print(__isl_keep isl_ast_node *node,
+	__isl_take isl_printer *p, __isl_take isl_ast_print_options *options)
+{
+	if (!options || !node)
+		goto error;
+	p = print_ast_node_c(p, node, options, 0, 0);
+	isl_ast_print_options_free(options);
+	return p;
+error:
+	isl_ast_print_options_free(options);
+	isl_printer_free(p);
+	return NULL;
+}
+
+/* Print "node" to "p".
+ */
+__isl_give isl_printer *isl_printer_print_ast_node(__isl_take isl_printer *p,
+	__isl_keep isl_ast_node *node)
+{
+	int format;
+	isl_ast_print_options *options;
+
+	if (!p)
+		return NULL;
+
+	format = isl_printer_get_output_format(p);
+	switch (format) {
+	case ISL_FORMAT_ISL:
+		p = print_ast_node_isl(p, node);
+		break;
+	case ISL_FORMAT_C:
+		options = isl_ast_print_options_alloc(isl_printer_get_ctx(p));
+		p = isl_ast_node_print(node, p, options);
+		break;
+	default:
+		isl_die(isl_printer_get_ctx(p), isl_error_unsupported,
+			"output format not supported for ast_node",
+			return isl_printer_free(p));
+	}
+
+	return p;
+}
+
+/* Print the list of nodes "list" to "p".
+ */
+__isl_give isl_printer *isl_ast_node_list_print(
+	__isl_keep isl_ast_node_list *list, __isl_take isl_printer *p,
+	__isl_keep isl_ast_print_options *options)
+{
+	int i;
+
+	if (!p || !list || !options)
+		return isl_printer_free(p);
+
+	for (i = 0; i < list->n; ++i)
+		p = print_ast_node_c(p, list->p[i], options, 1, 1);
+
+	return p;
+}
+
+#define ISL_AST_MACRO_FLOORD	(1 << 0)
+#define ISL_AST_MACRO_MIN	(1 << 1)
+#define ISL_AST_MACRO_MAX	(1 << 2)
+#define ISL_AST_MACRO_ALL	(ISL_AST_MACRO_FLOORD | \
+				 ISL_AST_MACRO_MIN | \
+				 ISL_AST_MACRO_MAX)
+
+/* If "expr" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
+ * then set the corresponding bit in "macros".
+ */
+static int ast_expr_required_macros(__isl_keep isl_ast_expr *expr, int macros)
+{
+	int i;
+
+	if (macros == ISL_AST_MACRO_ALL)
+		return macros;
+
+	if (expr->type != isl_ast_expr_op)
+		return macros;
+
+	if (expr->u.op.op == isl_ast_op_min)
+		macros |= ISL_AST_MACRO_MIN;
+	if (expr->u.op.op == isl_ast_op_max)
+		macros |= ISL_AST_MACRO_MAX;
+	if (expr->u.op.op == isl_ast_op_fdiv_q)
+		macros |= ISL_AST_MACRO_FLOORD;
+
+	for (i = 0; i < expr->u.op.n_arg; ++i)
+		macros = ast_expr_required_macros(expr->u.op.args[i], macros);
+
+	return macros;
+}
+
+static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
+	int macros);
+
+/* If "node" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
+ * then set the corresponding bit in "macros".
+ */
+static int ast_node_required_macros(__isl_keep isl_ast_node *node, int macros)
+{
+	if (macros == ISL_AST_MACRO_ALL)
+		return macros;
+
+	switch (node->type) {
+	case isl_ast_node_for:
+		macros = ast_expr_required_macros(node->u.f.init, macros);
+		if (!node->u.f.degenerate) {
+			macros = ast_expr_required_macros(node->u.f.cond,
+								macros);
+			macros = ast_expr_required_macros(node->u.f.inc,
+								macros);
+		}
+		macros = ast_node_required_macros(node->u.f.body, macros);
+		break;
+	case isl_ast_node_if:
+		macros = ast_expr_required_macros(node->u.i.guard, macros);
+		macros = ast_node_required_macros(node->u.i.then, macros);
+		if (node->u.i.else_node)
+			macros = ast_node_required_macros(node->u.i.else_node,
+								macros);
+		break;
+	case isl_ast_node_block:
+		macros = ast_node_list_required_macros(node->u.b.children,
+							macros);
+		break;
+	case isl_ast_node_user:
+		macros = ast_expr_required_macros(node->u.e.expr, macros);
+		break;
+	case isl_ast_node_error:
+		break;
+	}
+
+	return macros;
+}
+
+/* If "list" contains an isl_ast_op_min, isl_ast_op_max or isl_ast_op_fdiv_q
+ * then set the corresponding bit in "macros".
+ */
+static int ast_node_list_required_macros(__isl_keep isl_ast_node_list *list,
+	int macros)
+{
+	int i;
+
+	for (i = 0; i < list->n; ++i)
+		macros = ast_node_required_macros(list->p[i], macros);
+
+	return macros;
+}
+
+/* Print a macro definition for the operator "type".
+ */
+__isl_give isl_printer *isl_ast_op_type_print_macro(
+	enum isl_ast_op_type type, __isl_take isl_printer *p)
+{
+	switch (type) {
+	case isl_ast_op_min:
+		p = isl_printer_start_line(p);
+		p = isl_printer_print_str(p,
+			"#define min(x,y)    ((x) < (y) ? (x) : (y))");
+		p = isl_printer_end_line(p);
+		break;
+	case isl_ast_op_max:
+		p = isl_printer_start_line(p);
+		p = isl_printer_print_str(p,
+			"#define max(x,y)    ((x) > (y) ? (x) : (y))");
+		p = isl_printer_end_line(p);
+		break;
+	case isl_ast_op_fdiv_q:
+		p = isl_printer_start_line(p);
+		p = isl_printer_print_str(p,
+			"#define floord(n,d) "
+			"(((n)<0) ? -((-(n)+(d)-1)/(d)) : (n)/(d))");
+		p = isl_printer_end_line(p);
+		break;
+	default:
+		break;
+	}
+
+	return p;
+}
+
+/* Call "fn" for each type of operation that appears in "node"
+ * and that requires a macro definition.
+ */
+int isl_ast_node_foreach_ast_op_type(__isl_keep isl_ast_node *node,
+	int (*fn)(enum isl_ast_op_type type, void *user), void *user)
+{
+	int macros;
+
+	if (!node)
+		return -1;
+
+	macros = ast_node_required_macros(node, 0);
+
+	if (macros & ISL_AST_MACRO_MIN && fn(isl_ast_op_min, user) < 0)
+		return -1;
+	if (macros & ISL_AST_MACRO_MAX && fn(isl_ast_op_max, user) < 0)
+		return -1;
+	if (macros & ISL_AST_MACRO_FLOORD && fn(isl_ast_op_fdiv_q, user) < 0)
+		return -1;
+
+	return 0;
+}
+
+static int ast_op_type_print_macro(enum isl_ast_op_type type, void *user)
+{
+	isl_printer **p = user;
+
+	*p = isl_ast_op_type_print_macro(type, *p);
+
+	return 0;
+}
+
+/* Print macro definitions for all the macros used in the result
+ * of printing "node.
+ */
+__isl_give isl_printer *isl_ast_node_print_macros(
+	__isl_keep isl_ast_node *node, __isl_take isl_printer *p)
+{
+	if (isl_ast_node_foreach_ast_op_type(node,
+					    &ast_op_type_print_macro, &p) < 0)
+		return isl_printer_free(p);
+	return p;
+}

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_build.c (added)
+++ polly/trunk/lib/External/isl/isl_ast_build.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,2162 @@
+/*
+ * Copyright 2012      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/map.h>
+#include <isl/aff.h>
+#include <isl/map.h>
+#include <isl_ast_build_private.h>
+#include <isl_ast_private.h>
+
+/* Construct a map that isolates the current dimension.
+ *
+ * Essentially, the current dimension of "set" is moved to the single output
+ * dimension in the result, with the current dimension in the domain replaced
+ * by an unconstrained variable.
+ */
+__isl_give isl_map *isl_ast_build_map_to_iterator(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+	isl_map *map;
+
+	map = isl_map_from_domain(set);
+	map = isl_map_add_dims(map, isl_dim_out, 1);
+
+	if (!build)
+		return isl_map_free(map);
+
+	map = isl_map_equate(map, isl_dim_in, build->depth, isl_dim_out, 0);
+	map = isl_map_eliminate(map, isl_dim_in, build->depth, 1);
+
+	return map;
+}
+
+/* Initialize the information derived during the AST generation to default
+ * values for a schedule domain in "space".
+ *
+ * We also check that the remaining fields are not NULL so that
+ * the calling functions don't have to perform this test.
+ */
+static __isl_give isl_ast_build *isl_ast_build_init_derived(
+	__isl_take isl_ast_build *build, __isl_take isl_space *space)
+{
+	isl_ctx *ctx;
+	isl_vec *strides;
+
+	build = isl_ast_build_cow(build);
+	if (!build || !build->domain)
+		goto error;
+
+	ctx = isl_ast_build_get_ctx(build);
+	strides = isl_vec_alloc(ctx, isl_space_dim(space, isl_dim_set));
+	strides = isl_vec_set_si(strides, 1);
+
+	isl_vec_free(build->strides);
+	build->strides = strides;
+
+	space = isl_space_map_from_set(space);
+	isl_multi_aff_free(build->offsets);
+	build->offsets = isl_multi_aff_zero(isl_space_copy(space));
+	isl_multi_aff_free(build->values);
+	build->values = isl_multi_aff_identity(space);
+
+	if (!build->iterators || !build->domain || !build->generated ||
+	    !build->pending || !build->values ||
+	    !build->strides || !build->offsets || !build->options)
+		return isl_ast_build_free(build);
+
+	return build;
+error:
+	isl_space_free(space);
+	return isl_ast_build_free(build);
+}
+
+/* Return an isl_id called "c%d", with "%d" set to "i".
+ * If an isl_id with such a name already appears among the parameters
+ * in build->domain, then adjust the name to "c%d_%d".
+ */
+static __isl_give isl_id *generate_name(isl_ctx *ctx, int i,
+	__isl_keep isl_ast_build *build)
+{
+	int j;
+	char name[16];
+	isl_set *dom = build->domain;
+
+	snprintf(name, sizeof(name), "c%d", i);
+	j = 0;
+	while (isl_set_find_dim_by_name(dom, isl_dim_param, name) >= 0)
+		snprintf(name, sizeof(name), "c%d_%d", i, j++);
+	return isl_id_alloc(ctx, name, NULL);
+}
+
+/* Create an isl_ast_build with "set" as domain.
+ *
+ * The input set is usually a parameter domain, but we currently allow it to
+ * be any kind of set.  We set the domain of the returned isl_ast_build
+ * to "set" and initialize all the other fields to default values.
+ */
+__isl_give isl_ast_build *isl_ast_build_from_context(__isl_take isl_set *set)
+{
+	int i, n;
+	isl_ctx *ctx;
+	isl_space *space;
+	isl_ast_build *build;
+
+	set = isl_set_compute_divs(set);
+	if (!set)
+		return NULL;
+
+	ctx = isl_set_get_ctx(set);
+
+	build = isl_calloc_type(ctx, isl_ast_build);
+	if (!build)
+		goto error;
+
+	build->ref = 1;
+	build->domain = set;
+	build->generated = isl_set_copy(build->domain);
+	build->pending = isl_set_universe(isl_set_get_space(build->domain));
+	build->options = isl_union_map_empty(isl_space_params_alloc(ctx, 0));
+	n = isl_set_dim(set, isl_dim_set);
+	build->depth = n;
+	build->iterators = isl_id_list_alloc(ctx, n);
+	for (i = 0; i < n; ++i) {
+		isl_id *id;
+		if (isl_set_has_dim_id(set, isl_dim_set, i))
+			id = isl_set_get_dim_id(set, isl_dim_set, i);
+		else
+			id = generate_name(ctx, i, build);
+		build->iterators = isl_id_list_add(build->iterators, id);
+	}
+	space = isl_set_get_space(set);
+	if (isl_space_is_params(space))
+		space = isl_space_set_from_params(space);
+
+	return isl_ast_build_init_derived(build, space);
+error:
+	isl_set_free(set);
+	return NULL;
+}
+
+__isl_give isl_ast_build *isl_ast_build_copy(__isl_keep isl_ast_build *build)
+{
+	if (!build)
+		return NULL;
+
+	build->ref++;
+	return build;
+}
+
+__isl_give isl_ast_build *isl_ast_build_dup(__isl_keep isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	isl_ast_build *dup;
+
+	if (!build)
+		return NULL;
+
+	ctx = isl_ast_build_get_ctx(build);
+	dup = isl_calloc_type(ctx, isl_ast_build);
+	if (!dup)
+		return NULL;
+
+	dup->ref = 1;
+	dup->outer_pos = build->outer_pos;
+	dup->depth = build->depth;
+	dup->iterators = isl_id_list_copy(build->iterators);
+	dup->domain = isl_set_copy(build->domain);
+	dup->generated = isl_set_copy(build->generated);
+	dup->pending = isl_set_copy(build->pending);
+	dup->values = isl_multi_aff_copy(build->values);
+	dup->value = isl_pw_aff_copy(build->value);
+	dup->strides = isl_vec_copy(build->strides);
+	dup->offsets = isl_multi_aff_copy(build->offsets);
+	dup->executed = isl_union_map_copy(build->executed);
+	dup->single_valued = build->single_valued;
+	dup->options = isl_union_map_copy(build->options);
+	dup->at_each_domain = build->at_each_domain;
+	dup->at_each_domain_user = build->at_each_domain_user;
+	dup->before_each_for = build->before_each_for;
+	dup->before_each_for_user = build->before_each_for_user;
+	dup->after_each_for = build->after_each_for;
+	dup->after_each_for_user = build->after_each_for_user;
+	dup->create_leaf = build->create_leaf;
+	dup->create_leaf_user = build->create_leaf_user;
+
+	if (!dup->iterators || !dup->domain || !dup->generated ||
+	    !dup->pending || !dup->values ||
+	    !dup->strides || !dup->offsets || !dup->options ||
+	    (build->executed && !dup->executed) ||
+	    (build->value && !dup->value))
+		return isl_ast_build_free(dup);
+
+	return dup;
+}
+
+/* Align the parameters of "build" to those of "model", introducing
+ * additional parameters if needed.
+ */
+__isl_give isl_ast_build *isl_ast_build_align_params(
+	__isl_take isl_ast_build *build, __isl_take isl_space *model)
+{
+	build = isl_ast_build_cow(build);
+	if (!build)
+		goto error;
+
+	build->domain = isl_set_align_params(build->domain,
+						isl_space_copy(model));
+	build->generated = isl_set_align_params(build->generated,
+						isl_space_copy(model));
+	build->pending = isl_set_align_params(build->pending,
+						isl_space_copy(model));
+	build->values = isl_multi_aff_align_params(build->values,
+						isl_space_copy(model));
+	build->offsets = isl_multi_aff_align_params(build->offsets,
+						isl_space_copy(model));
+	build->options = isl_union_map_align_params(build->options,
+						isl_space_copy(model));
+	isl_space_free(model);
+
+	if (!build->domain || !build->values || !build->offsets ||
+	    !build->options)
+		return isl_ast_build_free(build);
+
+	return build;
+error:
+	isl_space_free(model);
+	return NULL;
+}
+
+__isl_give isl_ast_build *isl_ast_build_cow(__isl_take isl_ast_build *build)
+{
+	if (!build)
+		return NULL;
+
+	if (build->ref == 1)
+		return build;
+	build->ref--;
+	return isl_ast_build_dup(build);
+}
+
+__isl_null isl_ast_build *isl_ast_build_free(
+	__isl_take isl_ast_build *build)
+{
+	if (!build)
+		return NULL;
+
+	if (--build->ref > 0)
+		return NULL;
+
+	isl_id_list_free(build->iterators);
+	isl_set_free(build->domain);
+	isl_set_free(build->generated);
+	isl_set_free(build->pending);
+	isl_multi_aff_free(build->values);
+	isl_pw_aff_free(build->value);
+	isl_vec_free(build->strides);
+	isl_multi_aff_free(build->offsets);
+	isl_multi_aff_free(build->schedule_map);
+	isl_union_map_free(build->executed);
+	isl_union_map_free(build->options);
+
+	free(build);
+
+	return NULL;
+}
+
+isl_ctx *isl_ast_build_get_ctx(__isl_keep isl_ast_build *build)
+{
+	return build ? isl_set_get_ctx(build->domain) : NULL;
+}
+
+/* Replace build->options by "options".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_options(
+	__isl_take isl_ast_build *build, __isl_take isl_union_map *options)
+{
+	build = isl_ast_build_cow(build);
+
+	if (!build || !options)
+		goto error;
+
+	isl_union_map_free(build->options);
+	build->options = options;
+
+	return build;
+error:
+	isl_union_map_free(options);
+	return isl_ast_build_free(build);
+}
+
+/* Set the iterators for the next code generation.
+ *
+ * If we still have some iterators left from the previous code generation
+ * (if any) or if iterators have already been set by a previous
+ * call to this function, then we remove them first.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_iterators(
+	__isl_take isl_ast_build *build, __isl_take isl_id_list *iterators)
+{
+	int dim, n_it;
+
+	build = isl_ast_build_cow(build);
+	if (!build)
+		goto error;
+
+	dim = isl_set_dim(build->domain, isl_dim_set);
+	n_it = isl_id_list_n_id(build->iterators);
+	if (n_it < dim)
+		isl_die(isl_ast_build_get_ctx(build), isl_error_internal,
+			"isl_ast_build in inconsistent state", goto error);
+	if (n_it > dim)
+		build->iterators = isl_id_list_drop(build->iterators,
+							dim, n_it - dim);
+	build->iterators = isl_id_list_concat(build->iterators, iterators);
+	if (!build->iterators)
+		return isl_ast_build_free(build);
+
+	return build;
+error:
+	isl_id_list_free(iterators);
+	return isl_ast_build_free(build);
+}
+
+/* Set the "at_each_domain" callback of "build" to "fn".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_at_each_domain(
+	__isl_take isl_ast_build *build,
+	__isl_give isl_ast_node *(*fn)(__isl_take isl_ast_node *node,
+		__isl_keep isl_ast_build *build, void *user), void *user)
+{
+	build = isl_ast_build_cow(build);
+
+	if (!build)
+		return NULL;
+
+	build->at_each_domain = fn;
+	build->at_each_domain_user = user;
+
+	return build;
+}
+
+/* Set the "before_each_for" callback of "build" to "fn".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_before_each_for(
+	__isl_take isl_ast_build *build,
+	__isl_give isl_id *(*fn)(__isl_keep isl_ast_build *build,
+		void *user), void *user)
+{
+	build = isl_ast_build_cow(build);
+
+	if (!build)
+		return NULL;
+
+	build->before_each_for = fn;
+	build->before_each_for_user = user;
+
+	return build;
+}
+
+/* Set the "after_each_for" callback of "build" to "fn".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_after_each_for(
+	__isl_take isl_ast_build *build,
+	__isl_give isl_ast_node *(*fn)(__isl_take isl_ast_node *node,
+		__isl_keep isl_ast_build *build, void *user), void *user)
+{
+	build = isl_ast_build_cow(build);
+
+	if (!build)
+		return NULL;
+
+	build->after_each_for = fn;
+	build->after_each_for_user = user;
+
+	return build;
+}
+
+/* Set the "create_leaf" callback of "build" to "fn".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_create_leaf(
+	__isl_take isl_ast_build *build,
+	__isl_give isl_ast_node *(*fn)(__isl_take isl_ast_build *build,
+		void *user), void *user)
+{
+	build = isl_ast_build_cow(build);
+
+	if (!build)
+		return NULL;
+
+	build->create_leaf = fn;
+	build->create_leaf_user = user;
+
+	return build;
+}
+
+/* Clear all information that is specific to this code generation
+ * and that is (probably) not meaningful to any nested code generation.
+ */
+__isl_give isl_ast_build *isl_ast_build_clear_local_info(
+	__isl_take isl_ast_build *build)
+{
+	isl_space *space;
+
+	build = isl_ast_build_cow(build);
+	if (!build)
+		return NULL;
+
+	space = isl_union_map_get_space(build->options);
+	isl_union_map_free(build->options);
+	build->options = isl_union_map_empty(space);
+
+	build->at_each_domain = NULL;
+	build->at_each_domain_user = NULL;
+	build->before_each_for = NULL;
+	build->before_each_for_user = NULL;
+	build->after_each_for = NULL;
+	build->after_each_for_user = NULL;
+	build->create_leaf = NULL;
+	build->create_leaf_user = NULL;
+
+	if (!build->options)
+		return isl_ast_build_free(build);
+
+	return build;
+}
+
+/* Have any loops been eliminated?
+ * That is, do any of the original schedule dimensions have a fixed
+ * value that has been substituted?
+ */
+static int any_eliminated(isl_ast_build *build)
+{
+	int i;
+
+	for (i = 0; i < build->depth; ++i)
+		if (isl_ast_build_has_affine_value(build, i))
+			return 1;
+
+	return 0;
+}
+
+/* Clear build->schedule_map.
+ * This function should be called whenever anything that might affect
+ * the result of isl_ast_build_get_schedule_map_multi_aff changes.
+ * In particular, it should be called when the depth is changed or
+ * when an iterator is determined to have a fixed value.
+ */
+static void isl_ast_build_reset_schedule_map(__isl_keep isl_ast_build *build)
+{
+	if (!build)
+		return;
+	isl_multi_aff_free(build->schedule_map);
+	build->schedule_map = NULL;
+}
+
+/* Do we need a (non-trivial) schedule map?
+ * That is, is the internal schedule space different from
+ * the external schedule space?
+ *
+ * The internal and external schedule spaces are only the same
+ * if code has been generated for the entire schedule and if none
+ * of the loops have been eliminated.
+ */
+__isl_give int isl_ast_build_need_schedule_map(__isl_keep isl_ast_build *build)
+{
+	int dim;
+
+	if (!build)
+		return -1;
+
+	dim = isl_set_dim(build->domain, isl_dim_set);
+	return build->depth != dim || any_eliminated(build);
+}
+
+/* Return a mapping from the internal schedule space to the external
+ * schedule space in the form of an isl_multi_aff.
+ * The internal schedule space originally corresponds to that of the
+ * input schedule.  This may change during the code generation if
+ * if isl_ast_build_insert_dim is ever called.
+ * The external schedule space corresponds to the
+ * loops that have been generated.
+ *
+ * Currently, the only difference between the internal schedule domain
+ * and the external schedule domain is that some dimensions are projected
+ * out in the external schedule domain.  In particular, the dimensions
+ * for which no code has been generated yet and the dimensions that correspond
+ * to eliminated loops.
+ *
+ * We cache a copy of the schedule_map in build->schedule_map.
+ * The cache is cleared through isl_ast_build_reset_schedule_map
+ * whenever anything changes that might affect the result of this function.
+ */
+__isl_give isl_multi_aff *isl_ast_build_get_schedule_map_multi_aff(
+	__isl_keep isl_ast_build *build)
+{
+	isl_space *space;
+	isl_multi_aff *ma;
+
+	if (!build)
+		return NULL;
+	if (build->schedule_map)
+		return isl_multi_aff_copy(build->schedule_map);
+
+	space = isl_ast_build_get_space(build, 1);
+	space = isl_space_map_from_set(space);
+	ma = isl_multi_aff_identity(space);
+	if (isl_ast_build_need_schedule_map(build)) {
+		int i;
+		int dim = isl_set_dim(build->domain, isl_dim_set);
+		ma = isl_multi_aff_drop_dims(ma, isl_dim_out,
+					build->depth, dim - build->depth);
+		for (i = build->depth - 1; i >= 0; --i)
+			if (isl_ast_build_has_affine_value(build, i))
+				ma = isl_multi_aff_drop_dims(ma,
+							isl_dim_out, i, 1);
+	}
+
+	build->schedule_map = ma;
+	return isl_multi_aff_copy(build->schedule_map);
+}
+
+/* Return a mapping from the internal schedule space to the external
+ * schedule space in the form of an isl_map.
+ */
+__isl_give isl_map *isl_ast_build_get_schedule_map(
+	__isl_keep isl_ast_build *build)
+{
+	isl_multi_aff *ma;
+
+	ma = isl_ast_build_get_schedule_map_multi_aff(build);
+	return isl_map_from_multi_aff(ma);
+}
+
+/* Return the position of the dimension in build->domain for which
+ * an AST node is currently being generated.
+ */
+int isl_ast_build_get_depth(__isl_keep isl_ast_build *build)
+{
+	return build ? build->depth : -1;
+}
+
+/* Prepare for generating code for the next level.
+ * In particular, increase the depth and reset any information
+ * that is local to the current depth.
+ */
+__isl_give isl_ast_build *isl_ast_build_increase_depth(
+	__isl_take isl_ast_build *build)
+{
+	build = isl_ast_build_cow(build);
+	if (!build)
+		return NULL;
+	build->depth++;
+	isl_ast_build_reset_schedule_map(build);
+	build->value = isl_pw_aff_free(build->value);
+	return build;
+}
+
+void isl_ast_build_dump(__isl_keep isl_ast_build *build)
+{
+	if (!build)
+		return;
+
+	fprintf(stderr, "domain: ");
+	isl_set_dump(build->domain);
+	fprintf(stderr, "generated: ");
+	isl_set_dump(build->generated);
+	fprintf(stderr, "pending: ");
+	isl_set_dump(build->pending);
+	fprintf(stderr, "iterators: ");
+	isl_id_list_dump(build->iterators);
+	fprintf(stderr, "values: ");
+	isl_multi_aff_dump(build->values);
+	if (build->value) {
+		fprintf(stderr, "value: ");
+		isl_pw_aff_dump(build->value);
+	}
+	fprintf(stderr, "strides: ");
+	isl_vec_dump(build->strides);
+	fprintf(stderr, "offsets: ");
+	isl_multi_aff_dump(build->offsets);
+}
+
+/* Initialize "build" for AST construction in schedule space "space"
+ * in the case that build->domain is a parameter set.
+ *
+ * build->iterators is assumed to have been updated already.
+ */
+static __isl_give isl_ast_build *isl_ast_build_init(
+	__isl_take isl_ast_build *build, __isl_take isl_space *space)
+{
+	isl_set *set;
+
+	build = isl_ast_build_cow(build);
+	if (!build)
+		goto error;
+
+	set = isl_set_universe(isl_space_copy(space));
+	build->domain = isl_set_intersect_params(isl_set_copy(set),
+						    build->domain);
+	build->pending = isl_set_intersect_params(isl_set_copy(set),
+						    build->pending);
+	build->generated = isl_set_intersect_params(set, build->generated);
+
+	return isl_ast_build_init_derived(build, space);
+error:
+	isl_ast_build_free(build);
+	isl_space_free(space);
+	return NULL;
+}
+
+/* Assign "aff" to *user and return -1, effectively extracting
+ * the first (and presumably only) affine expression in the isl_pw_aff
+ * on which this function is used.
+ */
+static int extract_single_piece(__isl_take isl_set *set,
+	__isl_take isl_aff *aff, void *user)
+{
+	isl_aff **p = user;
+
+	*p = aff;
+	isl_set_free(set);
+
+	return -1;
+}
+
+/* Intersect "set" with the stride constraint of "build", if any.
+ */
+static __isl_give isl_set *intersect_stride_constraint(__isl_take isl_set *set,
+	__isl_keep isl_ast_build *build)
+{
+	isl_set *stride;
+
+	if (!build)
+		return isl_set_free(set);
+	if (!isl_ast_build_has_stride(build, build->depth))
+		return set;
+
+	stride = isl_ast_build_get_stride_constraint(build);
+	return isl_set_intersect(set, stride);
+}
+
+/* Check if the given bounds on the current dimension (together with
+ * the stride constraint, if any) imply that
+ * this current dimension attains only a single value (in terms of
+ * parameters and outer dimensions).
+ * If so, we record it in build->value.
+ * If, moreover, this value can be represented as a single affine expression,
+ * then we also update build->values, effectively marking the current
+ * dimension as "eliminated".
+ *
+ * When computing the gist of the fixed value that can be represented
+ * as a single affine expression, it is important to only take into
+ * account the domain constraints in the original AST build and
+ * not the domain of the affine expression itself.
+ * Otherwise, a [i/3] is changed into a i/3 because we know that i
+ * is a multiple of 3, but then we end up not expressing anywhere
+ * in the context that i is a multiple of 3.
+ */
+static __isl_give isl_ast_build *update_values(
+	__isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
+{
+	int sv;
+	isl_pw_multi_aff *pma;
+	isl_aff *aff = NULL;
+	isl_map *it_map;
+	isl_set *set;
+
+	set = isl_set_from_basic_set(bounds);
+	set = isl_set_intersect(set, isl_set_copy(build->domain));
+	set = intersect_stride_constraint(set, build);
+	it_map = isl_ast_build_map_to_iterator(build, set);
+
+	sv = isl_map_is_single_valued(it_map);
+	if (sv < 0)
+		build = isl_ast_build_free(build);
+	if (!build || !sv) {
+		isl_map_free(it_map);
+		return build;
+	}
+
+	pma = isl_pw_multi_aff_from_map(it_map);
+	build->value = isl_pw_multi_aff_get_pw_aff(pma, 0);
+	build->value = isl_ast_build_compute_gist_pw_aff(build, build->value);
+	build->value = isl_pw_aff_coalesce(build->value);
+	isl_pw_multi_aff_free(pma);
+
+	if (!build->value)
+		return isl_ast_build_free(build);
+
+	if (isl_pw_aff_n_piece(build->value) != 1)
+		return build;
+
+	isl_pw_aff_foreach_piece(build->value, &extract_single_piece, &aff);
+
+	build->values = isl_multi_aff_set_aff(build->values, build->depth, aff);
+	if (!build->values)
+		return isl_ast_build_free(build);
+	isl_ast_build_reset_schedule_map(build);
+	return build;
+}
+
+/* Update the AST build based on the given loop bounds for
+ * the current dimension and the stride information available in the build.
+ *
+ * We first make sure that the bounds do not refer to any iterators
+ * that have already been eliminated.
+ * Then, we check if the bounds imply that the current iterator
+ * has a fixed value.
+ * If they do and if this fixed value can be expressed as a single
+ * affine expression, we eliminate the iterators from the bounds.
+ * Note that we cannot simply plug in this single value using
+ * isl_basic_set_preimage_multi_aff as the single value may only
+ * be defined on a subset of the domain.  Plugging in the value
+ * would restrict the build domain to this subset, while this
+ * restriction may not be reflected in the generated code.
+ * Finally, we intersect build->domain with the updated bounds.
+ * We also add the stride constraint unless we have been able
+ * to find a fixed value expressed as a single affine expression.
+ *
+ * Note that the check for a fixed value in update_values requires
+ * us to intersect the bounds with the current build domain.
+ * When we intersect build->domain with the updated bounds in
+ * the final step, we make sure that these updated bounds have
+ * not been intersected with the old build->domain.
+ * Otherwise, we would indirectly intersect the build domain with itself,
+ * which can lead to inefficiencies, in particular if the build domain
+ * contains any unknown divs.
+ */
+__isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
+	__isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds)
+{
+	isl_set *set;
+
+	build = isl_ast_build_cow(build);
+	if (!build)
+		goto error;
+
+	bounds = isl_basic_set_preimage_multi_aff(bounds,
+					isl_multi_aff_copy(build->values));
+	build = update_values(build, isl_basic_set_copy(bounds));
+	if (!build)
+		goto error;
+	set = isl_set_from_basic_set(isl_basic_set_copy(bounds));
+	if (isl_ast_build_has_affine_value(build, build->depth)) {
+		set = isl_set_eliminate(set, isl_dim_set, build->depth, 1);
+		set = isl_set_compute_divs(set);
+		build->pending = isl_set_intersect(build->pending,
+							isl_set_copy(set));
+		build->domain = isl_set_intersect(build->domain, set);
+	} else {
+		isl_basic_set *generated, *pending;
+
+		pending = isl_basic_set_copy(bounds);
+		pending = isl_basic_set_drop_constraints_involving_dims(pending,
+					isl_dim_set, build->depth, 1);
+		build->pending = isl_set_intersect(build->pending,
+					isl_set_from_basic_set(pending));
+		generated = isl_basic_set_copy(bounds);
+		generated = isl_basic_set_drop_constraints_not_involving_dims(
+				    generated, isl_dim_set, build->depth, 1);
+		build->generated = isl_set_intersect(build->generated,
+					isl_set_from_basic_set(generated));
+		build->domain = isl_set_intersect(build->domain, set);
+		build = isl_ast_build_include_stride(build);
+		if (!build)
+			goto error;
+	}
+	isl_basic_set_free(bounds);
+
+	if (!build->domain || !build->pending || !build->generated)
+		return isl_ast_build_free(build);
+
+	return build;
+error:
+	isl_ast_build_free(build);
+	isl_basic_set_free(bounds);
+	return NULL;
+}
+
+/* Intersect build->domain with "set", where "set" is specified
+ * in terms of the internal schedule domain.
+ */
+static __isl_give isl_ast_build *isl_ast_build_restrict_internal(
+	__isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+	build = isl_ast_build_cow(build);
+	if (!build)
+		goto error;
+
+	set = isl_set_compute_divs(set);
+	build->domain = isl_set_intersect(build->domain, set);
+	build->domain = isl_set_coalesce(build->domain);
+
+	if (!build->domain)
+		return isl_ast_build_free(build);
+
+	return build;
+error:
+	isl_ast_build_free(build);
+	isl_set_free(set);
+	return NULL;
+}
+
+/* Intersect build->generated and build->domain with "set",
+ * where "set" is specified in terms of the internal schedule domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_restrict_generated(
+	__isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+	set = isl_set_compute_divs(set);
+	build = isl_ast_build_restrict_internal(build, isl_set_copy(set));
+	build = isl_ast_build_cow(build);
+	if (!build)
+		goto error;
+
+	build->generated = isl_set_intersect(build->generated, set);
+	build->generated = isl_set_coalesce(build->generated);
+
+	if (!build->generated)
+		return isl_ast_build_free(build);
+
+	return build;
+error:
+	isl_ast_build_free(build);
+	isl_set_free(set);
+	return NULL;
+}
+
+/* Replace the set of pending constraints by "guard", which is then
+ * no longer considered as pending.
+ * That is, add "guard" to the generated constraints and clear all pending
+ * constraints, making the domain equal to the generated constraints.
+ */
+__isl_give isl_ast_build *isl_ast_build_replace_pending_by_guard(
+	__isl_take isl_ast_build *build, __isl_take isl_set *guard)
+{
+	build = isl_ast_build_restrict_generated(build, guard);
+	build = isl_ast_build_cow(build);
+	if (!build)
+		return NULL;
+
+	isl_set_free(build->domain);
+	build->domain = isl_set_copy(build->generated);
+	isl_set_free(build->pending);
+	build->pending = isl_set_universe(isl_set_get_space(build->domain));
+
+	if (!build->pending)
+		return isl_ast_build_free(build);
+
+	return build;
+}
+
+/* Intersect build->pending and build->domain with "set",
+ * where "set" is specified in terms of the internal schedule domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_restrict_pending(
+	__isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+	set = isl_set_compute_divs(set);
+	build = isl_ast_build_restrict_internal(build, isl_set_copy(set));
+	build = isl_ast_build_cow(build);
+	if (!build)
+		goto error;
+
+	build->pending = isl_set_intersect(build->pending, set);
+	build->pending = isl_set_coalesce(build->pending);
+
+	if (!build->pending)
+		return isl_ast_build_free(build);
+
+	return build;
+error:
+	isl_ast_build_free(build);
+	isl_set_free(set);
+	return NULL;
+}
+
+/* Intersect build->domain with "set", where "set" is specified
+ * in terms of the external schedule domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_restrict(
+	__isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+	if (isl_set_is_params(set))
+		return isl_ast_build_restrict_generated(build, set);
+
+	if (isl_ast_build_need_schedule_map(build)) {
+		isl_multi_aff *ma;
+		ma = isl_ast_build_get_schedule_map_multi_aff(build);
+		set = isl_set_preimage_multi_aff(set, ma);
+	}
+	return isl_ast_build_restrict_generated(build, set);
+}
+
+/* Replace build->executed by "executed".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_executed(
+	__isl_take isl_ast_build *build, __isl_take isl_union_map *executed)
+{
+	build = isl_ast_build_cow(build);
+	if (!build)
+		goto error;
+
+	isl_union_map_free(build->executed);
+	build->executed = executed;
+
+	return build;
+error:
+	isl_ast_build_free(build);
+	isl_union_map_free(executed);
+	return NULL;
+}
+
+/* Return a copy of the current schedule domain.
+ */
+__isl_give isl_set *isl_ast_build_get_domain(__isl_keep isl_ast_build *build)
+{
+	return build ? isl_set_copy(build->domain) : NULL;
+}
+
+/* Return a copy of the set of pending constraints.
+ */
+__isl_give isl_set *isl_ast_build_get_pending(
+	__isl_keep isl_ast_build *build)
+{
+	return build ? isl_set_copy(build->pending) : NULL;
+}
+
+/* Return a copy of the set of generated constraints.
+ */
+__isl_give isl_set *isl_ast_build_get_generated(
+	__isl_keep isl_ast_build *build)
+{
+	return build ? isl_set_copy(build->generated) : NULL;
+}
+
+/* Return the number of variables of the given type
+ * in the (internal) schedule space.
+ */
+unsigned isl_ast_build_dim(__isl_keep isl_ast_build *build,
+	enum isl_dim_type type)
+{
+	if (!build)
+		return 0;
+	return isl_set_dim(build->domain, type);
+}
+
+/* Return the (schedule) space of "build".
+ *
+ * If "internal" is set, then this space is the space of the internal
+ * representation of the entire schedule, including those parts for
+ * which no code has been generated yet.
+ *
+ * If "internal" is not set, then this space is the external representation
+ * of the loops generated so far.
+ */
+__isl_give isl_space *isl_ast_build_get_space(__isl_keep isl_ast_build *build,
+	int internal)
+{
+	int i;
+	int dim;
+	isl_space *space;
+
+	if (!build)
+		return NULL;
+
+	space = isl_set_get_space(build->domain);
+	if (internal)
+		return space;
+
+	if (!isl_ast_build_need_schedule_map(build))
+		return space;
+
+	dim = isl_set_dim(build->domain, isl_dim_set);
+	space = isl_space_drop_dims(space, isl_dim_set,
+				    build->depth, dim - build->depth);
+	for (i = build->depth - 1; i >= 0; --i)
+		if (isl_ast_build_has_affine_value(build, i))
+			space = isl_space_drop_dims(space, isl_dim_set, i, 1);
+
+	return space;
+}
+
+/* Return the external representation of the schedule space of "build",
+ * i.e., a space with a dimension for each loop generated so far,
+ * with the names of the dimensions set to the loop iterators.
+ */
+__isl_give isl_space *isl_ast_build_get_schedule_space(
+	__isl_keep isl_ast_build *build)
+{
+	isl_space *space;
+	int i, skip;
+
+	if (!build)
+		return NULL;
+
+	space = isl_ast_build_get_space(build, 0);
+
+	skip = 0;
+	for (i = 0; i < build->depth; ++i) {
+		isl_id *id;
+
+		if (isl_ast_build_has_affine_value(build, i)) {
+			skip++;
+			continue;
+		}
+
+		id = isl_ast_build_get_iterator_id(build, i);
+		space = isl_space_set_dim_id(space, isl_dim_set, i - skip, id);
+	}
+
+	return space;
+}
+
+/* Return the current schedule, as stored in build->executed, in terms
+ * of the external schedule domain.
+ */
+__isl_give isl_union_map *isl_ast_build_get_schedule(
+	__isl_keep isl_ast_build *build)
+{
+	isl_union_map *executed;
+	isl_union_map *schedule;
+
+	if (!build)
+		return NULL;
+
+	executed = isl_union_map_copy(build->executed);
+	if (isl_ast_build_need_schedule_map(build)) {
+		isl_map *proj = isl_ast_build_get_schedule_map(build);
+		executed = isl_union_map_apply_domain(executed,
+					isl_union_map_from_map(proj));
+	}
+	schedule = isl_union_map_reverse(executed);
+
+	return schedule;
+}
+
+/* Return the iterator attached to the internal schedule dimension "pos".
+ */
+__isl_give isl_id *isl_ast_build_get_iterator_id(
+	__isl_keep isl_ast_build *build, int pos)
+{
+	if (!build)
+		return NULL;
+
+	return isl_id_list_get_id(build->iterators, pos);
+}
+
+/* Set the stride and offset of the current dimension to the given
+ * value and expression.
+ *
+ * If we had already found a stride before, then the two strides
+ * are combined into a single stride.
+ *
+ * In particular, if the new stride information is of the form
+ *
+ *	i = f + s (...)
+ *
+ * and the old stride information is of the form
+ *
+ *	i = f2 + s2 (...)
+ *
+ * then we compute the extended gcd of s and s2
+ *
+ *	a s + b s2 = g,
+ *
+ * with g = gcd(s,s2), multiply the first equation with t1 = b s2/g
+ * and the second with t2 = a s1/g.
+ * This results in
+ *
+ *	i = (b s2 + a s1)/g i = t1 f + t2 f2 + (s s2)/g (...)
+ *
+ * so that t1 f + t2 f2 is the combined offset and (s s2)/g = lcm(s,s2)
+ * is the combined stride.
+ */
+static __isl_give isl_ast_build *set_stride(__isl_take isl_ast_build *build,
+	__isl_take isl_val *stride, __isl_take isl_aff *offset)
+{
+	int pos;
+
+	build = isl_ast_build_cow(build);
+	if (!build || !stride || !offset)
+		goto error;
+
+	pos = build->depth;
+
+	if (isl_ast_build_has_stride(build, pos)) {
+		isl_val *stride2, *a, *b, *g;
+		isl_aff *offset2;
+
+		stride2 = isl_vec_get_element_val(build->strides, pos);
+		g = isl_val_gcdext(isl_val_copy(stride), isl_val_copy(stride2),
+					&a, &b);
+		a = isl_val_mul(a, isl_val_copy(stride));
+		a = isl_val_div(a, isl_val_copy(g));
+		stride2 = isl_val_div(stride2, g);
+		b = isl_val_mul(b, isl_val_copy(stride2));
+		stride = isl_val_mul(stride, stride2);
+
+		offset2 = isl_multi_aff_get_aff(build->offsets, pos);
+		offset2 = isl_aff_scale_val(offset2, a);
+		offset = isl_aff_scale_val(offset, b);
+		offset = isl_aff_add(offset, offset2);
+	}
+
+	build->strides = isl_vec_set_element_val(build->strides, pos, stride);
+	build->offsets = isl_multi_aff_set_aff(build->offsets, pos, offset);
+	if (!build->strides || !build->offsets)
+		return isl_ast_build_free(build);
+
+	return build;
+error:
+	isl_val_free(stride);
+	isl_aff_free(offset);
+	return isl_ast_build_free(build);
+}
+
+/* Return a set expressing the stride constraint at the current depth.
+ *
+ * In particular, if the current iterator (i) is known to attain values
+ *
+ *	f + s a
+ *
+ * where f is the offset and s is the stride, then the returned set
+ * expresses the constraint
+ *
+ *	(f - i) mod s = 0
+ */
+__isl_give isl_set *isl_ast_build_get_stride_constraint(
+	__isl_keep isl_ast_build *build)
+{
+	isl_aff *aff;
+	isl_set *set;
+	isl_val *stride;
+	int pos;
+
+	if (!build)
+		return NULL;
+
+	pos = build->depth;
+
+	if (!isl_ast_build_has_stride(build, pos))
+		return isl_set_universe(isl_ast_build_get_space(build, 1));
+
+	stride = isl_ast_build_get_stride(build, pos);
+	aff = isl_ast_build_get_offset(build, pos);
+	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, pos, -1);
+	aff = isl_aff_mod_val(aff, stride);
+	set = isl_set_from_basic_set(isl_aff_zero_basic_set(aff));
+
+	return set;
+}
+
+/* Return the expansion implied by the stride and offset at the current
+ * depth.
+ *
+ * That is, return the mapping
+ *
+ *	[i_0, ..., i_{d-1}, i_d, i_{d+1}, ...]
+ *		-> [i_0, ..., i_{d-1}, s * i_d + offset(i),  i_{d+1}, ...]
+ *
+ * where s is the stride at the current depth d and offset(i) is
+ * the corresponding offset.
+ */
+__isl_give isl_multi_aff *isl_ast_build_get_stride_expansion(
+	__isl_keep isl_ast_build *build)
+{
+	isl_space *space;
+	isl_multi_aff *ma;
+	int pos;
+	isl_aff *aff, *offset;
+	isl_val *stride;
+
+	if (!build)
+		return NULL;
+
+	pos = isl_ast_build_get_depth(build);
+	space = isl_ast_build_get_space(build, 1);
+	space = isl_space_map_from_set(space);
+	ma = isl_multi_aff_identity(space);
+
+	if (!isl_ast_build_has_stride(build, pos))
+		return ma;
+
+	offset = isl_ast_build_get_offset(build, pos);
+	stride = isl_ast_build_get_stride(build, pos);
+	aff = isl_multi_aff_get_aff(ma, pos);
+	aff = isl_aff_scale_val(aff, stride);
+	aff = isl_aff_add(aff, offset);
+	ma = isl_multi_aff_set_aff(ma, pos, aff);
+
+	return ma;
+}
+
+/* Add constraints corresponding to any previously detected
+ * stride on the current dimension to build->domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_include_stride(
+	__isl_take isl_ast_build *build)
+{
+	isl_set *set;
+
+	if (!build)
+		return NULL;
+	if (!isl_ast_build_has_stride(build, build->depth))
+		return build;
+	build = isl_ast_build_cow(build);
+	if (!build)
+		return NULL;
+
+	set = isl_ast_build_get_stride_constraint(build);
+
+	build->domain = isl_set_intersect(build->domain, isl_set_copy(set));
+	build->generated = isl_set_intersect(build->generated, set);
+	if (!build->domain || !build->generated)
+		return isl_ast_build_free(build);
+
+	return build;
+}
+
+/* Information used inside detect_stride.
+ *
+ * "build" may be updated by detect_stride to include stride information.
+ * "pos" is equal to build->depth.
+ */
+struct isl_detect_stride_data {
+	isl_ast_build *build;
+	int pos;
+};
+
+/* Check if constraint "c" imposes any stride on dimension data->pos
+ * and, if so, update the stride information in data->build.
+ *
+ * In order to impose a stride on the dimension, "c" needs to be an equality
+ * and it needs to involve the dimension.  Note that "c" may also be
+ * a div constraint and thus an inequality that we cannot use.
+ *
+ * Let c be of the form
+ *
+ *	h(p) + g * v * i + g * stride * f(alpha) = 0
+ *
+ * with h(p) an expression in terms of the parameters and outer dimensions
+ * and f(alpha) an expression in terms of the existentially quantified
+ * variables.  Note that the inner dimensions have been eliminated so
+ * they do not appear in "c".
+ *
+ * If "stride" is not zero and not one, then it represents a non-trivial stride
+ * on "i".  We compute a and b such that
+ *
+ *	a v + b stride = 1
+ *
+ * We have
+ *
+ *	g v i = -h(p) + g stride f(alpha)
+ *
+ *	a g v i = -a h(p) + g stride f(alpha)
+ *
+ *	a g v i + b g stride i = -a h(p) + g stride * (...)
+ *
+ *	g i = -a h(p) + g stride * (...)
+ *
+ *	i = -a h(p)/g + stride * (...)
+ *
+ * The expression "-a h(p)/g" can therefore be used as offset.
+ */
+static int detect_stride(__isl_take isl_constraint *c, void *user)
+{
+	struct isl_detect_stride_data *data = user;
+	int i, n_div;
+	isl_ctx *ctx;
+	isl_val *v, *stride, *m;
+
+	if (!isl_constraint_is_equality(c) ||
+	    !isl_constraint_involves_dims(c, isl_dim_set, data->pos, 1)) {
+		isl_constraint_free(c);
+		return 0;
+	}
+
+	ctx = isl_constraint_get_ctx(c);
+	stride = isl_val_zero(ctx);
+	n_div = isl_constraint_dim(c, isl_dim_div);
+	for (i = 0; i < n_div; ++i) {
+		v = isl_constraint_get_coefficient_val(c, isl_dim_div, i);
+		stride = isl_val_gcd(stride, v);
+	}
+
+	v = isl_constraint_get_coefficient_val(c, isl_dim_set, data->pos);
+	m = isl_val_gcd(isl_val_copy(stride), isl_val_copy(v));
+	stride = isl_val_div(stride, isl_val_copy(m));
+	v = isl_val_div(v, isl_val_copy(m));
+
+	if (!isl_val_is_zero(stride) && !isl_val_is_one(stride)) {
+		isl_aff *aff;
+		isl_val *gcd, *a, *b;
+
+		gcd = isl_val_gcdext(v, isl_val_copy(stride), &a, &b);
+		isl_val_free(gcd);
+		isl_val_free(b);
+
+		aff = isl_constraint_get_aff(c);
+		for (i = 0; i < n_div; ++i)
+			aff = isl_aff_set_coefficient_si(aff,
+							 isl_dim_div, i, 0);
+		aff = isl_aff_set_coefficient_si(aff, isl_dim_in, data->pos, 0);
+		a = isl_val_neg(a);
+		aff = isl_aff_scale_val(aff, a);
+		aff = isl_aff_scale_down_val(aff, m);
+		data->build = set_stride(data->build, stride, aff);
+	} else {
+		isl_val_free(stride);
+		isl_val_free(m);
+		isl_val_free(v);
+	}
+
+	isl_constraint_free(c);
+	return 0;
+}
+
+/* Check if the constraints in "set" imply any stride on the current
+ * dimension and, if so, record the stride information in "build"
+ * and return the updated "build".
+ *
+ * We compute the affine hull and then check if any of the constraints
+ * in the hull imposes any stride on the current dimension.
+ *
+ * We assume that inner dimensions have been eliminated from "set"
+ * by the caller.  This is needed because the common stride
+ * may be imposed by different inner dimensions on different parts of
+ * the domain.
+ */
+__isl_give isl_ast_build *isl_ast_build_detect_strides(
+	__isl_take isl_ast_build *build, __isl_take isl_set *set)
+{
+	isl_basic_set *hull;
+	struct isl_detect_stride_data data;
+
+	if (!build)
+		goto error;
+
+	data.build = build;
+	data.pos = isl_ast_build_get_depth(build);
+	hull = isl_set_affine_hull(set);
+
+	if (isl_basic_set_foreach_constraint(hull, &detect_stride, &data) < 0)
+		data.build = isl_ast_build_free(data.build);
+
+	isl_basic_set_free(hull);
+	return data.build;
+error:
+	isl_set_free(set);
+	return NULL;
+}
+
+struct isl_ast_build_involves_data {
+	int depth;
+	int involves;
+};
+
+/* Check if "map" involves the input dimension data->depth.
+ */
+static int involves_depth(__isl_take isl_map *map, void *user)
+{
+	struct isl_ast_build_involves_data *data = user;
+
+	data->involves = isl_map_involves_dims(map, isl_dim_in, data->depth, 1);
+	isl_map_free(map);
+
+	if (data->involves < 0 || data->involves)
+		return -1;
+	return 0;
+}
+
+/* Do any options depend on the value of the dimension at the current depth?
+ */
+int isl_ast_build_options_involve_depth(__isl_keep isl_ast_build *build)
+{
+	struct isl_ast_build_involves_data data;
+
+	if (!build)
+		return -1;
+
+	data.depth = build->depth;
+	data.involves = 0;
+
+	if (isl_union_map_foreach_map(build->options,
+					&involves_depth, &data) < 0) {
+		if (data.involves < 0 || !data.involves)
+			return -1;
+	}
+
+	return data.involves;
+}
+
+/* Construct the map
+ *
+ *	{ [i] -> [i] : i < pos; [i] -> [i + 1] : i >= pos }
+ *
+ * with "space" the parameter space of the constructed map.
+ */
+static __isl_give isl_map *construct_insertion_map(__isl_take isl_space *space,
+	int pos)
+{
+	isl_constraint *c;
+	isl_basic_map *bmap1, *bmap2;
+
+	space = isl_space_set_from_params(space);
+	space = isl_space_add_dims(space, isl_dim_set, 1);
+	space = isl_space_map_from_set(space);
+	c = isl_equality_alloc(isl_local_space_from_space(space));
+	c = isl_constraint_set_coefficient_si(c, isl_dim_in, 0, 1);
+	c = isl_constraint_set_coefficient_si(c, isl_dim_out, 0, -1);
+	bmap1 = isl_basic_map_from_constraint(isl_constraint_copy(c));
+	c = isl_constraint_set_constant_si(c, 1);
+	bmap2 = isl_basic_map_from_constraint(c);
+
+	bmap1 = isl_basic_map_upper_bound_si(bmap1, isl_dim_in, 0, pos - 1);
+	bmap2 = isl_basic_map_lower_bound_si(bmap2, isl_dim_in, 0, pos);
+
+	return isl_basic_map_union(bmap1, bmap2);
+}
+
+static const char *option_str[] = {
+	[atomic] = "atomic",
+	[unroll] = "unroll",
+	[separate] = "separate"
+};
+
+/* Update the "options" to reflect the insertion of a dimension
+ * at position "pos" in the schedule domain space.
+ * "space" is the original domain space before the insertion and
+ * may be named and/or structured.
+ *
+ * The (relevant) input options all have "space" as domain, which
+ * has to be mapped to the extended space.
+ * The values of the ranges also refer to the schedule domain positions
+ * and they therefore also need to be adjusted.  In particular, values
+ * smaller than pos do not need to change, while values greater than or
+ * equal to pos need to be incremented.
+ * That is, we need to apply the following map.
+ *
+ *	{ atomic[i] -> atomic[i] : i < pos; [i] -> [i + 1] : i >= pos;
+ *	  unroll[i] -> unroll[i] : i < pos; [i] -> [i + 1] : i >= pos;
+ *	  separate[i] -> separate[i] : i < pos; [i] -> [i + 1] : i >= pos;
+ *	  separation_class[[i] -> [c]]
+ *		-> separation_class[[i] -> [c]] : i < pos;
+ *	  separation_class[[i] -> [c]]
+ *		-> separation_class[[i + 1] -> [c]] : i >= pos }
+ */
+static __isl_give isl_union_map *options_insert_dim(
+	__isl_take isl_union_map *options, __isl_take isl_space *space, int pos)
+{
+	isl_map *map;
+	isl_union_map *insertion;
+	enum isl_ast_build_domain_type type;
+	const char *name = "separation_class";
+
+	space = isl_space_map_from_set(space);
+	map = isl_map_identity(space);
+	map = isl_map_insert_dims(map, isl_dim_out, pos, 1);
+	options = isl_union_map_apply_domain(options,
+						isl_union_map_from_map(map));
+
+	if (!options)
+		return NULL;
+
+	map = construct_insertion_map(isl_union_map_get_space(options), pos);
+
+	insertion = isl_union_map_empty(isl_union_map_get_space(options));
+
+	for (type = atomic; type <= separate; ++type) {
+		isl_map *map_type = isl_map_copy(map);
+		const char *name = option_str[type];
+		map_type = isl_map_set_tuple_name(map_type, isl_dim_in, name);
+		map_type = isl_map_set_tuple_name(map_type, isl_dim_out, name);
+		insertion = isl_union_map_add_map(insertion, map_type);
+	}
+
+	map = isl_map_product(map, isl_map_identity(isl_map_get_space(map)));
+	map = isl_map_set_tuple_name(map, isl_dim_in, name);
+	map = isl_map_set_tuple_name(map, isl_dim_out, name);
+	insertion = isl_union_map_add_map(insertion, map);
+
+	options = isl_union_map_apply_range(options, insertion);
+
+	return options;
+}
+
+/* Insert a single dimension in the schedule domain at position "pos".
+ * The new dimension is given an isl_id with the empty string as name.
+ *
+ * The main difficulty is updating build->options to reflect the
+ * extra dimension.  This is handled in options_insert_dim.
+ *
+ * Note that because of the dimension manipulations, the resulting
+ * schedule domain space will always be unnamed and unstructured.
+ * However, the original schedule domain space may be named and/or
+ * structured, so we have to take this possibility into account
+ * while performing the transformations.
+ */
+__isl_give isl_ast_build *isl_ast_build_insert_dim(
+	__isl_take isl_ast_build *build, int pos)
+{
+	isl_ctx *ctx;
+	isl_space *space, *ma_space;
+	isl_id *id;
+	isl_multi_aff *ma;
+
+	build = isl_ast_build_cow(build);
+	if (!build)
+		return NULL;
+
+	ctx = isl_ast_build_get_ctx(build);
+	id = isl_id_alloc(ctx, "", NULL);
+	space = isl_ast_build_get_space(build, 1);
+	build->iterators = isl_id_list_insert(build->iterators, pos, id);
+	build->domain = isl_set_insert_dims(build->domain,
+						isl_dim_set, pos, 1);
+	build->generated = isl_set_insert_dims(build->generated,
+						isl_dim_set, pos, 1);
+	build->pending = isl_set_insert_dims(build->pending,
+						isl_dim_set, pos, 1);
+	build->strides = isl_vec_insert_els(build->strides, pos, 1);
+	build->strides = isl_vec_set_element_si(build->strides, pos, 1);
+	ma_space = isl_space_params(isl_multi_aff_get_space(build->offsets));
+	ma_space = isl_space_set_from_params(ma_space);
+	ma_space = isl_space_add_dims(ma_space, isl_dim_set, 1);
+	ma_space = isl_space_map_from_set(ma_space);
+	ma = isl_multi_aff_zero(isl_space_copy(ma_space));
+	build->offsets = isl_multi_aff_splice(build->offsets, pos, pos, ma);
+	ma = isl_multi_aff_identity(ma_space);
+	build->values = isl_multi_aff_splice(build->values, pos, pos, ma);
+	build->options = options_insert_dim(build->options, space, pos);
+
+	if (!build->iterators || !build->domain || !build->generated ||
+	    !build->pending || !build->values ||
+	    !build->strides || !build->offsets || !build->options)
+		return isl_ast_build_free(build);
+
+	return build;
+}
+
+/* Scale down the current dimension by a factor of "m".
+ * "umap" is an isl_union_map that implements the scaling down.
+ * That is, it is of the form
+ *
+ *	{ [.... i ....] -> [.... i' ....] : i = m i' }
+ *
+ * This function is called right after the strides have been
+ * detected, but before any constraints on the current dimension
+ * have been included in build->domain.
+ * We therefore only need to update stride, offset and the options.
+ */
+__isl_give isl_ast_build *isl_ast_build_scale_down(
+	__isl_take isl_ast_build *build, __isl_take isl_val *m,
+	__isl_take isl_union_map *umap)
+{
+	isl_aff *aff;
+	isl_val *v;
+	int depth;
+
+	build = isl_ast_build_cow(build);
+	if (!build || !umap || !m)
+		goto error;
+
+	depth = build->depth;
+
+	v = isl_vec_get_element_val(build->strides, depth);
+	v = isl_val_div(v, isl_val_copy(m));
+	build->strides = isl_vec_set_element_val(build->strides, depth, v);
+
+	aff = isl_multi_aff_get_aff(build->offsets, depth);
+	aff = isl_aff_scale_down_val(aff, m);
+	build->offsets = isl_multi_aff_set_aff(build->offsets, depth, aff);
+	build->options = isl_union_map_apply_domain(build->options, umap);
+	if (!build->strides || !build->offsets || !build->options)
+		return isl_ast_build_free(build);
+
+	return build;
+error:
+	isl_val_free(m);
+	isl_union_map_free(umap);
+	return isl_ast_build_free(build);
+}
+
+/* Return a list of "n" isl_ids called "c%d", with "%d" starting at "first".
+ * If an isl_id with such a name already appears among the parameters
+ * in build->domain, then adjust the name to "c%d_%d".
+ */
+static __isl_give isl_id_list *generate_names(isl_ctx *ctx, int n, int first,
+	__isl_keep isl_ast_build *build)
+{
+	int i;
+	isl_id_list *names;
+
+	names = isl_id_list_alloc(ctx, n);
+	for (i = 0; i < n; ++i) {
+		isl_id *id;
+
+		id = generate_name(ctx, first + i, build);
+		names = isl_id_list_add(names, id);
+	}
+
+	return names;
+}
+
+/* Embed "options" into the given isl_ast_build space.
+ *
+ * This function is called from within a nested call to
+ * isl_ast_build_ast_from_schedule.
+ * "options" refers to the additional schedule,
+ * while space refers to both the space of the outer isl_ast_build and
+ * that of the additional schedule.
+ * Specifically, space is of the form
+ *
+ *	[I -> S]
+ *
+ * while options lives in the space(s)
+ *
+ *	S -> *
+ *
+ * We compute
+ *
+ *	[I -> S] -> S
+ *
+ * and compose this with options, to obtain the new options
+ * living in the space(s)
+ *
+ *	[I -> S] -> *
+ */
+static __isl_give isl_union_map *embed_options(
+	__isl_take isl_union_map *options, __isl_take isl_space *space)
+{
+	isl_map *map;
+
+	map = isl_map_universe(isl_space_unwrap(space));
+	map = isl_map_range_map(map);
+
+	options = isl_union_map_apply_range(
+				isl_union_map_from_map(map), options);
+
+	return options;
+}
+
+/* Update "build" for use in a (possibly nested) code generation.  That is,
+ * extend "build" from an AST build on some domain O to an AST build
+ * on domain [O -> S], with S corresponding to "space".
+ * If the original domain is a parameter domain, then the new domain is
+ * simply S.
+ * "iterators" is a list of iterators for S, but the number of elements
+ * may be smaller or greater than the number of set dimensions of S.
+ * If "keep_iterators" is set, then any extra ids in build->iterators
+ * are reused for S.  Otherwise, these extra ids are dropped.
+ *
+ * We first update build->outer_pos to the current depth.
+ * This depth is zero in case this is the outermost code generation.
+ *
+ * We then add additional ids such that the number of iterators is at least
+ * equal to the dimension of the new build domain.
+ *
+ * If the original domain is parametric, then we are constructing
+ * an isl_ast_build for the outer code generation and we pass control
+ * to isl_ast_build_init.
+ *
+ * Otherwise, we adjust the fields of "build" to include "space".
+ */
+__isl_give isl_ast_build *isl_ast_build_product(
+	__isl_take isl_ast_build *build, __isl_take isl_space *space)
+{
+	isl_ctx *ctx;
+	isl_vec *strides;
+	isl_set *set;
+	isl_multi_aff *embedding;
+	int dim, n_it;
+
+	build = isl_ast_build_cow(build);
+	if (!build)
+		goto error;
+
+	build->outer_pos = build->depth;
+
+	ctx = isl_ast_build_get_ctx(build);
+	dim = isl_set_dim(build->domain, isl_dim_set);
+	dim += isl_space_dim(space, isl_dim_set);
+	n_it = isl_id_list_n_id(build->iterators);
+	if (n_it < dim) {
+		isl_id_list *l;
+		l = generate_names(ctx, dim - n_it, n_it, build);
+		build->iterators = isl_id_list_concat(build->iterators, l);
+	}
+
+	if (isl_set_is_params(build->domain))
+		return isl_ast_build_init(build, space);
+
+	set = isl_set_universe(isl_space_copy(space));
+	build->domain = isl_set_product(build->domain, isl_set_copy(set));
+	build->pending = isl_set_product(build->pending, isl_set_copy(set));
+	build->generated = isl_set_product(build->generated, set);
+
+	strides = isl_vec_alloc(ctx, isl_space_dim(space, isl_dim_set));
+	strides = isl_vec_set_si(strides, 1);
+	build->strides = isl_vec_concat(build->strides, strides);
+
+	space = isl_space_map_from_set(space);
+	build->offsets = isl_multi_aff_align_params(build->offsets,
+						    isl_space_copy(space));
+	build->offsets = isl_multi_aff_product(build->offsets,
+				isl_multi_aff_zero(isl_space_copy(space)));
+	build->values = isl_multi_aff_align_params(build->values,
+						    isl_space_copy(space));
+	embedding = isl_multi_aff_identity(space);
+	build->values = isl_multi_aff_product(build->values, embedding);
+
+	space = isl_ast_build_get_space(build, 1);
+	build->options = embed_options(build->options, space);
+
+	if (!build->iterators || !build->domain || !build->generated ||
+	    !build->pending || !build->values ||
+	    !build->strides || !build->offsets || !build->options)
+		return isl_ast_build_free(build);
+
+	return build;
+error:
+	isl_ast_build_free(build);
+	isl_space_free(space);
+	return NULL;
+}
+
+/* Does "aff" only attain non-negative values over build->domain?
+ * That is, does it not attain any negative values?
+ */
+int isl_ast_build_aff_is_nonneg(__isl_keep isl_ast_build *build,
+	__isl_keep isl_aff *aff)
+{
+	isl_set *test;
+	int empty;
+
+	if (!build)
+		return -1;
+
+	aff = isl_aff_copy(aff);
+	test = isl_set_from_basic_set(isl_aff_neg_basic_set(aff));
+	test = isl_set_intersect(test, isl_set_copy(build->domain));
+	empty = isl_set_is_empty(test);
+	isl_set_free(test);
+
+	return empty;
+}
+
+/* Does the dimension at (internal) position "pos" have a non-trivial stride?
+ */
+int isl_ast_build_has_stride(__isl_keep isl_ast_build *build, int pos)
+{
+	isl_val *v;
+	int has_stride;
+
+	if (!build)
+		return -1;
+
+	v = isl_vec_get_element_val(build->strides, pos);
+	if (!v)
+		return -1;
+	has_stride = !isl_val_is_one(v);
+	isl_val_free(v);
+
+	return has_stride;
+}
+
+/* Given that the dimension at position "pos" takes on values
+ *
+ *	f + s a
+ *
+ * with a an integer, return s through *stride.
+ */
+__isl_give isl_val *isl_ast_build_get_stride(__isl_keep isl_ast_build *build,
+	int pos)
+{
+	if (!build)
+		return NULL;
+
+	return isl_vec_get_element_val(build->strides, pos);
+}
+
+/* Given that the dimension at position "pos" takes on values
+ *
+ *	f + s a
+ *
+ * with a an integer, return f.
+ */
+__isl_give isl_aff *isl_ast_build_get_offset(
+	__isl_keep isl_ast_build *build, int pos)
+{
+	if (!build)
+		return NULL;
+
+	return isl_multi_aff_get_aff(build->offsets, pos);
+}
+
+/* Is the dimension at position "pos" known to attain only a single
+ * 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
+ * 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.
+ */
+int isl_ast_build_has_affine_value(__isl_keep isl_ast_build *build,
+	int pos)
+{
+	isl_aff *aff;
+	int involves;
+
+	if (!build)
+		return -1;
+
+	aff = isl_multi_aff_get_aff(build->values, pos);
+	involves = isl_aff_involves_dims(aff, isl_dim_in, pos, 1);
+	isl_aff_free(aff);
+
+	if (involves < 0)
+		return -1;
+
+	return !involves;
+}
+
+/* Plug in the known values (fixed affine expressions in terms of
+ * parameters and outer loop iterators) of all loop iterators
+ * in the domain of "umap".
+ *
+ * We simply precompose "umap" with build->values.
+ */
+__isl_give isl_union_map *isl_ast_build_substitute_values_union_map_domain(
+	__isl_keep isl_ast_build *build, __isl_take isl_union_map *umap)
+{
+	isl_multi_aff *values;
+
+	if (!build)
+		return isl_union_map_free(umap);
+
+	values = isl_multi_aff_copy(build->values);
+	umap = isl_union_map_preimage_domain_multi_aff(umap, values);
+
+	return umap;
+}
+
+/* Is the current dimension known to attain only a single value?
+ */
+int isl_ast_build_has_value(__isl_keep isl_ast_build *build)
+{
+	if (!build)
+		return -1;
+
+	return build->value != NULL;
+}
+
+/* Simplify the basic set "bset" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * "bset" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_basic_set *isl_ast_build_compute_gist_basic_set(
+	__isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
+{
+	if (!build)
+		goto error;
+
+	bset = isl_basic_set_preimage_multi_aff(bset,
+					isl_multi_aff_copy(build->values));
+	bset = isl_basic_set_gist(bset,
+			isl_set_simple_hull(isl_set_copy(build->domain)));
+
+	return bset;
+error:
+	isl_basic_set_free(bset);
+	return NULL;
+}
+
+/* Simplify the set "set" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * "set" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_set *isl_ast_build_compute_gist(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+	if (!build)
+		goto error;
+
+	set = isl_set_preimage_multi_aff(set,
+					isl_multi_aff_copy(build->values));
+	set = isl_set_gist(set, isl_set_copy(build->domain));
+
+	return set;
+error:
+	isl_set_free(set);
+	return NULL;
+}
+
+/* Include information about what we know about the iterators of
+ * already generated loops to "set".
+ *
+ * We currently only plug in the known affine values of outer loop
+ * iterators.
+ * In principle we could also introduce equalities or even other
+ * constraints implied by the intersection of "set" and build->domain.
+ */
+__isl_give isl_set *isl_ast_build_specialize(__isl_keep isl_ast_build *build,
+	__isl_take isl_set *set)
+{
+	if (!build)
+		return isl_set_free(set);
+
+	return isl_set_preimage_multi_aff(set,
+					isl_multi_aff_copy(build->values));
+}
+
+/* Simplify the map "map" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * The domain of "map" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_map *isl_ast_build_compute_gist_map_domain(
+	__isl_keep isl_ast_build *build, __isl_take isl_map *map)
+{
+	if (!build)
+		goto error;
+
+	map = isl_map_gist_domain(map, isl_set_copy(build->domain));
+
+	return map;
+error:
+	isl_map_free(map);
+	return NULL;
+}
+
+/* Simplify the affine expression "aff" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * The domain of "aff" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_aff *isl_ast_build_compute_gist_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_aff *aff)
+{
+	if (!build)
+		goto error;
+
+	aff = isl_aff_gist(aff, isl_set_copy(build->domain));
+
+	return aff;
+error:
+	isl_aff_free(aff);
+	return NULL;
+}
+
+/* Simplify the piecewise affine expression "aff" based on what we know about
+ * the iterators of already generated loops.
+ *
+ * The domain of "pa" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_pw_aff *isl_ast_build_compute_gist_pw_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
+{
+	if (!build)
+		goto error;
+
+	if (!isl_set_is_params(build->domain))
+		pa = isl_pw_aff_pullback_multi_aff(pa,
+					isl_multi_aff_copy(build->values));
+	pa = isl_pw_aff_gist(pa, isl_set_copy(build->domain));
+
+	return pa;
+error:
+	isl_pw_aff_free(pa);
+	return NULL;
+}
+
+/* Simplify the piecewise multi-affine expression "aff" based on what
+ * we know about the iterators of already generated loops.
+ *
+ * The domain of "pma" is assumed to live in the (internal) schedule domain.
+ */
+__isl_give isl_pw_multi_aff *isl_ast_build_compute_gist_pw_multi_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
+{
+	if (!build)
+		goto error;
+
+	pma = isl_pw_multi_aff_pullback_multi_aff(pma,
+					isl_multi_aff_copy(build->values));
+	pma = isl_pw_multi_aff_gist(pma, isl_set_copy(build->domain));
+
+	return pma;
+error:
+	isl_pw_multi_aff_free(pma);
+	return NULL;
+}
+
+/* Extract the schedule domain of the given type from build->options
+ * at the current depth.
+ *
+ * In particular, find the subset of build->options that is of
+ * the following form
+ *
+ *	schedule_domain -> type[depth]
+ *
+ * and return the corresponding domain, after eliminating inner dimensions
+ * and divs that depend on the current dimension.
+ *
+ * Note that the domain of build->options has been reformulated
+ * in terms of the internal build space in embed_options,
+ * but the position is still that within the current code generation.
+ */
+__isl_give isl_set *isl_ast_build_get_option_domain(
+	__isl_keep isl_ast_build *build,
+	enum isl_ast_build_domain_type type)
+{
+	const char *name;
+	isl_space *space;
+	isl_map *option;
+	isl_set *domain;
+	int local_pos;
+
+	if (!build)
+		return NULL;
+
+	name = option_str[type];
+	local_pos = build->depth - build->outer_pos;
+
+	space = isl_ast_build_get_space(build, 1);
+	space = isl_space_from_domain(space);
+	space = isl_space_add_dims(space, isl_dim_out, 1);
+	space = isl_space_set_tuple_name(space, isl_dim_out, name);
+
+	option = isl_union_map_extract_map(build->options, space);
+	option = isl_map_fix_si(option, isl_dim_out, 0, local_pos);
+
+	domain = isl_map_domain(option);
+	domain = isl_ast_build_eliminate(build, domain);
+
+	return domain;
+}
+
+/* Extract the separation class mapping at the current depth.
+ *
+ * In particular, find and return the subset of build->options that is of
+ * the following form
+ *
+ *	schedule_domain -> separation_class[[depth] -> [class]]
+ *
+ * The caller is expected to eliminate inner dimensions from the domain.
+ *
+ * Note that the domain of build->options has been reformulated
+ * in terms of the internal build space in embed_options,
+ * but the position is still that within the current code generation.
+ */
+__isl_give isl_map *isl_ast_build_get_separation_class(
+	__isl_keep isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	isl_space *space_sep, *space;
+	isl_map *res;
+	int local_pos;
+
+	if (!build)
+		return NULL;
+
+	local_pos = build->depth - build->outer_pos;
+	ctx = isl_ast_build_get_ctx(build);
+	space_sep = isl_space_alloc(ctx, 0, 1, 1);
+	space_sep = isl_space_wrap(space_sep);
+	space_sep = isl_space_set_tuple_name(space_sep, isl_dim_set,
+						"separation_class");
+	space = isl_ast_build_get_space(build, 1);
+	space_sep = isl_space_align_params(space_sep, isl_space_copy(space));
+	space = isl_space_map_from_domain_and_range(space, space_sep);
+
+	res = isl_union_map_extract_map(build->options, space);
+	res = isl_map_fix_si(res, isl_dim_out, 0, local_pos);
+	res = isl_map_coalesce(res);
+
+	return res;
+}
+
+/* Eliminate dimensions inner to the current dimension.
+ */
+__isl_give isl_set *isl_ast_build_eliminate_inner(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+	int dim;
+	int depth;
+
+	if (!build)
+		return isl_set_free(set);
+
+	dim = isl_set_dim(set, isl_dim_set);
+	depth = build->depth;
+	set = isl_set_detect_equalities(set);
+	set = isl_set_eliminate(set, isl_dim_set, depth + 1, dim - (depth + 1));
+
+	return set;
+}
+
+/* Eliminate unknown divs and divs that depend on the current dimension.
+ *
+ * Note that during the elimination of unknown divs, we may discover
+ * an explicit representation of some other unknown divs, which may
+ * depend on the current dimension.  We therefore need to eliminate
+ * unknown divs first.
+ */
+__isl_give isl_set *isl_ast_build_eliminate_divs(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+	int depth;
+
+	if (!build)
+		return isl_set_free(set);
+
+	set = isl_set_remove_unknown_divs(set);
+	depth = build->depth;
+	set = isl_set_remove_divs_involving_dims(set, isl_dim_set, depth, 1);
+
+	return set;
+}
+
+/* Eliminate dimensions inner to the current dimension as well as
+ * unknown divs and divs that depend on the current dimension.
+ * The result then consists only of constraints that are independent
+ * of the current dimension and upper and lower bounds on the current
+ * dimension.
+ */
+__isl_give isl_set *isl_ast_build_eliminate(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *domain)
+{
+	domain = isl_ast_build_eliminate_inner(build, domain);
+	domain = isl_ast_build_eliminate_divs(build, domain);
+	return domain;
+}
+
+/* Replace build->single_valued by "sv".
+ */
+__isl_give isl_ast_build *isl_ast_build_set_single_valued(
+	__isl_take isl_ast_build *build, int sv)
+{
+	if (!build)
+		return build;
+	if (build->single_valued == sv)
+		return build;
+	build = isl_ast_build_cow(build);
+	if (!build)
+		return build;
+	build->single_valued = sv;
+
+	return build;
+}

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_build_expr.c (added)
+++ polly/trunk/lib/External/isl/isl_ast_build_expr.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,1779 @@
+/*
+ * Copyright 2012-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/ilp.h>
+#include <isl_ast_build_expr.h>
+#include <isl_ast_private.h>
+#include <isl_ast_build_private.h>
+
+/* Compute the "opposite" of the (numerator of the) argument of a div
+ * with denonimator "d".
+ *
+ * In particular, compute
+ *
+ *	-aff + (d - 1)
+ */
+static __isl_give isl_aff *oppose_div_arg(__isl_take isl_aff *aff,
+	__isl_take isl_val *d)
+{
+	aff = isl_aff_neg(aff);
+	aff = isl_aff_add_constant_val(aff, d);
+	aff = isl_aff_add_constant_si(aff, -1);
+
+	return aff;
+}
+
+/* Create an isl_ast_expr evaluating the div at position "pos" in "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.
+ * "ls" is known to be non-NULL.
+ *
+ * Let the div be of the form floor(e/d).
+ * If the ast_build_prefer_pdiv option is set then we check if "e"
+ * is non-negative, so that we can generate
+ *
+ *	(pdiv_q, expr(e), expr(d))
+ *
+ * instead of
+ *
+ *	(fdiv_q, expr(e), expr(d))
+ *
+ * If the ast_build_prefer_pdiv option is set and
+ * if "e" is not non-negative, then we check if "-e + d - 1" is non-negative.
+ * If so, we can rewrite
+ *
+ *	floor(e/d) = -ceil(-e/d) = -floor((-e + d - 1)/d)
+ *
+ * and still use pdiv_q.
+ */
+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)
+{
+	isl_ctx *ctx = isl_local_space_get_ctx(ls);
+	isl_aff *aff;
+	isl_ast_expr *num, *den;
+	isl_val *d;
+	enum isl_ast_op_type type;
+
+	aff = isl_local_space_get_div(ls, pos);
+	d = isl_aff_get_denominator_val(aff);
+	aff = isl_aff_scale_val(aff, isl_val_copy(d));
+	den = isl_ast_expr_from_val(isl_val_copy(d));
+
+	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);
+		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);
+			if (non_neg >= 0 && non_neg) {
+				*change_sign = 1;
+				isl_aff_free(aff);
+				aff = opp;
+			} else
+				isl_aff_free(opp);
+		}
+		if (non_neg < 0)
+			aff = isl_aff_free(aff);
+		else if (non_neg)
+			type = isl_ast_op_pdiv_q;
+	}
+
+	isl_val_free(d);
+	num = isl_ast_expr_from_aff(aff, 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 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"
+ * - 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)
+{
+	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);
+
+	if (type == isl_dim_set) {
+		id = isl_ast_build_get_iterator_id(build, pos);
+		return isl_ast_expr_from_id(id);
+	}
+
+	if (!isl_local_space_has_dim_id(ls, type, pos))
+		isl_die(ctx, isl_error_internal, "unnamed dimension",
+			return NULL);
+	id = isl_local_space_get_dim_id(ls, type, pos);
+	return isl_ast_expr_from_id(id);
+}
+
+/* Does "expr" represent the zero integer?
+ */
+static int ast_expr_is_zero(__isl_keep isl_ast_expr *expr)
+{
+	if (!expr)
+		return -1;
+	if (expr->type != isl_ast_expr_int)
+		return 0;
+	return isl_val_is_zero(expr->u.v);
+}
+
+/* Create an expression representing the sum of "expr1" and "expr2",
+ * provided neither of the two expressions is identically zero.
+ */
+static __isl_give isl_ast_expr *ast_expr_add(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	if (!expr1 || !expr2)
+		goto error;
+
+	if (ast_expr_is_zero(expr1)) {
+		isl_ast_expr_free(expr1);
+		return expr2;
+	}
+
+	if (ast_expr_is_zero(expr2)) {
+		isl_ast_expr_free(expr2);
+		return expr1;
+	}
+
+	return isl_ast_expr_add(expr1, expr2);
+error:
+	isl_ast_expr_free(expr1);
+	isl_ast_expr_free(expr2);
+	return NULL;
+}
+
+/* Subtract expr2 from expr1.
+ *
+ * If expr2 is zero, we simply return expr1.
+ * If expr1 is zero, we return
+ *
+ *	(isl_ast_op_minus, expr2)
+ *
+ * Otherwise, we return
+ *
+ *	(isl_ast_op_sub, expr1, expr2)
+ */
+static __isl_give isl_ast_expr *ast_expr_sub(__isl_take isl_ast_expr *expr1,
+	__isl_take isl_ast_expr *expr2)
+{
+	if (!expr1 || !expr2)
+		goto error;
+
+	if (ast_expr_is_zero(expr2)) {
+		isl_ast_expr_free(expr2);
+		return expr1;
+	}
+
+	if (ast_expr_is_zero(expr1)) {
+		isl_ast_expr_free(expr1);
+		return isl_ast_expr_neg(expr2);
+	}
+
+	return isl_ast_expr_sub(expr1, expr2);
+error:
+	isl_ast_expr_free(expr1);
+	isl_ast_expr_free(expr2);
+	return NULL;
+}
+
+/* Return an isl_ast_expr that represents
+ *
+ *	v * (aff mod d)
+ *
+ * v is assumed to be non-negative.
+ * The result is simplified in terms of build->domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_mod(__isl_keep isl_val *v,
+	__isl_keep isl_aff *aff, __isl_keep isl_val *d,
+	__isl_keep isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	isl_ast_expr *expr;
+	isl_ast_expr *c;
+
+	if (!aff)
+		return NULL;
+
+	ctx = isl_aff_get_ctx(aff);
+	expr = isl_ast_expr_from_aff(isl_aff_copy(aff), build);
+
+	c = isl_ast_expr_from_val(isl_val_copy(d));
+	expr = isl_ast_expr_alloc_binary(isl_ast_op_pdiv_r, expr, c);
+
+	if (!isl_val_is_one(v)) {
+		c = isl_ast_expr_from_val(isl_val_copy(v));
+		expr = isl_ast_expr_mul(c, expr);
+	}
+
+	return expr;
+}
+
+/* Create an isl_ast_expr that scales "expr" by "v".
+ *
+ * If v is 1, we simply return expr.
+ * If v is -1, we return
+ *
+ *	(isl_ast_op_minus, expr)
+ *
+ * Otherwise, we return
+ *
+ *	(isl_ast_op_mul, expr(v), expr)
+ */
+static __isl_give isl_ast_expr *scale(__isl_take isl_ast_expr *expr,
+	__isl_take isl_val *v)
+{
+	isl_ast_expr *c;
+
+	if (!expr || !v)
+		goto error;
+	if (isl_val_is_one(v)) {
+		isl_val_free(v);
+		return expr;
+	}
+
+	if (isl_val_is_negone(v)) {
+		isl_val_free(v);
+		expr = isl_ast_expr_neg(expr);
+	} else {
+		c = isl_ast_expr_from_val(v);
+		expr = isl_ast_expr_mul(c, expr);
+	}
+
+	return expr;
+error:
+	isl_val_free(v);
+	isl_ast_expr_free(expr);
+	return NULL;
+}
+
+/* Add an expression for "*v" times the specified dimension of "ls"
+ * to expr.
+ *
+ * Let e be the expression for the specified dimension,
+ * multiplied by the absolute value of "*v".
+ * If "*v" is negative, we create
+ *
+ *	(isl_ast_op_sub, expr, e)
+ *
+ * except when expr is trivially zero, in which case we create
+ *
+ *	(isl_ast_op_minus, e)
+ *
+ * instead.
+ *
+ * If "*v" is positive, we simply create
+ *
+ *	(isl_ast_op_add, expr, e)
+ *
+ */
+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_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);
+
+	if (isl_val_is_neg(v) && !ast_expr_is_zero(expr)) {
+		v = isl_val_neg(v);
+		term = scale(term, v);
+		return ast_expr_sub(expr, term);
+	} else {
+		term = scale(term, v);
+		return ast_expr_add(expr, term);
+	}
+}
+
+/* Add an expression for "v" to expr.
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_add_int(
+	__isl_take isl_ast_expr *expr, __isl_take isl_val *v)
+{
+	isl_ctx *ctx;
+	isl_ast_expr *expr_int;
+
+	if (!expr || !v)
+		goto error;
+
+	if (isl_val_is_zero(v)) {
+		isl_val_free(v);
+		return expr;
+	}
+
+	ctx = isl_ast_expr_get_ctx(expr);
+	if (isl_val_is_neg(v) && !ast_expr_is_zero(expr)) {
+		v = isl_val_neg(v);
+		expr_int = isl_ast_expr_from_val(v);
+		return ast_expr_sub(expr, expr_int);
+	} else {
+		expr_int = isl_ast_expr_from_val(v);
+		return ast_expr_add(expr, expr_int);
+	}
+error:
+	isl_ast_expr_free(expr);
+	isl_val_free(v);
+	return NULL;
+}
+
+/* Internal data structure used inside extract_modulos.
+ *
+ * If any modulo expressions are detected in "aff", then the
+ * expression is removed from "aff" and added to either "pos" or "neg"
+ * depending on the sign of the coefficient of the modulo expression
+ * inside "aff".
+ *
+ * "add" is an expression that needs to be added to "aff" at the end of
+ * the computation.  It is NULL as long as no modulos have been extracted.
+ *
+ * "i" is the position in "aff" of the div under investigation
+ * "v" is the coefficient in "aff" of the div
+ * "div" is the argument of the div, with the denominator removed
+ * "d" is the original denominator of the argument of the div
+ *
+ * "nonneg" is an affine expression that is non-negative over "build"
+ * and that can be used to extract a modulo expression from "div".
+ * In particular, if "sign" is 1, then the coefficients of "nonneg"
+ * are equal to those of "div" modulo "d".  If "sign" is -1, then
+ * the coefficients of "nonneg" are opposite to those of "div" modulo "d".
+ * If "sign" is 0, then no such affine expression has been found (yet).
+ */
+struct isl_extract_mod_data {
+	isl_ast_build *build;
+	isl_aff *aff;
+
+	isl_ast_expr *pos;
+	isl_ast_expr *neg;
+
+	isl_aff *add;
+
+	int i;
+	isl_val *v;
+	isl_val *d;
+	isl_aff *div;
+
+	isl_aff *nonneg;
+	int sign;
+};
+
+/* Given that data->v * div_i in data->aff is equal to
+ *
+ *	f * (term - (arg mod d))
+ *
+ * with data->d * f = data->v, add
+ *
+ *	f * term
+ *
+ * to data->add and
+ *
+ *	abs(f) * (arg mod d)
+ *
+ * to data->neg or data->pos depending on the sign of -f.
+ */
+static int extract_term_and_mod(struct isl_extract_mod_data *data,
+	__isl_take isl_aff *term, __isl_take isl_aff *arg)
+{
+	isl_ast_expr *expr;
+	int s;
+
+	data->v = isl_val_div(data->v, isl_val_copy(data->d));
+	s = isl_val_sgn(data->v);
+	data->v = isl_val_abs(data->v);
+	expr = isl_ast_expr_mod(data->v, arg, data->d, data->build);
+	isl_aff_free(arg);
+	if (s > 0)
+		data->neg = ast_expr_add(data->neg, expr);
+	else
+		data->pos = ast_expr_add(data->pos, expr);
+	data->aff = isl_aff_set_coefficient_si(data->aff,
+						isl_dim_div, data->i, 0);
+	if (s < 0)
+		data->v = isl_val_neg(data->v);
+	term = isl_aff_scale_val(data->div, isl_val_copy(data->v));
+
+	if (!data->add)
+		data->add = term;
+	else
+		data->add = isl_aff_add(data->add, term);
+	if (!data->add)
+		return -1;
+
+	return 0;
+}
+
+/* Given that data->v * div_i in data->aff is of the form
+ *
+ *	f * d * floor(div/d)
+ *
+ * with div nonnegative on data->build, rewrite it as
+ *
+ *	f * (div - (div mod d)) = f * div - f * (div mod d)
+ *
+ * and add
+ *
+ *	f * div
+ *
+ * to data->add and
+ *
+ *	abs(f) * (div mod d)
+ *
+ * to data->neg or data->pos depending on the sign of -f.
+ */
+static int extract_mod(struct isl_extract_mod_data *data)
+{
+	return extract_term_and_mod(data, isl_aff_copy(data->div),
+			isl_aff_copy(data->div));
+}
+
+/* Given that data->v * div_i in data->aff is of the form
+ *
+ *	f * d * floor(div/d)					(1)
+ *
+ * check if div is non-negative on data->build and, if so,
+ * extract the corresponding modulo from data->aff.
+ * If not, then check if
+ *
+ *	-div + d - 1
+ *
+ * is non-negative on data->build.  If so, replace (1) by
+ *
+ *	-f * d * floor((-div + d - 1)/d)
+ *
+ * and extract the corresponding modulo from data->aff.
+ *
+ * This function may modify data->div.
+ */
+static int extract_nonneg_mod(struct isl_extract_mod_data *data)
+{
+	int mod;
+
+	mod = isl_ast_build_aff_is_nonneg(data->build, data->div);
+	if (mod < 0)
+		goto error;
+	if (mod)
+		return extract_mod(data);
+
+	data->div = oppose_div_arg(data->div, isl_val_copy(data->d));
+	mod = isl_ast_build_aff_is_nonneg(data->build, data->div);
+	if (mod < 0)
+		goto error;
+	if (mod) {
+		data->v = isl_val_neg(data->v);
+		return extract_mod(data);
+	}
+
+	return 0;
+error:
+	data->aff = isl_aff_free(data->aff);
+	return -1;
+}
+
+/* Is the affine expression of constraint "c" "simpler" than data->nonneg
+ * for use in extracting a modulo expression?
+ *
+ * We currently only consider the constant term of the affine expression.
+ * In particular, we prefer the affine expression with the smallest constant
+ * term.
+ * This means that if there are two constraints, say x >= 0 and -x + 10 >= 0,
+ * then we would pick x >= 0
+ *
+ * More detailed heuristics could be used if it turns out that there is a need.
+ */
+static int mod_constraint_is_simpler(struct isl_extract_mod_data *data,
+	__isl_keep isl_constraint *c)
+{
+	isl_val *v1, *v2;
+	int simpler;
+
+	if (!data->nonneg)
+		return 1;
+
+	v1 = isl_val_abs(isl_constraint_get_constant_val(c));
+	v2 = isl_val_abs(isl_aff_get_constant_val(data->nonneg));
+	simpler = isl_val_lt(v1, v2);
+	isl_val_free(v1);
+	isl_val_free(v2);
+
+	return simpler;
+}
+
+/* Check if the coefficients of "c" are either equal or opposite to those
+ * of data->div modulo data->d.  If so, and if "c" is "simpler" than
+ * data->nonneg, then replace data->nonneg by the affine expression of "c"
+ * and set data->sign accordingly.
+ *
+ * Both "c" and data->div are assumed not to involve any integer divisions.
+ *
+ * Before we start the actual comparison, we first quickly check if
+ * "c" and data->div have the same non-zero coefficients.
+ * If not, then we assume that "c" is not of the desired form.
+ * Note that while the coefficients of data->div can be reasonably expected
+ * not to involve any coefficients that are multiples of d, "c" may
+ * very well involve such coefficients.  This means that we may actually
+ * miss some cases.
+ */
+static int check_parallel_or_opposite(__isl_take isl_constraint *c, void *user)
+{
+	struct isl_extract_mod_data *data = user;
+	enum isl_dim_type c_type[2] = { isl_dim_param, isl_dim_set };
+	enum isl_dim_type a_type[2] = { isl_dim_param, isl_dim_in };
+	int i, t;
+	int n[2];
+	int parallel = 1, opposite = 1;
+
+	for (t = 0; t < 2; ++t) {
+		n[t] = isl_constraint_dim(c, c_type[t]);
+		for (i = 0; i < n[t]; ++i) {
+			int a, b;
+
+			a = isl_constraint_involves_dims(c, c_type[t], i, 1);
+			b = isl_aff_involves_dims(data->div, a_type[t], i, 1);
+			if (a != b)
+				parallel = opposite = 0;
+		}
+	}
+
+	for (t = 0; t < 2; ++t) {
+		for (i = 0; i < n[t]; ++i) {
+			isl_val *v1, *v2;
+
+			if (!parallel && !opposite)
+				break;
+			v1 = isl_constraint_get_coefficient_val(c,
+								c_type[t], i);
+			v2 = isl_aff_get_coefficient_val(data->div,
+								a_type[t], i);
+			if (parallel) {
+				v1 = isl_val_sub(v1, isl_val_copy(v2));
+				parallel = isl_val_is_divisible_by(v1, data->d);
+				v1 = isl_val_add(v1, isl_val_copy(v2));
+			}
+			if (opposite) {
+				v1 = isl_val_add(v1, isl_val_copy(v2));
+				opposite = isl_val_is_divisible_by(v1, data->d);
+			}
+			isl_val_free(v1);
+			isl_val_free(v2);
+		}
+	}
+
+	if ((parallel || opposite) && mod_constraint_is_simpler(data, c)) {
+		isl_aff_free(data->nonneg);
+		data->nonneg = isl_constraint_get_aff(c);
+		data->sign = parallel ? 1 : -1;
+	}
+
+	isl_constraint_free(c);
+
+	if (data->sign != 0 && data->nonneg == NULL)
+		return -1;
+
+	return 0;
+}
+
+/* Given that data->v * div_i in data->aff is of the form
+ *
+ *	f * d * floor(div/d)					(1)
+ *
+ * see if we can find an expression div' that is non-negative over data->build
+ * and that is related to div through
+ *
+ *	div' = div + d * e
+ *
+ * or
+ *
+ *	div' = -div + d - 1 + d * e
+ *
+ * with e some affine expression.
+ * If so, we write (1) as
+ *
+ *	f * div + f * (div' mod d)
+ *
+ * or
+ *
+ *	-f * (-div + d - 1) - f * (div' mod d)
+ *
+ * exploiting (in the second case) the fact that
+ *
+ *	f * d * floor(div/d) =	-f * d * floor((-div + d - 1)/d)
+ *
+ *
+ * We first try to find an appropriate expression for div'
+ * from the constraints of data->build->domain (which is therefore
+ * guaranteed to be non-negative on data->build), where we remove
+ * any integer divisions from the constraints and skip this step
+ * if "div" itself involves any integer divisions.
+ * If we cannot find an appropriate expression this way, then
+ * we pass control to extract_nonneg_mod where check
+ * if div or "-div + d -1" themselves happen to be
+ * non-negative on data->build.
+ *
+ * While looking for an appropriate constraint in data->build->domain,
+ * we ignore the constant term, so after finding such a constraint,
+ * we still need to fix up the constant term.
+ * In particular, if a is the constant term of "div"
+ * (or d - 1 - the constant term of "div" if data->sign < 0)
+ * and b is the constant term of the constraint, then we need to find
+ * a non-negative constant c such that
+ *
+ *	b + c \equiv a	mod d
+ *
+ * We therefore take
+ *
+ *	c = (a - b) mod d
+ *
+ * and add it to b to obtain the constant term of div'.
+ * If this constant term is "too negative", then we add an appropriate
+ * multiple of d to make it positive.
+ *
+ *
+ * Note that the above is a only a very simple heuristic for finding an
+ * appropriate expression.  We could try a bit harder by also considering
+ * sums of constraints that involve disjoint sets of variables or
+ * we could consider arbitrary linear combinations of constraints,
+ * although that could potentially be much more expensive as it involves
+ * the solution of an LP problem.
+ *
+ * In particular, if v_i is a column vector representing constraint i,
+ * w represents div and e_i is the i-th unit vector, then we are looking
+ * for a solution of the constraints
+ *
+ *	\sum_i lambda_i v_i = w + \sum_i alpha_i d e_i
+ *
+ * with \lambda_i >= 0 and alpha_i of unrestricted sign.
+ * If we are not just interested in a non-negative expression, but
+ * also in one with a minimal range, then we don't just want
+ * c = \sum_i lambda_i v_i to be non-negative over the domain,
+ * but also beta - c = \sum_i mu_i v_i, where beta is a scalar
+ * that we want to minimize and we now also have to take into account
+ * the constant terms of the constraints.
+ * Alternatively, we could first compute the dual of the domain
+ * and plug in the constraints on the coefficients.
+ */
+static int try_extract_mod(struct isl_extract_mod_data *data)
+{
+	isl_basic_set *hull;
+	isl_val *v1, *v2;
+	int r;
+
+	if (!data->build)
+		goto error;
+
+	int 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);
+
+	hull = isl_set_simple_hull(isl_set_copy(data->build->domain));
+	hull = isl_basic_set_remove_divs(hull);
+	data->sign = 0;
+	data->nonneg = NULL;
+	r = isl_basic_set_foreach_constraint(hull, &check_parallel_or_opposite,
+					data);
+	isl_basic_set_free(hull);
+
+	if (!data->sign || r < 0) {
+		isl_aff_free(data->nonneg);
+		if (r < 0)
+			goto error;
+		return extract_nonneg_mod(data);
+	}
+
+	v1 = isl_aff_get_constant_val(data->div);
+	v2 = isl_aff_get_constant_val(data->nonneg);
+	if (data->sign < 0) {
+		v1 = isl_val_neg(v1);
+		v1 = isl_val_add(v1, isl_val_copy(data->d));
+		v1 = isl_val_sub_ui(v1, 1);
+	}
+	v1 = isl_val_sub(v1, isl_val_copy(v2));
+	v1 = isl_val_mod(v1, isl_val_copy(data->d));
+	v1 = isl_val_add(v1, v2);
+	v2 = isl_val_div(isl_val_copy(v1), isl_val_copy(data->d));
+	v2 = isl_val_ceil(v2);
+	if (isl_val_is_neg(v2)) {
+		v2 = isl_val_mul(v2, isl_val_copy(data->d));
+		v1 = isl_val_sub(v1, isl_val_copy(v2));
+	}
+	data->nonneg = isl_aff_set_constant_val(data->nonneg, v1);
+	isl_val_free(v2);
+
+	if (data->sign < 0) {
+		data->div = oppose_div_arg(data->div, isl_val_copy(data->d));
+		data->v = isl_val_neg(data->v);
+	}
+
+	return extract_term_and_mod(data,
+				    isl_aff_copy(data->div), data->nonneg);
+error:
+	data->aff = isl_aff_free(data->aff);
+	return -1;
+}
+
+/* Check if "data->aff" involves any (implicit) modulo computations based
+ * on div "data->i".
+ * If so, remove them from aff and add expressions corresponding
+ * to those modulo computations to data->pos and/or data->neg.
+ *
+ * "aff" is assumed to be an integer affine expression.
+ *
+ * In particular, check if (v * div_j) is of the form
+ *
+ *	f * m * floor(a / m)
+ *
+ * and, if so, rewrite it as
+ *
+ *	f * (a - (a mod m)) = f * a - f * (a mod m)
+ *
+ * and extract out -f * (a mod m).
+ * In particular, if f > 0, we add (f * (a mod m)) to *neg.
+ * If f < 0, we add ((-f) * (a mod m)) to *pos.
+ *
+ * Note that in order to represent "a mod m" as
+ *
+ *	(isl_ast_op_pdiv_r, a, m)
+ *
+ * we need to make sure that a is non-negative.
+ * If not, we check if "-a + m - 1" is non-negative.
+ * If so, we can rewrite
+ *
+ *	floor(a/m) = -ceil(-a/m) = -floor((-a + m - 1)/m)
+ *
+ * and still extract a modulo.
+ */
+static int extract_modulo(struct isl_extract_mod_data *data)
+{
+	data->div = isl_aff_get_div(data->aff, data->i);
+	data->d = isl_aff_get_denominator_val(data->div);
+	if (isl_val_is_divisible_by(data->v, data->d)) {
+		data->div = isl_aff_scale_val(data->div, isl_val_copy(data->d));
+		if (try_extract_mod(data) < 0)
+			data->aff = isl_aff_free(data->aff);
+	}
+	isl_aff_free(data->div);
+	isl_val_free(data->d);
+	return 0;
+}
+
+/* Check if "aff" involves any (implicit) modulo computations.
+ * If so, remove them from aff and add expressions corresponding
+ * to those modulo computations to *pos and/or *neg.
+ * We only do this if the option ast_build_prefer_pdiv is set.
+ *
+ * "aff" is assumed to be an integer affine expression.
+ *
+ * A modulo expression is of the form
+ *
+ *	a mod m = a - m * floor(a / m)
+ *
+ * To detect them in aff, we look for terms of the form
+ *
+ *	f * m * floor(a / m)
+ *
+ * rewrite them as
+ *
+ *	f * (a - (a mod m)) = f * a - f * (a mod m)
+ *
+ * and extract out -f * (a mod m).
+ * In particular, if f > 0, we add (f * (a mod m)) to *neg.
+ * If f < 0, we add ((-f) * (a mod m)) to *pos.
+ */
+static __isl_give isl_aff *extract_modulos(__isl_take isl_aff *aff,
+	__isl_keep isl_ast_expr **pos, __isl_keep isl_ast_expr **neg,
+	__isl_keep isl_ast_build *build)
+{
+	struct isl_extract_mod_data data = { build, aff, *pos, *neg };
+	isl_ctx *ctx;
+	int n;
+
+	if (!aff)
+		return NULL;
+
+	ctx = isl_aff_get_ctx(aff);
+	if (!isl_options_get_ast_build_prefer_pdiv(ctx))
+		return aff;
+
+	n = isl_aff_dim(data.aff, isl_dim_div);
+	for (data.i = 0; data.i < n; ++data.i) {
+		data.v = isl_aff_get_coefficient_val(data.aff,
+							isl_dim_div, data.i);
+		if (!data.v)
+			return isl_aff_free(aff);
+		if (isl_val_is_zero(data.v) ||
+		    isl_val_is_one(data.v) || isl_val_is_negone(data.v)) {
+			isl_val_free(data.v);
+			continue;
+		}
+		if (extract_modulo(&data) < 0)
+			data.aff = isl_aff_free(data.aff);
+		isl_val_free(data.v);
+		if (!data.aff)
+			break;
+	}
+
+	if (data.add)
+		data.aff = isl_aff_add(data.aff, data.add);
+
+	*pos = data.pos;
+	*neg = data.neg;
+	return data.aff;
+}
+
+/* Check if aff involves any non-integer coefficients.
+ * If so, split aff into
+ *
+ *	aff = aff1 + (aff2 / d)
+ *
+ * with both aff1 and aff2 having only integer coefficients.
+ * Return aff1 and add (aff2 / d) to *expr.
+ */
+static __isl_give isl_aff *extract_rational(__isl_take isl_aff *aff,
+	__isl_keep isl_ast_expr **expr, __isl_keep isl_ast_build *build)
+{
+	int i, j, n;
+	isl_aff *rat = NULL;
+	isl_local_space *ls = NULL;
+	isl_ast_expr *rat_expr;
+	isl_val *v, *d;
+	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 };
+
+	if (!aff)
+		return NULL;
+	d = isl_aff_get_denominator_val(aff);
+	if (!d)
+		goto error;
+	if (isl_val_is_one(d)) {
+		isl_val_free(d);
+		return aff;
+	}
+
+	aff = isl_aff_scale_val(aff, isl_val_copy(d));
+
+	ls = isl_aff_get_domain_local_space(aff);
+	rat = isl_aff_zero_on_domain(isl_local_space_copy(ls));
+
+	for (i = 0; i < 3; ++i) {
+		n = isl_aff_dim(aff, t[i]);
+		for (j = 0; j < n; ++j) {
+			isl_aff *rat_j;
+
+			v = isl_aff_get_coefficient_val(aff, t[i], j);
+			if (!v)
+				goto error;
+			if (isl_val_is_divisible_by(v, d)) {
+				isl_val_free(v);
+				continue;
+			}
+			rat_j = isl_aff_var_on_domain(isl_local_space_copy(ls),
+							l[i], j);
+			rat_j = isl_aff_scale_val(rat_j, v);
+			rat = isl_aff_add(rat, rat_j);
+		}
+	}
+
+	v = isl_aff_get_constant_val(aff);
+	if (isl_val_is_divisible_by(v, d)) {
+		isl_val_free(v);
+	} else {
+		isl_aff *rat_0;
+
+		rat_0 = isl_aff_val_on_domain(isl_local_space_copy(ls), v);
+		rat = isl_aff_add(rat, rat_0);
+	}
+
+	isl_local_space_free(ls);
+
+	aff = isl_aff_sub(aff, isl_aff_copy(rat));
+	aff = isl_aff_scale_down_val(aff, isl_val_copy(d));
+
+	rat_expr = isl_ast_expr_from_aff(rat, build);
+	rat_expr = isl_ast_expr_div(rat_expr, isl_ast_expr_from_val(d));
+	*expr = ast_expr_add(*expr, rat_expr);
+
+	return aff;
+error:
+	isl_aff_free(rat);
+	isl_local_space_free(ls);
+	isl_aff_free(aff);
+	isl_val_free(d);
+	return NULL;
+}
+
+/* Construct an isl_ast_expr that evaluates the affine expression "aff",
+ * The result is simplified in terms of build->domain.
+ *
+ * We first extract hidden modulo computations from the affine expression
+ * and then add terms for each variable with a non-zero coefficient.
+ * Finally, if the affine expression has a non-trivial denominator,
+ * we divide the resulting isl_ast_expr by this denominator.
+ */
+__isl_give isl_ast_expr *isl_ast_expr_from_aff(__isl_take isl_aff *aff,
+	__isl_keep isl_ast_build *build)
+{
+	int i, j;
+	int n;
+	isl_val *v;
+	isl_ctx *ctx = isl_aff_get_ctx(aff);
+	isl_ast_expr *expr, *expr_neg;
+	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;
+
+	if (!aff)
+		return NULL;
+
+	expr = isl_ast_expr_alloc_int_si(ctx, 0);
+	expr_neg = isl_ast_expr_alloc_int_si(ctx, 0);
+
+	aff = extract_rational(aff, &expr, build);
+
+	aff = extract_modulos(aff, &expr, &expr_neg, build);
+	expr = ast_expr_sub(expr, expr_neg);
+
+	ls = isl_aff_get_domain_local_space(aff);
+
+	for (i = 0; i < 3; ++i) {
+		n = isl_aff_dim(aff, t[i]);
+		for (j = 0; j < n; ++j) {
+			v = isl_aff_get_coefficient_val(aff, t[i], j);
+			if (!v)
+				expr = isl_ast_expr_free(expr);
+			if (isl_val_is_zero(v)) {
+				isl_val_free(v);
+				continue;
+			}
+			expr = isl_ast_expr_add_term(expr,
+							ls, l[i], j, v, build);
+		}
+	}
+
+	v = isl_aff_get_constant_val(aff);
+	expr = isl_ast_expr_add_int(expr, v);
+
+	isl_local_space_free(ls);
+	isl_aff_free(aff);
+	return expr;
+}
+
+/* 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.
+ */
+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)
+{
+	int i, j;
+	isl_val *v;
+	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;
+
+	ls = isl_aff_get_domain_local_space(aff);
+
+	for (i = 0; i < 3; ++i) {
+		int n = isl_aff_dim(aff, t[i]);
+		for (j = 0; j < n; ++j) {
+			v = isl_aff_get_coefficient_val(aff, t[i], j);
+			if (sign * isl_val_sgn(v) <= 0) {
+				isl_val_free(v);
+				continue;
+			}
+			v = isl_val_abs(v);
+			expr = isl_ast_expr_add_term(expr,
+						ls, l[i], j, v, build);
+		}
+	}
+
+	isl_local_space_free(ls);
+
+	return expr;
+}
+
+/* Should the constant term "v" be considered positive?
+ *
+ * A positive constant will be added to "pos" by the caller,
+ * while a negative constant will be added to "neg".
+ * If either "pos" or "neg" is exactly zero, then we prefer
+ * to add the constant "v" to that side, irrespective of the sign of "v".
+ * This results in slightly shorter expressions and may reduce the risk
+ * of overflows.
+ */
+static int constant_is_considered_positive(__isl_keep isl_val *v,
+	__isl_keep isl_ast_expr *pos, __isl_keep isl_ast_expr *neg)
+{
+	if (ast_expr_is_zero(pos))
+		return 1;
+	if (ast_expr_is_zero(neg))
+		return 0;
+	return isl_val_is_pos(v);
+}
+
+/* Check if the equality
+ *
+ *	aff = 0
+ *
+ * represents a stride constraint on the integer division "pos".
+ *
+ * In particular, if the integer division "pos" is equal to
+ *
+ *	floor(e/d)
+ *
+ * then check if aff is equal to
+ *
+ *	e - d floor(e/d)
+ *
+ * or its opposite.
+ *
+ * If so, the equality is exactly
+ *
+ *	e mod d = 0
+ *
+ * Note that in principle we could also accept
+ *
+ *	e - d floor(e'/d)
+ *
+ * where e and e' differ by a constant.
+ */
+static int is_stride_constraint(__isl_keep isl_aff *aff, int pos)
+{
+	isl_aff *div;
+	isl_val *c, *d;
+	int eq;
+
+	div = isl_aff_get_div(aff, pos);
+	c = isl_aff_get_coefficient_val(aff, isl_dim_div, pos);
+	d = isl_aff_get_denominator_val(div);
+	eq = isl_val_abs_eq(c, d);
+	if (eq >= 0 && eq) {
+		aff = isl_aff_copy(aff);
+		aff = isl_aff_set_coefficient_si(aff, isl_dim_div, pos, 0);
+		div = isl_aff_scale_val(div, d);
+		if (isl_val_is_pos(c))
+			div = isl_aff_neg(div);
+		eq = isl_aff_plain_is_equal(div, aff);
+		isl_aff_free(aff);
+	} else
+		isl_val_free(d);
+	isl_val_free(c);
+	isl_aff_free(div);
+
+	return eq;
+}
+
+/* Are all coefficients of "aff" (zero or) negative?
+ */
+static int all_negative_coefficients(__isl_keep isl_aff *aff)
+{
+	int i, n;
+
+	if (!aff)
+		return 0;
+
+	n = isl_aff_dim(aff, isl_dim_param);
+	for (i = 0; i < n; ++i)
+		if (isl_aff_coefficient_sgn(aff, isl_dim_param, i) > 0)
+			return 0;
+
+	n = isl_aff_dim(aff, isl_dim_in);
+	for (i = 0; i < n; ++i)
+		if (isl_aff_coefficient_sgn(aff, isl_dim_in, i) > 0)
+			return 0;
+
+	return 1;
+}
+
+/* Give an equality of the form
+ *
+ *	aff = e - d floor(e/d) = 0
+ *
+ * or
+ *
+ *	aff = -e + d floor(e/d) = 0
+ *
+ * with the integer division "pos" equal to floor(e/d),
+ * construct the AST expression
+ *
+ *	(isl_ast_op_eq, (isl_ast_op_zdiv_r, expr(e), expr(d)), expr(0))
+ *
+ * If e only has negative coefficients, then construct
+ *
+ *	(isl_ast_op_eq, (isl_ast_op_zdiv_r, expr(-e), expr(d)), expr(0))
+ *
+ * instead.
+ */
+static __isl_give isl_ast_expr *extract_stride_constraint(
+	__isl_take isl_aff *aff, int pos, __isl_keep isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	isl_val *c;
+	isl_ast_expr *expr, *cst;
+
+	if (!aff)
+		return NULL;
+
+	ctx = isl_aff_get_ctx(aff);
+
+	c = isl_aff_get_coefficient_val(aff, isl_dim_div, pos);
+	aff = isl_aff_set_coefficient_si(aff, isl_dim_div, pos, 0);
+
+	if (all_negative_coefficients(aff))
+		aff = isl_aff_neg(aff);
+
+	cst = isl_ast_expr_from_val(isl_val_abs(c));
+	expr = isl_ast_expr_from_aff(aff, build);
+
+	expr = isl_ast_expr_alloc_binary(isl_ast_op_zdiv_r, expr, cst);
+	cst = isl_ast_expr_alloc_int_si(ctx, 0);
+	expr = isl_ast_expr_alloc_binary(isl_ast_op_eq, expr, cst);
+
+	return expr;
+}
+
+/* Construct an isl_ast_expr that evaluates the condition "constraint",
+ * The result is simplified in terms of build->domain.
+ *
+ * We first check if the constraint is an equality of the form
+ *
+ *	e - d floor(e/d) = 0
+ *
+ * i.e.,
+ *
+ *	e mod d = 0
+ *
+ * If so, we convert it to
+ *
+ *	(isl_ast_op_eq, (isl_ast_op_zdiv_r, expr(e), expr(d)), expr(0))
+ *
+ * Otherwise, let the constraint by either "a >= 0" or "a == 0".
+ * We first extract hidden modulo computations from "a"
+ * and then collect all the terms with a positive coefficient in cons_pos
+ * and the terms with a negative coefficient in cons_neg.
+ *
+ * The result is then of the form
+ *
+ *	(isl_ast_op_ge, expr(pos), expr(-neg)))
+ *
+ * or
+ *
+ *	(isl_ast_op_eq, expr(pos), expr(-neg)))
+ *
+ * However, if the first expression is an integer constant (and the second
+ * is not), then we swap the two expressions.  This ensures that we construct,
+ * e.g., "i <= 5" rather than "5 >= i".
+ *
+ * Furthermore, is there are no terms with positive coefficients (or no terms
+ * with negative coefficients), then the constant term is added to "pos"
+ * (or "neg"), ignoring the sign of the constant term.
+ */
+static __isl_give isl_ast_expr *isl_ast_expr_from_constraint(
+	__isl_take isl_constraint *constraint, __isl_keep isl_ast_build *build)
+{
+	int i, n;
+	isl_ctx *ctx;
+	isl_ast_expr *expr_pos;
+	isl_ast_expr *expr_neg;
+	isl_ast_expr *expr;
+	isl_aff *aff;
+	isl_val *v;
+	int eq;
+	enum isl_ast_op_type type;
+
+	if (!constraint)
+		return NULL;
+
+	aff = isl_constraint_get_aff(constraint);
+	eq = isl_constraint_is_equality(constraint);
+	isl_constraint_free(constraint);
+
+	n = isl_aff_dim(aff, isl_dim_div);
+	if (eq && n > 0)
+		for (i = 0; i < n; ++i) {
+			int is_stride;
+			is_stride = is_stride_constraint(aff, i);
+			if (is_stride < 0)
+				goto error;
+			if (is_stride)
+				return extract_stride_constraint(aff, i, build);
+		}
+
+	ctx = isl_aff_get_ctx(aff);
+	expr_pos = isl_ast_expr_alloc_int_si(ctx, 0);
+	expr_neg = isl_ast_expr_alloc_int_si(ctx, 0);
+
+	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);
+
+	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);
+	} else {
+		v = isl_val_neg(v);
+		expr_neg = isl_ast_expr_add_int(expr_neg, v);
+	}
+
+	if (isl_ast_expr_get_type(expr_pos) == isl_ast_expr_int &&
+	    isl_ast_expr_get_type(expr_neg) != isl_ast_expr_int) {
+		type = eq ? isl_ast_op_eq : isl_ast_op_le;
+		expr = isl_ast_expr_alloc_binary(type, expr_neg, expr_pos);
+	} else {
+		type = eq ? isl_ast_op_eq : isl_ast_op_ge;
+		expr = isl_ast_expr_alloc_binary(type, expr_pos, expr_neg);
+	}
+
+	isl_aff_free(aff);
+	return expr;
+error:
+	isl_aff_free(aff);
+	return NULL;
+}
+
+/* Wrapper around isl_constraint_cmp_last_non_zero for use
+ * as a callback to isl_constraint_list_sort.
+ * If isl_constraint_cmp_last_non_zero cannot tell the constraints
+ * apart, then use isl_constraint_plain_cmp instead.
+ */
+static int cmp_constraint(__isl_keep isl_constraint *a,
+	__isl_keep isl_constraint *b, void *user)
+{
+	int cmp;
+
+	cmp = isl_constraint_cmp_last_non_zero(a, b);
+	if (cmp != 0)
+		return cmp;
+	return isl_constraint_plain_cmp(a, b);
+}
+
+/* Construct an isl_ast_expr that evaluates the conditions defining "bset".
+ * The result is simplified in terms of build->domain.
+ *
+ * If "bset" is not bounded by any constraint, then we contruct
+ * the expression "1", i.e., "true".
+ *
+ * Otherwise, we sort the constraints, putting constraints that involve
+ * integer divisions after those that do not, and construct an "and"
+ * of the ast expressions of the individual constraints.
+ *
+ * Each constraint is added to the generated constraints of the build
+ * after it has been converted to an AST expression so that it can be used
+ * to simplify the following constraints.  This may change the truth value
+ * of subsequent constraints that do not satisfy the earlier constraints,
+ * but this does not affect the outcome of the conjunction as it is
+ * only true if all the conjuncts are true (no matter in what order
+ * they are evaluated).  In particular, the constraints that do not
+ * involve integer divisions may serve to simplify some constraints
+ * that do involve integer divisions.
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
+	 __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset)
+{
+	int i, n;
+	isl_constraint *c;
+	isl_constraint_list *list;
+	isl_ast_expr *res;
+	isl_set *set;
+
+	list = isl_basic_set_get_constraint_list(bset);
+	isl_basic_set_free(bset);
+	list = isl_constraint_list_sort(list, &cmp_constraint, NULL);
+	if (!list)
+		return NULL;
+	n = isl_constraint_list_n_constraint(list);
+	if (n == 0) {
+		isl_ctx *ctx = isl_basic_set_get_ctx(bset);
+		isl_constraint_list_free(list);
+		return isl_ast_expr_alloc_int_si(ctx, 1);
+	}
+
+	build = isl_ast_build_copy(build);
+
+	c = isl_constraint_list_get_constraint(list, 0);
+	bset = isl_basic_set_from_constraint(isl_constraint_copy(c));
+	set = isl_set_from_basic_set(bset);
+	res = isl_ast_expr_from_constraint(c, build);
+	build = isl_ast_build_restrict_generated(build, set);
+
+	for (i = 1; i < n; ++i) {
+		isl_ast_expr *expr;
+
+		c = isl_constraint_list_get_constraint(list, i);
+		bset = isl_basic_set_from_constraint(isl_constraint_copy(c));
+		set = isl_set_from_basic_set(bset);
+		expr = isl_ast_expr_from_constraint(c, build);
+		build = isl_ast_build_restrict_generated(build, set);
+		res = isl_ast_expr_and(res, expr);
+	}
+
+	isl_constraint_list_free(list);
+	isl_ast_build_free(build);
+	return res;
+}
+
+struct isl_expr_from_set_data {
+	isl_ast_build *build;
+	int first;
+	isl_ast_expr *res;
+};
+
+/* Construct an isl_ast_expr that evaluates the conditions defining "bset"
+ * and add it to data->res.
+ * The result is simplified in terms of data->build->domain.
+ */
+static int expr_from_set(__isl_take isl_basic_set *bset, void *user)
+{
+	struct isl_expr_from_set_data *data = user;
+	isl_ast_expr *expr;
+
+	expr = isl_ast_build_expr_from_basic_set(data->build, bset);
+	if (data->first)
+		data->res = expr;
+	else
+		data->res = isl_ast_expr_or(data->res, expr);
+
+	data->first = 0;
+
+	if (!data->res)
+		return -1;
+	return 0;
+}
+
+/* Construct an isl_ast_expr that evaluates the conditions defining "set".
+ * The result is simplified in terms of build->domain.
+ *
+ * If "set" is an (obviously) empty set, then return the expression "0".
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *set)
+{
+	struct isl_expr_from_set_data data = { build, 1, NULL };
+
+	if (isl_set_foreach_basic_set(set, &expr_from_set, &data) < 0)
+		data.res = isl_ast_expr_free(data.res);
+	else if (data.first) {
+		isl_ctx *ctx = isl_ast_build_get_ctx(build);
+		data.res = isl_ast_expr_from_val(isl_val_zero(ctx));
+	}
+
+	isl_set_free(set);
+	return data.res;
+}
+
+struct isl_from_pw_aff_data {
+	isl_ast_build *build;
+	int n;
+	isl_ast_expr **next;
+	isl_set *dom;
+};
+
+/* This function is called during the construction of an isl_ast_expr
+ * that evaluates an isl_pw_aff.
+ * Adjust data->next to take into account this piece.
+ *
+ * data->n is the number of pairs of set and aff to go.
+ * data->dom is the domain of the entire isl_pw_aff.
+ *
+ * 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
+ * that will be filled in by later calls otherwise.
+ *
+ * In both cases, the constraints of "set" are added to the generated
+ * constraints of the build such that they can be exploited to simplify
+ * the AST expression constructed from "aff".
+ */
+static int ast_expr_from_pw_aff(__isl_take isl_set *set,
+	__isl_take isl_aff *aff, void *user)
+{
+	struct isl_from_pw_aff_data *data = user;
+	isl_ctx *ctx;
+	isl_ast_build *build;
+
+	ctx = isl_set_get_ctx(set);
+	data->n--;
+	if (data->n == 0) {
+		build = isl_ast_build_copy(data->build);
+		build = isl_ast_build_restrict_generated(build, set);
+		*data->next = isl_ast_expr_from_aff(aff, build);
+		isl_ast_build_free(build);
+		if (!*data->next)
+			return -1;
+	} else {
+		isl_ast_expr *ternary, *arg;
+		isl_set *gist;
+
+		ternary = isl_ast_expr_alloc_op(ctx, isl_ast_op_select, 3);
+		gist = isl_set_gist(isl_set_copy(set), isl_set_copy(data->dom));
+		arg = isl_ast_build_expr_from_set(data->build, gist);
+		ternary = isl_ast_expr_set_op_arg(ternary, 0, arg);
+		build = isl_ast_build_copy(data->build);
+		build = isl_ast_build_restrict_generated(build, set);
+		arg = isl_ast_expr_from_aff(aff, build);
+		isl_ast_build_free(build);
+		ternary = isl_ast_expr_set_op_arg(ternary, 1, arg);
+		if (!ternary)
+			return -1;
+
+		*data->next = ternary;
+		data->next = &ternary->u.op.args[2];
+	}
+
+	return 0;
+}
+
+/* Construct an isl_ast_expr that evaluates "pa".
+ * The result is simplified in terms of build->domain.
+ *
+ * The domain of "pa" lives in the internal schedule space.
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff_internal(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
+{
+	struct isl_from_pw_aff_data data;
+	isl_ast_expr *res = NULL;
+
+	pa = isl_ast_build_compute_gist_pw_aff(build, pa);
+	pa = isl_pw_aff_coalesce(pa);
+	if (!pa)
+		return NULL;
+
+	data.build = build;
+	data.n = isl_pw_aff_n_piece(pa);
+	data.next = &res;
+	data.dom = isl_pw_aff_domain(isl_pw_aff_copy(pa));
+
+	if (isl_pw_aff_foreach_piece(pa, &ast_expr_from_pw_aff, &data) < 0)
+		res = isl_ast_expr_free(res);
+	else if (!res)
+		isl_die(isl_pw_aff_get_ctx(pa), isl_error_invalid,
+			"cannot handle void expression", res = NULL);
+
+	isl_pw_aff_free(pa);
+	isl_set_free(data.dom);
+	return res;
+}
+
+/* Construct an isl_ast_expr that evaluates "pa".
+ * The result is simplified in terms of build->domain.
+ *
+ * The domain of "pa" lives in the external schedule space.
+ */
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa)
+{
+	isl_ast_expr *expr;
+
+	if (isl_ast_build_need_schedule_map(build)) {
+		isl_multi_aff *ma;
+		ma = isl_ast_build_get_schedule_map_multi_aff(build);
+		pa = isl_pw_aff_pullback_multi_aff(pa, ma);
+	}
+	expr = isl_ast_build_expr_from_pw_aff_internal(build, pa);
+	return expr;
+}
+
+/* Set the ids of the input dimensions of "mpa" to the iterator ids
+ * of "build".
+ *
+ * The domain of "mpa" is assumed to live in the internal schedule domain.
+ */
+static __isl_give isl_multi_pw_aff *set_iterator_names(
+	__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
+{
+	int i, n;
+
+	n = isl_multi_pw_aff_dim(mpa, isl_dim_in);
+	for (i = 0; i < n; ++i) {
+		isl_id *id;
+
+		id = isl_ast_build_get_iterator_id(build, i);
+		mpa = isl_multi_pw_aff_set_dim_id(mpa, isl_dim_in, i, id);
+	}
+
+	return mpa;
+}
+
+/* Construct an isl_ast_expr of type "type" with as first argument "arg0" and
+ * the remaining arguments derived from "mpa".
+ * That is, construct a call or access expression that calls/accesses "arg0"
+ * with arguments/indices specified by "mpa".
+ */
+static __isl_give isl_ast_expr *isl_ast_build_with_arguments(
+	__isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+	__isl_take isl_ast_expr *arg0, __isl_take isl_multi_pw_aff *mpa)
+{
+	int i, n;
+	isl_ctx *ctx;
+	isl_ast_expr *expr;
+
+	ctx = isl_ast_build_get_ctx(build);
+
+	n = isl_multi_pw_aff_dim(mpa, isl_dim_out);
+	expr = isl_ast_expr_alloc_op(ctx, type, 1 + n);
+	expr = isl_ast_expr_set_op_arg(expr, 0, arg0);
+	for (i = 0; i < n; ++i) {
+		isl_pw_aff *pa;
+		isl_ast_expr *arg;
+
+		pa = isl_multi_pw_aff_get_pw_aff(mpa, i);
+		arg = isl_ast_build_expr_from_pw_aff_internal(build, pa);
+		expr = isl_ast_expr_set_op_arg(expr, 1 + i, arg);
+	}
+
+	isl_multi_pw_aff_free(mpa);
+	return expr;
+}
+
+static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_internal(
+	__isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+	__isl_take isl_multi_pw_aff *mpa);
+
+/* Construct an isl_ast_expr that accesses the member specified by "mpa".
+ * The range of "mpa" is assumed to be wrapped relation.
+ * The domain of this wrapped relation specifies the structure being
+ * accessed, while the range of this wrapped relation spacifies the
+ * member of the structure being accessed.
+ *
+ * The domain of "mpa" is assumed to live in the internal schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_member(
+	__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
+{
+	isl_id *id;
+	isl_multi_pw_aff *domain;
+	isl_ast_expr *domain_expr, *expr;
+	enum isl_ast_op_type type = isl_ast_op_access;
+
+	domain = isl_multi_pw_aff_copy(mpa);
+	domain = isl_multi_pw_aff_range_factor_domain(domain);
+	domain_expr = isl_ast_build_from_multi_pw_aff_internal(build,
+								type, domain);
+	mpa = isl_multi_pw_aff_range_factor_range(mpa);
+	if (!isl_multi_pw_aff_has_tuple_id(mpa, isl_dim_out))
+		isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
+			"missing field name", goto error);
+	id = isl_multi_pw_aff_get_tuple_id(mpa, isl_dim_out);
+	expr = isl_ast_expr_from_id(id);
+	expr = isl_ast_expr_alloc_binary(isl_ast_op_member, domain_expr, expr);
+	return isl_ast_build_with_arguments(build, type, expr, mpa);
+error:
+	isl_multi_pw_aff_free(mpa);
+	return NULL;
+}
+
+/* Construct an isl_ast_expr of type "type" that calls or accesses
+ * the element specified by "mpa".
+ * The first argument is obtained from the output tuple name.
+ * The remaining arguments are given by the piecewise affine expressions.
+ *
+ * If the range of "mpa" is a mapped relation, then we assume it
+ * represents an access to a member of a structure.
+ *
+ * The domain of "mpa" is assumed to live in the internal schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff_internal(
+	__isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+	__isl_take isl_multi_pw_aff *mpa)
+{
+	isl_ctx *ctx;
+	isl_id *id;
+	isl_ast_expr *expr;
+
+	if (!mpa)
+		goto error;
+
+	if (type == isl_ast_op_access &&
+	    isl_multi_pw_aff_range_is_wrapping(mpa))
+		return isl_ast_build_from_multi_pw_aff_member(build, mpa);
+
+	mpa = set_iterator_names(build, mpa);
+	if (!build || !mpa)
+		goto error;
+
+	ctx = isl_ast_build_get_ctx(build);
+
+	if (isl_multi_pw_aff_has_tuple_id(mpa, isl_dim_out))
+		id = isl_multi_pw_aff_get_tuple_id(mpa, isl_dim_out);
+	else
+		id = isl_id_alloc(ctx, "", NULL);
+
+	expr = isl_ast_expr_from_id(id);
+	return isl_ast_build_with_arguments(build, type, expr, mpa);
+error:
+	isl_multi_pw_aff_free(mpa);
+	return NULL;
+}
+
+/* Construct an isl_ast_expr of type "type" that calls or accesses
+ * the element specified by "pma".
+ * The first argument is obtained from the output tuple name.
+ * The remaining arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "pma" is assumed to live in the internal schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_from_pw_multi_aff_internal(
+	__isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+	__isl_take isl_pw_multi_aff *pma)
+{
+	isl_multi_pw_aff *mpa;
+
+	mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
+	return isl_ast_build_from_multi_pw_aff_internal(build, type, mpa);
+}
+
+/* Construct an isl_ast_expr of type "type" that calls or accesses
+ * the element specified by "mpa".
+ * The first argument is obtained from the output tuple name.
+ * The remaining arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "mpa" is assumed to live in the external schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_from_multi_pw_aff(
+	__isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+	__isl_take isl_multi_pw_aff *mpa)
+{
+	int is_domain;
+	isl_ast_expr *expr;
+	isl_space *space_build, *space_mpa;
+
+	space_build = isl_ast_build_get_space(build, 0);
+	space_mpa = isl_multi_pw_aff_get_space(mpa);
+	is_domain = isl_space_tuple_is_equal(space_build, isl_dim_set,
+					space_mpa, isl_dim_in);
+	isl_space_free(space_build);
+	isl_space_free(space_mpa);
+	if (is_domain < 0)
+		goto error;
+	if (!is_domain)
+		isl_die(isl_ast_build_get_ctx(build), isl_error_invalid,
+			"spaces don't match", goto error);
+
+	if (isl_ast_build_need_schedule_map(build)) {
+		isl_multi_aff *ma;
+		ma = isl_ast_build_get_schedule_map_multi_aff(build);
+		mpa = isl_multi_pw_aff_pullback_multi_aff(mpa, ma);
+	}
+
+	expr = isl_ast_build_from_multi_pw_aff_internal(build, type, mpa);
+	return expr;
+error:
+	isl_multi_pw_aff_free(mpa);
+	return NULL;
+}
+
+/* Construct an isl_ast_expr that calls the domain element specified by "mpa".
+ * The name of the function is obtained from the output tuple name.
+ * The arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "mpa" is assumed to live in the external schedule domain.
+ */
+__isl_give isl_ast_expr *isl_ast_build_call_from_multi_pw_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
+{
+	return isl_ast_build_from_multi_pw_aff(build, isl_ast_op_call, mpa);
+}
+
+/* Construct an isl_ast_expr that accesses the array element specified by "mpa".
+ * The name of the array is obtained from the output tuple name.
+ * The index expressions are given by the piecewise affine expressions.
+ *
+ * The domain of "mpa" is assumed to live in the external schedule domain.
+ */
+__isl_give isl_ast_expr *isl_ast_build_access_from_multi_pw_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_multi_pw_aff *mpa)
+{
+	return isl_ast_build_from_multi_pw_aff(build, isl_ast_op_access, mpa);
+}
+
+/* Construct an isl_ast_expr of type "type" that calls or accesses
+ * the element specified by "pma".
+ * The first argument is obtained from the output tuple name.
+ * The remaining arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "pma" is assumed to live in the external schedule domain.
+ */
+static __isl_give isl_ast_expr *isl_ast_build_from_pw_multi_aff(
+	__isl_keep isl_ast_build *build, enum isl_ast_op_type type,
+	__isl_take isl_pw_multi_aff *pma)
+{
+	isl_multi_pw_aff *mpa;
+
+	mpa = isl_multi_pw_aff_from_pw_multi_aff(pma);
+	return isl_ast_build_from_multi_pw_aff(build, type, mpa);
+}
+
+/* Construct an isl_ast_expr that calls the domain element specified by "pma".
+ * The name of the function is obtained from the output tuple name.
+ * The arguments are given by the piecewise affine expressions.
+ *
+ * The domain of "pma" is assumed to live in the external schedule domain.
+ */
+__isl_give isl_ast_expr *isl_ast_build_call_from_pw_multi_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
+{
+	return isl_ast_build_from_pw_multi_aff(build, isl_ast_op_call, pma);
+}
+
+/* Construct an isl_ast_expr that accesses the array element specified by "pma".
+ * The name of the array is obtained from the output tuple name.
+ * The index expressions are given by the piecewise affine expressions.
+ *
+ * The domain of "pma" is assumed to live in the external schedule domain.
+ */
+__isl_give isl_ast_expr *isl_ast_build_access_from_pw_multi_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma)
+{
+	return isl_ast_build_from_pw_multi_aff(build, isl_ast_op_access, pma);
+}
+
+/* Construct an isl_ast_expr that calls the domain element
+ * specified by "executed".
+ *
+ * "executed" is assumed to be single-valued, with a domain that lives
+ * in the internal schedule space.
+ */
+__isl_give isl_ast_node *isl_ast_build_call_from_executed(
+	__isl_keep isl_ast_build *build, __isl_take isl_map *executed)
+{
+	isl_pw_multi_aff *iteration;
+	isl_ast_expr *expr;
+
+	iteration = isl_pw_multi_aff_from_map(executed);
+	iteration = isl_ast_build_compute_gist_pw_multi_aff(build, iteration);
+	iteration = isl_pw_multi_aff_intersect_domain(iteration,
+					isl_ast_build_get_domain(build));
+	expr = isl_ast_build_from_pw_multi_aff_internal(build, isl_ast_op_call,
+							iteration);
+	return isl_ast_node_alloc_user(expr);
+}

Added: polly/trunk/lib/External/isl/isl_ast_build_expr.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_ast_build_expr.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_build_expr.h (added)
+++ polly/trunk/lib/External/isl/isl_ast_build_expr.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,22 @@
+#ifndef ISL_AST_BUILD_EXPR_PRIVATE_H
+#define ISL_AST_BUILD_EXPR_PRIVATE_H
+
+#include <isl/ast.h>
+#include <isl/ast_build.h>
+
+__isl_give isl_ast_expr *isl_ast_build_expr_from_basic_set(
+	 __isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
+__isl_give isl_ast_expr *isl_ast_build_expr_from_set(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *set);
+
+__isl_give isl_ast_expr *isl_ast_build_expr_from_pw_aff_internal(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa);
+__isl_give isl_ast_expr *isl_ast_expr_from_aff(__isl_take isl_aff *aff,
+	__isl_keep isl_ast_build *build);
+__isl_give isl_ast_expr *isl_ast_expr_set_op_arg(__isl_take isl_ast_expr *expr,
+	int pos, __isl_take isl_ast_expr *arg);
+
+__isl_give isl_ast_node *isl_ast_build_call_from_executed(
+	__isl_keep isl_ast_build *build, __isl_take isl_map *executed);
+
+#endif

Added: polly/trunk/lib/External/isl/isl_ast_build_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_ast_build_private.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_build_private.h (added)
+++ polly/trunk/lib/External/isl/isl_ast_build_private.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,267 @@
+#ifndef ISL_AST_BUILD_PRIVATE_H
+#define ISL_AST_BUILD_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/ast.h>
+#include <isl/ast_build.h>
+#include <isl/set.h>
+#include <isl/list.h>
+
+enum isl_ast_build_domain_type {
+	atomic,
+	unroll,
+	separate
+};
+
+/* An isl_ast_build represents the context in which AST is being
+ * generated.  That is, it (mostly) contains information about outer
+ * loops that can be used to simplify inner loops.
+ *
+ * "domain" represents constraints on the internal schedule domain,
+ * corresponding to the context of the AST generation and the constraints
+ * implied by the loops that have already been generated.
+ * When an isl_ast_build is first created, outside any AST generation,
+ * the domain is typically a parameter set.  It is only when a AST
+ * generation phase is initiated that the domain of the isl_ast_build
+ * is changed to refer to the internal schedule domain.
+ * The domain then lives in a space of the form
+ *
+ *	S
+ *
+ *  or
+ *
+ *	[O -> S]
+ *
+ * O represents the loops generated in outer AST generations.
+ * S represents the loops (both generated and to be generated)
+ * of the current AST generation.
+ * Both include eliminated loops.
+ * "domain" is expected not to have any unknown divs because
+ * it is used as the context argument in a call to isl_basic_set_gist
+ * in isl_ast_build_compute_gist_basic_set.
+ *
+ * "depth" is equal to the number of loops that have already
+ * been generated (including those in outer AST generations).
+ * "outer_pos" is equal to the number of loops in outer AST generations.
+ *
+ * "generated" is a superset of "domain" corresponding to those
+ * constraints that were either given by the user or that have
+ * effectively been generated (as bounds on a for loop).
+ *
+ * "pending" is a superset of "domain" corresponding to the constraints
+ * that still need to be generated (as guards), but that may end up
+ * not getting generated if they are implied by any constraints
+ * enforced by inner loops.
+ *
+ * "strides" contains the stride of each loop.  The number of elements
+ * is equal to the number of dimensions in "domain".
+ * "offsets" constains the offsets of strided loops.  If s is the stride
+ * for a given dimension and f is the corresponding offset, then the
+ * dimension takes on values
+ *
+ *	f + s a
+ *
+ * with a an integer.  For non-strided loops, the offset is zero.
+ *
+ * "iterators" contains the loop iterators of both generated and
+ * to be generated loops.  The number of elements is at least as
+ * large as the dimension of the internal schedule domain.  The
+ * number may be larger, in which case the additional ids can be
+ * used in a nested AST generation should the schedule be non-injective.
+ *
+ * "values" lives in the space
+ *
+ *	[O -> S] -> [O -> S]		(or S -> S)
+ *
+ * and expresses (if possible) loop iterators in terms of parameters
+ * and outer loop iterators.  If the value of a given loop iterator
+ * cannot be expressed as an affine expression (either because the iterator
+ * attains multiple values or because the single value is a piecewise
+ * affine expression), then it is expressed in "values" as being equal
+ * to itself.
+ *
+ * "value" is the value of the loop iterator at the current depth.
+ * It is NULL if it has not been computed yet or if the value of the
+ * given loop iterator cannot be expressed as a piecewise affine expression
+ * (because the iterator attains multiple values).
+ *
+ * "schedule_map" maps the internal schedule domain to the external schedule
+ * domain.  It may be NULL if it hasn't been computed yet.
+ * See isl_ast_build_get_schedule_map_multi_aff.
+ *
+ * The "create_leaf" callback is called for every leaf in the generated AST.
+ * The callback is responsible for creating the node to be placed at those
+ * leaves.  If this callback is not set, then isl will generated user
+ * nodes with call expressions corresponding to an element of the domain.
+ *
+ * The "at_each_domain" callback is called on every node created to represent
+ * an element of the domain.  Each of these nodes is a user node
+ * with as expression a call expression.
+ *
+ * The "before_each_for" callback is called on each for node before
+ * its children have been created.
+ *
+ * The "after_each_for" callback is called on each for node after
+ * its children have been created.
+ *
+ * "executed" contains the inverse schedule at this point
+ * of the AST generation.
+ * It is currently only used in isl_ast_build_get_schedule, which is
+ * in turn only used by user code from within a callback.
+ * The value is set right before we may be calling such a callback.
+ *
+ * "single_valued" is set if the current inverse schedule (which may or may
+ * not be stored in "executed") is known to be single valued, specifically
+ * an inverse schedule that was not (appeared not to be) single valued
+ * is extended to a single valued inverse schedule.  This is mainly used
+ * to avoid an infinite recursion when we fail to detect later on that
+ * the extended inverse schedule is single valued.
+ */
+struct isl_ast_build {
+	int ref;
+
+	int outer_pos;
+	int depth;
+
+	isl_id_list *iterators;
+
+	isl_set *domain;
+	isl_set *generated;
+	isl_set *pending;
+	isl_multi_aff *values;
+
+	isl_pw_aff *value;
+
+	isl_vec *strides;
+	isl_multi_aff *offsets;
+
+	isl_multi_aff *schedule_map;
+
+	isl_union_map *options;
+
+	__isl_give isl_ast_node *(*at_each_domain)(
+		__isl_take isl_ast_node *node,
+		__isl_keep isl_ast_build *build, void *user);
+	void *at_each_domain_user;
+
+	__isl_give isl_id *(*before_each_for)(
+		__isl_keep isl_ast_build *context, void *user);
+	void *before_each_for_user;
+	__isl_give isl_ast_node *(*after_each_for)(
+		__isl_take isl_ast_node *node,
+		__isl_keep isl_ast_build *context, void *user);
+	void *after_each_for_user;
+
+	__isl_give isl_ast_node *(*create_leaf)(
+		__isl_take isl_ast_build *build, void *user);
+	void *create_leaf_user;
+
+	isl_union_map *executed;
+	int single_valued;
+};
+
+__isl_give isl_ast_build *isl_ast_build_clear_local_info(
+	__isl_take isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_increase_depth(
+	__isl_take isl_ast_build *build);
+int isl_ast_build_get_depth(__isl_keep isl_ast_build *build);
+unsigned isl_ast_build_dim(__isl_keep isl_ast_build *build,
+	enum isl_dim_type type);
+__isl_give isl_space *isl_ast_build_get_space(
+	__isl_keep isl_ast_build *build, int internal);
+__isl_give isl_ast_build *isl_ast_build_align_params(
+	__isl_take isl_ast_build *build, __isl_take isl_space *model);
+__isl_give isl_ast_build *isl_ast_build_cow(
+	__isl_take isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_insert_dim(
+	__isl_take isl_ast_build *build, int pos);
+__isl_give isl_ast_build *isl_ast_build_scale_down(
+	__isl_take isl_ast_build *build, __isl_take isl_val *m,
+	__isl_take isl_union_map *umap);
+__isl_give isl_ast_build *isl_ast_build_product(
+	__isl_take isl_ast_build *build, __isl_take isl_space *embedding);
+__isl_give isl_ast_build *isl_ast_build_set_loop_bounds(
+	__isl_take isl_ast_build *build, __isl_take isl_basic_set *bounds);
+__isl_give isl_ast_build *isl_ast_build_detect_strides(
+	__isl_take isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_ast_build *isl_ast_build_include_stride(
+	__isl_take isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_set_executed(
+	__isl_take isl_ast_build *build,
+	__isl_take isl_union_map *executed);
+__isl_give isl_ast_build *isl_ast_build_set_single_valued(
+	__isl_take isl_ast_build *build, int sv);
+__isl_give isl_set *isl_ast_build_get_domain(
+	__isl_keep isl_ast_build *build);
+__isl_give isl_set *isl_ast_build_get_pending(
+	__isl_keep isl_ast_build *build);
+__isl_give isl_set *isl_ast_build_get_generated(
+	__isl_keep isl_ast_build *build);
+__isl_give isl_ast_build *isl_ast_build_restrict_generated(
+	__isl_take isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_ast_build *isl_ast_build_replace_pending_by_guard(
+	__isl_take isl_ast_build *build, __isl_take isl_set *guard);
+__isl_give isl_ast_build *isl_ast_build_restrict_pending(
+	__isl_take isl_ast_build *build, __isl_take isl_set *set);
+__isl_give int isl_ast_build_need_schedule_map(
+	__isl_keep isl_ast_build *build);
+__isl_give isl_multi_aff *isl_ast_build_get_schedule_map_multi_aff(
+	__isl_keep isl_ast_build *build);
+__isl_give isl_map *isl_ast_build_get_schedule_map(
+	__isl_keep isl_ast_build *build);
+int isl_ast_build_has_affine_value(__isl_keep isl_ast_build *build, int pos);
+int isl_ast_build_has_value(__isl_keep isl_ast_build *build);
+__isl_give isl_id *isl_ast_build_get_iterator_id(
+	__isl_keep isl_ast_build *build, int pos);
+
+__isl_give isl_basic_set *isl_ast_build_compute_gist_basic_set(
+	__isl_keep isl_ast_build *build, __isl_take isl_basic_set *bset);
+__isl_give isl_set *isl_ast_build_specialize(__isl_keep isl_ast_build *build,
+	__isl_take isl_set *set);
+__isl_give isl_set *isl_ast_build_compute_gist(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_map *isl_ast_build_compute_gist_map_domain(
+	__isl_keep isl_ast_build *build, __isl_take isl_map *map);
+__isl_give isl_aff *isl_ast_build_compute_gist_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_aff *aff);
+__isl_give isl_pw_aff *isl_ast_build_compute_gist_pw_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_aff *pa);
+__isl_give isl_pw_multi_aff *isl_ast_build_compute_gist_pw_multi_aff(
+	__isl_keep isl_ast_build *build, __isl_take isl_pw_multi_aff *pma);
+
+__isl_give isl_union_map *isl_ast_build_substitute_values_union_map_domain(
+	__isl_keep isl_ast_build *build, __isl_take isl_union_map *umap);
+
+int isl_ast_build_aff_is_nonneg(__isl_keep isl_ast_build *build,
+	__isl_keep isl_aff *aff);
+
+int isl_ast_build_has_stride(__isl_keep isl_ast_build *build, int pos);
+__isl_give isl_aff *isl_ast_build_get_offset(__isl_keep isl_ast_build *build,
+	int pos);
+__isl_give isl_val *isl_ast_build_get_stride(__isl_keep isl_ast_build *build,
+	int pos);
+__isl_give isl_set *isl_ast_build_get_stride_constraint(
+	__isl_keep isl_ast_build *build);
+__isl_give isl_multi_aff *isl_ast_build_get_stride_expansion(
+	__isl_keep isl_ast_build *build);
+
+void isl_ast_build_dump(__isl_keep isl_ast_build *build);
+
+__isl_give isl_set *isl_ast_build_get_option_domain(
+	__isl_keep isl_ast_build *build,
+	enum isl_ast_build_domain_type type);
+__isl_give isl_map *isl_ast_build_get_separation_class(
+	__isl_keep isl_ast_build *build);
+__isl_give isl_set *isl_ast_build_eliminate(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *domain);
+__isl_give isl_set *isl_ast_build_eliminate_inner(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *set);
+__isl_give isl_set *isl_ast_build_eliminate_divs(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *set);
+
+__isl_give isl_map *isl_ast_build_map_to_iterator(
+	__isl_keep isl_ast_build *build, __isl_take isl_set *set);
+
+int isl_ast_build_options_involve_depth(__isl_keep isl_ast_build *build);
+
+#endif

Added: 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=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_codegen.c (added)
+++ polly/trunk/lib/External/isl/isl_ast_codegen.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,3921 @@
+/*
+ * 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 <limits.h>
+#include <isl/aff.h>
+#include <isl/set.h>
+#include <isl/ilp.h>
+#include <isl/union_map.h>
+#include <isl_sort.h>
+#include <isl_tarjan.h>
+#include <isl_ast_private.h>
+#include <isl_ast_build_expr.h>
+#include <isl_ast_build_private.h>
+#include <isl_ast_graft_private.h>
+
+/* Data used in generate_domain.
+ *
+ * "build" is the input build.
+ * "list" collects the results.
+ */
+struct isl_generate_domain_data {
+	isl_ast_build *build;
+
+	isl_ast_graft_list *list;
+};
+
+static __isl_give isl_ast_graft_list *generate_next_level(
+	__isl_take isl_union_map *executed,
+	__isl_take isl_ast_build *build);
+static __isl_give isl_ast_graft_list *generate_code(
+	__isl_take isl_union_map *executed, __isl_take isl_ast_build *build,
+	int internal);
+
+/* Generate an AST for a single domain based on
+ * the (non single valued) inverse schedule "executed".
+ *
+ * We extend the schedule with the iteration domain
+ * and continue generating through a call to generate_code.
+ *
+ * In particular, if executed has the form
+ *
+ *	S -> D
+ *
+ * then we continue generating code on
+ *
+ *	[S -> D] -> D
+ *
+ * The extended inverse schedule is clearly single valued
+ * ensuring that the nested generate_code will not reach this function,
+ * but will instead create calls to all elements of D that need
+ * to be executed from the current schedule domain.
+ */
+static int generate_non_single_valued(__isl_take isl_map *executed,
+	struct isl_generate_domain_data *data)
+{
+	isl_map *identity;
+	isl_ast_build *build;
+	isl_ast_graft_list *list;
+
+	build = isl_ast_build_copy(data->build);
+
+	identity = isl_set_identity(isl_map_range(isl_map_copy(executed)));
+	executed = isl_map_domain_product(executed, identity);
+	build = isl_ast_build_set_single_valued(build, 1);
+
+	list = generate_code(isl_union_map_from_map(executed), build, 1);
+
+	data->list = isl_ast_graft_list_concat(data->list, list);
+
+	return 0;
+}
+
+/* Call the at_each_domain callback, if requested by the user,
+ * after recording the current inverse schedule in the build.
+ */
+static __isl_give isl_ast_graft *at_each_domain(__isl_take isl_ast_graft *graft,
+	__isl_keep isl_map *executed, __isl_keep isl_ast_build *build)
+{
+	if (!graft || !build)
+		return isl_ast_graft_free(graft);
+	if (!build->at_each_domain)
+		return graft;
+
+	build = isl_ast_build_copy(build);
+	build = isl_ast_build_set_executed(build,
+			isl_union_map_from_map(isl_map_copy(executed)));
+	if (!build)
+		return isl_ast_graft_free(graft);
+
+	graft->node = build->at_each_domain(graft->node,
+					build, build->at_each_domain_user);
+	isl_ast_build_free(build);
+
+	if (!graft->node)
+		graft = isl_ast_graft_free(graft);
+
+	return graft;
+}
+
+/* Generate an AST for a single domain based on
+ * the inverse schedule "executed" and add it to data->list.
+ *
+ * If there is more than one domain element associated to the current
+ * schedule "time", then we need to continue the generation process
+ * in generate_non_single_valued.
+ * Note that the inverse schedule being single-valued may depend
+ * on constraints that are only available in the original context
+ * domain specified by the user.  We therefore first introduce
+ * some of the constraints of data->build->domain.  In particular,
+ * we intersect with a single-disjunct approximation of this set.
+ * We perform this approximation to avoid further splitting up
+ * the executed relation, possibly introducing a disjunctive guard
+ * on the statement.
+ *
+ * On the other hand, we only perform the test after having taken the gist
+ * of the domain as the resulting map is the one from which the call
+ * expression is constructed.  Using this map to construct the call
+ * expression usually yields simpler results.
+ * Because we perform the single-valuedness test on the gisted map,
+ * we may in rare cases fail to recognize that the inverse schedule
+ * is single-valued.  This becomes problematic if this happens
+ * from the recursive call through generate_non_single_valued
+ * as we would then end up in an infinite recursion.
+ * We therefore check if we are inside a call to generate_non_single_valued
+ * and revert to the ungisted map if the gisted map turns out not to be
+ * single-valued.
+ *
+ * Otherwise, we generate a call expression for the single executed
+ * domain element and put a guard around it based on the (simplified)
+ * domain of "executed".
+ *
+ * At this stage, any pending constraints in the build can no longer
+ * be simplified with respect to any enforced constraints since
+ * the call node does not have any enforced constraints.
+ * We therefore turn all pending constraints into guards
+ * (after simplifying them with respect to the already generated
+ * constraints) and add them to both the generated constraints
+ * and the guard of the constructed graft.  This guard will ensure
+ * that the constraints are effectively generated.
+ *
+ * If the user has set an at_each_domain callback, it is called
+ * on the constructed call expression node.
+ */
+static int generate_domain(__isl_take isl_map *executed, void *user)
+{
+	struct isl_generate_domain_data *data = user;
+	isl_ast_build *build;
+	isl_ast_graft *graft;
+	isl_ast_graft_list *list;
+	isl_set *guard, *domain;
+	isl_map *map = NULL;
+	int empty, sv;
+
+	domain = isl_ast_build_get_domain(data->build);
+	domain = isl_set_from_basic_set(isl_set_simple_hull(domain));
+	executed = isl_map_intersect_domain(executed, domain);
+	empty = isl_map_is_empty(executed);
+	if (empty < 0)
+		goto error;
+	if (empty) {
+		isl_map_free(executed);
+		return 0;
+	}
+
+	executed = isl_map_coalesce(executed);
+	map = isl_map_copy(executed);
+	map = isl_ast_build_compute_gist_map_domain(data->build, map);
+	sv = isl_map_is_single_valued(map);
+	if (sv < 0)
+		goto error;
+	if (!sv) {
+		isl_map_free(map);
+		if (data->build->single_valued)
+			map = isl_map_copy(executed);
+		else
+			return generate_non_single_valued(executed, data);
+	}
+	guard = isl_map_domain(isl_map_copy(map));
+	guard = isl_set_compute_divs(guard);
+	guard = isl_set_intersect(guard,
+				    isl_ast_build_get_pending(data->build));
+	guard = isl_set_coalesce(guard);
+	guard = isl_ast_build_specialize(data->build, guard);
+	guard = isl_set_gist(guard, isl_ast_build_get_generated(data->build));
+
+	build = isl_ast_build_copy(data->build);
+	build = isl_ast_build_replace_pending_by_guard(build,
+							isl_set_copy(guard));
+	graft = isl_ast_graft_alloc_domain(map, build);
+	graft = at_each_domain(graft, executed, build);
+	isl_ast_build_free(build);
+	isl_map_free(executed);
+	graft = isl_ast_graft_add_guard(graft, guard, data->build);
+
+	list = isl_ast_graft_list_from_ast_graft(graft);
+	data->list = isl_ast_graft_list_concat(data->list, list);
+
+	return 0;
+error:
+	isl_map_free(map);
+	isl_map_free(executed);
+	return -1;
+}
+
+/* Call build->create_leaf to a create "leaf" node in the AST,
+ * encapsulate the result in an isl_ast_graft and return the result
+ * as a 1-element list.
+ *
+ * Note that the node returned by the user may be an entire tree.
+ *
+ * Since the node itself cannot enforce any constraints, we turn
+ * all pending constraints into guards and add them to the resulting
+ * graft to ensure that they will be generated.
+ *
+ * Before we pass control to the user, we first clear some information
+ * from the build that is (presumbably) only meaningful
+ * for the current code generation.
+ * This includes the create_leaf callback itself, so we make a copy
+ * of the build first.
+ */
+static __isl_give isl_ast_graft_list *call_create_leaf(
+	__isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+	isl_set *guard;
+	isl_ast_node *node;
+	isl_ast_graft *graft;
+	isl_ast_build *user_build;
+
+	guard = isl_ast_build_get_pending(build);
+	user_build = isl_ast_build_copy(build);
+	user_build = isl_ast_build_replace_pending_by_guard(user_build,
+							isl_set_copy(guard));
+	user_build = isl_ast_build_set_executed(user_build, executed);
+	user_build = isl_ast_build_clear_local_info(user_build);
+	if (!user_build)
+		node = NULL;
+	else
+		node = build->create_leaf(user_build, build->create_leaf_user);
+	graft = isl_ast_graft_alloc(node, build);
+	graft = isl_ast_graft_add_guard(graft, guard, build);
+	isl_ast_build_free(build);
+	return isl_ast_graft_list_from_ast_graft(graft);
+}
+
+/* Generate an AST after having handled the complete schedule
+ * of this call to the code generator.
+ *
+ * If the user has specified a create_leaf callback, control
+ * is passed to the user in call_create_leaf.
+ *
+ * Otherwise, we generate one or more calls for each individual
+ * domain in generate_domain.
+ */
+static __isl_give isl_ast_graft_list *generate_inner_level(
+	__isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	struct isl_generate_domain_data data = { build };
+
+	if (!build || !executed)
+		goto error;
+
+	if (build->create_leaf)
+		return call_create_leaf(executed, build);
+
+	ctx = isl_union_map_get_ctx(executed);
+	data.list = isl_ast_graft_list_alloc(ctx, 0);
+	if (isl_union_map_foreach_map(executed, &generate_domain, &data) < 0)
+		data.list = isl_ast_graft_list_free(data.list);
+
+	if (0)
+error:		data.list = NULL;
+	isl_ast_build_free(build);
+	isl_union_map_free(executed);
+	return data.list;
+}
+
+/* Call the before_each_for callback, if requested by the user.
+ */
+static __isl_give isl_ast_node *before_each_for(__isl_take isl_ast_node *node,
+	__isl_keep isl_ast_build *build)
+{
+	isl_id *id;
+
+	if (!node || !build)
+		return isl_ast_node_free(node);
+	if (!build->before_each_for)
+		return node;
+	id = build->before_each_for(build, build->before_each_for_user);
+	node = isl_ast_node_set_annotation(node, id);
+	return node;
+}
+
+/* Call the after_each_for callback, if requested by the user.
+ */
+static __isl_give isl_ast_graft *after_each_for(__isl_take isl_ast_graft *graft,
+	__isl_keep isl_ast_build *build)
+{
+	if (!graft || !build)
+		return isl_ast_graft_free(graft);
+	if (!build->after_each_for)
+		return graft;
+	graft->node = build->after_each_for(graft->node, build,
+						build->after_each_for_user);
+	if (!graft->node)
+		return isl_ast_graft_free(graft);
+	return graft;
+}
+
+/* Plug in all the know values of the current and outer dimensions
+ * in the domain of "executed".  In principle, we only need to plug
+ * in the known value of the current dimension since the values of
+ * outer dimensions have been plugged in already.
+ * However, it turns out to be easier to just plug in all known values.
+ */
+static __isl_give isl_union_map *plug_in_values(
+	__isl_take isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+	return isl_ast_build_substitute_values_union_map_domain(build,
+								    executed);
+}
+
+/* Check if the constraint "c" is a lower bound on dimension "pos",
+ * an upper bound, or independent of dimension "pos".
+ */
+static int constraint_type(isl_constraint *c, int pos)
+{
+	if (isl_constraint_is_lower_bound(c, isl_dim_set, pos))
+		return 1;
+	if (isl_constraint_is_upper_bound(c, isl_dim_set, pos))
+		return 2;
+	return 0;
+}
+
+/* Compare the types of the constraints "a" and "b",
+ * resulting in constraints that are independent of "depth"
+ * to be sorted before the lower bounds on "depth", which in
+ * turn are sorted before the upper bounds on "depth".
+ */
+static int cmp_constraint(__isl_keep isl_constraint *a,
+	__isl_keep isl_constraint *b, void *user)
+{
+	int *depth = user;
+	int t1 = constraint_type(a, *depth);
+	int t2 = constraint_type(b, *depth);
+
+	return t1 - t2;
+}
+
+/* Extract a lower bound on dimension "pos" from constraint "c".
+ *
+ * If the constraint is of the form
+ *
+ *	a x + f(...) >= 0
+ *
+ * then we essentially return
+ *
+ *	l = ceil(-f(...)/a)
+ *
+ * However, if the current dimension is strided, then we need to make
+ * sure that the lower bound we construct is of the form
+ *
+ *	f + s a
+ *
+ * with f the offset and s the stride.
+ * We therefore compute
+ *
+ *	f + s * ceil((l - f)/s)
+ */
+static __isl_give isl_aff *lower_bound(__isl_keep isl_constraint *c,
+	int pos, __isl_keep isl_ast_build *build)
+{
+	isl_aff *aff;
+
+	aff = isl_constraint_get_bound(c, isl_dim_set, pos);
+	aff = isl_aff_ceil(aff);
+
+	if (isl_ast_build_has_stride(build, pos)) {
+		isl_aff *offset;
+		isl_val *stride;
+
+		offset = isl_ast_build_get_offset(build, pos);
+		stride = isl_ast_build_get_stride(build, pos);
+
+		aff = isl_aff_sub(aff, isl_aff_copy(offset));
+		aff = isl_aff_scale_down_val(aff, isl_val_copy(stride));
+		aff = isl_aff_ceil(aff);
+		aff = isl_aff_scale_val(aff, stride);
+		aff = isl_aff_add(aff, offset);
+	}
+
+	aff = isl_ast_build_compute_gist_aff(build, aff);
+
+	return aff;
+}
+
+/* Return the exact lower bound (or upper bound if "upper" is set)
+ * of "domain" as a piecewise affine expression.
+ *
+ * If we are computing a lower bound (of a strided dimension), then
+ * we need to make sure it is of the form
+ *
+ *	f + s a
+ *
+ * where f is the offset and s is the stride.
+ * We therefore need to include the stride constraint before computing
+ * the minimum.
+ */
+static __isl_give isl_pw_aff *exact_bound(__isl_keep isl_set *domain,
+	__isl_keep isl_ast_build *build, int upper)
+{
+	isl_set *stride;
+	isl_map *it_map;
+	isl_pw_aff *pa;
+	isl_pw_multi_aff *pma;
+
+	domain = isl_set_copy(domain);
+	if (!upper) {
+		stride = isl_ast_build_get_stride_constraint(build);
+		domain = isl_set_intersect(domain, stride);
+	}
+	it_map = isl_ast_build_map_to_iterator(build, domain);
+	if (upper)
+		pma = isl_map_lexmax_pw_multi_aff(it_map);
+	else
+		pma = isl_map_lexmin_pw_multi_aff(it_map);
+	pa = isl_pw_multi_aff_get_pw_aff(pma, 0);
+	isl_pw_multi_aff_free(pma);
+	pa = isl_ast_build_compute_gist_pw_aff(build, pa);
+	pa = isl_pw_aff_coalesce(pa);
+
+	return pa;
+}
+
+/* Callback for sorting the isl_pw_aff_list passed to reduce_list and
+ * remove_redundant_lower_bounds.
+ */
+static int reduce_list_cmp(__isl_keep isl_pw_aff *a, __isl_keep isl_pw_aff *b,
+	void *user)
+{
+	return isl_pw_aff_plain_cmp(a, b);
+}
+
+/* Given a list of lower bounds "list", remove those that are redundant
+ * with respect to the other bounds in "list" and the domain of "build".
+ *
+ * We first sort the bounds in the same way as they would be sorted
+ * by set_for_node_expressions so that we can try and remove the last
+ * bounds first.
+ *
+ * For a lower bound to be effective, there needs to be at least
+ * one domain element for which it is larger than all other lower bounds.
+ * For each lower bound we therefore intersect the domain with
+ * the conditions that it is larger than all other bounds and
+ * check whether the result is empty.  If so, the bound can be removed.
+ */
+static __isl_give isl_pw_aff_list *remove_redundant_lower_bounds(
+	__isl_take isl_pw_aff_list *list, __isl_keep isl_ast_build *build)
+{
+	int i, j, n;
+	isl_set *domain;
+
+	list = isl_pw_aff_list_sort(list, &reduce_list_cmp, NULL);
+	if (!list)
+		return NULL;
+
+	n = isl_pw_aff_list_n_pw_aff(list);
+	if (n <= 1)
+		return list;
+
+	domain = isl_ast_build_get_domain(build);
+
+	for (i = n - 1; i >= 0; --i) {
+		isl_pw_aff *pa_i;
+		isl_set *domain_i;
+		int empty;
+
+		domain_i = isl_set_copy(domain);
+		pa_i = isl_pw_aff_list_get_pw_aff(list, i);
+
+		for (j = 0; j < n; ++j) {
+			isl_pw_aff *pa_j;
+			isl_set *better;
+
+			if (j == i)
+				continue;
+
+			pa_j = isl_pw_aff_list_get_pw_aff(list, j);
+			better = isl_pw_aff_gt_set(isl_pw_aff_copy(pa_i), pa_j);
+			domain_i = isl_set_intersect(domain_i, better);
+		}
+
+		empty = isl_set_is_empty(domain_i);
+
+		isl_set_free(domain_i);
+		isl_pw_aff_free(pa_i);
+
+		if (empty < 0)
+			goto error;
+		if (!empty)
+			continue;
+		list = isl_pw_aff_list_drop(list, i, 1);
+		n--;
+	}
+
+	isl_set_free(domain);
+
+	return list;
+error:
+	isl_set_free(domain);
+	return isl_pw_aff_list_free(list);
+}
+
+/* Extract a lower bound on dimension "pos" from each constraint
+ * in "constraints" and return the list of lower bounds.
+ * If "constraints" has zero elements, then we extract a lower bound
+ * from "domain" instead.
+ *
+ * If the current dimension is strided, then the lower bound
+ * is adjusted by lower_bound to match the stride information.
+ * This modification may make one or more lower bounds redundant
+ * with respect to the other lower bounds.  We therefore check
+ * for this condition and remove the redundant lower bounds.
+ */
+static __isl_give isl_pw_aff_list *lower_bounds(
+	__isl_keep isl_constraint_list *constraints, int pos,
+	__isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	isl_pw_aff_list *list;
+	int i, n;
+
+	if (!build)
+		return NULL;
+
+	n = isl_constraint_list_n_constraint(constraints);
+	if (n == 0) {
+		isl_pw_aff *pa;
+		pa = exact_bound(domain, build, 0);
+		return isl_pw_aff_list_from_pw_aff(pa);
+	}
+
+	ctx = isl_ast_build_get_ctx(build);
+	list = isl_pw_aff_list_alloc(ctx,n);
+
+	for (i = 0; i < n; ++i) {
+		isl_aff *aff;
+		isl_constraint *c;
+
+		c = isl_constraint_list_get_constraint(constraints, i);
+		aff = lower_bound(c, pos, build);
+		isl_constraint_free(c);
+		list = isl_pw_aff_list_add(list, isl_pw_aff_from_aff(aff));
+	}
+
+	if (isl_ast_build_has_stride(build, pos))
+		list = remove_redundant_lower_bounds(list, build);
+
+	return list;
+}
+
+/* Extract an upper bound on dimension "pos" from each constraint
+ * in "constraints" and return the list of upper bounds.
+ * If "constraints" has zero elements, then we extract an upper bound
+ * from "domain" instead.
+ */
+static __isl_give isl_pw_aff_list *upper_bounds(
+	__isl_keep isl_constraint_list *constraints, int pos,
+	__isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	isl_pw_aff_list *list;
+	int i, n;
+
+	n = isl_constraint_list_n_constraint(constraints);
+	if (n == 0) {
+		isl_pw_aff *pa;
+		pa = exact_bound(domain, build, 1);
+		return isl_pw_aff_list_from_pw_aff(pa);
+	}
+
+	ctx = isl_ast_build_get_ctx(build);
+	list = isl_pw_aff_list_alloc(ctx,n);
+
+	for (i = 0; i < n; ++i) {
+		isl_aff *aff;
+		isl_constraint *c;
+
+		c = isl_constraint_list_get_constraint(constraints, i);
+		aff = isl_constraint_get_bound(c, isl_dim_set, pos);
+		isl_constraint_free(c);
+		aff = isl_aff_floor(aff);
+		list = isl_pw_aff_list_add(list, isl_pw_aff_from_aff(aff));
+	}
+
+	return list;
+}
+
+/* Return an isl_ast_expr that performs the reduction of type "type"
+ * on AST expressions corresponding to the elements in "list".
+ *
+ * The list is assumed to contain at least one element.
+ * If the list contains exactly one element, then the returned isl_ast_expr
+ * simply computes that affine expression.
+ * If the list contains more than one element, then we sort it
+ * using a fairly abitrary but hopefully reasonably stable order.
+ */
+static __isl_give isl_ast_expr *reduce_list(enum isl_ast_op_type type,
+	__isl_keep isl_pw_aff_list *list, __isl_keep isl_ast_build *build)
+{
+	int i, n;
+	isl_ctx *ctx;
+	isl_ast_expr *expr;
+
+	if (!list)
+		return NULL;
+
+	n = isl_pw_aff_list_n_pw_aff(list);
+
+	if (n == 1)
+		return isl_ast_build_expr_from_pw_aff_internal(build,
+				isl_pw_aff_list_get_pw_aff(list, 0));
+
+	ctx = isl_pw_aff_list_get_ctx(list);
+	expr = isl_ast_expr_alloc_op(ctx, type, n);
+	if (!expr)
+		return NULL;
+
+	list = isl_pw_aff_list_copy(list);
+	list = isl_pw_aff_list_sort(list, &reduce_list_cmp, NULL);
+	if (!list)
+		return isl_ast_expr_free(expr);
+
+	for (i = 0; i < n; ++i) {
+		isl_ast_expr *expr_i;
+
+		expr_i = isl_ast_build_expr_from_pw_aff_internal(build,
+				isl_pw_aff_list_get_pw_aff(list, i));
+		if (!expr_i)
+			goto error;
+		expr->u.op.args[i] = expr_i;
+	}
+
+	isl_pw_aff_list_free(list);
+	return expr;
+error:
+	isl_pw_aff_list_free(list);
+	isl_ast_expr_free(expr);
+	return NULL;
+}
+
+/* Add guards implied by the "generated constraints",
+ * but not (necessarily) enforced by the generated AST to "guard".
+ * In particular, if there is any stride constraints,
+ * then add the guard implied by those constraints.
+ * 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.
+ */
+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;
+
+	depth = isl_ast_build_get_depth(build);
+	has_stride = isl_ast_build_has_stride(build, depth);
+	if (!has_stride && !degenerate)
+		return guard;
+
+	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);
+	}
+
+	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);
+	}
+
+	return guard;
+}
+
+/* Update "graft" based on "sub_build" for the degenerate case.
+ *
+ * "build" is the build in which graft->node was created
+ * "sub_build" contains information about the current level itself,
+ * including the single value attained.
+ *
+ * We set the initialization part of the for loop to the single
+ * value attained by the current dimension.
+ * The increment and condition are not strictly needed as the are known
+ * to be "1" and "iterator <= value" respectively.
+ */
+static __isl_give isl_ast_graft *refine_degenerate(
+	__isl_take isl_ast_graft *graft, __isl_keep isl_ast_build *build,
+	__isl_keep isl_ast_build *sub_build)
+{
+	isl_pw_aff *value;
+
+	if (!graft || !sub_build)
+		return isl_ast_graft_free(graft);
+
+	value = isl_pw_aff_copy(sub_build->value);
+
+	graft->node->u.f.init = isl_ast_build_expr_from_pw_aff_internal(build,
+						value);
+	if (!graft->node->u.f.init)
+		return isl_ast_graft_free(graft);
+
+	return graft;
+}
+
+/* Return the intersection of constraints in "list" as a set.
+ */
+static __isl_give isl_set *intersect_constraints(
+	__isl_keep isl_constraint_list *list)
+{
+	int i, n;
+	isl_basic_set *bset;
+
+	n = isl_constraint_list_n_constraint(list);
+	if (n < 1)
+		isl_die(isl_constraint_list_get_ctx(list), isl_error_internal,
+			"expecting at least one constraint", return NULL);
+
+	bset = isl_basic_set_from_constraint(
+				isl_constraint_list_get_constraint(list, 0));
+	for (i = 1; i < n; ++i) {
+		isl_basic_set *bset_i;
+
+		bset_i = isl_basic_set_from_constraint(
+				isl_constraint_list_get_constraint(list, i));
+		bset = isl_basic_set_intersect(bset, bset_i);
+	}
+
+	return isl_set_from_basic_set(bset);
+}
+
+/* Compute the constraints on the outer dimensions enforced by
+ * graft->node and add those constraints to graft->enforced,
+ * in case the upper bound is expressed as a set "upper".
+ *
+ * In particular, if l(...) is a lower bound in "lower", and
+ *
+ *	-a i + f(...) >= 0		or	a i <= f(...)
+ *
+ * is an upper bound ocnstraint on the current dimension i,
+ * then the for loop enforces the constraint
+ *
+ *	-a l(...) + f(...) >= 0		or	a l(...) <= f(...)
+ *
+ * We therefore simply take each lower bound in turn, plug it into
+ * the upper bounds and compute the intersection over all lower bounds.
+ *
+ * If a lower bound is a rational expression, then
+ * isl_basic_set_preimage_multi_aff will force this rational
+ * expression to have only integer values.  However, the loop
+ * itself does not enforce this integrality constraint.  We therefore
+ * use the ceil of the lower bounds instead of the lower bounds themselves.
+ * Other constraints will make sure that the for loop is only executed
+ * when each of the lower bounds attains an integral value.
+ * In particular, potentially rational values only occur in
+ * lower_bound if the offset is a (seemingly) rational expression,
+ * but then outer conditions will make sure that this rational expression
+ * only attains integer values.
+ */
+static __isl_give isl_ast_graft *set_enforced_from_set(
+	__isl_take isl_ast_graft *graft,
+	__isl_keep isl_pw_aff_list *lower, int pos, __isl_keep isl_set *upper)
+{
+	isl_space *space;
+	isl_basic_set *enforced;
+	isl_pw_multi_aff *pma;
+	int i, n;
+
+	if (!graft || !lower)
+		return isl_ast_graft_free(graft);
+
+	space = isl_set_get_space(upper);
+	enforced = isl_basic_set_universe(isl_space_copy(space));
+
+	space = isl_space_map_from_set(space);
+	pma = isl_pw_multi_aff_identity(space);
+
+	n = isl_pw_aff_list_n_pw_aff(lower);
+	for (i = 0; i < n; ++i) {
+		isl_pw_aff *pa;
+		isl_set *enforced_i;
+		isl_basic_set *hull;
+		isl_pw_multi_aff *pma_i;
+
+		pa = isl_pw_aff_list_get_pw_aff(lower, i);
+		pa = isl_pw_aff_ceil(pa);
+		pma_i = isl_pw_multi_aff_copy(pma);
+		pma_i = isl_pw_multi_aff_set_pw_aff(pma_i, pos, pa);
+		enforced_i = isl_set_copy(upper);
+		enforced_i = isl_set_preimage_pw_multi_aff(enforced_i, pma_i);
+		hull = isl_set_simple_hull(enforced_i);
+		enforced = isl_basic_set_intersect(enforced, hull);
+	}
+
+	isl_pw_multi_aff_free(pma);
+
+	graft = isl_ast_graft_enforce(graft, enforced);
+
+	return graft;
+}
+
+/* Compute the constraints on the outer dimensions enforced by
+ * graft->node and add those constraints to graft->enforced,
+ * in case the upper bound is expressed as
+ * a list of affine expressions "upper".
+ *
+ * The enforced condition is that each lower bound expression is less
+ * than or equal to each upper bound expression.
+ */
+static __isl_give isl_ast_graft *set_enforced_from_list(
+	__isl_take isl_ast_graft *graft,
+	__isl_keep isl_pw_aff_list *lower, __isl_keep isl_pw_aff_list *upper)
+{
+	isl_set *cond;
+	isl_basic_set *enforced;
+
+	lower = isl_pw_aff_list_copy(lower);
+	upper = isl_pw_aff_list_copy(upper);
+	cond = isl_pw_aff_list_le_set(lower, upper);
+	enforced = isl_set_simple_hull(cond);
+	graft = isl_ast_graft_enforce(graft, enforced);
+
+	return graft;
+}
+
+/* Does "aff" have a negative constant term?
+ */
+static int aff_constant_is_negative(__isl_take isl_set *set,
+	__isl_take isl_aff *aff, void *user)
+{
+	int *neg = user;
+	isl_val *v;
+
+	v = isl_aff_get_constant_val(aff);
+	*neg = isl_val_is_neg(v);
+	isl_val_free(v);
+	isl_set_free(set);
+	isl_aff_free(aff);
+
+	return *neg ? 0 : -1;
+}
+
+/* Does "pa" have a negative constant term over its entire domain?
+ */
+static int pw_aff_constant_is_negative(__isl_take isl_pw_aff *pa, void *user)
+{
+	int r;
+	int *neg = user;
+
+	r = isl_pw_aff_foreach_piece(pa, &aff_constant_is_negative, user);
+	isl_pw_aff_free(pa);
+
+	return *neg ? 0 : -1;
+}
+
+/* Does each element in "list" have a negative constant term?
+ *
+ * The callback terminates the iteration as soon an element has been
+ * found that does not have a negative constant term.
+ */
+static int list_constant_is_negative(__isl_keep isl_pw_aff_list *list)
+{
+	int neg = 1;
+
+	if (isl_pw_aff_list_foreach(list,
+				&pw_aff_constant_is_negative, &neg) < 0 && neg)
+		return -1;
+
+	return neg;
+}
+
+/* Add 1 to each of the elements in "list", where each of these elements
+ * is defined over the internal schedule space of "build".
+ */
+static __isl_give isl_pw_aff_list *list_add_one(
+	__isl_take isl_pw_aff_list *list, __isl_keep isl_ast_build *build)
+{
+	int i, n;
+	isl_space *space;
+	isl_aff *aff;
+	isl_pw_aff *one;
+
+	space = isl_ast_build_get_space(build, 1);
+	aff = isl_aff_zero_on_domain(isl_local_space_from_space(space));
+	aff = isl_aff_add_constant_si(aff, 1);
+	one = isl_pw_aff_from_aff(aff);
+
+	n = isl_pw_aff_list_n_pw_aff(list);
+	for (i = 0; i < n; ++i) {
+		isl_pw_aff *pa;
+		pa = isl_pw_aff_list_get_pw_aff(list, i);
+		pa = isl_pw_aff_add(pa, isl_pw_aff_copy(one));
+		list = isl_pw_aff_list_set_pw_aff(list, i, pa);
+	}
+
+	isl_pw_aff_free(one);
+
+	return list;
+}
+
+/* Set the condition part of the for node graft->node in case
+ * the upper bound is represented as a list of piecewise affine expressions.
+ *
+ * In particular, set the condition to
+ *
+ *	iterator <= min(list of upper bounds)
+ *
+ * If each of the upper bounds has a negative constant term, then
+ * set the condition to
+ *
+ *	iterator < min(list of (upper bound + 1)s)
+ *
+ */
+static __isl_give isl_ast_graft *set_for_cond_from_list(
+	__isl_take isl_ast_graft *graft, __isl_keep isl_pw_aff_list *list,
+	__isl_keep isl_ast_build *build)
+{
+	int neg;
+	isl_ast_expr *bound, *iterator, *cond;
+	enum isl_ast_op_type type = isl_ast_op_le;
+
+	if (!graft || !list)
+		return isl_ast_graft_free(graft);
+
+	neg = list_constant_is_negative(list);
+	if (neg < 0)
+		return isl_ast_graft_free(graft);
+	list = isl_pw_aff_list_copy(list);
+	if (neg) {
+		list = list_add_one(list, build);
+		type = isl_ast_op_lt;
+	}
+
+	bound = reduce_list(isl_ast_op_min, list, build);
+	iterator = isl_ast_expr_copy(graft->node->u.f.iterator);
+	cond = isl_ast_expr_alloc_binary(type, iterator, bound);
+	graft->node->u.f.cond = cond;
+
+	isl_pw_aff_list_free(list);
+	if (!graft->node->u.f.cond)
+		return isl_ast_graft_free(graft);
+	return graft;
+}
+
+/* Set the condition part of the for node graft->node in case
+ * the upper bound is represented as a set.
+ */
+static __isl_give isl_ast_graft *set_for_cond_from_set(
+	__isl_take isl_ast_graft *graft, __isl_keep isl_set *set,
+	__isl_keep isl_ast_build *build)
+{
+	isl_ast_expr *cond;
+
+	if (!graft)
+		return NULL;
+
+	cond = isl_ast_build_expr_from_set(build, isl_set_copy(set));
+	graft->node->u.f.cond = cond;
+	if (!graft->node->u.f.cond)
+		return isl_ast_graft_free(graft);
+	return graft;
+}
+
+/* Construct an isl_ast_expr for the increment (i.e., stride) of
+ * the current dimension.
+ */
+static __isl_give isl_ast_expr *for_inc(__isl_keep isl_ast_build *build)
+{
+	int depth;
+	isl_val *v;
+	isl_ctx *ctx;
+
+	if (!build)
+		return NULL;
+	ctx = isl_ast_build_get_ctx(build);
+	depth = isl_ast_build_get_depth(build);
+
+	if (!isl_ast_build_has_stride(build, depth))
+		return isl_ast_expr_alloc_int_si(ctx, 1);
+
+	v = isl_ast_build_get_stride(build, depth);
+	return isl_ast_expr_from_val(v);
+}
+
+/* Should we express the loop condition as
+ *
+ *	iterator <= min(list of upper bounds)
+ *
+ * or as a conjunction of constraints?
+ *
+ * The first is constructed from a list of upper bounds.
+ * The second is constructed from a set.
+ *
+ * If there are no upper bounds in "constraints", then this could mean
+ * that "domain" simply doesn't have an upper bound or that we didn't
+ * pick any upper bound.  In the first case, we want to generate the
+ * loop condition as a(n empty) conjunction of constraints
+ * In the second case, we will compute
+ * a single upper bound from "domain" and so we use the list form.
+ *
+ * If there are upper bounds in "constraints",
+ * then we use the list form iff the atomic_upper_bound option is set.
+ */
+static int use_upper_bound_list(isl_ctx *ctx, int n_upper,
+	__isl_keep isl_set *domain, int depth)
+{
+	if (n_upper > 0)
+		return isl_options_get_ast_build_atomic_upper_bound(ctx);
+	else
+		return isl_set_dim_has_upper_bound(domain, isl_dim_set, depth);
+}
+
+/* Fill in the expressions of the for node in graft->node.
+ *
+ * In particular,
+ * - set the initialization part of the loop to the maximum of the lower bounds
+ * - extract the increment from the stride of the current dimension
+ * - construct the for condition either based on a list of upper bounds
+ *	or on a set of upper bound constraints.
+ */
+static __isl_give isl_ast_graft *set_for_node_expressions(
+	__isl_take isl_ast_graft *graft, __isl_keep isl_pw_aff_list *lower,
+	int use_list, __isl_keep isl_pw_aff_list *upper_list,
+	__isl_keep isl_set *upper_set, __isl_keep isl_ast_build *build)
+{
+	isl_ast_node *node;
+
+	if (!graft)
+		return NULL;
+
+	build = isl_ast_build_copy(build);
+
+	node = graft->node;
+	node->u.f.init = reduce_list(isl_ast_op_max, lower, build);
+	node->u.f.inc = for_inc(build);
+
+	if (use_list)
+		graft = set_for_cond_from_list(graft, upper_list, build);
+	else
+		graft = set_for_cond_from_set(graft, upper_set, build);
+
+	isl_ast_build_free(build);
+
+	if (!node->u.f.iterator || !node->u.f.init ||
+	    !node->u.f.cond || !node->u.f.inc)
+		return isl_ast_graft_free(graft);
+
+	return graft;
+}
+
+/* Update "graft" based on "bounds" and "domain" for the generic,
+ * non-degenerate, case.
+ *
+ * "c_lower" and "c_upper" contain the lower and upper bounds
+ * that the loop node should express.
+ * "domain" is the subset of the intersection of the constraints
+ * for which some code is executed.
+ *
+ * There may be zero lower bounds or zero upper bounds in "constraints"
+ * in case the list of constraints was created
+ * based on the atomic option or based on separation with explicit bounds.
+ * In that case, we use "domain" to derive lower and/or upper bounds.
+ *
+ * We first compute a list of one or more lower bounds.
+ *
+ * Then we decide if we want to express the condition as
+ *
+ *	iterator <= min(list of upper bounds)
+ *
+ * or as a conjunction of constraints.
+ *
+ * The set of enforced constraints is then computed either based on
+ * a list of upper bounds or on a set of upper bound constraints.
+ * We do not compute any enforced constraints if we were forced
+ * to compute a lower or upper bound using exact_bound.  The domains
+ * of the resulting expressions may imply some bounds on outer dimensions
+ * that we do not want to appear in the enforced constraints since
+ * they are not actually enforced by the corresponding code.
+ *
+ * Finally, we fill in the expressions of the for node.
+ */
+static __isl_give isl_ast_graft *refine_generic_bounds(
+	__isl_take isl_ast_graft *graft,
+	__isl_take isl_constraint_list *c_lower,
+	__isl_take isl_constraint_list *c_upper,
+	__isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+	int depth;
+	isl_ctx *ctx;
+	isl_pw_aff_list *lower;
+	int use_list;
+	isl_set *upper_set = NULL;
+	isl_pw_aff_list *upper_list = NULL;
+	int n_lower, n_upper;
+
+	if (!graft || !c_lower || !c_upper || !build)
+		goto error;
+
+	depth = isl_ast_build_get_depth(build);
+	ctx = isl_ast_graft_get_ctx(graft);
+
+	n_lower = isl_constraint_list_n_constraint(c_lower);
+	n_upper = isl_constraint_list_n_constraint(c_upper);
+
+	use_list = use_upper_bound_list(ctx, n_upper, domain, depth);
+
+	lower = lower_bounds(c_lower, depth, domain, build);
+
+	if (use_list)
+		upper_list = upper_bounds(c_upper, depth, domain, build);
+	else if (n_upper > 0)
+		upper_set = intersect_constraints(c_upper);
+	else
+		upper_set = isl_set_universe(isl_set_get_space(domain));
+
+	if (n_lower == 0 || n_upper == 0)
+		;
+	else if (use_list)
+		graft = set_enforced_from_list(graft, lower, upper_list);
+	else
+		graft = set_enforced_from_set(graft, lower, depth, upper_set);
+
+	graft = set_for_node_expressions(graft, lower, use_list, upper_list,
+					upper_set, build);
+
+	isl_pw_aff_list_free(lower);
+	isl_pw_aff_list_free(upper_list);
+	isl_set_free(upper_set);
+	isl_constraint_list_free(c_lower);
+	isl_constraint_list_free(c_upper);
+
+	return graft;
+error:
+	isl_constraint_list_free(c_lower);
+	isl_constraint_list_free(c_upper);
+	return isl_ast_graft_free(graft);
+}
+
+/* Internal data structure used inside count_constraints to keep
+ * track of the number of constraints that are independent of dimension "pos",
+ * the lower bounds in "pos" and the upper bounds in "pos".
+ */
+struct isl_ast_count_constraints_data {
+	int pos;
+
+	int n_indep;
+	int n_lower;
+	int n_upper;
+};
+
+/* Increment data->n_indep, data->lower or data->upper depending
+ * on whether "c" is independenct of dimensions data->pos,
+ * a lower bound or an upper bound.
+ */
+static int count_constraints(__isl_take isl_constraint *c, void *user)
+{
+	struct isl_ast_count_constraints_data *data = user;
+
+	if (isl_constraint_is_lower_bound(c, isl_dim_set, data->pos))
+		data->n_lower++;
+	else if (isl_constraint_is_upper_bound(c, isl_dim_set, data->pos))
+		data->n_upper++;
+	else
+		data->n_indep++;
+
+	isl_constraint_free(c);
+
+	return 0;
+}
+
+/* Update "graft" based on "bounds" and "domain" for the generic,
+ * non-degenerate, case.
+ *
+ * "list" respresent the list of bounds that need to be encoded by
+ * the for loop.  Only the constraints that involve the iterator
+ * are relevant here.  The other constraints are taken care of by
+ * the caller and are included in the generated constraints of "build".
+ * "domain" is the subset of the intersection of the constraints
+ * for which some code is executed.
+ * "build" is the build in which graft->node was created.
+ *
+ * We separate lower bounds, upper bounds and constraints that
+ * are independent of the loop iterator.
+ *
+ * The actual for loop bounds are generated in refine_generic_bounds.
+ */
+static __isl_give isl_ast_graft *refine_generic_split(
+	__isl_take isl_ast_graft *graft, __isl_take isl_constraint_list *list,
+	__isl_keep isl_set *domain, __isl_keep isl_ast_build *build)
+{
+	struct isl_ast_count_constraints_data data;
+	isl_constraint_list *lower;
+	isl_constraint_list *upper;
+
+	if (!list)
+		return isl_ast_graft_free(graft);
+
+	data.pos = isl_ast_build_get_depth(build);
+
+	list = isl_constraint_list_sort(list, &cmp_constraint, &data.pos);
+	if (!list)
+		return isl_ast_graft_free(graft);
+
+	data.n_indep = data.n_lower = data.n_upper = 0;
+	if (isl_constraint_list_foreach(list, &count_constraints, &data) < 0) {
+		isl_constraint_list_free(list);
+		return isl_ast_graft_free(graft);
+	}
+
+	lower = isl_constraint_list_drop(list, 0, data.n_indep);
+	upper = isl_constraint_list_copy(lower);
+	lower = isl_constraint_list_drop(lower, data.n_lower, data.n_upper);
+	upper = isl_constraint_list_drop(upper, 0, data.n_lower);
+
+	return refine_generic_bounds(graft, lower, upper, domain, build);
+}
+
+/* Update "graft" based on "bounds" and "domain" for the generic,
+ * non-degenerate, case.
+ *
+ * "bounds" respresent the bounds that need to be encoded by
+ * the for loop (or a guard around the for loop).
+ * "domain" is the subset of "bounds" for which some code is executed.
+ * "build" is the build in which graft->node was created.
+ *
+ * We break up "bounds" into a list of constraints and continue with
+ * refine_generic_split.
+ */
+static __isl_give isl_ast_graft *refine_generic(
+	__isl_take isl_ast_graft *graft,
+	__isl_keep isl_basic_set *bounds, __isl_keep isl_set *domain,
+	__isl_keep isl_ast_build *build)
+{
+	isl_constraint_list *list;
+
+	if (!build || !graft)
+		return isl_ast_graft_free(graft);
+
+	list = isl_basic_set_get_constraint_list(bounds);
+
+	graft = refine_generic_split(graft, list, domain, build);
+
+	return graft;
+}
+
+/* Create a for node for the current level.
+ *
+ * Mark the for node degenerate if "degenerate" is set.
+ */
+static __isl_give isl_ast_node *create_for(__isl_keep isl_ast_build *build,
+	int degenerate)
+{
+	int depth;
+	isl_id *id;
+	isl_ast_node *node;
+
+	if (!build)
+		return NULL;
+
+	depth = isl_ast_build_get_depth(build);
+	id = isl_ast_build_get_iterator_id(build, depth);
+	node = isl_ast_node_alloc_for(id);
+	if (degenerate)
+		node = isl_ast_node_for_mark_degenerate(node);
+
+	return node;
+}
+
+/* If the ast_build_exploit_nested_bounds option is set, then return
+ * the constraints enforced by all elements in "list".
+ * Otherwise, return the universe.
+ */
+static __isl_give isl_basic_set *extract_shared_enforced(
+	__isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	isl_space *space;
+
+	if (!list)
+		return NULL;
+
+	ctx = isl_ast_graft_list_get_ctx(list);
+	if (isl_options_get_ast_build_exploit_nested_bounds(ctx))
+		return isl_ast_graft_list_extract_shared_enforced(list, build);
+
+	space = isl_ast_build_get_space(build, 1);
+	return isl_basic_set_universe(space);
+}
+
+/* Return the pending constraints of "build" that are not already taken
+ * care of (by a combination of "enforced" and the generated constraints
+ * of "build").
+ */
+static __isl_give isl_set *extract_pending(__isl_keep isl_ast_build *build,
+	__isl_keep isl_basic_set *enforced)
+{
+	isl_set *guard, *context;
+
+	guard = isl_ast_build_get_pending(build);
+	context = isl_set_from_basic_set(isl_basic_set_copy(enforced));
+	context = isl_set_intersect(context,
+					isl_ast_build_get_generated(build));
+	return isl_set_gist(guard, context);
+}
+
+/* Create an AST node for the current dimension based on
+ * the schedule domain "bounds" and return the node encapsulated
+ * in an isl_ast_graft.
+ *
+ * "executed" is the current inverse schedule, taking into account
+ * the bounds in "bounds"
+ * "domain" is the domain of "executed", with inner dimensions projected out.
+ * It may be a strict subset of "bounds" in case "bounds" was created
+ * based on the atomic option or based on separation with explicit bounds.
+ *
+ * "domain" may satisfy additional equalities that result
+ * from intersecting "executed" with "bounds" in add_node.
+ * It may also satisfy some global constraints that were dropped out because
+ * we performed separation with explicit bounds.
+ * The very first step is then to copy these constraints to "bounds".
+ *
+ * Since we may be calling before_each_for and after_each_for
+ * callbacks, we record the current inverse schedule in the build.
+ *
+ * We consider three builds,
+ * "build" is the one in which the current level is created,
+ * "body_build" is the build in which the next level is created,
+ * "sub_build" is essentially the same as "body_build", except that
+ * the depth has not been increased yet.
+ *
+ * "build" already contains information (in strides and offsets)
+ * about the strides at the current level, but this information is not
+ * reflected in the build->domain.
+ * We first add this information and the "bounds" to the sub_build->domain.
+ * isl_ast_build_set_loop_bounds adds the stride information and
+ * checks whether the current dimension attains
+ * only a single value and whether this single value can be represented using
+ * a single affine expression.
+ * In the first case, the current level is considered "degenerate".
+ * In the second, sub-case, the current level is considered "eliminated".
+ * Eliminated levels don't need to be reflected in the AST since we can
+ * simply plug in the affine expression.  For degenerate, but non-eliminated,
+ * levels, we do introduce a for node, but mark is as degenerate so that
+ * it can be printed as an assignment of the single value to the loop
+ * "iterator".
+ *
+ * If the current level is eliminated, we explicitly plug in the value
+ * for the current level found by isl_ast_build_set_loop_bounds in the
+ * inverse schedule.  This ensures that if we are working on a slice
+ * of the domain based on information available in the inverse schedule
+ * and the build domain, that then this information is also reflected
+ * in the inverse schedule.  This operation also eliminates the current
+ * dimension from the inverse schedule making sure no inner dimensions depend
+ * on the current dimension.  Otherwise, we create a for node, marking
+ * it degenerate if appropriate.  The initial for node is still incomplete
+ * and will be completed in either refine_degenerate or refine_generic.
+ *
+ * We then generate a sequence of grafts for the next level,
+ * create a surrounding graft for the current level and insert
+ * the for node we created (if the current level is not eliminated).
+ * Before creating a graft for the current level, we first extract
+ * hoistable constraints from the child guards and combine them
+ * with the pending constraints in the build.  These constraints
+ * are used to simplify the child guards and then added to the guard
+ * of the current graft to ensure that they will be generated.
+ * If the hoisted guard is a disjunction, then we use it directly
+ * to gist the guards on the children before intersect it with the
+ * pending constraints.  We do so because this disjunction is typically
+ * identical to the guards on the children such that these guards
+ * can be effectively removed completely.  After the intersection,
+ * the gist operation would have a harder time figuring this out.
+ *
+ * Finally, we set the bounds of the for loop in either
+ * refine_degenerate or refine_generic.
+ * We do so in a context where the pending constraints of the build
+ * have been replaced by the guard of the current graft.
+ */
+static __isl_give isl_ast_graft *create_node_scaled(
+	__isl_take isl_union_map *executed,
+	__isl_take isl_basic_set *bounds, __isl_take isl_set *domain,
+	__isl_take isl_ast_build *build)
+{
+	int depth;
+	int degenerate, eliminated;
+	isl_basic_set *hull;
+	isl_basic_set *enforced;
+	isl_set *guard, *hoisted;
+	isl_ast_node *node = NULL;
+	isl_ast_graft *graft;
+	isl_ast_graft_list *children;
+	isl_ast_build *sub_build;
+	isl_ast_build *body_build;
+
+	domain = isl_ast_build_eliminate_divs(build, domain);
+	domain = isl_set_detect_equalities(domain);
+	hull = isl_set_unshifted_simple_hull(isl_set_copy(domain));
+	bounds = isl_basic_set_intersect(bounds, hull);
+	build = isl_ast_build_set_executed(build, isl_union_map_copy(executed));
+
+	depth = isl_ast_build_get_depth(build);
+	sub_build = isl_ast_build_copy(build);
+	sub_build = isl_ast_build_set_loop_bounds(sub_build,
+						isl_basic_set_copy(bounds));
+	degenerate = isl_ast_build_has_value(sub_build);
+	eliminated = isl_ast_build_has_affine_value(sub_build, depth);
+	if (degenerate < 0 || eliminated < 0)
+		executed = isl_union_map_free(executed);
+	if (eliminated)
+		executed = plug_in_values(executed, sub_build);
+	else
+		node = create_for(build, degenerate);
+
+	body_build = isl_ast_build_copy(sub_build);
+	body_build = isl_ast_build_increase_depth(body_build);
+	if (!eliminated)
+		node = before_each_for(node, body_build);
+	children = generate_next_level(executed,
+				    isl_ast_build_copy(body_build));
+
+	enforced = extract_shared_enforced(children, build);
+	guard = extract_pending(sub_build, enforced);
+	hoisted = isl_ast_graft_list_extract_hoistable_guard(children, build);
+	if (isl_set_n_basic_set(hoisted) > 1)
+		children = isl_ast_graft_list_gist_guards(children,
+						    isl_set_copy(hoisted));
+	guard = isl_set_intersect(guard, hoisted);
+	if (!eliminated)
+		guard = add_implied_guards(guard, degenerate, bounds, build);
+
+	graft = isl_ast_graft_alloc_from_children(children,
+			    isl_set_copy(guard), enforced, build, sub_build);
+
+	if (!degenerate)
+		bounds = isl_ast_build_compute_gist_basic_set(build, bounds);
+	if (!eliminated) {
+		isl_ast_build *for_build;
+
+		graft = isl_ast_graft_insert_for(graft, node);
+		for_build = isl_ast_build_copy(build);
+		for_build = isl_ast_build_replace_pending_by_guard(for_build,
+							isl_set_copy(guard));
+		if (degenerate)
+			graft = refine_degenerate(graft, for_build, sub_build);
+		else
+			graft = refine_generic(graft, bounds,
+					domain, for_build);
+		isl_ast_build_free(for_build);
+	}
+	isl_set_free(guard);
+	if (!eliminated)
+		graft = after_each_for(graft, body_build);
+
+	isl_ast_build_free(body_build);
+	isl_ast_build_free(sub_build);
+	isl_ast_build_free(build);
+	isl_basic_set_free(bounds);
+	isl_set_free(domain);
+
+	return graft;
+}
+
+/* Internal data structure for checking if all constraints involving
+ * the input dimension "depth" are such that the other coefficients
+ * are multiples of "m", reducing "m" if they are not.
+ * If "m" is reduced all the way down to "1", then the check has failed
+ * and we break out of the iteration.
+ */
+struct isl_check_scaled_data {
+	int depth;
+	isl_val *m;
+};
+
+/* If constraint "c" involves the input dimension data->depth,
+ * then make sure that all the other coefficients are multiples of data->m,
+ * reducing data->m if needed.
+ * Break out of the iteration if data->m has become equal to "1".
+ */
+static int constraint_check_scaled(__isl_take isl_constraint *c, void *user)
+{
+	struct isl_check_scaled_data *data = user;
+	int i, j, n;
+	enum isl_dim_type t[] = { isl_dim_param, isl_dim_in, isl_dim_out,
+				    isl_dim_div };
+
+	if (!isl_constraint_involves_dims(c, isl_dim_in, data->depth, 1)) {
+		isl_constraint_free(c);
+		return 0;
+	}
+
+	for (i = 0; i < 4; ++i) {
+		n = isl_constraint_dim(c, t[i]);
+		for (j = 0; j < n; ++j) {
+			isl_val *d;
+
+			if (t[i] == isl_dim_in && j == data->depth)
+				continue;
+			if (!isl_constraint_involves_dims(c, t[i], j, 1))
+				continue;
+			d = isl_constraint_get_coefficient_val(c, t[i], j);
+			data->m = isl_val_gcd(data->m, d);
+			if (isl_val_is_one(data->m))
+				break;
+		}
+		if (j < n)
+			break;
+	}
+
+	isl_constraint_free(c);
+
+	return i < 4 ? -1 : 0;
+}
+
+/* For each constraint of "bmap" that involves the input dimension data->depth,
+ * make sure that all the other coefficients are multiples of data->m,
+ * reducing data->m if needed.
+ * Break out of the iteration if data->m has become equal to "1".
+ */
+static int basic_map_check_scaled(__isl_take isl_basic_map *bmap, void *user)
+{
+	int r;
+
+	r = isl_basic_map_foreach_constraint(bmap,
+						&constraint_check_scaled, user);
+	isl_basic_map_free(bmap);
+
+	return r;
+}
+
+/* For each constraint of "map" that involves the input dimension data->depth,
+ * make sure that all the other coefficients are multiples of data->m,
+ * reducing data->m if needed.
+ * Break out of the iteration if data->m has become equal to "1".
+ */
+static int map_check_scaled(__isl_take isl_map *map, void *user)
+{
+	int r;
+
+	r = isl_map_foreach_basic_map(map, &basic_map_check_scaled, user);
+	isl_map_free(map);
+
+	return r;
+}
+
+/* Create an AST node for the current dimension based on
+ * the schedule domain "bounds" and return the node encapsulated
+ * in an isl_ast_graft.
+ *
+ * "executed" is the current inverse schedule, taking into account
+ * the bounds in "bounds"
+ * "domain" is the domain of "executed", with inner dimensions projected out.
+ *
+ *
+ * Before moving on to the actual AST node construction in create_node_scaled,
+ * we first check if the current dimension is strided and if we can scale
+ * down this stride.  Note that we only do this if the ast_build_scale_strides
+ * option is set.
+ *
+ * In particular, let the current dimension take on values
+ *
+ *	f + s a
+ *
+ * with a an integer.  We check if we can find an integer m that (obviously)
+ * divides both f and s.
+ *
+ * If so, we check if the current dimension only appears in constraints
+ * where the coefficients of the other variables are multiples of m.
+ * We perform this extra check to avoid the risk of introducing
+ * divisions by scaling down the current dimension.
+ *
+ * If so, we scale the current dimension down by a factor of m.
+ * That is, we plug in
+ *
+ *	i = m i'							(1)
+ *
+ * Note that in principle we could always scale down strided loops
+ * by plugging in
+ *
+ *	i = f + s i'
+ *
+ * but this may result in i' taking on larger values than the original i,
+ * due to the shift by "f".
+ * By constrast, the scaling in (1) can only reduce the (absolute) value "i".
+ */
+static __isl_give isl_ast_graft *create_node(__isl_take isl_union_map *executed,
+	__isl_take isl_basic_set *bounds, __isl_take isl_set *domain,
+	__isl_take isl_ast_build *build)
+{
+	struct isl_check_scaled_data data;
+	isl_ctx *ctx;
+	isl_aff *offset;
+	isl_val *d;
+
+	ctx = isl_ast_build_get_ctx(build);
+	if (!isl_options_get_ast_build_scale_strides(ctx))
+		return create_node_scaled(executed, bounds, domain, build);
+
+	data.depth = isl_ast_build_get_depth(build);
+	if (!isl_ast_build_has_stride(build, data.depth))
+		return create_node_scaled(executed, bounds, domain, build);
+
+	offset = isl_ast_build_get_offset(build, data.depth);
+	data.m = isl_ast_build_get_stride(build, data.depth);
+	if (!data.m)
+		offset = isl_aff_free(offset);
+	offset = isl_aff_scale_down_val(offset, isl_val_copy(data.m));
+	d = isl_aff_get_denominator_val(offset);
+	if (!d)
+		executed = isl_union_map_free(executed);
+
+	if (executed && isl_val_is_divisible_by(data.m, d))
+		data.m = isl_val_div(data.m, d);
+	else {
+		data.m = isl_val_set_si(data.m, 1);
+		isl_val_free(d);
+	}
+
+	if (!isl_val_is_one(data.m)) {
+		if (isl_union_map_foreach_map(executed, &map_check_scaled,
+						&data) < 0 &&
+		    !isl_val_is_one(data.m))
+			executed = isl_union_map_free(executed);
+	}
+
+	if (!isl_val_is_one(data.m)) {
+		isl_space *space;
+		isl_multi_aff *ma;
+		isl_aff *aff;
+		isl_map *map;
+		isl_union_map *umap;
+
+		space = isl_ast_build_get_space(build, 1);
+		space = isl_space_map_from_set(space);
+		ma = isl_multi_aff_identity(space);
+		aff = isl_multi_aff_get_aff(ma, data.depth);
+		aff = isl_aff_scale_val(aff, isl_val_copy(data.m));
+		ma = isl_multi_aff_set_aff(ma, data.depth, aff);
+
+		bounds = isl_basic_set_preimage_multi_aff(bounds,
+						isl_multi_aff_copy(ma));
+		domain = isl_set_preimage_multi_aff(domain,
+						isl_multi_aff_copy(ma));
+		map = isl_map_reverse(isl_map_from_multi_aff(ma));
+		umap = isl_union_map_from_map(map);
+		executed = isl_union_map_apply_domain(executed,
+						isl_union_map_copy(umap));
+		build = isl_ast_build_scale_down(build, isl_val_copy(data.m),
+						umap);
+	}
+	isl_aff_free(offset);
+	isl_val_free(data.m);
+
+	return create_node_scaled(executed, bounds, domain, build);
+}
+
+/* Add the basic set to the list that "user" points to.
+ */
+static int collect_basic_set(__isl_take isl_basic_set *bset, void *user)
+{
+	isl_basic_set_list **list = user;
+
+	*list = isl_basic_set_list_add(*list, bset);
+
+	return 0;
+}
+
+/* Extract the basic sets of "set" and collect them in an isl_basic_set_list.
+ */
+static __isl_give isl_basic_set_list *isl_basic_set_list_from_set(
+	__isl_take isl_set *set)
+{
+	int n;
+	isl_ctx *ctx;
+	isl_basic_set_list *list;
+
+	if (!set)
+		return NULL;
+
+	ctx = isl_set_get_ctx(set);
+
+	n = isl_set_n_basic_set(set);
+	list = isl_basic_set_list_alloc(ctx, n);
+	if (isl_set_foreach_basic_set(set, &collect_basic_set, &list) < 0)
+		list = isl_basic_set_list_free(list);
+
+	isl_set_free(set);
+	return list;
+}
+
+/* Generate code for the schedule domain "bounds"
+ * and add the result to "list".
+ *
+ * We mainly detect strides here and check if the bounds do not
+ * conflict with the current build domain
+ * and then pass over control to create_node.
+ *
+ * "bounds" reflects the bounds on the current dimension and possibly
+ * some extra conditions on outer dimensions.
+ * It does not, however, include any divs involving the current dimension,
+ * so it does not capture any stride constraints.
+ * We therefore need to compute that part of the schedule domain that
+ * intersects with "bounds" and derive the strides from the result.
+ */
+static __isl_give isl_ast_graft_list *add_node(
+	__isl_take isl_ast_graft_list *list, __isl_take isl_union_map *executed,
+	__isl_take isl_basic_set *bounds, __isl_take isl_ast_build *build)
+{
+	isl_ast_graft *graft;
+	isl_set *domain = NULL;
+	isl_union_set *uset;
+	int empty, disjoint;
+
+	uset = isl_union_set_from_basic_set(isl_basic_set_copy(bounds));
+	executed = isl_union_map_intersect_domain(executed, uset);
+	empty = isl_union_map_is_empty(executed);
+	if (empty < 0)
+		goto error;
+	if (empty)
+		goto done;
+
+	uset = isl_union_map_domain(isl_union_map_copy(executed));
+	domain = isl_set_from_union_set(uset);
+	domain = isl_ast_build_specialize(build, domain);
+
+	domain = isl_set_compute_divs(domain);
+	domain = isl_ast_build_eliminate_inner(build, domain);
+	disjoint = isl_set_is_disjoint(domain, build->domain);
+	if (disjoint < 0)
+		goto error;
+	if (disjoint)
+		goto done;
+
+	build = isl_ast_build_detect_strides(build, isl_set_copy(domain));
+
+	graft = create_node(executed, bounds, domain,
+				isl_ast_build_copy(build));
+	list = isl_ast_graft_list_add(list, graft);
+	isl_ast_build_free(build);
+	return list;
+error:
+	list = isl_ast_graft_list_free(list);
+done:
+	isl_set_free(domain);
+	isl_basic_set_free(bounds);
+	isl_union_map_free(executed);
+	isl_ast_build_free(build);
+	return list;
+}
+
+/* Does any element of i follow or coincide with any element of j
+ * at the current depth for equal values of the outer dimensions?
+ */
+static int domain_follows_at_depth(__isl_keep isl_basic_set *i,
+	__isl_keep isl_basic_set *j, void *user)
+{
+	int depth = *(int *) user;
+	isl_basic_map *test;
+	int empty;
+	int l;
+
+	test = isl_basic_map_from_domain_and_range(isl_basic_set_copy(i),
+						    isl_basic_set_copy(j));
+	for (l = 0; l < depth; ++l)
+		test = isl_basic_map_equate(test, isl_dim_in, l,
+						isl_dim_out, l);
+	test = isl_basic_map_order_ge(test, isl_dim_in, depth,
+					isl_dim_out, depth);
+	empty = isl_basic_map_is_empty(test);
+	isl_basic_map_free(test);
+
+	return empty < 0 ? -1 : !empty;
+}
+
+/* Split up each element of "list" into a part that is related to "bset"
+ * according to "gt" and a part that is not.
+ * Return a list that consist of "bset" and all the pieces.
+ */
+static __isl_give isl_basic_set_list *add_split_on(
+	__isl_take isl_basic_set_list *list, __isl_take isl_basic_set *bset,
+	__isl_keep isl_basic_map *gt)
+{
+	int i, n;
+	isl_basic_set_list *res;
+
+	if (!list)
+		bset = isl_basic_set_free(bset);
+
+	gt = isl_basic_map_copy(gt);
+	gt = isl_basic_map_intersect_domain(gt, isl_basic_set_copy(bset));
+	n = isl_basic_set_list_n_basic_set(list);
+	res = isl_basic_set_list_from_basic_set(bset);
+	for (i = 0; res && i < n; ++i) {
+		isl_basic_set *bset;
+		isl_set *set1, *set2;
+		isl_basic_map *bmap;
+		int empty;
+
+		bset = isl_basic_set_list_get_basic_set(list, i);
+		bmap = isl_basic_map_copy(gt);
+		bmap = isl_basic_map_intersect_range(bmap, bset);
+		bset = isl_basic_map_range(bmap);
+		empty = isl_basic_set_is_empty(bset);
+		if (empty < 0)
+			res = isl_basic_set_list_free(res);
+		if (empty)  {
+			isl_basic_set_free(bset);
+			bset = isl_basic_set_list_get_basic_set(list, i);
+			res = isl_basic_set_list_add(res, bset);
+			continue;
+		}
+
+		res = isl_basic_set_list_add(res, isl_basic_set_copy(bset));
+		set1 = isl_set_from_basic_set(bset);
+		bset = isl_basic_set_list_get_basic_set(list, i);
+		set2 = isl_set_from_basic_set(bset);
+		set1 = isl_set_subtract(set2, set1);
+		set1 = isl_set_make_disjoint(set1);
+
+		res = isl_basic_set_list_concat(res,
+					    isl_basic_set_list_from_set(set1));
+	}
+	isl_basic_map_free(gt);
+	isl_basic_set_list_free(list);
+	return res;
+}
+
+static __isl_give isl_ast_graft_list *generate_sorted_domains(
+	__isl_keep isl_basic_set_list *domain_list,
+	__isl_keep isl_union_map *executed,
+	__isl_keep isl_ast_build *build);
+
+/* Internal data structure for add_nodes.
+ *
+ * "executed" and "build" are extra arguments to be passed to add_node.
+ * "list" collects the results.
+ */
+struct isl_add_nodes_data {
+	isl_union_map *executed;
+	isl_ast_build *build;
+
+	isl_ast_graft_list *list;
+};
+
+/* Generate code for the schedule domains in "scc"
+ * and add the results to "list".
+ *
+ * The domains in "scc" form a strongly connected component in the ordering.
+ * If the number of domains in "scc" is larger than 1, then this means
+ * that we cannot determine a valid ordering for the domains in the component.
+ * This should be fairly rare because the individual domains
+ * have been made disjoint first.
+ * The problem is that the domains may be integrally disjoint but not
+ * rationally disjoint.  For example, we may have domains
+ *
+ *	{ [i,i] : 0 <= i <= 1 }		and	{ [i,1-i] : 0 <= i <= 1 }
+ *
+ * These two domains have an empty intersection, but their rational
+ * relaxations do intersect.  It is impossible to order these domains
+ * in the second dimension because the first should be ordered before
+ * the second for outer dimension equal to 0, while it should be ordered
+ * after for outer dimension equal to 1.
+ *
+ * This may happen in particular in case of unrolling since the domain
+ * of each slice is replaced by its simple hull.
+ *
+ * For each basic set i in "scc" and for each of the following basic sets j,
+ * we split off that part of the basic set i that shares the outer dimensions
+ * with j and lies before j in the current dimension.
+ * We collect all the pieces in a new list that replaces "scc".
+ *
+ * While the elements in "scc" should be disjoint, we double-check
+ * this property to avoid running into an infinite recursion in case
+ * they intersect due to some internal error.
+ */
+static int add_nodes(__isl_take isl_basic_set_list *scc, void *user)
+{
+	struct isl_add_nodes_data *data = user;
+	int i, n, depth;
+	isl_basic_set *bset, *first;
+	isl_basic_set_list *list;
+	isl_space *space;
+	isl_basic_map *gt;
+
+	n = isl_basic_set_list_n_basic_set(scc);
+	bset = isl_basic_set_list_get_basic_set(scc, 0);
+	if (n == 1) {
+		isl_basic_set_list_free(scc);
+		data->list = add_node(data->list,
+				isl_union_map_copy(data->executed), bset,
+				isl_ast_build_copy(data->build));
+		return data->list ? 0 : -1;
+	}
+
+	depth = isl_ast_build_get_depth(data->build);
+	space = isl_basic_set_get_space(bset);
+	space = isl_space_map_from_set(space);
+	gt = isl_basic_map_universe(space);
+	for (i = 0; i < depth; ++i)
+		gt = isl_basic_map_equate(gt, isl_dim_in, i, isl_dim_out, i);
+	gt = isl_basic_map_order_gt(gt, isl_dim_in, depth, isl_dim_out, depth);
+
+	first = isl_basic_set_copy(bset);
+	list = isl_basic_set_list_from_basic_set(bset);
+	for (i = 1; i < n; ++i) {
+		int disjoint;
+
+		bset = isl_basic_set_list_get_basic_set(scc, i);
+
+		disjoint = isl_basic_set_is_disjoint(bset, first);
+		if (disjoint < 0)
+			list = isl_basic_set_list_free(list);
+		else if (!disjoint)
+			isl_die(isl_basic_set_list_get_ctx(scc),
+				isl_error_internal,
+				"basic sets in scc are assumed to be disjoint",
+				list = isl_basic_set_list_free(list));
+
+		list = add_split_on(list, bset, gt);
+	}
+	isl_basic_set_free(first);
+	isl_basic_map_free(gt);
+	isl_basic_set_list_free(scc);
+	scc = list;
+	data->list = isl_ast_graft_list_concat(data->list,
+		    generate_sorted_domains(scc, data->executed, data->build));
+	isl_basic_set_list_free(scc);
+
+	return data->list ? 0 : -1;
+}
+
+/* Sort the domains in "domain_list" according to the execution order
+ * at the current depth (for equal values of the outer dimensions),
+ * generate code for each of them, collecting the results in a list.
+ * If no code is generated (because the intersection of the inverse schedule
+ * with the domains turns out to be empty), then an empty list is returned.
+ *
+ * The caller is responsible for ensuring that the basic sets in "domain_list"
+ * are pair-wise disjoint.  It can, however, in principle happen that
+ * two basic sets should be ordered one way for one value of the outer
+ * dimensions and the other way for some other value of the outer dimensions.
+ * We therefore play safe and look for strongly connected components.
+ * The function add_nodes takes care of handling non-trivial components.
+ */
+static __isl_give isl_ast_graft_list *generate_sorted_domains(
+	__isl_keep isl_basic_set_list *domain_list,
+	__isl_keep isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	struct isl_add_nodes_data data;
+	int depth;
+	int n;
+
+	if (!domain_list)
+		return NULL;
+
+	ctx = isl_basic_set_list_get_ctx(domain_list);
+	n = isl_basic_set_list_n_basic_set(domain_list);
+	data.list = isl_ast_graft_list_alloc(ctx, n);
+	if (n == 0)
+		return data.list;
+	if (n == 1)
+		return add_node(data.list, isl_union_map_copy(executed),
+			isl_basic_set_list_get_basic_set(domain_list, 0),
+			isl_ast_build_copy(build));
+
+	depth = isl_ast_build_get_depth(build);
+	data.executed = executed;
+	data.build = build;
+	if (isl_basic_set_list_foreach_scc(domain_list,
+					&domain_follows_at_depth, &depth,
+					&add_nodes, &data) < 0)
+		data.list = isl_ast_graft_list_free(data.list);
+
+	return data.list;
+}
+
+/* Do i and j share any values for the outer dimensions?
+ */
+static int shared_outer(__isl_keep isl_basic_set *i,
+	__isl_keep isl_basic_set *j, void *user)
+{
+	int depth = *(int *) user;
+	isl_basic_map *test;
+	int empty;
+	int l;
+
+	test = isl_basic_map_from_domain_and_range(isl_basic_set_copy(i),
+						    isl_basic_set_copy(j));
+	for (l = 0; l < depth; ++l)
+		test = isl_basic_map_equate(test, isl_dim_in, l,
+						isl_dim_out, l);
+	empty = isl_basic_map_is_empty(test);
+	isl_basic_map_free(test);
+
+	return empty < 0 ? -1 : !empty;
+}
+
+/* Internal data structure for generate_sorted_domains_wrap.
+ *
+ * "n" is the total number of basic sets
+ * "executed" and "build" are extra arguments to be passed
+ *	to generate_sorted_domains.
+ *
+ * "single" is set to 1 by generate_sorted_domains_wrap if there
+ * is only a single component.
+ * "list" collects the results.
+ */
+struct isl_ast_generate_parallel_domains_data {
+	int n;
+	isl_union_map *executed;
+	isl_ast_build *build;
+
+	int single;
+	isl_ast_graft_list *list;
+};
+
+/* Call generate_sorted_domains on "scc", fuse the result into a list
+ * with either zero or one graft and collect the these single element
+ * lists into data->list.
+ *
+ * If there is only one component, i.e., if the number of basic sets
+ * in the current component is equal to the total number of basic sets,
+ * then data->single is set to 1 and the result of generate_sorted_domains
+ * is not fused.
+ */
+static int generate_sorted_domains_wrap(__isl_take isl_basic_set_list *scc,
+	void *user)
+{
+	struct isl_ast_generate_parallel_domains_data *data = user;
+	isl_ast_graft_list *list;
+
+	list = generate_sorted_domains(scc, data->executed, data->build);
+	data->single = isl_basic_set_list_n_basic_set(scc) == data->n;
+	if (!data->single)
+		list = isl_ast_graft_list_fuse(list, data->build);
+	if (!data->list)
+		data->list = list;
+	else
+		data->list = isl_ast_graft_list_concat(data->list, list);
+
+	isl_basic_set_list_free(scc);
+	if (!data->list)
+		return -1;
+
+	return 0;
+}
+
+/* Look for any (weakly connected) components in the "domain_list"
+ * of domains that share some values of the outer dimensions.
+ * That is, domains in different components do not share any values
+ * of the outer dimensions.  This means that these components
+ * can be freely reordered.
+ * Within each of the components, we sort the domains according
+ * to the execution order at the current depth.
+ *
+ * If there is more than one component, then generate_sorted_domains_wrap
+ * fuses the result of each call to generate_sorted_domains
+ * into a list with either zero or one graft and collects these (at most)
+ * single element lists into a bigger list. This means that the elements of the
+ * final list can be freely reordered.  In particular, we sort them
+ * according to an arbitrary but fixed ordering to ease merging of
+ * graft lists from different components.
+ */
+static __isl_give isl_ast_graft_list *generate_parallel_domains(
+	__isl_keep isl_basic_set_list *domain_list,
+	__isl_keep isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+	int depth;
+	struct isl_ast_generate_parallel_domains_data data;
+
+	if (!domain_list)
+		return NULL;
+
+	data.n = isl_basic_set_list_n_basic_set(domain_list);
+	if (data.n <= 1)
+		return generate_sorted_domains(domain_list, executed, build);
+
+	depth = isl_ast_build_get_depth(build);
+	data.list = NULL;
+	data.executed = executed;
+	data.build = build;
+	data.single = 0;
+	if (isl_basic_set_list_foreach_scc(domain_list, &shared_outer, &depth,
+					    &generate_sorted_domains_wrap,
+					    &data) < 0)
+		data.list = isl_ast_graft_list_free(data.list);
+
+	if (!data.single)
+		data.list = isl_ast_graft_list_sort_guard(data.list);
+
+	return data.list;
+}
+
+/* Internal data for separate_domain.
+ *
+ * "explicit" is set if we only want to use explicit bounds.
+ *
+ * "domain" collects the separated domains.
+ */
+struct isl_separate_domain_data {
+	isl_ast_build *build;
+	int explicit;
+	isl_set *domain;
+};
+
+/* Extract implicit bounds on the current dimension for the executed "map".
+ *
+ * The domain of "map" may involve inner dimensions, so we
+ * need to eliminate them.
+ */
+static __isl_give isl_set *implicit_bounds(__isl_take isl_map *map,
+	__isl_keep isl_ast_build *build)
+{
+	isl_set *domain;
+
+	domain = isl_map_domain(map);
+	domain = isl_ast_build_eliminate(build, domain);
+
+	return domain;
+}
+
+/* Extract explicit bounds on the current dimension for the executed "map".
+ *
+ * Rather than eliminating the inner dimensions as in implicit_bounds,
+ * we simply drop any constraints involving those inner dimensions.
+ * The idea is that most bounds that are implied by constraints on the
+ * inner dimensions will be enforced by for loops and not by explicit guards.
+ * There is then no need to separate along those bounds.
+ */
+static __isl_give isl_set *explicit_bounds(__isl_take isl_map *map,
+	__isl_keep isl_ast_build *build)
+{
+	isl_set *domain;
+	int depth, dim;
+
+	dim = isl_map_dim(map, isl_dim_out);
+	map = isl_map_drop_constraints_involving_dims(map, isl_dim_out, 0, dim);
+
+	domain = isl_map_domain(map);
+	depth = isl_ast_build_get_depth(build);
+	dim = isl_set_dim(domain, isl_dim_set);
+	domain = isl_set_detect_equalities(domain);
+	domain = isl_set_drop_constraints_involving_dims(domain,
+				isl_dim_set, depth + 1, dim - (depth + 1));
+	domain = isl_set_remove_divs_involving_dims(domain,
+				isl_dim_set, depth, 1);
+	domain = isl_set_remove_unknown_divs(domain);
+
+	return domain;
+}
+
+/* Split data->domain into pieces that intersect with the range of "map"
+ * and pieces that do not intersect with the range of "map"
+ * and then add that part of the range of "map" that does not intersect
+ * with data->domain.
+ */
+static int separate_domain(__isl_take isl_map *map, void *user)
+{
+	struct isl_separate_domain_data *data = user;
+	isl_set *domain;
+	isl_set *d1, *d2;
+
+	if (data->explicit)
+		domain = explicit_bounds(map, data->build);
+	else
+		domain = implicit_bounds(map, data->build);
+
+	domain = isl_set_coalesce(domain);
+	domain = isl_set_make_disjoint(domain);
+	d1 = isl_set_subtract(isl_set_copy(domain), isl_set_copy(data->domain));
+	d2 = isl_set_subtract(isl_set_copy(data->domain), isl_set_copy(domain));
+	data->domain = isl_set_intersect(data->domain, domain);
+	data->domain = isl_set_union(data->domain, d1);
+	data->domain = isl_set_union(data->domain, d2);
+
+	return 0;
+}
+
+/* Separate the schedule domains of "executed".
+ *
+ * That is, break up the domain of "executed" into basic sets,
+ * such that for each basic set S, every element in S is associated with
+ * the same domain spaces.
+ *
+ * "space" is the (single) domain space of "executed".
+ */
+static __isl_give isl_set *separate_schedule_domains(
+	__isl_take isl_space *space, __isl_take isl_union_map *executed,
+	__isl_keep isl_ast_build *build)
+{
+	struct isl_separate_domain_data data = { build };
+	isl_ctx *ctx;
+
+	ctx = isl_ast_build_get_ctx(build);
+	data.explicit = isl_options_get_ast_build_separation_bounds(ctx) ==
+				    ISL_AST_BUILD_SEPARATION_BOUNDS_EXPLICIT;
+	data.domain = isl_set_empty(space);
+	if (isl_union_map_foreach_map(executed, &separate_domain, &data) < 0)
+		data.domain = isl_set_free(data.domain);
+
+	isl_union_map_free(executed);
+	return data.domain;
+}
+
+/* Temporary data used during the search for a lower bound for unrolling.
+ *
+ * "domain" is the original set for which to find a lower bound
+ * "depth" is the dimension for which to find a lower boudn
+ *
+ * "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.
+ */
+struct isl_find_unroll_data {
+	isl_set *domain;
+	int depth;
+
+	isl_aff *lower;
+	int *n;
+};
+
+/* Check if we can use "c" as a lower bound and if it is better than
+ * any previously found lower bound.
+ *
+ * If "c" does not involve the dimension at the current depth,
+ * then we cannot use it.
+ * Otherwise, let "c" be of the form
+ *
+ *	i >= f(j)/a
+ *
+ * We compute the maximal value of
+ *
+ *	-ceil(f(j)/a)) + i + 1
+ *
+ * over the domain.  If there is such a value "n", then we know
+ *
+ *	-ceil(f(j)/a)) + i + 1 <= n
+ *
+ * or
+ *
+ *	i < ceil(f(j)/a)) + n
+ *
+ * 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.
+ */
+static int update_unrolling_lower_bound(struct isl_find_unroll_data *data,
+	__isl_keep isl_constraint *c)
+{
+	isl_aff *aff, *lower;
+	isl_val *max;
+
+	if (!isl_constraint_is_lower_bound(c, isl_dim_set, data->depth))
+		return 0;
+
+	lower = isl_constraint_get_bound(c, isl_dim_set, data->depth);
+	lower = isl_aff_ceil(lower);
+	aff = isl_aff_copy(lower);
+	aff = isl_aff_neg(aff);
+	aff = isl_aff_add_coefficient_si(aff, isl_dim_in, data->depth, 1);
+	aff = isl_aff_add_constant_si(aff, 1);
+	max = isl_set_max_val(data->domain, aff);
+	isl_aff_free(aff);
+
+	if (!max)
+		goto error;
+	if (isl_val_is_infty(max)) {
+		isl_val_free(max);
+		isl_aff_free(lower);
+		return 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_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
+ * any previously found lower bound.
+ */
+static int constraint_find_unroll(__isl_take isl_constraint *c, void *user)
+{
+	struct isl_find_unroll_data *data;
+	int r;
+
+	data = (struct isl_find_unroll_data *) user;
+	r = update_unrolling_lower_bound(data, c);
+	isl_constraint_free(c);
+
+	return r;
+}
+
+/* Look for a lower bound l(i) on the dimension at "depth"
+ * and a size n such that "domain" is a subset of
+ *
+ *	{ [i] : l(i) <= i_d < l(i) + n }
+ *
+ * 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.
+ *
+ * Inner dimensions have been eliminated from "domain" by the caller.
+ *
+ * We first construct a collection of lower bounds on the input set
+ * by computing its simple hull.  We then iterate through them,
+ * discarding those that we cannot use (either because they do not
+ * involve the dimension at "depth" or because they have no corresponding
+ * upper bound, meaning that "n" would be unbounded) and pick out the
+ * best from the remaining ones.
+ *
+ * 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)
+{
+	struct isl_find_unroll_data data = { domain, depth, NULL, n };
+	isl_basic_set *hull;
+
+	hull = isl_set_simple_hull(isl_set_copy(domain));
+
+	if (isl_basic_set_foreach_constraint(hull,
+					    &constraint_find_unroll, &data) < 0)
+		goto error;
+
+	isl_basic_set_free(hull);
+
+	if (!data.lower)
+		isl_die(isl_set_get_ctx(domain), isl_error_invalid,
+			"cannot find lower bound for unrolling", return NULL);
+
+	return data.lower;
+error:
+	isl_basic_set_free(hull);
+	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.
+ *
+ * "list" is the main result of the function and contains a list
+ * of disjoint basic sets for which code should be generated.
+ *
+ * "executed" and "build" are inputs to compute_domains.
+ * "schedule_domain" is the domain of "executed".
+ *
+ * "option" constains the domains at the current depth that should by
+ * atomic, separated or unrolled.  These domains are as specified by
+ * the user, except that inner dimensions have been eliminated and
+ * that they have been made pair-wise disjoint.
+ *
+ * "sep_class" contains the user-specified split into separation classes
+ * specialized to the current depth.
+ * "done" contains the union of the separation domains that have already
+ * been handled.
+ */
+struct isl_codegen_domains {
+	isl_basic_set_list *list;
+
+	isl_union_map *executed;
+	isl_ast_build *build;
+	isl_set *schedule_domain;
+
+	isl_set *option[3];
+
+	isl_map *sep_class;
+	isl_set *done;
+};
+
+/* Extend domains->list with a list of basic sets, one for each value
+ * of the current dimension in "domain" and remove the corresponding
+ * sets from the class domain.  Return the updated class domain.
+ * The divs that involve the current dimension have not been projected out
+ * from this domain.
+ *
+ * Since we are going to be iterating over the individual values,
+ * we first check if there are any strides on the current dimension.
+ * If there is, we rewrite the current dimension i as
+ *
+ *		i = stride i' + offset
+ *
+ * and then iterate over individual values of i' instead.
+ *
+ * We then look for a lower bound on i' and a size such that the domain
+ * is a subset of
+ *
+ *	{ [j,i'] : l(j) <= i' < l(j) + n }
+ *
+ * and then take slices of the domain at values of i'
+ * between l(j) and l(j) + n - 1.
+ *
+ * We compute the unshifted simple hull of each slice to ensure that
+ * we have a single basic set per offset.  The slicing constraint
+ * may get simplified away before the unshifted simple hull is taken
+ * and may therefore in some rare cases disappear from the result.
+ * We therefore explicitly add the constraint back after computing
+ * the unshifted simple hull to ensure that the basic sets
+ * remain disjoint.  The constraints that are dropped by taking the hull
+ * will be taken into account at the next level, as in the case of the
+ * atomic option.
+ *
+ * Finally, we map i' back to i and add each basic set to the list.
+ * Since we may have dropped some constraints, we intersect with
+ * the class domain again to ensure that each element in the list
+ * is disjoint from the other class domains.
+ */
+static __isl_give isl_set *do_unroll(struct isl_codegen_domains *domains,
+	__isl_take isl_set *domain, __isl_take isl_set *class_domain)
+{
+	int i, n;
+	int depth;
+	isl_ctx *ctx;
+	isl_aff *lower;
+	isl_multi_aff *expansion;
+	isl_basic_map *bmap;
+	isl_set *unroll_domain;
+	isl_ast_build *build;
+
+	if (!domain)
+		return isl_set_free(class_domain);
+
+	ctx = isl_set_get_ctx(domain);
+	depth = isl_ast_build_get_depth(domains->build);
+	build = isl_ast_build_copy(domains->build);
+	domain = isl_ast_build_eliminate_inner(build, domain);
+	domain = isl_set_intersect(domain, isl_ast_build_get_domain(build));
+	build = isl_ast_build_detect_strides(build, isl_set_copy(domain));
+	expansion = isl_ast_build_get_stride_expansion(build);
+
+	domain = isl_set_preimage_multi_aff(domain,
+					    isl_multi_aff_copy(expansion));
+	domain = isl_ast_build_eliminate_divs(build, domain);
+
+	isl_ast_build_free(build);
+
+	lower = find_unroll_lower_bound(domain, depth, &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) {
+		isl_set *set;
+		isl_basic_set *bset;
+		isl_constraint *slice;
+		isl_basic_set_list *list;
+
+		slice = at_offset(depth, lower, i);
+		set = isl_set_copy(domain);
+		set = isl_set_add_constraint(set, isl_constraint_copy(slice));
+		bset = isl_set_unshifted_simple_hull(set);
+		bset = isl_basic_set_add_constraint(bset, slice);
+		bset = isl_basic_set_apply(bset, isl_basic_map_copy(bmap));
+		set = isl_set_from_basic_set(bset);
+		unroll_domain = isl_set_union(unroll_domain, isl_set_copy(set));
+		set = isl_set_intersect(set, isl_set_copy(class_domain));
+		set = isl_set_make_disjoint(set);
+		list = isl_basic_set_list_from_set(set);
+		domains->list = isl_basic_set_list_concat(domains->list, list);
+	}
+
+	class_domain = isl_set_subtract(class_domain, unroll_domain);
+
+	isl_aff_free(lower);
+	isl_set_free(domain);
+	isl_basic_map_free(bmap);
+
+	return class_domain;
+}
+
+/* Add domains to domains->list for each individual value of the current
+ * dimension, for that part of the schedule domain that lies in the
+ * intersection of the option domain and the class domain.
+ * Remove the corresponding sets from the class domain and
+ * return the updated class domain.
+ *
+ * We first break up the unroll option domain into individual pieces
+ * and then handle each of them separately.  The unroll option domain
+ * has been made disjoint in compute_domains_init_options,
+ *
+ * Note that we actively want to combine different pieces of the
+ * schedule domain that have the same value at the current dimension.
+ * We therefore need to break up the unroll option domain before
+ * intersecting with class and schedule domain, hoping that the
+ * unroll option domain specified by the user is relatively simple.
+ */
+static __isl_give isl_set *compute_unroll_domains(
+	struct isl_codegen_domains *domains, __isl_take isl_set *class_domain)
+{
+	isl_set *unroll_domain;
+	isl_basic_set_list *unroll_list;
+	int i, n;
+	int empty;
+
+	empty = isl_set_is_empty(domains->option[unroll]);
+	if (empty < 0)
+		return isl_set_free(class_domain);
+	if (empty)
+		return class_domain;
+
+	unroll_domain = isl_set_copy(domains->option[unroll]);
+	unroll_list = isl_basic_set_list_from_set(unroll_domain);
+
+	n = isl_basic_set_list_n_basic_set(unroll_list);
+	for (i = 0; i < n; ++i) {
+		isl_basic_set *bset;
+
+		bset = isl_basic_set_list_get_basic_set(unroll_list, i);
+		unroll_domain = isl_set_from_basic_set(bset);
+		unroll_domain = isl_set_intersect(unroll_domain,
+						    isl_set_copy(class_domain));
+		unroll_domain = isl_set_intersect(unroll_domain,
+					isl_set_copy(domains->schedule_domain));
+
+		empty = isl_set_is_empty(unroll_domain);
+		if (empty >= 0 && empty) {
+			isl_set_free(unroll_domain);
+			continue;
+		}
+
+		class_domain = do_unroll(domains, unroll_domain, class_domain);
+	}
+
+	isl_basic_set_list_free(unroll_list);
+
+	return class_domain;
+}
+
+/* Try and construct a single basic set that includes the intersection of
+ * the schedule domain, the atomic option domain and the class domain.
+ * Add the resulting basic set(s) to domains->list and remove them
+ * from class_domain.  Return the updated class domain.
+ *
+ * We construct a single domain rather than trying to combine
+ * the schedule domains of individual domains because we are working
+ * within a single component so that non-overlapping schedule domains
+ * should already have been separated.
+ * We do however need to make sure that this single domains is a subset
+ * of the class domain so that it would not intersect with any other
+ * class domains.  This means that we may end up splitting up the atomic
+ * domain in case separation classes are being used.
+ *
+ * "domain" is the intersection of the schedule domain and the class domain,
+ * with inner dimensions projected out.
+ */
+static __isl_give isl_set *compute_atomic_domain(
+	struct isl_codegen_domains *domains, __isl_take isl_set *class_domain)
+{
+	isl_basic_set *bset;
+	isl_basic_set_list *list;
+	isl_set *domain, *atomic_domain;
+	int empty;
+
+	domain = isl_set_copy(domains->option[atomic]);
+	domain = isl_set_intersect(domain, isl_set_copy(class_domain));
+	domain = isl_set_intersect(domain,
+				isl_set_copy(domains->schedule_domain));
+	empty = isl_set_is_empty(domain);
+	if (empty < 0)
+		class_domain = isl_set_free(class_domain);
+	if (empty) {
+		isl_set_free(domain);
+		return class_domain;
+	}
+
+	domain = isl_ast_build_eliminate(domains->build, domain);
+	domain = isl_set_coalesce(domain);
+	bset = isl_set_unshifted_simple_hull(domain);
+	domain = isl_set_from_basic_set(bset);
+	atomic_domain = isl_set_copy(domain);
+	domain = isl_set_intersect(domain, isl_set_copy(class_domain));
+	class_domain = isl_set_subtract(class_domain, atomic_domain);
+	domain = isl_set_make_disjoint(domain);
+	list = isl_basic_set_list_from_set(domain);
+	domains->list = isl_basic_set_list_concat(domains->list, list);
+
+	return class_domain;
+}
+
+/* Split up the schedule domain into uniform basic sets,
+ * in the sense that each element in a basic set is associated to
+ * elements of the same domains, and add the result to domains->list.
+ * Do this for that part of the schedule domain that lies in the
+ * intersection of "class_domain" and the separate option domain.
+ *
+ * "class_domain" may or may not include the constraints
+ * of the schedule domain, but this does not make a difference
+ * since we are going to intersect it with the domain of the inverse schedule.
+ * If it includes schedule domain constraints, then they may involve
+ * inner dimensions, but we will eliminate them in separation_domain.
+ */
+static int compute_separate_domain(struct isl_codegen_domains *domains,
+	__isl_keep isl_set *class_domain)
+{
+	isl_space *space;
+	isl_set *domain;
+	isl_union_map *executed;
+	isl_basic_set_list *list;
+	int empty;
+
+	domain = isl_set_copy(domains->option[separate]);
+	domain = isl_set_intersect(domain, isl_set_copy(class_domain));
+	executed = isl_union_map_copy(domains->executed);
+	executed = isl_union_map_intersect_domain(executed,
+				    isl_union_set_from_set(domain));
+	empty = isl_union_map_is_empty(executed);
+	if (empty < 0 || empty) {
+		isl_union_map_free(executed);
+		return empty < 0 ? -1 : 0;
+	}
+
+	space = isl_set_get_space(class_domain);
+	domain = separate_schedule_domains(space, executed, domains->build);
+
+	list = isl_basic_set_list_from_set(domain);
+	domains->list = isl_basic_set_list_concat(domains->list, list);
+
+	return 0;
+}
+
+/* Split up the domain at the current depth into disjoint
+ * basic sets for which code should be generated separately
+ * for the given separation class domain.
+ *
+ * If any separation classes have been defined, then "class_domain"
+ * is the domain of the current class and does not refer to inner dimensions.
+ * Otherwise, "class_domain" is the universe domain.
+ *
+ * We first make sure that the class domain is disjoint from
+ * previously considered class domains.
+ *
+ * The separate domains can be computed directly from the "class_domain".
+ *
+ * The unroll, atomic and remainder domains need the constraints
+ * from the schedule domain.
+ *
+ * For unrolling, the actual schedule domain is needed (with divs that
+ * may refer to the current dimension) so that stride detection can be
+ * performed.
+ *
+ * For atomic and remainder domains, inner dimensions and divs involving
+ * the current dimensions should be eliminated.
+ * In case we are working within a separation class, we need to intersect
+ * the result with the current "class_domain" to ensure that the domains
+ * are disjoint from those generated from other class domains.
+ *
+ * The domain that has been made atomic may be larger than specified
+ * by the user since it needs to be representable as a single basic set.
+ * This possibly larger domain is removed from class_domain by
+ * compute_atomic_domain.  It is computed first so that the extended domain
+ * would not overlap with any domains computed before.
+ * Similary, the unrolled domains may have some constraints removed and
+ * may therefore also be larger than specified by the user.
+ *
+ * If anything is left after handling separate, unroll and atomic,
+ * we split it up into basic sets and append the basic sets to domains->list.
+ */
+static int compute_partial_domains(struct isl_codegen_domains *domains,
+	__isl_take isl_set *class_domain)
+{
+	isl_basic_set_list *list;
+	isl_set *domain;
+
+	class_domain = isl_set_subtract(class_domain,
+					isl_set_copy(domains->done));
+	domains->done = isl_set_union(domains->done,
+					isl_set_copy(class_domain));
+
+	class_domain = compute_atomic_domain(domains, class_domain);
+	class_domain = compute_unroll_domains(domains, class_domain);
+
+	domain = isl_set_copy(class_domain);
+
+	if (compute_separate_domain(domains, domain) < 0)
+		goto error;
+	domain = isl_set_subtract(domain,
+				    isl_set_copy(domains->option[separate]));
+
+	domain = isl_set_intersect(domain,
+				isl_set_copy(domains->schedule_domain));
+
+	domain = isl_ast_build_eliminate(domains->build, domain);
+	domain = isl_set_intersect(domain, isl_set_copy(class_domain));
+
+	domain = isl_set_coalesce(domain);
+	domain = isl_set_make_disjoint(domain);
+
+	list = isl_basic_set_list_from_set(domain);
+	domains->list = isl_basic_set_list_concat(domains->list, list);
+
+	isl_set_free(class_domain);
+
+	return 0;
+error:
+	isl_set_free(domain);
+	isl_set_free(class_domain);
+	return -1;
+}
+
+/* Split up the domain at the current depth into disjoint
+ * basic sets for which code should be generated separately
+ * for the separation class identified by "pnt".
+ *
+ * We extract the corresponding class domain from domains->sep_class,
+ * eliminate inner dimensions and pass control to compute_partial_domains.
+ */
+static int compute_class_domains(__isl_take isl_point *pnt, void *user)
+{
+	struct isl_codegen_domains *domains = user;
+	isl_set *class_set;
+	isl_set *domain;
+	int disjoint;
+
+	class_set = isl_set_from_point(pnt);
+	domain = isl_map_domain(isl_map_intersect_range(
+				isl_map_copy(domains->sep_class), class_set));
+	domain = isl_ast_build_compute_gist(domains->build, domain);
+	domain = isl_ast_build_eliminate(domains->build, domain);
+
+	disjoint = isl_set_plain_is_disjoint(domain, domains->schedule_domain);
+	if (disjoint < 0)
+		return -1;
+	if (disjoint) {
+		isl_set_free(domain);
+		return 0;
+	}
+
+	return compute_partial_domains(domains, domain);
+}
+
+/* Extract the domains at the current depth that should be atomic,
+ * separated or unrolled and store them in option.
+ *
+ * The domains specified by the user might overlap, so we make
+ * them disjoint by subtracting earlier domains from later domains.
+ */
+static void compute_domains_init_options(isl_set *option[3],
+	__isl_keep isl_ast_build *build)
+{
+	enum isl_ast_build_domain_type type, type2;
+
+	for (type = atomic; type <= separate; ++type) {
+		option[type] = isl_ast_build_get_option_domain(build, type);
+		for (type2 = atomic; type2 < type; ++type2)
+			option[type] = isl_set_subtract(option[type],
+						isl_set_copy(option[type2]));
+	}
+
+	option[unroll] = isl_set_coalesce(option[unroll]);
+	option[unroll] = isl_set_make_disjoint(option[unroll]);
+}
+
+/* Split up the domain at the current depth into disjoint
+ * basic sets for which code should be generated separately,
+ * based on the user-specified options.
+ * Return the list of disjoint basic sets.
+ *
+ * There are three kinds of domains that we need to keep track of.
+ * - the "schedule domain" is the domain of "executed"
+ * - the "class domain" is the domain corresponding to the currrent
+ *	separation class
+ * - the "option domain" is the domain corresponding to one of the options
+ *	atomic, unroll or separate
+ *
+ * We first consider the individial values of the separation classes
+ * and split up the domain for each of them separately.
+ * Finally, we consider the remainder.  If no separation classes were
+ * specified, then we call compute_partial_domains with the universe
+ * "class_domain".  Otherwise, we take the "schedule_domain" as "class_domain",
+ * with inner dimensions removed.  We do this because we want to
+ * avoid computing the complement of the class domains (i.e., the difference
+ * between the universe and domains->done).
+ */
+static __isl_give isl_basic_set_list *compute_domains(
+	__isl_keep isl_union_map *executed, __isl_keep isl_ast_build *build)
+{
+	struct isl_codegen_domains domains;
+	isl_ctx *ctx;
+	isl_set *domain;
+	isl_union_set *schedule_domain;
+	isl_set *classes;
+	isl_space *space;
+	int n_param;
+	enum isl_ast_build_domain_type type;
+	int empty;
+
+	if (!executed)
+		return NULL;
+
+	ctx = isl_union_map_get_ctx(executed);
+	domains.list = isl_basic_set_list_alloc(ctx, 0);
+
+	schedule_domain = isl_union_map_domain(isl_union_map_copy(executed));
+	domain = isl_set_from_union_set(schedule_domain);
+
+	compute_domains_init_options(domains.option, build);
+
+	domains.sep_class = isl_ast_build_get_separation_class(build);
+	classes = isl_map_range(isl_map_copy(domains.sep_class));
+	n_param = isl_set_dim(classes, isl_dim_param);
+	classes = isl_set_project_out(classes, isl_dim_param, 0, n_param);
+
+	space = isl_set_get_space(domain);
+	domains.build = build;
+	domains.schedule_domain = isl_set_copy(domain);
+	domains.executed = executed;
+	domains.done = isl_set_empty(space);
+
+	if (isl_set_foreach_point(classes, &compute_class_domains, &domains) < 0)
+		domains.list = isl_basic_set_list_free(domains.list);
+	isl_set_free(classes);
+
+	empty = isl_set_is_empty(domains.done);
+	if (empty < 0) {
+		domains.list = isl_basic_set_list_free(domains.list);
+		domain = isl_set_free(domain);
+	} else if (empty) {
+		isl_set_free(domain);
+		domain = isl_set_universe(isl_set_get_space(domains.done));
+	} else {
+		domain = isl_ast_build_eliminate(build, domain);
+	}
+	if (compute_partial_domains(&domains, domain) < 0)
+		domains.list = isl_basic_set_list_free(domains.list);
+
+	isl_set_free(domains.schedule_domain);
+	isl_set_free(domains.done);
+	isl_map_free(domains.sep_class);
+	for (type = atomic; type <= separate; ++type)
+		isl_set_free(domains.option[type]);
+
+	return domains.list;
+}
+
+/* Generate code for a single component, after shifting (if any)
+ * has been applied.
+ *
+ * We first split up the domain at the current depth into disjoint
+ * basic sets based on the user-specified options.
+ * Then we generated code for each of them and concatenate the results.
+ */
+static __isl_give isl_ast_graft_list *generate_shifted_component(
+	__isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+	isl_basic_set_list *domain_list;
+	isl_ast_graft_list *list = NULL;
+
+	domain_list = compute_domains(executed, build);
+	list = generate_parallel_domains(domain_list, executed, build);
+
+	isl_basic_set_list_free(domain_list);
+	isl_union_map_free(executed);
+	isl_ast_build_free(build);
+
+	return list;
+}
+
+struct isl_set_map_pair {
+	isl_set *set;
+	isl_map *map;
+};
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * return the union of the "map" fields of the elements
+ * indexed by the first "n" elements of "order".
+ */
+static __isl_give isl_union_map *construct_component_executed(
+	struct isl_set_map_pair *domain, int *order, int n)
+{
+	int i;
+	isl_map *map;
+	isl_union_map *executed;
+
+	map = isl_map_copy(domain[order[0]].map);
+	executed = isl_union_map_from_map(map);
+	for (i = 1; i < n; ++i) {
+		map = isl_map_copy(domain[order[i]].map);
+		executed = isl_union_map_add_map(executed, map);
+	}
+
+	return executed;
+}
+
+/* Generate code for a single component, after shifting (if any)
+ * has been applied.
+ *
+ * The component inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ */
+static __isl_give isl_ast_graft_list *generate_shifted_component_from_list(
+	struct isl_set_map_pair *domain, int *order, int n,
+	__isl_take isl_ast_build *build)
+{
+	isl_union_map *executed;
+
+	executed = construct_component_executed(domain, order, n);
+	return generate_shifted_component(executed, build);
+}
+
+/* Does set dimension "pos" of "set" have an obviously fixed value?
+ */
+static int dim_is_fixed(__isl_keep isl_set *set, int pos)
+{
+	int fixed;
+	isl_val *v;
+
+	v = isl_set_plain_get_val_if_fixed(set, isl_dim_set, pos);
+	if (!v)
+		return -1;
+	fixed = !isl_val_is_nan(v);
+	isl_val_free(v);
+
+	return fixed;
+}
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * do all (except for at most one) of the "set" field of the elements
+ * indexed by the first "n" elements of "order" have a fixed value
+ * at position "depth"?
+ */
+static int at_most_one_non_fixed(struct isl_set_map_pair *domain,
+	int *order, int n, int depth)
+{
+	int i;
+	int non_fixed = -1;
+
+	for (i = 0; i < n; ++i) {
+		int f;
+
+		f = dim_is_fixed(domain[order[i]].set, depth);
+		if (f < 0)
+			return -1;
+		if (f)
+			continue;
+		if (non_fixed >= 0)
+			return 0;
+		non_fixed = i;
+	}
+
+	return 1;
+}
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * eliminate the inner dimensions from the "set" field of the elements
+ * indexed by the first "n" elements of "order", provided the current
+ * dimension does not have a fixed value.
+ *
+ * Return the index of the first element in "order" with a corresponding
+ * "set" field that does not have an (obviously) fixed value.
+ */
+static int eliminate_non_fixed(struct isl_set_map_pair *domain,
+	int *order, int n, int depth, __isl_keep isl_ast_build *build)
+{
+	int i;
+	int base = -1;
+
+	for (i = n - 1; i >= 0; --i) {
+		int f;
+		f = dim_is_fixed(domain[order[i]].set, depth);
+		if (f < 0)
+			return -1;
+		if (f)
+			continue;
+		domain[order[i]].set = isl_ast_build_eliminate_inner(build,
+							domain[order[i]].set);
+		base = i;
+	}
+
+	return base;
+}
+
+/* Given an array "domain" of isl_set_map_pairs and an array "order"
+ * of indices into the "domain" array,
+ * find the element of "domain" (amongst those indexed by the first "n"
+ * elements of "order") with the "set" field that has the smallest
+ * value for the current iterator.
+ *
+ * Note that the domain with the smallest value may depend on the parameters
+ * and/or outer loop dimension.  Since the result of this function is only
+ * used as heuristic, we only make a reasonable attempt at finding the best
+ * domain, one that should work in case a single domain provides the smallest
+ * value for the current dimension over all values of the parameters
+ * and outer dimensions.
+ *
+ * In particular, we compute the smallest value of the first domain
+ * and replace it by that of any later domain if that later domain
+ * has a smallest value that is smaller for at least some value
+ * of the parameters and outer dimensions.
+ */
+static int first_offset(struct isl_set_map_pair *domain, int *order, int n,
+	__isl_keep isl_ast_build *build)
+{
+	int i;
+	isl_map *min_first;
+	int first = 0;
+
+	min_first = isl_ast_build_map_to_iterator(build,
+					isl_set_copy(domain[order[0]].set));
+	min_first = isl_map_lexmin(min_first);
+
+	for (i = 1; i < n; ++i) {
+		isl_map *min, *test;
+		int empty;
+
+		min = isl_ast_build_map_to_iterator(build,
+					isl_set_copy(domain[order[i]].set));
+		min = isl_map_lexmin(min);
+		test = isl_map_copy(min);
+		test = isl_map_apply_domain(isl_map_copy(min_first), test);
+		test = isl_map_order_lt(test, isl_dim_in, 0, isl_dim_out, 0);
+		empty = isl_map_is_empty(test);
+		isl_map_free(test);
+		if (empty >= 0 && !empty) {
+			isl_map_free(min_first);
+			first = i;
+			min_first = min;
+		} else
+			isl_map_free(min);
+
+		if (empty < 0)
+			break;
+	}
+
+	isl_map_free(min_first);
+
+	return i < n ? -1 : first;
+}
+
+/* Construct a shifted inverse schedule based on the original inverse schedule,
+ * the stride and the offset.
+ *
+ * The original inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ *
+ * "stride" and "offset" are such that the difference
+ * between the values of the current dimension of domain "i"
+ * and the values of the current dimension for some reference domain are
+ * equal to
+ *
+ *	stride * integer + offset[i]
+ *
+ * Moreover, 0 <= offset[i] < stride.
+ *
+ * For each domain, we create a map
+ *
+ *	{ [..., j, ...] -> [..., j - offset[i], offset[i], ....] }
+ *
+ * where j refers to the current dimension and the other dimensions are
+ * unchanged, and apply this map to the original schedule domain.
+ *
+ * For example, for the original schedule
+ *
+ *	{ A[i] -> [2i]: 0 <= i < 10; B[i] -> [2i+1] : 0 <= i < 10 }
+ *
+ * and assuming the offset is 0 for the A domain and 1 for the B domain,
+ * we apply the mapping
+ *
+ *	{ [j] -> [j, 0] }
+ *
+ * to the schedule of the "A" domain and the mapping
+ *
+ *	{ [j - 1] -> [j, 1] }
+ *
+ * to the schedule of the "B" domain.
+ *
+ *
+ * Note that after the transformation, the differences between pairs
+ * of values of the current dimension over all domains are multiples
+ * of stride and that we have therefore exposed the stride.
+ *
+ *
+ * To see that the mapping preserves the lexicographic order,
+ * first note that each of the individual maps above preserves the order.
+ * If the value of the current iterator is j1 in one domain and j2 in another,
+ * then if j1 = j2, we know that the same map is applied to both domains
+ * and the order is preserved.
+ * Otherwise, let us assume, without loss of generality, that j1 < j2.
+ * If c1 >= c2 (with c1 and c2 the corresponding offsets), then
+ *
+ *	j1 - c1 < j2 - c2
+ *
+ * and the order is preserved.
+ * If c1 < c2, then we know
+ *
+ *	0 <= c2 - c1 < s
+ *
+ * We also have
+ *
+ *	j2 - j1 = n * s + r
+ *
+ * with n >= 0 and 0 <= r < s.
+ * In other words, r = c2 - c1.
+ * If n > 0, then
+ *
+ *	j1 - c1 < j2 - c2
+ *
+ * If n = 0, then
+ *
+ *	j1 - c1 = j2 - c2
+ *
+ * and so
+ *
+ *	(j1 - c1, c1) << (j2 - c2, c2)
+ *
+ * with "<<" the lexicographic order, proving that the order is preserved
+ * in all cases.
+ */
+static __isl_give isl_union_map *contruct_shifted_executed(
+	struct isl_set_map_pair *domain, int *order, int n,
+	__isl_keep isl_val *stride, __isl_keep isl_multi_val *offset,
+	__isl_take isl_ast_build *build)
+{
+	int i;
+	isl_union_map *executed;
+	isl_space *space;
+	isl_map *map;
+	int depth;
+	isl_constraint *c;
+
+	depth = isl_ast_build_get_depth(build);
+	space = isl_ast_build_get_space(build, 1);
+	executed = isl_union_map_empty(isl_space_copy(space));
+	space = isl_space_map_from_set(space);
+	map = isl_map_identity(isl_space_copy(space));
+	map = isl_map_eliminate(map, isl_dim_out, depth, 1);
+	map = isl_map_insert_dims(map, isl_dim_out, depth + 1, 1);
+	space = isl_space_insert_dims(space, isl_dim_out, depth + 1, 1);
+
+	c = isl_equality_alloc(isl_local_space_from_space(space));
+	c = isl_constraint_set_coefficient_si(c, isl_dim_in, depth, 1);
+	c = isl_constraint_set_coefficient_si(c, isl_dim_out, depth, -1);
+
+	for (i = 0; i < n; ++i) {
+		isl_map *map_i;
+		isl_val *v;
+
+		v = isl_multi_val_get_val(offset, i);
+		if (!v)
+			break;
+		map_i = isl_map_copy(map);
+		map_i = isl_map_fix_val(map_i, isl_dim_out, depth + 1,
+					isl_val_copy(v));
+		v = isl_val_neg(v);
+		c = isl_constraint_set_constant_val(c, v);
+		map_i = isl_map_add_constraint(map_i, isl_constraint_copy(c));
+
+		map_i = isl_map_apply_domain(isl_map_copy(domain[order[i]].map),
+						map_i);
+		executed = isl_union_map_add_map(executed, map_i);
+	}
+
+	isl_constraint_free(c);
+	isl_map_free(map);
+
+	if (i < n)
+		executed = isl_union_map_free(executed);
+
+	return executed;
+}
+
+/* Generate code for a single component, after exposing the stride,
+ * given that the schedule domain is "shifted strided".
+ *
+ * The component inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ *
+ * The schedule domain being "shifted strided" means that the differences
+ * between the values of the current dimension of domain "i"
+ * and the values of the current dimension for some reference domain are
+ * equal to
+ *
+ *	stride * integer + offset[i]
+ *
+ * We first look for the domain with the "smallest" value for the current
+ * dimension and adjust the offsets such that the offset of the "smallest"
+ * domain is equal to zero.  The other offsets are reduced modulo stride.
+ *
+ * Based on this information, we construct a new inverse schedule in
+ * contruct_shifted_executed that exposes the stride.
+ * Since this involves the introduction of a new schedule dimension,
+ * the build needs to be changed accodingly.
+ * After computing the AST, the newly introduced dimension needs
+ * to be removed again from the list of grafts.  We do this by plugging
+ * in a mapping that represents the new schedule domain in terms of the
+ * old schedule domain.
+ */
+static __isl_give isl_ast_graft_list *generate_shift_component(
+	struct isl_set_map_pair *domain, int *order, int n,
+	__isl_keep isl_val *stride, __isl_keep isl_multi_val *offset,
+	__isl_take isl_ast_build *build)
+{
+	isl_ast_graft_list *list;
+	int first;
+	int depth;
+	isl_ctx *ctx;
+	isl_val *val;
+	isl_multi_val *mv;
+	isl_space *space;
+	isl_multi_aff *ma, *zero;
+	isl_union_map *executed;
+
+	ctx = isl_ast_build_get_ctx(build);
+	depth = isl_ast_build_get_depth(build);
+
+	first = first_offset(domain, order, n, build);
+	if (first < 0)
+		goto error;
+
+	mv = isl_multi_val_copy(offset);
+	val = isl_multi_val_get_val(offset, first);
+	val = isl_val_neg(val);
+	mv = isl_multi_val_add_val(mv, val);
+	mv = isl_multi_val_mod_val(mv, isl_val_copy(stride));
+
+	executed = contruct_shifted_executed(domain, order, n, stride, mv,
+						build);
+	space = isl_ast_build_get_space(build, 1);
+	space = isl_space_map_from_set(space);
+	ma = isl_multi_aff_identity(isl_space_copy(space));
+	space = isl_space_from_domain(isl_space_domain(space));
+	space = isl_space_add_dims(space, isl_dim_out, 1);
+	zero = isl_multi_aff_zero(space);
+	ma = isl_multi_aff_range_splice(ma, depth + 1, zero);
+	build = isl_ast_build_insert_dim(build, depth + 1);
+	list = generate_shifted_component(executed, build);
+
+	list = isl_ast_graft_list_preimage_multi_aff(list, ma);
+
+	isl_multi_val_free(mv);
+
+	return list;
+error:
+	isl_ast_build_free(build);
+	return NULL;
+}
+
+/* Generate code for a single component.
+ *
+ * The component inverse schedule is specified as the "map" fields
+ * of the elements of "domain" indexed by the first "n" elements of "order".
+ *
+ * This function may modify the "set" fields of "domain".
+ *
+ * Before proceeding with the actual code generation for the component,
+ * we first check if there are any "shifted" strides, meaning that
+ * the schedule domains of the individual domains are all strided,
+ * but that they have different offsets, resulting in the union
+ * of schedule domains not being strided anymore.
+ *
+ * The simplest example is the schedule
+ *
+ *	{ A[i] -> [2i]: 0 <= i < 10; B[i] -> [2i+1] : 0 <= i < 10 }
+ *
+ * Both schedule domains are strided, but their union is not.
+ * This function detects such cases and then rewrites the schedule to
+ *
+ *	{ A[i] -> [2i, 0]: 0 <= i < 10; B[i] -> [2i, 1] : 0 <= i < 10 }
+ *
+ * In the new schedule, the schedule domains have the same offset (modulo
+ * the stride), ensuring that the union of schedule domains is also strided.
+ *
+ *
+ * If there is only a single domain in the component, then there is
+ * nothing to do.   Similarly, if the current schedule dimension has
+ * a fixed value for almost all domains then there is nothing to be done.
+ * In particular, we need at least two domains where the current schedule
+ * dimension does not have a fixed value.
+ * Finally, if any of the options refer to the current schedule dimension,
+ * then we bail out as well.  It would be possible to reformulate the options
+ * in terms of the new schedule domain, but that would introduce constraints
+ * that separate the domains in the options and that is something we would
+ * like to avoid.
+ *
+ *
+ * To see if there is any shifted stride, we look at the differences
+ * between the values of the current dimension in pairs of domains
+ * for equal values of outer dimensions.  These differences should be
+ * of the form
+ *
+ *	m x + r
+ *
+ * with "m" the stride and "r" a constant.  Note that we cannot perform
+ * this analysis on individual domains as the lower bound in each domain
+ * may depend on parameters or outer dimensions and so the current dimension
+ * itself may not have a fixed remainder on division by the stride.
+ *
+ * In particular, we compare the first domain that does not have an
+ * obviously fixed value for the current dimension to itself and all
+ * other domains and collect the offsets and the gcd of the strides.
+ * If the gcd becomes one, then we failed to find shifted strides.
+ * If the gcd is zero, then the differences were all fixed, meaning
+ * that some domains had non-obviously fixed values for the current dimension.
+ * If all the offsets are the same (for those domains that do not have
+ * an obviously fixed value for the current dimension), then we do not
+ * apply the transformation.
+ * If none of the domains were skipped, then there is nothing to do.
+ * If some of them were skipped, then if we apply separation, the schedule
+ * domain should get split in pieces with a (non-shifted) stride.
+ *
+ * Otherwise, we apply a shift to expose the stride in
+ * generate_shift_component.
+ */
+static __isl_give isl_ast_graft_list *generate_component(
+	struct isl_set_map_pair *domain, int *order, int n,
+	__isl_take isl_ast_build *build)
+{
+	int i, d;
+	int depth;
+	isl_ctx *ctx;
+	isl_map *map;
+	isl_set *deltas;
+	isl_val *gcd = NULL;
+	isl_multi_val *mv;
+	int fixed, skip;
+	int base;
+	isl_ast_graft_list *list;
+	int res = 0;
+
+	depth = isl_ast_build_get_depth(build);
+
+	skip = n == 1;
+	if (skip >= 0 && !skip)
+		skip = at_most_one_non_fixed(domain, order, n, depth);
+	if (skip >= 0 && !skip)
+		skip = isl_ast_build_options_involve_depth(build);
+	if (skip < 0)
+		goto error;
+	if (skip)
+		return generate_shifted_component_from_list(domain,
+							    order, n, build);
+
+	base = eliminate_non_fixed(domain, order, n, depth, build);
+	if (base < 0)
+		goto error;
+
+	ctx = isl_ast_build_get_ctx(build);
+
+	mv = isl_multi_val_zero(isl_space_set_alloc(ctx, 0, n));
+
+	fixed = 1;
+	for (i = 0; i < n; ++i) {
+		isl_val *r, *m;
+
+		map = isl_map_from_domain_and_range(
+					isl_set_copy(domain[order[base]].set),
+					isl_set_copy(domain[order[i]].set));
+		for (d = 0; d < depth; ++d)
+			map = isl_map_equate(map, isl_dim_in, d,
+						    isl_dim_out, d);
+		deltas = isl_map_deltas(map);
+		res = isl_set_dim_residue_class_val(deltas, depth, &m, &r);
+		isl_set_free(deltas);
+		if (res < 0)
+			break;
+
+		if (i == 0)
+			gcd = m;
+		else
+			gcd = isl_val_gcd(gcd, m);
+		if (isl_val_is_one(gcd)) {
+			isl_val_free(r);
+			break;
+		}
+		mv = isl_multi_val_set_val(mv, i, r);
+
+		res = dim_is_fixed(domain[order[i]].set, depth);
+		if (res < 0)
+			break;
+		if (res)
+			continue;
+
+		if (fixed && i > base) {
+			isl_val *a, *b;
+			a = isl_multi_val_get_val(mv, i);
+			b = isl_multi_val_get_val(mv, base);
+			if (isl_val_ne(a, b))
+				fixed = 0;
+			isl_val_free(a);
+			isl_val_free(b);
+		}
+	}
+
+	if (res < 0 || !gcd) {
+		isl_ast_build_free(build);
+		list = NULL;
+	} else if (i < n || fixed || isl_val_is_zero(gcd)) {
+		list = generate_shifted_component_from_list(domain,
+							    order, n, build);
+	} else {
+		list = generate_shift_component(domain, order, n, gcd, mv,
+						build);
+	}
+
+	isl_val_free(gcd);
+	isl_multi_val_free(mv);
+
+	return list;
+error:
+	isl_ast_build_free(build);
+	return NULL;
+}
+
+/* Store both "map" itself and its domain in the
+ * structure pointed to by *next and advance to the next array element.
+ */
+static int extract_domain(__isl_take isl_map *map, void *user)
+{
+	struct isl_set_map_pair **next = user;
+
+	(*next)->map = isl_map_copy(map);
+	(*next)->set = isl_map_domain(map);
+	(*next)++;
+
+	return 0;
+}
+
+/* Internal data for any_scheduled_after.
+ *
+ * "depth" is the number of loops that have already been generated
+ * "group_coscheduled" is a local copy of options->ast_build_group_coscheduled
+ * "domain" is an array of set-map pairs corresponding to the different
+ * iteration domains.  The set is the schedule domain, i.e., the domain
+ * of the inverse schedule, while the map is the inverse schedule itself.
+ */
+struct isl_any_scheduled_after_data {
+	int depth;
+	int group_coscheduled;
+	struct isl_set_map_pair *domain;
+};
+
+/* Is any element of domain "i" scheduled after any element of domain "j"
+ * (for a common iteration of the first data->depth loops)?
+ *
+ * data->domain[i].set contains the domain of the inverse schedule
+ * for domain "i", i.e., elements in the schedule domain.
+ *
+ * If data->group_coscheduled is set, then we also return 1 if there
+ * is any pair of elements in the two domains that are scheduled together.
+ */
+static int any_scheduled_after(int i, int j, void *user)
+{
+	struct isl_any_scheduled_after_data *data = user;
+	int dim = isl_set_dim(data->domain[i].set, isl_dim_set);
+	int pos;
+
+	for (pos = data->depth; pos < dim; ++pos) {
+		int follows;
+
+		follows = isl_set_follows_at(data->domain[i].set,
+						data->domain[j].set, pos);
+
+		if (follows < -1)
+			return -1;
+		if (follows > 0)
+			return 1;
+		if (follows < 0)
+			return 0;
+	}
+
+	return data->group_coscheduled;
+}
+
+/* Look for independent components at the current depth and generate code
+ * for each component separately.  The resulting lists of grafts are
+ * merged in an attempt to combine grafts with identical guards.
+ *
+ * Code for two domains can be generated separately if all the elements
+ * of one domain are scheduled before (or together with) all the elements
+ * of the other domain.  We therefore consider the graph with as nodes
+ * the domains and an edge between two nodes if any element of the first
+ * node is scheduled after any element of the second node.
+ * If the ast_build_group_coscheduled is set, then we also add an edge if
+ * there is any pair of elements in the two domains that are scheduled
+ * together.
+ * Code is then generated (by generate_component)
+ * for each of the strongly connected components in this graph
+ * in their topological order.
+ *
+ * Since the test is performed on the domain of the inverse schedules of
+ * the different domains, we precompute these domains and store
+ * them in data.domain.
+ */
+static __isl_give isl_ast_graft_list *generate_components(
+	__isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+	int i;
+	isl_ctx *ctx = isl_ast_build_get_ctx(build);
+	int n = isl_union_map_n_map(executed);
+	struct isl_any_scheduled_after_data data;
+	struct isl_set_map_pair *next;
+	struct isl_tarjan_graph *g = NULL;
+	isl_ast_graft_list *list = NULL;
+	int n_domain = 0;
+
+	data.domain = isl_calloc_array(ctx, struct isl_set_map_pair, n);
+	if (!data.domain)
+		goto error;
+	n_domain = n;
+
+	next = data.domain;
+	if (isl_union_map_foreach_map(executed, &extract_domain, &next) < 0)
+		goto error;
+
+	if (!build)
+		goto error;
+	data.depth = isl_ast_build_get_depth(build);
+	data.group_coscheduled = isl_options_get_ast_build_group_coscheduled(ctx);
+	g = isl_tarjan_graph_init(ctx, n, &any_scheduled_after, &data);
+	if (!g)
+		goto error;
+
+	list = isl_ast_graft_list_alloc(ctx, 0);
+
+	i = 0;
+	while (list && n) {
+		isl_ast_graft_list *list_c;
+		int first = i;
+
+		if (g->order[i] == -1)
+			isl_die(ctx, isl_error_internal, "cannot happen",
+				goto error);
+		++i; --n;
+		while (g->order[i] != -1) {
+			++i; --n;
+		}
+
+		list_c = generate_component(data.domain,
+					    g->order + first, i - first,
+					    isl_ast_build_copy(build));
+		list = isl_ast_graft_list_merge(list, list_c, build);
+
+		++i;
+	}
+
+	if (0)
+error:		list = isl_ast_graft_list_free(list);
+	isl_tarjan_graph_free(g);
+	for (i = 0; i < n_domain; ++i) {
+		isl_map_free(data.domain[i].map);
+		isl_set_free(data.domain[i].set);
+	}
+	free(data.domain);
+	isl_union_map_free(executed);
+	isl_ast_build_free(build);
+
+	return list;
+}
+
+/* Generate code for the next level (and all inner levels).
+ *
+ * If "executed" is empty, i.e., no code needs to be generated,
+ * then we return an empty list.
+ *
+ * If we have already generated code for all loop levels, then we pass
+ * control to generate_inner_level.
+ *
+ * If "executed" lives in a single space, i.e., if code needs to be
+ * generated for a single domain, then there can only be a single
+ * component and we go directly to generate_shifted_component.
+ * Otherwise, we call generate_components to detect the components
+ * and to call generate_component on each of them separately.
+ */
+static __isl_give isl_ast_graft_list *generate_next_level(
+	__isl_take isl_union_map *executed, __isl_take isl_ast_build *build)
+{
+	int depth;
+
+	if (!build || !executed)
+		goto error;
+
+	if (isl_union_map_is_empty(executed)) {
+		isl_ctx *ctx = isl_ast_build_get_ctx(build);
+		isl_union_map_free(executed);
+		isl_ast_build_free(build);
+		return isl_ast_graft_list_alloc(ctx, 0);
+	}
+
+	depth = isl_ast_build_get_depth(build);
+	if (depth >= isl_ast_build_dim(build, isl_dim_set))
+		return generate_inner_level(executed, build);
+
+	if (isl_union_map_n_map(executed) == 1)
+		return generate_shifted_component(executed, build);
+
+	return generate_components(executed, build);
+error:
+	isl_union_map_free(executed);
+	isl_ast_build_free(build);
+	return NULL;
+}
+
+/* Internal data structure used by isl_ast_build_ast_from_schedule.
+ * internal, executed and build are the inputs to generate_code.
+ * list collects the output.
+ */
+struct isl_generate_code_data {
+	int internal;
+	isl_union_map *executed;
+	isl_ast_build *build;
+
+	isl_ast_graft_list *list;
+};
+
+/* Given an inverse schedule in terms of the external build schedule, i.e.,
+ *
+ *	[E -> S] -> D
+ *
+ * with E the external build schedule and S the additional schedule "space",
+ * reformulate the inverse schedule in terms of the internal schedule domain,
+ * i.e., return
+ *
+ *	[I -> S] -> D
+ *
+ * We first obtain a mapping
+ *
+ *	I -> E
+ *
+ * take the inverse and the product with S -> S, resulting in
+ *
+ *	[I -> S] -> [E -> S]
+ *
+ * Applying the map to the input produces the desired result.
+ */
+static __isl_give isl_union_map *internal_executed(
+	__isl_take isl_union_map *executed, __isl_keep isl_space *space,
+	__isl_keep isl_ast_build *build)
+{
+	isl_map *id, *proj;
+
+	proj = isl_ast_build_get_schedule_map(build);
+	proj = isl_map_reverse(proj);
+	space = isl_space_map_from_set(isl_space_copy(space));
+	id = isl_map_identity(space);
+	proj = isl_map_product(proj, id);
+	executed = isl_union_map_apply_domain(executed,
+						isl_union_map_from_map(proj));
+	return executed;
+}
+
+/* Generate an AST that visits the elements in the range of data->executed
+ * in the relative order specified by the corresponding domain element(s)
+ * for those domain elements that belong to "set".
+ * Add the result to data->list.
+ *
+ * The caller ensures that "set" is a universe domain.
+ * "space" is the space of the additional part of the schedule.
+ * It is equal to the space of "set" if build->domain is parametric.
+ * Otherwise, it is equal to the range of the wrapped space of "set".
+ *
+ * If the build space is not parametric and if isl_ast_build_ast_from_schedule
+ * was called from an outside user (data->internal not set), then
+ * the (inverse) schedule refers to the external build domain and needs to
+ * be transformed to refer to the internal build domain.
+ *
+ * If the build space is parametric, then we add some of the parameter
+ * constraints to the executed relation.  Adding these constraints
+ * allows for an earlier detection of conflicts in some cases.
+ * However, we do not want to divide the executed relation into
+ * more disjuncts than necessary.  We therefore approximate
+ * the constraints on the parameters by a single disjunct set.
+ *
+ * The build is extended to include the additional part of the schedule.
+ * If the original build space was not parametric, then the options
+ * in data->build refer only to the additional part of the schedule
+ * and they need to be adjusted to refer to the complete AST build
+ * domain.
+ *
+ * After having adjusted inverse schedule and build, we start generating
+ * code with the outer loop of the current code generation
+ * in generate_next_level.
+ *
+ * If the original build space was not parametric, we undo the embedding
+ * on the resulting isl_ast_node_list so that it can be used within
+ * the outer AST build.
+ */
+static int generate_code_in_space(struct isl_generate_code_data *data,
+	__isl_take isl_set *set, __isl_take isl_space *space)
+{
+	isl_union_map *executed;
+	isl_ast_build *build;
+	isl_ast_graft_list *list;
+	int embed;
+
+	executed = isl_union_map_copy(data->executed);
+	executed = isl_union_map_intersect_domain(executed,
+						 isl_union_set_from_set(set));
+
+	embed = !isl_set_is_params(data->build->domain);
+	if (embed && !data->internal)
+		executed = internal_executed(executed, space, data->build);
+	if (!embed) {
+		isl_set *domain;
+		domain = isl_ast_build_get_domain(data->build);
+		domain = isl_set_from_basic_set(isl_set_simple_hull(domain));
+		executed = isl_union_map_intersect_params(executed, domain);
+	}
+
+	build = isl_ast_build_copy(data->build);
+	build = isl_ast_build_product(build, space);
+
+	list = generate_next_level(executed, build);
+
+	list = isl_ast_graft_list_unembed(list, embed);
+
+	data->list = isl_ast_graft_list_concat(data->list, list);
+
+	return 0;
+}
+
+/* Generate an AST that visits the elements in the range of data->executed
+ * in the relative order specified by the corresponding domain element(s)
+ * for those domain elements that belong to "set".
+ * Add the result to data->list.
+ *
+ * The caller ensures that "set" is a universe domain.
+ *
+ * If the build space S is not parametric, then the space of "set"
+ * need to be a wrapped relation with S as domain.  That is, it needs
+ * to be of the form
+ *
+ *	[S -> T]
+ *
+ * Check this property and pass control to generate_code_in_space
+ * passing along T.
+ * If the build space is not parametric, then T is the space of "set".
+ */
+static int generate_code_set(__isl_take isl_set *set, void *user)
+{
+	struct isl_generate_code_data *data = user;
+	isl_space *space, *build_space;
+	int is_domain;
+
+	space = isl_set_get_space(set);
+
+	if (isl_set_is_params(data->build->domain))
+		return generate_code_in_space(data, set, space);
+
+	build_space = isl_ast_build_get_space(data->build, data->internal);
+	space = isl_space_unwrap(space);
+	is_domain = isl_space_is_domain(build_space, space);
+	isl_space_free(build_space);
+	space = isl_space_range(space);
+
+	if (is_domain < 0)
+		goto error;
+	if (!is_domain)
+		isl_die(isl_set_get_ctx(set), isl_error_invalid,
+			"invalid nested schedule space", goto error);
+
+	return generate_code_in_space(data, set, space);
+error:
+	isl_set_free(set);
+	isl_space_free(space);
+	return -1;
+}
+
+/* Generate an AST that visits the elements in the range of "executed"
+ * in the relative order specified by the corresponding domain element(s).
+ *
+ * "build" is an isl_ast_build that has either been constructed by
+ * isl_ast_build_from_context or passed to a callback set by
+ * isl_ast_build_set_create_leaf.
+ * In the first case, the space of the isl_ast_build is typically
+ * a parametric space, although this is currently not enforced.
+ * In the second case, the space is never a parametric space.
+ * If the space S is not parametric, then the domain space(s) of "executed"
+ * need to be wrapped relations with S as domain.
+ *
+ * If the domain of "executed" consists of several spaces, then an AST
+ * is generated for each of them (in arbitrary order) and the results
+ * are concatenated.
+ *
+ * If "internal" is set, then the domain "S" above refers to the internal
+ * schedule domain representation.  Otherwise, it refers to the external
+ * representation, as returned by isl_ast_build_get_schedule_space.
+ *
+ * We essentially run over all the spaces in the domain of "executed"
+ * and call generate_code_set on each of them.
+ */
+static __isl_give isl_ast_graft_list *generate_code(
+	__isl_take isl_union_map *executed, __isl_take isl_ast_build *build,
+	int internal)
+{
+	isl_ctx *ctx;
+	struct isl_generate_code_data data = { 0 };
+	isl_space *space;
+	isl_union_set *schedule_domain;
+	isl_union_map *universe;
+
+	if (!build)
+		goto error;
+	space = isl_ast_build_get_space(build, 1);
+	space = isl_space_align_params(space,
+				    isl_union_map_get_space(executed));
+	space = isl_space_align_params(space,
+				    isl_union_map_get_space(build->options));
+	build = isl_ast_build_align_params(build, isl_space_copy(space));
+	executed = isl_union_map_align_params(executed, space);
+	if (!executed || !build)
+		goto error;
+
+	ctx = isl_ast_build_get_ctx(build);
+
+	data.internal = internal;
+	data.executed = executed;
+	data.build = build;
+	data.list = isl_ast_graft_list_alloc(ctx, 0);
+
+	universe = isl_union_map_universe(isl_union_map_copy(executed));
+	schedule_domain = isl_union_map_domain(universe);
+	if (isl_union_set_foreach_set(schedule_domain, &generate_code_set,
+					&data) < 0)
+		data.list = isl_ast_graft_list_free(data.list);
+
+	isl_union_set_free(schedule_domain);
+	isl_union_map_free(executed);
+
+	isl_ast_build_free(build);
+	return data.list;
+error:
+	isl_union_map_free(executed);
+	isl_ast_build_free(build);
+	return NULL;
+}
+
+/* Generate an AST that visits the elements in the domain of "schedule"
+ * in the relative order specified by the corresponding image element(s).
+ *
+ * "build" is an isl_ast_build that has either been constructed by
+ * isl_ast_build_from_context or passed to a callback set by
+ * isl_ast_build_set_create_leaf.
+ * In the first case, the space of the isl_ast_build is typically
+ * a parametric space, although this is currently not enforced.
+ * In the second case, the space is never a parametric space.
+ * If the space S is not parametric, then the range space(s) of "schedule"
+ * need to be wrapped relations with S as domain.
+ *
+ * If the range of "schedule" consists of several spaces, then an AST
+ * is generated for each of them (in arbitrary order) and the results
+ * are concatenated.
+ *
+ * We first initialize the local copies of the relevant options.
+ * We do this here rather than when the isl_ast_build is created
+ * because the options may have changed between the construction
+ * of the isl_ast_build and the call to isl_generate_code.
+ *
+ * The main computation is performed on an inverse schedule (with
+ * the schedule domain in the domain and the elements to be executed
+ * in the range) called "executed".
+ */
+__isl_give isl_ast_node *isl_ast_build_ast_from_schedule(
+	__isl_keep isl_ast_build *build, __isl_take isl_union_map *schedule)
+{
+	isl_ast_graft_list *list;
+	isl_ast_node *node;
+	isl_union_map *executed;
+
+	build = isl_ast_build_copy(build);
+	build = isl_ast_build_set_single_valued(build, 0);
+	schedule = isl_union_map_coalesce(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);
+	isl_ast_build_free(build);
+
+	return node;
+}

Added: polly/trunk/lib/External/isl/isl_ast_graft.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_ast_graft.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_graft.c (added)
+++ polly/trunk/lib/External/isl/isl_ast_graft.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,1242 @@
+/*
+ * Copyright 2012      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_ast_private.h>
+#include <isl_ast_build_expr.h>
+#include <isl_ast_build_private.h>
+#include <isl_ast_graft_private.h>
+
+static __isl_give isl_ast_graft *isl_ast_graft_copy(
+	__isl_keep isl_ast_graft *graft);
+
+#undef BASE
+#define BASE ast_graft
+
+#include <isl_list_templ.c>
+
+#undef BASE
+#define BASE ast_graft
+#include <print_templ.c>
+
+isl_ctx *isl_ast_graft_get_ctx(__isl_keep isl_ast_graft *graft)
+{
+	if (!graft)
+		return NULL;
+	return isl_basic_set_get_ctx(graft->enforced);
+}
+
+__isl_give isl_ast_node *isl_ast_graft_get_node(
+	__isl_keep isl_ast_graft *graft)
+{
+	return graft ? isl_ast_node_copy(graft->node) : NULL;
+}
+
+/* Create a graft for "node" with no guards and no enforced conditions.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_alloc(
+	__isl_take isl_ast_node *node, __isl_keep isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	isl_space *space;
+	isl_ast_graft *graft;
+
+	if (!node)
+		return NULL;
+
+	ctx = isl_ast_node_get_ctx(node);
+	graft = isl_calloc_type(ctx, isl_ast_graft);
+	if (!graft)
+		goto error;
+
+	space = isl_ast_build_get_space(build, 1);
+
+	graft->ref = 1;
+	graft->node = node;
+	graft->guard = isl_set_universe(isl_space_copy(space));
+	graft->enforced = isl_basic_set_universe(space);
+
+	if (!graft->guard || !graft->enforced)
+		return isl_ast_graft_free(graft);
+
+	return graft;
+error:
+	isl_ast_node_free(node);
+	return NULL;
+}
+
+/* Create a graft with no guards and no enforced conditions
+ * encapsulating a call to the domain element specified by "executed".
+ * "executed" is assumed to be single-valued.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_alloc_domain(
+	__isl_take isl_map *executed, __isl_keep isl_ast_build *build)
+{
+	isl_ast_node *node;
+
+	node = isl_ast_build_call_from_executed(build, executed);
+
+	return isl_ast_graft_alloc(node, build);
+}
+
+static __isl_give isl_ast_graft *isl_ast_graft_copy(
+	__isl_keep isl_ast_graft *graft)
+{
+	if (!graft)
+		return NULL;
+
+	graft->ref++;
+	return graft;
+}
+
+/* Do all the grafts in "list" have the same guard and is this guard
+ * independent of the current depth?
+ */
+static int equal_independent_guards(__isl_keep isl_ast_graft_list *list,
+	__isl_keep isl_ast_build *build)
+{
+	int i, n;
+	int depth;
+	isl_ast_graft *graft_0;
+	int equal = 1;
+	int skip;
+
+	graft_0 = isl_ast_graft_list_get_ast_graft(list, 0);
+	if (!graft_0)
+		return -1;
+
+	depth = isl_ast_build_get_depth(build);
+	skip = isl_set_involves_dims(graft_0->guard, isl_dim_set, depth, 1);
+	if (skip < 0 || skip) {
+		isl_ast_graft_free(graft_0);
+		return skip < 0 ? -1 : 0;
+	}
+
+	n = isl_ast_graft_list_n_ast_graft(list);
+	for (i = 1; i < n; ++i) {
+		isl_ast_graft *graft;
+		graft = isl_ast_graft_list_get_ast_graft(list, i);
+		if (!graft)
+			equal = -1;
+		else
+			equal = isl_set_is_equal(graft_0->guard, graft->guard);
+		isl_ast_graft_free(graft);
+		if (equal < 0 || !equal)
+			break;
+	}
+
+	isl_ast_graft_free(graft_0);
+
+	return equal;
+}
+
+/* Hoist "guard" out of the current level (given by "build").
+ *
+ * In particular, eliminate the dimension corresponding to the current depth.
+ */
+static __isl_give isl_set *hoist_guard(__isl_take isl_set *guard,
+	__isl_keep isl_ast_build *build)
+{
+	int depth;
+
+	depth = isl_ast_build_get_depth(build);
+	if (depth < isl_set_dim(guard, isl_dim_set)) {
+		guard = isl_set_remove_divs_involving_dims(guard,
+						isl_dim_set, depth, 1);
+		guard = isl_set_eliminate(guard, isl_dim_set, depth, 1);
+		guard = isl_set_compute_divs(guard);
+	}
+
+	return guard;
+}
+
+/* Extract a common guard from the grafts in "list" that can be hoisted
+ * out of the current level.  If no such guard can be found, then return
+ * a universal set.
+ *
+ * If all the grafts in the list have the same guard and if this guard
+ * is independent of the current level, then it can be hoisted out.
+ * If there is only one graft in the list and if its guard
+ * depends on the current level, then we eliminate this level and
+ * return the result.
+ *
+ * Otherwise, we return the unshifted simple hull of the guards.
+ * In order to be able to hoist as many constraints as possible,
+ * but at the same time avoid hoisting constraints that did not
+ * appear in the guards in the first place, we intersect the guards
+ * with all the information that is available (i.e., the domain
+ * from the build and the enforced constraints of the graft) and
+ * compute the unshifted hull of the result using only constraints
+ * from the original guards.
+ * In particular, intersecting the guards with other known information
+ * allows us to hoist guards that are only explicit is some of
+ * the grafts and implicit in the others.
+ *
+ * The special case for equal guards is needed in case those guards
+ * are non-convex.  Taking the simple hull would remove information
+ * and would not allow for these guards to be hoisted completely.
+ */
+__isl_give isl_set *isl_ast_graft_list_extract_hoistable_guard(
+	__isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build)
+{
+	int i, n;
+	int equal;
+	isl_ctx *ctx;
+	isl_set *guard;
+	isl_set_list *set_list;
+	isl_basic_set *hull;
+
+	if (!list || !build)
+		return NULL;
+
+	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n == 0)
+		return isl_set_universe(isl_ast_build_get_space(build, 1));
+
+	equal = equal_independent_guards(list, build);
+	if (equal < 0)
+		return NULL;
+
+	if (equal || n == 1) {
+		isl_ast_graft *graft_0;
+
+		graft_0 = isl_ast_graft_list_get_ast_graft(list, 0);
+		if (!graft_0)
+			return NULL;
+		guard = isl_set_copy(graft_0->guard);
+		if (!equal)
+			guard = hoist_guard(guard, build);
+		isl_ast_graft_free(graft_0);
+		return guard;
+	}
+
+	ctx = isl_ast_build_get_ctx(build);
+	set_list = isl_set_list_alloc(ctx, n);
+	guard = isl_set_empty(isl_ast_build_get_space(build, 1));
+	for (i = 0; i < n; ++i) {
+		isl_ast_graft *graft;
+		isl_basic_set *enforced;
+		isl_set *guard_i;
+
+		graft = isl_ast_graft_list_get_ast_graft(list, i);
+		enforced = isl_ast_graft_get_enforced(graft);
+		guard_i = isl_set_copy(graft->guard);
+		isl_ast_graft_free(graft);
+		set_list = isl_set_list_add(set_list, isl_set_copy(guard_i));
+		guard_i = isl_set_intersect(guard_i,
+					    isl_set_from_basic_set(enforced));
+		guard_i = isl_set_intersect(guard_i,
+					    isl_ast_build_get_domain(build));
+		guard = isl_set_union(guard, guard_i);
+	}
+	hull = isl_set_unshifted_simple_hull_from_set_list(guard, set_list);
+	guard = isl_set_from_basic_set(hull);
+	return hoist_guard(guard, build);
+}
+
+/* Internal data structure used inside insert_if.
+ *
+ * list is the list of guarded nodes created by each call to insert_if.
+ * node is the original node that is guarded by insert_if.
+ * build is the build in which the AST is constructed.
+ */
+struct isl_insert_if_data {
+	isl_ast_node_list *list;
+	isl_ast_node *node;
+	isl_ast_build *build;
+};
+
+static int insert_if(__isl_take isl_basic_set *bset, void *user);
+
+/* Insert an if node around "node" testing the condition encoded
+ * in guard "guard".
+ *
+ * If the user does not want any disjunctions in the if conditions
+ * and if "guard" does involve a disjunction, then we make the different
+ * disjuncts disjoint and insert an if node corresponding to each disjunct
+ * around a copy of "node".  The result is then a block node containing
+ * this sequence of guarded copies of "node".
+ */
+static __isl_give isl_ast_node *ast_node_insert_if(
+	__isl_take isl_ast_node *node, __isl_take isl_set *guard,
+	__isl_keep isl_ast_build *build)
+{
+	struct isl_insert_if_data data;
+	isl_ctx *ctx;
+
+	ctx = isl_ast_build_get_ctx(build);
+	if (isl_options_get_ast_build_allow_or(ctx) ||
+	    isl_set_n_basic_set(guard) <= 1) {
+		isl_ast_node *if_node;
+		isl_ast_expr *expr;
+
+		expr = isl_ast_build_expr_from_set(build, guard);
+
+		if_node = isl_ast_node_alloc_if(expr);
+		return isl_ast_node_if_set_then(if_node, node);
+	}
+
+	guard = isl_set_make_disjoint(guard);
+
+	data.list = isl_ast_node_list_alloc(ctx, 0);
+	data.node = node;
+	data.build = build;
+	if (isl_set_foreach_basic_set(guard, &insert_if, &data) < 0)
+		data.list = isl_ast_node_list_free(data.list);
+
+	isl_set_free(guard);
+	isl_ast_node_free(data.node);
+	return isl_ast_node_alloc_block(data.list);
+}
+
+/* Insert an if node around a copy of "data->node" testing the condition
+ * encoded in guard "bset" and add the result to data->list.
+ */
+static int insert_if(__isl_take isl_basic_set *bset, void *user)
+{
+	struct isl_insert_if_data *data = user;
+	isl_ast_node *node;
+	isl_set *set;
+
+	set = isl_set_from_basic_set(bset);
+	node = isl_ast_node_copy(data->node);
+	node = ast_node_insert_if(node, set, data->build);
+	data->list = isl_ast_node_list_add(data->list, node);
+
+	return 0;
+}
+
+/* Insert an if node around graft->node testing the condition encoded
+ * in guard "guard", assuming guard involves any conditions.
+ */
+static __isl_give isl_ast_graft *insert_if_node(
+	__isl_take isl_ast_graft *graft, __isl_take isl_set *guard,
+	__isl_keep isl_ast_build *build)
+{
+	int univ;
+
+	if (!graft)
+		goto error;
+
+	univ = isl_set_plain_is_universe(guard);
+	if (univ < 0)
+		goto error;
+	if (univ) {
+		isl_set_free(guard);
+		return graft;
+	}
+
+	build = isl_ast_build_copy(build);
+	graft->node = ast_node_insert_if(graft->node, guard, build);
+	isl_ast_build_free(build);
+
+	if (!graft->node)
+		return isl_ast_graft_free(graft);
+
+	return graft;
+error:
+	isl_set_free(guard);
+	return isl_ast_graft_free(graft);
+}
+
+/* Insert an if node around graft->node testing the condition encoded
+ * in graft->guard, assuming graft->guard involves any conditions.
+ */
+static __isl_give isl_ast_graft *insert_pending_guard_node(
+	__isl_take isl_ast_graft *graft, __isl_keep isl_ast_build *build)
+{
+	if (!graft)
+		return NULL;
+
+	return insert_if_node(graft, isl_set_copy(graft->guard), build);
+}
+
+/* Replace graft->enforced by "enforced".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_set_enforced(
+	__isl_take isl_ast_graft *graft, __isl_take isl_basic_set *enforced)
+{
+	if (!graft || !enforced)
+		goto error;
+
+	isl_basic_set_free(graft->enforced);
+	graft->enforced = enforced;
+
+	return graft;
+error:
+	isl_basic_set_free(enforced);
+	return isl_ast_graft_free(graft);
+}
+
+/* Update "enforced" such that it only involves constraints that are
+ * also enforced by "graft".
+ */
+static __isl_give isl_basic_set *update_enforced(
+	__isl_take isl_basic_set *enforced, __isl_keep isl_ast_graft *graft,
+	int depth)
+{
+	isl_basic_set *enforced_g;
+
+	enforced_g = isl_ast_graft_get_enforced(graft);
+	if (depth < isl_basic_set_dim(enforced_g, isl_dim_set))
+		enforced_g = isl_basic_set_eliminate(enforced_g,
+							isl_dim_set, depth, 1);
+	enforced_g = isl_basic_set_remove_unknown_divs(enforced_g);
+	enforced_g = isl_basic_set_align_params(enforced_g,
+				isl_basic_set_get_space(enforced));
+	enforced = isl_basic_set_align_params(enforced,
+				isl_basic_set_get_space(enforced_g));
+	enforced = isl_set_simple_hull(isl_basic_set_union(enforced,
+						enforced_g));
+
+	return enforced;
+}
+
+/* Extend the node at *body with node.
+ *
+ * If body points to the else branch, then *body may still be NULL.
+ * If so, we simply attach node to this else branch.
+ * Otherwise, we attach a list containing the statements already
+ * attached at *body followed by node.
+ */
+static void extend_body(__isl_keep isl_ast_node **body,
+	__isl_take isl_ast_node *node)
+{
+	isl_ast_node_list *list;
+
+	if  (!*body) {
+		*body = node;
+		return;
+	}
+
+	if ((*body)->type == isl_ast_node_block) {
+		list = isl_ast_node_block_get_children(*body);
+		isl_ast_node_free(*body);
+	} else
+		list = isl_ast_node_list_from_ast_node(*body);
+	list = isl_ast_node_list_add(list, node);
+	*body = isl_ast_node_alloc_block(list);
+}
+
+/* Merge "graft" into the last graft of "list".
+ * body points to the then or else branch of an if node in that last graft.
+ *
+ * We attach graft->node to this branch and update the enforced
+ * set of the last graft of "list" to take into account the enforced
+ * set of "graft".
+ */
+static __isl_give isl_ast_graft_list *graft_extend_body(
+	__isl_take isl_ast_graft_list *list,
+	__isl_keep isl_ast_node **body, __isl_take isl_ast_graft *graft,
+	__isl_keep isl_ast_build *build)
+{
+	int n;
+	int depth;
+	isl_ast_graft *last;
+	isl_space *space;
+	isl_basic_set *enforced;
+
+	if (!list || !graft)
+		goto error;
+	extend_body(body, isl_ast_node_copy(graft->node));
+	if (!*body)
+		goto error;
+
+	n = isl_ast_graft_list_n_ast_graft(list);
+	last = isl_ast_graft_list_get_ast_graft(list, n - 1);
+
+	depth = isl_ast_build_get_depth(build);
+	space = isl_ast_build_get_space(build, 1);
+	enforced = isl_basic_set_empty(space);
+	enforced = update_enforced(enforced, last, depth);
+	enforced = update_enforced(enforced, graft, depth);
+	last = isl_ast_graft_set_enforced(last, enforced);
+
+	list = isl_ast_graft_list_set_ast_graft(list, n - 1, last);
+	isl_ast_graft_free(graft);
+	return list;
+error:
+	isl_ast_graft_free(graft);
+	return isl_ast_graft_list_free(list);
+}
+
+/* Merge "graft" into the last graft of "list", attaching graft->node
+ * to the then branch of "last_if".
+ */
+static __isl_give isl_ast_graft_list *extend_then(
+	__isl_take isl_ast_graft_list *list,
+	__isl_keep isl_ast_node *last_if, __isl_take isl_ast_graft *graft,
+	__isl_keep isl_ast_build *build)
+{
+	return graft_extend_body(list, &last_if->u.i.then, graft, build);
+}
+
+/* Merge "graft" into the last graft of "list", attaching graft->node
+ * to the else branch of "last_if".
+ */
+static __isl_give isl_ast_graft_list *extend_else(
+	__isl_take isl_ast_graft_list *list,
+	__isl_keep isl_ast_node *last_if, __isl_take isl_ast_graft *graft,
+	__isl_keep isl_ast_build *build)
+{
+	return graft_extend_body(list, &last_if->u.i.else_node, graft, build);
+}
+
+/* This data structure keeps track of an if node.
+ *
+ * "node" is the actual if-node
+ * "guard" is the original, non-simplified guard of the node
+ * "complement" is the complement of "guard" in the context of outer if nodes
+ */
+struct isl_if_node {
+	isl_ast_node *node;
+	isl_set *guard;
+	isl_set *complement;
+};
+
+/* Given a list of "n" if nodes, clear those starting at "first"
+ * and return "first" (i.e., the updated size of the array).
+ */
+static int clear_if_nodes(struct isl_if_node *if_node, int first, int n)
+{
+	int i;
+
+	for (i = first; i < n; ++i) {
+		isl_set_free(if_node[i].guard);
+		isl_set_free(if_node[i].complement);
+	}
+
+	return first;
+}
+
+/* For each graft in "list",
+ * insert an if node around graft->node testing the condition encoded
+ * in graft->guard, assuming graft->guard involves any conditions.
+ *
+ * We keep track of a list of generated if nodes that can be extended
+ * without changing the order of the elements in "list".
+ * If the guard of a graft is a subset of either the guard or its complement
+ * of one of those if nodes, then the node
+ * of the new graft is inserted into the then or else branch of the last graft
+ * and the current graft is discarded.
+ * The guard of the node is then simplified based on the conditions
+ * enforced at that then or else branch.
+ * Otherwise, the current graft is appended to the list.
+ *
+ * We only construct else branches if allowed by the user.
+ */
+static __isl_give isl_ast_graft_list *insert_pending_guard_nodes(
+	__isl_take isl_ast_graft_list *list,
+	__isl_keep isl_ast_build *build)
+{
+	int i, j, n, n_if;
+	int allow_else;
+	isl_ctx *ctx;
+	isl_ast_graft_list *res;
+	struct isl_if_node *if_node = NULL;
+
+	if (!build || !list)
+		return isl_ast_graft_list_free(list);
+
+	ctx = isl_ast_build_get_ctx(build);
+	n = isl_ast_graft_list_n_ast_graft(list);
+
+	allow_else = isl_options_get_ast_build_allow_else(ctx);
+
+	n_if = 0;
+	if (n > 1) {
+		if_node = isl_alloc_array(ctx, struct isl_if_node, n - 1);
+		if (!if_node)
+			return isl_ast_graft_list_free(list);
+	}
+
+	res = isl_ast_graft_list_alloc(ctx, n);
+
+	for (i = 0; i < n; ++i) {
+		isl_set *guard;
+		isl_ast_graft *graft;
+		int subset, found_then, found_else;
+		isl_ast_node *node;
+
+		graft = isl_ast_graft_list_get_ast_graft(list, i);
+		if (!graft)
+			break;
+		subset = 0;
+		found_then = found_else = -1;
+		if (n_if > 0) {
+			isl_set *test;
+			test = isl_set_copy(graft->guard);
+			test = isl_set_intersect(test,
+						isl_set_copy(build->domain));
+			for (j = n_if - 1; j >= 0; --j) {
+				subset = isl_set_is_subset(test,
+							if_node[j].guard);
+				if (subset < 0 || subset) {
+					found_then = j;
+					break;
+				}
+				if (!allow_else)
+					continue;
+				subset = isl_set_is_subset(test,
+							if_node[j].complement);
+				if (subset < 0 || subset) {
+					found_else = j;
+					break;
+				}
+			}
+			n_if = clear_if_nodes(if_node, j + 1, n_if);
+			isl_set_free(test);
+		}
+		if (subset < 0) {
+			graft = isl_ast_graft_free(graft);
+			break;
+		}
+
+		guard = isl_set_copy(graft->guard);
+		if (found_then >= 0)
+			graft->guard = isl_set_gist(graft->guard,
+				isl_set_copy(if_node[found_then].guard));
+		else if (found_else >= 0)
+			graft->guard = isl_set_gist(graft->guard,
+				isl_set_copy(if_node[found_else].complement));
+
+		node = graft->node;
+		if (!graft->guard)
+			graft = isl_ast_graft_free(graft);
+		graft = insert_pending_guard_node(graft, build);
+		if (graft && graft->node != node && i != n - 1) {
+			isl_set *set;
+			if_node[n_if].node = graft->node;
+			if_node[n_if].guard = guard;
+			if (found_then >= 0)
+				set = if_node[found_then].guard;
+			else if (found_else >= 0)
+				set = if_node[found_else].complement;
+			else
+				set = build->domain;
+			set = isl_set_copy(set);
+			set = isl_set_subtract(set, isl_set_copy(guard));
+			if_node[n_if].complement = set;
+			n_if++;
+		} else
+			isl_set_free(guard);
+		if (!graft)
+			break;
+
+		if (found_then >= 0)
+			res = extend_then(res, if_node[found_then].node,
+						graft, build);
+		else if (found_else >= 0)
+			res = extend_else(res, if_node[found_else].node,
+						graft, build);
+		else
+			res = isl_ast_graft_list_add(res, graft);
+	}
+	if (i < n)
+		res = isl_ast_graft_list_free(res);
+
+	isl_ast_graft_list_free(list);
+	clear_if_nodes(if_node, 0, n_if);
+	free(if_node);
+	return res;
+}
+
+/* Collect the nodes contained in the grafts in "list" in a node list.
+ */
+static __isl_give isl_ast_node_list *extract_node_list(
+	__isl_keep isl_ast_graft_list *list)
+{
+	int i, n;
+	isl_ctx *ctx;
+	isl_ast_node_list *node_list;
+
+	if (!list)
+		return NULL;
+	ctx = isl_ast_graft_list_get_ctx(list);
+	n = isl_ast_graft_list_n_ast_graft(list);
+	node_list = isl_ast_node_list_alloc(ctx, n);
+	for (i = 0; i < n; ++i) {
+		isl_ast_node *node;
+		isl_ast_graft *graft;
+
+		graft = isl_ast_graft_list_get_ast_graft(list, i);
+		node = isl_ast_graft_get_node(graft);
+		node_list = isl_ast_node_list_add(node_list, node);
+		isl_ast_graft_free(graft);
+	}
+
+	return node_list;
+}
+
+/* Look for shared enforced constraints by all the elements in "list"
+ * on outer loops (with respect to the current depth) and return the result.
+ *
+ * We assume that the number of children is at least one.
+ */
+__isl_give isl_basic_set *isl_ast_graft_list_extract_shared_enforced(
+	__isl_keep isl_ast_graft_list *list,
+	__isl_keep isl_ast_build *build)
+{
+	int i, n;
+	int depth;
+	isl_space *space;
+	isl_basic_set *enforced;
+
+	if (!list)
+		return NULL;
+
+	n = isl_ast_graft_list_n_ast_graft(list);
+	if (n == 0)
+		isl_die(isl_ast_graft_list_get_ctx(list), isl_error_invalid,
+			"for node should have at least one child",
+			return NULL);
+
+	space = isl_ast_build_get_space(build, 1);
+	enforced = isl_basic_set_empty(space);
+
+	depth = isl_ast_build_get_depth(build);
+	for (i = 0; i < n; ++i) {
+		isl_ast_graft *graft;
+
+		graft = isl_ast_graft_list_get_ast_graft(list, i);
+		enforced = update_enforced(enforced, graft, depth);
+		isl_ast_graft_free(graft);
+	}
+
+	return enforced;
+}
+
+/* Record "guard" in "graft" so that it will be enforced somewhere
+ * up the tree.  If the graft already has a guard, then it may be partially
+ * redundant in combination with the new guard and in the context
+ * the generated constraints of "build".  In fact, the new guard
+ * may in itself have some redundant constraints.
+ * We therefore (re)compute the gist of the intersection
+ * and coalesce the result.
+ */
+static __isl_give isl_ast_graft *store_guard(__isl_take isl_ast_graft *graft,
+	__isl_take isl_set *guard, __isl_keep isl_ast_build *build)
+{
+	int is_universe;
+
+	if (!graft)
+		goto error;
+
+	is_universe = isl_set_plain_is_universe(guard);
+	if (is_universe < 0)
+		goto error;
+	if (is_universe) {
+		isl_set_free(guard);
+		return graft;
+	}
+
+	graft->guard = isl_set_intersect(graft->guard, guard);
+	graft->guard = isl_set_gist(graft->guard,
+				    isl_ast_build_get_generated(build));
+	graft->guard = isl_set_coalesce(graft->guard);
+	if (!graft->guard)
+		return isl_ast_graft_free(graft);
+
+	return graft;
+error:
+	isl_set_free(guard);
+	return isl_ast_graft_free(graft);
+}
+
+/* For each graft in "list", replace its guard with the gist with
+ * respect to "context".
+ */
+static __isl_give isl_ast_graft_list *gist_guards(
+	__isl_take isl_ast_graft_list *list, __isl_keep isl_set *context)
+{
+	int i, n;
+
+	if (!list)
+		return NULL;
+
+	n = isl_ast_graft_list_n_ast_graft(list);
+	for (i = 0; i < n; ++i) {
+		isl_ast_graft *graft;
+
+		graft = isl_ast_graft_list_get_ast_graft(list, i);
+		if (!graft)
+			break;
+		graft->guard = isl_set_gist(graft->guard,
+						isl_set_copy(context));
+		if (!graft->guard)
+			graft = isl_ast_graft_free(graft);
+		list = isl_ast_graft_list_set_ast_graft(list, i, graft);
+	}
+	if (i < n)
+		return isl_ast_graft_list_free(list);
+
+	return list;
+}
+
+/* For each graft in "list", replace its guard with the gist with
+ * respect to "context".
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_gist_guards(
+	__isl_take isl_ast_graft_list *list, __isl_take isl_set *context)
+{
+	list = gist_guards(list, context);
+	isl_set_free(context);
+
+	return list;
+}
+
+/* Allocate a graft in "build" based on the list of grafts in "sub_build".
+ * "guard" and "enforced" are the guard and enforced constraints
+ * of the allocated graft.  The guard is used to simplify the guards
+ * of the elements in "list".
+ *
+ * The node is initialized to either a block containing the nodes of "children"
+ * or, if there is only a single child, the node of that child.
+ * If the current level requires a for node, it should be inserted by
+ * a subsequent call to isl_ast_graft_insert_for.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_alloc_from_children(
+	__isl_take isl_ast_graft_list *list, __isl_take isl_set *guard,
+	__isl_take isl_basic_set *enforced, __isl_keep isl_ast_build *build,
+	__isl_keep isl_ast_build *sub_build)
+{
+	isl_ast_build *guard_build;
+	isl_ast_node *node;
+	isl_ast_node_list *node_list;
+	isl_ast_graft *graft;
+
+	guard_build = isl_ast_build_copy(sub_build);
+	guard_build = isl_ast_build_replace_pending_by_guard(guard_build,
+						isl_set_copy(guard));
+	list = gist_guards(list, guard);
+	list = insert_pending_guard_nodes(list, guard_build);
+	isl_ast_build_free(guard_build);
+
+	node_list = extract_node_list(list);
+	node = isl_ast_node_from_ast_node_list(node_list);
+	isl_ast_graft_list_free(list);
+
+	graft = isl_ast_graft_alloc(node, build);
+	graft = store_guard(graft, guard, build);
+	graft = isl_ast_graft_enforce(graft, enforced);
+
+	return graft;
+}
+
+/* Combine the grafts in the list into a single graft.
+ *
+ * The guard is initialized to the shared guard of the list elements (if any),
+ * provided it does not depend on the current dimension.
+ * The guards in the elements are then simplified with respect to the
+ * hoisted guard and materialized as if nodes around the contained AST nodes
+ * in the context of "sub_build".
+ *
+ * The enforced set is initialized to the simple hull of the enforced sets
+ * of the elements, provided the ast_build_exploit_nested_bounds option is set
+ * or the new graft will be used at the same level.
+ *
+ * The node is initialized to either a block containing the nodes of "list"
+ * or, if there is only a single element, the node of that element.
+ */
+static __isl_give isl_ast_graft *ast_graft_list_fuse(
+	__isl_take isl_ast_graft_list *list, __isl_keep isl_ast_build *build)
+{
+	isl_ast_graft *graft;
+	isl_basic_set *enforced;
+	isl_set *guard;
+
+	if (!list)
+		return NULL;
+
+	enforced = isl_ast_graft_list_extract_shared_enforced(list, build);
+	guard = isl_ast_graft_list_extract_hoistable_guard(list, build);
+	graft = isl_ast_graft_alloc_from_children(list, guard, enforced,
+						    build, build);
+
+	return graft;
+}
+
+/* Combine the grafts in the list into a single graft.
+ * Return a list containing this single graft.
+ * If the original list is empty, then return an empty list.
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_fuse(
+	__isl_take isl_ast_graft_list *list,
+	__isl_keep isl_ast_build *build)
+{
+	isl_ast_graft *graft;
+
+	if (!list)
+		return NULL;
+	if (isl_ast_graft_list_n_ast_graft(list) <= 1)
+		return list;
+	graft = ast_graft_list_fuse(list, build);
+	return isl_ast_graft_list_from_ast_graft(graft);
+}
+
+/* Combine the two grafts into a single graft.
+ * Return a list containing this single graft.
+ */
+static __isl_give isl_ast_graft *isl_ast_graft_fuse(
+	__isl_take isl_ast_graft *graft1, __isl_take isl_ast_graft *graft2,
+	__isl_keep isl_ast_build *build)
+{
+	isl_ctx *ctx;
+	isl_ast_graft_list *list;
+
+	ctx = isl_ast_build_get_ctx(build);
+
+	list = isl_ast_graft_list_alloc(ctx, 2);
+	list = isl_ast_graft_list_add(list, graft1);
+	list = isl_ast_graft_list_add(list, graft2);
+
+	return ast_graft_list_fuse(list, build);
+}
+
+/* Insert a for node enclosing the current graft->node.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_insert_for(
+	__isl_take isl_ast_graft *graft, __isl_take isl_ast_node *node)
+{
+	if (!graft)
+		goto error;
+
+	graft->node = isl_ast_node_for_set_body(node, graft->node);
+	if (!graft->node)
+		return isl_ast_graft_free(graft);
+
+	return graft;
+error:
+	isl_ast_node_free(node);
+	isl_ast_graft_free(graft);
+	return NULL;
+}
+
+/* Represent the graft list as an AST node.
+ * This operation drops the information about guards in the grafts, so
+ * if there are any pending guards, then they are materialized as if nodes.
+ */
+__isl_give isl_ast_node *isl_ast_node_from_graft_list(
+	__isl_take isl_ast_graft_list *list,
+	__isl_keep isl_ast_build *build)
+{
+	isl_ast_node_list *node_list;
+
+	list = insert_pending_guard_nodes(list, build);
+	node_list = extract_node_list(list);
+	isl_ast_graft_list_free(list);
+
+	return isl_ast_node_from_ast_node_list(node_list);
+}
+
+void *isl_ast_graft_free(__isl_take isl_ast_graft *graft)
+{
+	if (!graft)
+		return NULL;
+
+	if (--graft->ref > 0)
+		return NULL;
+
+	isl_ast_node_free(graft->node);
+	isl_set_free(graft->guard);
+	isl_basic_set_free(graft->enforced);
+	free(graft);
+
+	return NULL;
+}
+
+/* Record that the grafted tree enforces
+ * "enforced" by intersecting graft->enforced with "enforced".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_enforce(
+	__isl_take isl_ast_graft *graft, __isl_take isl_basic_set *enforced)
+{
+	if (!graft || !enforced)
+		goto error;
+
+	enforced = isl_basic_set_align_params(enforced,
+				isl_basic_set_get_space(graft->enforced));
+	graft->enforced = isl_basic_set_align_params(graft->enforced,
+				isl_basic_set_get_space(enforced));
+	graft->enforced = isl_basic_set_intersect(graft->enforced, enforced);
+	if (!graft->enforced)
+		return isl_ast_graft_free(graft);
+
+	return graft;
+error:
+	isl_basic_set_free(enforced);
+	return isl_ast_graft_free(graft);
+}
+
+__isl_give isl_basic_set *isl_ast_graft_get_enforced(
+	__isl_keep isl_ast_graft *graft)
+{
+	return graft ? isl_basic_set_copy(graft->enforced) : NULL;
+}
+
+__isl_give isl_set *isl_ast_graft_get_guard(__isl_keep isl_ast_graft *graft)
+{
+	return graft ? isl_set_copy(graft->guard) : NULL;
+}
+
+/* Record that "guard" needs to be inserted in "graft".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_add_guard(
+	__isl_take isl_ast_graft *graft,
+	__isl_take isl_set *guard, __isl_keep isl_ast_build *build)
+{
+	return store_guard(graft, guard, build);
+}
+
+/* Reformulate the "graft", which was generated in the context
+ * of an inner code generation, in terms of the outer code generation
+ * AST build.
+ *
+ * If "product" is set, then the domain of the inner code generation build is
+ *
+ *	[O -> S]
+ *
+ * with O the domain of the outer code generation build.
+ * We essentially need to project out S.
+ *
+ * If "product" is not set, then we need to project the domains onto
+ * their parameter spaces.
+ */
+__isl_give isl_ast_graft *isl_ast_graft_unembed(__isl_take isl_ast_graft *graft,
+	int product)
+{
+	isl_basic_set *enforced;
+
+	if (!graft)
+		return NULL;
+
+	if (product) {
+		enforced = graft->enforced;
+		enforced = isl_basic_map_domain(isl_basic_set_unwrap(enforced));
+		graft->enforced = enforced;
+		graft->guard = isl_map_domain(isl_set_unwrap(graft->guard));
+	} else {
+		graft->enforced = isl_basic_set_params(graft->enforced);
+		graft->guard = isl_set_params(graft->guard);
+	}
+	graft->guard = isl_set_compute_divs(graft->guard);
+
+	if (!graft->enforced || !graft->guard)
+		return isl_ast_graft_free(graft);
+
+	return graft;
+}
+
+/* Reformulate the grafts in "list", which were generated in the context
+ * of an inner code generation, in terms of the outer code generation
+ * AST build.
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_unembed(
+	__isl_take isl_ast_graft_list *list, int product)
+{
+	int i, n;
+
+	n = isl_ast_graft_list_n_ast_graft(list);
+	for (i = 0; i < n; ++i) {
+		isl_ast_graft *graft;
+
+		graft = isl_ast_graft_list_get_ast_graft(list, i);
+		graft = isl_ast_graft_unembed(graft, product);
+		list = isl_ast_graft_list_set_ast_graft(list, i, graft);
+	}
+
+	return list;
+}
+
+/* Compute the preimage of "graft" under the function represented by "ma".
+ * In other words, plug in "ma" in "enforced" and "guard" fields of "graft".
+ */
+__isl_give isl_ast_graft *isl_ast_graft_preimage_multi_aff(
+	__isl_take isl_ast_graft *graft, __isl_take isl_multi_aff *ma)
+{
+	isl_basic_set *enforced;
+
+	if (!graft)
+		return NULL;
+
+	enforced = graft->enforced;
+	graft->enforced = isl_basic_set_preimage_multi_aff(enforced,
+						isl_multi_aff_copy(ma));
+	graft->guard = isl_set_preimage_multi_aff(graft->guard, ma);
+
+	if (!graft->enforced || !graft->guard)
+		return isl_ast_graft_free(graft);
+
+	return graft;
+}
+
+/* Compute the preimage of all the grafts in "list" under
+ * the function represented by "ma".
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_preimage_multi_aff(
+	__isl_take isl_ast_graft_list *list, __isl_take isl_multi_aff *ma)
+{
+	int i, n;
+
+	n = isl_ast_graft_list_n_ast_graft(list);
+	for (i = 0; i < n; ++i) {
+		isl_ast_graft *graft;
+
+		graft = isl_ast_graft_list_get_ast_graft(list, i);
+		graft = isl_ast_graft_preimage_multi_aff(graft,
+						    isl_multi_aff_copy(ma));
+		list = isl_ast_graft_list_set_ast_graft(list, i, graft);
+	}
+
+	isl_multi_aff_free(ma);
+	return list;
+}
+
+/* Compare two grafts based on their guards.
+ */
+static int cmp_graft(__isl_keep isl_ast_graft *a, __isl_keep isl_ast_graft *b,
+	void *user)
+{
+	return isl_set_plain_cmp(a->guard, b->guard);
+}
+
+/* Order the elements in "list" based on their guards.
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_sort_guard(
+	__isl_take isl_ast_graft_list *list)
+{
+	return isl_ast_graft_list_sort(list, &cmp_graft, NULL);
+}
+
+/* Merge the given two lists into a single list of grafts,
+ * merging grafts with the same guard into a single graft.
+ *
+ * "list2" has been sorted using isl_ast_graft_list_sort.
+ * "list1" may be the result of a previous call to isl_ast_graft_list_merge
+ * and may therefore not be completely sorted.
+ *
+ * The elements in "list2" need to be executed after those in "list1",
+ * but if the guard of a graft in "list2" is disjoint from the guards
+ * of some final elements in "list1", then it can be moved up to before
+ * those final elements.
+ *
+ * In particular, we look at each element g of "list2" in turn
+ * and move it up beyond elements of "list1" that would be sorted
+ * after g as long as each of these elements has a guard that is disjoint
+ * from that of g.
+ *
+ * We do not allow the second or any later element of "list2" to be moved
+ * before a previous elements of "list2" even if the reason that
+ * that element didn't move up further was that its guard was not disjoint
+ * from that of the previous element in "list1".
+ */
+__isl_give isl_ast_graft_list *isl_ast_graft_list_merge(
+	__isl_take isl_ast_graft_list *list1,
+	__isl_take isl_ast_graft_list *list2,
+	__isl_keep isl_ast_build *build)
+{
+	int i, j, first;
+
+	if (!list1 || !list2 || !build)
+		goto error;
+	if (list2->n == 0) {
+		isl_ast_graft_list_free(list2);
+		return list1;
+	}
+	if (list1->n == 0) {
+		isl_ast_graft_list_free(list1);
+		return list2;
+	}
+
+	first = 0;
+	for (i = 0; i < list2->n; ++i) {
+		isl_ast_graft *graft;
+		graft = isl_ast_graft_list_get_ast_graft(list2, i);
+		if (!graft)
+			break;
+
+		for (j = list1->n; j >= 0; --j) {
+			int cmp, disjoint;
+			isl_ast_graft *graft_j;
+
+			if (j == first)
+				cmp = -1;
+			else
+				cmp = isl_set_plain_cmp(list1->p[j - 1]->guard,
+							graft->guard);
+			if (cmp > 0) {
+				disjoint = isl_set_is_disjoint(graft->guard,
+							list1->p[j - 1]->guard);
+				if (disjoint < 0) {
+					list1 = isl_ast_graft_list_free(list1);
+					break;
+				}
+				if (!disjoint)
+					cmp = -1;
+			}
+			if (cmp > 0)
+				continue;
+			if (cmp < 0) {
+				list1 = isl_ast_graft_list_insert(list1, j,
+								graft);
+				break;
+			}
+
+			--j;
+
+			graft_j = isl_ast_graft_list_get_ast_graft(list1, j);
+			graft_j = isl_ast_graft_fuse(graft_j, graft, build);
+			list1 = isl_ast_graft_list_set_ast_graft(list1, j,
+								graft_j);
+			break;
+		}
+
+		if (j < 0)
+			isl_die(isl_ast_build_get_ctx(build),
+				isl_error_internal,
+				"element failed to get inserted", break);
+
+		first = j + 1;
+		if (!list1)
+			break;
+	}
+	if (i < list2->n)
+		list1 = isl_ast_graft_list_free(list1);
+	isl_ast_graft_list_free(list2);
+
+	return list1;
+error:
+	isl_ast_graft_list_free(list1);
+	isl_ast_graft_list_free(list2);
+	return NULL;
+}
+
+__isl_give isl_printer *isl_printer_print_ast_graft(__isl_take isl_printer *p,
+	__isl_keep isl_ast_graft *graft)
+{
+	if (!p)
+		return NULL;
+	if (!graft)
+		return isl_printer_free(p);
+
+	p = isl_printer_print_str(p, "(");
+	p = isl_printer_print_str(p, "guard: ");
+	p = isl_printer_print_set(p, graft->guard);
+	p = isl_printer_print_str(p, ", ");
+	p = isl_printer_print_str(p, "enforced: ");
+	p = isl_printer_print_basic_set(p, graft->enforced);
+	p = isl_printer_print_str(p, ", ");
+	p = isl_printer_print_str(p, "node: ");
+	p = isl_printer_print_ast_node(p, graft->node);
+	p = isl_printer_print_str(p, ")");
+
+	return p;
+}

Added: polly/trunk/lib/External/isl/isl_ast_graft_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_ast_graft_private.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_graft_private.h (added)
+++ polly/trunk/lib/External/isl/isl_ast_graft_private.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,97 @@
+#ifndef ISL_AST_GRAFT_PRIVATE_H
+#define ISL_AST_GRAFT_PRIVATE_H
+
+#include <isl/ast.h>
+#include <isl/set.h>
+#include <isl/list.h>
+#include <isl/printer.h>
+
+struct isl_ast_graft;
+typedef struct isl_ast_graft isl_ast_graft;
+
+/* Representation of part of an AST ("node") with some additional polyhedral
+ * information about the tree.
+ *
+ * "guard" contains conditions that should still be enforced by
+ * some ancestor of the current tree.  In particular, the already
+ * generated tree assumes that these conditions hold, but may not
+ * have enforced them itself.
+ * The guard should not contain any unknown divs as it will be used
+ * to generate an if condition.
+ *
+ * "enforced" expresses constraints that are already enforced by the for
+ * nodes in the current tree and that therefore do not need to be enforced
+ * by any ancestor.
+ * The constraints only involve outer loop iterators.
+ */
+struct isl_ast_graft {
+	int ref;
+
+	isl_ast_node *node;
+
+	isl_set *guard;
+	isl_basic_set *enforced;
+};
+
+ISL_DECLARE_LIST(ast_graft)
+
+#undef EL
+#define EL isl_ast_graft
+
+#include <isl_list_templ.h>
+
+isl_ctx *isl_ast_graft_get_ctx(__isl_keep isl_ast_graft *graft);
+
+__isl_give isl_ast_graft *isl_ast_graft_alloc(
+	__isl_take isl_ast_node *node, __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft *isl_ast_graft_alloc_from_children(
+	__isl_take isl_ast_graft_list *list, __isl_take isl_set *guard,
+	__isl_take isl_basic_set *enforced, __isl_keep isl_ast_build *build,
+	__isl_keep isl_ast_build *sub_build);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_fuse(
+	__isl_take isl_ast_graft_list *children,
+	__isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft *isl_ast_graft_alloc_domain(
+	__isl_take isl_map *schedule, __isl_keep isl_ast_build *build);
+void *isl_ast_graft_free(__isl_take isl_ast_graft *graft);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_sort_guard(
+	__isl_take isl_ast_graft_list *list);
+
+__isl_give isl_ast_graft_list *isl_ast_graft_list_merge(
+	__isl_take isl_ast_graft_list *list1,
+	__isl_take isl_ast_graft_list *list2,
+	__isl_keep isl_ast_build *build);
+
+__isl_give isl_ast_node *isl_ast_graft_get_node(
+	__isl_keep isl_ast_graft *graft);
+__isl_give isl_basic_set *isl_ast_graft_get_enforced(
+	__isl_keep isl_ast_graft *graft);
+__isl_give isl_set *isl_ast_graft_get_guard(__isl_keep isl_ast_graft *graft);
+
+__isl_give isl_ast_graft *isl_ast_graft_insert_for(
+	__isl_take isl_ast_graft *graft, __isl_take isl_ast_node *node);
+__isl_give isl_ast_graft *isl_ast_graft_add_guard(
+	__isl_take isl_ast_graft *graft,
+	__isl_take isl_set *guard, __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft *isl_ast_graft_enforce(
+	__isl_take isl_ast_graft *graft, __isl_take isl_basic_set *enforced);
+
+__isl_give isl_ast_graft_list *isl_ast_graft_list_unembed(
+	__isl_take isl_ast_graft_list *list, int product);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_preimage_multi_aff(
+	__isl_take isl_ast_graft_list *list, __isl_take isl_multi_aff *ma);
+
+__isl_give isl_ast_node *isl_ast_node_from_graft_list(
+	__isl_take isl_ast_graft_list *list, __isl_keep isl_ast_build *build);
+
+__isl_give isl_basic_set *isl_ast_graft_list_extract_shared_enforced(
+	__isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build);
+__isl_give isl_set *isl_ast_graft_list_extract_hoistable_guard(
+	__isl_keep isl_ast_graft_list *list, __isl_keep isl_ast_build *build);
+__isl_give isl_ast_graft_list *isl_ast_graft_list_gist_guards(
+	__isl_take isl_ast_graft_list *list, __isl_take isl_set *context);
+
+__isl_give isl_printer *isl_printer_print_ast_graft(__isl_take isl_printer *p,
+	__isl_keep isl_ast_graft *graft);
+
+#endif

Added: polly/trunk/lib/External/isl/isl_ast_int.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_ast_int.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_int.c (added)
+++ polly/trunk/lib/External/isl/isl_ast_int.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,13 @@
+#include <isl/deprecated/ast_int.h>
+#include <isl/deprecated/val_int.h>
+#include <isl_ast_private.h>
+
+int isl_ast_expr_get_int(__isl_keep isl_ast_expr *expr, isl_int *v)
+{
+	if (!expr)
+		return -1;
+	if (expr->type != isl_ast_expr_int)
+		isl_die(isl_ast_expr_get_ctx(expr), isl_error_invalid,
+			"expression not an int", return -1);
+	return isl_val_get_num_isl_int(expr->u.v, v);
+}

Added: polly/trunk/lib/External/isl/isl_ast_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_ast_private.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_ast_private.h (added)
+++ polly/trunk/lib/External/isl/isl_ast_private.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,114 @@
+#ifndef ISL_AST_PRIVATE_H
+#define ISL_AST_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/ast.h>
+#include <isl/set.h>
+#include <isl/map.h>
+#include <isl/vec.h>
+#include <isl/list.h>
+
+/* An expression is either an integer, an identifier or an operation
+ * with zero or more arguments.
+ */
+struct isl_ast_expr {
+	int ref;
+
+	isl_ctx *ctx;
+
+	enum isl_ast_expr_type type;
+
+	union {
+		isl_val *v;
+		isl_id *id;
+		struct {
+			enum isl_ast_op_type op;
+			unsigned n_arg;
+			isl_ast_expr **args;
+		} op;
+	} u;
+};
+
+#undef EL
+#define EL isl_ast_expr
+
+#include <isl_list_templ.h>
+
+__isl_give isl_ast_expr *isl_ast_expr_alloc_int_si(isl_ctx *ctx, int i);
+__isl_give isl_ast_expr *isl_ast_expr_alloc_op(isl_ctx *ctx,
+	enum isl_ast_op_type op, int n_arg);
+__isl_give isl_ast_expr *isl_ast_expr_alloc_binary(enum isl_ast_op_type type,
+	__isl_take isl_ast_expr *expr1, __isl_take isl_ast_expr *expr2);
+
+#undef EL
+#define EL isl_ast_node
+
+#include <isl_list_templ.h>
+
+/* A node is either a block, an if, a for or a user node.
+ * "else_node" is NULL if the if node does not have an else branch.
+ * "cond" and "inc" are NULL for degenerate for nodes.
+ */
+struct isl_ast_node {
+	int ref;
+
+	isl_ctx *ctx;
+	enum isl_ast_node_type type;
+
+	union {
+		struct {
+			isl_ast_node_list *children;
+		} b;
+		struct {
+			isl_ast_expr *guard;
+			isl_ast_node *then;
+			isl_ast_node *else_node;
+		} i;
+		struct {
+			unsigned degenerate : 1;
+			isl_ast_expr *iterator;
+			isl_ast_expr *init;
+			isl_ast_expr *cond;
+			isl_ast_expr *inc;
+			isl_ast_node *body;
+		} f;
+		struct {
+			isl_ast_expr *expr;
+		} e;
+	} u;
+
+	isl_id *annotation;
+};
+
+__isl_give isl_ast_node *isl_ast_node_alloc_for(__isl_take isl_id *id);
+__isl_give isl_ast_node *isl_ast_node_for_mark_degenerate(
+	__isl_take isl_ast_node *node);
+__isl_give isl_ast_node *isl_ast_node_alloc_if(__isl_take isl_ast_expr *guard);
+__isl_give isl_ast_node *isl_ast_node_alloc_block(
+	__isl_take isl_ast_node_list *list);
+__isl_give isl_ast_node *isl_ast_node_from_ast_node_list(
+	__isl_take isl_ast_node_list *list);
+__isl_give isl_ast_node *isl_ast_node_for_set_body(
+	__isl_take isl_ast_node *node, __isl_take isl_ast_node *body);
+__isl_give isl_ast_node *isl_ast_node_if_set_then(
+	__isl_take isl_ast_node *node, __isl_take isl_ast_node *child);
+
+struct isl_ast_print_options {
+	int ref;
+	isl_ctx *ctx;
+
+	__isl_give isl_printer *(*print_for)(__isl_take isl_printer *p,
+		__isl_take isl_ast_print_options *options,
+		__isl_keep isl_ast_node *node, void *user);
+	void *print_for_user;
+	__isl_give isl_printer *(*print_user)(__isl_take isl_printer *p,
+		__isl_take isl_ast_print_options *options,
+		__isl_keep isl_ast_node *node, void *user);
+	void *print_user_user;
+};
+
+__isl_give isl_printer *isl_ast_node_list_print(
+	__isl_keep isl_ast_node_list *list, __isl_take isl_printer *p,
+	__isl_keep isl_ast_print_options *options);
+
+#endif

Added: polly/trunk/lib/External/isl/isl_band.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_band.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_band.c (added)
+++ polly/trunk/lib/External/isl/isl_band.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,726 @@
+/*
+ * Copyright 2011      INRIA Saclay
+ * Copyright 2012-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
+ */
+
+#include <isl_band_private.h>
+#include <isl_schedule_private.h>
+
+#undef BASE
+#define BASE band
+
+#include <isl_list_templ.c>
+
+isl_ctx *isl_band_get_ctx(__isl_keep isl_band *band)
+{
+	return band ? isl_union_pw_multi_aff_get_ctx(band->pma) : NULL;
+}
+
+__isl_give isl_band *isl_band_alloc(isl_ctx *ctx)
+{
+	isl_band *band;
+
+	band = isl_calloc_type(ctx, isl_band);
+	if (!band)
+		return NULL;
+
+	band->ref = 1;
+
+	return band;
+}
+
+/* Create a duplicate of the given band.  The duplicate refers
+ * to the same schedule and parent as the input, but does not
+ * increment their reference counts.
+ */
+__isl_give isl_band *isl_band_dup(__isl_keep isl_band *band)
+{
+	int i;
+	isl_ctx *ctx;
+	isl_band *dup;
+
+	if (!band)
+		return NULL;
+
+	ctx = isl_band_get_ctx(band);
+	dup = isl_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)
+		goto error;
+
+	for (i = 0; i < band->n; ++i)
+		dup->coincident[i] = band->coincident[i];
+
+	dup->pma = isl_union_pw_multi_aff_copy(band->pma);
+	dup->schedule = band->schedule;
+	dup->parent = band->parent;
+
+	if (!dup->pma)
+		goto error;
+
+	return dup;
+error:
+	isl_band_free(dup);
+	return NULL;
+}
+
+/* We not only increment the reference count of the band,
+ * but also that of the schedule that contains this band.
+ * This ensures that the schedule won't disappear while there
+ * is still a reference to the band outside of the schedule.
+ * There is no need to increment the reference count of the parent
+ * band as the parent band is part of the same schedule.
+ */
+__isl_give isl_band *isl_band_copy(__isl_keep isl_band *band)
+{
+	if (!band)
+		return NULL;
+
+	band->ref++;
+	band->schedule->ref++;
+	return band;
+}
+
+/* If this is not the last reference to the band (the one from within the
+ * schedule), then we also need to decrement the reference count of the
+ * containing schedule as it was incremented in isl_band_copy.
+ */
+__isl_null isl_band *isl_band_free(__isl_take isl_band *band)
+{
+	if (!band)
+		return NULL;
+
+	if (--band->ref > 0) {
+		isl_schedule_free(band->schedule);
+		return NULL;
+	}
+
+	isl_union_pw_multi_aff_free(band->pma);
+	isl_band_list_free(band->children);
+	free(band->coincident);
+	free(band);
+
+	return NULL;
+}
+
+int isl_band_has_children(__isl_keep isl_band *band)
+{
+	if (!band)
+		return -1;
+
+	return band->children != NULL;
+}
+
+__isl_give isl_band_list *isl_band_get_children(
+	__isl_keep isl_band *band)
+{
+	if (!band)
+		return NULL;
+	if (!band->children)
+		isl_die(isl_band_get_ctx(band), isl_error_invalid,
+			"band has no children", return NULL);
+	return isl_band_list_dup(band->children);
+}
+
+int isl_band_n_member(__isl_keep isl_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_band_member_is_coincident(__isl_keep isl_band *band, int pos)
+{
+	if (!band)
+		return -1;
+
+	if (pos < 0 || pos >= band->n)
+		isl_die(isl_band_get_ctx(band), isl_error_invalid,
+			"invalid member position", return -1);
+
+	return band->coincident[pos];
+}
+
+/* Return the schedule that leads up to this band.
+ */
+__isl_give isl_union_map *isl_band_get_prefix_schedule(
+	__isl_keep isl_band *band)
+{
+	isl_union_set *domain;
+	isl_union_pw_multi_aff *prefix;
+	isl_band *a;
+
+	if (!band)
+		return NULL;
+
+	prefix = isl_union_pw_multi_aff_copy(band->pma);
+	domain = isl_union_pw_multi_aff_domain(prefix);
+	prefix = isl_union_pw_multi_aff_from_domain(domain);
+
+	for (a = band->parent; a; a = a->parent) {
+		isl_union_pw_multi_aff *partial;
+
+		partial = isl_union_pw_multi_aff_copy(a->pma);
+		prefix = isl_union_pw_multi_aff_flat_range_product(partial,
+								   prefix);
+	}
+
+	return isl_union_map_from_union_pw_multi_aff(prefix);
+}
+
+/* Return the schedule of the band in isolation.
+ */
+__isl_give isl_union_pw_multi_aff *
+isl_band_get_partial_schedule_union_pw_multi_aff(__isl_keep isl_band *band)
+{
+	return band ? isl_union_pw_multi_aff_copy(band->pma) : NULL;
+}
+
+/* Return the schedule of the band in isolation.
+ */
+__isl_give isl_union_map *isl_band_get_partial_schedule(
+	__isl_keep isl_band *band)
+{
+	isl_union_pw_multi_aff *sched;
+
+	sched = isl_band_get_partial_schedule_union_pw_multi_aff(band);
+	return isl_union_map_from_union_pw_multi_aff(sched);
+}
+
+__isl_give isl_union_pw_multi_aff *
+isl_band_get_suffix_schedule_union_pw_multi_aff(__isl_keep isl_band *band);
+
+/* Return the schedule for the given band list.
+ * For each band in the list, the schedule is composed of the partial
+ * and suffix schedules of that band.
+ */
+__isl_give isl_union_pw_multi_aff *
+isl_band_list_get_suffix_schedule_union_pw_multi_aff(
+	__isl_keep isl_band_list *list)
+{
+	isl_ctx *ctx;
+	int i, n;
+	isl_space *space;
+	isl_union_pw_multi_aff *suffix;
+
+	if (!list)
+		return NULL;
+
+	ctx = isl_band_list_get_ctx(list);
+	space = isl_space_alloc(ctx, 0, 0, 0);
+	suffix = isl_union_pw_multi_aff_empty(space);
+	n = isl_band_list_n_band(list);
+	for (i = 0; i < n; ++i) {
+		isl_band *el;
+		isl_union_pw_multi_aff *partial;
+		isl_union_pw_multi_aff *suffix_i;
+
+		el = isl_band_list_get_band(list, i);
+		partial = isl_band_get_partial_schedule_union_pw_multi_aff(el);
+		suffix_i = isl_band_get_suffix_schedule_union_pw_multi_aff(el);
+		suffix_i = isl_union_pw_multi_aff_flat_range_product(
+				partial, suffix_i);
+		suffix = isl_union_pw_multi_aff_union_add(suffix, suffix_i);
+
+		isl_band_free(el);
+	}
+
+	return suffix;
+}
+
+/* Return the schedule for the given band list.
+ * For each band in the list, the schedule is composed of the partial
+ * and suffix schedules of that band.
+ */
+__isl_give isl_union_map *isl_band_list_get_suffix_schedule(
+	__isl_keep isl_band_list *list)
+{
+	isl_union_pw_multi_aff *suffix;
+
+	suffix = isl_band_list_get_suffix_schedule_union_pw_multi_aff(list);
+	return isl_union_map_from_union_pw_multi_aff(suffix);
+}
+
+/* Return the schedule for the forest underneath the given band.
+ */
+__isl_give isl_union_pw_multi_aff *
+isl_band_get_suffix_schedule_union_pw_multi_aff(__isl_keep isl_band *band)
+{
+	isl_union_pw_multi_aff *suffix;
+
+	if (!band)
+		return NULL;
+
+	if (!isl_band_has_children(band)) {
+		isl_union_set *domain;
+
+		suffix = isl_union_pw_multi_aff_copy(band->pma);
+		domain = isl_union_pw_multi_aff_domain(suffix);
+		suffix = isl_union_pw_multi_aff_from_domain(domain);
+	} else {
+		isl_band_list *list;
+
+		list = isl_band_get_children(band);
+		suffix =
+		    isl_band_list_get_suffix_schedule_union_pw_multi_aff(list);
+		isl_band_list_free(list);
+	}
+
+	return suffix;
+}
+
+/* Return the schedule for the forest underneath the given band.
+ */
+__isl_give isl_union_map *isl_band_get_suffix_schedule(
+	__isl_keep isl_band *band)
+{
+	isl_union_pw_multi_aff *suffix;
+
+	suffix = isl_band_get_suffix_schedule_union_pw_multi_aff(band);
+	return isl_union_map_from_union_pw_multi_aff(suffix);
+}
+
+/* Call "fn" on each band (recursively) in the list
+ * in depth-first post-order.
+ */
+int isl_band_list_foreach_band(__isl_keep isl_band_list *list,
+	int (*fn)(__isl_keep isl_band *band, void *user), void *user)
+{
+	int i, n;
+
+	if (!list)
+		return -1;
+
+	n = isl_band_list_n_band(list);
+	for (i = 0; i < n; ++i) {
+		isl_band *band;
+		int r = 0;
+
+		band = isl_band_list_get_band(list, i);
+		if (isl_band_has_children(band)) {
+			isl_band_list *children;
+
+			children = isl_band_get_children(band);
+			r = isl_band_list_foreach_band(children, fn, user);
+			isl_band_list_free(children);
+		}
+
+		if (!band)
+			r = -1;
+		if (r == 0)
+			r = fn(band, user);
+
+		isl_band_free(band);
+		if (r)
+			return r;
+	}
+
+	return 0;
+}
+
+/* Internal data used during the construction of the schedule
+ * for the tile loops.
+ *
+ * sizes contains the tile sizes
+ * scale is set if the tile loops should be scaled
+ * tiled collects the result for a single statement
+ * res collects the result for all statements
+ */
+struct isl_band_tile_data {
+	isl_multi_val *sizes;
+	isl_union_pw_multi_aff *res;
+	isl_pw_multi_aff *tiled;
+	int scale;
+};
+
+/* Given part of the schedule of a band, construct the corresponding
+ * schedule for the tile loops based on the tile sizes in data->sizes
+ * and add the result to data->tiled.
+ *
+ * If data->scale is set, then dimension i of the schedule will be
+ * of the form
+ *
+ *	m_i * floor(s_i(x) / m_i)
+ *
+ * where s_i(x) refers to the original schedule and m_i is the tile size.
+ * If data->scale is not set, then dimension i of the schedule will be
+ * of the form
+ *
+ *	floor(s_i(x) / m_i)
+ *
+ */
+static int multi_aff_tile(__isl_take isl_set *set,
+	__isl_take isl_multi_aff *ma, void *user)
+{
+	struct isl_band_tile_data *data = user;
+	isl_pw_multi_aff *pma;
+	int i, n;
+	isl_val *v;
+
+	n = isl_multi_aff_dim(ma, isl_dim_out);
+
+	for (i = 0; i < n; ++i) {
+		isl_aff *aff;
+
+		aff = isl_multi_aff_get_aff(ma, i);
+		v = isl_multi_val_get_val(data->sizes, i);
+
+		aff = isl_aff_scale_down_val(aff, isl_val_copy(v));
+		aff = isl_aff_floor(aff);
+		if (data->scale)
+			aff = isl_aff_scale_val(aff, isl_val_copy(v));
+		isl_val_free(v);
+
+		ma = isl_multi_aff_set_aff(ma, i, aff);
+	}
+
+	pma = isl_pw_multi_aff_alloc(set, ma);
+	data->tiled = isl_pw_multi_aff_union_add(data->tiled, pma);
+
+	return 0;
+}
+
+/* Given part of the schedule of a band, construct the corresponding
+ * schedule for the tile loops based on the tile sizes in data->sizes
+ * and add the result to data->res.
+ */
+static int pw_multi_aff_tile(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+	struct isl_band_tile_data *data = user;
+
+	data->tiled = isl_pw_multi_aff_empty(isl_pw_multi_aff_get_space(pma));
+
+	if (isl_pw_multi_aff_foreach_piece(pma, &multi_aff_tile, data) < 0)
+		goto error;
+
+	isl_pw_multi_aff_free(pma);
+	data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res,
+								data->tiled);
+
+	return 0;
+error:
+	isl_pw_multi_aff_free(pma);
+	isl_pw_multi_aff_free(data->tiled);
+	return -1;
+}
+
+/* Given the schedule of a band, construct the corresponding
+ * schedule for the tile loops based on the given tile sizes
+ * and return the result.
+ */
+static isl_union_pw_multi_aff *isl_union_pw_multi_aff_tile(
+	__isl_take isl_union_pw_multi_aff *sched,
+	__isl_keep isl_multi_val *sizes)
+{
+	isl_ctx *ctx;
+	isl_space *space;
+	struct isl_band_tile_data data = { sizes };
+
+	ctx = isl_multi_val_get_ctx(sizes);
+
+	space = isl_union_pw_multi_aff_get_space(sched);
+	data.res = isl_union_pw_multi_aff_empty(space);
+	data.scale = isl_options_get_tile_scale_tile_loops(ctx);
+
+	if (isl_union_pw_multi_aff_foreach_pw_multi_aff(sched,
+						&pw_multi_aff_tile, &data) < 0)
+		goto error;
+
+	isl_union_pw_multi_aff_free(sched);
+	return data.res;
+error:
+	isl_union_pw_multi_aff_free(sched);
+	isl_union_pw_multi_aff_free(data.res);
+	return NULL;
+}
+
+/* Extract the range space from "pma" and store it in *user.
+ * All entries are expected to have the same range space, so we can
+ * stop after extracting the range space from the first entry.
+ */
+static int extract_range_space(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+	isl_space **space = user;
+
+	*space = isl_space_range(isl_pw_multi_aff_get_space(pma));
+	isl_pw_multi_aff_free(pma);
+
+	return -1;
+}
+
+/* Extract the range space of "band".  All entries in band->pma should
+ * have the same range space.  Furthermore, band->pma should have at least
+ * one entry.
+ */
+static __isl_give isl_space *band_get_range_space(__isl_keep isl_band *band)
+{
+	isl_space *space;
+
+	if (!band)
+		return NULL;
+
+	space = NULL;
+	isl_union_pw_multi_aff_foreach_pw_multi_aff(band->pma,
+						&extract_range_space, &space);
+
+	return space;
+}
+
+/* Construct and return an isl_multi_val in the given space, with as entries
+ * the first elements of "v", padded with ones if the size of "v" is smaller
+ * than the dimension of "space".
+ */
+static __isl_give isl_multi_val *multi_val_from_vec(__isl_take isl_space *space,
+	__isl_take isl_vec *v)
+{
+	isl_ctx *ctx;
+	isl_multi_val *mv;
+	int i, n, size;
+
+	if (!space || !v)
+		goto error;
+
+	ctx = isl_space_get_ctx(space);
+	mv = isl_multi_val_zero(space);
+	n = isl_multi_val_dim(mv, isl_dim_set);
+	size = isl_vec_size(v);
+	if (n < size)
+		size = n;
+
+	for (i = 0; i < size; ++i) {
+		isl_val *val = isl_vec_get_element_val(v, i);
+		mv = isl_multi_val_set_val(mv, i, val);
+	}
+	for (i = size; i < n; ++i)
+		mv = isl_multi_val_set_val(mv, i, isl_val_one(ctx));
+
+	isl_vec_free(v);
+	return mv;
+error:
+	isl_space_free(space);
+	isl_vec_free(v);
+	return NULL;
+}
+
+/* Tile the given band using the specified tile sizes.
+ * The given band is modified to refer to the tile loops and
+ * a child band is created to refer to the point loops.
+ * The children of this point loop band are the children
+ * of the original band.
+ *
+ * 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)
+ */
+int isl_band_tile(__isl_keep isl_band *band, __isl_take isl_vec *sizes)
+{
+	isl_ctx *ctx;
+	isl_band *child;
+	isl_band_list *list = NULL;
+	isl_union_pw_multi_aff *sched = NULL, *child_sched = NULL;
+	isl_space *space;
+	isl_multi_val *mv_sizes;
+
+	if (!band || !sizes)
+		goto error;
+
+	ctx = isl_vec_get_ctx(sizes);
+	child = isl_band_dup(band);
+	list = isl_band_list_alloc(ctx, 1);
+	list = isl_band_list_add(list, child);
+	if (!list)
+		goto error;
+
+	space = band_get_range_space(band);
+	mv_sizes = multi_val_from_vec(space, isl_vec_copy(sizes));
+	sched = isl_union_pw_multi_aff_copy(band->pma);
+	sched = isl_union_pw_multi_aff_tile(sched, mv_sizes);
+
+	child_sched = isl_union_pw_multi_aff_copy(child->pma);
+	if (isl_options_get_tile_shift_point_loops(ctx)) {
+		isl_union_pw_multi_aff *scaled;
+		scaled = isl_union_pw_multi_aff_copy(sched);
+		if (!isl_options_get_tile_scale_tile_loops(ctx))
+			scaled = isl_union_pw_multi_aff_scale_multi_val(scaled,
+						isl_multi_val_copy(mv_sizes));
+		child_sched = isl_union_pw_multi_aff_sub(child_sched, scaled);
+	}
+	isl_multi_val_free(mv_sizes);
+	if (!sched || !child_sched)
+		goto error;
+
+	child->children = band->children;
+	band->children = list;
+	child->parent = band;
+	isl_union_pw_multi_aff_free(band->pma);
+	band->pma = sched;
+	isl_union_pw_multi_aff_free(child->pma);
+	child->pma = child_sched;
+
+	isl_vec_free(sizes);
+	return 0;
+error:
+	isl_union_pw_multi_aff_free(sched);
+	isl_union_pw_multi_aff_free(child_sched);
+	isl_band_list_free(list);
+	isl_vec_free(sizes);
+	return -1;
+}
+
+/* Internal data structure used inside isl_union_pw_multi_aff_drop.
+ *
+ * "pos" is the position of the first dimension to drop.
+ * "n" is the number of dimensions to drop.
+ * "res" accumulates the result.
+ */
+struct isl_union_pw_multi_aff_drop_data {
+	int pos;
+	int n;
+	isl_union_pw_multi_aff *res;
+};
+
+/* Drop the data->n output dimensions starting at data->pos from "pma"
+ * and add the result to data->res.
+ */
+static int pw_multi_aff_drop(__isl_take isl_pw_multi_aff *pma, void *user)
+{
+	struct isl_union_pw_multi_aff_drop_data *data = user;
+
+	pma = isl_pw_multi_aff_drop_dims(pma, isl_dim_out, data->pos, data->n);
+
+	data->res = isl_union_pw_multi_aff_add_pw_multi_aff(data->res, pma);
+	if (!data->res)
+		return -1;
+
+	return 0;
+}
+
+/* Drop the "n" output dimensions starting at "pos" from "sched".
+ */
+static isl_union_pw_multi_aff *isl_union_pw_multi_aff_drop(
+	__isl_take isl_union_pw_multi_aff *sched, int pos, int n)
+{
+	isl_space *space;
+	struct isl_union_pw_multi_aff_drop_data data = { pos, n };
+
+	space = isl_union_pw_multi_aff_get_space(sched);
+	data.res = isl_union_pw_multi_aff_empty(space);
+
+	if (isl_union_pw_multi_aff_foreach_pw_multi_aff(sched,
+						&pw_multi_aff_drop, &data) < 0)
+		data.res = isl_union_pw_multi_aff_free(data.res);
+
+	isl_union_pw_multi_aff_free(sched);
+	return data.res;
+}
+
+/* Drop the "n" dimensions starting at "pos" from "band".
+ */
+static int isl_band_drop(__isl_keep isl_band *band, int pos, int n)
+{
+	int i;
+	isl_union_pw_multi_aff *sched;
+
+	if (!band)
+		return -1;
+	if (n == 0)
+		return 0;
+
+	sched = isl_union_pw_multi_aff_copy(band->pma);
+	sched = isl_union_pw_multi_aff_drop(sched, pos, n);
+	if (!sched)
+		return -1;
+
+	isl_union_pw_multi_aff_free(band->pma);
+	band->pma = sched;
+
+	for (i = pos + n; i < band->n; ++i)
+		band->coincident[i - n] = band->coincident[i];
+
+	band->n -= n;
+
+	return 0;
+}
+
+/* Split the given band into two nested bands, one with the first "pos"
+ * dimensions of "band" and one with the remaining band->n - pos dimensions.
+ */
+int isl_band_split(__isl_keep isl_band *band, int pos)
+{
+	isl_ctx *ctx;
+	isl_band *child;
+	isl_band_list *list;
+
+	if (!band)
+		return -1;
+
+	ctx = isl_band_get_ctx(band);
+
+	if (pos < 0 || pos > band->n)
+		isl_die(ctx, isl_error_invalid, "position out of bounds",
+			return -1);
+
+	child = isl_band_dup(band);
+	if (isl_band_drop(child, 0, pos) < 0)
+		child = isl_band_free(child);
+	list = isl_band_list_alloc(ctx, 1);
+	list = isl_band_list_add(list, child);
+	if (!list)
+		return -1;
+
+	if (isl_band_drop(band, pos, band->n - pos) < 0) {
+		isl_band_list_free(list);
+		return -1;
+	}
+
+	child->children = band->children;
+	band->children = list;
+	child->parent = band;
+
+	return 0;
+}
+
+__isl_give isl_printer *isl_printer_print_band(__isl_take isl_printer *p,
+	__isl_keep isl_band *band)
+{
+	isl_union_map *prefix, *partial, *suffix;
+
+	prefix = isl_band_get_prefix_schedule(band);
+	partial = isl_band_get_partial_schedule(band);
+	suffix = isl_band_get_suffix_schedule(band);
+
+	p = isl_printer_print_str(p, "(");
+	p = isl_printer_print_union_map(p, prefix);
+	p = isl_printer_print_str(p, ",");
+	p = isl_printer_print_union_map(p, partial);
+	p = isl_printer_print_str(p, ",");
+	p = isl_printer_print_union_map(p, suffix);
+	p = isl_printer_print_str(p, ")");
+
+	isl_union_map_free(prefix);
+	isl_union_map_free(partial);
+	isl_union_map_free(suffix);
+
+	return p;
+}

Added: polly/trunk/lib/External/isl/isl_band_private.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_band_private.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_band_private.h (added)
+++ polly/trunk/lib/External/isl/isl_band_private.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,47 @@
+#ifndef ISL_BAND_PRIVATE_H
+#define ISL_BAND_PRIVATE_H
+
+#include <isl/aff.h>
+#include <isl/band.h>
+#include <isl/list.h>
+#include <isl/schedule.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.
+ * pma is the partial schedule corresponding to this band.
+ * schedule is the schedule that contains this band.
+ * parent is the parent of this band (or NULL if the band is a root).
+ * children are the children of this band (or NULL if the band is a leaf).
+ *
+ * To avoid circular dependences in the reference counting,
+ * the schedule and parent pointers are not reference counted.
+ * isl_band_copy increments the reference count of schedule to ensure
+ * that outside references to the band keep the schedule alive.
+ */
+struct isl_band {
+	int ref;
+
+	int n;
+	int *coincident;
+
+	isl_union_pw_multi_aff *pma;
+	isl_schedule *schedule;
+	isl_band *parent;
+	isl_band_list *children;
+};
+
+#undef EL
+#define EL isl_band
+
+#include <isl_list_templ.h>
+
+__isl_give isl_band *isl_band_alloc(isl_ctx *ctx);
+
+__isl_give isl_union_map *isl_band_list_get_suffix_schedule(
+	__isl_keep isl_band_list *list);
+
+#endif

Added: polly/trunk/lib/External/isl/isl_basis_reduction.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_basis_reduction.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_basis_reduction.h (added)
+++ polly/trunk/lib/External/isl/isl_basis_reduction.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_BASIS_REDUCTION_H
+#define ISL_BASIS_REDUCTION_H
+
+#include <isl/set.h>
+#include <isl_mat_private.h>
+#include "isl_tab.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_tab *isl_tab_compute_reduced_basis(struct isl_tab *tab);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/isl_bernstein.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_bernstein.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_bernstein.c (added)
+++ polly/trunk/lib/External/isl/isl_bernstein.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,555 @@
+/*
+ * Copyright 2006-2007 Universiteit Leiden
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ * Copyright 2010      INRIA Saclay
+ *
+ * Use of this software is governed by the MIT license
+ *
+ * Written by Sven Verdoolaege, Leiden Institute of Advanced Computer Science,
+ * Universiteit Leiden, Niels Bohrweg 1, 2333 CA Leiden, The Netherlands
+ * and K.U.Leuven, Departement Computerwetenschappen, Celestijnenlaan 200A,
+ * B-3001 Leuven, Belgium
+ * and INRIA Saclay - Ile-de-France, Parc Club Orsay Universite,
+ * ZAC des vignes, 4 rue Jacques Monod, 91893 Orsay, France
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl/set.h>
+#include <isl_seq.h>
+#include <isl_morph.h>
+#include <isl_factorization.h>
+#include <isl_vertices_private.h>
+#include <isl_polynomial_private.h>
+#include <isl_options_private.h>
+#include <isl_vec_private.h>
+#include <isl_bernstein.h>
+
+struct bernstein_data {
+	enum isl_fold type;
+	isl_qpolynomial *poly;
+	int check_tight;
+
+	isl_cell *cell;
+
+	isl_qpolynomial_fold *fold;
+	isl_qpolynomial_fold *fold_tight;
+	isl_pw_qpolynomial_fold *pwf;
+	isl_pw_qpolynomial_fold *pwf_tight;
+};
+
+static int vertex_is_integral(__isl_keep isl_basic_set *vertex)
+{
+	unsigned nvar;
+	unsigned nparam;
+	int i;
+
+	nvar = isl_basic_set_dim(vertex, isl_dim_set);
+	nparam = isl_basic_set_dim(vertex, isl_dim_param);
+	for (i = 0; i < nvar; ++i) {
+		int r = nvar - 1 - i;
+		if (!isl_int_is_one(vertex->eq[r][1 + nparam + i]) &&
+		    !isl_int_is_negone(vertex->eq[r][1 + nparam + i]))
+			return 0;
+	}
+
+	return 1;
+}
+
+static __isl_give isl_qpolynomial *vertex_coordinate(
+	__isl_keep isl_basic_set *vertex, int i, __isl_take isl_space *dim)
+{
+	unsigned nvar;
+	unsigned nparam;
+	int r;
+	isl_int denom;
+	isl_qpolynomial *v;
+
+	nvar = isl_basic_set_dim(vertex, isl_dim_set);
+	nparam = isl_basic_set_dim(vertex, isl_dim_param);
+	r = nvar - 1 - i;
+
+	isl_int_init(denom);
+	isl_int_set(denom, vertex->eq[r][1 + nparam + i]);
+	isl_assert(vertex->ctx, !isl_int_is_zero(denom), goto error);
+
+	if (isl_int_is_pos(denom))
+		isl_seq_neg(vertex->eq[r], vertex->eq[r],
+				1 + isl_basic_set_total_dim(vertex));
+	else
+		isl_int_neg(denom, denom);
+
+	v = isl_qpolynomial_from_affine(dim, vertex->eq[r], denom);
+	isl_int_clear(denom);
+
+	return v;
+error:
+	isl_space_free(dim);
+	isl_int_clear(denom);
+	return NULL;
+}
+
+/* Check whether the bound associated to the selection "k" is tight,
+ * which is the case if we select exactly one vertex and if that vertex
+ * is integral for all values of the parameters.
+ */
+static int is_tight(int *k, int n, int d, isl_cell *cell)
+{
+	int i;
+
+	for (i = 0; i < n; ++i) {
+		int v;
+		if (k[i] != d) {
+			if (k[i])
+				return 0;
+			continue;
+		}
+		v = cell->ids[n - 1 - i];
+		return vertex_is_integral(cell->vertices->v[v].vertex);
+	}
+
+	return 0;
+}
+
+static void add_fold(__isl_take isl_qpolynomial *b, __isl_keep isl_set *dom,
+	int *k, int n, int d, struct bernstein_data *data)
+{
+	isl_qpolynomial_fold *fold;
+
+	fold = isl_qpolynomial_fold_alloc(data->type, b);
+
+	if (data->check_tight && is_tight(k, n, d, data->cell))
+		data->fold_tight = isl_qpolynomial_fold_fold_on_domain(dom,
+							data->fold_tight, fold);
+	else
+		data->fold = isl_qpolynomial_fold_fold_on_domain(dom,
+							data->fold, fold);
+}
+
+/* Extract the coefficients of the Bernstein base polynomials and store
+ * them in data->fold and data->fold_tight.
+ *
+ * In particular, the coefficient of each monomial
+ * of multi-degree (k[0], k[1], ..., k[n-1]) is divided by the corresponding
+ * multinomial coefficient d!/k[0]! k[1]! ... k[n-1]!
+ *
+ * c[i] contains the coefficient of the selected powers of the first i+1 vars.
+ * multinom[i] contains the partial multinomial coefficient.
+ */
+static void extract_coefficients(isl_qpolynomial *poly,
+	__isl_keep isl_set *dom, struct bernstein_data *data)
+{
+	int i;
+	int d;
+	int n;
+	isl_ctx *ctx;
+	isl_qpolynomial **c = NULL;
+	int *k = NULL;
+	int *left = NULL;
+	isl_vec *multinom = NULL;
+
+	if (!poly)
+		return;
+
+	ctx = isl_qpolynomial_get_ctx(poly);
+	n = isl_qpolynomial_dim(poly, isl_dim_in);
+	d = isl_qpolynomial_degree(poly);
+	isl_assert(ctx, n >= 2, return);
+
+	c = isl_calloc_array(ctx, isl_qpolynomial *, n);
+	k = isl_alloc_array(ctx, int, n);
+	left = isl_alloc_array(ctx, int, n);
+	multinom = isl_vec_alloc(ctx, n);
+	if (!c || !k || !left || !multinom)
+		goto error;
+
+	isl_int_set_si(multinom->el[0], 1);
+	for (k[0] = d; k[0] >= 0; --k[0]) {
+		int i = 1;
+		isl_qpolynomial_free(c[0]);
+		c[0] = isl_qpolynomial_coeff(poly, isl_dim_in, n - 1, k[0]);
+		left[0] = d - k[0];
+		k[1] = -1;
+		isl_int_set(multinom->el[1], multinom->el[0]);
+		while (i > 0) {
+			if (i == n - 1) {
+				int j;
+				isl_space *dim;
+				isl_qpolynomial *b;
+				isl_qpolynomial *f;
+				for (j = 2; j <= left[i - 1]; ++j)
+					isl_int_divexact_ui(multinom->el[i],
+						multinom->el[i], j);
+				b = isl_qpolynomial_coeff(c[i - 1], isl_dim_in,
+					n - 1 - i, left[i - 1]);
+				b = isl_qpolynomial_project_domain_on_params(b);
+				dim = isl_qpolynomial_get_domain_space(b);
+				f = isl_qpolynomial_rat_cst_on_domain(dim, ctx->one,
+					multinom->el[i]);
+				b = isl_qpolynomial_mul(b, f);
+				k[n - 1] = left[n - 2];
+				add_fold(b, dom, k, n, d, data);
+				--i;
+				continue;
+			}
+			if (k[i] >= left[i - 1]) {
+				--i;
+				continue;
+			}
+			++k[i];
+			if (k[i])
+				isl_int_divexact_ui(multinom->el[i],
+					multinom->el[i], k[i]);
+			isl_qpolynomial_free(c[i]);
+			c[i] = isl_qpolynomial_coeff(c[i - 1], isl_dim_in,
+					n - 1 - i, k[i]);
+			left[i] = left[i - 1] - k[i];
+			k[i + 1] = -1;
+			isl_int_set(multinom->el[i + 1], multinom->el[i]);
+			++i;
+		}
+		isl_int_mul_ui(multinom->el[0], multinom->el[0], k[0]);
+	}
+
+	for (i = 0; i < n; ++i)
+		isl_qpolynomial_free(c[i]);
+
+	isl_vec_free(multinom);
+	free(left);
+	free(k);
+	free(c);
+	return;
+error:
+	isl_vec_free(multinom);
+	free(left);
+	free(k);
+	if (c)
+		for (i = 0; i < n; ++i)
+			isl_qpolynomial_free(c[i]);
+	free(c);
+	return;
+}
+
+/* Perform bernstein expansion on the parametric vertices that are active
+ * on "cell".
+ *
+ * data->poly has been homogenized in the calling function.
+ *
+ * We plug in the barycentric coordinates for the set variables
+ *
+ *		\vec x = \sum_i \alpha_i v_i(\vec p)
+ *
+ * and the constant "1 = \sum_i \alpha_i" for the homogeneous dimension.
+ * Next, we extract the coefficients of the Bernstein base polynomials.
+ */
+static int bernstein_coefficients_cell(__isl_take isl_cell *cell, void *user)
+{
+	int i, j;
+	struct bernstein_data *data = (struct bernstein_data *)user;
+	isl_space *dim_param;
+	isl_space *dim_dst;
+	isl_qpolynomial *poly = data->poly;
+	unsigned nvar;
+	int n_vertices;
+	isl_qpolynomial **subs;
+	isl_pw_qpolynomial_fold *pwf;
+	isl_set *dom;
+	isl_ctx *ctx;
+
+	if (!poly)
+		goto error;
+
+	nvar = isl_qpolynomial_dim(poly, isl_dim_in) - 1;
+	n_vertices = cell->n_vertices;
+
+	ctx = isl_qpolynomial_get_ctx(poly);
+	if (n_vertices > nvar + 1 && ctx->opt->bernstein_triangulate)
+		return isl_cell_foreach_simplex(cell,
+					    &bernstein_coefficients_cell, user);
+
+	subs = isl_alloc_array(ctx, isl_qpolynomial *, 1 + nvar);
+	if (!subs)
+		goto error;
+
+	dim_param = isl_basic_set_get_space(cell->dom);
+	dim_dst = isl_qpolynomial_get_domain_space(poly);
+	dim_dst = isl_space_add_dims(dim_dst, isl_dim_set, n_vertices);
+
+	for (i = 0; i < 1 + nvar; ++i)
+		subs[i] = isl_qpolynomial_zero_on_domain(isl_space_copy(dim_dst));
+
+	for (i = 0; i < n_vertices; ++i) {
+		isl_qpolynomial *c;
+		c = isl_qpolynomial_var_on_domain(isl_space_copy(dim_dst), isl_dim_set,
+					1 + nvar + i);
+		for (j = 0; j < nvar; ++j) {
+			int k = cell->ids[i];
+			isl_qpolynomial *v;
+			v = vertex_coordinate(cell->vertices->v[k].vertex, j,
+						isl_space_copy(dim_param));
+			v = isl_qpolynomial_add_dims(v, isl_dim_in,
+							1 + nvar + n_vertices);
+			v = isl_qpolynomial_mul(v, isl_qpolynomial_copy(c));
+			subs[1 + j] = isl_qpolynomial_add(subs[1 + j], v);
+		}
+		subs[0] = isl_qpolynomial_add(subs[0], c);
+	}
+	isl_space_free(dim_dst);
+
+	poly = isl_qpolynomial_copy(poly);
+
+	poly = isl_qpolynomial_add_dims(poly, isl_dim_in, n_vertices);
+	poly = isl_qpolynomial_substitute(poly, isl_dim_in, 0, 1 + nvar, subs);
+	poly = isl_qpolynomial_drop_dims(poly, isl_dim_in, 0, 1 + nvar);
+
+	data->cell = cell;
+	dom = isl_set_from_basic_set(isl_basic_set_copy(cell->dom));
+	data->fold = isl_qpolynomial_fold_empty(data->type, isl_space_copy(dim_param));
+	data->fold_tight = isl_qpolynomial_fold_empty(data->type, dim_param);
+	extract_coefficients(poly, dom, data);
+
+	pwf = isl_pw_qpolynomial_fold_alloc(data->type, isl_set_copy(dom),
+					    data->fold);
+	data->pwf = isl_pw_qpolynomial_fold_fold(data->pwf, pwf);
+	pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, data->fold_tight);
+	data->pwf_tight = isl_pw_qpolynomial_fold_fold(data->pwf_tight, pwf);
+
+	isl_qpolynomial_free(poly);
+	isl_cell_free(cell);
+	for (i = 0; i < 1 + nvar; ++i)
+		isl_qpolynomial_free(subs[i]);
+	free(subs);
+	return 0;
+error:
+	isl_cell_free(cell);
+	return -1;
+}
+
+/* Base case of applying bernstein expansion.
+ *
+ * We compute the chamber decomposition of the parametric polytope "bset"
+ * and then perform bernstein expansion on the parametric vertices
+ * that are active on each chamber.
+ */
+static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_base(
+	__isl_take isl_basic_set *bset,
+	__isl_take isl_qpolynomial *poly, struct bernstein_data *data, int *tight)
+{
+	unsigned nvar;
+	isl_space *dim;
+	isl_pw_qpolynomial_fold *pwf;
+	isl_vertices *vertices;
+	int covers;
+
+	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	if (nvar == 0) {
+		isl_set *dom;
+		isl_qpolynomial_fold *fold;
+
+		fold = isl_qpolynomial_fold_alloc(data->type, poly);
+		dom = isl_set_from_basic_set(bset);
+		if (tight)
+			*tight = 1;
+		pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, fold);
+		return isl_pw_qpolynomial_fold_project_domain_on_params(pwf);
+	}
+
+	if (isl_qpolynomial_is_zero(poly)) {
+		isl_set *dom;
+		isl_qpolynomial_fold *fold;
+		fold = isl_qpolynomial_fold_alloc(data->type, poly);
+		dom = isl_set_from_basic_set(bset);
+		pwf = isl_pw_qpolynomial_fold_alloc(data->type, dom, fold);
+		if (tight)
+			*tight = 1;
+		return isl_pw_qpolynomial_fold_project_domain_on_params(pwf);
+	}
+
+	dim = isl_basic_set_get_space(bset);
+	dim = isl_space_params(dim);
+	dim = isl_space_from_domain(dim);
+	dim = isl_space_add_dims(dim, isl_dim_set, 1);
+	data->pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(dim), data->type);
+	data->pwf_tight = isl_pw_qpolynomial_fold_zero(dim, data->type);
+	data->poly = isl_qpolynomial_homogenize(isl_qpolynomial_copy(poly));
+	vertices = isl_basic_set_compute_vertices(bset);
+	isl_vertices_foreach_disjoint_cell(vertices,
+		&bernstein_coefficients_cell, data);
+	isl_vertices_free(vertices);
+	isl_qpolynomial_free(data->poly);
+
+	isl_basic_set_free(bset);
+	isl_qpolynomial_free(poly);
+
+	covers = isl_pw_qpolynomial_fold_covers(data->pwf_tight, data->pwf);
+	if (covers < 0)
+		goto error;
+
+	if (tight)
+		*tight = covers;
+
+	if (covers) {
+		isl_pw_qpolynomial_fold_free(data->pwf);
+		return data->pwf_tight;
+	}
+
+	data->pwf = isl_pw_qpolynomial_fold_fold(data->pwf, data->pwf_tight);
+
+	return data->pwf;
+error:
+	isl_pw_qpolynomial_fold_free(data->pwf_tight);
+	isl_pw_qpolynomial_fold_free(data->pwf);
+	return NULL;
+}
+
+/* Apply bernstein expansion recursively by working in on len[i]
+ * set variables at a time, with i ranging from n_group - 1 to 0.
+ */
+static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_recursive(
+	__isl_take isl_pw_qpolynomial *pwqp,
+	int n_group, int *len, struct bernstein_data *data, int *tight)
+{
+	int i;
+	unsigned nparam;
+	unsigned nvar;
+	isl_pw_qpolynomial_fold *pwf;
+
+	if (!pwqp)
+		return NULL;
+
+	nparam = isl_pw_qpolynomial_dim(pwqp, isl_dim_param);
+	nvar = isl_pw_qpolynomial_dim(pwqp, isl_dim_in);
+
+	pwqp = isl_pw_qpolynomial_move_dims(pwqp, isl_dim_param, nparam,
+					isl_dim_in, 0, nvar - len[n_group - 1]);
+	pwf = isl_pw_qpolynomial_bound(pwqp, data->type, tight);
+
+	for (i = n_group - 2; i >= 0; --i) {
+		nparam = isl_pw_qpolynomial_fold_dim(pwf, isl_dim_param);
+		pwf = isl_pw_qpolynomial_fold_move_dims(pwf, isl_dim_in, 0,
+				isl_dim_param, nparam - len[i], len[i]);
+		if (tight && !*tight)
+			tight = NULL;
+		pwf = isl_pw_qpolynomial_fold_bound(pwf, tight);
+	}
+
+	return pwf;
+}
+
+static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_factors(
+	__isl_take isl_basic_set *bset,
+	__isl_take isl_qpolynomial *poly, struct bernstein_data *data, int *tight)
+{
+	isl_factorizer *f;
+	isl_set *set;
+	isl_pw_qpolynomial *pwqp;
+	isl_pw_qpolynomial_fold *pwf;
+
+	f = isl_basic_set_factorizer(bset);
+	if (!f)
+		goto error;
+	if (f->n_group == 0) {
+		isl_factorizer_free(f);
+		return  bernstein_coefficients_base(bset, poly, data, tight);
+	}
+
+	set = isl_set_from_basic_set(bset);
+	pwqp = isl_pw_qpolynomial_alloc(set, poly);
+	pwqp = isl_pw_qpolynomial_morph_domain(pwqp, isl_morph_copy(f->morph));
+
+	pwf = bernstein_coefficients_recursive(pwqp, f->n_group, f->len, data,
+						tight);
+
+	isl_factorizer_free(f);
+
+	return pwf;
+error:
+	isl_basic_set_free(bset);
+	isl_qpolynomial_free(poly);
+	return NULL;
+}
+
+static __isl_give isl_pw_qpolynomial_fold *bernstein_coefficients_full_recursive(
+	__isl_take isl_basic_set *bset,
+	__isl_take isl_qpolynomial *poly, struct bernstein_data *data, int *tight)
+{
+	int i;
+	int *len;
+	unsigned nvar;
+	isl_pw_qpolynomial_fold *pwf;
+	isl_set *set;
+	isl_pw_qpolynomial *pwqp;
+
+	if (!bset || !poly)
+		goto error;
+
+	nvar = isl_basic_set_dim(bset, isl_dim_set);
+	
+	len = isl_alloc_array(bset->ctx, int, nvar);
+	if (nvar && !len)
+		goto error;
+
+	for (i = 0; i < nvar; ++i)
+		len[i] = 1;
+
+	set = isl_set_from_basic_set(bset);
+	pwqp = isl_pw_qpolynomial_alloc(set, poly);
+
+	pwf = bernstein_coefficients_recursive(pwqp, nvar, len, data, tight);
+
+	free(len);
+
+	return pwf;
+error:
+	isl_basic_set_free(bset);
+	isl_qpolynomial_free(poly);
+	return NULL;
+}
+
+/* Compute a bound on the polynomial defined over the parametric polytope
+ * using bernstein expansion and store the result
+ * in bound->pwf and bound->pwf_tight.
+ *
+ * If bernstein_recurse is set to ISL_BERNSTEIN_FACTORS, we check if
+ * the polytope can be factorized and apply bernstein expansion recursively
+ * on the factors.
+ * If bernstein_recurse is set to ISL_BERNSTEIN_INTERVALS, we apply
+ * bernstein expansion recursively on each dimension.
+ * Otherwise, we apply bernstein expansion on the entire polytope.
+ */
+int isl_qpolynomial_bound_on_domain_bernstein(__isl_take isl_basic_set *bset,
+	__isl_take isl_qpolynomial *poly, struct isl_bound *bound)
+{
+	struct bernstein_data data;
+	isl_pw_qpolynomial_fold *pwf;
+	unsigned nvar;
+	int tight = 0;
+	int *tp = bound->check_tight ? &tight : NULL;
+
+	if (!bset || !poly)
+		goto error;
+
+	data.type = bound->type;
+	data.check_tight = bound->check_tight;
+
+	nvar = isl_basic_set_dim(bset, isl_dim_set);
+
+	if (bset->ctx->opt->bernstein_recurse & ISL_BERNSTEIN_FACTORS)
+		pwf = bernstein_coefficients_factors(bset, poly, &data, tp);
+	else if (nvar > 1 &&
+	    (bset->ctx->opt->bernstein_recurse & ISL_BERNSTEIN_INTERVALS))
+		pwf = bernstein_coefficients_full_recursive(bset, poly, &data, tp);
+	else
+		pwf = bernstein_coefficients_base(bset, poly, &data, tp);
+
+	if (tight)
+		bound->pwf_tight = isl_pw_qpolynomial_fold_fold(bound->pwf_tight, pwf);
+	else
+		bound->pwf = isl_pw_qpolynomial_fold_fold(bound->pwf, pwf);
+
+	return 0;
+error:
+	isl_basic_set_free(bset);
+	isl_qpolynomial_free(poly);
+	return -1;
+}

Added: polly/trunk/lib/External/isl/isl_bernstein.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_bernstein.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_bernstein.h (added)
+++ polly/trunk/lib/External/isl/isl_bernstein.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,4 @@
+#include <isl_bound.h>
+
+int isl_qpolynomial_bound_on_domain_bernstein(__isl_take isl_basic_set *bset,
+	__isl_take isl_qpolynomial *poly, struct isl_bound *bound);

Added: polly/trunk/lib/External/isl/isl_blk.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_blk.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_blk.c (added)
+++ polly/trunk/lib/External/isl/isl_blk.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#include <isl_blk.h>
+#include <isl_ctx_private.h>
+
+/* The maximal number of cache misses before first element is evicted */
+#define ISL_BLK_MAX_MISS	100
+
+struct isl_blk isl_blk_empty()
+{
+	struct isl_blk block;
+	block.size = 0;
+	block.data = NULL;
+	return block;
+}
+
+static int isl_blk_is_empty(struct isl_blk block)
+{
+	return block.size == 0 && block.data == NULL;
+}
+
+static struct isl_blk isl_blk_error()
+{
+	struct isl_blk block;
+	block.size = -1;
+	block.data = NULL;
+	return block;
+}
+
+int isl_blk_is_error(struct isl_blk block)
+{
+	return block.size == -1 && block.data == NULL;
+}
+
+static struct isl_blk extend(struct isl_ctx *ctx, struct isl_blk block,
+				size_t new_n)
+{
+	int i;
+	isl_int *p;
+
+	if (block.size >= new_n)
+		return block;
+
+	p = block.data;
+	block.data = isl_realloc_array(ctx, block.data, isl_int, new_n);
+	if (!block.data) {
+		free(p);
+		return isl_blk_error();
+	}
+
+	for (i = block.size; i < new_n; ++i)
+		isl_int_init(block.data[i]);
+	block.size = new_n;
+
+	return block;
+}
+
+static void isl_blk_free_force(struct isl_ctx *ctx, struct isl_blk block)
+{
+	int i;
+
+	for (i = 0; i < block.size; ++i)
+		isl_int_clear(block.data[i]);
+	free(block.data);
+}
+
+struct isl_blk isl_blk_alloc(struct isl_ctx *ctx, size_t n)
+{
+	int i;
+	struct isl_blk block;
+
+	block = isl_blk_empty();
+	if (n && ctx->n_cached) {
+		int best = 0;
+		for (i = 1; ctx->cache[best].size != n && i < ctx->n_cached; ++i) {
+			if (ctx->cache[best].size < n) {
+				if (ctx->cache[i].size > ctx->cache[best].size)
+					best = i;
+			} else if (ctx->cache[i].size >= n &&
+				   ctx->cache[i].size < ctx->cache[best].size)
+					best = i;
+		}
+		if (ctx->cache[best].size < 2 * n + 100) {
+			block = ctx->cache[best];
+			if (--ctx->n_cached != best)
+				ctx->cache[best] = ctx->cache[ctx->n_cached];
+			if (best == 0)
+				ctx->n_miss = 0;
+		} else if (ctx->n_miss++ >= ISL_BLK_MAX_MISS) {
+			isl_blk_free_force(ctx, ctx->cache[0]);
+			if (--ctx->n_cached != 0)
+				ctx->cache[0] = ctx->cache[ctx->n_cached];
+			ctx->n_miss = 0;
+		}
+	}
+
+	return extend(ctx, block, n);
+}
+
+struct isl_blk isl_blk_extend(struct isl_ctx *ctx, struct isl_blk block,
+				size_t new_n)
+{
+	if (isl_blk_is_empty(block))
+		return isl_blk_alloc(ctx, new_n);
+
+	return extend(ctx, block, new_n);
+}
+
+void isl_blk_free(struct isl_ctx *ctx, struct isl_blk block)
+{
+	if (isl_blk_is_empty(block) || isl_blk_is_error(block))
+		return;
+
+	if (ctx->n_cached < ISL_BLK_CACHE_SIZE)
+		ctx->cache[ctx->n_cached++] = block;
+	else
+		isl_blk_free_force(ctx, block);
+}
+
+void isl_blk_clear_cache(struct isl_ctx *ctx)
+{
+	int i;
+
+	for (i = 0; i < ctx->n_cached; ++i)
+		isl_blk_free_force(ctx, ctx->cache[i]);
+	ctx->n_cached = 0;
+}

Added: polly/trunk/lib/External/isl/isl_blk.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_blk.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_blk.h (added)
+++ polly/trunk/lib/External/isl/isl_blk.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008-2009 Katholieke Universiteit Leuven
+ *
+ * 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
+ */
+
+#ifndef ISL_BLK_H
+#define ISL_BLK_H
+
+#include <isl_int.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+struct isl_blk {
+	size_t size;
+	isl_int *data;
+};
+
+#define ISL_BLK_CACHE_SIZE	20
+
+struct isl_ctx;
+
+struct isl_blk isl_blk_alloc(struct isl_ctx *ctx, size_t n);
+struct isl_blk isl_blk_empty(void);
+int isl_blk_is_error(struct isl_blk block);
+struct isl_blk isl_blk_extend(struct isl_ctx *ctx, struct isl_blk block,
+				size_t new_n);
+void isl_blk_free(struct isl_ctx *ctx, struct isl_blk block);
+void isl_blk_clear_cache(struct isl_ctx *ctx);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif

Added: polly/trunk/lib/External/isl/isl_bound.c
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_bound.c?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_bound.c (added)
+++ polly/trunk/lib/External/isl/isl_bound.c Wed Feb  4 14:55:43 2015
@@ -0,0 +1,331 @@
+/*
+ * Copyright 2010      INRIA Saclay
+ *
+ * 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 
+ */
+
+#include <isl_ctx_private.h>
+#include <isl_map_private.h>
+#include <isl_bound.h>
+#include <isl_bernstein.h>
+#include <isl_range.h>
+#include <isl_polynomial_private.h>
+#include <isl_options_private.h>
+
+/* Compute a bound on the polynomial defined over the parametric polytope
+ * using either range propagation or bernstein expansion and
+ * store the result in bound->pwf and bound->pwf_tight.
+ * Since bernstein expansion requires bounded domains, we apply
+ * range propagation on unbounded domains.  Otherwise, we respect the choice
+ * of the user.
+ */
+static int compressed_guarded_poly_bound(__isl_take isl_basic_set *bset,
+	__isl_take isl_qpolynomial *poly, void *user)
+{
+	struct isl_bound *bound = (struct isl_bound *)user;
+	int bounded;
+
+	if (!bset || !poly)
+		goto error;
+
+	if (bset->ctx->opt->bound == ISL_BOUND_RANGE)
+		return isl_qpolynomial_bound_on_domain_range(bset, poly, bound);
+
+	bounded = isl_basic_set_is_bounded(bset);
+	if (bounded < 0)
+		goto error;
+	if (bounded)
+		return isl_qpolynomial_bound_on_domain_bernstein(bset, poly, bound);
+	else
+		return isl_qpolynomial_bound_on_domain_range(bset, poly, bound);
+error:
+	isl_basic_set_free(bset);
+	isl_qpolynomial_free(poly);
+	return -1;
+}
+
+static int unwrapped_guarded_poly_bound(__isl_take isl_basic_set *bset,
+	__isl_take isl_qpolynomial *poly, void *user)
+{
+	struct isl_bound *bound = (struct isl_bound *)user;
+	isl_pw_qpolynomial_fold *top_pwf;
+	isl_pw_qpolynomial_fold *top_pwf_tight;
+	isl_space *dim;
+	isl_morph *morph;
+	int r;
+
+	bset = isl_basic_set_detect_equalities(bset);
+
+	if (!bset)
+		goto error;
+
+	if (bset->n_eq == 0)
+		return compressed_guarded_poly_bound(bset, poly, user);
+
+	morph = isl_basic_set_full_compression(bset);
+
+	bset = isl_morph_basic_set(isl_morph_copy(morph), bset);
+	poly = isl_qpolynomial_morph_domain(poly, isl_morph_copy(morph));
+
+	dim = isl_morph_get_ran_space(morph);
+	dim = isl_space_params(dim);
+
+	top_pwf = bound->pwf;
+	top_pwf_tight = bound->pwf_tight;
+
+	dim = isl_space_from_domain(dim);
+	dim = isl_space_add_dims(dim, isl_dim_out, 1);
+	bound->pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(dim),
+						  bound->type);
+	bound->pwf_tight = isl_pw_qpolynomial_fold_zero(dim, bound->type);
+
+	r = compressed_guarded_poly_bound(bset, poly, user);
+
+	morph = isl_morph_dom_params(morph);
+	morph = isl_morph_ran_params(morph);
+	morph = isl_morph_inverse(morph);
+
+	bound->pwf = isl_pw_qpolynomial_fold_morph_domain(bound->pwf,
+							isl_morph_copy(morph));
+	bound->pwf_tight = isl_pw_qpolynomial_fold_morph_domain(
+						bound->pwf_tight, morph);
+
+	bound->pwf = isl_pw_qpolynomial_fold_fold(top_pwf, bound->pwf);
+	bound->pwf_tight = isl_pw_qpolynomial_fold_fold(top_pwf_tight,
+							bound->pwf_tight);
+
+	return r;
+error:
+	isl_basic_set_free(bset);
+	isl_qpolynomial_free(poly);
+	return -1;
+}
+
+static int guarded_poly_bound(__isl_take isl_basic_set *bset,
+	__isl_take isl_qpolynomial *poly, void *user)
+{
+	struct isl_bound *bound = (struct isl_bound *)user;
+	isl_space *dim;
+	isl_pw_qpolynomial_fold *top_pwf;
+	isl_pw_qpolynomial_fold *top_pwf_tight;
+	int nparam;
+	int n_in;
+	int r;
+
+	if (!bound->wrapping)
+		return unwrapped_guarded_poly_bound(bset, poly, user);
+
+	nparam = isl_space_dim(bound->dim, isl_dim_param);
+	n_in = isl_space_dim(bound->dim, isl_dim_in);
+
+	bset = isl_basic_set_move_dims(bset, isl_dim_param, nparam,
+					isl_dim_set, 0, n_in);
+	poly = isl_qpolynomial_move_dims(poly, isl_dim_param, nparam,
+					isl_dim_in, 0, n_in);
+
+	dim = isl_basic_set_get_space(bset);
+	dim = isl_space_params(dim);
+
+	top_pwf = bound->pwf;
+	top_pwf_tight = bound->pwf_tight;
+
+	dim = isl_space_from_domain(dim);
+	dim = isl_space_add_dims(dim, isl_dim_out, 1);
+	bound->pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(dim),
+						  bound->type);
+	bound->pwf_tight = isl_pw_qpolynomial_fold_zero(dim, bound->type);
+
+	r = unwrapped_guarded_poly_bound(bset, poly, user);
+
+	bound->pwf = isl_pw_qpolynomial_fold_reset_space(bound->pwf,
+						    isl_space_copy(bound->dim));
+	bound->pwf_tight = isl_pw_qpolynomial_fold_reset_space(bound->pwf_tight,
+						    isl_space_copy(bound->dim));
+
+	bound->pwf = isl_pw_qpolynomial_fold_fold(top_pwf, bound->pwf);
+	bound->pwf_tight = isl_pw_qpolynomial_fold_fold(top_pwf_tight,
+							bound->pwf_tight);
+
+	return r;
+}
+
+static int guarded_qp(__isl_take isl_qpolynomial *qp, void *user)
+{
+	struct isl_bound *bound = (struct isl_bound *)user;
+	int r;
+
+	r = isl_qpolynomial_as_polynomial_on_domain(qp, bound->bset,
+						    &guarded_poly_bound, user);
+	isl_qpolynomial_free(qp);
+	return r;
+}
+
+static int basic_guarded_fold(__isl_take isl_basic_set *bset, void *user)
+{
+	struct isl_bound *bound = (struct isl_bound *)user;
+	int r;
+
+	bound->bset = bset;
+	r = isl_qpolynomial_fold_foreach_qpolynomial(bound->fold,
+							&guarded_qp, user);
+	isl_basic_set_free(bset);
+	return r;
+}
+
+static int guarded_fold(__isl_take isl_set *set,
+	__isl_take isl_qpolynomial_fold *fold, void *user)
+{
+	struct isl_bound *bound = (struct isl_bound *)user;
+
+	if (!set || !fold)
+		goto error;
+
+	set = isl_set_make_disjoint(set);
+
+	bound->fold = fold;
+	bound->type = isl_qpolynomial_fold_get_type(fold);
+
+	if (isl_set_foreach_basic_set(set, &basic_guarded_fold, bound) < 0)
+		goto error;
+
+	isl_set_free(set);
+	isl_qpolynomial_fold_free(fold);
+
+	return 0;
+error:
+	isl_set_free(set);
+	isl_qpolynomial_fold_free(fold);
+	return -1;
+}
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_fold_bound(
+	__isl_take isl_pw_qpolynomial_fold *pwf, int *tight)
+{
+	unsigned nvar;
+	struct isl_bound bound;
+	int covers;
+
+	if (!pwf)
+		return NULL;
+
+	bound.dim = isl_pw_qpolynomial_fold_get_domain_space(pwf);
+
+	bound.wrapping = isl_space_is_wrapping(bound.dim);
+	if (bound.wrapping)
+		bound.dim = isl_space_unwrap(bound.dim);
+	nvar = isl_space_dim(bound.dim, isl_dim_out);
+	bound.dim = isl_space_domain(bound.dim);
+	bound.dim = isl_space_from_domain(bound.dim);
+	bound.dim = isl_space_add_dims(bound.dim, isl_dim_out, 1);
+
+	if (nvar == 0) {
+		if (tight)
+			*tight = 1;
+		return isl_pw_qpolynomial_fold_reset_space(pwf, bound.dim);
+	}
+
+	if (isl_pw_qpolynomial_fold_is_zero(pwf)) {
+		enum isl_fold type = pwf->type;
+		isl_pw_qpolynomial_fold_free(pwf);
+		if (tight)
+			*tight = 1;
+		return isl_pw_qpolynomial_fold_zero(bound.dim, type);
+	}
+
+	bound.pwf = isl_pw_qpolynomial_fold_zero(isl_space_copy(bound.dim),
+							pwf->type);
+	bound.pwf_tight = isl_pw_qpolynomial_fold_zero(isl_space_copy(bound.dim),
+							pwf->type);
+	bound.check_tight = !!tight;
+
+	if (isl_pw_qpolynomial_fold_foreach_lifted_piece(pwf,
+							guarded_fold, &bound) < 0)
+		goto error;
+
+	covers = isl_pw_qpolynomial_fold_covers(bound.pwf_tight, bound.pwf);
+	if (covers < 0)
+		goto error;
+
+	if (tight)
+		*tight = covers;
+
+	isl_space_free(bound.dim);
+	isl_pw_qpolynomial_fold_free(pwf);
+
+	if (covers) {
+		isl_pw_qpolynomial_fold_free(bound.pwf);
+		return bound.pwf_tight;
+	}
+
+	bound.pwf = isl_pw_qpolynomial_fold_fold(bound.pwf, bound.pwf_tight);
+
+	return bound.pwf;
+error:
+	isl_pw_qpolynomial_fold_free(bound.pwf_tight);
+	isl_pw_qpolynomial_fold_free(bound.pwf);
+	isl_pw_qpolynomial_fold_free(pwf);
+	isl_space_free(bound.dim);
+	return NULL;
+}
+
+__isl_give isl_pw_qpolynomial_fold *isl_pw_qpolynomial_bound(
+	__isl_take isl_pw_qpolynomial *pwqp, enum isl_fold type, int *tight)
+{
+	isl_pw_qpolynomial_fold *pwf;
+
+	pwf = isl_pw_qpolynomial_fold_from_pw_qpolynomial(type, pwqp);
+	return isl_pw_qpolynomial_fold_bound(pwf, tight);
+}
+
+struct isl_union_bound_data {
+	enum isl_fold type;
+	int tight;
+	isl_union_pw_qpolynomial_fold *res;
+};
+
+static int bound_pw(__isl_take isl_pw_qpolynomial *pwqp, void *user)
+{
+	struct isl_union_bound_data *data = user;
+	isl_pw_qpolynomial_fold *pwf;
+
+	pwf = isl_pw_qpolynomial_bound(pwqp, data->type,
+					data->tight ? &data->tight : NULL);
+	data->res = isl_union_pw_qpolynomial_fold_fold_pw_qpolynomial_fold(
+								data->res, pwf);
+
+	return 0;
+}
+
+__isl_give isl_union_pw_qpolynomial_fold *isl_union_pw_qpolynomial_bound(
+	__isl_take isl_union_pw_qpolynomial *upwqp,
+	enum isl_fold type, int *tight)
+{
+	isl_space *dim;
+	struct isl_union_bound_data data = { type, 1, NULL };
+
+	if (!upwqp)
+		return NULL;
+
+	if (!tight)
+		data.tight = 0;
+
+	dim = isl_union_pw_qpolynomial_get_space(upwqp);
+	data.res = isl_union_pw_qpolynomial_fold_zero(dim, type);
+	if (isl_union_pw_qpolynomial_foreach_pw_qpolynomial(upwqp,
+						    &bound_pw, &data) < 0)
+		goto error;
+
+	isl_union_pw_qpolynomial_free(upwqp);
+	if (tight)
+		*tight = data.tight;
+
+	return data.res;
+error:
+	isl_union_pw_qpolynomial_free(upwqp);
+	isl_union_pw_qpolynomial_fold_free(data.res);
+	return NULL;
+}

Added: polly/trunk/lib/External/isl/isl_bound.h
URL: http://llvm.org/viewvc/llvm-project/polly/trunk/lib/External/isl/isl_bound.h?rev=228193&view=auto
==============================================================================
--- polly/trunk/lib/External/isl/isl_bound.h (added)
+++ polly/trunk/lib/External/isl/isl_bound.h Wed Feb  4 14:55:43 2015
@@ -0,0 +1,20 @@
+#ifndef ISL_BOUND_H
+#define ISL_BOUND_H
+
+#include <isl/polynomial.h>
+
+struct isl_bound {
+	/* input */
+	int check_tight;
+	int wrapping;
+	enum isl_fold type;
+	isl_space *dim;
+	isl_basic_set *bset;
+	isl_qpolynomial_fold *fold;
+
+	/* output */
+	isl_pw_qpolynomial_fold *pwf;
+	isl_pw_qpolynomial_fold *pwf_tight;
+};
+
+#endif






More information about the llvm-commits mailing list