[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